@@ -246,9 +246,10 @@ static int try_handle_skey(struct kvm_vcpu *vcpu)
246
246
247
247
static int handle_iske (struct kvm_vcpu * vcpu )
248
248
{
249
- unsigned long addr ;
249
+ unsigned long gaddr , vmaddr ;
250
250
unsigned char key ;
251
251
int reg1 , reg2 ;
252
+ bool unlocked ;
252
253
int rc ;
253
254
254
255
vcpu -> stat .instruction_iske ++ ;
@@ -262,27 +263,38 @@ static int handle_iske(struct kvm_vcpu *vcpu)
262
263
263
264
kvm_s390_get_regs_rre (vcpu , & reg1 , & reg2 );
264
265
265
- addr = vcpu -> run -> s .regs .gprs [reg2 ] & PAGE_MASK ;
266
- addr = kvm_s390_logical_to_effective (vcpu , addr );
267
- addr = kvm_s390_real_to_abs (vcpu , addr );
268
- addr = gfn_to_hva (vcpu -> kvm , gpa_to_gfn (addr ));
269
- if (kvm_is_error_hva (addr ))
266
+ gaddr = vcpu -> run -> s .regs .gprs [reg2 ] & PAGE_MASK ;
267
+ gaddr = kvm_s390_logical_to_effective (vcpu , gaddr );
268
+ gaddr = kvm_s390_real_to_abs (vcpu , gaddr );
269
+ vmaddr = gfn_to_hva (vcpu -> kvm , gpa_to_gfn (gaddr ));
270
+ if (kvm_is_error_hva (vmaddr ))
270
271
return kvm_s390_inject_program_int (vcpu , PGM_ADDRESSING );
271
-
272
+ retry :
273
+ unlocked = false;
272
274
down_read (& current -> mm -> mmap_sem );
273
- rc = get_guest_storage_key (current -> mm , addr , & key );
274
- up_read (& current -> mm -> mmap_sem );
275
+ rc = get_guest_storage_key (current -> mm , vmaddr , & key );
276
+
277
+ if (rc ) {
278
+ rc = fixup_user_fault (current , current -> mm , vmaddr ,
279
+ FAULT_FLAG_WRITE , & unlocked );
280
+ if (!rc ) {
281
+ up_read (& current -> mm -> mmap_sem );
282
+ goto retry ;
283
+ }
284
+ }
275
285
if (rc )
276
286
return kvm_s390_inject_program_int (vcpu , PGM_ADDRESSING );
287
+ up_read (& current -> mm -> mmap_sem );
277
288
vcpu -> run -> s .regs .gprs [reg1 ] &= ~0xff ;
278
289
vcpu -> run -> s .regs .gprs [reg1 ] |= key ;
279
290
return 0 ;
280
291
}
281
292
282
293
static int handle_rrbe (struct kvm_vcpu * vcpu )
283
294
{
284
- unsigned long addr ;
295
+ unsigned long vmaddr , gaddr ;
285
296
int reg1 , reg2 ;
297
+ bool unlocked ;
286
298
int rc ;
287
299
288
300
vcpu -> stat .instruction_rrbe ++ ;
@@ -296,19 +308,27 @@ static int handle_rrbe(struct kvm_vcpu *vcpu)
296
308
297
309
kvm_s390_get_regs_rre (vcpu , & reg1 , & reg2 );
298
310
299
- addr = vcpu -> run -> s .regs .gprs [reg2 ] & PAGE_MASK ;
300
- addr = kvm_s390_logical_to_effective (vcpu , addr );
301
- addr = kvm_s390_real_to_abs (vcpu , addr );
302
- addr = gfn_to_hva (vcpu -> kvm , gpa_to_gfn (addr ));
303
- if (kvm_is_error_hva (addr ))
311
+ gaddr = vcpu -> run -> s .regs .gprs [reg2 ] & PAGE_MASK ;
312
+ gaddr = kvm_s390_logical_to_effective (vcpu , gaddr );
313
+ gaddr = kvm_s390_real_to_abs (vcpu , gaddr );
314
+ vmaddr = gfn_to_hva (vcpu -> kvm , gpa_to_gfn (gaddr ));
315
+ if (kvm_is_error_hva (vmaddr ))
304
316
return kvm_s390_inject_program_int (vcpu , PGM_ADDRESSING );
305
-
317
+ retry :
318
+ unlocked = false;
306
319
down_read (& current -> mm -> mmap_sem );
307
- rc = reset_guest_reference_bit (current -> mm , addr );
308
- up_read (& current -> mm -> mmap_sem );
320
+ rc = reset_guest_reference_bit (current -> mm , vmaddr );
321
+ if (rc < 0 ) {
322
+ rc = fixup_user_fault (current , current -> mm , vmaddr ,
323
+ FAULT_FLAG_WRITE , & unlocked );
324
+ if (!rc ) {
325
+ up_read (& current -> mm -> mmap_sem );
326
+ goto retry ;
327
+ }
328
+ }
309
329
if (rc < 0 )
310
330
return kvm_s390_inject_program_int (vcpu , PGM_ADDRESSING );
311
-
331
+ up_read ( & current -> mm -> mmap_sem );
312
332
kvm_s390_set_psw_cc (vcpu , rc );
313
333
return 0 ;
314
334
}
@@ -323,6 +343,7 @@ static int handle_sske(struct kvm_vcpu *vcpu)
323
343
unsigned long start , end ;
324
344
unsigned char key , oldkey ;
325
345
int reg1 , reg2 ;
346
+ bool unlocked ;
326
347
int rc ;
327
348
328
349
vcpu -> stat .instruction_sske ++ ;
@@ -355,19 +376,28 @@ static int handle_sske(struct kvm_vcpu *vcpu)
355
376
}
356
377
357
378
while (start != end ) {
358
- unsigned long addr = gfn_to_hva (vcpu -> kvm , gpa_to_gfn (start ));
379
+ unsigned long vmaddr = gfn_to_hva (vcpu -> kvm , gpa_to_gfn (start ));
380
+ unlocked = false;
359
381
360
- if (kvm_is_error_hva (addr ))
382
+ if (kvm_is_error_hva (vmaddr ))
361
383
return kvm_s390_inject_program_int (vcpu , PGM_ADDRESSING );
362
384
363
385
down_read (& current -> mm -> mmap_sem );
364
- rc = cond_set_guest_storage_key (current -> mm , addr , key , & oldkey ,
386
+ rc = cond_set_guest_storage_key (current -> mm , vmaddr , key , & oldkey ,
365
387
m3 & SSKE_NQ , m3 & SSKE_MR ,
366
388
m3 & SSKE_MC );
367
- up_read (& current -> mm -> mmap_sem );
368
- if (rc < 0 )
389
+
390
+ if (rc < 0 ) {
391
+ rc = fixup_user_fault (current , current -> mm , vmaddr ,
392
+ FAULT_FLAG_WRITE , & unlocked );
393
+ rc = !rc ? - EAGAIN : rc ;
394
+ }
395
+ if (rc == - EFAULT )
369
396
return kvm_s390_inject_program_int (vcpu , PGM_ADDRESSING );
370
- start += PAGE_SIZE ;
397
+
398
+ up_read (& current -> mm -> mmap_sem );
399
+ if (rc >= 0 )
400
+ start += PAGE_SIZE ;
371
401
}
372
402
373
403
if (m3 & (SSKE_MC | SSKE_MR )) {
@@ -948,15 +978,16 @@ static int handle_pfmf(struct kvm_vcpu *vcpu)
948
978
}
949
979
950
980
while (start != end ) {
951
- unsigned long useraddr ;
981
+ unsigned long vmaddr ;
982
+ bool unlocked = false;
952
983
953
984
/* Translate guest address to host address */
954
- useraddr = gfn_to_hva (vcpu -> kvm , gpa_to_gfn (start ));
955
- if (kvm_is_error_hva (useraddr ))
985
+ vmaddr = gfn_to_hva (vcpu -> kvm , gpa_to_gfn (start ));
986
+ if (kvm_is_error_hva (vmaddr ))
956
987
return kvm_s390_inject_program_int (vcpu , PGM_ADDRESSING );
957
988
958
989
if (vcpu -> run -> s .regs .gprs [reg1 ] & PFMF_CF ) {
959
- if (clear_user ((void __user * )useraddr , PAGE_SIZE ))
990
+ if (clear_user ((void __user * )vmaddr , PAGE_SIZE ))
960
991
return kvm_s390_inject_program_int (vcpu , PGM_ADDRESSING );
961
992
}
962
993
@@ -966,14 +997,20 @@ static int handle_pfmf(struct kvm_vcpu *vcpu)
966
997
if (rc )
967
998
return rc ;
968
999
down_read (& current -> mm -> mmap_sem );
969
- rc = cond_set_guest_storage_key (current -> mm , useraddr ,
1000
+ rc = cond_set_guest_storage_key (current -> mm , vmaddr ,
970
1001
key , NULL , nq , mr , mc );
971
- up_read (& current -> mm -> mmap_sem );
972
- if (rc < 0 )
1002
+ if (rc < 0 ) {
1003
+ rc = fixup_user_fault (current , current -> mm , vmaddr ,
1004
+ FAULT_FLAG_WRITE , & unlocked );
1005
+ rc = !rc ? - EAGAIN : rc ;
1006
+ }
1007
+ if (rc == - EFAULT )
973
1008
return kvm_s390_inject_program_int (vcpu , PGM_ADDRESSING );
974
- }
975
1009
976
- start += PAGE_SIZE ;
1010
+ up_read (& current -> mm -> mmap_sem );
1011
+ if (rc >= 0 )
1012
+ start += PAGE_SIZE ;
1013
+ }
977
1014
}
978
1015
if (vcpu -> run -> s .regs .gprs [reg1 ] & PFMF_FSC ) {
979
1016
if (psw_bits (vcpu -> arch .sie_block -> gpsw ).eaba == PSW_BITS_AMODE_64BIT ) {
0 commit comments