From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jan Kiszka Subject: [PATCH] KVM: x86: Fix guest single-stepping while interruptible Date: Sun, 18 Oct 2009 13:24:44 +0200 Message-ID: <4ADAFAFC.2010603@web.de> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="------------enig8114EF129B1F7971ADE80B35" Cc: kvm-devel To: Avi Kivity , Marcelo Tosatti Return-path: Received: from fmmailgate02.web.de ([217.72.192.227]:37702 "EHLO fmmailgate02.web.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752844AbZJRLYq (ORCPT ); Sun, 18 Oct 2009 07:24:46 -0400 Sender: kvm-owner@vger.kernel.org List-ID: This is an OpenPGP/MIME signed message (RFC 2440 and 3156) --------------enig8114EF129B1F7971ADE80B35 Content-Type: text/plain; charset=ISO-8859-15 Content-Transfer-Encoding: quoted-printable Commit 705c5323 opened the doors of hell by unconditionally injecting single-step flags as long as guest_debug signaled this. This doesn't work when the guest branches into some interrupt or exception handler and triggers a vmexit with flag reloading. Fix it by saving cs:rip when user space requests single-stepping and restricting the trace flag injection to this guest code position. Signed-off-by: Jan Kiszka --- arch/x86/include/asm/kvm_host.h | 4 +++ arch/x86/kvm/x86.c | 47 +++++++++++++++++++++++----------= ------ 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_h= ost.h index 179a919..c6094f1 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -371,6 +371,10 @@ struct kvm_vcpu_arch { u64 mcg_status; u64 mcg_ctl; u64 *mce_banks; + + /* used for guest single stepping over the given code position */ + u16 singlestep_cs; + unsigned long singlestep_rip; }; =20 struct kvm_mem_alias { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index c1e9094..c30ed79 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -235,25 +235,6 @@ bool kvm_require_cpl(struct kvm_vcpu *vcpu, int requ= ired_cpl) } EXPORT_SYMBOL_GPL(kvm_require_cpl); =20 -unsigned long kvm_get_rflags(struct kvm_vcpu *vcpu) -{ - unsigned long rflags; - - rflags =3D kvm_x86_ops->get_rflags(vcpu); - if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) - rflags &=3D ~(unsigned long)(X86_EFLAGS_TF | X86_EFLAGS_RF); - return rflags; -} -EXPORT_SYMBOL_GPL(kvm_get_rflags); - -void kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags) -{ - if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) - rflags |=3D X86_EFLAGS_TF | X86_EFLAGS_RF; - kvm_x86_ops->set_rflags(vcpu, rflags); -} -EXPORT_SYMBOL_GPL(kvm_set_rflags); - /* * Load the pae pdptrs. Return true is they are all valid. */ @@ -4519,6 +4500,12 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm= _vcpu *vcpu, vcpu->arch.switch_db_regs =3D (vcpu->arch.dr7 & DR7_BP_EN_MASK); } =20 + if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) { + vcpu->arch.singlestep_cs =3D + get_segment_selector(vcpu, VCPU_SREG_CS); + vcpu->arch.singlestep_rip =3D kvm_rip_read(vcpu); + } + /* * Trigger an rflags update that will inject or remove the trace * flags. @@ -4985,6 +4972,28 @@ int kvm_arch_interrupt_allowed(struct kvm_vcpu *vc= pu) return kvm_x86_ops->interrupt_allowed(vcpu); } =20 +unsigned long kvm_get_rflags(struct kvm_vcpu *vcpu) +{ + unsigned long rflags; + + rflags =3D kvm_x86_ops->get_rflags(vcpu); + if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) + rflags &=3D ~(unsigned long)(X86_EFLAGS_TF | X86_EFLAGS_RF); + return rflags; +} +EXPORT_SYMBOL_GPL(kvm_get_rflags); + +void kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags) +{ + if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP && + vcpu->arch.singlestep_cs =3D=3D + get_segment_selector(vcpu, VCPU_SREG_CS) && + vcpu->arch.singlestep_rip =3D=3D kvm_rip_read(vcpu)) + rflags |=3D X86_EFLAGS_TF | X86_EFLAGS_RF; + kvm_x86_ops->set_rflags(vcpu, rflags); +} +EXPORT_SYMBOL_GPL(kvm_set_rflags); + EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_exit); EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_inj_virq); EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_page_fault); --------------enig8114EF129B1F7971ADE80B35 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.9 (GNU/Linux) Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org iEYEARECAAYFAkra+wAACgkQitSsb3rl5xToegCgisOGjoDaNDWQN/bs5HLLxLTk xbwAnA1i+uWJ7mK8iKU/kjM/bFnbDD42 =CaxX -----END PGP SIGNATURE----- --------------enig8114EF129B1F7971ADE80B35--