Date: Fri, 12 Jan 2018 14:01:38 +0000 (UTC) From: Andrew Turner <andrew@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r327876 - in head/sys/arm64: arm64 include Message-ID: <201801121401.w0CE1cW4058239@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: andrew Date: Fri Jan 12 14:01:38 2018 New Revision: 327876 URL: https://svnweb.freebsd.org/changeset/base/327876 Log: Workaround Spectre Variant 2 on arm64. We need to handle two cases: 1. One process attacking another process. 2. A process attacking the kernel. For the first case we clear the branch predictor state on context switch between different processes. For the second we do this when taking an instruction abort on a non-userspace address. To clear the branch predictor state a per-CPU function pointer has been added. This is set by the new cpu errata code based on if the CPU is known to be affected. On Cortex-A57, A72, A73, and A75 we call into the PSCI firmware as newer versions of this will clear the branch predictor state for us. It has been reported the ThunderX is unaffected, however the ThunderX2 is vulnerable. The Qualcomm Falkor core is also affected. As FreeBSD doesn't yet run on the ThunderX2 or Falkor no workaround is included for these CPUs. MFC after: 3 days Sponsored by: DARPA, AFRL Differential Revision: https://reviews.freebsd.org/D13812 Modified: head/sys/arm64/arm64/cpu_errata.c head/sys/arm64/arm64/pmap.c head/sys/arm64/arm64/trap.c head/sys/arm64/include/pcpu.h Modified: head/sys/arm64/arm64/cpu_errata.c ============================================================================== --- head/sys/arm64/arm64/cpu_errata.c Fri Jan 12 13:40:50 2018 (r327875) +++ head/sys/arm64/arm64/cpu_errata.c Fri Jan 12 14:01:38 2018 (r327876) @@ -30,6 +30,8 @@ * SUCH DAMAGE. */ +#include "opt_platform.h" + #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); @@ -39,6 +41,10 @@ __FBSDID("$FreeBSD$"); #include <machine/cpu.h> +#ifdef DEV_PSCI +#include <dev/psci/psci.h> +#endif + typedef void (cpu_quirk_install)(void); struct cpu_quirks { cpu_quirk_install *quirk_install; @@ -49,7 +55,36 @@ struct cpu_quirks { static cpu_quirk_install install_psci_bp_hardening; static struct cpu_quirks cpu_quirks[] = { + { + .midr_mask = CPU_IMPL_MASK | CPU_PART_MASK, + .midr_value = CPU_ID_RAW(CPU_IMPL_ARM, CPU_PART_CORTEX_A57,0,0), + .quirk_install = install_psci_bp_hardening, + }, + { + .midr_mask = CPU_IMPL_MASK | CPU_PART_MASK, + .midr_value = CPU_ID_RAW(CPU_IMPL_ARM, CPU_PART_CORTEX_A72,0,0), + .quirk_install = install_psci_bp_hardening, + }, + { + .midr_mask = CPU_IMPL_MASK | CPU_PART_MASK, + .midr_value = CPU_ID_RAW(CPU_IMPL_ARM, CPU_PART_CORTEX_A73,0,0), + .quirk_install = install_psci_bp_hardening, + }, + { + .midr_mask = CPU_IMPL_MASK | CPU_PART_MASK, + .midr_value = CPU_ID_RAW(CPU_IMPL_ARM, CPU_PART_CORTEX_A75,0,0), + .quirk_install = install_psci_bp_hardening, + }, }; + +static void +install_psci_bp_hardening(void) +{ + +#ifdef DEV_PSCI + PCPU_SET(bp_harden, psci_get_version); +#endif +} void install_cpu_errata(void) Modified: head/sys/arm64/arm64/pmap.c ============================================================================== --- head/sys/arm64/arm64/pmap.c Fri Jan 12 13:40:50 2018 (r327875) +++ head/sys/arm64/arm64/pmap.c Fri Jan 12 14:01:38 2018 (r327876) @@ -4663,6 +4663,7 @@ pmap_activate(struct thread *td) struct pcb * pmap_switch(struct thread *old, struct thread *new) { + pcpu_bp_harden bp_harden; struct pcb *pcb; /* Store the new curthread */ @@ -4690,6 +4691,15 @@ pmap_switch(struct thread *old, struct thread *new) "dsb ish \n" "isb \n" : : "r"(new->td_proc->p_md.md_l0addr)); + + /* + * Stop userspace from training the branch predictor against + * other processes. This will call into a CPU specific + * function that clears the branch predictor state. + */ + bp_harden = PCPU_GET(bp_harden); + if (bp_harden != NULL) + bp_harden(); } return (pcb); Modified: head/sys/arm64/arm64/trap.c ============================================================================== --- head/sys/arm64/arm64/trap.c Fri Jan 12 13:40:50 2018 (r327875) +++ head/sys/arm64/arm64/trap.c Fri Jan 12 14:01:38 2018 (r327876) @@ -352,6 +352,7 @@ do_el1h_sync(struct thread *td, struct trapframe *fram void do_el0_sync(struct thread *td, struct trapframe *frame) { + pcpu_bp_harden bp_harden; uint32_t exception; uint64_t esr, far; @@ -363,11 +364,25 @@ do_el0_sync(struct thread *td, struct trapframe *frame esr = frame->tf_esr; exception = ESR_ELx_EXCEPTION(esr); switch (exception) { - case EXCP_UNKNOWN: case EXCP_INSN_ABORT_L: + far = READ_SPECIALREG(far_el1); + + /* + * Userspace may be trying to train the branch predictor to + * attack the kernel. If we are on a CPU affected by this + * call the handler to clear the branch predictor state. + */ + if (far > VM_MAXUSER_ADDRESS) { + bp_harden = PCPU_GET(bp_harden); + if (bp_harden != NULL) + bp_harden(); + } + break; + case EXCP_UNKNOWN: case EXCP_DATA_ABORT_L: case EXCP_DATA_ABORT: far = READ_SPECIALREG(far_el1); + break; } intr_enable(); Modified: head/sys/arm64/include/pcpu.h ============================================================================== --- head/sys/arm64/include/pcpu.h Fri Jan 12 13:40:50 2018 (r327875) +++ head/sys/arm64/include/pcpu.h Fri Jan 12 14:01:38 2018 (r327876) @@ -35,11 +35,14 @@ #define ALT_STACK_SIZE 128 +typedef int (*pcpu_bp_harden)(void); + #define PCPU_MD_FIELDS \ u_int pc_acpi_id; /* ACPI CPU id */ \ u_int pc_midr; /* stored MIDR value */ \ uint64_t pc_clock; \ - char __pad[241] + pcpu_bp_harden pc_bp_harden; \ + char __pad[233] #ifdef _KERNEL
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201801121401.w0CE1cW4058239>