2008-05-12 23:20:42 +04:00
# ifndef _LINUX_KERNEL_TRACE_H
# define _LINUX_KERNEL_TRACE_H
# include <linux/fs.h>
# include <asm/atomic.h>
# include <linux/sched.h>
# include <linux/clocksource.h>
ftrace: mmiotrace, updates
here is a patch that makes mmiotrace work almost well within the tracing
framework. The patch applies on top of my previous patch. I have my own
output formatting in place now.
Summary of changes:
- fix the NULL dereference that was due to not calling tracing_reset()
- add print_line() callback into struct tracer
- implement print_line() for mmiotrace, producing up-to-spec text
- add my output header, but that is not really called in the right place
- rewrote the main structs in mmiotrace
- added two new trace entry types: TRACE_MMIO_RW and TRACE_MMIO_MAP
- made some functions in trace.c non-static
- check current==NULL in tracing_generic_entry_update()
- fix(?) comparison in trace_seq_printf()
Things seem to work fine except a few issues. Markers (text lines injected
into mmiotrace log) are missing, I did not feel hacking them in before we
have variable length entries. My output header is printed only for 'trace'
file, but not 'trace_pipe'. For some reason, despite my quick fix,
iter->trace is NULL in print_trace_line() when called from 'trace_pipe'
file, which means I don't get proper output formatting.
I only tried by loading nouveau.ko, which just detects the card, and that
is traced fine. I didn't try further. Map, two reads and unmap. Works
perfectly.
I am missing the information about overflows, I'd prefer to have a
counter for lost events. I didn't try, but I guess currently there is no
way of knowning when it overflows?
So, not too far from being fully operational, it seems :-)
And looking at the diffstat, there also is some 700-900 lines of user space
code that just became obsolete.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-05-12 23:20:57 +04:00
# include <linux/mmiotrace.h>
2008-05-12 23:20:42 +04:00
2008-05-23 23:37:28 +04:00
enum trace_type {
__TRACE_FIRST_TYPE = 0 ,
TRACE_FN ,
TRACE_CTX ,
TRACE_WAKE ,
2008-08-01 20:26:41 +04:00
TRACE_CONT ,
2008-05-23 23:37:28 +04:00
TRACE_STACK ,
2008-08-01 20:26:41 +04:00
TRACE_PRINT ,
2008-05-23 23:37:28 +04:00
TRACE_SPECIAL ,
ftrace: mmiotrace, updates
here is a patch that makes mmiotrace work almost well within the tracing
framework. The patch applies on top of my previous patch. I have my own
output formatting in place now.
Summary of changes:
- fix the NULL dereference that was due to not calling tracing_reset()
- add print_line() callback into struct tracer
- implement print_line() for mmiotrace, producing up-to-spec text
- add my output header, but that is not really called in the right place
- rewrote the main structs in mmiotrace
- added two new trace entry types: TRACE_MMIO_RW and TRACE_MMIO_MAP
- made some functions in trace.c non-static
- check current==NULL in tracing_generic_entry_update()
- fix(?) comparison in trace_seq_printf()
Things seem to work fine except a few issues. Markers (text lines injected
into mmiotrace log) are missing, I did not feel hacking them in before we
have variable length entries. My output header is printed only for 'trace'
file, but not 'trace_pipe'. For some reason, despite my quick fix,
iter->trace is NULL in print_trace_line() when called from 'trace_pipe'
file, which means I don't get proper output formatting.
I only tried by loading nouveau.ko, which just detects the card, and that
is traced fine. I didn't try further. Map, two reads and unmap. Works
perfectly.
I am missing the information about overflows, I'd prefer to have a
counter for lost events. I didn't try, but I guess currently there is no
way of knowning when it overflows?
So, not too far from being fully operational, it seems :-)
And looking at the diffstat, there also is some 700-900 lines of user space
code that just became obsolete.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-05-12 23:20:57 +04:00
TRACE_MMIO_RW ,
TRACE_MMIO_MAP ,
2008-05-23 23:37:28 +04:00
__TRACE_LAST_TYPE
} ;
2008-05-12 23:20:42 +04:00
/*
* Function trace entry - function address and parent function addres :
*/
struct ftrace_entry {
unsigned long ip ;
unsigned long parent_ip ;
} ;
/*
* Context switch trace entry - which task ( and prio ) we switched from / to :
*/
struct ctx_switch_entry {
unsigned int prev_pid ;
unsigned char prev_prio ;
unsigned char prev_state ;
unsigned int next_pid ;
unsigned char next_prio ;
2008-05-12 23:20:53 +04:00
unsigned char next_state ;
2008-09-04 12:24:16 +04:00
unsigned int next_cpu ;
2008-05-12 23:20:42 +04:00
} ;
2008-05-12 23:20:47 +04:00
/*
* Special ( free - form ) trace entry :
*/
struct special_entry {
unsigned long arg1 ;
unsigned long arg2 ;
unsigned long arg3 ;
} ;
2008-05-12 23:20:51 +04:00
/*
* Stack - trace entry :
*/
2008-05-12 23:21:15 +04:00
# define FTRACE_STACK_ENTRIES 8
2008-05-12 23:20:51 +04:00
struct stack_entry {
unsigned long caller [ FTRACE_STACK_ENTRIES ] ;
} ;
2008-08-01 20:26:41 +04:00
/*
* ftrace_printk entry :
*/
struct print_entry {
unsigned long ip ;
char buf [ ] ;
} ;
2008-09-16 23:02:27 +04:00
/*
* trace_flag_type is an enumeration that holds different
* states when a trace occurs . These are :
* IRQS_OFF - interrupts were disabled
* NEED_RESCED - reschedule is requested
* HARDIRQ - inside an interrupt handler
* SOFTIRQ - inside a softirq handler
* CONT - multiple entries hold the trace item
*/
enum trace_flag_type {
TRACE_FLAG_IRQS_OFF = 0x01 ,
TRACE_FLAG_NEED_RESCHED = 0x02 ,
TRACE_FLAG_HARDIRQ = 0x04 ,
TRACE_FLAG_SOFTIRQ = 0x08 ,
TRACE_FLAG_CONT = 0x10 ,
} ;
2008-05-12 23:20:42 +04:00
/*
2008-08-01 20:26:40 +04:00
* The trace field - the most basic unit of tracing . This is what
2008-05-12 23:20:42 +04:00
* is printed in the end as a single line in the trace output , such as :
*
* bash - 15816 [ 01 ] 235.197585 : idle_cpu < - irq_enter
*/
2008-08-01 20:26:40 +04:00
struct trace_field {
2008-05-12 23:20:42 +04:00
char cpu ;
char flags ;
char preempt_count ;
int pid ;
cycle_t t ;
union {
struct ftrace_entry fn ;
struct ctx_switch_entry ctx ;
2008-05-12 23:20:47 +04:00
struct special_entry special ;
2008-05-12 23:20:51 +04:00
struct stack_entry stack ;
2008-08-01 20:26:41 +04:00
struct print_entry print ;
ftrace: mmiotrace, updates
here is a patch that makes mmiotrace work almost well within the tracing
framework. The patch applies on top of my previous patch. I have my own
output formatting in place now.
Summary of changes:
- fix the NULL dereference that was due to not calling tracing_reset()
- add print_line() callback into struct tracer
- implement print_line() for mmiotrace, producing up-to-spec text
- add my output header, but that is not really called in the right place
- rewrote the main structs in mmiotrace
- added two new trace entry types: TRACE_MMIO_RW and TRACE_MMIO_MAP
- made some functions in trace.c non-static
- check current==NULL in tracing_generic_entry_update()
- fix(?) comparison in trace_seq_printf()
Things seem to work fine except a few issues. Markers (text lines injected
into mmiotrace log) are missing, I did not feel hacking them in before we
have variable length entries. My output header is printed only for 'trace'
file, but not 'trace_pipe'. For some reason, despite my quick fix,
iter->trace is NULL in print_trace_line() when called from 'trace_pipe'
file, which means I don't get proper output formatting.
I only tried by loading nouveau.ko, which just detects the card, and that
is traced fine. I didn't try further. Map, two reads and unmap. Works
perfectly.
I am missing the information about overflows, I'd prefer to have a
counter for lost events. I didn't try, but I guess currently there is no
way of knowning when it overflows?
So, not too far from being fully operational, it seems :-)
And looking at the diffstat, there also is some 700-900 lines of user space
code that just became obsolete.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-05-12 23:20:57 +04:00
struct mmiotrace_rw mmiorw ;
struct mmiotrace_map mmiomap ;
2008-05-12 23:20:42 +04:00
} ;
} ;
2008-08-01 20:26:40 +04:00
struct trace_field_cont {
char buf [ sizeof ( struct trace_field ) ] ;
} ;
struct trace_entry {
char type ;
union {
struct trace_field field ;
struct trace_field_cont cont ;
} ;
} ;
2008-05-12 23:20:42 +04:00
# define TRACE_ENTRY_SIZE sizeof(struct trace_entry)
2008-09-16 23:06:42 +04:00
# define TRACE_BUF_SIZE 1024
# define TRACE_PRINT_BUF_SIZE \
( sizeof ( struct trace_field ) - offsetof ( struct trace_field , print . buf ) )
# define TRACE_CONT_BUF_SIZE sizeof(struct trace_field)
2008-05-12 23:20:42 +04:00
/*
* 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 {
2008-05-12 23:20:43 +04:00
struct list_head trace_pages ;
2008-05-12 23:20:42 +04:00
atomic_t disabled ;
2008-05-12 23:20:55 +04:00
raw_spinlock_t lock ;
2008-05-12 23:20:46 +04:00
struct lock_class_key lock_key ;
2008-05-12 23:20:45 +04:00
2008-05-12 23:20:45 +04:00
/* these fields get copied into max-trace: */
2008-05-12 23:20:45 +04:00
unsigned trace_head_idx ;
unsigned trace_tail_idx ;
void * trace_head ; /* producer */
void * trace_tail ; /* consumer */
2008-05-12 23:20:45 +04:00
unsigned long trace_idx ;
2008-05-12 23:21:01 +04:00
unsigned long overrun ;
2008-05-12 23:20:42 +04:00
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 ;
cycle_t preempt_timestamp ;
pid_t pid ;
uid_t uid ;
char comm [ TASK_COMM_LEN ] ;
} ;
struct trace_iterator ;
/*
* 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 {
unsigned long entries ;
long ctrl ;
int cpu ;
cycle_t time_start ;
2008-05-12 23:20:46 +04:00
struct task_struct * waiter ;
2008-05-12 23:20:42 +04:00
struct trace_array_cpu * data [ NR_CPUS ] ;
} ;
/*
* A specific tracer , represented by methods that operate on a trace array :
*/
struct tracer {
const char * name ;
void ( * init ) ( struct trace_array * tr ) ;
void ( * reset ) ( struct trace_array * tr ) ;
void ( * open ) ( struct trace_iterator * iter ) ;
2008-05-12 23:21:01 +04:00
void ( * pipe_open ) ( struct trace_iterator * iter ) ;
2008-05-12 23:20:42 +04:00
void ( * close ) ( struct trace_iterator * iter ) ;
void ( * start ) ( struct trace_iterator * iter ) ;
void ( * stop ) ( struct trace_iterator * iter ) ;
2008-05-12 23:21:01 +04:00
ssize_t ( * read ) ( struct trace_iterator * iter ,
struct file * filp , char __user * ubuf ,
size_t cnt , loff_t * ppos ) ;
2008-05-12 23:20:42 +04:00
void ( * ctrl_update ) ( struct trace_array * tr ) ;
2008-05-12 23:20:44 +04:00
# ifdef CONFIG_FTRACE_STARTUP_TEST
int ( * selftest ) ( struct tracer * trace ,
struct trace_array * tr ) ;
# endif
2008-05-23 23:37:28 +04:00
int ( * print_line ) ( struct trace_iterator * iter ) ;
2008-05-12 23:20:42 +04:00
struct tracer * next ;
int print_max ;
} ;
2008-05-12 23:20:46 +04:00
struct trace_seq {
unsigned char buffer [ PAGE_SIZE ] ;
unsigned int len ;
2008-05-12 23:21:02 +04:00
unsigned int readpos ;
2008-05-12 23:20:46 +04:00
} ;
2008-05-12 23:20:42 +04:00
/*
* Trace iterator - used by printout routines who present trace
* results to users and which routines might sleep , etc :
*/
struct trace_iterator {
struct trace_array * tr ;
struct tracer * trace ;
2008-05-12 23:21:01 +04:00
void * private ;
2008-05-12 23:21:01 +04:00
long last_overrun [ NR_CPUS ] ;
long overrun [ NR_CPUS ] ;
2008-05-12 23:20:45 +04:00
2008-05-12 23:21:01 +04:00
/* The below is zeroed out in pipe_read */
struct trace_seq seq ;
2008-05-12 23:20:42 +04:00
struct trace_entry * ent ;
2008-05-12 23:20:45 +04:00
int cpu ;
struct trace_entry * prev_ent ;
int prev_cpu ;
2008-05-12 23:20:42 +04:00
unsigned long iter_flags ;
loff_t pos ;
unsigned long next_idx [ NR_CPUS ] ;
2008-05-12 23:20:43 +04:00
struct list_head * next_page [ NR_CPUS ] ;
unsigned next_page_idx [ NR_CPUS ] ;
long idx ;
2008-05-12 23:20:42 +04:00
} ;
2008-09-16 22:56:41 +04:00
void trace_wake_up ( void ) ;
2008-05-12 23:20:51 +04:00
void tracing_reset ( struct trace_array_cpu * data ) ;
2008-05-12 23:20:42 +04:00
int tracing_open_generic ( struct inode * inode , struct file * filp ) ;
struct dentry * tracing_init_dentry ( void ) ;
2008-05-12 23:20:49 +04:00
void init_tracer_sysprof_debugfs ( struct dentry * d_tracer ) ;
2008-09-16 22:56:41 +04:00
struct trace_entry * tracing_get_trace_entry ( struct trace_array * tr ,
struct trace_array_cpu * data ) ;
void tracing_generic_entry_update ( struct trace_entry * entry ,
unsigned long flags ) ;
2008-05-12 23:20:42 +04:00
void ftrace ( struct trace_array * tr ,
struct trace_array_cpu * data ,
unsigned long ip ,
unsigned long parent_ip ,
unsigned long flags ) ;
void tracing_sched_switch_trace ( struct trace_array * tr ,
struct trace_array_cpu * data ,
struct task_struct * prev ,
struct task_struct * next ,
unsigned long flags ) ;
void tracing_record_cmdline ( struct task_struct * tsk ) ;
2008-05-12 23:20:51 +04:00
void tracing_sched_wakeup_trace ( struct trace_array * tr ,
struct trace_array_cpu * data ,
struct task_struct * wakee ,
struct task_struct * cur ,
unsigned long flags ) ;
2008-05-12 23:20:47 +04:00
void trace_special ( struct trace_array * tr ,
struct trace_array_cpu * data ,
unsigned long arg1 ,
unsigned long arg2 ,
unsigned long arg3 ) ;
2008-05-12 23:20:49 +04:00
void trace_function ( struct trace_array * tr ,
struct trace_array_cpu * data ,
unsigned long ip ,
unsigned long parent_ip ,
unsigned long flags ) ;
2008-05-12 23:20:42 +04:00
2008-05-22 19:49:22 +04:00
void tracing_start_cmdline_record ( void ) ;
void tracing_stop_cmdline_record ( void ) ;
2008-05-12 23:20:42 +04:00
int register_tracer ( struct tracer * type ) ;
void unregister_tracer ( struct tracer * type ) ;
extern unsigned long nsecs_to_usecs ( unsigned long nsecs ) ;
extern unsigned long tracing_max_latency ;
extern unsigned long tracing_thresh ;
void update_max_tr ( struct trace_array * tr , struct task_struct * tsk , int cpu ) ;
void update_max_tr_single ( struct trace_array * tr ,
struct task_struct * tsk , int cpu ) ;
2008-05-12 23:20:51 +04:00
extern cycle_t ftrace_now ( int cpu ) ;
2008-05-12 23:20:42 +04:00
2008-07-11 04:58:10 +04:00
# ifdef CONFIG_FTRACE
void tracing_start_function_trace ( void ) ;
void tracing_stop_function_trace ( void ) ;
# else
# define tracing_start_function_trace() do { } while (0)
# define tracing_stop_function_trace() do { } while (0)
# endif
2008-05-12 23:20:42 +04:00
# ifdef CONFIG_CONTEXT_SWITCH_TRACER
typedef void
( * tracer_switch_func_t ) ( void * private ,
2008-05-12 23:21:10 +04:00
void * __rq ,
2008-05-12 23:20:42 +04:00
struct task_struct * prev ,
struct task_struct * next ) ;
struct tracer_switch_ops {
tracer_switch_func_t func ;
void * private ;
struct tracer_switch_ops * next ;
} ;
# endif /* CONFIG_CONTEXT_SWITCH_TRACER */
# ifdef CONFIG_DYNAMIC_FTRACE
extern unsigned long ftrace_update_tot_cnt ;
2008-05-12 23:20:54 +04:00
# define DYN_FTRACE_TEST_NAME trace_selftest_dynamic_test_func
extern int DYN_FTRACE_TEST_NAME ( void ) ;
2008-05-12 23:20:42 +04:00
# endif
2008-05-12 23:20:44 +04:00
# ifdef CONFIG_FTRACE_STARTUP_TEST
extern int trace_selftest_startup_function ( struct tracer * trace ,
struct trace_array * tr ) ;
extern int trace_selftest_startup_irqsoff ( struct tracer * trace ,
struct trace_array * tr ) ;
extern int trace_selftest_startup_preemptoff ( struct tracer * trace ,
struct trace_array * tr ) ;
extern int trace_selftest_startup_preemptirqsoff ( struct tracer * trace ,
struct trace_array * tr ) ;
extern int trace_selftest_startup_wakeup ( struct tracer * trace ,
struct trace_array * tr ) ;
2008-09-19 14:06:43 +04:00
extern int trace_selftest_startup_nop ( struct tracer * trace ,
struct trace_array * tr ) ;
2008-05-12 23:20:44 +04:00
extern int trace_selftest_startup_sched_switch ( struct tracer * trace ,
struct trace_array * tr ) ;
2008-05-12 23:20:47 +04:00
extern int trace_selftest_startup_sysprof ( struct tracer * trace ,
struct trace_array * tr ) ;
2008-05-12 23:20:44 +04:00
# endif /* CONFIG_FTRACE_STARTUP_TEST */
2008-05-12 23:20:45 +04:00
extern void * head_page ( struct trace_array_cpu * data ) ;
2008-05-23 23:37:28 +04:00
extern int trace_seq_printf ( struct trace_seq * s , const char * fmt , . . . ) ;
2008-09-16 23:02:27 +04:00
extern void trace_seq_print_cont ( struct trace_seq * s ,
struct trace_iterator * iter ) ;
2008-05-12 23:21:02 +04:00
extern ssize_t trace_seq_to_user ( struct trace_seq * s , char __user * ubuf ,
size_t cnt ) ;
2008-05-23 23:37:28 +04:00
extern long ns2usecs ( cycle_t nsec ) ;
2008-09-16 22:58:24 +04:00
extern int trace_vprintk ( unsigned long ip , const char * fmt , va_list args ) ;
2008-05-12 23:20:45 +04:00
2008-05-12 23:20:52 +04:00
extern unsigned long trace_flags ;
2008-05-12 23:21:00 +04:00
/*
* trace_iterator_flags is an enumeration that defines bit
* positions into trace_flags that controls the output .
*
* NOTE : These bits must match the trace_options array in
* trace . c .
*/
2008-05-12 23:20:52 +04:00
enum trace_iterator_flags {
TRACE_ITER_PRINT_PARENT = 0x01 ,
TRACE_ITER_SYM_OFFSET = 0x02 ,
TRACE_ITER_SYM_ADDR = 0x04 ,
TRACE_ITER_VERBOSE = 0x08 ,
TRACE_ITER_RAW = 0x10 ,
TRACE_ITER_HEX = 0x20 ,
TRACE_ITER_BIN = 0x40 ,
TRACE_ITER_BLOCK = 0x80 ,
TRACE_ITER_STACKTRACE = 0x100 ,
2008-05-12 23:20:52 +04:00
TRACE_ITER_SCHED_TREE = 0x200 ,
2008-09-04 12:24:14 +04:00
TRACE_ITER_PRINTK = 0x400 ,
2008-05-12 23:20:52 +04:00
} ;
2008-09-21 22:16:30 +04:00
extern struct tracer nop_trace ;
2008-05-12 23:20:42 +04:00
# endif /* _LINUX_KERNEL_TRACE_H */