Skip to content

Commit 2bd1337

Browse files
ajdlinuxfrankjaa
authored andcommitted
KVM: s390: Use generic VIRT_XFER_TO_GUEST_WORK functions
Switch to using the generic infrastructure to check for and handle pending work before transitioning into guest mode. xfer_to_guest_mode_handle_work() does a few more things than the current code does when deciding whether or not to exit the __vcpu_run() loop. The exittime tests from kvm-unit-tests, in my tests, were within a few percent compared to before this series, which is within noise tolerance. Co-developed-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Andrew Donnellan <ajd@linux.ibm.com> Acked-by: Janosch Frank <frankja@linux.ibm.com> [frankja@linux.ibm.com: Removed semicolon] Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
1 parent d013905 commit 2bd1337

File tree

3 files changed

+32
-12
lines changed

3 files changed

+32
-12
lines changed

arch/s390/kvm/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ config KVM
3030
select HAVE_KVM_NO_POLL
3131
select KVM_VFIO
3232
select MMU_NOTIFIER
33+
select VIRT_XFER_TO_GUEST_WORK
3334
help
3435
Support hosting paravirtualized guest machines using the SIE
3536
virtualization capability on the mainframe. This should work

arch/s390/kvm/kvm-s390.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
1515

1616
#include <linux/compiler.h>
17+
#include <linux/entry-virt.h>
1718
#include <linux/export.h>
1819
#include <linux/err.h>
1920
#include <linux/fs.h>
@@ -4675,9 +4676,6 @@ static int vcpu_pre_run(struct kvm_vcpu *vcpu)
46754676
vcpu->arch.sie_block->gg14 = vcpu->run->s.regs.gprs[14];
46764677
vcpu->arch.sie_block->gg15 = vcpu->run->s.regs.gprs[15];
46774678

4678-
if (need_resched())
4679-
schedule();
4680-
46814679
if (!kvm_is_ucontrol(vcpu->kvm)) {
46824680
rc = kvm_s390_deliver_pending_interrupts(vcpu);
46834681
if (rc || guestdbg_exit_pending(vcpu))
@@ -4982,12 +4980,12 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
49824980
*/
49834981
kvm_vcpu_srcu_read_lock(vcpu);
49844982

4985-
do {
4983+
while (true) {
49864984
rc = vcpu_pre_run(vcpu);
4985+
kvm_vcpu_srcu_read_unlock(vcpu);
49874986
if (rc || guestdbg_exit_pending(vcpu))
49884987
break;
49894988

4990-
kvm_vcpu_srcu_read_unlock(vcpu);
49914989
/*
49924990
* As PF_VCPU will be used in fault handler, between
49934991
* guest_timing_enter_irqoff and guest_timing_exit_irqoff
@@ -4999,7 +4997,17 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
49994997
sizeof(sie_page->pv_grregs));
50004998
}
50014999

5000+
xfer_to_guest_mode_check:
50025001
local_irq_disable();
5002+
xfer_to_guest_mode_prepare();
5003+
if (xfer_to_guest_mode_work_pending()) {
5004+
local_irq_enable();
5005+
rc = kvm_xfer_to_guest_mode_handle_work(vcpu);
5006+
if (rc)
5007+
break;
5008+
goto xfer_to_guest_mode_check;
5009+
}
5010+
50035011
guest_timing_enter_irqoff();
50045012
__disable_cpu_timer_accounting(vcpu);
50055013

@@ -5029,9 +5037,12 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
50295037
kvm_vcpu_srcu_read_lock(vcpu);
50305038

50315039
rc = vcpu_post_run(vcpu, exit_reason);
5032-
} while (!signal_pending(current) && !guestdbg_exit_pending(vcpu) && !rc);
5040+
if (rc || guestdbg_exit_pending(vcpu)) {
5041+
kvm_vcpu_srcu_read_unlock(vcpu);
5042+
break;
5043+
}
5044+
}
50335045

5034-
kvm_vcpu_srcu_read_unlock(vcpu);
50355046
return rc;
50365047
}
50375048

arch/s390/kvm/vsie.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,12 +1180,23 @@ static int do_vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
11801180
current->thread.gmap_int_code = 0;
11811181
barrier();
11821182
if (!kvm_s390_vcpu_sie_inhibited(vcpu)) {
1183+
xfer_to_guest_mode_check:
11831184
local_irq_disable();
1185+
xfer_to_guest_mode_prepare();
1186+
if (xfer_to_guest_mode_work_pending()) {
1187+
local_irq_enable();
1188+
rc = kvm_xfer_to_guest_mode_handle_work(vcpu);
1189+
if (rc)
1190+
goto skip_sie;
1191+
goto xfer_to_guest_mode_check;
1192+
}
11841193
guest_timing_enter_irqoff();
11851194
rc = kvm_s390_enter_exit_sie(scb_s, vcpu->run->s.regs.gprs, vsie_page->gmap->asce);
11861195
guest_timing_exit_irqoff();
11871196
local_irq_enable();
11881197
}
1198+
1199+
skip_sie:
11891200
barrier();
11901201
vcpu->arch.sie_block->prog0c &= ~PROG_IN_SIE;
11911202

@@ -1345,13 +1356,11 @@ static int vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
13451356
* but rewind the PSW to re-enter SIE once that's completed
13461357
* instead of passing a "no action" intercept to the guest.
13471358
*/
1348-
if (signal_pending(current) ||
1349-
kvm_s390_vcpu_has_irq(vcpu, 0) ||
1359+
if (kvm_s390_vcpu_has_irq(vcpu, 0) ||
13501360
kvm_s390_vcpu_sie_inhibited(vcpu)) {
13511361
kvm_s390_rewind_psw(vcpu, 4);
13521362
break;
13531363
}
1354-
cond_resched();
13551364
}
13561365

13571366
if (rc == -EFAULT) {
@@ -1483,8 +1492,7 @@ int kvm_s390_handle_vsie(struct kvm_vcpu *vcpu)
14831492
if (unlikely(scb_addr & 0x1ffUL))
14841493
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
14851494

1486-
if (signal_pending(current) || kvm_s390_vcpu_has_irq(vcpu, 0) ||
1487-
kvm_s390_vcpu_sie_inhibited(vcpu)) {
1495+
if (kvm_s390_vcpu_has_irq(vcpu, 0) || kvm_s390_vcpu_sie_inhibited(vcpu)) {
14881496
kvm_s390_rewind_psw(vcpu, 4);
14891497
return 0;
14901498
}

0 commit comments

Comments
 (0)