aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-08-31 18:11:53 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-08-31 18:11:53 -0400
commit9c6a019c6edf8591e34ae9da51bac7684131d905 (patch)
treeeac9f69fc6f4dc338d6c91a4c96e2b8a2766737c /arch/s390/kvm
parent7c01919130ef8b27306ed1faf1f2cc079621923c (diff)
parente4ec73510812f24087a28ac8cbf1f77c9fb262e5 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 updates from Martin Schwidefsky: "The big one is support for fake NUMA, splitting a really large machine in more manageable piece improves performance in some cases, e.g. for a KVM host. The FICON Link Incident handling has been improved, this helps the operator to identify degraded or non-operational FICON connections. The save and restore of floating point and vector registers has been overhauled to allow the future use of vector registers in the kernel. A few small enhancement, magic sys-requests for the vt220 console via SCLP, some more assembler code has been converted to C, the PCI error handling is improved. And the usual cleanup and bug fixing" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (59 commits) s390/jump_label: Use %*ph to print small buffers s390/sclp_vt220: support magic sysrequests s390/ctrlchar: improve handling of magic sysrequests s390/numa: remove superfluous ARCH_WANT defines s390/3270: redraw screen on unsolicited device end s390/dcssblk: correct out of bounds array indexes s390/mm: simplify page table alloc/free code s390/pci: move debug messages to debugfs s390/nmi: initialize control register 0 earlier s390/zcrypt: use msleep() instead of mdelay() s390/hmcdrv: fix interrupt registration s390/setup: fix novx parameter s390/uaccess: remove uaccess_primary kernel parameter s390: remove unneeded sizeof(void *) comparisons s390/facilities: remove transactional-execution bits s390/numa: re-add DIE sched_domain_topology_level s390/dasd: enhance CUIR scope detection s390/dasd: fix failing path verification s390/vdso: emit a GNU hash s390/numa: make core to node mapping data dynamic ...
Diffstat (limited to 'arch/s390/kvm')
-rw-r--r--arch/s390/kvm/kvm-s390.c130
1 files changed, 97 insertions, 33 deletions
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 6861b74649ae..98df53c01343 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -1283,21 +1283,54 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
1283 return 0; 1283 return 0;
1284} 1284}
1285 1285
1286/*
1287 * Backs up the current FP/VX register save area on a particular
1288 * destination. Used to switch between different register save
1289 * areas.
1290 */
1291static inline void save_fpu_to(struct fpu *dst)
1292{
1293 dst->fpc = current->thread.fpu.fpc;
1294 dst->flags = current->thread.fpu.flags;
1295 dst->regs = current->thread.fpu.regs;
1296}
1297
1298/*
1299 * Switches the FP/VX register save area from which to lazy
1300 * restore register contents.
1301 */
1302static inline void load_fpu_from(struct fpu *from)
1303{
1304 current->thread.fpu.fpc = from->fpc;
1305 current->thread.fpu.flags = from->flags;
1306 current->thread.fpu.regs = from->regs;
1307}
1308
1286void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) 1309void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
1287{ 1310{
1288 save_fp_ctl(&vcpu->arch.host_fpregs.fpc); 1311 /* Save host register state */
1289 if (test_kvm_facility(vcpu->kvm, 129)) 1312 save_fpu_regs();
1290 save_vx_regs((__vector128 *)&vcpu->arch.host_vregs->vrs); 1313 save_fpu_to(&vcpu->arch.host_fpregs);
1291 else 1314
1292 save_fp_regs(vcpu->arch.host_fpregs.fprs);
1293 save_access_regs(vcpu->arch.host_acrs);
1294 if (test_kvm_facility(vcpu->kvm, 129)) { 1315 if (test_kvm_facility(vcpu->kvm, 129)) {
1295 restore_fp_ctl(&vcpu->run->s.regs.fpc); 1316 current->thread.fpu.fpc = vcpu->run->s.regs.fpc;
1296 restore_vx_regs((__vector128 *)&vcpu->run->s.regs.vrs); 1317 current->thread.fpu.flags = FPU_USE_VX;
1297 } else { 1318 /*
1298 restore_fp_ctl(&vcpu->arch.guest_fpregs.fpc); 1319 * Use the register save area in the SIE-control block
1299 restore_fp_regs(vcpu->arch.guest_fpregs.fprs); 1320 * for register restore and save in kvm_arch_vcpu_put()
1300 } 1321 */
1322 current->thread.fpu.vxrs =
1323 (__vector128 *)&vcpu->run->s.regs.vrs;
1324 /* Always enable the vector extension for KVM */
1325 __ctl_set_vx();
1326 } else
1327 load_fpu_from(&vcpu->arch.guest_fpregs);
1328
1329 if (test_fp_ctl(current->thread.fpu.fpc))
1330 /* User space provided an invalid FPC, let's clear it */
1331 current->thread.fpu.fpc = 0;
1332
1333 save_access_regs(vcpu->arch.host_acrs);
1301 restore_access_regs(vcpu->run->s.regs.acrs); 1334 restore_access_regs(vcpu->run->s.regs.acrs);
1302 gmap_enable(vcpu->arch.gmap); 1335 gmap_enable(vcpu->arch.gmap);
1303 atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags); 1336 atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
@@ -1307,19 +1340,22 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
1307{ 1340{
1308 atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags); 1341 atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
1309 gmap_disable(vcpu->arch.gmap); 1342 gmap_disable(vcpu->arch.gmap);
1310 if (test_kvm_facility(vcpu->kvm, 129)) { 1343
1311 save_fp_ctl(&vcpu->run->s.regs.fpc); 1344 save_fpu_regs();
1312 save_vx_regs((__vector128 *)&vcpu->run->s.regs.vrs); 1345
1313 } else {
1314 save_fp_ctl(&vcpu->arch.guest_fpregs.fpc);
1315 save_fp_regs(vcpu->arch.guest_fpregs.fprs);
1316 }
1317 save_access_regs(vcpu->run->s.regs.acrs);
1318 restore_fp_ctl(&vcpu->arch.host_fpregs.fpc);
1319 if (test_kvm_facility(vcpu->kvm, 129)) 1346 if (test_kvm_facility(vcpu->kvm, 129))
1320 restore_vx_regs((__vector128 *)&vcpu->arch.host_vregs->vrs); 1347 /*
1348 * kvm_arch_vcpu_load() set up the register save area to
1349 * the &vcpu->run->s.regs.vrs and, thus, the vector registers
1350 * are already saved. Only the floating-point control must be
1351 * copied.
1352 */
1353 vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
1321 else 1354 else
1322 restore_fp_regs(vcpu->arch.host_fpregs.fprs); 1355 save_fpu_to(&vcpu->arch.guest_fpregs);
1356 load_fpu_from(&vcpu->arch.host_fpregs);
1357
1358 save_access_regs(vcpu->run->s.regs.acrs);
1323 restore_access_regs(vcpu->arch.host_acrs); 1359 restore_access_regs(vcpu->arch.host_acrs);
1324} 1360}
1325 1361
@@ -1464,7 +1500,6 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
1464 1500
1465 vcpu->arch.sie_block = &sie_page->sie_block; 1501 vcpu->arch.sie_block = &sie_page->sie_block;
1466 vcpu->arch.sie_block->itdba = (unsigned long) &sie_page->itdb; 1502 vcpu->arch.sie_block->itdba = (unsigned long) &sie_page->itdb;
1467 vcpu->arch.host_vregs = &sie_page->vregs;
1468 1503
1469 vcpu->arch.sie_block->icpua = id; 1504 vcpu->arch.sie_block->icpua = id;
1470 if (!kvm_is_ucontrol(kvm)) { 1505 if (!kvm_is_ucontrol(kvm)) {
@@ -1486,6 +1521,19 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
1486 vcpu->arch.local_int.wq = &vcpu->wq; 1521 vcpu->arch.local_int.wq = &vcpu->wq;
1487 vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags; 1522 vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags;
1488 1523
1524 /*
1525 * Allocate a save area for floating-point registers. If the vector
1526 * extension is available, register contents are saved in the SIE
1527 * control block. The allocated save area is still required in
1528 * particular places, for example, in kvm_s390_vcpu_store_status().
1529 */
1530 vcpu->arch.guest_fpregs.fprs = kzalloc(sizeof(freg_t) * __NUM_FPRS,
1531 GFP_KERNEL);
1532 if (!vcpu->arch.guest_fpregs.fprs) {
1533 rc = -ENOMEM;
1534 goto out_free_sie_block;
1535 }
1536
1489 rc = kvm_vcpu_init(vcpu, kvm, id); 1537 rc = kvm_vcpu_init(vcpu, kvm, id);
1490 if (rc) 1538 if (rc)
1491 goto out_free_sie_block; 1539 goto out_free_sie_block;
@@ -1708,16 +1756,16 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
1708{ 1756{
1709 if (test_fp_ctl(fpu->fpc)) 1757 if (test_fp_ctl(fpu->fpc))
1710 return -EINVAL; 1758 return -EINVAL;
1711 memcpy(&vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs)); 1759 memcpy(vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs));
1712 vcpu->arch.guest_fpregs.fpc = fpu->fpc; 1760 vcpu->arch.guest_fpregs.fpc = fpu->fpc;
1713 restore_fp_ctl(&vcpu->arch.guest_fpregs.fpc); 1761 save_fpu_regs();
1714 restore_fp_regs(vcpu->arch.guest_fpregs.fprs); 1762 load_fpu_from(&vcpu->arch.guest_fpregs);
1715 return 0; 1763 return 0;
1716} 1764}
1717 1765
1718int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) 1766int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
1719{ 1767{
1720 memcpy(&fpu->fprs, &vcpu->arch.guest_fpregs.fprs, sizeof(fpu->fprs)); 1768 memcpy(&fpu->fprs, vcpu->arch.guest_fpregs.fprs, sizeof(fpu->fprs));
1721 fpu->fpc = vcpu->arch.guest_fpregs.fpc; 1769 fpu->fpc = vcpu->arch.guest_fpregs.fpc;
1722 return 0; 1770 return 0;
1723} 1771}
@@ -2268,8 +2316,21 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
2268 * copying in vcpu load/put. Lets update our copies before we save 2316 * copying in vcpu load/put. Lets update our copies before we save
2269 * it into the save area 2317 * it into the save area
2270 */ 2318 */
2271 save_fp_ctl(&vcpu->arch.guest_fpregs.fpc); 2319 save_fpu_regs();
2272 save_fp_regs(vcpu->arch.guest_fpregs.fprs); 2320 if (test_kvm_facility(vcpu->kvm, 129)) {
2321 /*
2322 * If the vector extension is available, the vector registers
2323 * which overlaps with floating-point registers are saved in
2324 * the SIE-control block. Hence, extract the floating-point
2325 * registers and the FPC value and store them in the
2326 * guest_fpregs structure.
2327 */
2328 WARN_ON(!is_vx_task(current)); /* XXX remove later */
2329 vcpu->arch.guest_fpregs.fpc = current->thread.fpu.fpc;
2330 convert_vx_to_fp(vcpu->arch.guest_fpregs.fprs,
2331 current->thread.fpu.vxrs);
2332 } else
2333 save_fpu_to(&vcpu->arch.guest_fpregs);
2273 save_access_regs(vcpu->run->s.regs.acrs); 2334 save_access_regs(vcpu->run->s.regs.acrs);
2274 2335
2275 return kvm_s390_store_status_unloaded(vcpu, addr); 2336 return kvm_s390_store_status_unloaded(vcpu, addr);
@@ -2296,10 +2357,13 @@ int kvm_s390_vcpu_store_adtl_status(struct kvm_vcpu *vcpu, unsigned long addr)
2296 2357
2297 /* 2358 /*
2298 * The guest VXRS are in the host VXRs due to the lazy 2359 * The guest VXRS are in the host VXRs due to the lazy
2299 * copying in vcpu load/put. Let's update our copies before we save 2360 * copying in vcpu load/put. We can simply call save_fpu_regs()
2300 * it into the save area. 2361 * to save the current register state because we are in the
2362 * middle of a load/put cycle.
2363 *
2364 * Let's update our copies before we save it into the save area.
2301 */ 2365 */
2302 save_vx_regs((__vector128 *)&vcpu->run->s.regs.vrs); 2366 save_fpu_regs();
2303 2367
2304 return kvm_s390_store_adtl_status_unloaded(vcpu, addr); 2368 return kvm_s390_store_adtl_status_unloaded(vcpu, addr);
2305} 2369}