aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/ftrace.c
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2008-11-14 19:21:19 -0500
committerIngo Molnar <mingo@elte.hu>2008-11-16 01:36:02 -0500
commit31e889098a80ceb3e9e3c555d522b2686a6663c6 (patch)
tree2acb73507de4191d4a9aa5ccf08fa24e7044c89e /arch/x86/kernel/ftrace.c
parentd51ad7ac48f991c4a8834485727efa99a691cb87 (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/ftrace.c')
-rw-r--r--arch/x86/kernel/ftrace.c29
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
169unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) 169static 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
312static unsigned char ftrace_nop[MCOUNT_INSN_SIZE]; 312static unsigned char ftrace_nop[MCOUNT_INSN_SIZE];
313 313
314unsigned char *ftrace_nop_replace(void) 314static unsigned char *ftrace_nop_replace(void)
315{ 315{
316 return ftrace_nop; 316 return ftrace_nop;
317} 317}
318 318
319int 319static int
320ftrace_modify_code(unsigned long ip, unsigned char *old_code, 320ftrace_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
352int 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
364int 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
352int ftrace_update_ftrace_func(ftrace_func_t func) 375int 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);