sparc64: Add proper dynamic ftrace support.
authorDavid S. Miller <davem@davemloft.net>
Sat, 13 Jun 2009 08:03:24 +0000 (01:03 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 16 Jun 2009 11:56:53 +0000 (04:56 -0700)
Signed-off-by: David S. Miller <davem@davemloft.net>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Acked-by: Ingo Molnar <mingo@elte.hu>
arch/sparc/Kconfig
arch/sparc/include/asm/ftrace.h
arch/sparc/kernel/ftrace.c
scripts/recordmcount.pl

index 2185cf946d6863316b9233141a2f4364822da039..3f8b6a92eabdff56413ed4cefd54d678290a228a 100644 (file)
@@ -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
index d27716cd38c1ac0243a74104f3106850d24397b1..b0f18e9893db5a77cbc45e221a8159e3dc4f2fc5 100644 (file)
@@ -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 */
index d0218e73f9820b6a478837df8dcd2869f233dcbd..d3b1a3076569890724fdc58a77fd1949ca96a684 100644 (file)
@@ -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
+
index 91033e67321e84e6479816cdff61c372f3be58d1..7109e2b5bc0acf61e39c24aff4b2074016e6078c 100755 (executable)
@@ -226,6 +226,26 @@ if ($arch eq "x86_64") {
     if ($is_module eq "0") {
         $cc .= " -mconstant-gp";
     }
+} elsif ($arch eq "sparc64") {
+    # In the objdump output there are giblets like:
+    # 0000000000000000 <igmp_net_exit-0x18>:
+    # As there's some data blobs that get emitted into the
+    # text section before the first instructions and the first
+    # real symbols.  We don't want to match that, so to combat
+    # this we use '\w' so we'll match just plain symbol names,
+    # and not those that also include hex offsets inside of the
+    # '<>' brackets.  Actually the generic function_regex setting
+    # could safely use this too.
+    $function_regex = "^([0-9a-fA-F]+)\\s+<(\\w*?)>:";
+
+    # Sparc64 calls '_mcount' instead of plain 'mcount'.
+    $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
+
+    $alignment = 8;
+    $type = ".xword";
+    $ld .= " -m elf64_sparc";
+    $cc .= " -m64";
+    $objcopy .= " -O elf64-sparc";
 } else {
     die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD";
 }