svn commit: r327876 - in head/sys/arm64: arm64 include
Marcin Wojtas
mw at semihalf.com
Fri Jan 12 14:10:59 UTC 2018
Hi Andrew,
2018-01-12 15:01 GMT+01:00 Andrew Turner <andrew at freebsd.org>:
> 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.
Regardless ThunderX2 / Falkor work-arounds, do I understand correctly
that pure CA72 machines, such as Marvell Armada 7k/8k are immune to
Variant 2 now?
Thanks,
Marcin
>
> 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
>
>
More information about the svn-src-all
mailing list