diff options
Diffstat (limited to 'arch/powerpc/lib/feature-fixups.c')
-rw-r--r-- | arch/powerpc/lib/feature-fixups.c | 60 |
1 files changed, 54 insertions, 6 deletions
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c index e1bcdc32a851..8b69f868298c 100644 --- a/arch/powerpc/lib/feature-fixups.c +++ b/arch/powerpc/lib/feature-fixups.c @@ -277,6 +277,43 @@ void do_rfi_flush_fixups(enum l1d_flush_type types) (types & L1D_FLUSH_MTTRIG) ? "mttrig type" : "unknown"); } + +void do_barrier_nospec_fixups_range(bool enable, void *fixup_start, void *fixup_end) +{ + unsigned int instr, *dest; + long *start, *end; + int i; + + start = fixup_start; + end = fixup_end; + + instr = 0x60000000; /* nop */ + + if (enable) { + pr_info("barrier-nospec: using ORI speculation barrier\n"); + instr = 0x63ff0000; /* ori 31,31,0 speculation barrier */ + } + + for (i = 0; start < end; start++, i++) { + dest = (void *)start + *start; + + pr_devel("patching dest %lx\n", (unsigned long)dest); + patch_instruction(dest, instr); + } + + printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i); +} + +void do_barrier_nospec_fixups(bool enable) +{ + void *start, *end; + + start = PTRRELOC(&__start___barrier_nospec_fixup), + end = PTRRELOC(&__stop___barrier_nospec_fixup); + + do_barrier_nospec_fixups_range(enable, start, end); +} + #endif /* CONFIG_PPC_BOOK3S_64 */ void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end) @@ -400,7 +437,7 @@ static void test_basic_patching(void) extern unsigned int end_ftr_fixup_test1[]; extern unsigned int ftr_fixup_test1_orig[]; extern unsigned int ftr_fixup_test1_expected[]; - int size = end_ftr_fixup_test1 - ftr_fixup_test1; + int size = 4 * (end_ftr_fixup_test1 - ftr_fixup_test1); fixup.value = fixup.mask = 8; fixup.start_off = calc_offset(&fixup, ftr_fixup_test1 + 1); @@ -432,7 +469,7 @@ static void test_alternative_patching(void) extern unsigned int ftr_fixup_test2_orig[]; extern unsigned int ftr_fixup_test2_alt[]; extern unsigned int ftr_fixup_test2_expected[]; - int size = end_ftr_fixup_test2 - ftr_fixup_test2; + int size = 4 * (end_ftr_fixup_test2 - ftr_fixup_test2); fixup.value = fixup.mask = 0xF; fixup.start_off = calc_offset(&fixup, ftr_fixup_test2 + 1); @@ -464,7 +501,7 @@ static void test_alternative_case_too_big(void) extern unsigned int end_ftr_fixup_test3[]; extern unsigned int ftr_fixup_test3_orig[]; extern unsigned int ftr_fixup_test3_alt[]; - int size = end_ftr_fixup_test3 - ftr_fixup_test3; + int size = 4 * (end_ftr_fixup_test3 - ftr_fixup_test3); fixup.value = fixup.mask = 0xC; fixup.start_off = calc_offset(&fixup, ftr_fixup_test3 + 1); @@ -491,7 +528,7 @@ static void test_alternative_case_too_small(void) extern unsigned int ftr_fixup_test4_orig[]; extern unsigned int ftr_fixup_test4_alt[]; extern unsigned int ftr_fixup_test4_expected[]; - int size = end_ftr_fixup_test4 - ftr_fixup_test4; + int size = 4 * (end_ftr_fixup_test4 - ftr_fixup_test4); unsigned long flag; /* Check a high-bit flag */ @@ -525,7 +562,7 @@ static void test_alternative_case_with_branch(void) extern unsigned int ftr_fixup_test5[]; extern unsigned int end_ftr_fixup_test5[]; extern unsigned int ftr_fixup_test5_expected[]; - int size = end_ftr_fixup_test5 - ftr_fixup_test5; + int size = 4 * (end_ftr_fixup_test5 - ftr_fixup_test5); check(memcmp(ftr_fixup_test5, ftr_fixup_test5_expected, size) == 0); } @@ -535,11 +572,21 @@ static void test_alternative_case_with_external_branch(void) extern unsigned int ftr_fixup_test6[]; extern unsigned int end_ftr_fixup_test6[]; extern unsigned int ftr_fixup_test6_expected[]; - int size = end_ftr_fixup_test6 - ftr_fixup_test6; + int size = 4 * (end_ftr_fixup_test6 - ftr_fixup_test6); check(memcmp(ftr_fixup_test6, ftr_fixup_test6_expected, size) == 0); } +static void test_alternative_case_with_branch_to_end(void) +{ + extern unsigned int ftr_fixup_test7[]; + extern unsigned int end_ftr_fixup_test7[]; + extern unsigned int ftr_fixup_test7_expected[]; + int size = 4 * (end_ftr_fixup_test7 - ftr_fixup_test7); + + check(memcmp(ftr_fixup_test7, ftr_fixup_test7_expected, size) == 0); +} + static void test_cpu_macros(void) { extern u8 ftr_fixup_test_FTR_macros[]; @@ -595,6 +642,7 @@ static int __init test_feature_fixups(void) test_alternative_case_too_small(); test_alternative_case_with_branch(); test_alternative_case_with_external_branch(); + test_alternative_case_with_branch_to_end(); test_cpu_macros(); test_fw_macros(); test_lwsync_macros(); |