xref: /linux-6.15/kernel/trace/trace_output.c (revision 0a8f11f8)
1bcea3f96SSteven Rostedt (VMware) // SPDX-License-Identifier: GPL-2.0
2f0868d1eSSteven Rostedt /*
3f0868d1eSSteven Rostedt  * trace_output.c
4f0868d1eSSteven Rostedt  *
5f0868d1eSSteven Rostedt  * Copyright (C) 2008 Red Hat Inc, Steven Rostedt <[email protected]>
6f0868d1eSSteven Rostedt  *
7f0868d1eSSteven Rostedt  */
835a380ddSMasami Hiramatsu (Google) #include "trace.h"
9f0868d1eSSteven Rostedt #include <linux/module.h>
10f0868d1eSSteven Rostedt #include <linux/mutex.h>
11f0868d1eSSteven Rostedt #include <linux/ftrace.h>
127da89495SMasami Hiramatsu #include <linux/kprobes.h>
13e6017571SIngo Molnar #include <linux/sched/clock.h>
146e84f315SIngo Molnar #include <linux/sched/mm.h>
1596e6122cSZheng Yejian #include <linux/idr.h>
16533c20b0SSven Schnelle #include <linux/btf.h>
17533c20b0SSven Schnelle #include <linux/bpf.h>
18391dda1bSSasha Levin #include <linux/hashtable.h>
19f0868d1eSSteven Rostedt 
20f0868d1eSSteven Rostedt #include "trace_output.h"
21533c20b0SSven Schnelle #include "trace_btf.h"
22f0868d1eSSteven Rostedt 
23391dda1bSSasha Levin /* 2^7 = 128 */
24391dda1bSSasha Levin #define EVENT_HASH_BITS 7
25f0868d1eSSteven Rostedt 
2652f6ad6dSzhangwei(Jovi) DECLARE_RWSEM(trace_event_sem);
27be74b73aSSteven Rostedt 
28391dda1bSSasha Levin static DEFINE_HASHTABLE(event_hash, EVENT_HASH_BITS);
29f0868d1eSSteven Rostedt 
trace_print_bputs_msg_only(struct trace_iterator * iter)3009ae7234SSteven Rostedt (Red Hat) enum print_line_t trace_print_bputs_msg_only(struct trace_iterator *iter)
3109ae7234SSteven Rostedt (Red Hat) {
3209ae7234SSteven Rostedt (Red Hat) 	struct trace_seq *s = &iter->seq;
3309ae7234SSteven Rostedt (Red Hat) 	struct trace_entry *entry = iter->ent;
3409ae7234SSteven Rostedt (Red Hat) 	struct bputs_entry *field;
3509ae7234SSteven Rostedt (Red Hat) 
3609ae7234SSteven Rostedt (Red Hat) 	trace_assign_type(field, entry);
3709ae7234SSteven Rostedt (Red Hat) 
3819a7fe20SSteven Rostedt (Red Hat) 	trace_seq_puts(s, field->str);
3909ae7234SSteven Rostedt (Red Hat) 
4019a7fe20SSteven Rostedt (Red Hat) 	return trace_handle_return(s);
4109ae7234SSteven Rostedt (Red Hat) }
4209ae7234SSteven Rostedt (Red Hat) 
trace_print_bprintk_msg_only(struct trace_iterator * iter)435ef841f6SSteven Rostedt enum print_line_t trace_print_bprintk_msg_only(struct trace_iterator *iter)
445ef841f6SSteven Rostedt {
455ef841f6SSteven Rostedt 	struct trace_seq *s = &iter->seq;
465ef841f6SSteven Rostedt 	struct trace_entry *entry = iter->ent;
475ef841f6SSteven Rostedt 	struct bprint_entry *field;
485ef841f6SSteven Rostedt 
495ef841f6SSteven Rostedt 	trace_assign_type(field, entry);
505ef841f6SSteven Rostedt 
5119a7fe20SSteven Rostedt (Red Hat) 	trace_seq_bprintf(s, field->fmt, field->buf);
525ef841f6SSteven Rostedt 
5319a7fe20SSteven Rostedt (Red Hat) 	return trace_handle_return(s);
545ef841f6SSteven Rostedt }
555ef841f6SSteven Rostedt 
trace_print_printk_msg_only(struct trace_iterator * iter)565ef841f6SSteven Rostedt enum print_line_t trace_print_printk_msg_only(struct trace_iterator *iter)
575ef841f6SSteven Rostedt {
585ef841f6SSteven Rostedt 	struct trace_seq *s = &iter->seq;
595ef841f6SSteven Rostedt 	struct trace_entry *entry = iter->ent;
605ef841f6SSteven Rostedt 	struct print_entry *field;
615ef841f6SSteven Rostedt 
625ef841f6SSteven Rostedt 	trace_assign_type(field, entry);
635ef841f6SSteven Rostedt 
6419a7fe20SSteven Rostedt (Red Hat) 	trace_seq_puts(s, field->buf);
655ef841f6SSteven Rostedt 
6619a7fe20SSteven Rostedt (Red Hat) 	return trace_handle_return(s);
675ef841f6SSteven Rostedt }
685ef841f6SSteven Rostedt 
69be74b73aSSteven Rostedt const char *
trace_print_flags_seq(struct trace_seq * p,const char * delim,unsigned long flags,const struct trace_print_flags * flag_array)70645df987SSteven Rostedt (Red Hat) trace_print_flags_seq(struct trace_seq *p, const char *delim,
71be74b73aSSteven Rostedt 		      unsigned long flags,
72be74b73aSSteven Rostedt 		      const struct trace_print_flags *flag_array)
73be74b73aSSteven Rostedt {
74be74b73aSSteven Rostedt 	unsigned long mask;
75be74b73aSSteven Rostedt 	const char *str;
767b039cb4SSteven Rostedt (Red Hat) 	const char *ret = trace_seq_buffer_ptr(p);
77e404b321SAndrey Vagin 	int i, first = 1;
78be74b73aSSteven Rostedt 
79be74b73aSSteven Rostedt 	for (i = 0;  flag_array[i].name && flags; i++) {
80be74b73aSSteven Rostedt 
81be74b73aSSteven Rostedt 		mask = flag_array[i].mask;
82be74b73aSSteven Rostedt 		if ((flags & mask) != mask)
83be74b73aSSteven Rostedt 			continue;
84be74b73aSSteven Rostedt 
85be74b73aSSteven Rostedt 		str = flag_array[i].name;
86be74b73aSSteven Rostedt 		flags &= ~mask;
87e404b321SAndrey Vagin 		if (!first && delim)
88be74b73aSSteven Rostedt 			trace_seq_puts(p, delim);
89e404b321SAndrey Vagin 		else
90e404b321SAndrey Vagin 			first = 0;
91be74b73aSSteven Rostedt 		trace_seq_puts(p, str);
92be74b73aSSteven Rostedt 	}
93be74b73aSSteven Rostedt 
94be74b73aSSteven Rostedt 	/* check for left over flags */
95be74b73aSSteven Rostedt 	if (flags) {
965b349261SSteven Rostedt 		if (!first && delim)
97be74b73aSSteven Rostedt 			trace_seq_puts(p, delim);
98be74b73aSSteven Rostedt 		trace_seq_printf(p, "0x%lx", flags);
99be74b73aSSteven Rostedt 	}
100be74b73aSSteven Rostedt 
101be74b73aSSteven Rostedt 	trace_seq_putc(p, 0);
102be74b73aSSteven Rostedt 
10356d8bd3fSSteven Whitehouse 	return ret;
104be74b73aSSteven Rostedt }
105645df987SSteven Rostedt (Red Hat) EXPORT_SYMBOL(trace_print_flags_seq);
106be74b73aSSteven Rostedt 
1070f4fc29dSSteven Rostedt const char *
trace_print_symbols_seq(struct trace_seq * p,unsigned long val,const struct trace_print_flags * symbol_array)108645df987SSteven Rostedt (Red Hat) trace_print_symbols_seq(struct trace_seq *p, unsigned long val,
1090f4fc29dSSteven Rostedt 			const struct trace_print_flags *symbol_array)
1100f4fc29dSSteven Rostedt {
1110f4fc29dSSteven Rostedt 	int i;
1127b039cb4SSteven Rostedt (Red Hat) 	const char *ret = trace_seq_buffer_ptr(p);
1130f4fc29dSSteven Rostedt 
1140f4fc29dSSteven Rostedt 	for (i = 0;  symbol_array[i].name; i++) {
1150f4fc29dSSteven Rostedt 
1160f4fc29dSSteven Rostedt 		if (val != symbol_array[i].mask)
1170f4fc29dSSteven Rostedt 			continue;
1180f4fc29dSSteven Rostedt 
1190f4fc29dSSteven Rostedt 		trace_seq_puts(p, symbol_array[i].name);
1200f4fc29dSSteven Rostedt 		break;
1210f4fc29dSSteven Rostedt 	}
1220f4fc29dSSteven Rostedt 
1237b039cb4SSteven Rostedt (Red Hat) 	if (ret == (const char *)(trace_seq_buffer_ptr(p)))
1240f4fc29dSSteven Rostedt 		trace_seq_printf(p, "0x%lx", val);
1250f4fc29dSSteven Rostedt 
1260f4fc29dSSteven Rostedt 	trace_seq_putc(p, 0);
1270f4fc29dSSteven Rostedt 
12856d8bd3fSSteven Whitehouse 	return ret;
1290f4fc29dSSteven Rostedt }
130645df987SSteven Rostedt (Red Hat) EXPORT_SYMBOL(trace_print_symbols_seq);
1310f4fc29dSSteven Rostedt 
1322fc1b6f0Sliubo #if BITS_PER_LONG == 32
1332fc1b6f0Sliubo const char *
trace_print_flags_seq_u64(struct trace_seq * p,const char * delim,unsigned long long flags,const struct trace_print_flags_u64 * flag_array)134d3213e8fSRoss Zwisler trace_print_flags_seq_u64(struct trace_seq *p, const char *delim,
135d3213e8fSRoss Zwisler 		      unsigned long long flags,
136d3213e8fSRoss Zwisler 		      const struct trace_print_flags_u64 *flag_array)
137d3213e8fSRoss Zwisler {
138d3213e8fSRoss Zwisler 	unsigned long long mask;
139d3213e8fSRoss Zwisler 	const char *str;
140d3213e8fSRoss Zwisler 	const char *ret = trace_seq_buffer_ptr(p);
141d3213e8fSRoss Zwisler 	int i, first = 1;
142d3213e8fSRoss Zwisler 
143d3213e8fSRoss Zwisler 	for (i = 0;  flag_array[i].name && flags; i++) {
144d3213e8fSRoss Zwisler 
145d3213e8fSRoss Zwisler 		mask = flag_array[i].mask;
146d3213e8fSRoss Zwisler 		if ((flags & mask) != mask)
147d3213e8fSRoss Zwisler 			continue;
148d3213e8fSRoss Zwisler 
149d3213e8fSRoss Zwisler 		str = flag_array[i].name;
150d3213e8fSRoss Zwisler 		flags &= ~mask;
151d3213e8fSRoss Zwisler 		if (!first && delim)
152d3213e8fSRoss Zwisler 			trace_seq_puts(p, delim);
153d3213e8fSRoss Zwisler 		else
154d3213e8fSRoss Zwisler 			first = 0;
155d3213e8fSRoss Zwisler 		trace_seq_puts(p, str);
156d3213e8fSRoss Zwisler 	}
157d3213e8fSRoss Zwisler 
158d3213e8fSRoss Zwisler 	/* check for left over flags */
159d3213e8fSRoss Zwisler 	if (flags) {
160d3213e8fSRoss Zwisler 		if (!first && delim)
161d3213e8fSRoss Zwisler 			trace_seq_puts(p, delim);
162d3213e8fSRoss Zwisler 		trace_seq_printf(p, "0x%llx", flags);
163d3213e8fSRoss Zwisler 	}
164d3213e8fSRoss Zwisler 
165d3213e8fSRoss Zwisler 	trace_seq_putc(p, 0);
166d3213e8fSRoss Zwisler 
167d3213e8fSRoss Zwisler 	return ret;
168d3213e8fSRoss Zwisler }
169d3213e8fSRoss Zwisler EXPORT_SYMBOL(trace_print_flags_seq_u64);
170d3213e8fSRoss Zwisler 
171d3213e8fSRoss Zwisler const char *
trace_print_symbols_seq_u64(struct trace_seq * p,unsigned long long val,const struct trace_print_flags_u64 * symbol_array)172645df987SSteven Rostedt (Red Hat) trace_print_symbols_seq_u64(struct trace_seq *p, unsigned long long val,
1732fc1b6f0Sliubo 			 const struct trace_print_flags_u64 *symbol_array)
1742fc1b6f0Sliubo {
1752fc1b6f0Sliubo 	int i;
1767b039cb4SSteven Rostedt (Red Hat) 	const char *ret = trace_seq_buffer_ptr(p);
1772fc1b6f0Sliubo 
1782fc1b6f0Sliubo 	for (i = 0;  symbol_array[i].name; i++) {
1792fc1b6f0Sliubo 
1802fc1b6f0Sliubo 		if (val != symbol_array[i].mask)
1812fc1b6f0Sliubo 			continue;
1822fc1b6f0Sliubo 
1832fc1b6f0Sliubo 		trace_seq_puts(p, symbol_array[i].name);
1842fc1b6f0Sliubo 		break;
1852fc1b6f0Sliubo 	}
1862fc1b6f0Sliubo 
1877b039cb4SSteven Rostedt (Red Hat) 	if (ret == (const char *)(trace_seq_buffer_ptr(p)))
1882fc1b6f0Sliubo 		trace_seq_printf(p, "0x%llx", val);
1892fc1b6f0Sliubo 
1902fc1b6f0Sliubo 	trace_seq_putc(p, 0);
1912fc1b6f0Sliubo 
1922fc1b6f0Sliubo 	return ret;
1932fc1b6f0Sliubo }
194645df987SSteven Rostedt (Red Hat) EXPORT_SYMBOL(trace_print_symbols_seq_u64);
1952fc1b6f0Sliubo #endif
1962fc1b6f0Sliubo 
1975a2e3995SKei Tokunaga const char *
trace_print_bitmask_seq(struct trace_seq * p,void * bitmask_ptr,unsigned int bitmask_size)198645df987SSteven Rostedt (Red Hat) trace_print_bitmask_seq(struct trace_seq *p, void *bitmask_ptr,
1994449bf92SSteven Rostedt (Red Hat) 			unsigned int bitmask_size)
2004449bf92SSteven Rostedt (Red Hat) {
2017b039cb4SSteven Rostedt (Red Hat) 	const char *ret = trace_seq_buffer_ptr(p);
2024449bf92SSteven Rostedt (Red Hat) 
2034449bf92SSteven Rostedt (Red Hat) 	trace_seq_bitmask(p, bitmask_ptr, bitmask_size * 8);
2044449bf92SSteven Rostedt (Red Hat) 	trace_seq_putc(p, 0);
2054449bf92SSteven Rostedt (Red Hat) 
2064449bf92SSteven Rostedt (Red Hat) 	return ret;
2074449bf92SSteven Rostedt (Red Hat) }
208645df987SSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_print_bitmask_seq);
2094449bf92SSteven Rostedt (Red Hat) 
2103898fac1SDaniel Borkmann /**
2113898fac1SDaniel Borkmann  * trace_print_hex_seq - print buffer as hex sequence
2123898fac1SDaniel Borkmann  * @p: trace seq struct to write to
2133898fac1SDaniel Borkmann  * @buf: The buffer to print
2143898fac1SDaniel Borkmann  * @buf_len: Length of @buf in bytes
2153898fac1SDaniel Borkmann  * @concatenate: Print @buf as single hex string or with spacing
2163898fac1SDaniel Borkmann  *
2173898fac1SDaniel Borkmann  * Prints the passed buffer as a hex sequence either as a whole,
2183898fac1SDaniel Borkmann  * single hex string if @concatenate is true or with spacing after
2193898fac1SDaniel Borkmann  * each byte in case @concatenate is false.
2203898fac1SDaniel Borkmann  */
2214449bf92SSteven Rostedt (Red Hat) const char *
trace_print_hex_seq(struct trace_seq * p,const unsigned char * buf,int buf_len,bool concatenate)2222acae0d5SDaniel Borkmann trace_print_hex_seq(struct trace_seq *p, const unsigned char *buf, int buf_len,
2233898fac1SDaniel Borkmann 		    bool concatenate)
2245a2e3995SKei Tokunaga {
2255a2e3995SKei Tokunaga 	int i;
2267b039cb4SSteven Rostedt (Red Hat) 	const char *ret = trace_seq_buffer_ptr(p);
227119cdbdbSAndy Shevchenko 	const char *fmt = concatenate ? "%*phN" : "%*ph";
2285a2e3995SKei Tokunaga 
229adace440SKen Lin 	for (i = 0; i < buf_len; i += 16) {
230adace440SKen Lin 		if (!concatenate && i != 0)
231adace440SKen Lin 			trace_seq_putc(p, ' ');
232119cdbdbSAndy Shevchenko 		trace_seq_printf(p, fmt, min(buf_len - i, 16), &buf[i]);
233adace440SKen Lin 	}
2345a2e3995SKei Tokunaga 	trace_seq_putc(p, 0);
2355a2e3995SKei Tokunaga 
2365a2e3995SKei Tokunaga 	return ret;
2375a2e3995SKei Tokunaga }
238645df987SSteven Rostedt (Red Hat) EXPORT_SYMBOL(trace_print_hex_seq);
2395a2e3995SKei Tokunaga 
2406ea22486SDave Martin const char *
trace_print_array_seq(struct trace_seq * p,const void * buf,int count,size_t el_size)241645df987SSteven Rostedt (Red Hat) trace_print_array_seq(struct trace_seq *p, const void *buf, int count,
2426ea22486SDave Martin 		      size_t el_size)
2436ea22486SDave Martin {
2446ea22486SDave Martin 	const char *ret = trace_seq_buffer_ptr(p);
2456ea22486SDave Martin 	const char *prefix = "";
2466ea22486SDave Martin 	void *ptr = (void *)buf;
247ac01ce14SAlex Bennée 	size_t buf_len = count * el_size;
2486ea22486SDave Martin 
2496ea22486SDave Martin 	trace_seq_putc(p, '{');
2506ea22486SDave Martin 
2516ea22486SDave Martin 	while (ptr < buf + buf_len) {
2526ea22486SDave Martin 		switch (el_size) {
2536ea22486SDave Martin 		case 1:
2546ea22486SDave Martin 			trace_seq_printf(p, "%s0x%x", prefix,
2556ea22486SDave Martin 					 *(u8 *)ptr);
2566ea22486SDave Martin 			break;
2576ea22486SDave Martin 		case 2:
2586ea22486SDave Martin 			trace_seq_printf(p, "%s0x%x", prefix,
2596ea22486SDave Martin 					 *(u16 *)ptr);
2606ea22486SDave Martin 			break;
2616ea22486SDave Martin 		case 4:
2626ea22486SDave Martin 			trace_seq_printf(p, "%s0x%x", prefix,
2636ea22486SDave Martin 					 *(u32 *)ptr);
2646ea22486SDave Martin 			break;
2656ea22486SDave Martin 		case 8:
2666ea22486SDave Martin 			trace_seq_printf(p, "%s0x%llx", prefix,
2676ea22486SDave Martin 					 *(u64 *)ptr);
2686ea22486SDave Martin 			break;
2696ea22486SDave Martin 		default:
2706ea22486SDave Martin 			trace_seq_printf(p, "BAD SIZE:%zu 0x%x", el_size,
2716ea22486SDave Martin 					 *(u8 *)ptr);
2726ea22486SDave Martin 			el_size = 1;
2736ea22486SDave Martin 		}
2746ea22486SDave Martin 		prefix = ",";
2756ea22486SDave Martin 		ptr += el_size;
2766ea22486SDave Martin 	}
2776ea22486SDave Martin 
2786ea22486SDave Martin 	trace_seq_putc(p, '}');
2796ea22486SDave Martin 	trace_seq_putc(p, 0);
2806ea22486SDave Martin 
2816ea22486SDave Martin 	return ret;
2826ea22486SDave Martin }
283645df987SSteven Rostedt (Red Hat) EXPORT_SYMBOL(trace_print_array_seq);
2846ea22486SDave Martin 
285ef56e047SPiotr Maziarz const char *
trace_print_hex_dump_seq(struct trace_seq * p,const char * prefix_str,int prefix_type,int rowsize,int groupsize,const void * buf,size_t len,bool ascii)286ef56e047SPiotr Maziarz trace_print_hex_dump_seq(struct trace_seq *p, const char *prefix_str,
287ef56e047SPiotr Maziarz 			 int prefix_type, int rowsize, int groupsize,
288ef56e047SPiotr Maziarz 			 const void *buf, size_t len, bool ascii)
289ef56e047SPiotr Maziarz {
290ef56e047SPiotr Maziarz 	const char *ret = trace_seq_buffer_ptr(p);
291ef56e047SPiotr Maziarz 
292ef56e047SPiotr Maziarz 	trace_seq_putc(p, '\n');
293ef56e047SPiotr Maziarz 	trace_seq_hex_dump(p, prefix_str, prefix_type,
294ef56e047SPiotr Maziarz 			   rowsize, groupsize, buf, len, ascii);
295ef56e047SPiotr Maziarz 	trace_seq_putc(p, 0);
296ef56e047SPiotr Maziarz 	return ret;
297ef56e047SPiotr Maziarz }
298ef56e047SPiotr Maziarz EXPORT_SYMBOL(trace_print_hex_dump_seq);
299ef56e047SPiotr Maziarz 
trace_raw_output_prep(struct trace_iterator * iter,struct trace_event * trace_event)300892c505aSSteven Rostedt (Red Hat) int trace_raw_output_prep(struct trace_iterator *iter,
301f71130deSLi Zefan 			  struct trace_event *trace_event)
302f71130deSLi Zefan {
3032425bcb9SSteven Rostedt (Red Hat) 	struct trace_event_call *event;
304f71130deSLi Zefan 	struct trace_seq *s = &iter->seq;
305f71130deSLi Zefan 	struct trace_seq *p = &iter->tmp_seq;
306f71130deSLi Zefan 	struct trace_entry *entry;
307f71130deSLi Zefan 
3082425bcb9SSteven Rostedt (Red Hat) 	event = container_of(trace_event, struct trace_event_call, event);
309f71130deSLi Zefan 	entry = iter->ent;
310f71130deSLi Zefan 
311f71130deSLi Zefan 	if (entry->type != event->event.type) {
312f71130deSLi Zefan 		WARN_ON_ONCE(1);
313f71130deSLi Zefan 		return TRACE_TYPE_UNHANDLED;
314f71130deSLi Zefan 	}
315f71130deSLi Zefan 
316f71130deSLi Zefan 	trace_seq_init(p);
317687fcc4aSSteven Rostedt (Red Hat) 	trace_seq_printf(s, "%s: ", trace_event_name(event));
31819a7fe20SSteven Rostedt (Red Hat) 
3198e2e095cSSteven Rostedt (Red Hat) 	return trace_handle_return(s);
320f71130deSLi Zefan }
321892c505aSSteven Rostedt (Red Hat) EXPORT_SYMBOL(trace_raw_output_prep);
322f71130deSLi Zefan 
trace_event_printf(struct trace_iterator * iter,const char * fmt,...)323efbbdaa2SMasami Hiramatsu void trace_event_printf(struct trace_iterator *iter, const char *fmt, ...)
324efbbdaa2SMasami Hiramatsu {
325afd2627fSSteven Rostedt 	struct trace_seq *s = &iter->seq;
326efbbdaa2SMasami Hiramatsu 	va_list ap;
327efbbdaa2SMasami Hiramatsu 
328afd2627fSSteven Rostedt 	if (ignore_event(iter))
329afd2627fSSteven Rostedt 		return;
330afd2627fSSteven Rostedt 
331efbbdaa2SMasami Hiramatsu 	va_start(ap, fmt);
332afd2627fSSteven Rostedt 	trace_seq_vprintf(s, trace_event_format(iter, fmt), ap);
333efbbdaa2SMasami Hiramatsu 	va_end(ap);
334efbbdaa2SMasami Hiramatsu }
335efbbdaa2SMasami Hiramatsu EXPORT_SYMBOL(trace_event_printf);
336efbbdaa2SMasami Hiramatsu 
337bfd5a5e8SDavid Howells static __printf(3, 0)
trace_output_raw(struct trace_iterator * iter,char * name,char * fmt,va_list ap)338bfd5a5e8SDavid Howells int trace_output_raw(struct trace_iterator *iter, char *name,
3391d6bae96SSteven Rostedt 		     char *fmt, va_list ap)
3401d6bae96SSteven Rostedt {
3411d6bae96SSteven Rostedt 	struct trace_seq *s = &iter->seq;
3421d6bae96SSteven Rostedt 
34319a7fe20SSteven Rostedt (Red Hat) 	trace_seq_printf(s, "%s: ", name);
344efbbdaa2SMasami Hiramatsu 	trace_seq_vprintf(s, trace_event_format(iter, fmt), ap);
3451d6bae96SSteven Rostedt 
34619a7fe20SSteven Rostedt (Red Hat) 	return trace_handle_return(s);
3471d6bae96SSteven Rostedt }
3481d6bae96SSteven Rostedt 
trace_output_call(struct trace_iterator * iter,char * name,char * fmt,...)349892c505aSSteven Rostedt (Red Hat) int trace_output_call(struct trace_iterator *iter, char *name, char *fmt, ...)
3501d6bae96SSteven Rostedt {
3511d6bae96SSteven Rostedt 	va_list ap;
3521d6bae96SSteven Rostedt 	int ret;
3531d6bae96SSteven Rostedt 
3541d6bae96SSteven Rostedt 	va_start(ap, fmt);
355892c505aSSteven Rostedt (Red Hat) 	ret = trace_output_raw(iter, name, fmt, ap);
3561d6bae96SSteven Rostedt 	va_end(ap);
3571d6bae96SSteven Rostedt 
3581d6bae96SSteven Rostedt 	return ret;
3591d6bae96SSteven Rostedt }
360892c505aSSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_output_call);
3611d6bae96SSteven Rostedt 
kretprobed(const char * name,unsigned long addr)3627da89495SMasami Hiramatsu static inline const char *kretprobed(const char *name, unsigned long addr)
363f0868d1eSSteven Rostedt {
3647da89495SMasami Hiramatsu 	if (is_kretprobe_trampoline(addr))
365f0868d1eSSteven Rostedt 		return "[unknown/kretprobe'd]";
366f0868d1eSSteven Rostedt 	return name;
367f0868d1eSSteven Rostedt }
368f0868d1eSSteven Rostedt 
369773c1670SSteven Rostedt (VMware) void
trace_seq_print_sym(struct trace_seq * s,unsigned long address,bool offset)370773c1670SSteven Rostedt (VMware) trace_seq_print_sym(struct trace_seq *s, unsigned long address, bool offset)
371f0868d1eSSteven Rostedt {
372feaf1283SSteven Rostedt (VMware) #ifdef CONFIG_KALLSYMS
373bea6957dSRasmus Villemoes 	char str[KSYM_SYMBOL_LEN];
374f0868d1eSSteven Rostedt 	const char *name;
375f0868d1eSSteven Rostedt 
37659dd974bSRasmus Villemoes 	if (offset)
377f0868d1eSSteven Rostedt 		sprint_symbol(str, address);
37859dd974bSRasmus Villemoes 	else
37959dd974bSRasmus Villemoes 		kallsyms_lookup(address, NULL, NULL, NULL, str);
3807da89495SMasami Hiramatsu 	name = kretprobed(str, address);
381f0868d1eSSteven Rostedt 
382feaf1283SSteven Rostedt (VMware) 	if (name && strlen(name)) {
383bea6957dSRasmus Villemoes 		trace_seq_puts(s, name);
384feaf1283SSteven Rostedt (VMware) 		return;
385feaf1283SSteven Rostedt (VMware) 	}
386f0868d1eSSteven Rostedt #endif
387bea6957dSRasmus Villemoes 	trace_seq_printf(s, "0x%08lx", address);
388f0868d1eSSteven Rostedt }
389f0868d1eSSteven Rostedt 
390f0868d1eSSteven Rostedt #ifndef CONFIG_64BIT
391f0868d1eSSteven Rostedt # define IP_FMT "%08lx"
392f0868d1eSSteven Rostedt #else
393f0868d1eSSteven Rostedt # define IP_FMT "%016lx"
394f0868d1eSSteven Rostedt #endif
395f0868d1eSSteven Rostedt 
seq_print_user_ip(struct trace_seq * s,struct mm_struct * mm,unsigned long ip,unsigned long sym_flags)396ef92480aSSteven Rostedt (Red Hat) static int seq_print_user_ip(struct trace_seq *s, struct mm_struct *mm,
397f0868d1eSSteven Rostedt 			     unsigned long ip, unsigned long sym_flags)
398f0868d1eSSteven Rostedt {
399f0868d1eSSteven Rostedt 	struct file *file = NULL;
400f0868d1eSSteven Rostedt 	unsigned long vmstart = 0;
401f0868d1eSSteven Rostedt 	int ret = 1;
402f0868d1eSSteven Rostedt 
403d184b31cSJohannes Berg 	if (s->full)
404d184b31cSJohannes Berg 		return 0;
405d184b31cSJohannes Berg 
406f0868d1eSSteven Rostedt 	if (mm) {
407f0868d1eSSteven Rostedt 		const struct vm_area_struct *vma;
408f0868d1eSSteven Rostedt 
409d8ed45c5SMichel Lespinasse 		mmap_read_lock(mm);
410f0868d1eSSteven Rostedt 		vma = find_vma(mm, ip);
411f0868d1eSSteven Rostedt 		if (vma) {
412f0868d1eSSteven Rostedt 			file = vma->vm_file;
413f0868d1eSSteven Rostedt 			vmstart = vma->vm_start;
414f0868d1eSSteven Rostedt 		}
415f0868d1eSSteven Rostedt 		if (file) {
41608582d67SAmir Goldstein 			ret = trace_seq_path(s, file_user_path(file));
417f0868d1eSSteven Rostedt 			if (ret)
41819a7fe20SSteven Rostedt (Red Hat) 				trace_seq_printf(s, "[+0x%lx]",
419f0868d1eSSteven Rostedt 						 ip - vmstart);
420f0868d1eSSteven Rostedt 		}
421d8ed45c5SMichel Lespinasse 		mmap_read_unlock(mm);
422f0868d1eSSteven Rostedt 	}
423f0868d1eSSteven Rostedt 	if (ret && ((sym_flags & TRACE_ITER_SYM_ADDR) || !file))
42419a7fe20SSteven Rostedt (Red Hat) 		trace_seq_printf(s, " <" IP_FMT ">", ip);
42519a7fe20SSteven Rostedt (Red Hat) 	return !trace_seq_has_overflowed(s);
426f0868d1eSSteven Rostedt }
427f0868d1eSSteven Rostedt 
428f0868d1eSSteven Rostedt int
seq_print_ip_sym(struct trace_seq * s,unsigned long ip,unsigned long sym_flags)429f0868d1eSSteven Rostedt seq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags)
430f0868d1eSSteven Rostedt {
43119a7fe20SSteven Rostedt (Red Hat) 	if (!ip) {
43219a7fe20SSteven Rostedt (Red Hat) 		trace_seq_putc(s, '0');
43319a7fe20SSteven Rostedt (Red Hat) 		goto out;
43419a7fe20SSteven Rostedt (Red Hat) 	}
435f0868d1eSSteven Rostedt 
436773c1670SSteven Rostedt (VMware) 	trace_seq_print_sym(s, ip, sym_flags & TRACE_ITER_SYM_OFFSET);
437f0868d1eSSteven Rostedt 
438f0868d1eSSteven Rostedt 	if (sym_flags & TRACE_ITER_SYM_ADDR)
43919a7fe20SSteven Rostedt (Red Hat) 		trace_seq_printf(s, " <" IP_FMT ">", ip);
44019a7fe20SSteven Rostedt (Red Hat) 
44119a7fe20SSteven Rostedt (Red Hat)  out:
44219a7fe20SSteven Rostedt (Red Hat) 	return !trace_seq_has_overflowed(s);
443f0868d1eSSteven Rostedt }
444f0868d1eSSteven Rostedt 
445f81c972dSSteven Rostedt /**
446f81c972dSSteven Rostedt  * trace_print_lat_fmt - print the irq, preempt and lockdep fields
447f81c972dSSteven Rostedt  * @s: trace seq struct to write to
448f81c972dSSteven Rostedt  * @entry: The trace entry field from the ring buffer
449f81c972dSSteven Rostedt  *
450f81c972dSSteven Rostedt  * Prints the generic fields of irqs off, in hard or softirq, preempt
451e6e1e259SSteven Rostedt  * count.
452f81c972dSSteven Rostedt  */
trace_print_lat_fmt(struct trace_seq * s,struct trace_entry * entry)453f81c972dSSteven Rostedt int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry)
454c4a8e8beSFrederic Weisbecker {
45510da37a6SDavid Sharp 	char hardsoft_irq;
45610da37a6SDavid Sharp 	char need_resched;
45710da37a6SDavid Sharp 	char irqs_off;
45810da37a6SDavid Sharp 	int hardirq;
45910da37a6SDavid Sharp 	int softirq;
460289e7b0fSSebastian Andrzej Siewior 	int bh_off;
4617e6867bfSPeter Zijlstra 	int nmi;
462c4a8e8beSFrederic Weisbecker 
4637e6867bfSPeter Zijlstra 	nmi = entry->flags & TRACE_FLAG_NMI;
464c4a8e8beSFrederic Weisbecker 	hardirq = entry->flags & TRACE_FLAG_HARDIRQ;
465c4a8e8beSFrederic Weisbecker 	softirq = entry->flags & TRACE_FLAG_SOFTIRQ;
466289e7b0fSSebastian Andrzej Siewior 	bh_off = entry->flags & TRACE_FLAG_BH_OFF;
467d9793bd8SArnaldo Carvalho de Melo 
46810da37a6SDavid Sharp 	irqs_off =
469289e7b0fSSebastian Andrzej Siewior 		(entry->flags & TRACE_FLAG_IRQS_OFF && bh_off) ? 'D' :
470d9793bd8SArnaldo Carvalho de Melo 		(entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
471289e7b0fSSebastian Andrzej Siewior 		bh_off ? 'b' :
47210da37a6SDavid Sharp 		'.';
473e5137b50SPeter Zijlstra 
4740172afefSThomas Gleixner 	switch (entry->flags & (TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_NEED_RESCHED_LAZY |
475e5137b50SPeter Zijlstra 				TRACE_FLAG_PREEMPT_RESCHED)) {
4760172afefSThomas Gleixner 	case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_NEED_RESCHED_LAZY | TRACE_FLAG_PREEMPT_RESCHED:
4770172afefSThomas Gleixner 		need_resched = 'B';
4780172afefSThomas Gleixner 		break;
479e5137b50SPeter Zijlstra 	case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_PREEMPT_RESCHED:
480e5137b50SPeter Zijlstra 		need_resched = 'N';
481e5137b50SPeter Zijlstra 		break;
4820172afefSThomas Gleixner 	case TRACE_FLAG_NEED_RESCHED_LAZY | TRACE_FLAG_PREEMPT_RESCHED:
4830172afefSThomas Gleixner 		need_resched = 'L';
4840172afefSThomas Gleixner 		break;
4850172afefSThomas Gleixner 	case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_NEED_RESCHED_LAZY:
4860172afefSThomas Gleixner 		need_resched = 'b';
4870172afefSThomas Gleixner 		break;
488e5137b50SPeter Zijlstra 	case TRACE_FLAG_NEED_RESCHED:
489e5137b50SPeter Zijlstra 		need_resched = 'n';
490e5137b50SPeter Zijlstra 		break;
491e5137b50SPeter Zijlstra 	case TRACE_FLAG_PREEMPT_RESCHED:
492e5137b50SPeter Zijlstra 		need_resched = 'p';
493e5137b50SPeter Zijlstra 		break;
4940172afefSThomas Gleixner 	case TRACE_FLAG_NEED_RESCHED_LAZY:
4950172afefSThomas Gleixner 		need_resched = 'l';
4960172afefSThomas Gleixner 		break;
497e5137b50SPeter Zijlstra 	default:
498e5137b50SPeter Zijlstra 		need_resched = '.';
499e5137b50SPeter Zijlstra 		break;
500e5137b50SPeter Zijlstra 	}
501e5137b50SPeter Zijlstra 
50210da37a6SDavid Sharp 	hardsoft_irq =
5037e6867bfSPeter Zijlstra 		(nmi && hardirq)     ? 'Z' :
5047e6867bfSPeter Zijlstra 		nmi                  ? 'z' :
505d9793bd8SArnaldo Carvalho de Melo 		(hardirq && softirq) ? 'H' :
50610da37a6SDavid Sharp 		hardirq              ? 'h' :
50710da37a6SDavid Sharp 		softirq              ? 's' :
50810da37a6SDavid Sharp 		                       '.' ;
50910da37a6SDavid Sharp 
51019a7fe20SSteven Rostedt (Red Hat) 	trace_seq_printf(s, "%c%c%c",
51119a7fe20SSteven Rostedt (Red Hat) 			 irqs_off, need_resched, hardsoft_irq);
512c4a8e8beSFrederic Weisbecker 
51354357f0cSThomas Gleixner 	if (entry->preempt_count & 0xf)
51454357f0cSThomas Gleixner 		trace_seq_printf(s, "%x", entry->preempt_count & 0xf);
51554357f0cSThomas Gleixner 	else
51654357f0cSThomas Gleixner 		trace_seq_putc(s, '.');
51754357f0cSThomas Gleixner 
51854357f0cSThomas Gleixner 	if (entry->preempt_count & 0xf0)
51954357f0cSThomas Gleixner 		trace_seq_printf(s, "%x", entry->preempt_count >> 4);
520637e7e86SSteven Rostedt 	else
52119a7fe20SSteven Rostedt (Red Hat) 		trace_seq_putc(s, '.');
522829b876dSSteven Rostedt 
52319a7fe20SSteven Rostedt (Red Hat) 	return !trace_seq_has_overflowed(s);
524c4a8e8beSFrederic Weisbecker }
525c4a8e8beSFrederic Weisbecker 
526f81c972dSSteven Rostedt static int
lat_print_generic(struct trace_seq * s,struct trace_entry * entry,int cpu)527f81c972dSSteven Rostedt lat_print_generic(struct trace_seq *s, struct trace_entry *entry, int cpu)
528f81c972dSSteven Rostedt {
529f81c972dSSteven Rostedt 	char comm[TASK_COMM_LEN];
530f81c972dSSteven Rostedt 
531f81c972dSSteven Rostedt 	trace_find_cmdline(entry->pid, comm);
532f81c972dSSteven Rostedt 
533795d6379SSebastian Andrzej Siewior 	trace_seq_printf(s, "%8.8s-%-7d %3d",
53419a7fe20SSteven Rostedt (Red Hat) 			 comm, entry->pid, cpu);
535f81c972dSSteven Rostedt 
536f81c972dSSteven Rostedt 	return trace_print_lat_fmt(s, entry);
537f81c972dSSteven Rostedt }
538f81c972dSSteven Rostedt 
5398e1e1df2SByungchul Park #undef MARK
5408e1e1df2SByungchul Park #define MARK(v, s) {.val = v, .sym = s}
5418e1e1df2SByungchul Park /* trace overhead mark */
5428e1e1df2SByungchul Park static const struct trace_mark {
5438e1e1df2SByungchul Park 	unsigned long long	val; /* unit: nsec */
5448e1e1df2SByungchul Park 	char			sym;
5458e1e1df2SByungchul Park } mark[] = {
5468e1e1df2SByungchul Park 	MARK(1000000000ULL	, '$'), /* 1 sec */
547b838e1d9SJungseok Lee 	MARK(100000000ULL	, '@'), /* 100 msec */
548b838e1d9SJungseok Lee 	MARK(10000000ULL	, '*'), /* 10 msec */
5498e1e1df2SByungchul Park 	MARK(1000000ULL		, '#'), /* 1000 usecs */
5508e1e1df2SByungchul Park 	MARK(100000ULL		, '!'), /* 100 usecs */
5518e1e1df2SByungchul Park 	MARK(10000ULL		, '+'), /* 10 usecs */
5528e1e1df2SByungchul Park };
5538e1e1df2SByungchul Park #undef MARK
5548e1e1df2SByungchul Park 
trace_find_mark(unsigned long long d)5558e1e1df2SByungchul Park char trace_find_mark(unsigned long long d)
5568e1e1df2SByungchul Park {
5578e1e1df2SByungchul Park 	int i;
5588e1e1df2SByungchul Park 	int size = ARRAY_SIZE(mark);
5598e1e1df2SByungchul Park 
5608e1e1df2SByungchul Park 	for (i = 0; i < size; i++) {
561b838e1d9SJungseok Lee 		if (d > mark[i].val)
5628e1e1df2SByungchul Park 			break;
5638e1e1df2SByungchul Park 	}
5648e1e1df2SByungchul Park 
5658e1e1df2SByungchul Park 	return (i == size) ? ' ' : mark[i].sym;
5668e1e1df2SByungchul Park }
567c4a8e8beSFrederic Weisbecker 
568d9793bd8SArnaldo Carvalho de Melo static int
lat_print_timestamp(struct trace_iterator * iter,u64 next_ts)5698be0709fSDavid Sharp lat_print_timestamp(struct trace_iterator *iter, u64 next_ts)
570c4a8e8beSFrederic Weisbecker {
571983f938aSSteven Rostedt (Red Hat) 	struct trace_array *tr = iter->tr;
572983f938aSSteven Rostedt (Red Hat) 	unsigned long verbose = tr->trace_flags & TRACE_ITER_VERBOSE;
5738be0709fSDavid Sharp 	unsigned long in_ns = iter->iter_flags & TRACE_FILE_TIME_IN_NS;
5741c5eb448SSteven Rostedt (VMware) 	unsigned long long abs_ts = iter->ts - iter->array_buffer->time_start;
5758be0709fSDavid Sharp 	unsigned long long rel_ts = next_ts - iter->ts;
5768be0709fSDavid Sharp 	struct trace_seq *s = &iter->seq;
5778be0709fSDavid Sharp 
5788be0709fSDavid Sharp 	if (in_ns) {
5798be0709fSDavid Sharp 		abs_ts = ns2usecs(abs_ts);
5808be0709fSDavid Sharp 		rel_ts = ns2usecs(rel_ts);
5818be0709fSDavid Sharp 	}
5828be0709fSDavid Sharp 
5838be0709fSDavid Sharp 	if (verbose && in_ns) {
5848be0709fSDavid Sharp 		unsigned long abs_usec = do_div(abs_ts, USEC_PER_MSEC);
5858be0709fSDavid Sharp 		unsigned long abs_msec = (unsigned long)abs_ts;
5868be0709fSDavid Sharp 		unsigned long rel_usec = do_div(rel_ts, USEC_PER_MSEC);
5878be0709fSDavid Sharp 		unsigned long rel_msec = (unsigned long)rel_ts;
5888be0709fSDavid Sharp 
58919a7fe20SSteven Rostedt (Red Hat) 		trace_seq_printf(
5908be0709fSDavid Sharp 			s, "[%08llx] %ld.%03ldms (+%ld.%03ldms): ",
5918be0709fSDavid Sharp 			ns2usecs(iter->ts),
5928be0709fSDavid Sharp 			abs_msec, abs_usec,
5938be0709fSDavid Sharp 			rel_msec, rel_usec);
59419a7fe20SSteven Rostedt (Red Hat) 
5958be0709fSDavid Sharp 	} else if (verbose && !in_ns) {
59619a7fe20SSteven Rostedt (Red Hat) 		trace_seq_printf(
5978be0709fSDavid Sharp 			s, "[%016llx] %lld (+%lld): ",
5988be0709fSDavid Sharp 			iter->ts, abs_ts, rel_ts);
59919a7fe20SSteven Rostedt (Red Hat) 
6008be0709fSDavid Sharp 	} else if (!verbose && in_ns) {
60119a7fe20SSteven Rostedt (Red Hat) 		trace_seq_printf(
6028be0709fSDavid Sharp 			s, " %4lldus%c: ",
6038be0709fSDavid Sharp 			abs_ts,
6048e1e1df2SByungchul Park 			trace_find_mark(rel_ts * NSEC_PER_USEC));
60519a7fe20SSteven Rostedt (Red Hat) 
6068be0709fSDavid Sharp 	} else { /* !verbose && !in_ns */
60719a7fe20SSteven Rostedt (Red Hat) 		trace_seq_printf(s, " %4lld: ", abs_ts);
6088be0709fSDavid Sharp 	}
60919a7fe20SSteven Rostedt (Red Hat) 
61019a7fe20SSteven Rostedt (Red Hat) 	return !trace_seq_has_overflowed(s);
611c4a8e8beSFrederic Weisbecker }
612c4a8e8beSFrederic Weisbecker 
trace_print_time(struct trace_seq * s,struct trace_iterator * iter,unsigned long long ts)613eaa7a897SYordan Karadzhov (VMware) static void trace_print_time(struct trace_seq *s, struct trace_iterator *iter,
614eaa7a897SYordan Karadzhov (VMware) 			     unsigned long long ts)
615eaa7a897SYordan Karadzhov (VMware) {
616eaa7a897SYordan Karadzhov (VMware) 	unsigned long secs, usec_rem;
617eaa7a897SYordan Karadzhov (VMware) 	unsigned long long t;
618eaa7a897SYordan Karadzhov (VMware) 
619eaa7a897SYordan Karadzhov (VMware) 	if (iter->iter_flags & TRACE_FILE_TIME_IN_NS) {
620eaa7a897SYordan Karadzhov (VMware) 		t = ns2usecs(ts);
621eaa7a897SYordan Karadzhov (VMware) 		usec_rem = do_div(t, USEC_PER_SEC);
622eaa7a897SYordan Karadzhov (VMware) 		secs = (unsigned long)t;
623eaa7a897SYordan Karadzhov (VMware) 		trace_seq_printf(s, " %5lu.%06lu", secs, usec_rem);
624eaa7a897SYordan Karadzhov (VMware) 	} else
625eaa7a897SYordan Karadzhov (VMware) 		trace_seq_printf(s, " %12llu", ts);
626eaa7a897SYordan Karadzhov (VMware) }
627eaa7a897SYordan Karadzhov (VMware) 
trace_print_context(struct trace_iterator * iter)628c4a8e8beSFrederic Weisbecker int trace_print_context(struct trace_iterator *iter)
629c4a8e8beSFrederic Weisbecker {
630983f938aSSteven Rostedt (Red Hat) 	struct trace_array *tr = iter->tr;
631c4a8e8beSFrederic Weisbecker 	struct trace_seq *s = &iter->seq;
632c4a8e8beSFrederic Weisbecker 	struct trace_entry *entry = iter->ent;
6334ca53085SSteven Rostedt 	char comm[TASK_COMM_LEN];
6344ca53085SSteven Rostedt 
6354ca53085SSteven Rostedt 	trace_find_cmdline(entry->pid, comm);
636c4a8e8beSFrederic Weisbecker 
637795d6379SSebastian Andrzej Siewior 	trace_seq_printf(s, "%16s-%-7d ", comm, entry->pid);
63877271ce4SSteven Rostedt 
639441dae8fSJoel Fernandes 	if (tr->trace_flags & TRACE_ITER_RECORD_TGID) {
640441dae8fSJoel Fernandes 		unsigned int tgid = trace_find_tgid(entry->pid);
641441dae8fSJoel Fernandes 
642441dae8fSJoel Fernandes 		if (!tgid)
643795d6379SSebastian Andrzej Siewior 			trace_seq_printf(s, "(-------) ");
644441dae8fSJoel Fernandes 		else
645795d6379SSebastian Andrzej Siewior 			trace_seq_printf(s, "(%7d) ", tgid);
646441dae8fSJoel Fernandes 	}
647441dae8fSJoel Fernandes 
648f8494fa3SJoel Fernandes (Google) 	trace_seq_printf(s, "[%03d] ", iter->cpu);
649f8494fa3SJoel Fernandes (Google) 
650983f938aSSteven Rostedt (Red Hat) 	if (tr->trace_flags & TRACE_ITER_IRQ_INFO)
65119a7fe20SSteven Rostedt (Red Hat) 		trace_print_lat_fmt(s, entry);
65277271ce4SSteven Rostedt 
653eaa7a897SYordan Karadzhov (VMware) 	trace_print_time(s, iter, iter->ts);
654eaa7a897SYordan Karadzhov (VMware) 	trace_seq_puts(s, ": ");
65519a7fe20SSteven Rostedt (Red Hat) 
65619a7fe20SSteven Rostedt (Red Hat) 	return !trace_seq_has_overflowed(s);
657c4a8e8beSFrederic Weisbecker }
658c4a8e8beSFrederic Weisbecker 
trace_print_lat_context(struct trace_iterator * iter)659c4a8e8beSFrederic Weisbecker int trace_print_lat_context(struct trace_iterator *iter)
660c4a8e8beSFrederic Weisbecker {
661ff895103SSteven Rostedt (VMware) 	struct trace_entry *entry, *next_entry;
662983f938aSSteven Rostedt (Red Hat) 	struct trace_array *tr = iter->tr;
663c4a8e8beSFrederic Weisbecker 	struct trace_seq *s = &iter->seq;
664983f938aSSteven Rostedt (Red Hat) 	unsigned long verbose = (tr->trace_flags & TRACE_ITER_VERBOSE);
665ff895103SSteven Rostedt (VMware) 	u64 next_ts;
666c4a8e8beSFrederic Weisbecker 
667ff895103SSteven Rostedt (VMware) 	next_entry = trace_find_next_entry(iter, NULL, &next_ts);
668c4a8e8beSFrederic Weisbecker 	if (!next_entry)
669c4a8e8beSFrederic Weisbecker 		next_ts = iter->ts;
670c4a8e8beSFrederic Weisbecker 
671ff895103SSteven Rostedt (VMware) 	/* trace_find_next_entry() may change iter->ent */
672ff895103SSteven Rostedt (VMware) 	entry = iter->ent;
673ff895103SSteven Rostedt (VMware) 
674c4a8e8beSFrederic Weisbecker 	if (verbose) {
6754ca53085SSteven Rostedt 		char comm[TASK_COMM_LEN];
6764ca53085SSteven Rostedt 
6774ca53085SSteven Rostedt 		trace_find_cmdline(entry->pid, comm);
6784ca53085SSteven Rostedt 
67919a7fe20SSteven Rostedt (Red Hat) 		trace_seq_printf(
680795d6379SSebastian Andrzej Siewior 			s, "%16s %7d %3d %d %08x %08lx ",
6818be0709fSDavid Sharp 			comm, entry->pid, iter->cpu, entry->flags,
68254357f0cSThomas Gleixner 			entry->preempt_count & 0xf, iter->idx);
683c4a8e8beSFrederic Weisbecker 	} else {
68419a7fe20SSteven Rostedt (Red Hat) 		lat_print_generic(s, entry, iter->cpu);
685c4a8e8beSFrederic Weisbecker 	}
686c4a8e8beSFrederic Weisbecker 
68719a7fe20SSteven Rostedt (Red Hat) 	lat_print_timestamp(iter, next_ts);
6888be0709fSDavid Sharp 
68919a7fe20SSteven Rostedt (Red Hat) 	return !trace_seq_has_overflowed(s);
690c4a8e8beSFrederic Weisbecker }
691c4a8e8beSFrederic Weisbecker 
692533c20b0SSven Schnelle #ifdef CONFIG_FUNCTION_TRACE_ARGS
print_function_args(struct trace_seq * s,unsigned long * args,unsigned long func)693533c20b0SSven Schnelle void print_function_args(struct trace_seq *s, unsigned long *args,
694533c20b0SSven Schnelle 			 unsigned long func)
695533c20b0SSven Schnelle {
696533c20b0SSven Schnelle 	const struct btf_param *param;
697533c20b0SSven Schnelle 	const struct btf_type *t;
698533c20b0SSven Schnelle 	const char *param_name;
699533c20b0SSven Schnelle 	char name[KSYM_NAME_LEN];
700533c20b0SSven Schnelle 	unsigned long arg;
701533c20b0SSven Schnelle 	struct btf *btf;
702533c20b0SSven Schnelle 	s32 tid, nr = 0;
703533c20b0SSven Schnelle 	int a, p, x;
704533c20b0SSven Schnelle 
705533c20b0SSven Schnelle 	trace_seq_printf(s, "(");
706533c20b0SSven Schnelle 
707533c20b0SSven Schnelle 	if (!args)
708533c20b0SSven Schnelle 		goto out;
709533c20b0SSven Schnelle 	if (lookup_symbol_name(func, name))
710533c20b0SSven Schnelle 		goto out;
711533c20b0SSven Schnelle 
712533c20b0SSven Schnelle 	/* TODO: Pass module name here too */
713533c20b0SSven Schnelle 	t = btf_find_func_proto(name, &btf);
714533c20b0SSven Schnelle 	if (IS_ERR_OR_NULL(t))
715533c20b0SSven Schnelle 		goto out;
716533c20b0SSven Schnelle 
717533c20b0SSven Schnelle 	param = btf_get_func_param(t, &nr);
718533c20b0SSven Schnelle 	if (!param)
719533c20b0SSven Schnelle 		goto out_put;
720533c20b0SSven Schnelle 
721533c20b0SSven Schnelle 	for (a = 0, p = 0; p < nr; a++, p++) {
722533c20b0SSven Schnelle 		if (p)
723533c20b0SSven Schnelle 			trace_seq_puts(s, ", ");
724533c20b0SSven Schnelle 
725533c20b0SSven Schnelle 		/* This only prints what the arch allows (6 args by default) */
726533c20b0SSven Schnelle 		if (a == FTRACE_REGS_MAX_ARGS) {
727533c20b0SSven Schnelle 			trace_seq_puts(s, "...");
728533c20b0SSven Schnelle 			break;
729533c20b0SSven Schnelle 		}
730533c20b0SSven Schnelle 
731533c20b0SSven Schnelle 		arg = args[a];
732533c20b0SSven Schnelle 
733533c20b0SSven Schnelle 		param_name = btf_name_by_offset(btf, param[p].name_off);
734533c20b0SSven Schnelle 		if (param_name)
735533c20b0SSven Schnelle 			trace_seq_printf(s, "%s=", param_name);
736533c20b0SSven Schnelle 		t = btf_type_skip_modifiers(btf, param[p].type, &tid);
737533c20b0SSven Schnelle 
738533c20b0SSven Schnelle 		switch (t ? BTF_INFO_KIND(t->info) : BTF_KIND_UNKN) {
739533c20b0SSven Schnelle 		case BTF_KIND_UNKN:
740533c20b0SSven Schnelle 			trace_seq_putc(s, '?');
741533c20b0SSven Schnelle 			/* Still print unknown type values */
742533c20b0SSven Schnelle 			fallthrough;
743533c20b0SSven Schnelle 		case BTF_KIND_PTR:
744533c20b0SSven Schnelle 			trace_seq_printf(s, "0x%lx", arg);
745533c20b0SSven Schnelle 			break;
746533c20b0SSven Schnelle 		case BTF_KIND_INT:
747533c20b0SSven Schnelle 			trace_seq_printf(s, "%ld", arg);
748533c20b0SSven Schnelle 			break;
749533c20b0SSven Schnelle 		case BTF_KIND_ENUM:
750533c20b0SSven Schnelle 			trace_seq_printf(s, "%ld", arg);
751533c20b0SSven Schnelle 			break;
752533c20b0SSven Schnelle 		default:
753533c20b0SSven Schnelle 			/* This does not handle complex arguments */
754533c20b0SSven Schnelle 			trace_seq_printf(s, "(%s)[0x%lx", btf_type_str(t), arg);
755533c20b0SSven Schnelle 			for (x = sizeof(long); x < t->size; x += sizeof(long)) {
756533c20b0SSven Schnelle 				trace_seq_putc(s, ':');
757533c20b0SSven Schnelle 				if (++a == FTRACE_REGS_MAX_ARGS) {
758533c20b0SSven Schnelle 					trace_seq_puts(s, "...]");
759533c20b0SSven Schnelle 					goto out_put;
760533c20b0SSven Schnelle 				}
761533c20b0SSven Schnelle 				trace_seq_printf(s, "0x%lx", args[a]);
762533c20b0SSven Schnelle 			}
763533c20b0SSven Schnelle 			trace_seq_putc(s, ']');
764533c20b0SSven Schnelle 			break;
765533c20b0SSven Schnelle 		}
766533c20b0SSven Schnelle 	}
767533c20b0SSven Schnelle out_put:
768533c20b0SSven Schnelle 	btf_put(btf);
769533c20b0SSven Schnelle out:
770533c20b0SSven Schnelle 	trace_seq_printf(s, ")");
771533c20b0SSven Schnelle }
772533c20b0SSven Schnelle #endif
773533c20b0SSven Schnelle 
774f0868d1eSSteven Rostedt /**
775f0868d1eSSteven Rostedt  * ftrace_find_event - find a registered event
776f0868d1eSSteven Rostedt  * @type: the type of event to look for
777f0868d1eSSteven Rostedt  *
778f0868d1eSSteven Rostedt  * Returns an event of type @type otherwise NULL
7794f535968SLai Jiangshan  * Called with trace_event_read_lock() held.
780f0868d1eSSteven Rostedt  */
ftrace_find_event(int type)781f0868d1eSSteven Rostedt struct trace_event *ftrace_find_event(int type)
782f0868d1eSSteven Rostedt {
783f0868d1eSSteven Rostedt 	struct trace_event *event;
784f0868d1eSSteven Rostedt 
785391dda1bSSasha Levin 	hash_for_each_possible(event_hash, event, node, type) {
786f0868d1eSSteven Rostedt 		if (event->type == type)
787f0868d1eSSteven Rostedt 			return event;
788f0868d1eSSteven Rostedt 	}
789f0868d1eSSteven Rostedt 
790f0868d1eSSteven Rostedt 	return NULL;
791f0868d1eSSteven Rostedt }
792f0868d1eSSteven Rostedt 
79396e6122cSZheng Yejian static DEFINE_IDA(trace_event_ida);
794060fa5c8SSteven Rostedt 
free_trace_event_type(int type)79596e6122cSZheng Yejian static void free_trace_event_type(int type)
796060fa5c8SSteven Rostedt {
79796e6122cSZheng Yejian 	if (type >= __TRACE_LAST_TYPE)
79896e6122cSZheng Yejian 		ida_free(&trace_event_ida, type);
799060fa5c8SSteven Rostedt }
800060fa5c8SSteven Rostedt 
alloc_trace_event_type(void)80196e6122cSZheng Yejian static int alloc_trace_event_type(void)
80296e6122cSZheng Yejian {
80396e6122cSZheng Yejian 	int next;
804060fa5c8SSteven Rostedt 
80596e6122cSZheng Yejian 	/* Skip static defined type numbers */
80696e6122cSZheng Yejian 	next = ida_alloc_range(&trace_event_ida, __TRACE_LAST_TYPE,
80796e6122cSZheng Yejian 			       TRACE_EVENT_TYPE_MAX, GFP_KERNEL);
80896e6122cSZheng Yejian 	if (next < 0)
809060fa5c8SSteven Rostedt 		return 0;
810746cf345SWei Yang 	return next;
811060fa5c8SSteven Rostedt }
812060fa5c8SSteven Rostedt 
trace_event_read_lock(void)8134f535968SLai Jiangshan void trace_event_read_lock(void)
8144f535968SLai Jiangshan {
81552f6ad6dSzhangwei(Jovi) 	down_read(&trace_event_sem);
8164f535968SLai Jiangshan }
8174f535968SLai Jiangshan 
trace_event_read_unlock(void)8184f535968SLai Jiangshan void trace_event_read_unlock(void)
8194f535968SLai Jiangshan {
82052f6ad6dSzhangwei(Jovi) 	up_read(&trace_event_sem);
8214f535968SLai Jiangshan }
8224f535968SLai Jiangshan 
823f0868d1eSSteven Rostedt /**
8249023c930SSteven Rostedt (Red Hat)  * register_trace_event - register output for an event type
825f0868d1eSSteven Rostedt  * @event: the event type to register
826f0868d1eSSteven Rostedt  *
827f0868d1eSSteven Rostedt  * Event types are stored in a hash and this hash is used to
828f0868d1eSSteven Rostedt  * find a way to print an event. If the @event->type is set
829f0868d1eSSteven Rostedt  * then it will use that type, otherwise it will assign a
830f0868d1eSSteven Rostedt  * type to use.
831f0868d1eSSteven Rostedt  *
832f0868d1eSSteven Rostedt  * If you assign your own type, please make sure it is added
833f0868d1eSSteven Rostedt  * to the trace_type enum in trace.h, to avoid collisions
834f0868d1eSSteven Rostedt  * with the dynamic types.
835f0868d1eSSteven Rostedt  *
836f0868d1eSSteven Rostedt  * Returns the event type number or zero on error.
837f0868d1eSSteven Rostedt  */
register_trace_event(struct trace_event * event)8389023c930SSteven Rostedt (Red Hat) int register_trace_event(struct trace_event *event)
839f0868d1eSSteven Rostedt {
840f0868d1eSSteven Rostedt 	int ret = 0;
841f0868d1eSSteven Rostedt 
84252f6ad6dSzhangwei(Jovi) 	down_write(&trace_event_sem);
843f0868d1eSSteven Rostedt 
844060fa5c8SSteven Rostedt 	if (WARN_ON(!event))
84528bea271SPeter Zijlstra 		goto out;
846060fa5c8SSteven Rostedt 
847a9a57763SSteven Rostedt 	if (WARN_ON(!event->funcs))
848a9a57763SSteven Rostedt 		goto out;
849a9a57763SSteven Rostedt 
850060fa5c8SSteven Rostedt 	if (!event->type) {
85196e6122cSZheng Yejian 		event->type = alloc_trace_event_type();
852060fa5c8SSteven Rostedt 		if (!event->type)
853060fa5c8SSteven Rostedt 			goto out;
8544ee51101SGuo Zhengkui 	} else if (WARN(event->type > __TRACE_LAST_TYPE,
8554ee51101SGuo Zhengkui 			"Need to add type to trace.h")) {
856060fa5c8SSteven Rostedt 		goto out;
857060fa5c8SSteven Rostedt 	} else {
858060fa5c8SSteven Rostedt 		/* Is this event already used */
859f0868d1eSSteven Rostedt 		if (ftrace_find_event(event->type))
860f0868d1eSSteven Rostedt 			goto out;
861060fa5c8SSteven Rostedt 	}
862f0868d1eSSteven Rostedt 
863a9a57763SSteven Rostedt 	if (event->funcs->trace == NULL)
864a9a57763SSteven Rostedt 		event->funcs->trace = trace_nop_print;
865a9a57763SSteven Rostedt 	if (event->funcs->raw == NULL)
866a9a57763SSteven Rostedt 		event->funcs->raw = trace_nop_print;
867a9a57763SSteven Rostedt 	if (event->funcs->hex == NULL)
868a9a57763SSteven Rostedt 		event->funcs->hex = trace_nop_print;
869a9a57763SSteven Rostedt 	if (event->funcs->binary == NULL)
870a9a57763SSteven Rostedt 		event->funcs->binary = trace_nop_print;
871268ccda0SArnaldo Carvalho de Melo 
872391dda1bSSasha Levin 	hash_add(event_hash, &event->node, event->type);
873f0868d1eSSteven Rostedt 
874f0868d1eSSteven Rostedt 	ret = event->type;
875f0868d1eSSteven Rostedt  out:
87652f6ad6dSzhangwei(Jovi) 	up_write(&trace_event_sem);
877f0868d1eSSteven Rostedt 
878f0868d1eSSteven Rostedt 	return ret;
879f0868d1eSSteven Rostedt }
8809023c930SSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(register_trace_event);
881f0868d1eSSteven Rostedt 
882110bf2b7SSteven Rostedt /*
88352f6ad6dSzhangwei(Jovi)  * Used by module code with the trace_event_sem held for write.
884110bf2b7SSteven Rostedt  */
__unregister_trace_event(struct trace_event * event)8859023c930SSteven Rostedt (Red Hat) int __unregister_trace_event(struct trace_event *event)
886110bf2b7SSteven Rostedt {
887391dda1bSSasha Levin 	hash_del(&event->node);
88896e6122cSZheng Yejian 	free_trace_event_type(event->type);
889110bf2b7SSteven Rostedt 	return 0;
890110bf2b7SSteven Rostedt }
891110bf2b7SSteven Rostedt 
892f0868d1eSSteven Rostedt /**
8939023c930SSteven Rostedt (Red Hat)  * unregister_trace_event - remove a no longer used event
894f0868d1eSSteven Rostedt  * @event: the event to remove
895f0868d1eSSteven Rostedt  */
unregister_trace_event(struct trace_event * event)8969023c930SSteven Rostedt (Red Hat) int unregister_trace_event(struct trace_event *event)
897f0868d1eSSteven Rostedt {
89852f6ad6dSzhangwei(Jovi) 	down_write(&trace_event_sem);
8999023c930SSteven Rostedt (Red Hat) 	__unregister_trace_event(event);
90052f6ad6dSzhangwei(Jovi) 	up_write(&trace_event_sem);
901f0868d1eSSteven Rostedt 
902f0868d1eSSteven Rostedt 	return 0;
903f0868d1eSSteven Rostedt }
9049023c930SSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(unregister_trace_event);
905f633cef0SSteven Rostedt 
906f633cef0SSteven Rostedt /*
907f633cef0SSteven Rostedt  * Standard events
908f633cef0SSteven Rostedt  */
909f633cef0SSteven Rostedt 
print_array(struct trace_iterator * iter,void * pos,struct ftrace_event_field * field)91080a76994SSteven Rostedt (Google) static void print_array(struct trace_iterator *iter, void *pos,
91180a76994SSteven Rostedt (Google) 			struct ftrace_event_field *field)
91280a76994SSteven Rostedt (Google) {
91380a76994SSteven Rostedt (Google) 	int offset;
91480a76994SSteven Rostedt (Google) 	int len;
91580a76994SSteven Rostedt (Google) 	int i;
91680a76994SSteven Rostedt (Google) 
91780a76994SSteven Rostedt (Google) 	offset = *(int *)pos & 0xffff;
91880a76994SSteven Rostedt (Google) 	len = *(int *)pos >> 16;
91980a76994SSteven Rostedt (Google) 
92080a76994SSteven Rostedt (Google) 	if (field)
921c7bdb079SBeau Belgrave 		offset += field->offset + sizeof(int);
92280a76994SSteven Rostedt (Google) 
923c7bdb079SBeau Belgrave 	if (offset + len > iter->ent_size) {
92480a76994SSteven Rostedt (Google) 		trace_seq_puts(&iter->seq, "<OVERFLOW>");
92580a76994SSteven Rostedt (Google) 		return;
92680a76994SSteven Rostedt (Google) 	}
92780a76994SSteven Rostedt (Google) 
928c7bdb079SBeau Belgrave 	pos = (void *)iter->ent + offset;
929c7bdb079SBeau Belgrave 
93080a76994SSteven Rostedt (Google) 	for (i = 0; i < len; i++, pos++) {
93180a76994SSteven Rostedt (Google) 		if (i)
93280a76994SSteven Rostedt (Google) 			trace_seq_putc(&iter->seq, ',');
93380a76994SSteven Rostedt (Google) 		trace_seq_printf(&iter->seq, "%02x", *(unsigned char *)pos);
93480a76994SSteven Rostedt (Google) 	}
93580a76994SSteven Rostedt (Google) }
93680a76994SSteven Rostedt (Google) 
print_fields(struct trace_iterator * iter,struct trace_event_call * call,struct list_head * head)93780a76994SSteven Rostedt (Google) static void print_fields(struct trace_iterator *iter, struct trace_event_call *call,
93880a76994SSteven Rostedt (Google) 			 struct list_head *head)
93980a76994SSteven Rostedt (Google) {
94080a76994SSteven Rostedt (Google) 	struct ftrace_event_field *field;
94180a76994SSteven Rostedt (Google) 	int offset;
94280a76994SSteven Rostedt (Google) 	int len;
94380a76994SSteven Rostedt (Google) 	int ret;
94480a76994SSteven Rostedt (Google) 	void *pos;
94580a76994SSteven Rostedt (Google) 
946e70bb54dSsunliming 	list_for_each_entry_reverse(field, head, link) {
94780a76994SSteven Rostedt (Google) 		trace_seq_printf(&iter->seq, " %s=", field->name);
94880a76994SSteven Rostedt (Google) 		if (field->offset + field->size > iter->ent_size) {
94980a76994SSteven Rostedt (Google) 			trace_seq_puts(&iter->seq, "<OVERFLOW>");
95080a76994SSteven Rostedt (Google) 			continue;
95180a76994SSteven Rostedt (Google) 		}
95280a76994SSteven Rostedt (Google) 		pos = (void *)iter->ent + field->offset;
95380a76994SSteven Rostedt (Google) 
95480a76994SSteven Rostedt (Google) 		switch (field->filter_type) {
95580a76994SSteven Rostedt (Google) 		case FILTER_COMM:
95680a76994SSteven Rostedt (Google) 		case FILTER_STATIC_STRING:
95780a76994SSteven Rostedt (Google) 			trace_seq_printf(&iter->seq, "%.*s", field->size, (char *)pos);
95880a76994SSteven Rostedt (Google) 			break;
95980a76994SSteven Rostedt (Google) 		case FILTER_RDYN_STRING:
96080a76994SSteven Rostedt (Google) 		case FILTER_DYN_STRING:
96180a76994SSteven Rostedt (Google) 			offset = *(int *)pos & 0xffff;
96280a76994SSteven Rostedt (Google) 			len = *(int *)pos >> 16;
96380a76994SSteven Rostedt (Google) 
96480a76994SSteven Rostedt (Google) 			if (field->filter_type == FILTER_RDYN_STRING)
965c7bdb079SBeau Belgrave 				offset += field->offset + sizeof(int);
96680a76994SSteven Rostedt (Google) 
967c7bdb079SBeau Belgrave 			if (offset + len > iter->ent_size) {
96880a76994SSteven Rostedt (Google) 				trace_seq_puts(&iter->seq, "<OVERFLOW>");
96980a76994SSteven Rostedt (Google) 				break;
97080a76994SSteven Rostedt (Google) 			}
97180a76994SSteven Rostedt (Google) 			pos = (void *)iter->ent + offset;
97280a76994SSteven Rostedt (Google) 			trace_seq_printf(&iter->seq, "%.*s", len, (char *)pos);
97380a76994SSteven Rostedt (Google) 			break;
97480a76994SSteven Rostedt (Google) 		case FILTER_PTR_STRING:
97580a76994SSteven Rostedt (Google) 			if (!iter->fmt_size)
97680a76994SSteven Rostedt (Google) 				trace_iter_expand_format(iter);
97780a76994SSteven Rostedt (Google) 			pos = *(void **)pos;
97880a76994SSteven Rostedt (Google) 			ret = strncpy_from_kernel_nofault(iter->fmt, pos,
97980a76994SSteven Rostedt (Google) 							  iter->fmt_size);
98080a76994SSteven Rostedt (Google) 			if (ret < 0)
98180a76994SSteven Rostedt (Google) 				trace_seq_printf(&iter->seq, "(0x%px)", pos);
98280a76994SSteven Rostedt (Google) 			else
98380a76994SSteven Rostedt (Google) 				trace_seq_printf(&iter->seq, "(0x%px:%s)",
98480a76994SSteven Rostedt (Google) 						 pos, iter->fmt);
98580a76994SSteven Rostedt (Google) 			break;
98680a76994SSteven Rostedt (Google) 		case FILTER_TRACE_FN:
98780a76994SSteven Rostedt (Google) 			pos = *(void **)pos;
98880a76994SSteven Rostedt (Google) 			trace_seq_printf(&iter->seq, "%pS", pos);
98980a76994SSteven Rostedt (Google) 			break;
99080a76994SSteven Rostedt (Google) 		case FILTER_CPU:
99180a76994SSteven Rostedt (Google) 		case FILTER_OTHER:
99280a76994SSteven Rostedt (Google) 			switch (field->size) {
99380a76994SSteven Rostedt (Google) 			case 1:
99480a76994SSteven Rostedt (Google) 				if (isprint(*(char *)pos)) {
99580a76994SSteven Rostedt (Google) 					trace_seq_printf(&iter->seq, "'%c'",
99680a76994SSteven Rostedt (Google) 						 *(unsigned char *)pos);
99780a76994SSteven Rostedt (Google) 				}
99880a76994SSteven Rostedt (Google) 				trace_seq_printf(&iter->seq, "(%d)",
99980a76994SSteven Rostedt (Google) 						 *(unsigned char *)pos);
100080a76994SSteven Rostedt (Google) 				break;
100180a76994SSteven Rostedt (Google) 			case 2:
100280a76994SSteven Rostedt (Google) 				trace_seq_printf(&iter->seq, "0x%x (%d)",
100380a76994SSteven Rostedt (Google) 						 *(unsigned short *)pos,
100480a76994SSteven Rostedt (Google) 						 *(unsigned short *)pos);
100580a76994SSteven Rostedt (Google) 				break;
100680a76994SSteven Rostedt (Google) 			case 4:
100780a76994SSteven Rostedt (Google) 				/* dynamic array info is 4 bytes */
100880a76994SSteven Rostedt (Google) 				if (strstr(field->type, "__data_loc")) {
100980a76994SSteven Rostedt (Google) 					print_array(iter, pos, NULL);
101080a76994SSteven Rostedt (Google) 					break;
101180a76994SSteven Rostedt (Google) 				}
101280a76994SSteven Rostedt (Google) 
101380a76994SSteven Rostedt (Google) 				if (strstr(field->type, "__rel_loc")) {
101480a76994SSteven Rostedt (Google) 					print_array(iter, pos, field);
101580a76994SSteven Rostedt (Google) 					break;
101680a76994SSteven Rostedt (Google) 				}
101780a76994SSteven Rostedt (Google) 
101880a76994SSteven Rostedt (Google) 				trace_seq_printf(&iter->seq, "0x%x (%d)",
101980a76994SSteven Rostedt (Google) 						 *(unsigned int *)pos,
102080a76994SSteven Rostedt (Google) 						 *(unsigned int *)pos);
102180a76994SSteven Rostedt (Google) 				break;
102280a76994SSteven Rostedt (Google) 			case 8:
102380a76994SSteven Rostedt (Google) 				trace_seq_printf(&iter->seq, "0x%llx (%lld)",
102480a76994SSteven Rostedt (Google) 						 *(unsigned long long *)pos,
102580a76994SSteven Rostedt (Google) 						 *(unsigned long long *)pos);
102680a76994SSteven Rostedt (Google) 				break;
102780a76994SSteven Rostedt (Google) 			default:
102880a76994SSteven Rostedt (Google) 				trace_seq_puts(&iter->seq, "<INVALID-SIZE>");
102980a76994SSteven Rostedt (Google) 				break;
103080a76994SSteven Rostedt (Google) 			}
103180a76994SSteven Rostedt (Google) 			break;
103280a76994SSteven Rostedt (Google) 		default:
103380a76994SSteven Rostedt (Google) 			trace_seq_puts(&iter->seq, "<INVALID-TYPE>");
103480a76994SSteven Rostedt (Google) 		}
103580a76994SSteven Rostedt (Google) 	}
103680a76994SSteven Rostedt (Google) 	trace_seq_putc(&iter->seq, '\n');
103780a76994SSteven Rostedt (Google) }
103880a76994SSteven Rostedt (Google) 
print_event_fields(struct trace_iterator * iter,struct trace_event * event)103980a76994SSteven Rostedt (Google) enum print_line_t print_event_fields(struct trace_iterator *iter,
104080a76994SSteven Rostedt (Google) 				     struct trace_event *event)
104180a76994SSteven Rostedt (Google) {
104280a76994SSteven Rostedt (Google) 	struct trace_event_call *call;
104380a76994SSteven Rostedt (Google) 	struct list_head *head;
104480a76994SSteven Rostedt (Google) 
1045*0a8f11f8SSteven Rostedt 	lockdep_assert_held_read(&trace_event_sem);
1046*0a8f11f8SSteven Rostedt 
104780a76994SSteven Rostedt (Google) 	/* ftrace defined events have separate call structures */
104880a76994SSteven Rostedt (Google) 	if (event->type <= __TRACE_LAST_TYPE) {
104980a76994SSteven Rostedt (Google) 		bool found = false;
105080a76994SSteven Rostedt (Google) 
105180a76994SSteven Rostedt (Google) 		list_for_each_entry(call, &ftrace_events, list) {
105280a76994SSteven Rostedt (Google) 			if (call->event.type == event->type) {
105380a76994SSteven Rostedt (Google) 				found = true;
105480a76994SSteven Rostedt (Google) 				break;
105580a76994SSteven Rostedt (Google) 			}
105680a76994SSteven Rostedt (Google) 			/* No need to search all events */
105780a76994SSteven Rostedt (Google) 			if (call->event.type > __TRACE_LAST_TYPE)
105880a76994SSteven Rostedt (Google) 				break;
105980a76994SSteven Rostedt (Google) 		}
106080a76994SSteven Rostedt (Google) 		if (!found) {
106180a76994SSteven Rostedt (Google) 			trace_seq_printf(&iter->seq, "UNKNOWN TYPE %d\n", event->type);
106280a76994SSteven Rostedt (Google) 			goto out;
106380a76994SSteven Rostedt (Google) 		}
106480a76994SSteven Rostedt (Google) 	} else {
106580a76994SSteven Rostedt (Google) 		call = container_of(event, struct trace_event_call, event);
106680a76994SSteven Rostedt (Google) 	}
106780a76994SSteven Rostedt (Google) 	head = trace_get_fields(call);
106880a76994SSteven Rostedt (Google) 
106980a76994SSteven Rostedt (Google) 	trace_seq_printf(&iter->seq, "%s:", trace_event_name(call));
107080a76994SSteven Rostedt (Google) 
107180a76994SSteven Rostedt (Google) 	if (head && !list_empty(head))
107280a76994SSteven Rostedt (Google) 		print_fields(iter, call, head);
107380a76994SSteven Rostedt (Google) 	else
107480a76994SSteven Rostedt (Google) 		trace_seq_puts(&iter->seq, "No fields found\n");
107580a76994SSteven Rostedt (Google) 
107680a76994SSteven Rostedt (Google)  out:
107780a76994SSteven Rostedt (Google) 	return trace_handle_return(&iter->seq);
107880a76994SSteven Rostedt (Google) }
107980a76994SSteven Rostedt (Google) 
trace_nop_print(struct trace_iterator * iter,int flags,struct trace_event * event)1080a9a57763SSteven Rostedt enum print_line_t trace_nop_print(struct trace_iterator *iter, int flags,
1081a9a57763SSteven Rostedt 				  struct trace_event *event)
1082f633cef0SSteven Rostedt {
108319a7fe20SSteven Rostedt (Red Hat) 	trace_seq_printf(&iter->seq, "type: %d\n", iter->ent->type);
1084ee5e51f5SJiri Olsa 
108519a7fe20SSteven Rostedt (Red Hat) 	return trace_handle_return(&iter->seq);
1086f633cef0SSteven Rostedt }
1087f633cef0SSteven Rostedt 
print_fn_trace(struct trace_seq * s,unsigned long ip,unsigned long parent_ip,long delta,unsigned long * args,int flags)1088e1db6338SSteven Rostedt (VMware) static void print_fn_trace(struct trace_seq *s, unsigned long ip,
108976fe0337SSven Schnelle 			   unsigned long parent_ip, long delta,
109076fe0337SSven Schnelle 			   unsigned long *args, int flags)
1091e1db6338SSteven Rostedt (VMware) {
10927cfeb903SSteven Rostedt (Google) 	ip += delta;
10937cfeb903SSteven Rostedt (Google) 	parent_ip += delta;
10947cfeb903SSteven Rostedt (Google) 
1095e1db6338SSteven Rostedt (VMware) 	seq_print_ip_sym(s, ip, flags);
109676fe0337SSven Schnelle 	if (args)
109776fe0337SSven Schnelle 		print_function_args(s, args, ip);
1098e1db6338SSteven Rostedt (VMware) 
1099e1db6338SSteven Rostedt (VMware) 	if ((flags & TRACE_ITER_PRINT_PARENT) && parent_ip) {
1100e1db6338SSteven Rostedt (VMware) 		trace_seq_puts(s, " <-");
1101e1db6338SSteven Rostedt (VMware) 		seq_print_ip_sym(s, parent_ip, flags);
1102e1db6338SSteven Rostedt (VMware) 	}
1103e1db6338SSteven Rostedt (VMware) }
1104e1db6338SSteven Rostedt (VMware) 
1105f633cef0SSteven Rostedt /* TRACE_FN */
trace_fn_trace(struct trace_iterator * iter,int flags,struct trace_event * event)1106a9a57763SSteven Rostedt static enum print_line_t trace_fn_trace(struct trace_iterator *iter, int flags,
1107a9a57763SSteven Rostedt 					struct trace_event *event)
1108f633cef0SSteven Rostedt {
1109f633cef0SSteven Rostedt 	struct ftrace_entry *field;
11102c9b238eSArnaldo Carvalho de Melo 	struct trace_seq *s = &iter->seq;
111176fe0337SSven Schnelle 	unsigned long *args;
111276fe0337SSven Schnelle 	int args_size;
1113f633cef0SSteven Rostedt 
11142c9b238eSArnaldo Carvalho de Melo 	trace_assign_type(field, iter->ent);
1115f633cef0SSteven Rostedt 
111676fe0337SSven Schnelle 	args_size = iter->ent_size - offsetof(struct ftrace_entry, args);
111776fe0337SSven Schnelle 	if (args_size >= FTRACE_REGS_MAX_ARGS * sizeof(long))
111876fe0337SSven Schnelle 		args = field->args;
111976fe0337SSven Schnelle 	else
112076fe0337SSven Schnelle 		args = NULL;
112176fe0337SSven Schnelle 
112276fe0337SSven Schnelle 	print_fn_trace(s, field->ip, field->parent_ip, iter->tr->text_delta,
112376fe0337SSven Schnelle 		       args, flags);
112419a7fe20SSteven Rostedt (Red Hat) 	trace_seq_putc(s, '\n');
1125f633cef0SSteven Rostedt 
112619a7fe20SSteven Rostedt (Red Hat) 	return trace_handle_return(s);
1127f633cef0SSteven Rostedt }
1128f633cef0SSteven Rostedt 
trace_fn_raw(struct trace_iterator * iter,int flags,struct trace_event * event)1129a9a57763SSteven Rostedt static enum print_line_t trace_fn_raw(struct trace_iterator *iter, int flags,
1130a9a57763SSteven Rostedt 				      struct trace_event *event)
1131f633cef0SSteven Rostedt {
1132f633cef0SSteven Rostedt 	struct ftrace_entry *field;
1133f633cef0SSteven Rostedt 
11342c9b238eSArnaldo Carvalho de Melo 	trace_assign_type(field, iter->ent);
1135f633cef0SSteven Rostedt 
113619a7fe20SSteven Rostedt (Red Hat) 	trace_seq_printf(&iter->seq, "%lx %lx\n",
1137f633cef0SSteven Rostedt 			 field->ip,
113819a7fe20SSteven Rostedt (Red Hat) 			 field->parent_ip);
1139f633cef0SSteven Rostedt 
114019a7fe20SSteven Rostedt (Red Hat) 	return trace_handle_return(&iter->seq);
1141f633cef0SSteven Rostedt }
1142f633cef0SSteven Rostedt 
trace_fn_hex(struct trace_iterator * iter,int flags,struct trace_event * event)1143a9a57763SSteven Rostedt static enum print_line_t trace_fn_hex(struct trace_iterator *iter, int flags,
1144a9a57763SSteven Rostedt 				      struct trace_event *event)
1145f633cef0SSteven Rostedt {
1146f633cef0SSteven Rostedt 	struct ftrace_entry *field;
11472c9b238eSArnaldo Carvalho de Melo 	struct trace_seq *s = &iter->seq;
1148f633cef0SSteven Rostedt 
11492c9b238eSArnaldo Carvalho de Melo 	trace_assign_type(field, iter->ent);
1150f633cef0SSteven Rostedt 
115119a7fe20SSteven Rostedt (Red Hat) 	SEQ_PUT_HEX_FIELD(s, field->ip);
115219a7fe20SSteven Rostedt (Red Hat) 	SEQ_PUT_HEX_FIELD(s, field->parent_ip);
1153f633cef0SSteven Rostedt 
115419a7fe20SSteven Rostedt (Red Hat) 	return trace_handle_return(s);
1155f633cef0SSteven Rostedt }
1156f633cef0SSteven Rostedt 
trace_fn_bin(struct trace_iterator * iter,int flags,struct trace_event * event)1157a9a57763SSteven Rostedt static enum print_line_t trace_fn_bin(struct trace_iterator *iter, int flags,
1158a9a57763SSteven Rostedt 				      struct trace_event *event)
1159f633cef0SSteven Rostedt {
1160f633cef0SSteven Rostedt 	struct ftrace_entry *field;
11612c9b238eSArnaldo Carvalho de Melo 	struct trace_seq *s = &iter->seq;
1162f633cef0SSteven Rostedt 
11632c9b238eSArnaldo Carvalho de Melo 	trace_assign_type(field, iter->ent);
1164f633cef0SSteven Rostedt 
116519a7fe20SSteven Rostedt (Red Hat) 	SEQ_PUT_FIELD(s, field->ip);
116619a7fe20SSteven Rostedt (Red Hat) 	SEQ_PUT_FIELD(s, field->parent_ip);
1167f633cef0SSteven Rostedt 
116819a7fe20SSteven Rostedt (Red Hat) 	return trace_handle_return(s);
1169f633cef0SSteven Rostedt }
1170f633cef0SSteven Rostedt 
1171a9a57763SSteven Rostedt static struct trace_event_functions trace_fn_funcs = {
1172f633cef0SSteven Rostedt 	.trace		= trace_fn_trace,
1173f633cef0SSteven Rostedt 	.raw		= trace_fn_raw,
1174f633cef0SSteven Rostedt 	.hex		= trace_fn_hex,
1175f633cef0SSteven Rostedt 	.binary		= trace_fn_bin,
1176f633cef0SSteven Rostedt };
1177f633cef0SSteven Rostedt 
1178a9a57763SSteven Rostedt static struct trace_event trace_fn_event = {
1179a9a57763SSteven Rostedt 	.type		= TRACE_FN,
1180a9a57763SSteven Rostedt 	.funcs		= &trace_fn_funcs,
1181a9a57763SSteven Rostedt };
1182a9a57763SSteven Rostedt 
1183f633cef0SSteven Rostedt /* TRACE_CTX an TRACE_WAKE */
trace_ctxwake_print(struct trace_iterator * iter,char * delim)1184ae7462b4SArnaldo Carvalho de Melo static enum print_line_t trace_ctxwake_print(struct trace_iterator *iter,
1185ae7462b4SArnaldo Carvalho de Melo 					     char *delim)
1186f633cef0SSteven Rostedt {
1187f633cef0SSteven Rostedt 	struct ctx_switch_entry *field;
11884ca53085SSteven Rostedt 	char comm[TASK_COMM_LEN];
1189f633cef0SSteven Rostedt 	int S, T;
1190f633cef0SSteven Rostedt 
11914ca53085SSteven Rostedt 
11922c9b238eSArnaldo Carvalho de Melo 	trace_assign_type(field, iter->ent);
1193f633cef0SSteven Rostedt 
11941d48b080SPeter Zijlstra 	T = task_index_to_char(field->next_state);
11951d48b080SPeter Zijlstra 	S = task_index_to_char(field->prev_state);
11964ca53085SSteven Rostedt 	trace_find_cmdline(field->next_pid, comm);
119719a7fe20SSteven Rostedt (Red Hat) 	trace_seq_printf(&iter->seq,
1198795d6379SSebastian Andrzej Siewior 			 " %7d:%3d:%c %s [%03d] %7d:%3d:%c %s\n",
1199f633cef0SSteven Rostedt 			 field->prev_pid,
1200f633cef0SSteven Rostedt 			 field->prev_prio,
1201f633cef0SSteven Rostedt 			 S, delim,
1202f633cef0SSteven Rostedt 			 field->next_cpu,
1203f633cef0SSteven Rostedt 			 field->next_pid,
1204f633cef0SSteven Rostedt 			 field->next_prio,
120519a7fe20SSteven Rostedt (Red Hat) 			 T, comm);
1206f633cef0SSteven Rostedt 
120719a7fe20SSteven Rostedt (Red Hat) 	return trace_handle_return(&iter->seq);
1208f633cef0SSteven Rostedt }
1209f633cef0SSteven Rostedt 
trace_ctx_print(struct trace_iterator * iter,int flags,struct trace_event * event)1210a9a57763SSteven Rostedt static enum print_line_t trace_ctx_print(struct trace_iterator *iter, int flags,
1211a9a57763SSteven Rostedt 					 struct trace_event *event)
1212f633cef0SSteven Rostedt {
12132c9b238eSArnaldo Carvalho de Melo 	return trace_ctxwake_print(iter, "==>");
1214f633cef0SSteven Rostedt }
1215f633cef0SSteven Rostedt 
trace_wake_print(struct trace_iterator * iter,int flags,struct trace_event * event)1216ae7462b4SArnaldo Carvalho de Melo static enum print_line_t trace_wake_print(struct trace_iterator *iter,
1217a9a57763SSteven Rostedt 					  int flags, struct trace_event *event)
1218f633cef0SSteven Rostedt {
12192c9b238eSArnaldo Carvalho de Melo 	return trace_ctxwake_print(iter, "  +");
1220f633cef0SSteven Rostedt }
1221f633cef0SSteven Rostedt 
trace_ctxwake_raw(struct trace_iterator * iter,char S)12222c9b238eSArnaldo Carvalho de Melo static int trace_ctxwake_raw(struct trace_iterator *iter, char S)
1223f633cef0SSteven Rostedt {
1224f633cef0SSteven Rostedt 	struct ctx_switch_entry *field;
1225f633cef0SSteven Rostedt 	int T;
1226f633cef0SSteven Rostedt 
12272c9b238eSArnaldo Carvalho de Melo 	trace_assign_type(field, iter->ent);
1228f633cef0SSteven Rostedt 
1229f633cef0SSteven Rostedt 	if (!S)
12301d48b080SPeter Zijlstra 		S = task_index_to_char(field->prev_state);
12311d48b080SPeter Zijlstra 	T = task_index_to_char(field->next_state);
123219a7fe20SSteven Rostedt (Red Hat) 	trace_seq_printf(&iter->seq, "%d %d %c %d %d %d %c\n",
1233f633cef0SSteven Rostedt 			 field->prev_pid,
1234f633cef0SSteven Rostedt 			 field->prev_prio,
1235f633cef0SSteven Rostedt 			 S,
1236f633cef0SSteven Rostedt 			 field->next_cpu,
1237f633cef0SSteven Rostedt 			 field->next_pid,
1238f633cef0SSteven Rostedt 			 field->next_prio,
123919a7fe20SSteven Rostedt (Red Hat) 			 T);
1240f633cef0SSteven Rostedt 
124119a7fe20SSteven Rostedt (Red Hat) 	return trace_handle_return(&iter->seq);
1242f633cef0SSteven Rostedt }
1243f633cef0SSteven Rostedt 
trace_ctx_raw(struct trace_iterator * iter,int flags,struct trace_event * event)1244a9a57763SSteven Rostedt static enum print_line_t trace_ctx_raw(struct trace_iterator *iter, int flags,
1245a9a57763SSteven Rostedt 				       struct trace_event *event)
1246f633cef0SSteven Rostedt {
12472c9b238eSArnaldo Carvalho de Melo 	return trace_ctxwake_raw(iter, 0);
1248f633cef0SSteven Rostedt }
1249f633cef0SSteven Rostedt 
trace_wake_raw(struct trace_iterator * iter,int flags,struct trace_event * event)1250a9a57763SSteven Rostedt static enum print_line_t trace_wake_raw(struct trace_iterator *iter, int flags,
1251a9a57763SSteven Rostedt 					struct trace_event *event)
1252f633cef0SSteven Rostedt {
12532c9b238eSArnaldo Carvalho de Melo 	return trace_ctxwake_raw(iter, '+');
1254f633cef0SSteven Rostedt }
1255f633cef0SSteven Rostedt 
1256f633cef0SSteven Rostedt 
trace_ctxwake_hex(struct trace_iterator * iter,char S)12572c9b238eSArnaldo Carvalho de Melo static int trace_ctxwake_hex(struct trace_iterator *iter, char S)
1258f633cef0SSteven Rostedt {
1259f633cef0SSteven Rostedt 	struct ctx_switch_entry *field;
12602c9b238eSArnaldo Carvalho de Melo 	struct trace_seq *s = &iter->seq;
1261f633cef0SSteven Rostedt 	int T;
1262f633cef0SSteven Rostedt 
12632c9b238eSArnaldo Carvalho de Melo 	trace_assign_type(field, iter->ent);
1264f633cef0SSteven Rostedt 
1265f633cef0SSteven Rostedt 	if (!S)
12661d48b080SPeter Zijlstra 		S = task_index_to_char(field->prev_state);
12671d48b080SPeter Zijlstra 	T = task_index_to_char(field->next_state);
1268f633cef0SSteven Rostedt 
126919a7fe20SSteven Rostedt (Red Hat) 	SEQ_PUT_HEX_FIELD(s, field->prev_pid);
127019a7fe20SSteven Rostedt (Red Hat) 	SEQ_PUT_HEX_FIELD(s, field->prev_prio);
127119a7fe20SSteven Rostedt (Red Hat) 	SEQ_PUT_HEX_FIELD(s, S);
127219a7fe20SSteven Rostedt (Red Hat) 	SEQ_PUT_HEX_FIELD(s, field->next_cpu);
127319a7fe20SSteven Rostedt (Red Hat) 	SEQ_PUT_HEX_FIELD(s, field->next_pid);
127419a7fe20SSteven Rostedt (Red Hat) 	SEQ_PUT_HEX_FIELD(s, field->next_prio);
127519a7fe20SSteven Rostedt (Red Hat) 	SEQ_PUT_HEX_FIELD(s, T);
1276f633cef0SSteven Rostedt 
127719a7fe20SSteven Rostedt (Red Hat) 	return trace_handle_return(s);
1278f633cef0SSteven Rostedt }
1279f633cef0SSteven Rostedt 
trace_ctx_hex(struct trace_iterator * iter,int flags,struct trace_event * event)1280a9a57763SSteven Rostedt static enum print_line_t trace_ctx_hex(struct trace_iterator *iter, int flags,
1281a9a57763SSteven Rostedt 				       struct trace_event *event)
1282f633cef0SSteven Rostedt {
12832c9b238eSArnaldo Carvalho de Melo 	return trace_ctxwake_hex(iter, 0);
1284f633cef0SSteven Rostedt }
1285f633cef0SSteven Rostedt 
trace_wake_hex(struct trace_iterator * iter,int flags,struct trace_event * event)1286a9a57763SSteven Rostedt static enum print_line_t trace_wake_hex(struct trace_iterator *iter, int flags,
1287a9a57763SSteven Rostedt 					struct trace_event *event)
1288f633cef0SSteven Rostedt {
12892c9b238eSArnaldo Carvalho de Melo 	return trace_ctxwake_hex(iter, '+');
1290f633cef0SSteven Rostedt }
1291f633cef0SSteven Rostedt 
trace_ctxwake_bin(struct trace_iterator * iter,int flags,struct trace_event * event)1292ae7462b4SArnaldo Carvalho de Melo static enum print_line_t trace_ctxwake_bin(struct trace_iterator *iter,
1293a9a57763SSteven Rostedt 					   int flags, struct trace_event *event)
1294f633cef0SSteven Rostedt {
1295f633cef0SSteven Rostedt 	struct ctx_switch_entry *field;
12962c9b238eSArnaldo Carvalho de Melo 	struct trace_seq *s = &iter->seq;
1297f633cef0SSteven Rostedt 
12982c9b238eSArnaldo Carvalho de Melo 	trace_assign_type(field, iter->ent);
1299f633cef0SSteven Rostedt 
130019a7fe20SSteven Rostedt (Red Hat) 	SEQ_PUT_FIELD(s, field->prev_pid);
130119a7fe20SSteven Rostedt (Red Hat) 	SEQ_PUT_FIELD(s, field->prev_prio);
130219a7fe20SSteven Rostedt (Red Hat) 	SEQ_PUT_FIELD(s, field->prev_state);
130319a7fe20SSteven Rostedt (Red Hat) 	SEQ_PUT_FIELD(s, field->next_cpu);
130419a7fe20SSteven Rostedt (Red Hat) 	SEQ_PUT_FIELD(s, field->next_pid);
130519a7fe20SSteven Rostedt (Red Hat) 	SEQ_PUT_FIELD(s, field->next_prio);
130619a7fe20SSteven Rostedt (Red Hat) 	SEQ_PUT_FIELD(s, field->next_state);
1307f633cef0SSteven Rostedt 
130819a7fe20SSteven Rostedt (Red Hat) 	return trace_handle_return(s);
1309f633cef0SSteven Rostedt }
1310f633cef0SSteven Rostedt 
1311a9a57763SSteven Rostedt static struct trace_event_functions trace_ctx_funcs = {
1312f633cef0SSteven Rostedt 	.trace		= trace_ctx_print,
1313f633cef0SSteven Rostedt 	.raw		= trace_ctx_raw,
1314f633cef0SSteven Rostedt 	.hex		= trace_ctx_hex,
1315f633cef0SSteven Rostedt 	.binary		= trace_ctxwake_bin,
1316f633cef0SSteven Rostedt };
1317f633cef0SSteven Rostedt 
1318a9a57763SSteven Rostedt static struct trace_event trace_ctx_event = {
1319a9a57763SSteven Rostedt 	.type		= TRACE_CTX,
1320a9a57763SSteven Rostedt 	.funcs		= &trace_ctx_funcs,
1321a9a57763SSteven Rostedt };
1322a9a57763SSteven Rostedt 
1323a9a57763SSteven Rostedt static struct trace_event_functions trace_wake_funcs = {
1324f633cef0SSteven Rostedt 	.trace		= trace_wake_print,
1325f633cef0SSteven Rostedt 	.raw		= trace_wake_raw,
1326f633cef0SSteven Rostedt 	.hex		= trace_wake_hex,
1327f633cef0SSteven Rostedt 	.binary		= trace_ctxwake_bin,
1328f633cef0SSteven Rostedt };
1329f633cef0SSteven Rostedt 
1330a9a57763SSteven Rostedt static struct trace_event trace_wake_event = {
1331a9a57763SSteven Rostedt 	.type		= TRACE_WAKE,
1332a9a57763SSteven Rostedt 	.funcs		= &trace_wake_funcs,
1333a9a57763SSteven Rostedt };
1334a9a57763SSteven Rostedt 
1335f633cef0SSteven Rostedt /* TRACE_STACK */
1336f633cef0SSteven Rostedt 
trace_stack_print(struct trace_iterator * iter,int flags,struct trace_event * event)1337ae7462b4SArnaldo Carvalho de Melo static enum print_line_t trace_stack_print(struct trace_iterator *iter,
1338a9a57763SSteven Rostedt 					   int flags, struct trace_event *event)
1339f633cef0SSteven Rostedt {
1340f633cef0SSteven Rostedt 	struct stack_entry *field;
13412c9b238eSArnaldo Carvalho de Melo 	struct trace_seq *s = &iter->seq;
13424a9bd3f1SSteven Rostedt 	unsigned long *p;
13434a9bd3f1SSteven Rostedt 	unsigned long *end;
1344f633cef0SSteven Rostedt 
13452c9b238eSArnaldo Carvalho de Melo 	trace_assign_type(field, iter->ent);
13464a9bd3f1SSteven Rostedt 	end = (unsigned long *)((long)iter->ent + iter->ent_size);
1347f633cef0SSteven Rostedt 
134819a7fe20SSteven Rostedt (Red Hat) 	trace_seq_puts(s, "<stack trace>\n");
13494a9bd3f1SSteven Rostedt 
1350becf33f6SEiichi Tsukata 	for (p = field->caller; p && p < end && *p != ULONG_MAX; p++) {
1351f633cef0SSteven Rostedt 
135219a7fe20SSteven Rostedt (Red Hat) 		if (trace_seq_has_overflowed(s))
135319a7fe20SSteven Rostedt (Red Hat) 			break;
135419a7fe20SSteven Rostedt (Red Hat) 
135519a7fe20SSteven Rostedt (Red Hat) 		trace_seq_puts(s, " => ");
13566ce5a6f0STatsuya S 		if ((*p) == FTRACE_TRAMPOLINE_MARKER) {
13576ce5a6f0STatsuya S 			trace_seq_puts(s, "[FTRACE TRAMPOLINE]\n");
13586ce5a6f0STatsuya S 			continue;
13596ce5a6f0STatsuya S 		}
136035a380ddSMasami Hiramatsu (Google) 		seq_print_ip_sym(s, trace_adjust_address(iter->tr, *p), flags);
136119a7fe20SSteven Rostedt (Red Hat) 		trace_seq_putc(s, '\n');
1362f633cef0SSteven Rostedt 	}
1363f633cef0SSteven Rostedt 
136419a7fe20SSteven Rostedt (Red Hat) 	return trace_handle_return(s);
1365f633cef0SSteven Rostedt }
1366f633cef0SSteven Rostedt 
1367a9a57763SSteven Rostedt static struct trace_event_functions trace_stack_funcs = {
1368f633cef0SSteven Rostedt 	.trace		= trace_stack_print,
1369f633cef0SSteven Rostedt };
1370f633cef0SSteven Rostedt 
1371a9a57763SSteven Rostedt static struct trace_event trace_stack_event = {
1372a9a57763SSteven Rostedt 	.type		= TRACE_STACK,
1373a9a57763SSteven Rostedt 	.funcs		= &trace_stack_funcs,
1374a9a57763SSteven Rostedt };
1375a9a57763SSteven Rostedt 
1376f633cef0SSteven Rostedt /* TRACE_USER_STACK */
trace_user_stack_print(struct trace_iterator * iter,int flags,struct trace_event * event)1377ae7462b4SArnaldo Carvalho de Melo static enum print_line_t trace_user_stack_print(struct trace_iterator *iter,
1378a9a57763SSteven Rostedt 						int flags, struct trace_event *event)
1379f633cef0SSteven Rostedt {
1380983f938aSSteven Rostedt (Red Hat) 	struct trace_array *tr = iter->tr;
1381f633cef0SSteven Rostedt 	struct userstack_entry *field;
13822c9b238eSArnaldo Carvalho de Melo 	struct trace_seq *s = &iter->seq;
13836b1032d5SSteven Rostedt (Red Hat) 	struct mm_struct *mm = NULL;
13846b1032d5SSteven Rostedt (Red Hat) 	unsigned int i;
1385f633cef0SSteven Rostedt 
13862c9b238eSArnaldo Carvalho de Melo 	trace_assign_type(field, iter->ent);
1387f633cef0SSteven Rostedt 
138819a7fe20SSteven Rostedt (Red Hat) 	trace_seq_puts(s, "<user stack trace>\n");
13896b1032d5SSteven Rostedt (Red Hat) 
1390983f938aSSteven Rostedt (Red Hat) 	if (tr->trace_flags & TRACE_ITER_SYM_USEROBJ) {
13916b1032d5SSteven Rostedt (Red Hat) 		struct task_struct *task;
13926b1032d5SSteven Rostedt (Red Hat) 		/*
13936b1032d5SSteven Rostedt (Red Hat) 		 * we do the lookup on the thread group leader,
13946b1032d5SSteven Rostedt (Red Hat) 		 * since individual threads might have already quit!
13956b1032d5SSteven Rostedt (Red Hat) 		 */
13966b1032d5SSteven Rostedt (Red Hat) 		rcu_read_lock();
13976b1032d5SSteven Rostedt (Red Hat) 		task = find_task_by_vpid(field->tgid);
13986b1032d5SSteven Rostedt (Red Hat) 		if (task)
13996b1032d5SSteven Rostedt (Red Hat) 			mm = get_task_mm(task);
14006b1032d5SSteven Rostedt (Red Hat) 		rcu_read_unlock();
14016b1032d5SSteven Rostedt (Red Hat) 	}
14026b1032d5SSteven Rostedt (Red Hat) 
14036b1032d5SSteven Rostedt (Red Hat) 	for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
14046b1032d5SSteven Rostedt (Red Hat) 		unsigned long ip = field->caller[i];
14056b1032d5SSteven Rostedt (Red Hat) 
14066d54ceb5SEiichi Tsukata 		if (!ip || trace_seq_has_overflowed(s))
14076b1032d5SSteven Rostedt (Red Hat) 			break;
14086b1032d5SSteven Rostedt (Red Hat) 
14096b1032d5SSteven Rostedt (Red Hat) 		trace_seq_puts(s, " => ");
14106b1032d5SSteven Rostedt (Red Hat) 		seq_print_user_ip(s, mm, ip, flags);
14116b1032d5SSteven Rostedt (Red Hat) 		trace_seq_putc(s, '\n');
14126b1032d5SSteven Rostedt (Red Hat) 	}
14136b1032d5SSteven Rostedt (Red Hat) 
14146b1032d5SSteven Rostedt (Red Hat) 	if (mm)
14156b1032d5SSteven Rostedt (Red Hat) 		mmput(mm);
1416f633cef0SSteven Rostedt 
141719a7fe20SSteven Rostedt (Red Hat) 	return trace_handle_return(s);
1418f633cef0SSteven Rostedt }
1419f633cef0SSteven Rostedt 
1420a9a57763SSteven Rostedt static struct trace_event_functions trace_user_stack_funcs = {
1421f633cef0SSteven Rostedt 	.trace		= trace_user_stack_print,
1422f633cef0SSteven Rostedt };
1423f633cef0SSteven Rostedt 
1424a9a57763SSteven Rostedt static struct trace_event trace_user_stack_event = {
1425a9a57763SSteven Rostedt 	.type		= TRACE_USER_STACK,
1426a9a57763SSteven Rostedt 	.funcs		= &trace_user_stack_funcs,
1427a9a57763SSteven Rostedt };
1428a9a57763SSteven Rostedt 
1429e7c15cd8SSteven Rostedt (Red Hat) /* TRACE_HWLAT */
1430e7c15cd8SSteven Rostedt (Red Hat) static enum print_line_t
trace_hwlat_print(struct trace_iterator * iter,int flags,struct trace_event * event)1431e7c15cd8SSteven Rostedt (Red Hat) trace_hwlat_print(struct trace_iterator *iter, int flags,
1432e7c15cd8SSteven Rostedt (Red Hat) 		  struct trace_event *event)
1433e7c15cd8SSteven Rostedt (Red Hat) {
1434e7c15cd8SSteven Rostedt (Red Hat) 	struct trace_entry *entry = iter->ent;
1435e7c15cd8SSteven Rostedt (Red Hat) 	struct trace_seq *s = &iter->seq;
1436e7c15cd8SSteven Rostedt (Red Hat) 	struct hwlat_entry *field;
1437e7c15cd8SSteven Rostedt (Red Hat) 
1438e7c15cd8SSteven Rostedt (Red Hat) 	trace_assign_type(field, entry);
1439e7c15cd8SSteven Rostedt (Red Hat) 
1440b396bfdeSSteven Rostedt (VMware) 	trace_seq_printf(s, "#%-5u inner/outer(us): %4llu/%-5llu ts:%lld.%09ld count:%d",
1441e7c15cd8SSteven Rostedt (Red Hat) 			 field->seqnum,
1442e7c15cd8SSteven Rostedt (Red Hat) 			 field->duration,
1443e7c15cd8SSteven Rostedt (Red Hat) 			 field->outer_duration,
144451aad0aeSDeepa Dinamani 			 (long long)field->timestamp.tv_sec,
1445b396bfdeSSteven Rostedt (VMware) 			 field->timestamp.tv_nsec, field->count);
1446e7c15cd8SSteven Rostedt (Red Hat) 
14477b2c8625SSteven Rostedt (Red Hat) 	if (field->nmi_count) {
14487b2c8625SSteven Rostedt (Red Hat) 		/*
14497b2c8625SSteven Rostedt (Red Hat) 		 * The generic sched_clock() is not NMI safe, thus
14507b2c8625SSteven Rostedt (Red Hat) 		 * we only record the count and not the time.
14517b2c8625SSteven Rostedt (Red Hat) 		 */
14527b2c8625SSteven Rostedt (Red Hat) 		if (!IS_ENABLED(CONFIG_GENERIC_SCHED_CLOCK))
14537b2c8625SSteven Rostedt (Red Hat) 			trace_seq_printf(s, " nmi-total:%llu",
14547b2c8625SSteven Rostedt (Red Hat) 					 field->nmi_total_ts);
14557b2c8625SSteven Rostedt (Red Hat) 		trace_seq_printf(s, " nmi-count:%u",
14567b2c8625SSteven Rostedt (Red Hat) 				 field->nmi_count);
14577b2c8625SSteven Rostedt (Red Hat) 	}
14587b2c8625SSteven Rostedt (Red Hat) 
14597b2c8625SSteven Rostedt (Red Hat) 	trace_seq_putc(s, '\n');
14607b2c8625SSteven Rostedt (Red Hat) 
1461e7c15cd8SSteven Rostedt (Red Hat) 	return trace_handle_return(s);
1462e7c15cd8SSteven Rostedt (Red Hat) }
1463e7c15cd8SSteven Rostedt (Red Hat) 
1464e7c15cd8SSteven Rostedt (Red Hat) static enum print_line_t
trace_hwlat_raw(struct trace_iterator * iter,int flags,struct trace_event * event)1465e7c15cd8SSteven Rostedt (Red Hat) trace_hwlat_raw(struct trace_iterator *iter, int flags,
1466e7c15cd8SSteven Rostedt (Red Hat) 		struct trace_event *event)
1467e7c15cd8SSteven Rostedt (Red Hat) {
1468e7c15cd8SSteven Rostedt (Red Hat) 	struct hwlat_entry *field;
1469e7c15cd8SSteven Rostedt (Red Hat) 	struct trace_seq *s = &iter->seq;
1470e7c15cd8SSteven Rostedt (Red Hat) 
1471e7c15cd8SSteven Rostedt (Red Hat) 	trace_assign_type(field, iter->ent);
1472e7c15cd8SSteven Rostedt (Red Hat) 
147351aad0aeSDeepa Dinamani 	trace_seq_printf(s, "%llu %lld %lld %09ld %u\n",
1474e7c15cd8SSteven Rostedt (Red Hat) 			 field->duration,
1475e7c15cd8SSteven Rostedt (Red Hat) 			 field->outer_duration,
147651aad0aeSDeepa Dinamani 			 (long long)field->timestamp.tv_sec,
1477e7c15cd8SSteven Rostedt (Red Hat) 			 field->timestamp.tv_nsec,
1478e7c15cd8SSteven Rostedt (Red Hat) 			 field->seqnum);
1479e7c15cd8SSteven Rostedt (Red Hat) 
1480e7c15cd8SSteven Rostedt (Red Hat) 	return trace_handle_return(s);
1481e7c15cd8SSteven Rostedt (Red Hat) }
1482e7c15cd8SSteven Rostedt (Red Hat) 
1483e7c15cd8SSteven Rostedt (Red Hat) static struct trace_event_functions trace_hwlat_funcs = {
1484e7c15cd8SSteven Rostedt (Red Hat) 	.trace		= trace_hwlat_print,
1485e7c15cd8SSteven Rostedt (Red Hat) 	.raw		= trace_hwlat_raw,
1486e7c15cd8SSteven Rostedt (Red Hat) };
1487e7c15cd8SSteven Rostedt (Red Hat) 
1488e7c15cd8SSteven Rostedt (Red Hat) static struct trace_event trace_hwlat_event = {
1489e7c15cd8SSteven Rostedt (Red Hat) 	.type		= TRACE_HWLAT,
1490e7c15cd8SSteven Rostedt (Red Hat) 	.funcs		= &trace_hwlat_funcs,
1491e7c15cd8SSteven Rostedt (Red Hat) };
1492e7c15cd8SSteven Rostedt (Red Hat) 
1493bce29ac9SDaniel Bristot de Oliveira /* TRACE_OSNOISE */
1494bce29ac9SDaniel Bristot de Oliveira static enum print_line_t
trace_osnoise_print(struct trace_iterator * iter,int flags,struct trace_event * event)1495bce29ac9SDaniel Bristot de Oliveira trace_osnoise_print(struct trace_iterator *iter, int flags,
1496bce29ac9SDaniel Bristot de Oliveira 		    struct trace_event *event)
1497bce29ac9SDaniel Bristot de Oliveira {
1498bce29ac9SDaniel Bristot de Oliveira 	struct trace_entry *entry = iter->ent;
1499bce29ac9SDaniel Bristot de Oliveira 	struct trace_seq *s = &iter->seq;
1500bce29ac9SDaniel Bristot de Oliveira 	struct osnoise_entry *field;
1501bce29ac9SDaniel Bristot de Oliveira 	u64 ratio, ratio_dec;
1502bce29ac9SDaniel Bristot de Oliveira 	u64 net_runtime;
1503bce29ac9SDaniel Bristot de Oliveira 
1504bce29ac9SDaniel Bristot de Oliveira 	trace_assign_type(field, entry);
1505bce29ac9SDaniel Bristot de Oliveira 
1506bce29ac9SDaniel Bristot de Oliveira 	/*
1507bce29ac9SDaniel Bristot de Oliveira 	 * compute the available % of cpu time.
1508bce29ac9SDaniel Bristot de Oliveira 	 */
1509bce29ac9SDaniel Bristot de Oliveira 	net_runtime = field->runtime - field->noise;
1510bce29ac9SDaniel Bristot de Oliveira 	ratio = net_runtime * 10000000;
1511bce29ac9SDaniel Bristot de Oliveira 	do_div(ratio, field->runtime);
1512bce29ac9SDaniel Bristot de Oliveira 	ratio_dec = do_div(ratio, 100000);
1513bce29ac9SDaniel Bristot de Oliveira 
1514bce29ac9SDaniel Bristot de Oliveira 	trace_seq_printf(s, "%llu %10llu %3llu.%05llu %7llu",
1515bce29ac9SDaniel Bristot de Oliveira 			 field->runtime,
1516bce29ac9SDaniel Bristot de Oliveira 			 field->noise,
1517bce29ac9SDaniel Bristot de Oliveira 			 ratio, ratio_dec,
1518bce29ac9SDaniel Bristot de Oliveira 			 field->max_sample);
1519bce29ac9SDaniel Bristot de Oliveira 
1520bce29ac9SDaniel Bristot de Oliveira 	trace_seq_printf(s, " %6u", field->hw_count);
1521bce29ac9SDaniel Bristot de Oliveira 	trace_seq_printf(s, " %6u", field->nmi_count);
1522bce29ac9SDaniel Bristot de Oliveira 	trace_seq_printf(s, " %6u", field->irq_count);
1523bce29ac9SDaniel Bristot de Oliveira 	trace_seq_printf(s, " %6u", field->softirq_count);
1524bce29ac9SDaniel Bristot de Oliveira 	trace_seq_printf(s, " %6u", field->thread_count);
1525bce29ac9SDaniel Bristot de Oliveira 
1526bce29ac9SDaniel Bristot de Oliveira 	trace_seq_putc(s, '\n');
1527bce29ac9SDaniel Bristot de Oliveira 
1528bce29ac9SDaniel Bristot de Oliveira 	return trace_handle_return(s);
1529bce29ac9SDaniel Bristot de Oliveira }
1530bce29ac9SDaniel Bristot de Oliveira 
1531bce29ac9SDaniel Bristot de Oliveira static enum print_line_t
trace_osnoise_raw(struct trace_iterator * iter,int flags,struct trace_event * event)1532bce29ac9SDaniel Bristot de Oliveira trace_osnoise_raw(struct trace_iterator *iter, int flags,
1533bce29ac9SDaniel Bristot de Oliveira 		  struct trace_event *event)
1534bce29ac9SDaniel Bristot de Oliveira {
1535bce29ac9SDaniel Bristot de Oliveira 	struct osnoise_entry *field;
1536bce29ac9SDaniel Bristot de Oliveira 	struct trace_seq *s = &iter->seq;
1537bce29ac9SDaniel Bristot de Oliveira 
1538bce29ac9SDaniel Bristot de Oliveira 	trace_assign_type(field, iter->ent);
1539bce29ac9SDaniel Bristot de Oliveira 
1540bce29ac9SDaniel Bristot de Oliveira 	trace_seq_printf(s, "%lld %llu %llu %u %u %u %u %u\n",
1541bce29ac9SDaniel Bristot de Oliveira 			 field->runtime,
1542bce29ac9SDaniel Bristot de Oliveira 			 field->noise,
1543bce29ac9SDaniel Bristot de Oliveira 			 field->max_sample,
1544bce29ac9SDaniel Bristot de Oliveira 			 field->hw_count,
1545bce29ac9SDaniel Bristot de Oliveira 			 field->nmi_count,
1546bce29ac9SDaniel Bristot de Oliveira 			 field->irq_count,
1547bce29ac9SDaniel Bristot de Oliveira 			 field->softirq_count,
1548bce29ac9SDaniel Bristot de Oliveira 			 field->thread_count);
1549bce29ac9SDaniel Bristot de Oliveira 
1550bce29ac9SDaniel Bristot de Oliveira 	return trace_handle_return(s);
1551bce29ac9SDaniel Bristot de Oliveira }
1552bce29ac9SDaniel Bristot de Oliveira 
1553bce29ac9SDaniel Bristot de Oliveira static struct trace_event_functions trace_osnoise_funcs = {
1554bce29ac9SDaniel Bristot de Oliveira 	.trace		= trace_osnoise_print,
1555bce29ac9SDaniel Bristot de Oliveira 	.raw		= trace_osnoise_raw,
1556bce29ac9SDaniel Bristot de Oliveira };
1557bce29ac9SDaniel Bristot de Oliveira 
1558bce29ac9SDaniel Bristot de Oliveira static struct trace_event trace_osnoise_event = {
1559bce29ac9SDaniel Bristot de Oliveira 	.type		= TRACE_OSNOISE,
1560bce29ac9SDaniel Bristot de Oliveira 	.funcs		= &trace_osnoise_funcs,
1561bce29ac9SDaniel Bristot de Oliveira };
1562bce29ac9SDaniel Bristot de Oliveira 
1563a955d7eaSDaniel Bristot de Oliveira /* TRACE_TIMERLAT */
1564e88ed227SDaniel Bristot de Oliveira 
1565e88ed227SDaniel Bristot de Oliveira static char *timerlat_lat_context[] = {"irq", "thread", "user-ret"};
1566a955d7eaSDaniel Bristot de Oliveira static enum print_line_t
trace_timerlat_print(struct trace_iterator * iter,int flags,struct trace_event * event)1567a955d7eaSDaniel Bristot de Oliveira trace_timerlat_print(struct trace_iterator *iter, int flags,
1568a955d7eaSDaniel Bristot de Oliveira 		     struct trace_event *event)
1569a955d7eaSDaniel Bristot de Oliveira {
1570a955d7eaSDaniel Bristot de Oliveira 	struct trace_entry *entry = iter->ent;
1571a955d7eaSDaniel Bristot de Oliveira 	struct trace_seq *s = &iter->seq;
1572a955d7eaSDaniel Bristot de Oliveira 	struct timerlat_entry *field;
1573a955d7eaSDaniel Bristot de Oliveira 
1574a955d7eaSDaniel Bristot de Oliveira 	trace_assign_type(field, entry);
1575a955d7eaSDaniel Bristot de Oliveira 
1576a955d7eaSDaniel Bristot de Oliveira 	trace_seq_printf(s, "#%-5u context %6s timer_latency %9llu ns\n",
1577a955d7eaSDaniel Bristot de Oliveira 			 field->seqnum,
1578e88ed227SDaniel Bristot de Oliveira 			 timerlat_lat_context[field->context],
1579a955d7eaSDaniel Bristot de Oliveira 			 field->timer_latency);
1580a955d7eaSDaniel Bristot de Oliveira 
1581a955d7eaSDaniel Bristot de Oliveira 	return trace_handle_return(s);
1582a955d7eaSDaniel Bristot de Oliveira }
1583a955d7eaSDaniel Bristot de Oliveira 
1584a955d7eaSDaniel Bristot de Oliveira static enum print_line_t
trace_timerlat_raw(struct trace_iterator * iter,int flags,struct trace_event * event)1585a955d7eaSDaniel Bristot de Oliveira trace_timerlat_raw(struct trace_iterator *iter, int flags,
1586a955d7eaSDaniel Bristot de Oliveira 		   struct trace_event *event)
1587a955d7eaSDaniel Bristot de Oliveira {
1588a955d7eaSDaniel Bristot de Oliveira 	struct timerlat_entry *field;
1589a955d7eaSDaniel Bristot de Oliveira 	struct trace_seq *s = &iter->seq;
1590a955d7eaSDaniel Bristot de Oliveira 
1591a955d7eaSDaniel Bristot de Oliveira 	trace_assign_type(field, iter->ent);
1592a955d7eaSDaniel Bristot de Oliveira 
1593a955d7eaSDaniel Bristot de Oliveira 	trace_seq_printf(s, "%u %d %llu\n",
1594a955d7eaSDaniel Bristot de Oliveira 			 field->seqnum,
1595a955d7eaSDaniel Bristot de Oliveira 			 field->context,
1596a955d7eaSDaniel Bristot de Oliveira 			 field->timer_latency);
1597a955d7eaSDaniel Bristot de Oliveira 
1598a955d7eaSDaniel Bristot de Oliveira 	return trace_handle_return(s);
1599a955d7eaSDaniel Bristot de Oliveira }
1600a955d7eaSDaniel Bristot de Oliveira 
1601a955d7eaSDaniel Bristot de Oliveira static struct trace_event_functions trace_timerlat_funcs = {
1602a955d7eaSDaniel Bristot de Oliveira 	.trace		= trace_timerlat_print,
1603a955d7eaSDaniel Bristot de Oliveira 	.raw		= trace_timerlat_raw,
1604a955d7eaSDaniel Bristot de Oliveira };
1605a955d7eaSDaniel Bristot de Oliveira 
1606a955d7eaSDaniel Bristot de Oliveira static struct trace_event trace_timerlat_event = {
1607a955d7eaSDaniel Bristot de Oliveira 	.type		= TRACE_TIMERLAT,
1608a955d7eaSDaniel Bristot de Oliveira 	.funcs		= &trace_timerlat_funcs,
1609a955d7eaSDaniel Bristot de Oliveira };
1610a955d7eaSDaniel Bristot de Oliveira 
161109ae7234SSteven Rostedt (Red Hat) /* TRACE_BPUTS */
161209ae7234SSteven Rostedt (Red Hat) static enum print_line_t
trace_bputs_print(struct trace_iterator * iter,int flags,struct trace_event * event)161309ae7234SSteven Rostedt (Red Hat) trace_bputs_print(struct trace_iterator *iter, int flags,
161409ae7234SSteven Rostedt (Red Hat) 		   struct trace_event *event)
161509ae7234SSteven Rostedt (Red Hat) {
161609ae7234SSteven Rostedt (Red Hat) 	struct trace_entry *entry = iter->ent;
161709ae7234SSteven Rostedt (Red Hat) 	struct trace_seq *s = &iter->seq;
161809ae7234SSteven Rostedt (Red Hat) 	struct bputs_entry *field;
161909ae7234SSteven Rostedt (Red Hat) 
162009ae7234SSteven Rostedt (Red Hat) 	trace_assign_type(field, entry);
162109ae7234SSteven Rostedt (Red Hat) 
162219a7fe20SSteven Rostedt (Red Hat) 	seq_print_ip_sym(s, field->ip, flags);
162319a7fe20SSteven Rostedt (Red Hat) 	trace_seq_puts(s, ": ");
162419a7fe20SSteven Rostedt (Red Hat) 	trace_seq_puts(s, field->str);
162509ae7234SSteven Rostedt (Red Hat) 
162619a7fe20SSteven Rostedt (Red Hat) 	return trace_handle_return(s);
162709ae7234SSteven Rostedt (Red Hat) }
162809ae7234SSteven Rostedt (Red Hat) 
162909ae7234SSteven Rostedt (Red Hat) 
163009ae7234SSteven Rostedt (Red Hat) static enum print_line_t
trace_bputs_raw(struct trace_iterator * iter,int flags,struct trace_event * event)163109ae7234SSteven Rostedt (Red Hat) trace_bputs_raw(struct trace_iterator *iter, int flags,
163209ae7234SSteven Rostedt (Red Hat) 		struct trace_event *event)
163309ae7234SSteven Rostedt (Red Hat) {
163409ae7234SSteven Rostedt (Red Hat) 	struct bputs_entry *field;
163509ae7234SSteven Rostedt (Red Hat) 	struct trace_seq *s = &iter->seq;
163609ae7234SSteven Rostedt (Red Hat) 
163709ae7234SSteven Rostedt (Red Hat) 	trace_assign_type(field, iter->ent);
163809ae7234SSteven Rostedt (Red Hat) 
163919a7fe20SSteven Rostedt (Red Hat) 	trace_seq_printf(s, ": %lx : ", field->ip);
164019a7fe20SSteven Rostedt (Red Hat) 	trace_seq_puts(s, field->str);
164109ae7234SSteven Rostedt (Red Hat) 
164219a7fe20SSteven Rostedt (Red Hat) 	return trace_handle_return(s);
164309ae7234SSteven Rostedt (Red Hat) }
164409ae7234SSteven Rostedt (Red Hat) 
164509ae7234SSteven Rostedt (Red Hat) static struct trace_event_functions trace_bputs_funcs = {
164609ae7234SSteven Rostedt (Red Hat) 	.trace		= trace_bputs_print,
164709ae7234SSteven Rostedt (Red Hat) 	.raw		= trace_bputs_raw,
164809ae7234SSteven Rostedt (Red Hat) };
164909ae7234SSteven Rostedt (Red Hat) 
165009ae7234SSteven Rostedt (Red Hat) static struct trace_event trace_bputs_event = {
165109ae7234SSteven Rostedt (Red Hat) 	.type		= TRACE_BPUTS,
165209ae7234SSteven Rostedt (Red Hat) 	.funcs		= &trace_bputs_funcs,
165309ae7234SSteven Rostedt (Red Hat) };
165409ae7234SSteven Rostedt (Red Hat) 
165548ead020SFrederic Weisbecker /* TRACE_BPRINT */
16561427cdf0SLai Jiangshan static enum print_line_t
trace_bprint_print(struct trace_iterator * iter,int flags,struct trace_event * event)1657a9a57763SSteven Rostedt trace_bprint_print(struct trace_iterator *iter, int flags,
1658a9a57763SSteven Rostedt 		   struct trace_event *event)
16591427cdf0SLai Jiangshan {
16601427cdf0SLai Jiangshan 	struct trace_entry *entry = iter->ent;
16611427cdf0SLai Jiangshan 	struct trace_seq *s = &iter->seq;
166248ead020SFrederic Weisbecker 	struct bprint_entry *field;
16631427cdf0SLai Jiangshan 
16641427cdf0SLai Jiangshan 	trace_assign_type(field, entry);
16651427cdf0SLai Jiangshan 
166619a7fe20SSteven Rostedt (Red Hat) 	seq_print_ip_sym(s, field->ip, flags);
166719a7fe20SSteven Rostedt (Red Hat) 	trace_seq_puts(s, ": ");
166819a7fe20SSteven Rostedt (Red Hat) 	trace_seq_bprintf(s, field->fmt, field->buf);
16691427cdf0SLai Jiangshan 
167019a7fe20SSteven Rostedt (Red Hat) 	return trace_handle_return(s);
16711427cdf0SLai Jiangshan }
16721427cdf0SLai Jiangshan 
16731427cdf0SLai Jiangshan 
167448ead020SFrederic Weisbecker static enum print_line_t
trace_bprint_raw(struct trace_iterator * iter,int flags,struct trace_event * event)1675a9a57763SSteven Rostedt trace_bprint_raw(struct trace_iterator *iter, int flags,
1676a9a57763SSteven Rostedt 		 struct trace_event *event)
1677769b0441SFrederic Weisbecker {
167848ead020SFrederic Weisbecker 	struct bprint_entry *field;
1679769b0441SFrederic Weisbecker 	struct trace_seq *s = &iter->seq;
1680769b0441SFrederic Weisbecker 
1681769b0441SFrederic Weisbecker 	trace_assign_type(field, iter->ent);
16821427cdf0SLai Jiangshan 
168319a7fe20SSteven Rostedt (Red Hat) 	trace_seq_printf(s, ": %lx : ", field->ip);
168419a7fe20SSteven Rostedt (Red Hat) 	trace_seq_bprintf(s, field->fmt, field->buf);
16851427cdf0SLai Jiangshan 
168619a7fe20SSteven Rostedt (Red Hat) 	return trace_handle_return(s);
16871427cdf0SLai Jiangshan }
16881427cdf0SLai Jiangshan 
1689a9a57763SSteven Rostedt static struct trace_event_functions trace_bprint_funcs = {
169048ead020SFrederic Weisbecker 	.trace		= trace_bprint_print,
169148ead020SFrederic Weisbecker 	.raw		= trace_bprint_raw,
169248ead020SFrederic Weisbecker };
169348ead020SFrederic Weisbecker 
1694a9a57763SSteven Rostedt static struct trace_event trace_bprint_event = {
1695a9a57763SSteven Rostedt 	.type		= TRACE_BPRINT,
1696a9a57763SSteven Rostedt 	.funcs		= &trace_bprint_funcs,
1697a9a57763SSteven Rostedt };
1698a9a57763SSteven Rostedt 
169948ead020SFrederic Weisbecker /* TRACE_PRINT */
trace_print_print(struct trace_iterator * iter,int flags,struct trace_event * event)170048ead020SFrederic Weisbecker static enum print_line_t trace_print_print(struct trace_iterator *iter,
1701a9a57763SSteven Rostedt 					   int flags, struct trace_event *event)
170248ead020SFrederic Weisbecker {
170348ead020SFrederic Weisbecker 	struct print_entry *field;
170448ead020SFrederic Weisbecker 	struct trace_seq *s = &iter->seq;
17059b7bdf6fSSteven Rostedt 	unsigned long ip;
170648ead020SFrederic Weisbecker 
170748ead020SFrederic Weisbecker 	trace_assign_type(field, iter->ent);
170848ead020SFrederic Weisbecker 
17099b7bdf6fSSteven Rostedt 	ip = field->ip + iter->tr->text_delta;
17109b7bdf6fSSteven Rostedt 
17119b7bdf6fSSteven Rostedt 	seq_print_ip_sym(s, ip, flags);
17125efd3e2aSSteven Rostedt (Google) 	trace_seq_printf(s, ": %s", field->buf);
171348ead020SFrederic Weisbecker 
171419a7fe20SSteven Rostedt (Red Hat) 	return trace_handle_return(s);
171548ead020SFrederic Weisbecker }
171648ead020SFrederic Weisbecker 
trace_print_raw(struct trace_iterator * iter,int flags,struct trace_event * event)1717a9a57763SSteven Rostedt static enum print_line_t trace_print_raw(struct trace_iterator *iter, int flags,
1718a9a57763SSteven Rostedt 					 struct trace_event *event)
171948ead020SFrederic Weisbecker {
172048ead020SFrederic Weisbecker 	struct print_entry *field;
172148ead020SFrederic Weisbecker 
172248ead020SFrederic Weisbecker 	trace_assign_type(field, iter->ent);
172348ead020SFrederic Weisbecker 
17245efd3e2aSSteven Rostedt (Google) 	trace_seq_printf(&iter->seq, "# %lx %s", field->ip, field->buf);
172548ead020SFrederic Weisbecker 
172619a7fe20SSteven Rostedt (Red Hat) 	return trace_handle_return(&iter->seq);
172748ead020SFrederic Weisbecker }
172848ead020SFrederic Weisbecker 
1729a9a57763SSteven Rostedt static struct trace_event_functions trace_print_funcs = {
1730769b0441SFrederic Weisbecker 	.trace		= trace_print_print,
1731769b0441SFrederic Weisbecker 	.raw		= trace_print_raw,
17321427cdf0SLai Jiangshan };
17331427cdf0SLai Jiangshan 
1734a9a57763SSteven Rostedt static struct trace_event trace_print_event = {
1735a9a57763SSteven Rostedt 	.type	 	= TRACE_PRINT,
1736a9a57763SSteven Rostedt 	.funcs		= &trace_print_funcs,
1737a9a57763SSteven Rostedt };
1738a9a57763SSteven Rostedt 
trace_raw_data(struct trace_iterator * iter,int flags,struct trace_event * event)1739fa32e855SSteven Rostedt static enum print_line_t trace_raw_data(struct trace_iterator *iter, int flags,
1740fa32e855SSteven Rostedt 					 struct trace_event *event)
1741fa32e855SSteven Rostedt {
1742fa32e855SSteven Rostedt 	struct raw_data_entry *field;
1743fa32e855SSteven Rostedt 	int i;
1744fa32e855SSteven Rostedt 
1745fa32e855SSteven Rostedt 	trace_assign_type(field, iter->ent);
1746fa32e855SSteven Rostedt 
1747fa32e855SSteven Rostedt 	trace_seq_printf(&iter->seq, "# %x buf:", field->id);
1748fa32e855SSteven Rostedt 
1749fa32e855SSteven Rostedt 	for (i = 0; i < iter->ent_size - offsetof(struct raw_data_entry, buf); i++)
1750fa32e855SSteven Rostedt 		trace_seq_printf(&iter->seq, " %02x",
1751fa32e855SSteven Rostedt 				 (unsigned char)field->buf[i]);
1752fa32e855SSteven Rostedt 
1753fa32e855SSteven Rostedt 	trace_seq_putc(&iter->seq, '\n');
1754fa32e855SSteven Rostedt 
1755fa32e855SSteven Rostedt 	return trace_handle_return(&iter->seq);
1756fa32e855SSteven Rostedt }
1757fa32e855SSteven Rostedt 
1758fa32e855SSteven Rostedt static struct trace_event_functions trace_raw_data_funcs = {
1759fa32e855SSteven Rostedt 	.trace		= trace_raw_data,
1760fa32e855SSteven Rostedt 	.raw		= trace_raw_data,
1761fa32e855SSteven Rostedt };
1762fa32e855SSteven Rostedt 
1763fa32e855SSteven Rostedt static struct trace_event trace_raw_data_event = {
1764fa32e855SSteven Rostedt 	.type	 	= TRACE_RAW_DATA,
1765fa32e855SSteven Rostedt 	.funcs		= &trace_raw_data_funcs,
1766fa32e855SSteven Rostedt };
1767fa32e855SSteven Rostedt 
1768f689e4f2SYordan Karadzhov (VMware) static enum print_line_t
trace_func_repeats_raw(struct trace_iterator * iter,int flags,struct trace_event * event)1769f689e4f2SYordan Karadzhov (VMware) trace_func_repeats_raw(struct trace_iterator *iter, int flags,
1770f689e4f2SYordan Karadzhov (VMware) 			 struct trace_event *event)
1771f689e4f2SYordan Karadzhov (VMware) {
1772f689e4f2SYordan Karadzhov (VMware) 	struct func_repeats_entry *field;
1773f689e4f2SYordan Karadzhov (VMware) 	struct trace_seq *s = &iter->seq;
1774f689e4f2SYordan Karadzhov (VMware) 
1775f689e4f2SYordan Karadzhov (VMware) 	trace_assign_type(field, iter->ent);
1776f689e4f2SYordan Karadzhov (VMware) 
1777f689e4f2SYordan Karadzhov (VMware) 	trace_seq_printf(s, "%lu %lu %u %llu\n",
1778f689e4f2SYordan Karadzhov (VMware) 			 field->ip,
1779f689e4f2SYordan Karadzhov (VMware) 			 field->parent_ip,
1780f689e4f2SYordan Karadzhov (VMware) 			 field->count,
1781f689e4f2SYordan Karadzhov (VMware) 			 FUNC_REPEATS_GET_DELTA_TS(field));
1782f689e4f2SYordan Karadzhov (VMware) 
1783f689e4f2SYordan Karadzhov (VMware) 	return trace_handle_return(s);
1784f689e4f2SYordan Karadzhov (VMware) }
1785f689e4f2SYordan Karadzhov (VMware) 
1786f689e4f2SYordan Karadzhov (VMware) static enum print_line_t
trace_func_repeats_print(struct trace_iterator * iter,int flags,struct trace_event * event)1787f689e4f2SYordan Karadzhov (VMware) trace_func_repeats_print(struct trace_iterator *iter, int flags,
1788f689e4f2SYordan Karadzhov (VMware) 			 struct trace_event *event)
1789f689e4f2SYordan Karadzhov (VMware) {
1790f689e4f2SYordan Karadzhov (VMware) 	struct func_repeats_entry *field;
1791f689e4f2SYordan Karadzhov (VMware) 	struct trace_seq *s = &iter->seq;
1792f689e4f2SYordan Karadzhov (VMware) 
1793f689e4f2SYordan Karadzhov (VMware) 	trace_assign_type(field, iter->ent);
1794f689e4f2SYordan Karadzhov (VMware) 
179576fe0337SSven Schnelle 	print_fn_trace(s, field->ip, field->parent_ip, iter->tr->text_delta, NULL, flags);
1796f689e4f2SYordan Karadzhov (VMware) 	trace_seq_printf(s, " (repeats: %u, last_ts:", field->count);
1797f689e4f2SYordan Karadzhov (VMware) 	trace_print_time(s, iter,
1798f689e4f2SYordan Karadzhov (VMware) 			 iter->ts - FUNC_REPEATS_GET_DELTA_TS(field));
1799f689e4f2SYordan Karadzhov (VMware) 	trace_seq_puts(s, ")\n");
1800f689e4f2SYordan Karadzhov (VMware) 
1801f689e4f2SYordan Karadzhov (VMware) 	return trace_handle_return(s);
1802f689e4f2SYordan Karadzhov (VMware) }
1803f689e4f2SYordan Karadzhov (VMware) 
1804f689e4f2SYordan Karadzhov (VMware) static struct trace_event_functions trace_func_repeats_funcs = {
1805f689e4f2SYordan Karadzhov (VMware) 	.trace		= trace_func_repeats_print,
1806f689e4f2SYordan Karadzhov (VMware) 	.raw		= trace_func_repeats_raw,
1807f689e4f2SYordan Karadzhov (VMware) };
1808f689e4f2SYordan Karadzhov (VMware) 
1809f689e4f2SYordan Karadzhov (VMware) static struct trace_event trace_func_repeats_event = {
1810f689e4f2SYordan Karadzhov (VMware) 	.type	 	= TRACE_FUNC_REPEATS,
1811f689e4f2SYordan Karadzhov (VMware) 	.funcs		= &trace_func_repeats_funcs,
1812f689e4f2SYordan Karadzhov (VMware) };
181348ead020SFrederic Weisbecker 
1814f633cef0SSteven Rostedt static struct trace_event *events[] __initdata = {
1815f633cef0SSteven Rostedt 	&trace_fn_event,
1816f633cef0SSteven Rostedt 	&trace_ctx_event,
1817f633cef0SSteven Rostedt 	&trace_wake_event,
1818f633cef0SSteven Rostedt 	&trace_stack_event,
1819f633cef0SSteven Rostedt 	&trace_user_stack_event,
182009ae7234SSteven Rostedt (Red Hat) 	&trace_bputs_event,
182148ead020SFrederic Weisbecker 	&trace_bprint_event,
1822f633cef0SSteven Rostedt 	&trace_print_event,
1823e7c15cd8SSteven Rostedt (Red Hat) 	&trace_hwlat_event,
1824bce29ac9SDaniel Bristot de Oliveira 	&trace_osnoise_event,
1825a955d7eaSDaniel Bristot de Oliveira 	&trace_timerlat_event,
1826fa32e855SSteven Rostedt 	&trace_raw_data_event,
1827f689e4f2SYordan Karadzhov (VMware) 	&trace_func_repeats_event,
1828f633cef0SSteven Rostedt 	NULL
1829f633cef0SSteven Rostedt };
1830f633cef0SSteven Rostedt 
init_events(void)18313bb06eb6SSteven Rostedt (Google) __init int init_events(void)
1832f633cef0SSteven Rostedt {
1833f633cef0SSteven Rostedt 	struct trace_event *event;
1834f633cef0SSteven Rostedt 	int i, ret;
1835f633cef0SSteven Rostedt 
1836f633cef0SSteven Rostedt 	for (i = 0; events[i]; i++) {
1837f633cef0SSteven Rostedt 		event = events[i];
18389023c930SSteven Rostedt (Red Hat) 		ret = register_trace_event(event);
18394ee51101SGuo Zhengkui 		WARN_ONCE(!ret, "event %d failed to register", event->type);
1840f633cef0SSteven Rostedt 	}
1841f633cef0SSteven Rostedt 
1842f633cef0SSteven Rostedt 	return 0;
1843f633cef0SSteven Rostedt }
1844