@@ -58,7 +58,10 @@ enum spec_barrier_type {
void __init setup_rfi_flush(enum l1d_flush_type, bool enable);
void do_rfi_flush_fixups(enum l1d_flush_type types);
void __init setup_barrier_nospec(enum spec_barrier_type, bool enable);
-void do_barrier_nospec_fixups(enum spec_barrier_type type);
+void do_barrier_nospec_fixups_kernel(enum spec_barrier_type type);
+void do_barrier_nospec_fixups(enum spec_barrier_type type,
+ void *start, void *end);
+extern enum spec_barrier_type powerpc_barrier_nospec;
#endif /* !__ASSEMBLY__ */
@@ -72,6 +72,12 @@ int module_finalize(const Elf_Ehdr *hdr,
do_feature_fixups(powerpc_firmware_features,
(void *)sect->sh_addr,
(void *)sect->sh_addr + sect->sh_size);
+
+ sect = find_section(hdr, sechdrs, "__spec_barrier_fixup");
+ if (sect != NULL)
+ do_barrier_nospec_fixups(powerpc_barrier_nospec,
+ (void *)sect->sh_addr,
+ (void *)sect->sh_addr + sect->sh_size);
#endif
sect = find_section(hdr, sechdrs, "__lwsync_fixup");
@@ -909,11 +909,11 @@ void barrier_nospec_enable(bool enable)
if (enable) {
powerpc_barrier_nospec = barrier_nospec_type;
- do_barrier_nospec_fixups(powerpc_barrier_nospec);
+ do_barrier_nospec_fixups_kernel(powerpc_barrier_nospec);
on_each_cpu(do_nothing, NULL, 1);
} else {
powerpc_barrier_nospec = SPEC_BARRIER_NONE;
- do_barrier_nospec_fixups(powerpc_barrier_nospec);
+ do_barrier_nospec_fixups_kernel(powerpc_barrier_nospec);
}
}
@@ -156,14 +156,15 @@ void do_rfi_flush_fixups(enum l1d_flush_type types)
printk(KERN_DEBUG "rfi-flush: patched %d locations\n", i);
}
-void do_barrier_nospec_fixups(enum spec_barrier_type type)
+void do_barrier_nospec_fixups(enum spec_barrier_type type,
+ void *fixup_start, void *fixup_end)
{
unsigned int instr, *dest;
long *start, *end;
int i;
- start = PTRRELOC(&__start___spec_barrier_fixup),
- end = PTRRELOC(&__stop___spec_barrier_fixup);
+ start = fixup_start;
+ end = fixup_end;
instr = 0x60000000; /* nop */
@@ -182,6 +183,16 @@ void do_barrier_nospec_fixups(enum spec_barrier_type type)
printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i);
}
+void do_barrier_nospec_fixups_kernel(enum spec_barrier_type type)
+{
+ void *start, *end;
+
+ start = PTRRELOC(&__start___spec_barrier_fixup),
+ end = PTRRELOC(&__stop___spec_barrier_fixup);
+
+ do_barrier_nospec_fixups(type, start, end);
+}
+
#endif /* CONFIG_PPC_BOOK3S_64 */
void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
Copypasta from lwsync patching. Note that unlike RFI which is patched only in kernel the nospec state reflects settings at the time the module was loaded. Iterating all modules and re-patching every time the settings change is not implemented. Signed-off-by: Michal Suchanek <msuchanek@suse.de> --- arch/powerpc/include/asm/setup.h | 5 ++++- arch/powerpc/kernel/module.c | 6 ++++++ arch/powerpc/kernel/setup_64.c | 4 ++-- arch/powerpc/lib/feature-fixups.c | 17 ++++++++++++++--- 4 files changed, 26 insertions(+), 6 deletions(-)