@@ -1244,7 +1244,6 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
12441244
12451245 if (vcpu -> kvm -> arch .use_cmma )
12461246 kvm_s390_vcpu_unsetup_cmma (vcpu );
1247- kfree (vcpu -> arch .guest_fpregs .fprs );
12481247 free_page ((unsigned long )(vcpu -> arch .sie_block ));
12491248
12501249 kvm_vcpu_uninit (vcpu );
@@ -1424,44 +1423,18 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
14241423 return 0 ;
14251424}
14261425
1427- /*
1428- * Backs up the current FP/VX register save area on a particular
1429- * destination. Used to switch between different register save
1430- * areas.
1431- */
1432- static inline void save_fpu_to (struct fpu * dst )
1433- {
1434- dst -> fpc = current -> thread .fpu .fpc ;
1435- dst -> regs = current -> thread .fpu .regs ;
1436- }
1437-
1438- /*
1439- * Switches the FP/VX register save area from which to lazy
1440- * restore register contents.
1441- */
1442- static inline void load_fpu_from (struct fpu * from )
1443- {
1444- current -> thread .fpu .fpc = from -> fpc ;
1445- current -> thread .fpu .regs = from -> regs ;
1446- }
1447-
14481426void kvm_arch_vcpu_load (struct kvm_vcpu * vcpu , int cpu )
14491427{
14501428 /* Save host register state */
14511429 save_fpu_regs ();
1452- save_fpu_to (& vcpu -> arch .host_fpregs );
1453-
1454- if (test_kvm_facility (vcpu -> kvm , 129 )) {
1455- current -> thread .fpu .fpc = vcpu -> run -> s .regs .fpc ;
1456- /*
1457- * Use the register save area in the SIE-control block
1458- * for register restore and save in kvm_arch_vcpu_put()
1459- */
1460- current -> thread .fpu .vxrs =
1461- (__vector128 * )& vcpu -> run -> s .regs .vrs ;
1462- } else
1463- load_fpu_from (& vcpu -> arch .guest_fpregs );
1430+ vcpu -> arch .host_fpregs .fpc = current -> thread .fpu .fpc ;
1431+ vcpu -> arch .host_fpregs .regs = current -> thread .fpu .regs ;
14641432
1433+ /* Depending on MACHINE_HAS_VX, data stored to vrs either
1434+ * has vector register or floating point register format.
1435+ */
1436+ current -> thread .fpu .regs = vcpu -> run -> s .regs .vrs ;
1437+ current -> thread .fpu .fpc = vcpu -> run -> s .regs .fpc ;
14651438 if (test_fp_ctl (current -> thread .fpu .fpc ))
14661439 /* User space provided an invalid FPC, let's clear it */
14671440 current -> thread .fpu .fpc = 0 ;
@@ -1477,19 +1450,13 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
14771450 atomic_andnot (CPUSTAT_RUNNING , & vcpu -> arch .sie_block -> cpuflags );
14781451 gmap_disable (vcpu -> arch .gmap );
14791452
1453+ /* Save guest register state */
14801454 save_fpu_regs ();
1455+ vcpu -> run -> s .regs .fpc = current -> thread .fpu .fpc ;
14811456
1482- if (test_kvm_facility (vcpu -> kvm , 129 ))
1483- /*
1484- * kvm_arch_vcpu_load() set up the register save area to
1485- * the &vcpu->run->s.regs.vrs and, thus, the vector registers
1486- * are already saved. Only the floating-point control must be
1487- * copied.
1488- */
1489- vcpu -> run -> s .regs .fpc = current -> thread .fpu .fpc ;
1490- else
1491- save_fpu_to (& vcpu -> arch .guest_fpregs );
1492- load_fpu_from (& vcpu -> arch .host_fpregs );
1457+ /* Restore host register state */
1458+ current -> thread .fpu .fpc = vcpu -> arch .host_fpregs .fpc ;
1459+ current -> thread .fpu .regs = vcpu -> arch .host_fpregs .regs ;
14931460
14941461 save_access_regs (vcpu -> run -> s .regs .acrs );
14951462 restore_access_regs (vcpu -> arch .host_acrs );
@@ -1507,8 +1474,9 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
15071474 memset (vcpu -> arch .sie_block -> gcr , 0 , 16 * sizeof (__u64 ));
15081475 vcpu -> arch .sie_block -> gcr [0 ] = 0xE0UL ;
15091476 vcpu -> arch .sie_block -> gcr [14 ] = 0xC2000000UL ;
1510- vcpu -> arch .guest_fpregs .fpc = 0 ;
1511- asm volatile ("lfpc %0" : : "Q" (vcpu -> arch .guest_fpregs .fpc ));
1477+ /* make sure the new fpc will be lazily loaded */
1478+ save_fpu_regs ();
1479+ current -> thread .fpu .fpc = 0 ;
15121480 vcpu -> arch .sie_block -> gbea = 1 ;
15131481 vcpu -> arch .sie_block -> pp = 0 ;
15141482 vcpu -> arch .pfault_token = KVM_S390_PFAULT_TOKEN_INVALID ;
@@ -1649,27 +1617,14 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
16491617 vcpu -> arch .local_int .wq = & vcpu -> wq ;
16501618 vcpu -> arch .local_int .cpuflags = & vcpu -> arch .sie_block -> cpuflags ;
16511619
1652- /*
1653- * Allocate a save area for floating-point registers. If the vector
1654- * extension is available, register contents are saved in the SIE
1655- * control block. The allocated save area is still required in
1656- * particular places, for example, in kvm_s390_vcpu_store_status().
1657- */
1658- vcpu -> arch .guest_fpregs .fprs = kzalloc (sizeof (freg_t ) * __NUM_FPRS ,
1659- GFP_KERNEL );
1660- if (!vcpu -> arch .guest_fpregs .fprs )
1661- goto out_free_sie_block ;
1662-
16631620 rc = kvm_vcpu_init (vcpu , kvm , id );
16641621 if (rc )
1665- goto out_free_fprs ;
1622+ goto out_free_sie_block ;
16661623 VM_EVENT (kvm , 3 , "create cpu %d at 0x%pK, sie block at 0x%pK" , id , vcpu ,
16671624 vcpu -> arch .sie_block );
16681625 trace_kvm_s390_create_vcpu (id , vcpu , vcpu -> arch .sie_block );
16691626
16701627 return vcpu ;
1671- out_free_fprs :
1672- kfree (vcpu -> arch .guest_fpregs .fprs );
16731628out_free_sie_block :
16741629 free_page ((unsigned long )(vcpu -> arch .sie_block ));
16751630out_free_cpu :
@@ -1882,19 +1837,27 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
18821837
18831838int kvm_arch_vcpu_ioctl_set_fpu (struct kvm_vcpu * vcpu , struct kvm_fpu * fpu )
18841839{
1840+ /* make sure the new values will be lazily loaded */
1841+ save_fpu_regs ();
18851842 if (test_fp_ctl (fpu -> fpc ))
18861843 return - EINVAL ;
1887- memcpy (vcpu -> arch .guest_fpregs .fprs , & fpu -> fprs , sizeof (fpu -> fprs ));
1888- vcpu -> arch .guest_fpregs .fpc = fpu -> fpc ;
1889- save_fpu_regs ();
1890- load_fpu_from (& vcpu -> arch .guest_fpregs );
1844+ current -> thread .fpu .fpc = fpu -> fpc ;
1845+ if (MACHINE_HAS_VX )
1846+ convert_fp_to_vx (current -> thread .fpu .vxrs , (freg_t * )fpu -> fprs );
1847+ else
1848+ memcpy (current -> thread .fpu .fprs , & fpu -> fprs , sizeof (fpu -> fprs ));
18911849 return 0 ;
18921850}
18931851
18941852int kvm_arch_vcpu_ioctl_get_fpu (struct kvm_vcpu * vcpu , struct kvm_fpu * fpu )
18951853{
1896- memcpy (& fpu -> fprs , vcpu -> arch .guest_fpregs .fprs , sizeof (fpu -> fprs ));
1897- fpu -> fpc = vcpu -> arch .guest_fpregs .fpc ;
1854+ /* make sure we have the latest values */
1855+ save_fpu_regs ();
1856+ if (MACHINE_HAS_VX )
1857+ convert_vx_to_fp ((freg_t * )fpu -> fprs , current -> thread .fpu .vxrs );
1858+ else
1859+ memcpy (fpu -> fprs , current -> thread .fpu .fprs , sizeof (fpu -> fprs ));
1860+ fpu -> fpc = current -> thread .fpu .fpc ;
18981861 return 0 ;
18991862}
19001863
@@ -2399,6 +2362,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
23992362int kvm_s390_store_status_unloaded (struct kvm_vcpu * vcpu , unsigned long gpa )
24002363{
24012364 unsigned char archmode = 1 ;
2365+ freg_t fprs [NUM_FPRS ];
24022366 unsigned int px ;
24032367 u64 clkcomp ;
24042368 int rc ;
@@ -2414,16 +2378,24 @@ int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long gpa)
24142378 gpa = px ;
24152379 } else
24162380 gpa -= __LC_FPREGS_SAVE_AREA ;
2417- rc = write_guest_abs (vcpu , gpa + __LC_FPREGS_SAVE_AREA ,
2418- vcpu -> arch .guest_fpregs .fprs , 128 );
2381+
2382+ /* manually convert vector registers if necessary */
2383+ if (MACHINE_HAS_VX ) {
2384+ convert_vx_to_fp (fprs , current -> thread .fpu .vxrs );
2385+ rc = write_guest_abs (vcpu , gpa + __LC_FPREGS_SAVE_AREA ,
2386+ fprs , 128 );
2387+ } else {
2388+ rc = write_guest_abs (vcpu , gpa + __LC_FPREGS_SAVE_AREA ,
2389+ vcpu -> run -> s .regs .vrs , 128 );
2390+ }
24192391 rc |= write_guest_abs (vcpu , gpa + __LC_GPREGS_SAVE_AREA ,
24202392 vcpu -> run -> s .regs .gprs , 128 );
24212393 rc |= write_guest_abs (vcpu , gpa + __LC_PSW_SAVE_AREA ,
24222394 & vcpu -> arch .sie_block -> gpsw , 16 );
24232395 rc |= write_guest_abs (vcpu , gpa + __LC_PREFIX_SAVE_AREA ,
24242396 & px , 4 );
24252397 rc |= write_guest_abs (vcpu , gpa + __LC_FP_CREG_SAVE_AREA ,
2426- & vcpu -> arch . guest_fpregs .fpc , 4 );
2398+ & vcpu -> run -> s . regs .fpc , 4 );
24272399 rc |= write_guest_abs (vcpu , gpa + __LC_TOD_PROGREG_SAVE_AREA ,
24282400 & vcpu -> arch .sie_block -> todpr , 4 );
24292401 rc |= write_guest_abs (vcpu , gpa + __LC_CPU_TIMER_SAVE_AREA ,
@@ -2446,19 +2418,7 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
24462418 * it into the save area
24472419 */
24482420 save_fpu_regs ();
2449- if (test_kvm_facility (vcpu -> kvm , 129 )) {
2450- /*
2451- * If the vector extension is available, the vector registers
2452- * which overlaps with floating-point registers are saved in
2453- * the SIE-control block. Hence, extract the floating-point
2454- * registers and the FPC value and store them in the
2455- * guest_fpregs structure.
2456- */
2457- vcpu -> arch .guest_fpregs .fpc = current -> thread .fpu .fpc ;
2458- convert_vx_to_fp (vcpu -> arch .guest_fpregs .fprs ,
2459- current -> thread .fpu .vxrs );
2460- } else
2461- save_fpu_to (& vcpu -> arch .guest_fpregs );
2421+ vcpu -> run -> s .regs .fpc = current -> thread .fpu .fpc ;
24622422 save_access_regs (vcpu -> run -> s .regs .acrs );
24632423
24642424 return kvm_s390_store_status_unloaded (vcpu , addr );
0 commit comments