6
6
#include <asm/cp15.h>
7
7
#include <asm/cputype.h>
8
8
#include <asm/proc-fns.h>
9
+ #include <asm/spectre.h>
9
10
#include <asm/system_misc.h>
10
11
12
+ #ifdef CONFIG_ARM_PSCI
13
+ static int __maybe_unused spectre_v2_get_cpu_fw_mitigation_state (void )
14
+ {
15
+ struct arm_smccc_res res ;
16
+
17
+ arm_smccc_1_1_invoke (ARM_SMCCC_ARCH_FEATURES_FUNC_ID ,
18
+ ARM_SMCCC_ARCH_WORKAROUND_1 , & res );
19
+
20
+ switch ((int )res .a0 ) {
21
+ case SMCCC_RET_SUCCESS :
22
+ return SPECTRE_MITIGATED ;
23
+
24
+ case SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED :
25
+ return SPECTRE_UNAFFECTED ;
26
+
27
+ default :
28
+ return SPECTRE_VULNERABLE ;
29
+ }
30
+ }
31
+ #else
32
+ static int __maybe_unused spectre_v2_get_cpu_fw_mitigation_state (void )
33
+ {
34
+ return SPECTRE_VULNERABLE ;
35
+ }
36
+ #endif
37
+
11
38
#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
12
39
DEFINE_PER_CPU (harden_branch_predictor_fn_t , harden_branch_predictor_fn );
13
40
@@ -36,13 +63,60 @@ static void __maybe_unused call_hvc_arch_workaround_1(void)
36
63
arm_smccc_1_1_hvc (ARM_SMCCC_ARCH_WORKAROUND_1 , NULL );
37
64
}
38
65
39
- static void cpu_v7_spectre_init ( void )
66
+ static unsigned int spectre_v2_install_workaround ( unsigned int method )
40
67
{
41
68
const char * spectre_v2_method = NULL ;
42
69
int cpu = smp_processor_id ();
43
70
44
71
if (per_cpu (harden_branch_predictor_fn , cpu ))
45
- return ;
72
+ return SPECTRE_MITIGATED ;
73
+
74
+ switch (method ) {
75
+ case SPECTRE_V2_METHOD_BPIALL :
76
+ per_cpu (harden_branch_predictor_fn , cpu ) =
77
+ harden_branch_predictor_bpiall ;
78
+ spectre_v2_method = "BPIALL" ;
79
+ break ;
80
+
81
+ case SPECTRE_V2_METHOD_ICIALLU :
82
+ per_cpu (harden_branch_predictor_fn , cpu ) =
83
+ harden_branch_predictor_iciallu ;
84
+ spectre_v2_method = "ICIALLU" ;
85
+ break ;
86
+
87
+ case SPECTRE_V2_METHOD_HVC :
88
+ per_cpu (harden_branch_predictor_fn , cpu ) =
89
+ call_hvc_arch_workaround_1 ;
90
+ cpu_do_switch_mm = cpu_v7_hvc_switch_mm ;
91
+ spectre_v2_method = "hypervisor" ;
92
+ break ;
93
+
94
+ case SPECTRE_V2_METHOD_SMC :
95
+ per_cpu (harden_branch_predictor_fn , cpu ) =
96
+ call_smc_arch_workaround_1 ;
97
+ cpu_do_switch_mm = cpu_v7_smc_switch_mm ;
98
+ spectre_v2_method = "firmware" ;
99
+ break ;
100
+ }
101
+
102
+ if (spectre_v2_method )
103
+ pr_info ("CPU%u: Spectre v2: using %s workaround\n" ,
104
+ smp_processor_id (), spectre_v2_method );
105
+
106
+ return SPECTRE_MITIGATED ;
107
+ }
108
+ #else
109
+ static unsigned int spectre_v2_install_workaround (unsigned int method )
110
+ {
111
+ pr_info ("CPU%u: Spectre V2: workarounds disabled by configuration\n" );
112
+
113
+ return SPECTRE_VULNERABLE ;
114
+ }
115
+ #endif
116
+
117
+ static void cpu_v7_spectre_v2_init (void )
118
+ {
119
+ unsigned int state , method = 0 ;
46
120
47
121
switch (read_cpuid_part ()) {
48
122
case ARM_CPU_PART_CORTEX_A8 :
@@ -51,68 +125,57 @@ static void cpu_v7_spectre_init(void)
51
125
case ARM_CPU_PART_CORTEX_A17 :
52
126
case ARM_CPU_PART_CORTEX_A73 :
53
127
case ARM_CPU_PART_CORTEX_A75 :
54
- per_cpu (harden_branch_predictor_fn , cpu ) =
55
- harden_branch_predictor_bpiall ;
56
- spectre_v2_method = "BPIALL" ;
128
+ state = SPECTRE_MITIGATED ;
129
+ method = SPECTRE_V2_METHOD_BPIALL ;
57
130
break ;
58
131
59
132
case ARM_CPU_PART_CORTEX_A15 :
60
133
case ARM_CPU_PART_BRAHMA_B15 :
61
- per_cpu (harden_branch_predictor_fn , cpu ) =
62
- harden_branch_predictor_iciallu ;
63
- spectre_v2_method = "ICIALLU" ;
134
+ state = SPECTRE_MITIGATED ;
135
+ method = SPECTRE_V2_METHOD_ICIALLU ;
64
136
break ;
65
137
66
- #ifdef CONFIG_ARM_PSCI
67
138
case ARM_CPU_PART_BRAHMA_B53 :
68
139
/* Requires no workaround */
140
+ state = SPECTRE_UNAFFECTED ;
69
141
break ;
142
+
70
143
default :
71
144
/* Other ARM CPUs require no workaround */
72
- if (read_cpuid_implementor () == ARM_CPU_IMP_ARM )
145
+ if (read_cpuid_implementor () == ARM_CPU_IMP_ARM ) {
146
+ state = SPECTRE_UNAFFECTED ;
73
147
break ;
148
+ }
149
+
74
150
fallthrough ;
75
- /* Cortex A57/A72 require firmware workaround */
76
- case ARM_CPU_PART_CORTEX_A57 :
77
- case ARM_CPU_PART_CORTEX_A72 : {
78
- struct arm_smccc_res res ;
79
151
80
- arm_smccc_1_1_invoke (ARM_SMCCC_ARCH_FEATURES_FUNC_ID ,
81
- ARM_SMCCC_ARCH_WORKAROUND_1 , & res );
82
- if ((int )res .a0 != 0 )
83
- return ;
152
+ /* Cortex A57/A72 require firmware workaround */
153
+ case ARM_CPU_PART_CORTEX_A57 :
154
+ case ARM_CPU_PART_CORTEX_A72 :
155
+ state = spectre_v2_get_cpu_fw_mitigation_state ();
156
+ if (state != SPECTRE_MITIGATED )
157
+ break ;
84
158
85
159
switch (arm_smccc_1_1_get_conduit ()) {
86
160
case SMCCC_CONDUIT_HVC :
87
- per_cpu (harden_branch_predictor_fn , cpu ) =
88
- call_hvc_arch_workaround_1 ;
89
- cpu_do_switch_mm = cpu_v7_hvc_switch_mm ;
90
- spectre_v2_method = "hypervisor" ;
161
+ method = SPECTRE_V2_METHOD_HVC ;
91
162
break ;
92
163
93
164
case SMCCC_CONDUIT_SMC :
94
- per_cpu (harden_branch_predictor_fn , cpu ) =
95
- call_smc_arch_workaround_1 ;
96
- cpu_do_switch_mm = cpu_v7_smc_switch_mm ;
97
- spectre_v2_method = "firmware" ;
165
+ method = SPECTRE_V2_METHOD_SMC ;
98
166
break ;
99
167
100
168
default :
169
+ state = SPECTRE_VULNERABLE ;
101
170
break ;
102
171
}
103
172
}
104
- #endif
105
- }
106
173
107
- if (spectre_v2_method )
108
- pr_info ("CPU%u: Spectre v2: using %s workaround\n" ,
109
- smp_processor_id (), spectre_v2_method );
110
- }
111
- #else
112
- static void cpu_v7_spectre_init (void )
113
- {
174
+ if (state == SPECTRE_MITIGATED )
175
+ state = spectre_v2_install_workaround (method );
176
+
177
+ spectre_v2_update_state (state , method );
114
178
}
115
- #endif
116
179
117
180
static __maybe_unused bool cpu_v7_check_auxcr_set (bool * warned ,
118
181
u32 mask , const char * msg )
@@ -142,16 +205,16 @@ static bool check_spectre_auxcr(bool *warned, u32 bit)
142
205
void cpu_v7_ca8_ibe (void )
143
206
{
144
207
if (check_spectre_auxcr (this_cpu_ptr (& spectre_warned ), BIT (6 )))
145
- cpu_v7_spectre_init ();
208
+ cpu_v7_spectre_v2_init ();
146
209
}
147
210
148
211
void cpu_v7_ca15_ibe (void )
149
212
{
150
213
if (check_spectre_auxcr (this_cpu_ptr (& spectre_warned ), BIT (0 )))
151
- cpu_v7_spectre_init ();
214
+ cpu_v7_spectre_v2_init ();
152
215
}
153
216
154
217
void cpu_v7_bugs_init (void )
155
218
{
156
- cpu_v7_spectre_init ();
219
+ cpu_v7_spectre_v2_init ();
157
220
}
0 commit comments