aboutsummaryrefslogtreecommitdiff
path: root/sys/arm64
diff options
context:
space:
mode:
authorAndrew Turner <andrew@FreeBSD.org>2018-07-31 12:53:27 +0000
committerAndrew Turner <andrew@FreeBSD.org>2018-07-31 12:53:27 +0000
commit0594061ee6fbd63d428e70cab4c82171f87f7604 (patch)
tree612de1fb938563b77727c6ef9b877792fb801e5c /sys/arm64
parent195e6c50d379f6d336888c17d91dca25493dbcd1 (diff)
downloadsrc-0594061ee6fbd63d428e70cab4c82171f87f7604.tar.gz
src-0594061ee6fbd63d428e70cab4c82171f87f7604.zip
Implement the SSBD (CVE-2018-3639) workaround on arm64
This calls into the Arm Trusted Firmware to enable and disable the workaround for the Speculative Store Bypass Disable (SSBD) issue, also known as Spectre Variant 4. As this may have a large performance overhead, and how exploitable SSBD is is unknown we follow the Linux lead of allowing the administrator to select between always on, always off, or only enabled in the kernel, with the latter being the default. PR: 228955 Sponsored by: DARPA, AFRL Differential Revision: https://reviews.freebsd.org/D15819
Notes
Notes: svn path=/head/; revision=336967
Diffstat (limited to 'sys/arm64')
-rw-r--r--sys/arm64/arm64/cpu_errata.c47
-rw-r--r--sys/arm64/arm64/exception.S16
-rw-r--r--sys/arm64/arm64/genassym.c1
-rw-r--r--sys/arm64/include/pcpu.h4
4 files changed, 67 insertions, 1 deletions
diff --git a/sys/arm64/arm64/cpu_errata.c b/sys/arm64/arm64/cpu_errata.c
index c54fb085e378..c41f9169cf4f 100644
--- a/sys/arm64/arm64/cpu_errata.c
+++ b/sys/arm64/arm64/cpu_errata.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/pcpu.h>
+#include <sys/systm.h>
#include <machine/cpu.h>
@@ -50,7 +51,14 @@ struct cpu_quirks {
u_int midr_value;
};
+static enum {
+ SSBD_FORCE_ON,
+ SSBD_FORCE_OFF,
+ SSBD_KERNEL,
+} ssbd_method = SSBD_KERNEL;
+
static cpu_quirk_install install_psci_bp_hardening;
+static cpu_quirk_install install_ssbd_workaround;
static struct cpu_quirks cpu_quirks[] = {
{
@@ -79,6 +87,11 @@ static struct cpu_quirks cpu_quirks[] = {
CPU_ID_RAW(CPU_IMPL_CAVIUM, CPU_PART_THUNDERX2, 0,0),
.quirk_install = install_psci_bp_hardening,
},
+ {
+ .midr_mask = 0,
+ .midr_value = 0,
+ .quirk_install = install_ssbd_workaround,
+ },
};
static void
@@ -91,6 +104,40 @@ install_psci_bp_hardening(void)
PCPU_SET(bp_harden, smccc_arch_workaround_1);
}
+static void
+install_ssbd_workaround(void)
+{
+ char *env;
+
+ if (PCPU_GET(cpuid) == 0) {
+ env = kern_getenv("kern.cfg.ssbd");
+ if (env != NULL) {
+ if (strcmp(env, "force-on") == 0) {
+ ssbd_method = SSBD_FORCE_ON;
+ } else if (strcmp(env, "force-off") == 0) {
+ ssbd_method = SSBD_FORCE_OFF;
+ }
+ }
+ }
+
+ /* Enable the workaround on this CPU if it's enabled in the firmware */
+ if (smccc_arch_features(SMCCC_ARCH_WORKAROUND_2) != SMCCC_RET_SUCCESS)
+ return;
+
+ switch(ssbd_method) {
+ case SSBD_FORCE_ON:
+ smccc_arch_workaround_2(true);
+ break;
+ case SSBD_FORCE_OFF:
+ smccc_arch_workaround_2(false);
+ break;
+ case SSBD_KERNEL:
+ default:
+ PCPU_SET(ssbd, smccc_arch_workaround_2);
+ break;
+ }
+}
+
void
install_cpu_errata(void)
{
diff --git a/sys/arm64/arm64/exception.S b/sys/arm64/arm64/exception.S
index 6cda7a265e75..d3242f4ac0b7 100644
--- a/sys/arm64/arm64/exception.S
+++ b/sys/arm64/arm64/exception.S
@@ -66,6 +66,14 @@ __FBSDID("$FreeBSD$");
stp x18, lr, [sp, #(TF_SP)]
mrs x18, tpidr_el1
add x29, sp, #(TF_SIZE)
+.if \el == 0
+ /* Apply the SSBD (CVE-2018-3639) workaround if needed */
+ ldr x1, [x18, #PC_SSBD]
+ cbz x1, 1f
+ mov w0, #1
+ blr x1
+1:
+.endif
.endm
.macro restore_registers el
@@ -76,6 +84,14 @@ __FBSDID("$FreeBSD$");
* handler. For EL0 exceptions, do_ast already did this.
*/
.endif
+.if \el == 0
+ /* Remove the SSBD (CVE-2018-3639) workaround if needed */
+ ldr x1, [x18, #PC_SSBD]
+ cbz x1, 1f
+ mov w0, #0
+ blr x1
+1:
+.endif
ldp x18, lr, [sp, #(TF_SP)]
ldp x10, x11, [sp, #(TF_ELR)]
.if \el == 0
diff --git a/sys/arm64/arm64/genassym.c b/sys/arm64/arm64/genassym.c
index 00b77a435867..debe63c62659 100644
--- a/sys/arm64/arm64/genassym.c
+++ b/sys/arm64/arm64/genassym.c
@@ -43,6 +43,7 @@ ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED);
ASSYM(PCPU_SIZE, sizeof(struct pcpu));
ASSYM(PC_CURPCB, offsetof(struct pcpu, pc_curpcb));
ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread));
+ASSYM(PC_SSBD, offsetof(struct pcpu, pc_ssbd));
/* Size of pcb, rounded to keep stack alignment */
ASSYM(PCB_SIZE, roundup2(sizeof(struct pcb), STACKALIGNBYTES + 1));
diff --git a/sys/arm64/include/pcpu.h b/sys/arm64/include/pcpu.h
index 48935c151072..fbe4310da2af 100644
--- a/sys/arm64/include/pcpu.h
+++ b/sys/arm64/include/pcpu.h
@@ -36,13 +36,15 @@
#define ALT_STACK_SIZE 128
typedef int (*pcpu_bp_harden)(void);
+typedef int (*pcpu_ssbd)(bool);
#define PCPU_MD_FIELDS \
u_int pc_acpi_id; /* ACPI CPU id */ \
u_int pc_midr; /* stored MIDR value */ \
uint64_t pc_clock; \
pcpu_bp_harden pc_bp_harden; \
- char __pad[233]
+ pcpu_ssbd pc_ssbd; \
+ char __pad[225]
#ifdef _KERNEL