aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2012-04-26 04:31:18 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-07-03 00:14:38 -0400
commitb6e3796834faefe4b6e9a2aedfe12665cd51fbc5 (patch)
treed330be3540cf441198f630c8fa0eda9899ddb8b5 /arch/powerpc
parentee456bb346e75a9b6d941224b108250e6ee5f79f (diff)
powerpc: Have patch_instruction detect faults
For ftrace to use the patch_instruction code, it needs to check for faults on write. Ftrace updates code all over the kernel, and we need to know if code is updated or not due to protections that are placed on some portions of the kernel. If ftrace does not detect a fault, it will error later on, and it will be much more difficult to find the problem. By changing patch_instruction() to detect faults, then ftrace will be able to make use of it too. Signed-off-by: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/code-patching.h4
-rw-r--r--arch/powerpc/lib/code-patching.c14
2 files changed, 12 insertions, 6 deletions
diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h
index 37c32aba79b7..a6f8c7a5cbb7 100644
--- a/arch/powerpc/include/asm/code-patching.h
+++ b/arch/powerpc/include/asm/code-patching.h
@@ -26,8 +26,8 @@ unsigned int create_branch(const unsigned int *addr,
26 unsigned long target, int flags); 26 unsigned long target, int flags);
27unsigned int create_cond_branch(const unsigned int *addr, 27unsigned int create_cond_branch(const unsigned int *addr,
28 unsigned long target, int flags); 28 unsigned long target, int flags);
29void patch_branch(unsigned int *addr, unsigned long target, int flags); 29int patch_branch(unsigned int *addr, unsigned long target, int flags);
30void patch_instruction(unsigned int *addr, unsigned int instr); 30int patch_instruction(unsigned int *addr, unsigned int instr);
31 31
32int instr_is_relative_branch(unsigned int instr); 32int instr_is_relative_branch(unsigned int instr);
33int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr); 33int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr);
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 7c975d43e3f3..dd223b3eb333 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -13,17 +13,23 @@
13#include <linux/mm.h> 13#include <linux/mm.h>
14#include <asm/page.h> 14#include <asm/page.h>
15#include <asm/code-patching.h> 15#include <asm/code-patching.h>
16#include <asm/uaccess.h>
16 17
17 18
18void patch_instruction(unsigned int *addr, unsigned int instr) 19int patch_instruction(unsigned int *addr, unsigned int instr)
19{ 20{
20 *addr = instr; 21 int err;
22
23 err = __put_user(instr, addr);
24 if (err)
25 return err;
21 asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" : : "r" (addr)); 26 asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" : : "r" (addr));
27 return 0;
22} 28}
23 29
24void patch_branch(unsigned int *addr, unsigned long target, int flags) 30int patch_branch(unsigned int *addr, unsigned long target, int flags)
25{ 31{
26 patch_instruction(addr, create_branch(addr, target, flags)); 32 return patch_instruction(addr, create_branch(addr, target, flags));
27} 33}
28 34
29unsigned int create_branch(const unsigned int *addr, 35unsigned int create_branch(const unsigned int *addr,