diff options
-rw-r--r-- | arch/powerpc/kernel/crash_dump.c | 6 | ||||
-rw-r--r-- | arch/powerpc/lib/code-patching.c | 20 | ||||
-rw-r--r-- | arch/powerpc/platforms/86xx/mpc86xx_smp.c | 5 | ||||
-rw-r--r-- | arch/powerpc/platforms/powermac/smp.c | 5 | ||||
-rw-r--r-- | include/asm-powerpc/code-patching.h | 6 |
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 | ||
35 | static void __init create_trampoline(unsigned long addr) | 35 | static 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 | ||
49 | void __init setup_kdump_trampoline(void) | 51 | void __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 | ||
14 | void create_instruction(unsigned long addr, unsigned int instr) | 14 | void 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 | ||
22 | void create_branch(unsigned long addr, unsigned long target, int flags) | 20 | void patch_branch(unsigned int *addr, unsigned long target, int flags) |
21 | { | ||
22 | patch_instruction(addr, create_branch(addr, target, flags)); | ||
23 | } | ||
24 | |||
25 | unsigned 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 | ||
22 | extern void create_branch(unsigned long addr, unsigned long target, int flags); | 22 | unsigned int create_branch(const unsigned int *addr, |
23 | extern void create_instruction(unsigned long addr, unsigned int instr); | 23 | unsigned long target, int flags); |
24 | void patch_branch(unsigned int *addr, unsigned long target, int flags); | ||
25 | void patch_instruction(unsigned int *addr, unsigned int instr); | ||
24 | 26 | ||
25 | #endif /* _ASM_POWERPC_CODE_PATCHING_H */ | 27 | #endif /* _ASM_POWERPC_CODE_PATCHING_H */ |