@@ -246,9 +246,10 @@ static int try_handle_skey(struct kvm_vcpu *vcpu)
246246
247247static int handle_iske (struct kvm_vcpu * vcpu )
248248{
249- unsigned long addr ;
249+ unsigned long gaddr , vmaddr ;
250250 unsigned char key ;
251251 int reg1 , reg2 ;
252+ bool unlocked ;
252253 int rc ;
253254
254255 vcpu -> stat .instruction_iske ++ ;
@@ -262,27 +263,38 @@ static int handle_iske(struct kvm_vcpu *vcpu)
262263
263264 kvm_s390_get_regs_rre (vcpu , & reg1 , & reg2 );
264265
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 ))
270271 return kvm_s390_inject_program_int (vcpu , PGM_ADDRESSING );
271-
272+ retry :
273+ unlocked = false;
272274 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+ }
275285 if (rc )
276286 return kvm_s390_inject_program_int (vcpu , PGM_ADDRESSING );
287+ up_read (& current -> mm -> mmap_sem );
277288 vcpu -> run -> s .regs .gprs [reg1 ] &= ~0xff ;
278289 vcpu -> run -> s .regs .gprs [reg1 ] |= key ;
279290 return 0 ;
280291}
281292
282293static int handle_rrbe (struct kvm_vcpu * vcpu )
283294{
284- unsigned long addr ;
295+ unsigned long vmaddr , gaddr ;
285296 int reg1 , reg2 ;
297+ bool unlocked ;
286298 int rc ;
287299
288300 vcpu -> stat .instruction_rrbe ++ ;
@@ -296,19 +308,27 @@ static int handle_rrbe(struct kvm_vcpu *vcpu)
296308
297309 kvm_s390_get_regs_rre (vcpu , & reg1 , & reg2 );
298310
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 ))
304316 return kvm_s390_inject_program_int (vcpu , PGM_ADDRESSING );
305-
317+ retry :
318+ unlocked = false;
306319 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+ }
309329 if (rc < 0 )
310330 return kvm_s390_inject_program_int (vcpu , PGM_ADDRESSING );
311-
331+ up_read ( & current -> mm -> mmap_sem );
312332 kvm_s390_set_psw_cc (vcpu , rc );
313333 return 0 ;
314334}
@@ -323,6 +343,7 @@ static int handle_sske(struct kvm_vcpu *vcpu)
323343 unsigned long start , end ;
324344 unsigned char key , oldkey ;
325345 int reg1 , reg2 ;
346+ bool unlocked ;
326347 int rc ;
327348
328349 vcpu -> stat .instruction_sske ++ ;
@@ -355,19 +376,28 @@ static int handle_sske(struct kvm_vcpu *vcpu)
355376 }
356377
357378 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;
359381
360- if (kvm_is_error_hva (addr ))
382+ if (kvm_is_error_hva (vmaddr ))
361383 return kvm_s390_inject_program_int (vcpu , PGM_ADDRESSING );
362384
363385 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 ,
365387 m3 & SSKE_NQ , m3 & SSKE_MR ,
366388 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 )
369396 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 ;
371401 }
372402
373403 if (m3 & (SSKE_MC | SSKE_MR )) {
@@ -948,15 +978,16 @@ static int handle_pfmf(struct kvm_vcpu *vcpu)
948978 }
949979
950980 while (start != end ) {
951- unsigned long useraddr ;
981+ unsigned long vmaddr ;
982+ bool unlocked = false;
952983
953984 /* 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 ))
956987 return kvm_s390_inject_program_int (vcpu , PGM_ADDRESSING );
957988
958989 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 ))
960991 return kvm_s390_inject_program_int (vcpu , PGM_ADDRESSING );
961992 }
962993
@@ -966,14 +997,20 @@ static int handle_pfmf(struct kvm_vcpu *vcpu)
966997 if (rc )
967998 return rc ;
968999 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 ,
9701001 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 )
9731008 return kvm_s390_inject_program_int (vcpu , PGM_ADDRESSING );
974- }
9751009
976- start += PAGE_SIZE ;
1010+ up_read (& current -> mm -> mmap_sem );
1011+ if (rc >= 0 )
1012+ start += PAGE_SIZE ;
1013+ }
9771014 }
9781015 if (vcpu -> run -> s .regs .gprs [reg1 ] & PFMF_FSC ) {
9791016 if (psw_bits (vcpu -> arch .sie_block -> gpsw ).eaba == PSW_BITS_AMODE_64BIT ) {
0 commit comments