summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/arm/arm/cpu.c45
-rw-r--r--sys/arch/arm/arm/cpufunc_asm_armv7.S13
-rw-r--r--sys/arch/arm/arm/fault.c13
-rw-r--r--sys/arch/arm/include/cpu.h4
-rw-r--r--sys/arch/arm/include/cpufunc.h5
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);