root/arch/arm/mm/proc-v7-bugs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. harden_branch_predictor_bpiall
  2. harden_branch_predictor_iciallu
  3. call_smc_arch_workaround_1
  4. call_hvc_arch_workaround_1
  5. cpu_v7_spectre_init
  6. cpu_v7_spectre_init
  7. cpu_v7_check_auxcr_set
  8. check_spectre_auxcr
  9. cpu_v7_ca8_ibe
  10. cpu_v7_ca15_ibe
  11. cpu_v7_bugs_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include <linux/arm-smccc.h>
   3 #include <linux/kernel.h>
   4 #include <linux/psci.h>
   5 #include <linux/smp.h>
   6 
   7 #include <asm/cp15.h>
   8 #include <asm/cputype.h>
   9 #include <asm/proc-fns.h>
  10 #include <asm/system_misc.h>
  11 
  12 #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
  13 DEFINE_PER_CPU(harden_branch_predictor_fn_t, harden_branch_predictor_fn);
  14 
  15 extern void cpu_v7_iciallu_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm);
  16 extern void cpu_v7_bpiall_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm);
  17 extern void cpu_v7_smc_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm);
  18 extern void cpu_v7_hvc_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm);
  19 
  20 static void harden_branch_predictor_bpiall(void)
  21 {
  22         write_sysreg(0, BPIALL);
  23 }
  24 
  25 static void harden_branch_predictor_iciallu(void)
  26 {
  27         write_sysreg(0, ICIALLU);
  28 }
  29 
  30 static void __maybe_unused call_smc_arch_workaround_1(void)
  31 {
  32         arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
  33 }
  34 
  35 static void __maybe_unused call_hvc_arch_workaround_1(void)
  36 {
  37         arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
  38 }
  39 
  40 static void cpu_v7_spectre_init(void)
  41 {
  42         const char *spectre_v2_method = NULL;
  43         int cpu = smp_processor_id();
  44 
  45         if (per_cpu(harden_branch_predictor_fn, cpu))
  46                 return;
  47 
  48         switch (read_cpuid_part()) {
  49         case ARM_CPU_PART_CORTEX_A8:
  50         case ARM_CPU_PART_CORTEX_A9:
  51         case ARM_CPU_PART_CORTEX_A12:
  52         case ARM_CPU_PART_CORTEX_A17:
  53         case ARM_CPU_PART_CORTEX_A73:
  54         case ARM_CPU_PART_CORTEX_A75:
  55                 per_cpu(harden_branch_predictor_fn, cpu) =
  56                         harden_branch_predictor_bpiall;
  57                 spectre_v2_method = "BPIALL";
  58                 break;
  59 
  60         case ARM_CPU_PART_CORTEX_A15:
  61         case ARM_CPU_PART_BRAHMA_B15:
  62                 per_cpu(harden_branch_predictor_fn, cpu) =
  63                         harden_branch_predictor_iciallu;
  64                 spectre_v2_method = "ICIALLU";
  65                 break;
  66 
  67 #ifdef CONFIG_ARM_PSCI
  68         case ARM_CPU_PART_BRAHMA_B53:
  69                 /* Requires no workaround */
  70                 break;
  71         default:
  72                 /* Other ARM CPUs require no workaround */
  73                 if (read_cpuid_implementor() == ARM_CPU_IMP_ARM)
  74                         break;
  75                 /* fallthrough */
  76                 /* Cortex A57/A72 require firmware workaround */
  77         case ARM_CPU_PART_CORTEX_A57:
  78         case ARM_CPU_PART_CORTEX_A72: {
  79                 struct arm_smccc_res res;
  80 
  81                 if (psci_ops.smccc_version == SMCCC_VERSION_1_0)
  82                         break;
  83 
  84                 switch (psci_ops.conduit) {
  85                 case PSCI_CONDUIT_HVC:
  86                         arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
  87                                           ARM_SMCCC_ARCH_WORKAROUND_1, &res);
  88                         if ((int)res.a0 != 0)
  89                                 break;
  90                         per_cpu(harden_branch_predictor_fn, cpu) =
  91                                 call_hvc_arch_workaround_1;
  92                         cpu_do_switch_mm = cpu_v7_hvc_switch_mm;
  93                         spectre_v2_method = "hypervisor";
  94                         break;
  95 
  96                 case PSCI_CONDUIT_SMC:
  97                         arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
  98                                           ARM_SMCCC_ARCH_WORKAROUND_1, &res);
  99                         if ((int)res.a0 != 0)
 100                                 break;
 101                         per_cpu(harden_branch_predictor_fn, cpu) =
 102                                 call_smc_arch_workaround_1;
 103                         cpu_do_switch_mm = cpu_v7_smc_switch_mm;
 104                         spectre_v2_method = "firmware";
 105                         break;
 106 
 107                 default:
 108                         break;
 109                 }
 110         }
 111 #endif
 112         }
 113 
 114         if (spectre_v2_method)
 115                 pr_info("CPU%u: Spectre v2: using %s workaround\n",
 116                         smp_processor_id(), spectre_v2_method);
 117 }
 118 #else
 119 static void cpu_v7_spectre_init(void)
 120 {
 121 }
 122 #endif
 123 
 124 static __maybe_unused bool cpu_v7_check_auxcr_set(bool *warned,
 125                                                   u32 mask, const char *msg)
 126 {
 127         u32 aux_cr;
 128 
 129         asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (aux_cr));
 130 
 131         if ((aux_cr & mask) != mask) {
 132                 if (!*warned)
 133                         pr_err("CPU%u: %s", smp_processor_id(), msg);
 134                 *warned = true;
 135                 return false;
 136         }
 137         return true;
 138 }
 139 
 140 static DEFINE_PER_CPU(bool, spectre_warned);
 141 
 142 static bool check_spectre_auxcr(bool *warned, u32 bit)
 143 {
 144         return IS_ENABLED(CONFIG_HARDEN_BRANCH_PREDICTOR) &&
 145                 cpu_v7_check_auxcr_set(warned, bit,
 146                                        "Spectre v2: firmware did not set auxiliary control register IBE bit, system vulnerable\n");
 147 }
 148 
 149 void cpu_v7_ca8_ibe(void)
 150 {
 151         if (check_spectre_auxcr(this_cpu_ptr(&spectre_warned), BIT(6)))
 152                 cpu_v7_spectre_init();
 153 }
 154 
 155 void cpu_v7_ca15_ibe(void)
 156 {
 157         if (check_spectre_auxcr(this_cpu_ptr(&spectre_warned), BIT(0)))
 158                 cpu_v7_spectre_init();
 159 }
 160 
 161 void cpu_v7_bugs_init(void)
 162 {
 163         cpu_v7_spectre_init();
 164 }

/* [<][>][^][v][top][bottom][index][help] */