diff options
author | Steven Rostedt <srostedt@redhat.com> | 2008-11-14 19:21:19 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-11-16 01:36:02 -0500 |
commit | 31e889098a80ceb3e9e3c555d522b2686a6663c6 (patch) | |
tree | 2acb73507de4191d4a9aa5ccf08fa24e7044c89e /include/linux/ftrace.h | |
parent | d51ad7ac48f991c4a8834485727efa99a691cb87 (diff) |
ftrace: pass module struct to arch dynamic ftrace functions
Impact: allow archs more flexibility on dynamic ftrace implementations
Dynamic ftrace has largly been developed on x86. Since x86 does not
have the same limitations as other architectures, the ftrace interaction
between the generic code and the architecture specific code was not
flexible enough to handle some of the issues that other architectures
have.
Most notably, module trampolines. Due to the limited branch distance
that archs make in calling kernel core code from modules, the module
load code must create a trampoline to jump to what will make the
larger jump into core kernel code.
The problem arises when this happens to a call to mcount. Ftrace checks
all code before modifying it and makes sure the current code is what
it expects. Right now, there is not enough information to handle modifying
module trampolines.
This patch changes the API between generic dynamic ftrace code and
the arch dependent code. There is now two functions for modifying code:
ftrace_make_nop(mod, rec, addr) - convert the code at rec->ip into
a nop, where the original text is calling addr. (mod is the
module struct if called by module init)
ftrace_make_caller(rec, addr) - convert the code rec->ip that should
be a nop into a caller to addr.
The record "rec" now has a new field called "arch" where the architecture
can add any special attributes to each call site record.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'include/linux/ftrace.h')
-rw-r--r-- | include/linux/ftrace.h | 53 |
1 files changed, 41 insertions, 12 deletions
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 4fbc4a8b86a5..166a2070ef65 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h | |||
@@ -74,6 +74,9 @@ static inline void ftrace_start(void) { } | |||
74 | #endif /* CONFIG_FUNCTION_TRACER */ | 74 | #endif /* CONFIG_FUNCTION_TRACER */ |
75 | 75 | ||
76 | #ifdef CONFIG_DYNAMIC_FTRACE | 76 | #ifdef CONFIG_DYNAMIC_FTRACE |
77 | /* asm/ftrace.h must be defined for archs supporting dynamic ftrace */ | ||
78 | #include <asm/ftrace.h> | ||
79 | |||
77 | enum { | 80 | enum { |
78 | FTRACE_FL_FREE = (1 << 0), | 81 | FTRACE_FL_FREE = (1 << 0), |
79 | FTRACE_FL_FAILED = (1 << 1), | 82 | FTRACE_FL_FAILED = (1 << 1), |
@@ -88,6 +91,7 @@ struct dyn_ftrace { | |||
88 | struct list_head list; | 91 | struct list_head list; |
89 | unsigned long ip; /* address of mcount call-site */ | 92 | unsigned long ip; /* address of mcount call-site */ |
90 | unsigned long flags; | 93 | unsigned long flags; |
94 | struct dyn_arch_ftrace arch; | ||
91 | }; | 95 | }; |
92 | 96 | ||
93 | int ftrace_force_update(void); | 97 | int ftrace_force_update(void); |
@@ -95,22 +99,40 @@ void ftrace_set_filter(unsigned char *buf, int len, int reset); | |||
95 | 99 | ||
96 | /* defined in arch */ | 100 | /* defined in arch */ |
97 | extern int ftrace_ip_converted(unsigned long ip); | 101 | extern int ftrace_ip_converted(unsigned long ip); |
98 | extern unsigned char *ftrace_nop_replace(void); | ||
99 | extern unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr); | ||
100 | extern int ftrace_dyn_arch_init(void *data); | 102 | extern int ftrace_dyn_arch_init(void *data); |
101 | extern int ftrace_update_ftrace_func(ftrace_func_t func); | 103 | extern int ftrace_update_ftrace_func(ftrace_func_t func); |
102 | extern void ftrace_caller(void); | 104 | extern void ftrace_caller(void); |
103 | extern void ftrace_call(void); | 105 | extern void ftrace_call(void); |
104 | extern void mcount_call(void); | 106 | extern void mcount_call(void); |
105 | 107 | ||
106 | /* May be defined in arch */ | 108 | /** |
107 | extern int ftrace_arch_read_dyn_info(char *buf, int size); | 109 | * ftrace_make_nop - convert code into top |
110 | * @mod: module structure if called by module load initialization | ||
111 | * @rec: the mcount call site record | ||
112 | * @addr: the address that the call site should be calling | ||
113 | * | ||
114 | * This is a very sensitive operation and great care needs | ||
115 | * to be taken by the arch. The operation should carefully | ||
116 | * read the location, check to see if what is read is indeed | ||
117 | * what we expect it to be, and then on success of the compare, | ||
118 | * it should write to the location. | ||
119 | * | ||
120 | * The code segment at @rec->ip should be a caller to @addr | ||
121 | * | ||
122 | * Return must be: | ||
123 | * 0 on success | ||
124 | * -EFAULT on error reading the location | ||
125 | * -EINVAL on a failed compare of the contents | ||
126 | * -EPERM on error writing to the location | ||
127 | * Any other value will be considered a failure. | ||
128 | */ | ||
129 | extern int ftrace_make_nop(struct module *mod, | ||
130 | struct dyn_ftrace *rec, unsigned long addr); | ||
108 | 131 | ||
109 | /** | 132 | /** |
110 | * ftrace_modify_code - modify code segment | 133 | * ftrace_make_call - convert a nop call site into a call to addr |
111 | * @ip: the address of the code segment | 134 | * @rec: the mcount call site record |
112 | * @old_code: the contents of what is expected to be there | 135 | * @addr: the address that the call site should call |
113 | * @new_code: the code to patch in | ||
114 | * | 136 | * |
115 | * This is a very sensitive operation and great care needs | 137 | * This is a very sensitive operation and great care needs |
116 | * to be taken by the arch. The operation should carefully | 138 | * to be taken by the arch. The operation should carefully |
@@ -118,6 +140,8 @@ extern int ftrace_arch_read_dyn_info(char *buf, int size); | |||
118 | * what we expect it to be, and then on success of the compare, | 140 | * what we expect it to be, and then on success of the compare, |
119 | * it should write to the location. | 141 | * it should write to the location. |
120 | * | 142 | * |
143 | * The code segment at @rec->ip should be a nop | ||
144 | * | ||
121 | * Return must be: | 145 | * Return must be: |
122 | * 0 on success | 146 | * 0 on success |
123 | * -EFAULT on error reading the location | 147 | * -EFAULT on error reading the location |
@@ -125,8 +149,11 @@ extern int ftrace_arch_read_dyn_info(char *buf, int size); | |||
125 | * -EPERM on error writing to the location | 149 | * -EPERM on error writing to the location |
126 | * Any other value will be considered a failure. | 150 | * Any other value will be considered a failure. |
127 | */ | 151 | */ |
128 | extern int ftrace_modify_code(unsigned long ip, unsigned char *old_code, | 152 | extern int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr); |
129 | unsigned char *new_code); | 153 | |
154 | |||
155 | /* May be defined in arch */ | ||
156 | extern int ftrace_arch_read_dyn_info(char *buf, int size); | ||
130 | 157 | ||
131 | extern int skip_trace(unsigned long ip); | 158 | extern int skip_trace(unsigned long ip); |
132 | 159 | ||
@@ -259,11 +286,13 @@ static inline void ftrace_dump(void) { } | |||
259 | 286 | ||
260 | #ifdef CONFIG_FTRACE_MCOUNT_RECORD | 287 | #ifdef CONFIG_FTRACE_MCOUNT_RECORD |
261 | extern void ftrace_init(void); | 288 | extern void ftrace_init(void); |
262 | extern void ftrace_init_module(unsigned long *start, unsigned long *end); | 289 | extern void ftrace_init_module(struct module *mod, |
290 | unsigned long *start, unsigned long *end); | ||
263 | #else | 291 | #else |
264 | static inline void ftrace_init(void) { } | 292 | static inline void ftrace_init(void) { } |
265 | static inline void | 293 | static inline void |
266 | ftrace_init_module(unsigned long *start, unsigned long *end) { } | 294 | ftrace_init_module(struct module *mod, |
295 | unsigned long *start, unsigned long *end) { } | ||
267 | #endif | 296 | #endif |
268 | 297 | ||
269 | 298 | ||