Message ID | 20120426183508.749515835@goodmis.org (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Michael Ellerman |
Headers | show |
On Thu, 2012-04-26 at 14:31 -0400, Steven Rostedt wrote: > plain text document attachment > (0001-ftrace-ppc-Have-PPC-skip-updating-with-stop_machine.patch) > From: Steven Rostedt <srostedt@redhat.com> > > PPC does not have the synchronization issues that x86 has with > modifying code on one CPU while another CPU is executing it. > The other CPU will either see the old or new code without any > issues, unlike x86 which may issue a GPF. > > Instead of calling the heavy stop_machine, just update the code. This looks nice, but it's giving me this: arch/powerpc/kernel/ftrace.c:497:13: error: static declaration of 'ftrace_replace_code' follows non-static declaration include/linux/ftrace.h:317:13: note: previous declaration of 'ftrace_replace_code' was here I think the fix is just to make our ftrace_replace_code() non-static? cheers > +static void ftrace_replace_code(int enable) > +{ > + struct ftrace_rec_iter *iter; > + struct dyn_ftrace *rec; > + int ret; > + > + for (iter = ftrace_rec_iter_start(); iter; > + iter = ftrace_rec_iter_next(iter)) { > + rec = ftrace_rec_iter_record(iter); > + ret = __ftrace_replace_code(rec, enable); > + if (ret) { > + ftrace_bug(ret, rec->ip); > + return; > + } > + } > +} > +
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c index bf99cfa..84a5ddd 100644 --- a/arch/powerpc/kernel/ftrace.c +++ b/arch/powerpc/kernel/ftrace.c @@ -484,6 +484,58 @@ int ftrace_update_ftrace_func(ftrace_func_t func) return ret; } +static int __ftrace_replace_code(struct dyn_ftrace *rec, int enable) +{ + unsigned long ftrace_addr = (unsigned long)FTRACE_ADDR; + int ret; + + ret = ftrace_update_record(rec, enable); + + switch (ret) { + case FTRACE_UPDATE_IGNORE: + return 0; + case FTRACE_UPDATE_MAKE_CALL: + return ftrace_make_call(rec, ftrace_addr); + case FTRACE_UPDATE_MAKE_NOP: + return ftrace_make_nop(NULL, rec, ftrace_addr); + } + + return 0; +} + +static void ftrace_replace_code(int enable) +{ + struct ftrace_rec_iter *iter; + struct dyn_ftrace *rec; + int ret; + + for (iter = ftrace_rec_iter_start(); iter; + iter = ftrace_rec_iter_next(iter)) { + rec = ftrace_rec_iter_record(iter); + ret = __ftrace_replace_code(rec, enable); + if (ret) { + ftrace_bug(ret, rec->ip); + return; + } + } +} + +void arch_ftrace_update_code(int command) +{ + if (command & FTRACE_UPDATE_CALLS) + ftrace_replace_code(1); + else if (command & FTRACE_DISABLE_CALLS) + ftrace_replace_code(0); + + if (command & FTRACE_UPDATE_TRACE_FUNC) + ftrace_update_ftrace_func(ftrace_trace_function); + + if (command & FTRACE_START_FUNC_RET) + ftrace_enable_ftrace_graph_caller(); + else if (command & FTRACE_STOP_FUNC_RET) + ftrace_disable_ftrace_graph_caller(); +} + int __init ftrace_dyn_arch_init(void *data) { /* caller expects data to be zero */