aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/crash_dump.c6
-rw-r--r--arch/powerpc/lib/code-patching.c20
-rw-r--r--arch/powerpc/platforms/86xx/mpc86xx_smp.c5
-rw-r--r--arch/powerpc/platforms/powermac/smp.c5
-rw-r--r--include/asm-powerpc/code-patching.h6
5 files changed, 24 insertions, 18 deletions
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
index 35b9a668b0e1..26648544d5e4 100644
--- a/arch/powerpc/kernel/crash_dump.c
+++ b/arch/powerpc/kernel/crash_dump.c
@@ -34,6 +34,8 @@ void __init reserve_kdump_trampoline(void)
34 34
35static void __init create_trampoline(unsigned long addr) 35static void __init create_trampoline(unsigned long addr)
36{ 36{
37 unsigned int *p = (unsigned int *)addr;
38
37 /* The maximum range of a single instruction branch, is the current 39 /* The maximum range of a single instruction branch, is the current
38 * instruction's address + (32 MB - 4) bytes. For the trampoline we 40 * instruction's address + (32 MB - 4) bytes. For the trampoline we
39 * need to branch to current address + 32 MB. So we insert a nop at 41 * need to branch to current address + 32 MB. So we insert a nop at
@@ -42,8 +44,8 @@ static void __init create_trampoline(unsigned long addr)
42 * branch to "addr" we jump to ("addr" + 32 MB). Although it requires 44 * branch to "addr" we jump to ("addr" + 32 MB). Although it requires
43 * two instructions it doesn't require any registers. 45 * two instructions it doesn't require any registers.
44 */ 46 */
45 create_instruction(addr, 0x60000000); /* nop */ 47 patch_instruction(p, 0x60000000); /* nop */
46 create_branch(addr + 4, addr + PHYSICAL_START, 0); 48 patch_branch(++p, addr + PHYSICAL_START, 0);
47} 49}
48 50
49void __init setup_kdump_trampoline(void) 51void __init setup_kdump_trampoline(void)
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}
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_smp.c b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
index 63f55853cd69..835f2dc24dc9 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_smp.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
@@ -57,8 +57,7 @@ smp_86xx_kick_cpu(int nr)
57 unsigned int save_vector; 57 unsigned int save_vector;
58 unsigned long target, flags; 58 unsigned long target, flags;
59 int n = 0; 59 int n = 0;
60 volatile unsigned int *vector 60 unsigned int *vector = (unsigned int *)(KERNELBASE + 0x100);
61 = (volatile unsigned int *)(KERNELBASE + 0x100);
62 61
63 if (nr < 0 || nr >= NR_CPUS) 62 if (nr < 0 || nr >= NR_CPUS)
64 return; 63 return;
@@ -72,7 +71,7 @@ smp_86xx_kick_cpu(int nr)
72 71
73 /* Setup fake reset vector to call __secondary_start_mpc86xx. */ 72 /* Setup fake reset vector to call __secondary_start_mpc86xx. */
74 target = (unsigned long) __secondary_start_mpc86xx; 73 target = (unsigned long) __secondary_start_mpc86xx;
75 create_branch((unsigned long)vector, target, BRANCH_SET_LINK); 74 patch_branch(vector, target, BRANCH_SET_LINK);
76 75
77 /* Kick that CPU */ 76 /* Kick that CPU */
78 smp_86xx_release_core(nr); 77 smp_86xx_release_core(nr);
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index bf202f7eadf8..4ae3d00e0bdd 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -787,8 +787,7 @@ static void __devinit smp_core99_kick_cpu(int nr)
787{ 787{
788 unsigned int save_vector; 788 unsigned int save_vector;
789 unsigned long target, flags; 789 unsigned long target, flags;
790 volatile unsigned int *vector 790 unsigned int *vector = (unsigned int *)(KERNELBASE+0x100);
791 = ((volatile unsigned int *)(KERNELBASE+0x100));
792 791
793 if (nr < 0 || nr > 3) 792 if (nr < 0 || nr > 3)
794 return; 793 return;
@@ -805,7 +804,7 @@ static void __devinit smp_core99_kick_cpu(int nr)
805 * b __secondary_start_pmac_0 + nr*8 - KERNELBASE 804 * b __secondary_start_pmac_0 + nr*8 - KERNELBASE
806 */ 805 */
807 target = (unsigned long) __secondary_start_pmac_0 + nr * 8; 806 target = (unsigned long) __secondary_start_pmac_0 + nr * 8;
808 create_branch((unsigned long)vector, target, BRANCH_SET_LINK); 807 patch_branch(vector, target, BRANCH_SET_LINK);
809 808
810 /* Put some life in our friend */ 809 /* Put some life in our friend */
811 pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0); 810 pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0);
diff --git a/include/asm-powerpc/code-patching.h b/include/asm-powerpc/code-patching.h
index 0b91fdf944db..fdb187cbc40d 100644
--- a/include/asm-powerpc/code-patching.h
+++ b/include/asm-powerpc/code-patching.h
@@ -19,7 +19,9 @@
19#define BRANCH_SET_LINK 0x1 19#define BRANCH_SET_LINK 0x1
20#define BRANCH_ABSOLUTE 0x2 20#define BRANCH_ABSOLUTE 0x2
21 21
22extern void create_branch(unsigned long addr, unsigned long target, int flags); 22unsigned int create_branch(const unsigned int *addr,
23extern void create_instruction(unsigned long addr, unsigned int instr); 23 unsigned long target, int flags);
24void patch_branch(unsigned int *addr, unsigned long target, int flags);
25void patch_instruction(unsigned int *addr, unsigned int instr);
24 26
25#endif /* _ASM_POWERPC_CODE_PATCHING_H */ 27#endif /* _ASM_POWERPC_CODE_PATCHING_H */