cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

trace_seq.c (10657B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * trace_seq.c
      4 *
      5 * Copyright (C) 2008-2014 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
      6 *
      7 * The trace_seq is a handy tool that allows you to pass a descriptor around
      8 * to a buffer that other functions can write to. It is similar to the
      9 * seq_file functionality but has some differences.
     10 *
     11 * To use it, the trace_seq must be initialized with trace_seq_init().
     12 * This will set up the counters within the descriptor. You can call
     13 * trace_seq_init() more than once to reset the trace_seq to start
     14 * from scratch.
     15 * 
     16 * The buffer size is currently PAGE_SIZE, although it may become dynamic
     17 * in the future.
     18 *
     19 * A write to the buffer will either succeed or fail. That is, unlike
     20 * sprintf() there will not be a partial write (well it may write into
     21 * the buffer but it wont update the pointers). This allows users to
     22 * try to write something into the trace_seq buffer and if it fails
     23 * they can flush it and try again.
     24 *
     25 */
     26#include <linux/uaccess.h>
     27#include <linux/seq_file.h>
     28#include <linux/trace_seq.h>
     29
     30/* How much buffer is left on the trace_seq? */
     31#define TRACE_SEQ_BUF_LEFT(s) seq_buf_buffer_left(&(s)->seq)
     32
     33/*
     34 * trace_seq should work with being initialized with 0s.
     35 */
     36static inline void __trace_seq_init(struct trace_seq *s)
     37{
     38	if (unlikely(!s->seq.size))
     39		trace_seq_init(s);
     40}
     41
     42/**
     43 * trace_print_seq - move the contents of trace_seq into a seq_file
     44 * @m: the seq_file descriptor that is the destination
     45 * @s: the trace_seq descriptor that is the source.
     46 *
     47 * Returns 0 on success and non zero on error. If it succeeds to
     48 * write to the seq_file it will reset the trace_seq, otherwise
     49 * it does not modify the trace_seq to let the caller try again.
     50 */
     51int trace_print_seq(struct seq_file *m, struct trace_seq *s)
     52{
     53	int ret;
     54
     55	__trace_seq_init(s);
     56
     57	ret = seq_buf_print_seq(m, &s->seq);
     58
     59	/*
     60	 * Only reset this buffer if we successfully wrote to the
     61	 * seq_file buffer. This lets the caller try again or
     62	 * do something else with the contents.
     63	 */
     64	if (!ret)
     65		trace_seq_init(s);
     66
     67	return ret;
     68}
     69
     70/**
     71 * trace_seq_printf - sequence printing of trace information
     72 * @s: trace sequence descriptor
     73 * @fmt: printf format string
     74 *
     75 * The tracer may use either sequence operations or its own
     76 * copy to user routines. To simplify formatting of a trace
     77 * trace_seq_printf() is used to store strings into a special
     78 * buffer (@s). Then the output may be either used by
     79 * the sequencer or pulled into another buffer.
     80 */
     81void trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
     82{
     83	unsigned int save_len = s->seq.len;
     84	va_list ap;
     85
     86	if (s->full)
     87		return;
     88
     89	__trace_seq_init(s);
     90
     91	va_start(ap, fmt);
     92	seq_buf_vprintf(&s->seq, fmt, ap);
     93	va_end(ap);
     94
     95	/* If we can't write it all, don't bother writing anything */
     96	if (unlikely(seq_buf_has_overflowed(&s->seq))) {
     97		s->seq.len = save_len;
     98		s->full = 1;
     99	}
    100}
    101EXPORT_SYMBOL_GPL(trace_seq_printf);
    102
    103/**
    104 * trace_seq_bitmask - write a bitmask array in its ASCII representation
    105 * @s:		trace sequence descriptor
    106 * @maskp:	points to an array of unsigned longs that represent a bitmask
    107 * @nmaskbits:	The number of bits that are valid in @maskp
    108 *
    109 * Writes a ASCII representation of a bitmask string into @s.
    110 */
    111void trace_seq_bitmask(struct trace_seq *s, const unsigned long *maskp,
    112		      int nmaskbits)
    113{
    114	unsigned int save_len = s->seq.len;
    115
    116	if (s->full)
    117		return;
    118
    119	__trace_seq_init(s);
    120
    121	seq_buf_printf(&s->seq, "%*pb", nmaskbits, maskp);
    122
    123	if (unlikely(seq_buf_has_overflowed(&s->seq))) {
    124		s->seq.len = save_len;
    125		s->full = 1;
    126	}
    127}
    128EXPORT_SYMBOL_GPL(trace_seq_bitmask);
    129
    130/**
    131 * trace_seq_vprintf - sequence printing of trace information
    132 * @s: trace sequence descriptor
    133 * @fmt: printf format string
    134 *
    135 * The tracer may use either sequence operations or its own
    136 * copy to user routines. To simplify formatting of a trace
    137 * trace_seq_printf is used to store strings into a special
    138 * buffer (@s). Then the output may be either used by
    139 * the sequencer or pulled into another buffer.
    140 */
    141void trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
    142{
    143	unsigned int save_len = s->seq.len;
    144
    145	if (s->full)
    146		return;
    147
    148	__trace_seq_init(s);
    149
    150	seq_buf_vprintf(&s->seq, fmt, args);
    151
    152	/* If we can't write it all, don't bother writing anything */
    153	if (unlikely(seq_buf_has_overflowed(&s->seq))) {
    154		s->seq.len = save_len;
    155		s->full = 1;
    156	}
    157}
    158EXPORT_SYMBOL_GPL(trace_seq_vprintf);
    159
    160/**
    161 * trace_seq_bprintf - Write the printf string from binary arguments
    162 * @s: trace sequence descriptor
    163 * @fmt: The format string for the @binary arguments
    164 * @binary: The binary arguments for @fmt.
    165 *
    166 * When recording in a fast path, a printf may be recorded with just
    167 * saving the format and the arguments as they were passed to the
    168 * function, instead of wasting cycles converting the arguments into
    169 * ASCII characters. Instead, the arguments are saved in a 32 bit
    170 * word array that is defined by the format string constraints.
    171 *
    172 * This function will take the format and the binary array and finish
    173 * the conversion into the ASCII string within the buffer.
    174 */
    175void trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary)
    176{
    177	unsigned int save_len = s->seq.len;
    178
    179	if (s->full)
    180		return;
    181
    182	__trace_seq_init(s);
    183
    184	seq_buf_bprintf(&s->seq, fmt, binary);
    185
    186	/* If we can't write it all, don't bother writing anything */
    187	if (unlikely(seq_buf_has_overflowed(&s->seq))) {
    188		s->seq.len = save_len;
    189		s->full = 1;
    190		return;
    191	}
    192}
    193EXPORT_SYMBOL_GPL(trace_seq_bprintf);
    194
    195/**
    196 * trace_seq_puts - trace sequence printing of simple string
    197 * @s: trace sequence descriptor
    198 * @str: simple string to record
    199 *
    200 * The tracer may use either the sequence operations or its own
    201 * copy to user routines. This function records a simple string
    202 * into a special buffer (@s) for later retrieval by a sequencer
    203 * or other mechanism.
    204 */
    205void trace_seq_puts(struct trace_seq *s, const char *str)
    206{
    207	unsigned int len = strlen(str);
    208
    209	if (s->full)
    210		return;
    211
    212	__trace_seq_init(s);
    213
    214	if (len > TRACE_SEQ_BUF_LEFT(s)) {
    215		s->full = 1;
    216		return;
    217	}
    218
    219	seq_buf_putmem(&s->seq, str, len);
    220}
    221EXPORT_SYMBOL_GPL(trace_seq_puts);
    222
    223/**
    224 * trace_seq_putc - trace sequence printing of simple character
    225 * @s: trace sequence descriptor
    226 * @c: simple character to record
    227 *
    228 * The tracer may use either the sequence operations or its own
    229 * copy to user routines. This function records a simple character
    230 * into a special buffer (@s) for later retrieval by a sequencer
    231 * or other mechanism.
    232 */
    233void trace_seq_putc(struct trace_seq *s, unsigned char c)
    234{
    235	if (s->full)
    236		return;
    237
    238	__trace_seq_init(s);
    239
    240	if (TRACE_SEQ_BUF_LEFT(s) < 1) {
    241		s->full = 1;
    242		return;
    243	}
    244
    245	seq_buf_putc(&s->seq, c);
    246}
    247EXPORT_SYMBOL_GPL(trace_seq_putc);
    248
    249/**
    250 * trace_seq_putmem - write raw data into the trace_seq buffer
    251 * @s: trace sequence descriptor
    252 * @mem: The raw memory to copy into the buffer
    253 * @len: The length of the raw memory to copy (in bytes)
    254 *
    255 * There may be cases where raw memory needs to be written into the
    256 * buffer and a strcpy() would not work. Using this function allows
    257 * for such cases.
    258 */
    259void trace_seq_putmem(struct trace_seq *s, const void *mem, unsigned int len)
    260{
    261	if (s->full)
    262		return;
    263
    264	__trace_seq_init(s);
    265
    266	if (len > TRACE_SEQ_BUF_LEFT(s)) {
    267		s->full = 1;
    268		return;
    269	}
    270
    271	seq_buf_putmem(&s->seq, mem, len);
    272}
    273EXPORT_SYMBOL_GPL(trace_seq_putmem);
    274
    275/**
    276 * trace_seq_putmem_hex - write raw memory into the buffer in ASCII hex
    277 * @s: trace sequence descriptor
    278 * @mem: The raw memory to write its hex ASCII representation of
    279 * @len: The length of the raw memory to copy (in bytes)
    280 *
    281 * This is similar to trace_seq_putmem() except instead of just copying the
    282 * raw memory into the buffer it writes its ASCII representation of it
    283 * in hex characters.
    284 */
    285void trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
    286			 unsigned int len)
    287{
    288	unsigned int save_len = s->seq.len;
    289
    290	if (s->full)
    291		return;
    292
    293	__trace_seq_init(s);
    294
    295	/* Each byte is represented by two chars */
    296	if (len * 2 > TRACE_SEQ_BUF_LEFT(s)) {
    297		s->full = 1;
    298		return;
    299	}
    300
    301	/* The added spaces can still cause an overflow */
    302	seq_buf_putmem_hex(&s->seq, mem, len);
    303
    304	if (unlikely(seq_buf_has_overflowed(&s->seq))) {
    305		s->seq.len = save_len;
    306		s->full = 1;
    307		return;
    308	}
    309}
    310EXPORT_SYMBOL_GPL(trace_seq_putmem_hex);
    311
    312/**
    313 * trace_seq_path - copy a path into the sequence buffer
    314 * @s: trace sequence descriptor
    315 * @path: path to write into the sequence buffer.
    316 *
    317 * Write a path name into the sequence buffer.
    318 *
    319 * Returns 1 if we successfully written all the contents to
    320 *   the buffer.
    321 * Returns 0 if we the length to write is bigger than the
    322 *   reserved buffer space. In this case, nothing gets written.
    323 */
    324int trace_seq_path(struct trace_seq *s, const struct path *path)
    325{
    326	unsigned int save_len = s->seq.len;
    327
    328	if (s->full)
    329		return 0;
    330
    331	__trace_seq_init(s);
    332
    333	if (TRACE_SEQ_BUF_LEFT(s) < 1) {
    334		s->full = 1;
    335		return 0;
    336	}
    337
    338	seq_buf_path(&s->seq, path, "\n");
    339
    340	if (unlikely(seq_buf_has_overflowed(&s->seq))) {
    341		s->seq.len = save_len;
    342		s->full = 1;
    343		return 0;
    344	}
    345
    346	return 1;
    347}
    348EXPORT_SYMBOL_GPL(trace_seq_path);
    349
    350/**
    351 * trace_seq_to_user - copy the sequence buffer to user space
    352 * @s: trace sequence descriptor
    353 * @ubuf: The userspace memory location to copy to
    354 * @cnt: The amount to copy
    355 *
    356 * Copies the sequence buffer into the userspace memory pointed to
    357 * by @ubuf. It starts from the last read position (@s->readpos)
    358 * and writes up to @cnt characters or till it reaches the end of
    359 * the content in the buffer (@s->len), which ever comes first.
    360 *
    361 * On success, it returns a positive number of the number of bytes
    362 * it copied.
    363 *
    364 * On failure it returns -EBUSY if all of the content in the
    365 * sequence has been already read, which includes nothing in the
    366 * sequence (@s->len == @s->readpos).
    367 *
    368 * Returns -EFAULT if the copy to userspace fails.
    369 */
    370int trace_seq_to_user(struct trace_seq *s, char __user *ubuf, int cnt)
    371{
    372	__trace_seq_init(s);
    373	return seq_buf_to_user(&s->seq, ubuf, cnt);
    374}
    375EXPORT_SYMBOL_GPL(trace_seq_to_user);
    376
    377int trace_seq_hex_dump(struct trace_seq *s, const char *prefix_str,
    378		       int prefix_type, int rowsize, int groupsize,
    379		       const void *buf, size_t len, bool ascii)
    380{
    381	unsigned int save_len = s->seq.len;
    382
    383	if (s->full)
    384		return 0;
    385
    386	__trace_seq_init(s);
    387
    388	if (TRACE_SEQ_BUF_LEFT(s) < 1) {
    389		s->full = 1;
    390		return 0;
    391	}
    392
    393	seq_buf_hex_dump(&(s->seq), prefix_str,
    394		   prefix_type, rowsize, groupsize,
    395		   buf, len, ascii);
    396
    397	if (unlikely(seq_buf_has_overflowed(&s->seq))) {
    398		s->seq.len = save_len;
    399		s->full = 1;
    400		return 0;
    401	}
    402
    403	return 1;
    404}
    405EXPORT_SYMBOL(trace_seq_hex_dump);