Page MenuHomeFreeBSD

D13812.id37867.diff
No OneTemporary

D13812.id37867.diff

Index: head/sys/arm64/arm64/cpu_errata.c
===================================================================
--- head/sys/arm64/arm64/cpu_errata.c
+++ head/sys/arm64/arm64/cpu_errata.c
@@ -30,6 +30,8 @@
* SUCH DAMAGE.
*/
+#include "opt_platform.h"
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -39,6 +41,10 @@
#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 @@
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)
Index: head/sys/arm64/arm64/pmap.c
===================================================================
--- head/sys/arm64/arm64/pmap.c
+++ head/sys/arm64/arm64/pmap.c
@@ -4663,6 +4663,7 @@
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 @@
"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);
Index: head/sys/arm64/arm64/trap.c
===================================================================
--- head/sys/arm64/arm64/trap.c
+++ head/sys/arm64/arm64/trap.c
@@ -352,6 +352,7 @@
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 @@
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();
Index: head/sys/arm64/include/pcpu.h
===================================================================
--- head/sys/arm64/include/pcpu.h
+++ head/sys/arm64/include/pcpu.h
@@ -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

File Metadata

Mime Type
text/plain
Expires
Fri, Apr 10, 1:49 PM (11 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31229556
Default Alt Text
D13812.id37867.diff (3 KB)

Event Timeline