diff options
Diffstat (limited to 'arch/arm64/kernel')
-rw-r--r-- | arch/arm64/kernel/cpu_errata.c | 64 | ||||
-rw-r--r-- | arch/arm64/kernel/entry-ftrace.S | 2 | ||||
-rw-r--r-- | arch/arm64/kernel/entry.S | 6 | ||||
-rw-r--r-- | arch/arm64/kernel/vmlinux.lds.S | 7 |
4 files changed, 75 insertions, 4 deletions
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index b5a28336c077..b6a20b767af6 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -462,3 +462,67 @@ void __init enable_errata_workarounds(void) { enable_cpu_capabilities(arm64_errata); } + +static inline bool retp_compiler(void) +{ + return __is_defined(RETPOLINE); +} + +/* The Spectre V2 mitigation variants */ +enum spectre_v2_mitigation { + SPECTRE_V2_NONE, + SPECTRE_V2_RETPOLINE_MINIMAL, + SPECTRE_V2_RETPOLINE_GENERIC, +}; + +static const char *spectre_v2_strings[] = { + [SPECTRE_V2_NONE] = "Vulnerable", + [SPECTRE_V2_RETPOLINE_MINIMAL] = "Vulnerable: Minimal generic ASM retpoline", + [SPECTRE_V2_RETPOLINE_GENERIC] = "Mitigation: Full generic retpoline", +}; + +enum spectre_v2_mitigation get_spectre_v2_mitigation(void) +{ + enum spectre_v2_mitigation mode; + +#ifndef RETPOLINE + return SPECTRE_V2_NONE; +#endif + + mode = retp_compiler() ? SPECTRE_V2_RETPOLINE_GENERIC : + SPECTRE_V2_RETPOLINE_MINIMAL; + + return mode; +} + +#ifdef RETPOLINE +static bool spectre_v2_bad_module; + +bool retpoline_module_ok(bool has_retpoline) +{ + if (has_retpoline) + return true; + + pr_err("System may be vulnerable to spectre v2\n"); + spectre_v2_bad_module = true; + return false; +} + +static inline const char *spectre_v2_module_string(void) +{ + return spectre_v2_bad_module ? " - vulnerable module loaded" : ""; +} +#else +static inline const char *spectre_v2_module_string(void) { return ""; } +#endif + +#ifdef CONFIG_SYSFS +ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, char *buf) +{ + enum spectre_v2_mitigation mode; + + mode = get_spectre_v2_mitigation(); + return sprintf(buf, "%s%s\n", spectre_v2_strings[mode], + spectre_v2_module_string()); +} +#endif diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S index 1175f5827ae1..27bb502aa5e6 100644 --- a/arch/arm64/kernel/entry-ftrace.S +++ b/arch/arm64/kernel/entry-ftrace.S @@ -106,7 +106,7 @@ ENTRY(_mcount) mcount_get_pc x0 // function's pc mcount_get_lr x1 // function's lr (= parent's pc) - blr x2 // (*ftrace_trace_function)(pc, lr); + blr_nospec x2 // (*ftrace_trace_function)(pc, lr); skip_ftrace_call: // } #ifdef CONFIG_FUNCTION_GRAPH_TRACER diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index f409b7750114..7475dbdb816f 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -395,7 +395,7 @@ tsk .req x28 // current thread_info ldr_l x1, handle_arch_irq mov x0, sp irq_stack_entry - blr x1 + blr_nospec x1 irq_stack_exit .endm @@ -976,7 +976,7 @@ el0_svc_naked: // compat entry point b.hs ni_sys mask_nospec64 xscno, xsc_nr, x19 // enforce bounds for syscall number ldr x16, [stbl, xscno, lsl #3] // address in the syscall table - blr x16 // call sys_* routine + blr_nospec x16 // call sys_* routine b ret_fast_syscall ni_sys: mov x0, sp @@ -1006,7 +1006,7 @@ __sys_trace: ldp x4, x5, [sp, #S_X4] ldp x6, x7, [sp, #S_X6] ldr x16, [stbl, xscno, lsl #3] // address in the syscall table - blr x16 // call sys_* routine + blr_nospec x16 // call sys_* routine __sys_trace_return: str x0, [sp, #S_X0] // save returned x0 diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index 0221aca6493d..7d534afe66b7 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -127,6 +127,13 @@ SECTIONS TRAMP_TEXT *(.fixup) *(.gnu.warning) + +#ifdef CONFIG_RETPOLINE + __indirect_thunk_start = .; + *(.text.__aarch64.indirect_thunk) + __indirect_thunk_end = .; +#endif /* CONFIG_RETPOLINE */ + . = ALIGN(16); *(.got) /* Global offset table */ } |