Message ID | 20230724094716.91510-4-iii@linux.ibm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | KVM: s390: interrupt: Fix stepping into interrupt handlers | expand |
On Mon, 24 Jul 2023 11:44:09 +0200 Ilya Leoshkevich <iii@linux.ibm.com> wrote: > Single-stepping a kernel-emulated instruction that generates an > interrupt causes GDB to land on the instruction following it instead of > the respective interrupt handler. > > The reason is that kvm_handle_sie_intercept(), after injecting the > interrupt, also processes the PER event and arranges a KVM_SINGLESTEP > exit. The interrupt is not yet delivered, however, so the userspace > sees the next instruction. > > Fix by avoiding the KVM_SINGLESTEP exit when there is a pending > interrupt. The next __vcpu_run() loop iteration will arrange a > KVM_SINGLESTEP exit after delivering the interrupt. > > Reviewed-by: David Hildenbrand <david@redhat.com> Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com> > Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> > --- > arch/s390/kvm/intercept.c | 17 ++++++++++++++--- > 1 file changed, 14 insertions(+), 3 deletions(-) > > diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c > index 7cdd927541b0..d2f7940c5d03 100644 > --- a/arch/s390/kvm/intercept.c > +++ b/arch/s390/kvm/intercept.c > @@ -583,6 +583,19 @@ static int handle_pv_notification(struct kvm_vcpu *vcpu) > return handle_instruction(vcpu); > } > > +static bool should_handle_per_ifetch(const struct kvm_vcpu *vcpu, int rc) > +{ > + /* Process PER, also if the instruction is processed in user space. */ > + if (!(vcpu->arch.sie_block->icptstatus & 0x02)) > + return false; > + if (rc != 0 && rc != -EOPNOTSUPP) > + return false; > + if (guestdbg_sstep_enabled(vcpu) && vcpu->arch.local_int.pending_irqs) > + /* __vcpu_run() will exit after delivering the interrupt. */ > + return false; > + return true; > +} > + > int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu) > { > int rc, per_rc = 0; > @@ -645,9 +658,7 @@ int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu) > return -EOPNOTSUPP; > } > > - /* process PER, also if the instruction is processed in user space */ > - if (vcpu->arch.sie_block->icptstatus & 0x02 && > - (!rc || rc == -EOPNOTSUPP)) > + if (should_handle_per_ifetch(vcpu, rc)) > per_rc = kvm_s390_handle_per_ifetch_icpt(vcpu); > return per_rc ? per_rc : rc; > }
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index 7cdd927541b0..d2f7940c5d03 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c @@ -583,6 +583,19 @@ static int handle_pv_notification(struct kvm_vcpu *vcpu) return handle_instruction(vcpu); } +static bool should_handle_per_ifetch(const struct kvm_vcpu *vcpu, int rc) +{ + /* Process PER, also if the instruction is processed in user space. */ + if (!(vcpu->arch.sie_block->icptstatus & 0x02)) + return false; + if (rc != 0 && rc != -EOPNOTSUPP) + return false; + if (guestdbg_sstep_enabled(vcpu) && vcpu->arch.local_int.pending_irqs) + /* __vcpu_run() will exit after delivering the interrupt. */ + return false; + return true; +} + int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu) { int rc, per_rc = 0; @@ -645,9 +658,7 @@ int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu) return -EOPNOTSUPP; } - /* process PER, also if the instruction is processed in user space */ - if (vcpu->arch.sie_block->icptstatus & 0x02 && - (!rc || rc == -EOPNOTSUPP)) + if (should_handle_per_ifetch(vcpu, rc)) per_rc = kvm_s390_handle_per_ifetch_icpt(vcpu); return per_rc ? per_rc : rc; }