2008-05-12 21:20:42 +02:00
|
|
|
#ifndef _LINUX_FTRACE_H
|
|
|
|
|
#define _LINUX_FTRACE_H
|
|
|
|
|
|
|
|
|
|
#include <linux/linkage.h>
|
2008-05-16 10:41:53 +02:00
|
|
|
#include <linux/fs.h>
|
2008-10-02 12:00:07 -07:00
|
|
|
#include <linux/ktime.h>
|
2008-09-23 11:32:08 +01:00
|
|
|
#include <linux/init.h>
|
|
|
|
|
#include <linux/types.h>
|
2008-12-09 13:14:27 -08:00
|
|
|
#include <linux/module.h>
|
2008-10-02 13:26:05 +02:00
|
|
|
#include <linux/kallsyms.h>
|
2008-12-03 15:36:57 -05:00
|
|
|
#include <linux/bitops.h>
|
2008-12-04 23:51:23 +01:00
|
|
|
#include <linux/sched.h>
|
2008-05-12 21:20:42 +02:00
|
|
|
|
2008-10-06 19:06:12 -04:00
|
|
|
#ifdef CONFIG_FUNCTION_TRACER
|
2008-10-02 17:45:47 +02:00
|
|
|
|
2008-05-12 21:20:43 +02:00
|
|
|
extern int ftrace_enabled;
|
|
|
|
|
extern int
|
|
|
|
|
ftrace_enable_sysctl(struct ctl_table *table, int write,
|
|
|
|
|
struct file *filp, void __user *buffer, size_t *lenp,
|
|
|
|
|
loff_t *ppos);
|
|
|
|
|
|
2008-05-12 21:20:42 +02:00
|
|
|
typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip);
|
|
|
|
|
|
|
|
|
|
struct ftrace_ops {
|
|
|
|
|
ftrace_func_t func;
|
|
|
|
|
struct ftrace_ops *next;
|
|
|
|
|
};
|
|
|
|
|
|
2008-11-05 16:05:44 -05:00
|
|
|
extern int function_trace_stop;
|
|
|
|
|
|
2008-11-16 06:02:06 +01:00
|
|
|
/*
|
|
|
|
|
* Type of the current tracing.
|
|
|
|
|
*/
|
|
|
|
|
enum ftrace_tracing_type_t {
|
|
|
|
|
FTRACE_TYPE_ENTER = 0, /* Hook the call of the function */
|
|
|
|
|
FTRACE_TYPE_RETURN, /* Hook the return of the function */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Current tracing type, default is FTRACE_TYPE_ENTER */
|
|
|
|
|
extern enum ftrace_tracing_type_t ftrace_tracing_type;
|
|
|
|
|
|
2008-11-05 16:05:44 -05:00
|
|
|
/**
|
|
|
|
|
* ftrace_stop - stop function tracer.
|
|
|
|
|
*
|
|
|
|
|
* A quick way to stop the function tracer. Note this an on off switch,
|
|
|
|
|
* it is not something that is recursive like preempt_disable.
|
|
|
|
|
* This does not disable the calling of mcount, it only stops the
|
|
|
|
|
* calling of functions from mcount.
|
|
|
|
|
*/
|
|
|
|
|
static inline void ftrace_stop(void)
|
|
|
|
|
{
|
|
|
|
|
function_trace_stop = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* ftrace_start - start the function tracer.
|
|
|
|
|
*
|
|
|
|
|
* This function is the inverse of ftrace_stop. This does not enable
|
|
|
|
|
* the function tracing if the function tracer is disabled. This only
|
|
|
|
|
* sets the function tracer flag to continue calling the functions
|
|
|
|
|
* from mcount.
|
|
|
|
|
*/
|
|
|
|
|
static inline void ftrace_start(void)
|
|
|
|
|
{
|
|
|
|
|
function_trace_stop = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-12 21:20:42 +02:00
|
|
|
/*
|
|
|
|
|
* The ftrace_ops must be a static and should also
|
|
|
|
|
* be read_mostly. These functions do modify read_mostly variables
|
|
|
|
|
* so use them sparely. Never free an ftrace_op or modify the
|
|
|
|
|
* next pointer after it has been registered. Even after unregistering
|
|
|
|
|
* it, the next pointer may still be used internally.
|
|
|
|
|
*/
|
|
|
|
|
int register_ftrace_function(struct ftrace_ops *ops);
|
|
|
|
|
int unregister_ftrace_function(struct ftrace_ops *ops);
|
|
|
|
|
void clear_ftrace_function(void);
|
|
|
|
|
|
|
|
|
|
extern void ftrace_stub(unsigned long a0, unsigned long a1);
|
|
|
|
|
|
2008-10-06 19:06:12 -04:00
|
|
|
#else /* !CONFIG_FUNCTION_TRACER */
|
2008-05-12 21:20:42 +02:00
|
|
|
# define register_ftrace_function(ops) do { } while (0)
|
|
|
|
|
# define unregister_ftrace_function(ops) do { } while (0)
|
|
|
|
|
# define clear_ftrace_function(ops) do { } while (0)
|
2008-10-23 09:33:02 -04:00
|
|
|
static inline void ftrace_kill(void) { }
|
2008-11-05 16:05:44 -05:00
|
|
|
static inline void ftrace_stop(void) { }
|
|
|
|
|
static inline void ftrace_start(void) { }
|
2008-10-06 19:06:12 -04:00
|
|
|
#endif /* CONFIG_FUNCTION_TRACER */
|
2008-05-12 21:20:42 +02:00
|
|
|
|
2008-12-16 23:06:40 -05:00
|
|
|
#ifdef CONFIG_STACK_TRACER
|
|
|
|
|
extern int stack_tracer_enabled;
|
|
|
|
|
int
|
|
|
|
|
stack_trace_sysctl(struct ctl_table *table, int write,
|
|
|
|
|
struct file *file, void __user *buffer, size_t *lenp,
|
|
|
|
|
loff_t *ppos);
|
|
|
|
|
#endif
|
|
|
|
|
|
2009-02-14 00:40:25 -05:00
|
|
|
struct ftrace_func_command {
|
|
|
|
|
struct list_head list;
|
|
|
|
|
char *name;
|
|
|
|
|
int (*func)(char *func, char *cmd,
|
|
|
|
|
char *params, int enable);
|
|
|
|
|
};
|
|
|
|
|
|
2008-05-12 21:20:42 +02:00
|
|
|
#ifdef CONFIG_DYNAMIC_FTRACE
|
2008-11-14 16:21:19 -08:00
|
|
|
/* asm/ftrace.h must be defined for archs supporting dynamic ftrace */
|
|
|
|
|
#include <asm/ftrace.h>
|
|
|
|
|
|
2009-02-16 23:06:01 -05:00
|
|
|
struct seq_file;
|
|
|
|
|
|
2009-02-14 15:29:06 -05:00
|
|
|
struct ftrace_hook_ops {
|
|
|
|
|
void (*func)(unsigned long ip,
|
|
|
|
|
unsigned long parent_ip,
|
|
|
|
|
void **data);
|
|
|
|
|
int (*callback)(unsigned long ip, void **data);
|
|
|
|
|
void (*free)(void **data);
|
2009-02-16 23:06:01 -05:00
|
|
|
int (*print)(struct seq_file *m,
|
|
|
|
|
unsigned long ip,
|
|
|
|
|
struct ftrace_hook_ops *ops,
|
|
|
|
|
void *data);
|
2009-02-14 15:29:06 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
extern int
|
|
|
|
|
register_ftrace_function_hook(char *glob, struct ftrace_hook_ops *ops,
|
|
|
|
|
void *data);
|
|
|
|
|
extern void
|
|
|
|
|
unregister_ftrace_function_hook(char *glob, struct ftrace_hook_ops *ops,
|
|
|
|
|
void *data);
|
|
|
|
|
extern void
|
|
|
|
|
unregister_ftrace_function_hook_func(char *glob, struct ftrace_hook_ops *ops);
|
|
|
|
|
extern void unregister_ftrace_function_hook_all(char *glob);
|
|
|
|
|
|
2008-05-12 21:20:43 +02:00
|
|
|
enum {
|
2008-05-12 21:20:48 +02:00
|
|
|
FTRACE_FL_FREE = (1 << 0),
|
|
|
|
|
FTRACE_FL_FAILED = (1 << 1),
|
|
|
|
|
FTRACE_FL_FILTER = (1 << 2),
|
|
|
|
|
FTRACE_FL_ENABLED = (1 << 3),
|
2008-05-22 11:46:33 -04:00
|
|
|
FTRACE_FL_NOTRACE = (1 << 4),
|
2008-06-01 21:47:30 +05:30
|
|
|
FTRACE_FL_CONVERTED = (1 << 5),
|
2008-06-21 23:47:53 +05:30
|
|
|
FTRACE_FL_FROZEN = (1 << 6),
|
2008-05-12 21:20:43 +02:00
|
|
|
};
|
|
|
|
|
|
2008-05-12 21:20:42 +02:00
|
|
|
struct dyn_ftrace {
|
2008-10-23 09:33:07 -04:00
|
|
|
struct list_head list;
|
|
|
|
|
unsigned long ip; /* address of mcount call-site */
|
|
|
|
|
unsigned long flags;
|
2008-11-14 16:21:19 -08:00
|
|
|
struct dyn_arch_ftrace arch;
|
2008-05-12 21:20:42 +02:00
|
|
|
};
|
|
|
|
|
|
2008-05-12 21:20:44 +02:00
|
|
|
int ftrace_force_update(void);
|
2008-05-12 21:20:45 +02:00
|
|
|
void ftrace_set_filter(unsigned char *buf, int len, int reset);
|
2008-05-12 21:20:44 +02:00
|
|
|
|
2009-02-14 00:40:25 -05:00
|
|
|
int register_ftrace_command(struct ftrace_func_command *cmd);
|
|
|
|
|
int unregister_ftrace_command(struct ftrace_func_command *cmd);
|
|
|
|
|
|
2008-05-12 21:20:42 +02:00
|
|
|
/* defined in arch */
|
2008-05-12 21:20:43 +02:00
|
|
|
extern int ftrace_ip_converted(unsigned long ip);
|
2008-05-12 21:20:43 +02:00
|
|
|
extern int ftrace_dyn_arch_init(void *data);
|
|
|
|
|
extern int ftrace_update_ftrace_func(ftrace_func_t func);
|
|
|
|
|
extern void ftrace_caller(void);
|
|
|
|
|
extern void ftrace_call(void);
|
|
|
|
|
extern void mcount_call(void);
|
2009-01-09 11:29:42 +08:00
|
|
|
|
|
|
|
|
#ifndef FTRACE_ADDR
|
|
|
|
|
#define FTRACE_ADDR ((unsigned long)ftrace_caller)
|
|
|
|
|
#endif
|
2008-11-25 21:07:04 +01:00
|
|
|
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
|
|
|
|
extern void ftrace_graph_caller(void);
|
2008-11-26 00:16:24 -05:00
|
|
|
extern int ftrace_enable_ftrace_graph_caller(void);
|
|
|
|
|
extern int ftrace_disable_ftrace_graph_caller(void);
|
|
|
|
|
#else
|
|
|
|
|
static inline int ftrace_enable_ftrace_graph_caller(void) { return 0; }
|
|
|
|
|
static inline int ftrace_disable_ftrace_graph_caller(void) { return 0; }
|
2008-11-16 06:02:06 +01:00
|
|
|
#endif
|
2008-05-27 20:48:37 -04:00
|
|
|
|
2008-10-23 09:32:59 -04:00
|
|
|
/**
|
2009-02-06 17:33:27 +08:00
|
|
|
* ftrace_make_nop - convert code into nop
|
2008-11-14 16:21:19 -08:00
|
|
|
* @mod: module structure if called by module load initialization
|
|
|
|
|
* @rec: the mcount call site record
|
|
|
|
|
* @addr: the address that the call site should be calling
|
2008-10-23 09:32:59 -04:00
|
|
|
*
|
|
|
|
|
* This is a very sensitive operation and great care needs
|
|
|
|
|
* to be taken by the arch. The operation should carefully
|
|
|
|
|
* read the location, check to see if what is read is indeed
|
|
|
|
|
* what we expect it to be, and then on success of the compare,
|
|
|
|
|
* it should write to the location.
|
|
|
|
|
*
|
2008-11-14 16:21:19 -08:00
|
|
|
* The code segment at @rec->ip should be a caller to @addr
|
|
|
|
|
*
|
2008-10-23 09:32:59 -04:00
|
|
|
* Return must be:
|
|
|
|
|
* 0 on success
|
|
|
|
|
* -EFAULT on error reading the location
|
|
|
|
|
* -EINVAL on a failed compare of the contents
|
|
|
|
|
* -EPERM on error writing to the location
|
|
|
|
|
* Any other value will be considered a failure.
|
|
|
|
|
*/
|
2008-11-14 16:21:19 -08:00
|
|
|
extern int ftrace_make_nop(struct module *mod,
|
|
|
|
|
struct dyn_ftrace *rec, unsigned long addr);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* ftrace_make_call - convert a nop call site into a call to addr
|
|
|
|
|
* @rec: the mcount call site record
|
|
|
|
|
* @addr: the address that the call site should call
|
|
|
|
|
*
|
|
|
|
|
* This is a very sensitive operation and great care needs
|
|
|
|
|
* to be taken by the arch. The operation should carefully
|
|
|
|
|
* read the location, check to see if what is read is indeed
|
|
|
|
|
* what we expect it to be, and then on success of the compare,
|
|
|
|
|
* it should write to the location.
|
|
|
|
|
*
|
|
|
|
|
* The code segment at @rec->ip should be a nop
|
|
|
|
|
*
|
|
|
|
|
* Return must be:
|
|
|
|
|
* 0 on success
|
|
|
|
|
* -EFAULT on error reading the location
|
|
|
|
|
* -EINVAL on a failed compare of the contents
|
|
|
|
|
* -EPERM on error writing to the location
|
|
|
|
|
* Any other value will be considered a failure.
|
|
|
|
|
*/
|
|
|
|
|
extern int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* May be defined in arch */
|
|
|
|
|
extern int ftrace_arch_read_dyn_info(char *buf, int size);
|
2008-10-23 09:32:59 -04:00
|
|
|
|
2008-06-21 23:47:53 +05:30
|
|
|
extern int skip_trace(unsigned long ip);
|
|
|
|
|
|
2008-09-06 01:06:03 -04:00
|
|
|
extern void ftrace_release(void *start, unsigned long size);
|
|
|
|
|
|
|
|
|
|
extern void ftrace_disable_daemon(void);
|
|
|
|
|
extern void ftrace_enable_daemon(void);
|
2008-05-12 21:20:44 +02:00
|
|
|
#else
|
2008-06-21 23:47:53 +05:30
|
|
|
# define skip_trace(ip) ({ 0; })
|
2008-05-12 21:20:49 +02:00
|
|
|
# define ftrace_force_update() ({ 0; })
|
|
|
|
|
# define ftrace_set_filter(buf, len, reset) do { } while (0)
|
2008-05-27 20:48:37 -04:00
|
|
|
# define ftrace_disable_daemon() do { } while (0)
|
|
|
|
|
# define ftrace_enable_daemon() do { } while (0)
|
2008-09-06 01:06:03 -04:00
|
|
|
static inline void ftrace_release(void *start, unsigned long size) { }
|
2009-02-14 00:40:25 -05:00
|
|
|
static inline int register_ftrace_command(struct ftrace_func_command *cmd)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
static inline int unregister_ftrace_command(char *cmd_name)
|
|
|
|
|
{
|
|
|
|
|
}
|
2008-06-21 23:47:53 +05:30
|
|
|
#endif /* CONFIG_DYNAMIC_FTRACE */
|
2008-05-12 21:20:42 +02:00
|
|
|
|
2008-05-12 21:20:49 +02:00
|
|
|
/* totally disable ftrace - can not re-enable after this */
|
|
|
|
|
void ftrace_kill(void);
|
|
|
|
|
|
2008-05-12 21:20:43 +02:00
|
|
|
static inline void tracer_disable(void)
|
|
|
|
|
{
|
2008-10-06 19:06:12 -04:00
|
|
|
#ifdef CONFIG_FUNCTION_TRACER
|
2008-05-12 21:20:43 +02:00
|
|
|
ftrace_enabled = 0;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-18 16:24:56 +08:00
|
|
|
/*
|
|
|
|
|
* Ftrace disable/restore without lock. Some synchronization mechanism
|
2008-08-15 00:40:25 -07:00
|
|
|
* must be used to prevent ftrace_enabled to be changed between
|
2008-08-18 16:24:56 +08:00
|
|
|
* disable/restore.
|
|
|
|
|
*/
|
2008-08-15 00:40:25 -07:00
|
|
|
static inline int __ftrace_enabled_save(void)
|
|
|
|
|
{
|
2008-10-06 19:06:12 -04:00
|
|
|
#ifdef CONFIG_FUNCTION_TRACER
|
2008-08-15 00:40:25 -07:00
|
|
|
int saved_ftrace_enabled = ftrace_enabled;
|
|
|
|
|
ftrace_enabled = 0;
|
|
|
|
|
return saved_ftrace_enabled;
|
|
|
|
|
#else
|
|
|
|
|
return 0;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void __ftrace_enabled_restore(int enabled)
|
|
|
|
|
{
|
2008-10-06 19:06:12 -04:00
|
|
|
#ifdef CONFIG_FUNCTION_TRACER
|
2008-08-15 00:40:25 -07:00
|
|
|
ftrace_enabled = enabled;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-12 21:20:42 +02:00
|
|
|
#ifdef CONFIG_FRAME_POINTER
|
|
|
|
|
/* TODO: need to fix this for ARM */
|
|
|
|
|
# define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
|
|
|
|
|
# define CALLER_ADDR1 ((unsigned long)__builtin_return_address(1))
|
|
|
|
|
# define CALLER_ADDR2 ((unsigned long)__builtin_return_address(2))
|
|
|
|
|
# define CALLER_ADDR3 ((unsigned long)__builtin_return_address(3))
|
|
|
|
|
# define CALLER_ADDR4 ((unsigned long)__builtin_return_address(4))
|
|
|
|
|
# define CALLER_ADDR5 ((unsigned long)__builtin_return_address(5))
|
2008-05-12 21:20:51 +02:00
|
|
|
# define CALLER_ADDR6 ((unsigned long)__builtin_return_address(6))
|
2008-05-12 21:20:42 +02:00
|
|
|
#else
|
|
|
|
|
# define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
|
|
|
|
|
# define CALLER_ADDR1 0UL
|
|
|
|
|
# define CALLER_ADDR2 0UL
|
|
|
|
|
# define CALLER_ADDR3 0UL
|
|
|
|
|
# define CALLER_ADDR4 0UL
|
|
|
|
|
# define CALLER_ADDR5 0UL
|
2008-05-12 21:20:51 +02:00
|
|
|
# define CALLER_ADDR6 0UL
|
2008-05-12 21:20:42 +02:00
|
|
|
#endif
|
|
|
|
|
|
2008-05-12 21:20:42 +02:00
|
|
|
#ifdef CONFIG_IRQSOFF_TRACER
|
2008-02-25 13:38:05 +01:00
|
|
|
extern void time_hardirqs_on(unsigned long a0, unsigned long a1);
|
|
|
|
|
extern void time_hardirqs_off(unsigned long a0, unsigned long a1);
|
2008-05-12 21:20:42 +02:00
|
|
|
#else
|
|
|
|
|
# define time_hardirqs_on(a0, a1) do { } while (0)
|
|
|
|
|
# define time_hardirqs_off(a0, a1) do { } while (0)
|
|
|
|
|
#endif
|
|
|
|
|
|
2008-05-12 21:20:42 +02:00
|
|
|
#ifdef CONFIG_PREEMPT_TRACER
|
2008-02-25 13:38:05 +01:00
|
|
|
extern void trace_preempt_on(unsigned long a0, unsigned long a1);
|
|
|
|
|
extern void trace_preempt_off(unsigned long a0, unsigned long a1);
|
2008-05-12 21:20:42 +02:00
|
|
|
#else
|
|
|
|
|
# define trace_preempt_on(a0, a1) do { } while (0)
|
|
|
|
|
# define trace_preempt_off(a0, a1) do { } while (0)
|
|
|
|
|
#endif
|
|
|
|
|
|
2008-05-28 01:22:08 +02:00
|
|
|
#ifdef CONFIG_TRACING
|
2008-10-23 19:26:08 -04:00
|
|
|
extern int ftrace_dump_on_oops;
|
|
|
|
|
|
2008-11-05 16:05:44 -05:00
|
|
|
extern void tracing_start(void);
|
|
|
|
|
extern void tracing_stop(void);
|
2008-11-21 12:59:38 -05:00
|
|
|
extern void ftrace_off_permanent(void);
|
2008-11-05 16:05:44 -05:00
|
|
|
|
2008-05-12 21:21:15 +02:00
|
|
|
extern void
|
|
|
|
|
ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3);
|
2008-08-01 16:45:49 -04:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* ftrace_printk - printf formatting in the ftrace buffer
|
|
|
|
|
* @fmt: the printf format for printing
|
|
|
|
|
*
|
|
|
|
|
* Note: __ftrace_printk is an internal function for ftrace_printk and
|
|
|
|
|
* the @ip is passed in via the ftrace_printk macro.
|
|
|
|
|
*
|
|
|
|
|
* This function allows a kernel developer to debug fast path sections
|
|
|
|
|
* that printk is not appropriate for. By scattering in various
|
|
|
|
|
* printk like tracing in the code, a developer can quickly see
|
|
|
|
|
* where problems are occurring.
|
|
|
|
|
*
|
|
|
|
|
* This is intended as a debugging tool for the developer only.
|
|
|
|
|
* Please refrain from leaving ftrace_printks scattered around in
|
|
|
|
|
* your code.
|
|
|
|
|
*/
|
|
|
|
|
# define ftrace_printk(fmt...) __ftrace_printk(_THIS_IP_, fmt)
|
2008-08-01 12:26:41 -04:00
|
|
|
extern int
|
|
|
|
|
__ftrace_printk(unsigned long ip, const char *fmt, ...)
|
|
|
|
|
__attribute__ ((format (printf, 2, 3)));
|
2009-01-23 12:06:23 -02:00
|
|
|
# define ftrace_vprintk(fmt, ap) __ftrace_printk(_THIS_IP_, fmt, ap)
|
|
|
|
|
extern int
|
|
|
|
|
__ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap);
|
2008-07-30 22:36:46 -04:00
|
|
|
extern void ftrace_dump(void);
|
2008-05-12 21:21:15 +02:00
|
|
|
#else
|
|
|
|
|
static inline void
|
|
|
|
|
ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3) { }
|
2008-08-01 12:26:41 -04:00
|
|
|
static inline int
|
2008-12-20 17:15:14 +08:00
|
|
|
ftrace_printk(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
|
2008-08-15 17:48:02 +02:00
|
|
|
|
2008-11-05 16:05:44 -05:00
|
|
|
static inline void tracing_start(void) { }
|
|
|
|
|
static inline void tracing_stop(void) { }
|
2008-11-21 12:59:38 -05:00
|
|
|
static inline void ftrace_off_permanent(void) { }
|
2008-08-15 17:48:02 +02:00
|
|
|
static inline int
|
|
|
|
|
ftrace_printk(const char *fmt, ...)
|
2008-08-01 12:26:41 -04:00
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2009-01-23 12:06:23 -02:00
|
|
|
static inline int
|
|
|
|
|
ftrace_vprintk(const char *fmt, va_list ap)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2008-07-30 22:36:46 -04:00
|
|
|
static inline void ftrace_dump(void) { }
|
2008-05-12 21:21:15 +02:00
|
|
|
#endif
|
|
|
|
|
|
2008-08-14 15:45:08 -04:00
|
|
|
#ifdef CONFIG_FTRACE_MCOUNT_RECORD
|
|
|
|
|
extern void ftrace_init(void);
|
2008-11-14 16:21:19 -08:00
|
|
|
extern void ftrace_init_module(struct module *mod,
|
|
|
|
|
unsigned long *start, unsigned long *end);
|
2008-08-14 15:45:08 -04:00
|
|
|
#else
|
|
|
|
|
static inline void ftrace_init(void) { }
|
2008-08-14 15:45:09 -04:00
|
|
|
static inline void
|
2008-11-14 16:21:19 -08:00
|
|
|
ftrace_init_module(struct module *mod,
|
|
|
|
|
unsigned long *start, unsigned long *end) { }
|
2008-08-14 15:45:08 -04:00
|
|
|
#endif
|
|
|
|
|
|
2008-11-26 00:57:25 +01:00
|
|
|
/*
|
|
|
|
|
* Structure that defines an entry function trace.
|
|
|
|
|
*/
|
|
|
|
|
struct ftrace_graph_ent {
|
|
|
|
|
unsigned long func; /* Current function */
|
|
|
|
|
int depth;
|
|
|
|
|
};
|
2008-08-01 12:26:41 -04:00
|
|
|
|
2008-11-11 07:03:45 +01:00
|
|
|
/*
|
|
|
|
|
* Structure that defines a return function trace.
|
|
|
|
|
*/
|
2008-11-25 21:07:04 +01:00
|
|
|
struct ftrace_graph_ret {
|
2008-11-11 07:03:45 +01:00
|
|
|
unsigned long func; /* Current function */
|
|
|
|
|
unsigned long long calltime;
|
|
|
|
|
unsigned long long rettime;
|
2008-11-17 03:22:41 +01:00
|
|
|
/* Number of functions that overran the depth limit for current task */
|
|
|
|
|
unsigned long overrun;
|
2008-11-26 00:57:25 +01:00
|
|
|
int depth;
|
2008-11-11 07:03:45 +01:00
|
|
|
};
|
|
|
|
|
|
2008-11-25 21:07:04 +01:00
|
|
|
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
2008-12-06 03:40:00 +01:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Sometimes we don't want to trace a function with the function
|
|
|
|
|
* graph tracer but we want them to keep traced by the usual function
|
|
|
|
|
* tracer if the function graph tracer is not configured.
|
|
|
|
|
*/
|
|
|
|
|
#define __notrace_funcgraph notrace
|
|
|
|
|
|
2008-12-09 23:54:20 +01:00
|
|
|
/*
|
|
|
|
|
* We want to which function is an entrypoint of a hardirq.
|
|
|
|
|
* That will help us to put a signal on output.
|
|
|
|
|
*/
|
|
|
|
|
#define __irq_entry __attribute__((__section__(".irqentry.text")))
|
|
|
|
|
|
|
|
|
|
/* Limits of hardirq entrypoints */
|
|
|
|
|
extern char __irqentry_text_start[];
|
|
|
|
|
extern char __irqentry_text_end[];
|
|
|
|
|
|
2008-11-23 06:22:56 +01:00
|
|
|
#define FTRACE_RETFUNC_DEPTH 50
|
|
|
|
|
#define FTRACE_RETSTACK_ALLOC_SIZE 32
|
2008-11-26 00:57:25 +01:00
|
|
|
/* Type of the callback handlers for tracing function graph*/
|
|
|
|
|
typedef void (*trace_func_graph_ret_t)(struct ftrace_graph_ret *); /* return */
|
2008-12-02 23:50:05 -05:00
|
|
|
typedef int (*trace_func_graph_ent_t)(struct ftrace_graph_ent *); /* entry */
|
2008-11-11 07:03:45 +01:00
|
|
|
|
2008-11-26 00:57:25 +01:00
|
|
|
extern int register_ftrace_graph(trace_func_graph_ret_t retfunc,
|
|
|
|
|
trace_func_graph_ent_t entryfunc);
|
2008-11-23 06:22:56 +01:00
|
|
|
|
2008-12-02 23:50:02 -05:00
|
|
|
extern void ftrace_graph_stop(void);
|
|
|
|
|
|
2008-11-26 00:57:25 +01:00
|
|
|
/* The current handlers in use */
|
|
|
|
|
extern trace_func_graph_ret_t ftrace_graph_return;
|
|
|
|
|
extern trace_func_graph_ent_t ftrace_graph_entry;
|
2008-11-11 07:03:45 +01:00
|
|
|
|
2008-11-25 21:07:04 +01:00
|
|
|
extern void unregister_ftrace_graph(void);
|
2008-11-23 06:22:56 +01:00
|
|
|
|
2008-11-25 21:07:04 +01:00
|
|
|
extern void ftrace_graph_init_task(struct task_struct *t);
|
|
|
|
|
extern void ftrace_graph_exit_task(struct task_struct *t);
|
2008-12-04 23:51:23 +01:00
|
|
|
|
|
|
|
|
static inline int task_curr_ret_stack(struct task_struct *t)
|
|
|
|
|
{
|
|
|
|
|
return t->curr_ret_stack;
|
|
|
|
|
}
|
2008-12-06 03:43:41 +01:00
|
|
|
|
|
|
|
|
static inline void pause_graph_tracing(void)
|
|
|
|
|
{
|
|
|
|
|
atomic_inc(¤t->tracing_graph_pause);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void unpause_graph_tracing(void)
|
|
|
|
|
{
|
|
|
|
|
atomic_dec(¤t->tracing_graph_pause);
|
|
|
|
|
}
|
2008-11-23 09:18:56 +01:00
|
|
|
#else
|
2008-12-06 03:40:00 +01:00
|
|
|
|
|
|
|
|
#define __notrace_funcgraph
|
2008-12-09 23:54:20 +01:00
|
|
|
#define __irq_entry
|
2008-12-06 03:40:00 +01:00
|
|
|
|
2008-11-25 21:07:04 +01:00
|
|
|
static inline void ftrace_graph_init_task(struct task_struct *t) { }
|
|
|
|
|
static inline void ftrace_graph_exit_task(struct task_struct *t) { }
|
2008-12-04 23:51:23 +01:00
|
|
|
|
|
|
|
|
static inline int task_curr_ret_stack(struct task_struct *tsk)
|
|
|
|
|
{
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2008-12-06 03:43:41 +01:00
|
|
|
|
|
|
|
|
static inline void pause_graph_tracing(void) { }
|
|
|
|
|
static inline void unpause_graph_tracing(void) { }
|
2008-11-11 07:03:45 +01:00
|
|
|
#endif
|
|
|
|
|
|
2008-12-03 15:36:57 -05:00
|
|
|
#ifdef CONFIG_TRACING
|
|
|
|
|
#include <linux/sched.h>
|
|
|
|
|
|
|
|
|
|
/* flags for current->trace */
|
|
|
|
|
enum {
|
|
|
|
|
TSK_TRACE_FL_TRACE_BIT = 0,
|
|
|
|
|
TSK_TRACE_FL_GRAPH_BIT = 1,
|
|
|
|
|
};
|
|
|
|
|
enum {
|
|
|
|
|
TSK_TRACE_FL_TRACE = 1 << TSK_TRACE_FL_TRACE_BIT,
|
|
|
|
|
TSK_TRACE_FL_GRAPH = 1 << TSK_TRACE_FL_GRAPH_BIT,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static inline void set_tsk_trace_trace(struct task_struct *tsk)
|
|
|
|
|
{
|
|
|
|
|
set_bit(TSK_TRACE_FL_TRACE_BIT, &tsk->trace);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void clear_tsk_trace_trace(struct task_struct *tsk)
|
|
|
|
|
{
|
|
|
|
|
clear_bit(TSK_TRACE_FL_TRACE_BIT, &tsk->trace);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline int test_tsk_trace_trace(struct task_struct *tsk)
|
|
|
|
|
{
|
|
|
|
|
return tsk->trace & TSK_TRACE_FL_TRACE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void set_tsk_trace_graph(struct task_struct *tsk)
|
|
|
|
|
{
|
|
|
|
|
set_bit(TSK_TRACE_FL_GRAPH_BIT, &tsk->trace);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void clear_tsk_trace_graph(struct task_struct *tsk)
|
|
|
|
|
{
|
|
|
|
|
clear_bit(TSK_TRACE_FL_GRAPH_BIT, &tsk->trace);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline int test_tsk_trace_graph(struct task_struct *tsk)
|
|
|
|
|
{
|
|
|
|
|
return tsk->trace & TSK_TRACE_FL_GRAPH;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif /* CONFIG_TRACING */
|
|
|
|
|
|
2009-01-19 10:31:01 +01:00
|
|
|
|
|
|
|
|
#ifdef CONFIG_HW_BRANCH_TRACER
|
|
|
|
|
|
|
|
|
|
void trace_hw_branch(u64 from, u64 to);
|
|
|
|
|
void trace_hw_branch_oops(void);
|
|
|
|
|
|
|
|
|
|
#else /* CONFIG_HW_BRANCH_TRACER */
|
|
|
|
|
|
|
|
|
|
static inline void trace_hw_branch(u64 from, u64 to) {}
|
|
|
|
|
static inline void trace_hw_branch_oops(void) {}
|
|
|
|
|
|
|
|
|
|
#endif /* CONFIG_HW_BRANCH_TRACER */
|
|
|
|
|
|
2008-05-12 21:20:42 +02:00
|
|
|
#endif /* _LINUX_FTRACE_H */
|