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-head mailing list