1
1
// SPDX-License-Identifier: GPL-2.0
2
+ #include <linux/arm-smccc.h>
2
3
#include <linux/kernel.h>
4
+ #include <linux/psci.h>
3
5
#include <linux/smp.h>
4
6
5
7
#include <asm/cp15.h>
6
8
#include <asm/cputype.h>
9
+ #include <asm/proc-fns.h>
7
10
#include <asm/system_misc.h>
8
11
9
12
#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
10
13
DEFINE_PER_CPU (harden_branch_predictor_fn_t , harden_branch_predictor_fn );
11
14
15
+ extern void cpu_v7_smc_switch_mm (phys_addr_t pgd_phys , struct mm_struct * mm );
16
+ extern void cpu_v7_hvc_switch_mm (phys_addr_t pgd_phys , struct mm_struct * mm );
17
+
12
18
static void harden_branch_predictor_bpiall (void )
13
19
{
14
20
write_sysreg (0 , BPIALL );
@@ -19,6 +25,16 @@ static void harden_branch_predictor_iciallu(void)
19
25
write_sysreg (0 , ICIALLU );
20
26
}
21
27
28
+ static void __maybe_unused call_smc_arch_workaround_1 (void )
29
+ {
30
+ arm_smccc_1_1_smc (ARM_SMCCC_ARCH_WORKAROUND_1 , NULL );
31
+ }
32
+
33
+ static void __maybe_unused call_hvc_arch_workaround_1 (void )
34
+ {
35
+ arm_smccc_1_1_hvc (ARM_SMCCC_ARCH_WORKAROUND_1 , NULL );
36
+ }
37
+
22
38
static void cpu_v7_spectre_init (void )
23
39
{
24
40
const char * spectre_v2_method = NULL ;
@@ -45,7 +61,51 @@ static void cpu_v7_spectre_init(void)
45
61
harden_branch_predictor_iciallu ;
46
62
spectre_v2_method = "ICIALLU" ;
47
63
break ;
64
+
65
+ #ifdef CONFIG_ARM_PSCI
66
+ default :
67
+ /* Other ARM CPUs require no workaround */
68
+ if (read_cpuid_implementor () == ARM_CPU_IMP_ARM )
69
+ break ;
70
+ /* fallthrough */
71
+ /* Cortex A57/A72 require firmware workaround */
72
+ case ARM_CPU_PART_CORTEX_A57 :
73
+ case ARM_CPU_PART_CORTEX_A72 : {
74
+ struct arm_smccc_res res ;
75
+
76
+ if (psci_ops .smccc_version == SMCCC_VERSION_1_0 )
77
+ break ;
78
+
79
+ switch (psci_ops .conduit ) {
80
+ case PSCI_CONDUIT_HVC :
81
+ arm_smccc_1_1_hvc (ARM_SMCCC_ARCH_FEATURES_FUNC_ID ,
82
+ ARM_SMCCC_ARCH_WORKAROUND_1 , & res );
83
+ if ((int )res .a0 != 0 )
84
+ break ;
85
+ per_cpu (harden_branch_predictor_fn , cpu ) =
86
+ call_hvc_arch_workaround_1 ;
87
+ processor .switch_mm = cpu_v7_hvc_switch_mm ;
88
+ spectre_v2_method = "hypervisor" ;
89
+ break ;
90
+
91
+ case PSCI_CONDUIT_SMC :
92
+ arm_smccc_1_1_smc (ARM_SMCCC_ARCH_FEATURES_FUNC_ID ,
93
+ ARM_SMCCC_ARCH_WORKAROUND_1 , & res );
94
+ if ((int )res .a0 != 0 )
95
+ break ;
96
+ per_cpu (harden_branch_predictor_fn , cpu ) =
97
+ call_smc_arch_workaround_1 ;
98
+ processor .switch_mm = cpu_v7_smc_switch_mm ;
99
+ spectre_v2_method = "firmware" ;
100
+ break ;
101
+
102
+ default :
103
+ break ;
104
+ }
48
105
}
106
+ #endif
107
+ }
108
+
49
109
if (spectre_v2_method )
50
110
pr_info ("CPU%u: Spectre v2: using %s workaround\n" ,
51
111
smp_processor_id (), spectre_v2_method );
0 commit comments