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 /arch/x86/kernel | |
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 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/ftrace.c | 29 |
1 files changed, 26 insertions, 3 deletions
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index fe832738e1e2..762222ad1387 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c | |||
@@ -166,7 +166,7 @@ static int ftrace_calc_offset(long ip, long addr) | |||
166 | return (int)(addr - ip); | 166 | return (int)(addr - ip); |
167 | } | 167 | } |
168 | 168 | ||
169 | unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) | 169 | static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) |
170 | { | 170 | { |
171 | static union ftrace_code_union calc; | 171 | static union ftrace_code_union calc; |
172 | 172 | ||
@@ -311,12 +311,12 @@ do_ftrace_mod_code(unsigned long ip, void *new_code) | |||
311 | 311 | ||
312 | static unsigned char ftrace_nop[MCOUNT_INSN_SIZE]; | 312 | static unsigned char ftrace_nop[MCOUNT_INSN_SIZE]; |
313 | 313 | ||
314 | unsigned char *ftrace_nop_replace(void) | 314 | static unsigned char *ftrace_nop_replace(void) |
315 | { | 315 | { |
316 | return ftrace_nop; | 316 | return ftrace_nop; |
317 | } | 317 | } |
318 | 318 | ||
319 | int | 319 | static int |
320 | ftrace_modify_code(unsigned long ip, unsigned char *old_code, | 320 | ftrace_modify_code(unsigned long ip, unsigned char *old_code, |
321 | unsigned char *new_code) | 321 | unsigned char *new_code) |
322 | { | 322 | { |
@@ -349,6 +349,29 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code, | |||
349 | return 0; | 349 | return 0; |
350 | } | 350 | } |
351 | 351 | ||
352 | int ftrace_make_nop(struct module *mod, | ||
353 | struct dyn_ftrace *rec, unsigned long addr) | ||
354 | { | ||
355 | unsigned char *new, *old; | ||
356 | unsigned long ip = rec->ip; | ||
357 | |||
358 | old = ftrace_call_replace(ip, addr); | ||
359 | new = ftrace_nop_replace(); | ||
360 | |||
361 | return ftrace_modify_code(rec->ip, old, new); | ||
362 | } | ||
363 | |||
364 | int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | ||
365 | { | ||
366 | unsigned char *new, *old; | ||
367 | unsigned long ip = rec->ip; | ||
368 | |||
369 | old = ftrace_nop_replace(); | ||
370 | new = ftrace_call_replace(ip, addr); | ||
371 | |||
372 | return ftrace_modify_code(rec->ip, old, new); | ||
373 | } | ||
374 | |||
352 | int ftrace_update_ftrace_func(ftrace_func_t func) | 375 | int ftrace_update_ftrace_func(ftrace_func_t func) |
353 | { | 376 | { |
354 | unsigned long ip = (unsigned long)(&ftrace_call); | 377 | unsigned long ip = (unsigned long)(&ftrace_call); |