2229 lines · 71.1 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0 #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/trace.h>#include <linux/hw_breakpoint.h>#include <linux/trace_seq.h>#include <linux/trace_events.h>#include <linux/compiler.h>#include <linux/glob.h>#include <linux/irq_work.h>#include <linux/workqueue.h>#include <linux/ctype.h>#include <linux/once_lite.h>#include <linux/ftrace_regs.h> #include "pid_list.h" #ifdef CONFIG_FTRACE_SYSCALLS#include <asm/unistd.h>		/* For NR_syscalls	     */#include <asm/syscall.h>	/* some archs define it here */#endif #define TRACE_MODE_WRITE	0640#define TRACE_MODE_READ		0440 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_GRAPH_RETADDR_ENT,	TRACE_USER_STACK,	TRACE_BLK,	TRACE_BPUTS,	TRACE_HWLAT,	TRACE_OSNOISE,	TRACE_TIMERLAT,	TRACE_RAW_DATA,	TRACE_FUNC_REPEATS, 	__TRACE_LAST_TYPE,};  #undef __field#define __field(type, item)		type	item; #undef __field_fn#define __field_fn(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 __field_packed#define __field_packed(type, container, item) #undef __array#define __array(type, item, size)	type	item[size]; /* * For backward compatibility, older user space expects to see the * kernel_stack event with a fixed size caller field. But today the fix * size is ignored by the kernel, and the real structure is dynamic. * Expose to user space: "unsigned long caller[8];" but the real structure * will be "unsigned long caller[] __counted_by(size)" */#undef __stack_array#define __stack_array(type, item, size, field)		type item[] __counted_by(field); #undef __array_desc#define __array_desc(type, container, item, size) #undef __dynamic_array#define __dynamic_array(type, item)	type	item[]; #undef __rel_dynamic_array#define __rel_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)		\	struct struct_name {						\		struct trace_entry	ent;				\		tstruct							\	} #undef FTRACE_ENTRY_DUP#define FTRACE_ENTRY_DUP(name, name_struct, id, tstruct, printk) #undef FTRACE_ENTRY_REG#define FTRACE_ENTRY_REG(name, struct_name, id, tstruct, print,	regfn)	\	FTRACE_ENTRY(name, struct_name, id, PARAMS(tstruct), PARAMS(print)) #undef FTRACE_ENTRY_PACKED#define FTRACE_ENTRY_PACKED(name, struct_name, id, tstruct, print)	\	FTRACE_ENTRY(name, struct_name, id, PARAMS(tstruct), PARAMS(print)) __packed #include "trace_entries.h" /* Use this for memory failure errors */#define MEM_FAIL(condition, fmt, ...)					\	DO_ONCE_LITE_IF(condition, pr_err, "ERROR: " fmt, ##__VA_ARGS__) #define FAULT_STRING "(fault)" #define HIST_STACKTRACE_DEPTH	16#define HIST_STACKTRACE_SIZE	(HIST_STACKTRACE_DEPTH * sizeof(unsigned long))#define HIST_STACKTRACE_SKIP	5 /* * 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 eprobe_trace_entry_head {	struct trace_entry	ent;}; struct kretprobe_trace_entry_head {	struct trace_entry	ent;	unsigned long		func;	unsigned long		ret_ip;}; struct fentry_trace_entry_head {	struct trace_entry	ent;	unsigned long		ip;}; struct fexit_trace_entry_head {	struct trace_entry	ent;	unsigned long		func;	unsigned long		ret_ip;}; #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;	u64			preempt_timestamp;	pid_t			pid;	kuid_t			uid;	char			comm[TASK_COMM_LEN]; #ifdef CONFIG_FUNCTION_TRACER	int			ftrace_ignore_pid;#endif	bool			ignore_pid;}; struct tracer;struct trace_option_dentry; struct array_buffer {	struct trace_array		*tr;	struct trace_buffer		*buffer;	struct trace_array_cpu __percpu	*data;	u64				time_start;	int				cpu;}; #define TRACE_FLAGS_MAX_SIZE		32 struct trace_options {	struct tracer			*tracer;	struct trace_option_dentry	*topts;}; struct trace_pid_list *trace_pid_list_alloc(void);void trace_pid_list_free(struct trace_pid_list *pid_list);bool trace_pid_list_is_set(struct trace_pid_list *pid_list, unsigned int pid);int trace_pid_list_set(struct trace_pid_list *pid_list, unsigned int pid);int trace_pid_list_clear(struct trace_pid_list *pid_list, unsigned int pid);int trace_pid_list_first(struct trace_pid_list *pid_list, unsigned int *pid);int trace_pid_list_next(struct trace_pid_list *pid_list, unsigned int pid,			unsigned int *next); enum {	TRACE_PIDS		= BIT(0),	TRACE_NO_PIDS		= BIT(1),}; static inline bool pid_type_enabled(int type, struct trace_pid_list *pid_list,				    struct trace_pid_list *no_pid_list){	/* Return true if the pid list in type has pids */	return ((type & TRACE_PIDS) && pid_list) ||		((type & TRACE_NO_PIDS) && no_pid_list);} static inline bool still_need_pid_events(int type, struct trace_pid_list *pid_list,					 struct trace_pid_list *no_pid_list){	/*	 * Turning off what is in @type, return true if the "other"	 * pid list, still has pids in it.	 */	return (!(type & TRACE_PIDS) && pid_list) ||		(!(type & TRACE_NO_PIDS) && no_pid_list);} typedef bool (*cond_update_fn_t)(struct trace_array *tr, void *cond_data); /** * struct cond_snapshot - conditional snapshot data and callback * * The cond_snapshot structure encapsulates a callback function and * data associated with the snapshot for a given tracing instance. * * When a snapshot is taken conditionally, by invoking * tracing_snapshot_cond(tr, cond_data), the cond_data passed in is * passed in turn to the cond_snapshot.update() function.  That data * can be compared by the update() implementation with the cond_data * contained within the struct cond_snapshot instance associated with * the trace_array.  Because the tr->max_lock is held throughout the * update() call, the update() function can directly retrieve the * cond_snapshot and cond_data associated with the per-instance * snapshot associated with the trace_array. * * The cond_snapshot.update() implementation can save data to be * associated with the snapshot if it decides to, and returns 'true' * in that case, or it returns 'false' if the conditional snapshot * shouldn't be taken. * * The cond_snapshot instance is created and associated with the * user-defined cond_data by tracing_cond_snapshot_enable(). * Likewise, the cond_snapshot instance is destroyed and is no longer * associated with the trace instance by * tracing_cond_snapshot_disable(). * * The method below is required. * * @update: When a conditional snapshot is invoked, the update() *	callback function is invoked with the tr->max_lock held.  The *	update() implementation signals whether or not to actually *	take the snapshot, by returning 'true' if so, 'false' if no *	snapshot should be taken.  Because the max_lock is held for *	the duration of update(), the implementation is safe to *	directly retrieved and save any implementation data it needs *	to in association with the snapshot. */struct cond_snapshot {	void				*cond_data;	cond_update_fn_t		update;}; /* * struct trace_func_repeats - used to keep track of the consecutive * (on the same CPU) calls of a single function. */struct trace_func_repeats {	unsigned long	ip;	unsigned long	parent_ip;	unsigned long	count;	u64		ts_last_call;}; struct trace_module_delta {	struct rcu_head	rcu;	long		delta[];}; /* * 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 array_buffer	array_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 array_buffer	 * When a snapshot is taken, the buffer of the max_buffer is swapped	 * with the buffer of the array_buffer and the buffers are reset for	 * the array_buffer so the tracing can continue.	 */	struct array_buffer	max_buffer;	bool			allocated_snapshot;	spinlock_t		snapshot_trigger_lock;	unsigned int		snapshot;	unsigned long		max_latency;#ifdef CONFIG_FSNOTIFY	struct dentry		*d_max_latency;	struct work_struct	fsnotify_work;	struct irq_work		fsnotify_irqwork;#endif#endif	/* The below is for memory mapped ring buffer */	unsigned int		mapped;	unsigned long		range_addr_start;	unsigned long		range_addr_size;	char			*range_name;	long			text_delta;	struct trace_module_delta *module_delta;	void			*scratch; /* pointer in persistent memory */	int			scratch_size; 	int			buffer_disabled; 	struct trace_pid_list	__rcu *filtered_pids;	struct trace_pid_list	__rcu *filtered_no_pids;	/*	 * 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;#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;	int			nr_topts;	bool			clear_trace;	int			buffer_percent;	unsigned int		n_err_log_entries;	struct tracer		*current_trace;	unsigned int		trace_flags;	unsigned char		trace_flags_index[TRACE_FLAGS_MAX_SIZE];	unsigned int		flags;	raw_spinlock_t		start_lock;	const char		*system_names;	struct list_head	err_log;	struct dentry		*dir;	struct dentry		*options;	struct dentry		*percpu_dir;	struct eventfs_inode	*event_dir;	struct trace_options	*topts;	struct list_head	systems;	struct list_head	events;	struct trace_event_file *trace_marker_file;	cpumask_var_t		tracing_cpumask; /* only trace on set CPUs */	/* one per_cpu trace_pipe can be opened by only one user */	cpumask_var_t		pipe_cpumask;	int			ref;	int			trace_ref;#ifdef CONFIG_MODULES	struct list_head	mod_events;#endif#ifdef CONFIG_FUNCTION_TRACER	struct ftrace_ops	*ops;	struct trace_pid_list	__rcu *function_pids;	struct trace_pid_list	__rcu *function_no_pids;#ifdef CONFIG_FUNCTION_GRAPH_TRACER	struct fgraph_ops	*gops;#endif#ifdef CONFIG_DYNAMIC_FTRACE	/* All of these are protected by the ftrace_lock */	struct list_head	func_probes;	struct list_head	mod_trace;	struct list_head	mod_notrace;#endif	/* function tracing enabled */	int			function_enabled;#endif	int			no_filter_buffering_ref;	struct list_head	hist_vars;#ifdef CONFIG_TRACER_SNAPSHOT	struct cond_snapshot	*cond_snapshot;#endif	struct trace_func_repeats	__percpu *last_func_repeats;	/*	 * On boot up, the ring buffer is set to the minimum size, so that	 * we do not waste memory on systems that are not using tracing.	 */	bool ring_buffer_expanded;}; enum {	TRACE_ARRAY_FL_GLOBAL		= BIT(0),	TRACE_ARRAY_FL_BOOT		= BIT(1),	TRACE_ARRAY_FL_LAST_BOOT	= BIT(2),	TRACE_ARRAY_FL_MOD_INIT		= BIT(3),	TRACE_ARRAY_FL_MEMMAP		= BIT(4),}; #ifdef CONFIG_MODULESbool module_exists(const char *module);#elsestatic inline bool module_exists(const char *module){	return false;}#endif extern struct list_head ftrace_trace_arrays; extern struct mutex trace_types_lock; extern int trace_array_get(struct trace_array *tr);extern int tracing_check_open_get_tr(struct trace_array *tr);extern struct trace_array *trace_array_find(const char *instance);extern struct trace_array *trace_array_find_get(const char *instance); extern u64 tracing_event_time_stamp(struct trace_buffer *buffer, struct ring_buffer_event *rbe);extern int tracing_set_filter_buffering(struct trace_array *tr, bool set);extern int tracing_set_clock(struct trace_array *tr, const char *clockstr); extern bool trace_clock_in_ns(struct trace_array *tr); extern unsigned long trace_adjust_address(struct trace_array *tr, unsigned long addr); /* * 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)			\

Lines 1–500 of 2229.