]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/x86/kernel/ftrace.c
Merge branch 'x86/signal' into core/signal
[linux-2.6-omap-h63xx.git] / arch / x86 / kernel / ftrace.c
index b69795efa2264008a7d168b564e2e9d173606d2d..ab115cd15fdfbb2cc06182385b4a60b8521f617c 100644 (file)
 #include <linux/list.h>
 
 #include <asm/alternative.h>
+#include <asm/ftrace.h>
 
-#define CALL_BACK              5
 
 /* Long is fine, even if it is only 4 bytes ;-) */
 static long *ftrace_nop;
 
 union ftrace_code_union {
-       char code[5];
+       char code[MCOUNT_INSN_SIZE];
        struct {
                char e8;
                int offset;
        } __attribute__((packed));
 };
 
-notrace int ftrace_ip_converted(unsigned long ip)
-{
-       unsigned long save;
-
-       ip -= CALL_BACK;
-       save = *(long *)ip;
-
-       return save == *ftrace_nop;
-}
 
 static int notrace ftrace_calc_offset(long ip, long addr)
 {
@@ -56,7 +47,7 @@ notrace unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr)
        static union ftrace_code_union calc;
 
        calc.e8         = 0xe8;
-       calc.offset     = ftrace_calc_offset(ip, addr);
+       calc.offset     = ftrace_calc_offset(ip + MCOUNT_INSN_SIZE, addr);
 
        /*
         * No locking needed, this must be called via kstop_machine
@@ -75,9 +66,6 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code,
        unsigned char newch = new_code[4];
        int faulted = 0;
 
-       /* move the IP back to the start of the call */
-       ip -= CALL_BACK;
-
        /*
         * Note: Due to modules and __init, code can
         *  disappear and change, we need to protect against faulting
@@ -93,12 +81,12 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code,
                "   movb %b4, 4(%2)\n"
                "2:\n"
                ".section .fixup, \"ax\"\n"
-               "       movl $1, %0\n"
-               "3:     jmp 2b\n"
+               "3:     movl $1, %0\n"
+               "       jmp 2b\n"
                ".previous\n"
                _ASM_EXTABLE(1b, 3b)
                : "=r"(faulted), "=a"(replaced)
-               : "r"(ip), "r"(new), "r"(newch),
+               : "r"(ip), "r"(new), "c"(newch),
                  "0"(faulted), "a"(old)
                : "memory");
        sync_core();
@@ -109,12 +97,45 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code,
        return faulted;
 }
 
-int __init ftrace_dyn_arch_init(void)
+notrace int ftrace_update_ftrace_func(ftrace_func_t func)
 {
-       const unsigned char *const *noptable = find_nop_table();
+       unsigned long ip = (unsigned long)(&ftrace_call);
+       unsigned char old[MCOUNT_INSN_SIZE], *new;
+       int ret;
 
-       ftrace_nop = (unsigned long *)noptable[CALL_BACK];
+       memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE);
+       new = ftrace_call_replace(ip, (unsigned long)func);
+       ret = ftrace_modify_code(ip, old, new);
+
+       return ret;
+}
+
+notrace int ftrace_mcount_set(unsigned long *data)
+{
+       unsigned long ip = (long)(&mcount_call);
+       unsigned long *addr = data;
+       unsigned char old[MCOUNT_INSN_SIZE], *new;
+
+       /*
+        * Replace the mcount stub with a pointer to the
+        * ip recorder function.
+        */
+       memcpy(old, &mcount_call, MCOUNT_INSN_SIZE);
+       new = ftrace_call_replace(ip, *addr);
+       *addr = ftrace_modify_code(ip, old, new);
 
        return 0;
 }
 
+int __init ftrace_dyn_arch_init(void *data)
+{
+       const unsigned char *const *noptable = find_nop_table();
+
+       /* This is running in kstop_machine */
+
+       ftrace_mcount_set(data);
+
+       ftrace_nop = (unsigned long *)noptable[MCOUNT_INSN_SIZE];
+
+       return 0;
+}