Hi,
I tried to compare the behavior of KVM and TCG by diffing instruction
traces, and found two issues in KVM related to stepping into interrupt
handlers.
I'm not very familiar with the KVM code base, so please let me know if
the fixes can be improved or if these problems need to be handled
completely differently.
Best regards,
Ilya
Ilya Leoshkevich (2):
KVM: s390: interrupt: Fix stepping into interrupt handlers
KVM: s390: interrupt: Fix stepping into program interrupt handlers
arch/s390/kvm/intercept.c | 19 +++++++++++++++++--
arch/s390/kvm/interrupt.c | 10 ++++++++++
arch/s390/kvm/kvm-s390.c | 4 ++--
3 files changed, 29 insertions(+), 4 deletions(-)
--
2.41.0
Currently, after single-stepping an instruction that causes a
specification exception, GDB ends up on the instruction immediately
following it.
The reason is that vcpu_post_run() injects the interrupt and sets
KVM_GUESTDBG_EXIT_PENDING, causing a KVM_SINGLESTEP exit. The
interrupt is not delivered, however, therefore userspace sees the
address of the next instruction.
Fix by letting the __vcpu_run() loop go into the next iteration,
where vcpu_pre_run() delivers the interrupt and sets
KVM_GUESTDBG_EXIT_PENDING.
Signed-off-by: Ilya Leoshkevich <[email protected]>
---
arch/s390/kvm/intercept.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index 0ee02dae14b2..f8adb64ebda1 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -226,7 +226,22 @@ static int handle_itdb(struct kvm_vcpu *vcpu)
return 0;
}
-#define per_event(vcpu) (vcpu->arch.sie_block->iprcc & PGM_PER)
+static bool should_handle_per_event(struct kvm_vcpu *vcpu)
+{
+ if (!guestdbg_enabled(vcpu))
+ return false;
+ if (!(vcpu->arch.sie_block->iprcc & PGM_PER))
+ return false;
+ if (guestdbg_sstep_enabled(vcpu) &&
+ vcpu->arch.sie_block->iprcc != PGM_PER) {
+ /*
+ * __vcpu_run() will exit after delivering the concurrently
+ * indicated condition.
+ */
+ return false;
+ }
+ return true;
+}
static int handle_prog(struct kvm_vcpu *vcpu)
{
@@ -242,7 +257,7 @@ static int handle_prog(struct kvm_vcpu *vcpu)
if (kvm_s390_pv_cpu_is_protected(vcpu))
return -EOPNOTSUPP;
- if (guestdbg_enabled(vcpu) && per_event(vcpu)) {
+ if (should_handle_per_event(vcpu)) {
rc = kvm_s390_handle_per_event(vcpu);
if (rc)
return rc;
--
2.41.0