aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm
diff options
context:
space:
mode:
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>2015-01-14 08:08:38 -0500
committerChristian Borntraeger <borntraeger@de.ibm.com>2015-05-08 09:51:16 -0400
commit96e0ed23dca3769053c5211ef885e789097834bf (patch)
treeae7324f669fcb7329a0681367bbfe8233d79091d /arch/s390/kvm
parentffeca0ae880055457e56e45fd79cfa28d7160c30 (diff)
KVM: s390: factor out and optimize floating irq VCPU kick
This patch factors out the search for a floating irq destination VCPU as well as the kicking of the found VCPU. The search is optimized in the following ways: 1. stopped VCPUs can't take any floating interrupts, so try to find an operating one. We have to take care of the special case where all VCPUs are stopped and we don't have any valid destination. 2. use online_vcpus, not KVM_MAX_VCPU. This speeds up the search especially if KVM_MAX_VCPU is increased one day. As these VCPU objects are initialized prior to increasing online_vcpus, we can be sure that they exist. Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com> Reviewed-by: Dominik Dingel <dingel@linux.vnet.ibm.com> Reviewed-by: Jens Freimann <jfrei@linux.vnet.ibm.com> Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'arch/s390/kvm')
-rw-r--r--arch/s390/kvm/interrupt.c74
1 files changed, 46 insertions, 28 deletions
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index acf4a4e660c0..322ef9cfdc80 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -1337,12 +1337,54 @@ static int __inject_io(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)
1337 return 0; 1337 return 0;
1338} 1338}
1339 1339
1340static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti) 1340/*
1341 * Find a destination VCPU for a floating irq and kick it.
1342 */
1343static void __floating_irq_kick(struct kvm *kvm, u64 type)
1341{ 1344{
1345 struct kvm_s390_float_interrupt *fi = &kvm->arch.float_int;
1342 struct kvm_s390_local_interrupt *li; 1346 struct kvm_s390_local_interrupt *li;
1347 struct kvm_vcpu *dst_vcpu;
1348 int sigcpu, online_vcpus, nr_tries = 0;
1349
1350 online_vcpus = atomic_read(&kvm->online_vcpus);
1351 if (!online_vcpus)
1352 return;
1353
1354 /* find idle VCPUs first, then round robin */
1355 sigcpu = find_first_bit(fi->idle_mask, online_vcpus);
1356 if (sigcpu == online_vcpus) {
1357 do {
1358 sigcpu = fi->next_rr_cpu;
1359 fi->next_rr_cpu = (fi->next_rr_cpu + 1) % online_vcpus;
1360 /* avoid endless loops if all vcpus are stopped */
1361 if (nr_tries++ >= online_vcpus)
1362 return;
1363 } while (is_vcpu_stopped(kvm_get_vcpu(kvm, sigcpu)));
1364 }
1365 dst_vcpu = kvm_get_vcpu(kvm, sigcpu);
1366
1367 /* make the VCPU drop out of the SIE, or wake it up if sleeping */
1368 li = &dst_vcpu->arch.local_int;
1369 spin_lock(&li->lock);
1370 switch (type) {
1371 case KVM_S390_MCHK:
1372 atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags);
1373 break;
1374 case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
1375 atomic_set_mask(CPUSTAT_IO_INT, li->cpuflags);
1376 break;
1377 default:
1378 atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
1379 break;
1380 }
1381 spin_unlock(&li->lock);
1382 kvm_s390_vcpu_wakeup(dst_vcpu);
1383}
1384
1385static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)
1386{
1343 struct kvm_s390_float_interrupt *fi; 1387 struct kvm_s390_float_interrupt *fi;
1344 struct kvm_vcpu *dst_vcpu = NULL;
1345 int sigcpu;
1346 u64 type = READ_ONCE(inti->type); 1388 u64 type = READ_ONCE(inti->type);
1347 int rc; 1389 int rc;
1348 1390
@@ -1370,32 +1412,8 @@ static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti)
1370 if (rc) 1412 if (rc)
1371 return rc; 1413 return rc;
1372 1414
1373 sigcpu = find_first_bit(fi->idle_mask, KVM_MAX_VCPUS); 1415 __floating_irq_kick(kvm, type);
1374 if (sigcpu == KVM_MAX_VCPUS) {
1375 do {
1376 sigcpu = fi->next_rr_cpu++;
1377 if (sigcpu == KVM_MAX_VCPUS)
1378 sigcpu = fi->next_rr_cpu = 0;
1379 } while (kvm_get_vcpu(kvm, sigcpu) == NULL);
1380 }
1381 dst_vcpu = kvm_get_vcpu(kvm, sigcpu);
1382 li = &dst_vcpu->arch.local_int;
1383 spin_lock(&li->lock);
1384 switch (type) {
1385 case KVM_S390_MCHK:
1386 atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags);
1387 break;
1388 case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
1389 atomic_set_mask(CPUSTAT_IO_INT, li->cpuflags);
1390 break;
1391 default:
1392 atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
1393 break;
1394 }
1395 spin_unlock(&li->lock);
1396 kvm_s390_vcpu_wakeup(kvm_get_vcpu(kvm, sigcpu));
1397 return 0; 1416 return 0;
1398
1399} 1417}
1400 1418
1401int kvm_s390_inject_vm(struct kvm *kvm, 1419int kvm_s390_inject_vm(struct kvm *kvm,