summaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-06-13 10:03:24 +0200
committerDavid S. Miller <davem@davemloft.net>2009-06-16 13:56:53 +0200
commit9be12f9b1c4fd5f18cc82c170a32bfe1713ba76d (patch)
treed59b601e655160be8caaeb3ba755b0ad50199cc0 /arch/sparc
parentsparc: Simplify code using is_power_of_2() routine. (diff)
downloadlinux-9be12f9b1c4fd5f18cc82c170a32bfe1713ba76d.tar.xz
linux-9be12f9b1c4fd5f18cc82c170a32bfe1713ba76d.zip
sparc64: Add proper dynamic ftrace support.
Signed-off-by: David S. Miller <davem@davemloft.net> Acked-by: Steven Rostedt <rostedt@goodmis.org> Acked-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/Kconfig2
-rw-r--r--arch/sparc/include/asm/ftrace.h11
-rw-r--r--arch/sparc/kernel/ftrace.c47
3 files changed, 45 insertions, 15 deletions
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 2185cf946d68..3f8b6a92eabd 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -37,6 +37,8 @@ config SPARC64
select HAVE_KPROBES
select HAVE_LMB
select HAVE_SYSCALL_WRAPPERS
+ select HAVE_DYNAMIC_FTRACE
+ select HAVE_FTRACE_MCOUNT_RECORD
select USE_GENERIC_SMP_HELPERS if SMP
select RTC_DRV_CMOS
select RTC_DRV_BQ4802
diff --git a/arch/sparc/include/asm/ftrace.h b/arch/sparc/include/asm/ftrace.h
index d27716cd38c1..b0f18e9893db 100644
--- a/arch/sparc/include/asm/ftrace.h
+++ b/arch/sparc/include/asm/ftrace.h
@@ -11,4 +11,15 @@ extern void _mcount(void);
#endif
+#ifdef CONFIG_DYNAMIC_FTRACE
+/* reloction of mcount call site is the same as the address */
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+ return addr;
+}
+
+struct dyn_arch_ftrace {
+};
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
#endif /* _ASM_SPARC64_FTRACE */
diff --git a/arch/sparc/kernel/ftrace.c b/arch/sparc/kernel/ftrace.c
index d0218e73f982..d3b1a3076569 100644
--- a/arch/sparc/kernel/ftrace.c
+++ b/arch/sparc/kernel/ftrace.c
@@ -7,14 +7,10 @@
#include <asm/ftrace.h>
+#ifdef CONFIG_DYNAMIC_FTRACE
static const u32 ftrace_nop = 0x01000000;
-unsigned char *ftrace_nop_replace(void)
-{
- return (char *)&ftrace_nop;
-}
-
-unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr)
+static u32 ftrace_call_replace(unsigned long ip, unsigned long addr)
{
static u32 call;
s32 off;
@@ -22,15 +18,11 @@ unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr)
off = ((s32)addr - (s32)ip);
call = 0x40000000 | ((u32)off >> 2);
- return (unsigned char *) &call;
+ return call;
}
-int
-ftrace_modify_code(unsigned long ip, unsigned char *old_code,
- unsigned char *new_code)
+static int ftrace_modify_code(unsigned long ip, u32 old, u32 new)
{
- u32 old = *(u32 *)old_code;
- u32 new = *(u32 *)new_code;
u32 replaced;
int faulted;
@@ -59,18 +51,43 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code,
return faulted;
}
+int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr)
+{
+ unsigned long ip = rec->ip;
+ u32 old, new;
+
+ old = ftrace_call_replace(ip, addr);
+ new = ftrace_nop;
+ return ftrace_modify_code(ip, old, new);
+}
+
+int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
+{
+ unsigned long ip = rec->ip;
+ u32 old, new;
+
+ old = ftrace_nop;
+ new = ftrace_call_replace(ip, addr);
+ return ftrace_modify_code(ip, old, new);
+}
+
int ftrace_update_ftrace_func(ftrace_func_t func)
{
unsigned long ip = (unsigned long)(&ftrace_call);
- unsigned char old[MCOUNT_INSN_SIZE], *new;
+ u32 old, new;
- memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE);
+ old = *(u32 *) &ftrace_call;
new = ftrace_call_replace(ip, (unsigned long)func);
return ftrace_modify_code(ip, old, new);
}
int __init ftrace_dyn_arch_init(void *data)
{
- ftrace_mcount_set(data);
+ unsigned long *p = data;
+
+ *p = 0;
+
return 0;
}
+#endif
+