diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-08-31 18:11:53 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-08-31 18:11:53 -0400 |
commit | 9c6a019c6edf8591e34ae9da51bac7684131d905 (patch) | |
tree | eac9f69fc6f4dc338d6c91a4c96e2b8a2766737c /arch/s390/kvm | |
parent | 7c01919130ef8b27306ed1faf1f2cc079621923c (diff) | |
parent | e4ec73510812f24087a28ac8cbf1f77c9fb262e5 (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.c | 130 |
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 | */ | ||
1291 | static 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 | */ | ||
1302 | static 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 | |||
1286 | void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | 1309 | void 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 | ||
1718 | int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) | 1766 | int 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 | } |