aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/lib
diff options
context:
space:
mode:
authorMichael Ellerman <michael@ellerman.id.au>2008-06-23 21:32:22 -0400
committerPaul Mackerras <paulus@samba.org>2008-06-30 21:28:19 -0400
commite7a57273c6407bb6903fbaddec8c2119bf318617 (patch)
tree4d5b787c286e1d0ae64f757ef1f68fedd9743a3c /arch/powerpc/lib
parentaaddd3eacaeaef3503035750b3f21ac2bfe97cbf (diff)
powerpc: Allow create_branch() to return errors
Currently create_branch() creates a branch instruction for you, and patches it into the call site. In some circumstances it would be nice to be able to create the instruction and patch it later, and also some code might want to check for errors in the branch creation before doing the patching. A future commit will change create_branch() to check for errors. For callers that don't care, replace create_branch() with patch_branch(), which just creates the branch and patches it directly. While we're touching all the callers, change to using unsigned int *, as this seems to match usage better. That allows (and requires) us to remove the volatile in the definition of vector in powermac/smp.c and mpc86xx_smp.c, that's correct because now that we're passing vector as an unsigned int * the compiler knows that it's value might change across the patch_branch() call. Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Acked-by: Kumar Gala <galak@kernel.crashing.org> Acked-by: Jon Loeliger <jdl@freescale.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/lib')
-rw-r--r--arch/powerpc/lib/code-patching.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 7afae88ed1d4..638dde313cbc 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -11,23 +11,27 @@
11#include <asm/code-patching.h> 11#include <asm/code-patching.h>
12 12
13 13
14void create_instruction(unsigned long addr, unsigned int instr) 14void patch_instruction(unsigned int *addr, unsigned int instr)
15{ 15{
16 unsigned int *p; 16 *addr = instr;
17 p = (unsigned int *)addr; 17 asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" : : "r" (addr));
18 *p = instr;
19 asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" : : "r" (p));
20} 18}
21 19
22void create_branch(unsigned long addr, unsigned long target, int flags) 20void patch_branch(unsigned int *addr, unsigned long target, int flags)
21{
22 patch_instruction(addr, create_branch(addr, target, flags));
23}
24
25unsigned int create_branch(const unsigned int *addr,
26 unsigned long target, int flags)
23{ 27{
24 unsigned int instruction; 28 unsigned int instruction;
25 29
26 if (! (flags & BRANCH_ABSOLUTE)) 30 if (! (flags & BRANCH_ABSOLUTE))
27 target = target - addr; 31 target = target - (unsigned long)addr;
28 32
29 /* Mask out the flags and target, so they don't step on each other. */ 33 /* Mask out the flags and target, so they don't step on each other. */
30 instruction = 0x48000000 | (flags & 0x3) | (target & 0x03FFFFFC); 34 instruction = 0x48000000 | (flags & 0x3) | (target & 0x03FFFFFC);
31 35
32 create_instruction(addr, instruction); 36 return instruction;
33} 37}