@@ -186,13 +186,44 @@ static void kvm_psci_system_reset(struct kvm_vcpu *vcpu)
186
186
kvm_prepare_system_event (vcpu , KVM_SYSTEM_EVENT_RESET );
187
187
}
188
188
189
+ static void kvm_psci_narrow_to_32bit (struct kvm_vcpu * vcpu )
190
+ {
191
+ int i ;
192
+
193
+ /*
194
+ * Zero the input registers' upper 32 bits. They will be fully
195
+ * zeroed on exit, so we're fine changing them in place.
196
+ */
197
+ for (i = 1 ; i < 4 ; i ++ )
198
+ vcpu_set_reg (vcpu , i , lower_32_bits (vcpu_get_reg (vcpu , i )));
199
+ }
200
+
201
+ static unsigned long kvm_psci_check_allowed_function (struct kvm_vcpu * vcpu , u32 fn )
202
+ {
203
+ switch (fn ) {
204
+ case PSCI_0_2_FN64_CPU_SUSPEND :
205
+ case PSCI_0_2_FN64_CPU_ON :
206
+ case PSCI_0_2_FN64_AFFINITY_INFO :
207
+ /* Disallow these functions for 32bit guests */
208
+ if (vcpu_mode_is_32bit (vcpu ))
209
+ return PSCI_RET_NOT_SUPPORTED ;
210
+ break ;
211
+ }
212
+
213
+ return 0 ;
214
+ }
215
+
189
216
static int kvm_psci_0_2_call (struct kvm_vcpu * vcpu )
190
217
{
191
218
struct kvm * kvm = vcpu -> kvm ;
192
219
u32 psci_fn = smccc_get_function (vcpu );
193
220
unsigned long val ;
194
221
int ret = 1 ;
195
222
223
+ val = kvm_psci_check_allowed_function (vcpu , psci_fn );
224
+ if (val )
225
+ goto out ;
226
+
196
227
switch (psci_fn ) {
197
228
case PSCI_0_2_FN_PSCI_VERSION :
198
229
/*
@@ -210,12 +241,16 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
210
241
val = PSCI_RET_SUCCESS ;
211
242
break ;
212
243
case PSCI_0_2_FN_CPU_ON :
244
+ kvm_psci_narrow_to_32bit (vcpu );
245
+ fallthrough ;
213
246
case PSCI_0_2_FN64_CPU_ON :
214
247
mutex_lock (& kvm -> lock );
215
248
val = kvm_psci_vcpu_on (vcpu );
216
249
mutex_unlock (& kvm -> lock );
217
250
break ;
218
251
case PSCI_0_2_FN_AFFINITY_INFO :
252
+ kvm_psci_narrow_to_32bit (vcpu );
253
+ fallthrough ;
219
254
case PSCI_0_2_FN64_AFFINITY_INFO :
220
255
val = kvm_psci_vcpu_affinity_info (vcpu );
221
256
break ;
@@ -256,6 +291,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
256
291
break ;
257
292
}
258
293
294
+ out :
259
295
smccc_set_retval (vcpu , val , 0 , 0 , 0 );
260
296
return ret ;
261
297
}
@@ -273,6 +309,10 @@ static int kvm_psci_1_0_call(struct kvm_vcpu *vcpu)
273
309
break ;
274
310
case PSCI_1_0_FN_PSCI_FEATURES :
275
311
feature = smccc_get_arg1 (vcpu );
312
+ val = kvm_psci_check_allowed_function (vcpu , feature );
313
+ if (val )
314
+ break ;
315
+
276
316
switch (feature ) {
277
317
case PSCI_0_2_FN_PSCI_VERSION :
278
318
case PSCI_0_2_FN_CPU_SUSPEND :
0 commit comments