aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm/kvm-s390.c
diff options
context:
space:
mode:
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>2014-03-14 06:00:21 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2014-04-29 09:01:54 -0400
commit8ad357551797b1edc184fb9f6a4f80a6fa626459 (patch)
tree3700cdc96803f5be483cd79453b240c73b522f3a /arch/s390/kvm/kvm-s390.c
parent6852d7b69b4949234c3a8ae1f279f6a4c6563662 (diff)
KVM: s390: enable IBS for single running VCPUs
This patch enables the IBS facility when a single VCPU is running. The facility is dynamically turned on/off as soon as other VCPUs enter/leave the stopped state. When this facility is operating, some instructions can be executed faster for single-cpu guests. Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Reviewed-by: Dominik Dingel <dingel@linux.vnet.ibm.com> Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'arch/s390/kvm/kvm-s390.c')
-rw-r--r--arch/s390/kvm/kvm-s390.c123
1 files changed, 121 insertions, 2 deletions
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 6c972d229ace..0a01744cbdd9 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -458,6 +458,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
458 kvm->arch.css_support = 0; 458 kvm->arch.css_support = 0;
459 kvm->arch.use_irqchip = 0; 459 kvm->arch.use_irqchip = 0;
460 460
461 spin_lock_init(&kvm->arch.start_stop_lock);
462
461 return 0; 463 return 0;
462out_nogmap: 464out_nogmap:
463 debug_unregister(kvm->arch.dbf); 465 debug_unregister(kvm->arch.dbf);
@@ -996,8 +998,15 @@ bool kvm_s390_cmma_enabled(struct kvm *kvm)
996 return true; 998 return true;
997} 999}
998 1000
1001static bool ibs_enabled(struct kvm_vcpu *vcpu)
1002{
1003 return atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_IBS;
1004}
1005
999static int kvm_s390_handle_requests(struct kvm_vcpu *vcpu) 1006static int kvm_s390_handle_requests(struct kvm_vcpu *vcpu)
1000{ 1007{
1008retry:
1009 s390_vcpu_unblock(vcpu);
1001 /* 1010 /*
1002 * We use MMU_RELOAD just to re-arm the ipte notifier for the 1011 * We use MMU_RELOAD just to re-arm the ipte notifier for the
1003 * guest prefix page. gmap_ipte_notify will wait on the ptl lock. 1012 * guest prefix page. gmap_ipte_notify will wait on the ptl lock.
@@ -1005,15 +1014,34 @@ static int kvm_s390_handle_requests(struct kvm_vcpu *vcpu)
1005 * already finished. We might race against a second unmapper that 1014 * already finished. We might race against a second unmapper that
1006 * wants to set the blocking bit. Lets just retry the request loop. 1015 * wants to set the blocking bit. Lets just retry the request loop.
1007 */ 1016 */
1008 while (kvm_check_request(KVM_REQ_MMU_RELOAD, vcpu)) { 1017 if (kvm_check_request(KVM_REQ_MMU_RELOAD, vcpu)) {
1009 int rc; 1018 int rc;
1010 rc = gmap_ipte_notify(vcpu->arch.gmap, 1019 rc = gmap_ipte_notify(vcpu->arch.gmap,
1011 vcpu->arch.sie_block->prefix, 1020 vcpu->arch.sie_block->prefix,
1012 PAGE_SIZE * 2); 1021 PAGE_SIZE * 2);
1013 if (rc) 1022 if (rc)
1014 return rc; 1023 return rc;
1015 s390_vcpu_unblock(vcpu); 1024 goto retry;
1025 }
1026
1027 if (kvm_check_request(KVM_REQ_ENABLE_IBS, vcpu)) {
1028 if (!ibs_enabled(vcpu)) {
1029 trace_kvm_s390_enable_disable_ibs(vcpu->vcpu_id, 1);
1030 atomic_set_mask(CPUSTAT_IBS,
1031 &vcpu->arch.sie_block->cpuflags);
1032 }
1033 goto retry;
1016 } 1034 }
1035
1036 if (kvm_check_request(KVM_REQ_DISABLE_IBS, vcpu)) {
1037 if (ibs_enabled(vcpu)) {
1038 trace_kvm_s390_enable_disable_ibs(vcpu->vcpu_id, 0);
1039 atomic_clear_mask(CPUSTAT_IBS,
1040 &vcpu->arch.sie_block->cpuflags);
1041 }
1042 goto retry;
1043 }
1044
1017 return 0; 1045 return 0;
1018} 1046}
1019 1047
@@ -1362,16 +1390,107 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
1362 return kvm_s390_store_status_unloaded(vcpu, addr); 1390 return kvm_s390_store_status_unloaded(vcpu, addr);
1363} 1391}
1364 1392
1393static inline int is_vcpu_stopped(struct kvm_vcpu *vcpu)
1394{
1395 return atomic_read(&(vcpu)->arch.sie_block->cpuflags) & CPUSTAT_STOPPED;
1396}
1397
1398static void __disable_ibs_on_vcpu(struct kvm_vcpu *vcpu)
1399{
1400 kvm_check_request(KVM_REQ_ENABLE_IBS, vcpu);
1401 kvm_make_request(KVM_REQ_DISABLE_IBS, vcpu);
1402 exit_sie_sync(vcpu);
1403}
1404
1405static void __disable_ibs_on_all_vcpus(struct kvm *kvm)
1406{
1407 unsigned int i;
1408 struct kvm_vcpu *vcpu;
1409
1410 kvm_for_each_vcpu(i, vcpu, kvm) {
1411 __disable_ibs_on_vcpu(vcpu);
1412 }
1413}
1414
1415static void __enable_ibs_on_vcpu(struct kvm_vcpu *vcpu)
1416{
1417 kvm_check_request(KVM_REQ_DISABLE_IBS, vcpu);
1418 kvm_make_request(KVM_REQ_ENABLE_IBS, vcpu);
1419 exit_sie_sync(vcpu);
1420}
1421
1365void kvm_s390_vcpu_start(struct kvm_vcpu *vcpu) 1422void kvm_s390_vcpu_start(struct kvm_vcpu *vcpu)
1366{ 1423{
1424 int i, online_vcpus, started_vcpus = 0;
1425
1426 if (!is_vcpu_stopped(vcpu))
1427 return;
1428
1367 trace_kvm_s390_vcpu_start_stop(vcpu->vcpu_id, 1); 1429 trace_kvm_s390_vcpu_start_stop(vcpu->vcpu_id, 1);
1430 /* Only one cpu at a time may enter/leave the STOPPED state. */
1431 spin_lock_bh(&vcpu->kvm->arch.start_stop_lock);
1432 online_vcpus = atomic_read(&vcpu->kvm->online_vcpus);
1433
1434 for (i = 0; i < online_vcpus; i++) {
1435 if (!is_vcpu_stopped(vcpu->kvm->vcpus[i]))
1436 started_vcpus++;
1437 }
1438
1439 if (started_vcpus == 0) {
1440 /* we're the only active VCPU -> speed it up */
1441 __enable_ibs_on_vcpu(vcpu);
1442 } else if (started_vcpus == 1) {
1443 /*
1444 * As we are starting a second VCPU, we have to disable
1445 * the IBS facility on all VCPUs to remove potentially
1446 * oustanding ENABLE requests.
1447 */
1448 __disable_ibs_on_all_vcpus(vcpu->kvm);
1449 }
1450
1368 atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags); 1451 atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
1452 /*
1453 * Another VCPU might have used IBS while we were offline.
1454 * Let's play safe and flush the VCPU at startup.
1455 */
1456 vcpu->arch.sie_block->ihcpu = 0xffff;
1457 spin_unlock_bh(&vcpu->kvm->arch.start_stop_lock);
1458 return;
1369} 1459}
1370 1460
1371void kvm_s390_vcpu_stop(struct kvm_vcpu *vcpu) 1461void kvm_s390_vcpu_stop(struct kvm_vcpu *vcpu)
1372{ 1462{
1463 int i, online_vcpus, started_vcpus = 0;
1464 struct kvm_vcpu *started_vcpu = NULL;
1465
1466 if (is_vcpu_stopped(vcpu))
1467 return;
1468
1373 trace_kvm_s390_vcpu_start_stop(vcpu->vcpu_id, 0); 1469 trace_kvm_s390_vcpu_start_stop(vcpu->vcpu_id, 0);
1470 /* Only one cpu at a time may enter/leave the STOPPED state. */
1471 spin_lock_bh(&vcpu->kvm->arch.start_stop_lock);
1472 online_vcpus = atomic_read(&vcpu->kvm->online_vcpus);
1473
1374 atomic_set_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags); 1474 atomic_set_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
1475 __disable_ibs_on_vcpu(vcpu);
1476
1477 for (i = 0; i < online_vcpus; i++) {
1478 if (!is_vcpu_stopped(vcpu->kvm->vcpus[i])) {
1479 started_vcpus++;
1480 started_vcpu = vcpu->kvm->vcpus[i];
1481 }
1482 }
1483
1484 if (started_vcpus == 1) {
1485 /*
1486 * As we only have one VCPU left, we want to enable the
1487 * IBS facility for that VCPU to speed it up.
1488 */
1489 __enable_ibs_on_vcpu(started_vcpu);
1490 }
1491
1492 spin_unlock_bh(&vcpu->kvm->arch.start_stop_lock);
1493 return;
1375} 1494}
1376 1495
1377static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, 1496static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,