Index: head/sys/arm64/arm64/cpu_errata.c =================================================================== --- head/sys/arm64/arm64/cpu_errata.c +++ head/sys/arm64/arm64/cpu_errata.c @@ -38,6 +38,7 @@ #include #include #include +#include #include @@ -50,7 +51,14 @@ 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 @@ 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 @@ -89,6 +102,40 @@ return; 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 Index: head/sys/arm64/arm64/exception.S =================================================================== --- head/sys/arm64/arm64/exception.S +++ head/sys/arm64/arm64/exception.S @@ -66,6 +66,14 @@ 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 @@ -75,6 +83,14 @@ * Disable interrupts, x18 may change in the interrupt exception * 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)] Index: head/sys/arm64/arm64/genassym.c =================================================================== --- head/sys/arm64/arm64/genassym.c +++ head/sys/arm64/arm64/genassym.c @@ -43,6 +43,7 @@ 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)); Index: head/sys/arm64/include/pcpu.h =================================================================== --- head/sys/arm64/include/pcpu.h +++ head/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 Index: head/sys/dev/psci/smccc.h =================================================================== --- head/sys/dev/psci/smccc.h +++ head/sys/dev/psci/smccc.h @@ -59,6 +59,8 @@ SMCCC_FUNC_ID(SMCCC_FAST_CALL, SMCCC_32BIT_CALL, 0, 1) #define SMCCC_ARCH_WORKAROUND_1 \ SMCCC_FUNC_ID(SMCCC_FAST_CALL, SMCCC_32BIT_CALL, 0, 0x8000) +#define SMCCC_ARCH_WORKAROUND_2 \ + SMCCC_FUNC_ID(SMCCC_FAST_CALL, SMCCC_32BIT_CALL, 0, 0x7fff) /* The return values from ARM DEN 0070A. */ #define SMCCC_RET_SUCCESS 0 @@ -67,6 +69,7 @@ int32_t smccc_arch_features(uint32_t); int smccc_arch_workaround_1(void); +int smccc_arch_workaround_2(bool); #endif /* _PSCI_SMCCC_H_ */ Index: head/sys/dev/psci/smccc.c =================================================================== --- head/sys/dev/psci/smccc.c +++ head/sys/dev/psci/smccc.c @@ -91,3 +91,12 @@ ("SMCCC arch workaround 1 called with an invalid SMCCC interface")); return (psci_call(SMCCC_ARCH_WORKAROUND_1, 0, 0, 0)); } + +int +smccc_arch_workaround_2(bool enable) +{ + + KASSERT(smccc_version != SMCCC_VERSION_1_0, + ("SMCCC arch workaround 2 called with an invalid SMCCC interface")); + return (psci_call(SMCCC_ARCH_WORKAROUND_2, enable ? 1 : 0, 0, 0)); +}