@@ -1244,7 +1244,6 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
1244
1244
1245
1245
if (vcpu -> kvm -> arch .use_cmma )
1246
1246
kvm_s390_vcpu_unsetup_cmma (vcpu );
1247
- kfree (vcpu -> arch .guest_fpregs .fprs );
1248
1247
free_page ((unsigned long )(vcpu -> arch .sie_block ));
1249
1248
1250
1249
kvm_vcpu_uninit (vcpu );
@@ -1424,44 +1423,18 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
1424
1423
return 0 ;
1425
1424
}
1426
1425
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
-
1448
1426
void kvm_arch_vcpu_load (struct kvm_vcpu * vcpu , int cpu )
1449
1427
{
1450
1428
/* Save host register state */
1451
1429
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 ;
1464
1432
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 ;
1465
1438
if (test_fp_ctl (current -> thread .fpu .fpc ))
1466
1439
/* User space provided an invalid FPC, let's clear it */
1467
1440
current -> thread .fpu .fpc = 0 ;
@@ -1477,19 +1450,13 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
1477
1450
atomic_andnot (CPUSTAT_RUNNING , & vcpu -> arch .sie_block -> cpuflags );
1478
1451
gmap_disable (vcpu -> arch .gmap );
1479
1452
1453
+ /* Save guest register state */
1480
1454
save_fpu_regs ();
1455
+ vcpu -> run -> s .regs .fpc = current -> thread .fpu .fpc ;
1481
1456
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 ;
1493
1460
1494
1461
save_access_regs (vcpu -> run -> s .regs .acrs );
1495
1462
restore_access_regs (vcpu -> arch .host_acrs );
@@ -1507,8 +1474,9 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
1507
1474
memset (vcpu -> arch .sie_block -> gcr , 0 , 16 * sizeof (__u64 ));
1508
1475
vcpu -> arch .sie_block -> gcr [0 ] = 0xE0UL ;
1509
1476
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 ;
1512
1480
vcpu -> arch .sie_block -> gbea = 1 ;
1513
1481
vcpu -> arch .sie_block -> pp = 0 ;
1514
1482
vcpu -> arch .pfault_token = KVM_S390_PFAULT_TOKEN_INVALID ;
@@ -1649,27 +1617,14 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
1649
1617
vcpu -> arch .local_int .wq = & vcpu -> wq ;
1650
1618
vcpu -> arch .local_int .cpuflags = & vcpu -> arch .sie_block -> cpuflags ;
1651
1619
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
-
1663
1620
rc = kvm_vcpu_init (vcpu , kvm , id );
1664
1621
if (rc )
1665
- goto out_free_fprs ;
1622
+ goto out_free_sie_block ;
1666
1623
VM_EVENT (kvm , 3 , "create cpu %d at 0x%pK, sie block at 0x%pK" , id , vcpu ,
1667
1624
vcpu -> arch .sie_block );
1668
1625
trace_kvm_s390_create_vcpu (id , vcpu , vcpu -> arch .sie_block );
1669
1626
1670
1627
return vcpu ;
1671
- out_free_fprs :
1672
- kfree (vcpu -> arch .guest_fpregs .fprs );
1673
1628
out_free_sie_block :
1674
1629
free_page ((unsigned long )(vcpu -> arch .sie_block ));
1675
1630
out_free_cpu :
@@ -1882,19 +1837,27 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
1882
1837
1883
1838
int kvm_arch_vcpu_ioctl_set_fpu (struct kvm_vcpu * vcpu , struct kvm_fpu * fpu )
1884
1839
{
1840
+ /* make sure the new values will be lazily loaded */
1841
+ save_fpu_regs ();
1885
1842
if (test_fp_ctl (fpu -> fpc ))
1886
1843
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 ));
1891
1849
return 0 ;
1892
1850
}
1893
1851
1894
1852
int kvm_arch_vcpu_ioctl_get_fpu (struct kvm_vcpu * vcpu , struct kvm_fpu * fpu )
1895
1853
{
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 ;
1898
1861
return 0 ;
1899
1862
}
1900
1863
@@ -2399,6 +2362,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
2399
2362
int kvm_s390_store_status_unloaded (struct kvm_vcpu * vcpu , unsigned long gpa )
2400
2363
{
2401
2364
unsigned char archmode = 1 ;
2365
+ freg_t fprs [NUM_FPRS ];
2402
2366
unsigned int px ;
2403
2367
u64 clkcomp ;
2404
2368
int rc ;
@@ -2414,16 +2378,24 @@ int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long gpa)
2414
2378
gpa = px ;
2415
2379
} else
2416
2380
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
+ }
2419
2391
rc |= write_guest_abs (vcpu , gpa + __LC_GPREGS_SAVE_AREA ,
2420
2392
vcpu -> run -> s .regs .gprs , 128 );
2421
2393
rc |= write_guest_abs (vcpu , gpa + __LC_PSW_SAVE_AREA ,
2422
2394
& vcpu -> arch .sie_block -> gpsw , 16 );
2423
2395
rc |= write_guest_abs (vcpu , gpa + __LC_PREFIX_SAVE_AREA ,
2424
2396
& px , 4 );
2425
2397
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 );
2427
2399
rc |= write_guest_abs (vcpu , gpa + __LC_TOD_PROGREG_SAVE_AREA ,
2428
2400
& vcpu -> arch .sie_block -> todpr , 4 );
2429
2401
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)
2446
2418
* it into the save area
2447
2419
*/
2448
2420
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 ;
2462
2422
save_access_regs (vcpu -> run -> s .regs .acrs );
2463
2423
2464
2424
return kvm_s390_store_status_unloaded (vcpu , addr );
0 commit comments