From: Jan K. <jan...@we...> - 2008-05-16 16:02:21
|
In order to allow the gdbstub of QEMU to push (soft) breakpoint handling completely into the gdb frontend, this patch enables guest exits also for #BP exceptions - in case guest debugging was turned on. Along this enhancement, this patch also fixes the flag manipulation for the singlestep mode. --- arch/x86/kvm/vmx.c | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) Index: b/arch/x86/kvm/vmx.c =================================================================== --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -461,7 +461,7 @@ static void update_exception_bitmap(stru if (!vcpu->fpu_active) eb |= 1u << NM_VECTOR; if (vcpu->guest_debug.enabled) - eb |= 1u << 1; + eb |= (1u << 1) | (1u << 3); if (vcpu->arch.rmode.active) eb = ~0; if (vm_need_ept()) @@ -949,6 +949,7 @@ static int set_guest_debug(struct kvm_vc { unsigned long dr7 = 0x400; int old_singlestep; + unsigned long flags; old_singlestep = vcpu->guest_debug.singlestep; @@ -969,13 +970,12 @@ static int set_guest_debug(struct kvm_vc } else vcpu->guest_debug.singlestep = 0; - if (old_singlestep && !vcpu->guest_debug.singlestep) { - unsigned long flags; - - flags = vmcs_readl(GUEST_RFLAGS); + flags = vmcs_readl(GUEST_RFLAGS); + if (vcpu->guest_debug.singlestep) + flags |= X86_EFLAGS_TF | X86_EFLAGS_RF; + else if (old_singlestep && !vcpu->guest_debug.singlestep) flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF); - vmcs_writel(GUEST_RFLAGS, flags); - } + vmcs_writel(GUEST_RFLAGS, flags); update_exception_bitmap(vcpu); vmcs_writel(GUEST_DR7, dr7); @@ -2192,14 +2192,6 @@ static void kvm_guest_debug_pre(struct k set_debugreg(dbg->bp[1], 1); set_debugreg(dbg->bp[2], 2); set_debugreg(dbg->bp[3], 3); - - if (dbg->singlestep) { - unsigned long flags; - - flags = vmcs_readl(GUEST_RFLAGS); - flags |= X86_EFLAGS_TF | X86_EFLAGS_RF; - vmcs_writel(GUEST_RFLAGS, flags); - } } static int handle_rmode_exception(struct kvm_vcpu *vcpu, @@ -2221,7 +2213,7 @@ static int handle_rmode_exception(struct static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) { struct vcpu_vmx *vmx = to_vmx(vcpu); - u32 intr_info, error_code; + u32 intr_info, ex_no, error_code; unsigned long cr2, rip; u32 vect_info; enum emulation_result er; @@ -2279,15 +2271,15 @@ static int handle_exception(struct kvm_v return 1; } - if ((intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VECTOR_MASK)) == - (INTR_TYPE_EXCEPTION | 1)) { + ex_no = intr_info & INTR_INFO_VECTOR_MASK; + if (ex_no == 1 || ex_no == 3) { kvm_run->exit_reason = KVM_EXIT_DEBUG; - kvm_run->debug.arch.exception = 1; - return 0; + kvm_run->debug.arch.exception = ex_no; + } else { + kvm_run->exit_reason = KVM_EXIT_EXCEPTION; + kvm_run->ex.exception = ex_no; + kvm_run->ex.error_code = error_code; } - kvm_run->exit_reason = KVM_EXIT_EXCEPTION; - kvm_run->ex.exception = intr_info & INTR_INFO_VECTOR_MASK; - kvm_run->ex.error_code = error_code; return 0; } |