diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/kernel/module.c | 6 | ||||
-rw-r--r-- | arch/powerpc/kernel/setup_32.c | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/setup_64.c | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/vdso.c | 10 | ||||
-rw-r--r-- | arch/powerpc/kernel/vdso32/vdso32.lds.S | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/vdso64/vdso64.lds.S | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/vmlinux.lds.S | 6 | ||||
-rw-r--r-- | arch/powerpc/lib/feature-fixups-test.S | 15 | ||||
-rw-r--r-- | arch/powerpc/lib/feature-fixups.c | 36 |
9 files changed, 85 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c index 40dd52d81c18..af07003573c4 100644 --- a/arch/powerpc/kernel/module.c +++ b/arch/powerpc/kernel/module.c | |||
@@ -86,6 +86,12 @@ int module_finalize(const Elf_Ehdr *hdr, | |||
86 | (void *)sect->sh_addr + sect->sh_size); | 86 | (void *)sect->sh_addr + sect->sh_size); |
87 | #endif | 87 | #endif |
88 | 88 | ||
89 | sect = find_section(hdr, sechdrs, "__lwsync_fixup"); | ||
90 | if (sect != NULL) | ||
91 | do_lwsync_fixups(cur_cpu_spec->cpu_features, | ||
92 | (void *)sect->sh_addr, | ||
93 | (void *)sect->sh_addr + sect->sh_size); | ||
94 | |||
89 | return 0; | 95 | return 0; |
90 | } | 96 | } |
91 | 97 | ||
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 9e83add54290..0109e7f0ccf9 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
@@ -101,6 +101,10 @@ unsigned long __init early_init(unsigned long dt_ptr) | |||
101 | PTRRELOC(&__start___ftr_fixup), | 101 | PTRRELOC(&__start___ftr_fixup), |
102 | PTRRELOC(&__stop___ftr_fixup)); | 102 | PTRRELOC(&__stop___ftr_fixup)); |
103 | 103 | ||
104 | do_lwsync_fixups(spec->cpu_features, | ||
105 | PTRRELOC(&__start___lwsync_fixup), | ||
106 | PTRRELOC(&__stop___lwsync_fixup)); | ||
107 | |||
104 | return KERNELBASE + offset; | 108 | return KERNELBASE + offset; |
105 | } | 109 | } |
106 | 110 | ||
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 098fd96a394a..04d8de9f0fc6 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -363,6 +363,8 @@ void __init setup_system(void) | |||
363 | &__start___ftr_fixup, &__stop___ftr_fixup); | 363 | &__start___ftr_fixup, &__stop___ftr_fixup); |
364 | do_feature_fixups(powerpc_firmware_features, | 364 | do_feature_fixups(powerpc_firmware_features, |
365 | &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup); | 365 | &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup); |
366 | do_lwsync_fixups(cur_cpu_spec->cpu_features, | ||
367 | &__start___lwsync_fixup, &__stop___lwsync_fixup); | ||
366 | 368 | ||
367 | /* | 369 | /* |
368 | * Unflatten the device-tree passed by prom_init or kexec | 370 | * Unflatten the device-tree passed by prom_init or kexec |
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index ce245a850db2..f177c60ea766 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c | |||
@@ -571,6 +571,11 @@ static __init int vdso_fixup_features(struct lib32_elfinfo *v32, | |||
571 | if (start64) | 571 | if (start64) |
572 | do_feature_fixups(powerpc_firmware_features, | 572 | do_feature_fixups(powerpc_firmware_features, |
573 | start64, start64 + size64); | 573 | start64, start64 + size64); |
574 | |||
575 | start64 = find_section64(v64->hdr, "__lwsync_fixup", &size64); | ||
576 | if (start64) | ||
577 | do_lwsync_fixups(cur_cpu_spec->cpu_features, | ||
578 | start64, start64 + size64); | ||
574 | #endif /* CONFIG_PPC64 */ | 579 | #endif /* CONFIG_PPC64 */ |
575 | 580 | ||
576 | start32 = find_section32(v32->hdr, "__ftr_fixup", &size32); | 581 | start32 = find_section32(v32->hdr, "__ftr_fixup", &size32); |
@@ -585,6 +590,11 @@ static __init int vdso_fixup_features(struct lib32_elfinfo *v32, | |||
585 | start32, start32 + size32); | 590 | start32, start32 + size32); |
586 | #endif /* CONFIG_PPC64 */ | 591 | #endif /* CONFIG_PPC64 */ |
587 | 592 | ||
593 | start32 = find_section32(v32->hdr, "__lwsync_fixup", &size32); | ||
594 | if (start32) | ||
595 | do_lwsync_fixups(cur_cpu_spec->cpu_features, | ||
596 | start32, start32 + size32); | ||
597 | |||
588 | return 0; | 598 | return 0; |
589 | } | 599 | } |
590 | 600 | ||
diff --git a/arch/powerpc/kernel/vdso32/vdso32.lds.S b/arch/powerpc/kernel/vdso32/vdso32.lds.S index 271793577cdc..be3b6a41dc09 100644 --- a/arch/powerpc/kernel/vdso32/vdso32.lds.S +++ b/arch/powerpc/kernel/vdso32/vdso32.lds.S | |||
@@ -33,6 +33,9 @@ SECTIONS | |||
33 | . = ALIGN(8); | 33 | . = ALIGN(8); |
34 | __ftr_fixup : { *(__ftr_fixup) } | 34 | __ftr_fixup : { *(__ftr_fixup) } |
35 | 35 | ||
36 | . = ALIGN(8); | ||
37 | __lwsync_fixup : { *(__lwsync_fixup) } | ||
38 | |||
36 | #ifdef CONFIG_PPC64 | 39 | #ifdef CONFIG_PPC64 |
37 | . = ALIGN(8); | 40 | . = ALIGN(8); |
38 | __fw_ftr_fixup : { *(__fw_ftr_fixup) } | 41 | __fw_ftr_fixup : { *(__fw_ftr_fixup) } |
diff --git a/arch/powerpc/kernel/vdso64/vdso64.lds.S b/arch/powerpc/kernel/vdso64/vdso64.lds.S index e608d1bd3bff..d0b2526dd38d 100644 --- a/arch/powerpc/kernel/vdso64/vdso64.lds.S +++ b/arch/powerpc/kernel/vdso64/vdso64.lds.S | |||
@@ -35,6 +35,9 @@ SECTIONS | |||
35 | __ftr_fixup : { *(__ftr_fixup) } | 35 | __ftr_fixup : { *(__ftr_fixup) } |
36 | 36 | ||
37 | . = ALIGN(8); | 37 | . = ALIGN(8); |
38 | __lwsync_fixup : { *(__lwsync_fixup) } | ||
39 | |||
40 | . = ALIGN(8); | ||
38 | __fw_ftr_fixup : { *(__fw_ftr_fixup) } | 41 | __fw_ftr_fixup : { *(__fw_ftr_fixup) } |
39 | 42 | ||
40 | /* | 43 | /* |
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 3c07811989fc..6856f6c15727 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S | |||
@@ -127,6 +127,12 @@ SECTIONS | |||
127 | *(__ftr_fixup) | 127 | *(__ftr_fixup) |
128 | __stop___ftr_fixup = .; | 128 | __stop___ftr_fixup = .; |
129 | } | 129 | } |
130 | . = ALIGN(8); | ||
131 | __lwsync_fixup : AT(ADDR(__lwsync_fixup) - LOAD_OFFSET) { | ||
132 | __start___lwsync_fixup = .; | ||
133 | *(__lwsync_fixup) | ||
134 | __stop___lwsync_fixup = .; | ||
135 | } | ||
130 | #ifdef CONFIG_PPC64 | 136 | #ifdef CONFIG_PPC64 |
131 | . = ALIGN(8); | 137 | . = ALIGN(8); |
132 | __fw_ftr_fixup : AT(ADDR(__fw_ftr_fixup) - LOAD_OFFSET) { | 138 | __fw_ftr_fixup : AT(ADDR(__fw_ftr_fixup) - LOAD_OFFSET) { |
diff --git a/arch/powerpc/lib/feature-fixups-test.S b/arch/powerpc/lib/feature-fixups-test.S index 0549be04399c..cb737484c5aa 100644 --- a/arch/powerpc/lib/feature-fixups-test.S +++ b/arch/powerpc/lib/feature-fixups-test.S | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #include <asm/feature-fixups.h> | 11 | #include <asm/feature-fixups.h> |
12 | #include <asm/ppc_asm.h> | 12 | #include <asm/ppc_asm.h> |
13 | #include <asm/synch.h> | ||
13 | 14 | ||
14 | .text | 15 | .text |
15 | 16 | ||
@@ -725,3 +726,17 @@ MAKE_MACRO_TEST_EXPECTED(FTR); | |||
725 | MAKE_MACRO_TEST(FW_FTR); | 726 | MAKE_MACRO_TEST(FW_FTR); |
726 | MAKE_MACRO_TEST_EXPECTED(FW_FTR); | 727 | MAKE_MACRO_TEST_EXPECTED(FW_FTR); |
727 | #endif | 728 | #endif |
729 | |||
730 | globl(lwsync_fixup_test) | ||
731 | 1: or 1,1,1 | ||
732 | LWSYNC | ||
733 | globl(end_lwsync_fixup_test) | ||
734 | |||
735 | globl(lwsync_fixup_test_expected_LWSYNC) | ||
736 | 1: or 1,1,1 | ||
737 | lwsync | ||
738 | |||
739 | globl(lwsync_fixup_test_expected_SYNC) | ||
740 | 1: or 1,1,1 | ||
741 | sync | ||
742 | |||
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c index 48e1ed89052d..4e43702b9813 100644 --- a/arch/powerpc/lib/feature-fixups.c +++ b/arch/powerpc/lib/feature-fixups.c | |||
@@ -110,6 +110,22 @@ void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end) | |||
110 | } | 110 | } |
111 | } | 111 | } |
112 | 112 | ||
113 | void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end) | ||
114 | { | ||
115 | unsigned int *start, *end, *dest; | ||
116 | |||
117 | if (!(value & CPU_FTR_LWSYNC)) | ||
118 | return ; | ||
119 | |||
120 | start = fixup_start; | ||
121 | end = fixup_end; | ||
122 | |||
123 | for (; start < end; start++) { | ||
124 | dest = (void *)start + *start; | ||
125 | patch_instruction(dest, PPC_LWSYNC_INSTR); | ||
126 | } | ||
127 | } | ||
128 | |||
113 | #ifdef CONFIG_FTR_FIXUP_SELFTEST | 129 | #ifdef CONFIG_FTR_FIXUP_SELFTEST |
114 | 130 | ||
115 | #define check(x) \ | 131 | #define check(x) \ |
@@ -295,6 +311,25 @@ static void test_fw_macros(void) | |||
295 | #endif | 311 | #endif |
296 | } | 312 | } |
297 | 313 | ||
314 | static void test_lwsync_macros(void) | ||
315 | { | ||
316 | extern void lwsync_fixup_test; | ||
317 | extern void end_lwsync_fixup_test; | ||
318 | extern void lwsync_fixup_test_expected_LWSYNC; | ||
319 | extern void lwsync_fixup_test_expected_SYNC; | ||
320 | unsigned long size = &end_lwsync_fixup_test - | ||
321 | &lwsync_fixup_test; | ||
322 | |||
323 | /* The fixups have already been done for us during boot */ | ||
324 | if (cur_cpu_spec->cpu_features & CPU_FTR_LWSYNC) { | ||
325 | check(memcmp(&lwsync_fixup_test, | ||
326 | &lwsync_fixup_test_expected_LWSYNC, size) == 0); | ||
327 | } else { | ||
328 | check(memcmp(&lwsync_fixup_test, | ||
329 | &lwsync_fixup_test_expected_SYNC, size) == 0); | ||
330 | } | ||
331 | } | ||
332 | |||
298 | static int __init test_feature_fixups(void) | 333 | static int __init test_feature_fixups(void) |
299 | { | 334 | { |
300 | printk(KERN_DEBUG "Running feature fixup self-tests ...\n"); | 335 | printk(KERN_DEBUG "Running feature fixup self-tests ...\n"); |
@@ -307,6 +342,7 @@ static int __init test_feature_fixups(void) | |||
307 | test_alternative_case_with_external_branch(); | 342 | test_alternative_case_with_external_branch(); |
308 | test_cpu_macros(); | 343 | test_cpu_macros(); |
309 | test_fw_macros(); | 344 | test_fw_macros(); |
345 | test_lwsync_macros(); | ||
310 | 346 | ||
311 | return 0; | 347 | return 0; |
312 | } | 348 | } |