diff options
-rw-r--r-- | sys/arch/arm/arm/cpu.c | 45 | ||||
-rw-r--r-- | sys/arch/arm/arm/cpufunc_asm_armv7.S | 13 | ||||
-rw-r--r-- | sys/arch/arm/arm/fault.c | 13 | ||||
-rw-r--r-- | sys/arch/arm/include/cpu.h | 4 | ||||
-rw-r--r-- | sys/arch/arm/include/cpufunc.h | 5 |
5 files changed, 73 insertions, 7 deletions
diff --git a/sys/arch/arm/arm/cpu.c b/sys/arch/arm/arm/cpu.c index d51f20e9849..5b6a9ce1f8a 100644 --- a/sys/arch/arm/arm/cpu.c +++ b/sys/arch/arm/arm/cpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.c,v 1.43 2017/12/29 14:45:15 kettenis Exp $ */ +/* $OpenBSD: cpu.c,v 1.44 2018/01/15 14:11:16 kettenis Exp $ */ /* $NetBSD: cpu.c,v 1.56 2004/04/14 04:01:49 bsh Exp $ */ @@ -257,6 +257,49 @@ identify_arm_cpu(struct device *dv, struct cpu_info *ci) printf("\n"); + /* + * Some ARM processors are vulnerable to branch target + * injection attacks. + */ + switch (cpuid & CPU_ID_CORTEX_MASK) { + case CPU_ID_CORTEX_A5: + case CPU_ID_CORTEX_A7: + case CPU_ID_CORTEX_A32: + case CPU_ID_CORTEX_A35: + case CPU_ID_CORTEX_A53: + case CPU_ID_CORTEX_A55: + /* Not vulnerable; no need to flush. */ + ci->ci_flush_bp = cpufunc_nullop; + break; + case CPU_ID_CORTEX_A8: + case CPU_ID_CORTEX_A9: + case CPU_ID_CORTEX_A12: + case CPU_ID_CORTEX_A17: + case CPU_ID_CORTEX_A73: + case CPU_ID_CORTEX_A75: + default: + /* Vulnerable; flush BP cache. */ + ci->ci_flush_bp = armv7_flush_bp; + break; + case CPU_ID_CORTEX_A15: + case CPU_ID_CORTEX_A72: + /* + * Vulnerable; BPIALL is "not effective" so must use + * ICIALLU and hope the firmware set the magic bit in + * the ACTLR that actually forces a BTB flush. + */ + ci->ci_flush_bp = cortex_a15_flush_bp; + break; + case CPU_ID_CORTEX_A57: + /* + * Vulnerable; must disable and enable the MMU which + * can be done by a PSCI call on firmware with the + * appropriate fixes. Punt for now. + */ + ci->ci_flush_bp = cpufunc_nullop; + break; + } + /* Print cache info. */ if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0) goto skip_pcache; diff --git a/sys/arch/arm/arm/cpufunc_asm_armv7.S b/sys/arch/arm/arm/cpufunc_asm_armv7.S index 05679df15fa..20e9db1435d 100644 --- a/sys/arch/arm/arm/cpufunc_asm_armv7.S +++ b/sys/arch/arm/arm/cpufunc_asm_armv7.S @@ -1,4 +1,4 @@ -/* $OpenBSD: cpufunc_asm_armv7.S,v 1.14 2016/08/15 21:08:56 kettenis Exp $ */ +/* $OpenBSD: cpufunc_asm_armv7.S,v 1.15 2018/01/15 14:11:16 kettenis Exp $ */ /* * Copyright (c) 2008 Dale Rahn <drahn@openbsd.org> * @@ -209,6 +209,17 @@ ENTRY(armv7_dcache_inv_range) /* + * BTB functions. + */ +ENTRY(armv7_flush_bp) + mcr CP15_BPIALL + mov pc, lr + +ENTRY(cortex_a15_flush_bp) + mcr CP15_ICIALLU /* Heavy hammer; BPIALL is a no-op */ + mov pc, lr + +/* * Context switch. * * These is the CPU-specific parts of the context switcher cpu_switch() diff --git a/sys/arch/arm/arm/fault.c b/sys/arch/arm/arm/fault.c index 47f308121d1..96c0e1b54a5 100644 --- a/sys/arch/arm/arm/fault.c +++ b/sys/arch/arm/arm/fault.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fault.c,v 1.30 2017/09/08 05:36:51 deraadt Exp $ */ +/* $OpenBSD: fault.c,v 1.31 2018/01/15 14:11:16 kettenis Exp $ */ /* $NetBSD: fault.c,v 1.46 2004/01/21 15:39:21 skrll Exp $ */ /* @@ -209,6 +209,15 @@ data_abort_handler(trapframe_t *tf) goto out; } + va = trunc_page((vaddr_t)far); + + /* + * Flush BP cache on processors that are vulnerable to branch + * target injection attacks if access is outside user space. + */ + if (va < VM_MIN_ADDRESS || va >= VM_MAX_ADDRESS) + curcpu()->ci_flush_bp(); + /* * At this point, we're dealing with one of the following data aborts: * @@ -256,8 +265,6 @@ data_abort_handler(trapframe_t *tf) dab_fatal(tf, fsr, far, p, NULL); } - va = trunc_page((vaddr_t)far); - /* * It is only a kernel address space fault iff: * 1. user == 0 and diff --git a/sys/arch/arm/include/cpu.h b/sys/arch/arm/include/cpu.h index 12df5df0146..2d783aaf374 100644 --- a/sys/arch/arm/include/cpu.h +++ b/sys/arch/arm/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.48 2017/08/12 13:18:48 tedu Exp $ */ +/* $OpenBSD: cpu.h,v 1.49 2018/01/15 14:11:16 kettenis Exp $ */ /* $NetBSD: cpu.h,v 1.34 2003/06/23 11:01:08 martin Exp $ */ /* @@ -206,6 +206,8 @@ struct cpu_info { #ifdef GPROF struct gmonparam *ci_gmon; #endif + + void (*ci_flush_bp)(void); }; extern struct cpu_info cpu_info_primary; diff --git a/sys/arch/arm/include/cpufunc.h b/sys/arch/arm/include/cpufunc.h index 65da821b49a..b58e2487dfb 100644 --- a/sys/arch/arm/include/cpufunc.h +++ b/sys/arch/arm/include/cpufunc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpufunc.h,v 1.29 2017/01/06 00:06:02 jsg Exp $ */ +/* $OpenBSD: cpufunc.h,v 1.30 2018/01/15 14:11:16 kettenis Exp $ */ /* $NetBSD: cpufunc.h,v 1.29 2003/09/06 09:08:35 rearnsha Exp $ */ /* @@ -231,6 +231,9 @@ void armv7_tlb_flushI (void); void armv7_tlb_flushD (void); void armv7_tlb_flushD_SE (u_int va); +void armv7_flush_bp(void); +void cortex_a15_flush_bp(void); + void armv7_drain_writebuf (void); void armv7_cpu_sleep (int mode); |