Skip to content

Commit 352ccf8

Browse files
committed
KVM: s390: improve interrupt cpu for wakeup
Turns out that picking an idle CPU for floating interrupts has some negative side effects. The guest will keep the IO workload on its CPU and rather use an IPI from the interrupt CPU instead of moving workload. For example a guest with 2 vCPUs and 1 fio process might run that fio on vcpu1. If after diag500 both vCPUs are idle then vcpu0 is woken up. The guest will then do an IPI from vcpu0 to vcpu1. So lets change the heuristics and prefer the last CPU that went to sleep. This one is likely still in halt polling and can be woken up quickly. This patch shows significant improvements in terms of bandwidth or cpu consumption for fio and uperf workloads and seems to be a net win. Link: https://lore.kernel.org/linux-s390/20250904113927.119306-1-borntraeger@linux.ibm.com/ Reviewed-by: Christoph Schlameuß <schlameuss@de.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com>
1 parent 57d88f0 commit 352ccf8

File tree

2 files changed

+10
-12
lines changed

2 files changed

+10
-12
lines changed

arch/s390/include/asm/kvm_host.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ struct kvm_s390_float_interrupt {
356356
int counters[FIRQ_MAX_COUNT];
357357
struct kvm_s390_mchk_info mchk;
358358
struct kvm_s390_ext_info srv_signal;
359-
int next_rr_cpu;
359+
int last_sleep_cpu;
360360
struct mutex ais_lock;
361361
u8 simm;
362362
u8 nimm;

arch/s390/kvm/interrupt.c

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,6 +1322,7 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)
13221322
VCPU_EVENT(vcpu, 4, "enabled wait: %llu ns", sltime);
13231323
no_timer:
13241324
kvm_vcpu_srcu_read_unlock(vcpu);
1325+
vcpu->kvm->arch.float_int.last_sleep_cpu = vcpu->vcpu_idx;
13251326
kvm_vcpu_halt(vcpu);
13261327
vcpu->valid_wakeup = false;
13271328
__unset_cpu_idle(vcpu);
@@ -1948,18 +1949,15 @@ static void __floating_irq_kick(struct kvm *kvm, u64 type)
19481949
if (!online_vcpus)
19491950
return;
19501951

1951-
/* find idle VCPUs first, then round robin */
1952-
sigcpu = find_first_bit(kvm->arch.idle_mask, online_vcpus);
1953-
if (sigcpu == online_vcpus) {
1954-
do {
1955-
sigcpu = kvm->arch.float_int.next_rr_cpu++;
1956-
kvm->arch.float_int.next_rr_cpu %= online_vcpus;
1957-
/* avoid endless loops if all vcpus are stopped */
1958-
if (nr_tries++ >= online_vcpus)
1959-
return;
1960-
} while (is_vcpu_stopped(kvm_get_vcpu(kvm, sigcpu)));
1952+
for (sigcpu = kvm->arch.float_int.last_sleep_cpu; ; sigcpu++) {
1953+
sigcpu %= online_vcpus;
1954+
dst_vcpu = kvm_get_vcpu(kvm, sigcpu);
1955+
if (!is_vcpu_stopped(dst_vcpu))
1956+
break;
1957+
/* avoid endless loops if all vcpus are stopped */
1958+
if (nr_tries++ >= online_vcpus)
1959+
return;
19611960
}
1962-
dst_vcpu = kvm_get_vcpu(kvm, sigcpu);
19631961

19641962
/* make the VCPU drop out of the SIE, or wake it up if sleeping */
19651963
switch (type) {

0 commit comments

Comments
 (0)