diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2022-12-10 10:13:59 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2022-12-10 10:13:59 +0000 |
commit | 841c4c1950f6a92db2da32e3ade853c7555bb4a0 (patch) | |
tree | c318dcfc7df4005f2bbe2a3c105aee07867737e0 /sys/dev/fdt | |
parent | 2f4121f4d8acbdeba004f7565460bd5994219967 (diff) |
Mitigate Spectre-BHB by using core-specific trampoline vectors. On some cores
Spectre-BHB can be mitigated by using a loop that branches a number of times.
For cores where this does not suffice, or where Spectre-V2 needs to be handled
as well, try and call into a new PSCI function that mitigates both Spectre-V2
and Spectre-BHB. Some newer machines, which might not be in anyone's hands
yet, have an instruction (CLRBHB) that clears the BHB. If ECBHB is set, the
BHB isn't vulnerable. If we have CSV2_3/HCXT, it's not vulnerable at all.
No visible performance dropoff on a MacchiatoBin (4xA72) or Lenovo x13s (4xA78C+
4xX1C), but around 2-3% on a LX2K (16xA72) and RK3399 (4xA53+2xA72).
ok kettenis@
Diffstat (limited to 'sys/dev/fdt')
-rw-r--r-- | sys/dev/fdt/psci.c | 45 | ||||
-rw-r--r-- | sys/dev/fdt/pscivar.h | 6 |
2 files changed, 48 insertions, 3 deletions
diff --git a/sys/dev/fdt/psci.c b/sys/dev/fdt/psci.c index a7ebb8d905a..10aaca1a320 100644 --- a/sys/dev/fdt/psci.c +++ b/sys/dev/fdt/psci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: psci.c,v 1.11 2022/07/09 19:27:56 kettenis Exp $ */ +/* $OpenBSD: psci.c,v 1.12 2022/12/10 10:13:58 patrick Exp $ */ /* * Copyright (c) 2016 Jonathan Gray <jsg@openbsd.org> @@ -34,6 +34,7 @@ extern void (*powerdownfn)(void); #define SMCCC_VERSION 0x80000000 #define SMCCC_ARCH_FEATURES 0x80000001 #define SMCCC_ARCH_WORKAROUND_1 0x80008000 +#define SMCCC_ARCH_WORKAROUND_3 0x80003fff #define PSCI_VERSION 0x84000000 #define CPU_OFF 0x84000002 @@ -63,6 +64,7 @@ struct psci_softc { uint32_t sc_cpu_off; uint32_t sc_smccc_version; + uint32_t sc_method; }; struct psci_softc *psci_sc; @@ -108,10 +110,13 @@ psci_attach(struct device *parent, struct device *self, void *aux) uint32_t version; if (OF_getprop(faa->fa_node, "method", method, sizeof(method))) { - if (strcmp(method, "hvc") == 0) + if (strcmp(method, "hvc") == 0) { sc->sc_callfn = hvc_call; - else if (strcmp(method, "smc") == 0) + sc->sc_method = PSCI_METHOD_HVC; + } else if (strcmp(method, "smc") == 0) { sc->sc_callfn = smc_call; + sc->sc_method = PSCI_METHOD_SMC; + } } /* @@ -198,6 +203,14 @@ psci_flush_bp_smccc_arch_workaround_1(void) } void +psci_flush_bp_smccc_arch_workaround_3(void) +{ + struct psci_softc *sc = psci_sc; + + (*sc->sc_callfn)(SMCCC_ARCH_WORKAROUND_3, 0, 0, 0); +} + +void psci_flush_bp(void) { struct psci_softc *sc = psci_sc; @@ -218,6 +231,24 @@ psci_flush_bp(void) } } +int +psci_flush_bp_has_bhb(void) +{ + struct psci_softc *sc = psci_sc; + + /* + * SMCCC 1.1 allows us to detect if the workaround is + * implemented and needed. + */ + if (sc && sc->sc_smccc_version >= 0x10001 && + smccc_arch_features(SMCCC_ARCH_WORKAROUND_3) == 0) { + /* Workaround implemented and needed. */ + return 1; + } + + return 0; +} + int32_t smccc_version(void) { @@ -308,3 +339,11 @@ psci_can_suspend(void) return (sc && sc->sc_system_suspend != 0); } + +int +psci_method(void) +{ + struct psci_softc *sc = psci_sc; + + return sc ? sc->sc_method : PSCI_METHOD_NONE; +} diff --git a/sys/dev/fdt/pscivar.h b/sys/dev/fdt/pscivar.h index 54ff2b1fd88..e8ec062f003 100644 --- a/sys/dev/fdt/pscivar.h +++ b/sys/dev/fdt/pscivar.h @@ -6,11 +6,17 @@ #define PSCI_SUCCESS 0 #define PSCI_NOT_SUPPORTED -1 +#define PSCI_METHOD_NONE 0 +#define PSCI_METHOD_HVC 1 +#define PSCI_METHOD_SMC 2 + int psci_can_suspend(void); int32_t psci_system_suspend(register_t, register_t); int32_t psci_cpu_on(register_t, register_t, register_t); int32_t psci_cpu_off(void); void psci_flush_bp(void); +int psci_flush_bp_has_bhb(void); +int psci_method(void); #endif /* _SYS_DEV_FDT_PSCIVAR_H_ */ |