1321 lines · 40.2 KB · C
RawDownload
 #ifndef _LINUX_KERNEL_TRACE_H#define _LINUX_KERNEL_TRACE_H #include <linux/fs.h>#include <linux/atomic.h>#include <linux/sched.h>#include <linux/clocksource.h>#include <linux/ring_buffer.h>#include <linux/mmiotrace.h>#include <linux/tracepoint.h>#include <linux/ftrace.h>#include <linux/hw_breakpoint.h>#include <linux/trace_seq.h>#include <linux/trace_events.h>#include <linux/compiler.h>#include <linux/trace_seq.h> #ifdef CONFIG_FTRACE_SYSCALLS#include <asm/unistd.h>		/* For NR_SYSCALLS	     */#include <asm/syscall.h>	/* some archs define it here */#endif enum trace_type {	__TRACE_FIRST_TYPE = 0, 	TRACE_FN,	TRACE_CTX,	TRACE_WAKE,	TRACE_STACK,	TRACE_PRINT,	TRACE_BPRINT,	TRACE_MMIO_RW,	TRACE_MMIO_MAP,	TRACE_BRANCH,	TRACE_GRAPH_RET,	TRACE_GRAPH_ENT,	TRACE_USER_STACK,	TRACE_BLK,	TRACE_BPUTS, 	__TRACE_LAST_TYPE,};  #undef __field#define __field(type, item)		type	item; #undef __field_struct#define __field_struct(type, item)	__field(type, item) #undef __field_desc#define __field_desc(type, container, item) #undef __array#define __array(type, item, size)	type	item[size]; #undef __array_desc#define __array_desc(type, container, item, size) #undef __dynamic_array#define __dynamic_array(type, item)	type	item[]; #undef F_STRUCT#define F_STRUCT(args...)		args #undef FTRACE_ENTRY#define FTRACE_ENTRY(name, struct_name, id, tstruct, print, filter)	\	struct struct_name {						\		struct trace_entry	ent;				\		tstruct							\	} #undef TP_ARGS#define TP_ARGS(args...)	args #undef FTRACE_ENTRY_DUP#define FTRACE_ENTRY_DUP(name, name_struct, id, tstruct, printk, filter) #undef FTRACE_ENTRY_REG#define FTRACE_ENTRY_REG(name, struct_name, id, tstruct, print,	\			 filter, regfn) \	FTRACE_ENTRY(name, struct_name, id, PARAMS(tstruct), PARAMS(print), \		     filter) #include "trace_entries.h" /* * syscalls are special, and need special handling, this is why * they are not included in trace_entries.h */struct syscall_trace_enter {	struct trace_entry	ent;	int			nr;	unsigned long		args[];}; struct syscall_trace_exit {	struct trace_entry	ent;	int			nr;	long			ret;}; struct kprobe_trace_entry_head {	struct trace_entry	ent;	unsigned long		ip;}; struct kretprobe_trace_entry_head {	struct trace_entry	ent;	unsigned long		func;	unsigned long		ret_ip;}; /* * trace_flag_type is an enumeration that holds different * states when a trace occurs. These are: *  IRQS_OFF		- interrupts were disabled *  IRQS_NOSUPPORT	- arch does not support irqs_disabled_flags *  NEED_RESCHED	- reschedule is requested *  HARDIRQ		- inside an interrupt handler *  SOFTIRQ		- inside a softirq handler */enum trace_flag_type {	TRACE_FLAG_IRQS_OFF		= 0x01,	TRACE_FLAG_IRQS_NOSUPPORT	= 0x02,	TRACE_FLAG_NEED_RESCHED		= 0x04,	TRACE_FLAG_HARDIRQ		= 0x08,	TRACE_FLAG_SOFTIRQ		= 0x10,	TRACE_FLAG_PREEMPT_RESCHED	= 0x20,}; #define TRACE_BUF_SIZE		1024 struct trace_array; /* * The CPU trace array - it consists of thousands of trace entries * plus some other descriptor data: (for example which task started * the trace, etc.) */struct trace_array_cpu {	atomic_t		disabled;	void			*buffer_page;	/* ring buffer spare */ 	unsigned long		entries;	unsigned long		saved_latency;	unsigned long		critical_start;	unsigned long		critical_end;	unsigned long		critical_sequence;	unsigned long		nice;	unsigned long		policy;	unsigned long		rt_priority;	unsigned long		skipped_entries;	cycle_t			preempt_timestamp;	pid_t			pid;	kuid_t			uid;	char			comm[TASK_COMM_LEN];}; struct tracer; struct trace_buffer {	struct trace_array		*tr;	struct ring_buffer		*buffer;	struct trace_array_cpu __percpu	*data;	cycle_t				time_start;	int				cpu;}; /* * The trace array - an array of per-CPU trace arrays. This is the * highest level data structure that individual tracers deal with. * They have on/off state as well: */struct trace_array {	struct list_head	list;	char			*name;	struct trace_buffer	trace_buffer;#ifdef CONFIG_TRACER_MAX_TRACE	/*	 * The max_buffer is used to snapshot the trace when a maximum	 * latency is reached, or when the user initiates a snapshot.	 * Some tracers will use this to store a maximum trace while	 * it continues examining live traces.	 *	 * The buffers for the max_buffer are set up the same as the trace_buffer	 * When a snapshot is taken, the buffer of the max_buffer is swapped	 * with the buffer of the trace_buffer and the buffers are reset for	 * the trace_buffer so the tracing can continue.	 */	struct trace_buffer	max_buffer;	bool			allocated_snapshot;	unsigned long		max_latency;#endif	/*	 * max_lock is used to protect the swapping of buffers	 * when taking a max snapshot. The buffers themselves are	 * protected by per_cpu spinlocks. But the action of the swap	 * needs its own lock.	 *	 * This is defined as a arch_spinlock_t in order to help	 * with performance when lockdep debugging is enabled.	 *	 * It is also used in other places outside the update_max_tr	 * so it needs to be defined outside of the	 * CONFIG_TRACER_MAX_TRACE.	 */	arch_spinlock_t		max_lock;	int			buffer_disabled;#ifdef CONFIG_FTRACE_SYSCALLS	int			sys_refcount_enter;	int			sys_refcount_exit;	struct trace_event_file __rcu *enter_syscall_files[NR_syscalls];	struct trace_event_file __rcu *exit_syscall_files[NR_syscalls];#endif	int			stop_count;	int			clock_id;	struct tracer		*current_trace;	unsigned int		flags;	raw_spinlock_t		start_lock;	struct dentry		*dir;	struct dentry		*options;	struct dentry		*percpu_dir;	struct dentry		*event_dir;	struct list_head	systems;	struct list_head	events;	cpumask_var_t		tracing_cpumask; /* only trace on set CPUs */	int			ref;#ifdef CONFIG_FUNCTION_TRACER	struct ftrace_ops	*ops;	/* function tracing enabled */	int			function_enabled;#endif}; enum {	TRACE_ARRAY_FL_GLOBAL	= (1 << 0)}; extern struct list_head ftrace_trace_arrays; extern struct mutex trace_types_lock; extern int trace_array_get(struct trace_array *tr);extern void trace_array_put(struct trace_array *tr); /* * The global tracer (top) should be the first trace array added, * but we check the flag anyway. */static inline struct trace_array *top_trace_array(void){	struct trace_array *tr; 	if (list_empty(&ftrace_trace_arrays))		return NULL; 	tr = list_entry(ftrace_trace_arrays.prev,			typeof(*tr), list);	WARN_ON(!(tr->flags & TRACE_ARRAY_FL_GLOBAL));	return tr;} #define FTRACE_CMP_TYPE(var, type) \	__builtin_types_compatible_p(typeof(var), type *) #undef IF_ASSIGN#define IF_ASSIGN(var, entry, etype, id)		\	if (FTRACE_CMP_TYPE(var, etype)) {		\		var = (typeof(var))(entry);		\		WARN_ON(id && (entry)->type != id);	\		break;					\	} /* Will cause compile errors if type is not found. */extern void __ftrace_bad_type(void); /* * The trace_assign_type is a verifier that the entry type is * the same as the type being assigned. To add new types simply * add a line with the following format: * * IF_ASSIGN(var, ent, type, id); * *  Where "type" is the trace type that includes the trace_entry *  as the "ent" item. And "id" is the trace identifier that is *  used in the trace_type enum. * *  If the type can have more than one id, then use zero. */#define trace_assign_type(var, ent)					\	do {								\		IF_ASSIGN(var, ent, struct ftrace_entry, TRACE_FN);	\		IF_ASSIGN(var, ent, struct ctx_switch_entry, 0);	\		IF_ASSIGN(var, ent, struct stack_entry, TRACE_STACK);	\		IF_ASSIGN(var, ent, struct userstack_entry, TRACE_USER_STACK);\		IF_ASSIGN(var, ent, struct print_entry, TRACE_PRINT);	\		IF_ASSIGN(var, ent, struct bprint_entry, TRACE_BPRINT);	\		IF_ASSIGN(var, ent, struct bputs_entry, TRACE_BPUTS);	\		IF_ASSIGN(var, ent, struct trace_mmiotrace_rw,		\			  TRACE_MMIO_RW);				\		IF_ASSIGN(var, ent, struct trace_mmiotrace_map,		\			  TRACE_MMIO_MAP);				\		IF_ASSIGN(var, ent, struct trace_branch, TRACE_BRANCH); \		IF_ASSIGN(var, ent, struct ftrace_graph_ent_entry,	\			  TRACE_GRAPH_ENT);		\		IF_ASSIGN(var, ent, struct ftrace_graph_ret_entry,	\			  TRACE_GRAPH_RET);		\		__ftrace_bad_type();					\	} while (0) /* * An option specific to a tracer. This is a boolean value. * The bit is the bit index that sets its value on the * flags value in struct tracer_flags. */struct tracer_opt {	const char	*name; /* Will appear on the trace_options file */	u32		bit; /* Mask assigned in val field in tracer_flags */}; /* * The set of specific options for a tracer. Your tracer * have to set the initial value of the flags val. */struct tracer_flags {	u32			val;	struct tracer_opt	*opts;}; /* Makes more easy to define a tracer opt */#define TRACER_OPT(s, b)	.name = #s, .bit = b  /** * struct tracer - a specific tracer and its callbacks to interact with tracefs * @name: the name chosen to select it on the available_tracers file * @init: called when one switches to this tracer (echo name > current_tracer) * @reset: called when one switches to another tracer * @start: called when tracing is unpaused (echo 1 > tracing_enabled) * @stop: called when tracing is paused (echo 0 > tracing_enabled) * @update_thresh: called when tracing_thresh is updated * @open: called when the trace file is opened * @pipe_open: called when the trace_pipe file is opened * @close: called when the trace file is released * @pipe_close: called when the trace_pipe file is released * @read: override the default read callback on trace_pipe * @splice_read: override the default splice_read callback on trace_pipe * @selftest: selftest to run on boot (see trace_selftest.c) * @print_headers: override the first lines that describe your columns * @print_line: callback that prints a trace * @set_flag: signals one of your private flags changed (trace_options file) * @flags: your private flags */struct tracer {	const char		*name;	int			(*init)(struct trace_array *tr);	void			(*reset)(struct trace_array *tr);	void			(*start)(struct trace_array *tr);	void			(*stop)(struct trace_array *tr);	int			(*update_thresh)(struct trace_array *tr);	void			(*open)(struct trace_iterator *iter);	void			(*pipe_open)(struct trace_iterator *iter);	void			(*close)(struct trace_iterator *iter);	void			(*pipe_close)(struct trace_iterator *iter);	ssize_t			(*read)(struct trace_iterator *iter,					struct file *filp, char __user *ubuf,					size_t cnt, loff_t *ppos);	ssize_t			(*splice_read)(struct trace_iterator *iter,					       struct file *filp,					       loff_t *ppos,					       struct pipe_inode_info *pipe,					       size_t len,					       unsigned int flags);#ifdef CONFIG_FTRACE_STARTUP_TEST	int			(*selftest)(struct tracer *trace,					    struct trace_array *tr);#endif	void			(*print_header)(struct seq_file *m);	enum print_line_t	(*print_line)(struct trace_iterator *iter);	/* If you handled the flag setting, return 0 */	int			(*set_flag)(struct trace_array *tr,					    u32 old_flags, u32 bit, int set);	/* Return 0 if OK with change, else return non-zero */	int			(*flag_changed)(struct trace_array *tr,						u32 mask, int set);	struct tracer		*next;	struct tracer_flags	*flags;	int			enabled;	int			ref;	bool			print_max;	bool			allow_instances;#ifdef CONFIG_TRACER_MAX_TRACE	bool			use_max_tr;#endif};  /* Only current can touch trace_recursion */ /* * For function tracing recursion: *  The order of these bits are important. * *  When function tracing occurs, the following steps are made: *   If arch does not support a ftrace feature: *    call internal function (uses INTERNAL bits) which calls... *   If callback is registered to the "global" list, the list *    function is called and recursion checks the GLOBAL bits. *    then this function calls... *   The function callback, which can use the FTRACE bits to *    check for recursion. * * Now if the arch does not suppport a feature, and it calls * the global list function which calls the ftrace callback * all three of these steps will do a recursion protection. * There's no reason to do one if the previous caller already * did. The recursion that we are protecting against will * go through the same steps again. * * To prevent the multiple recursion checks, if a recursion * bit is set that is higher than the MAX bit of the current * check, then we know that the check was made by the previous * caller, and we can skip the current check. */enum {	TRACE_BUFFER_BIT,	TRACE_BUFFER_NMI_BIT,	TRACE_BUFFER_IRQ_BIT,	TRACE_BUFFER_SIRQ_BIT, 	/* Start of function recursion bits */	TRACE_FTRACE_BIT,	TRACE_FTRACE_NMI_BIT,	TRACE_FTRACE_IRQ_BIT,	TRACE_FTRACE_SIRQ_BIT, 	/* INTERNAL_BITs must be greater than FTRACE_BITs */	TRACE_INTERNAL_BIT,	TRACE_INTERNAL_NMI_BIT,	TRACE_INTERNAL_IRQ_BIT,	TRACE_INTERNAL_SIRQ_BIT, 	TRACE_CONTROL_BIT, 	TRACE_BRANCH_BIT,/* * Abuse of the trace_recursion. * As we need a way to maintain state if we are tracing the function * graph in irq because we want to trace a particular function that * was called in irq context but we have irq tracing off. Since this * can only be modified by current, we can reuse trace_recursion. */	TRACE_IRQ_BIT,}; #define trace_recursion_set(bit)	do { (current)->trace_recursion |= (1<<(bit)); } while (0)#define trace_recursion_clear(bit)	do { (current)->trace_recursion &= ~(1<<(bit)); } while (0)#define trace_recursion_test(bit)	((current)->trace_recursion & (1<<(bit))) #define TRACE_CONTEXT_BITS	4 #define TRACE_FTRACE_START	TRACE_FTRACE_BIT#define TRACE_FTRACE_MAX	((1 << (TRACE_FTRACE_START + TRACE_CONTEXT_BITS)) - 1) #define TRACE_LIST_START	TRACE_INTERNAL_BIT#define TRACE_LIST_MAX		((1 << (TRACE_LIST_START + TRACE_CONTEXT_BITS)) - 1) #define TRACE_CONTEXT_MASK	TRACE_LIST_MAX static __always_inline int trace_get_context_bit(void){	int bit; 	if (in_interrupt()) {		if (in_nmi())			bit = 0; 		else if (in_irq())			bit = 1;		else			bit = 2;	} else		bit = 3; 	return bit;} static __always_inline int trace_test_and_set_recursion(int start, int max){	unsigned int val = current->trace_recursion;	int bit; 	/* A previous recursion check was made */	if ((val & TRACE_CONTEXT_MASK) > max)		return 0; 	bit = trace_get_context_bit() + start;	if (unlikely(val & (1 << bit)))

Lines 1–500 of 1321.