ftrace introduces instability into kernel 2.6.27(-rc2,-rc3)
Benjamin Herrenschmidt
benh at kernel.crashing.org
Tue Aug 19 12:56:40 EST 2008
Ok, so i did a patch, but it doesn't fix the problem. So
there's something else whacking on the stack frames.
Still, here it is:
powerpc/ftrace: Fix broken assembly for code replacement
Instead, uses __get_user() and __put_user().
Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
---
Index: linux-work/arch/powerpc/kernel/ftrace.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/ftrace.c 2008-08-19 12:45:49.000000000 +1000
+++ linux-work/arch/powerpc/kernel/ftrace.c 2008-08-19 12:52:51.000000000 +1000
@@ -16,7 +16,7 @@
#include <asm/cacheflush.h>
#include <asm/ftrace.h>
-
+#include <asm/uaccess.h>
static unsigned int ftrace_nop = 0x60000000;
@@ -72,10 +72,9 @@ notrace int
ftrace_modify_code(unsigned long ip, unsigned char *old_code,
unsigned char *new_code)
{
- unsigned replaced;
- unsigned old = *(unsigned *)old_code;
- unsigned new = *(unsigned *)new_code;
- int faulted = 0;
+ unsigned int old = *(unsigned int *)old_code;
+ unsigned int new = *(unsigned int *)new_code;
+ unsigned int instr;
/*
* Note: Due to modules and __init, code can
@@ -85,32 +84,13 @@ ftrace_modify_code(unsigned long ip, uns
* No real locking needed, this code is run through
* kstop_machine.
*/
- asm volatile (
- "1: lwz %1, 0(%2)\n"
- " cmpw %1, %5\n"
- " bne 2f\n"
- " stwu %3, 0(%2)\n"
- "2:\n"
- ".section .fixup, \"ax\"\n"
- "3: li %0, 1\n"
- " b 2b\n"
- ".previous\n"
- ".section __ex_table,\"a\"\n"
- _ASM_ALIGN "\n"
- _ASM_PTR "1b, 3b\n"
- ".previous"
- : "=r"(faulted), "=r"(replaced)
- : "r"(ip), "r"(new),
- "0"(faulted), "r"(old)
- : "memory");
-
- if (replaced != old && replaced != new)
- faulted = 2;
-
- if (!faulted)
- flush_icache_range(ip, ip + 8);
-
- return faulted;
+ if (__get_user(instr, (unsigned int __user *)ip))
+ return 1;
+ if (instr != old && instr != new)
+ return 2;
+ WARN_ON_ONCE(__put_user(new, (unsigned int __user *)ip));
+ flush_icache_range(ip, ip + 8);
+ return 0;
}
notrace int ftrace_update_ftrace_func(ftrace_func_t func)
More information about the Linuxppc-dev
mailing list