summaryrefslogtreecommitdiff
path: root/arch/arm64/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm64/kernel')
-rw-r--r--arch/arm64/kernel/cpu_errata.c64
-rw-r--r--arch/arm64/kernel/entry-ftrace.S2
-rw-r--r--arch/arm64/kernel/entry.S6
-rw-r--r--arch/arm64/kernel/vmlinux.lds.S7
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 */
}