From: Joerg R. <joe...@am...> - 2008-02-14 16:57:30
|
This patch implements guest debug support for KVM running on AMD hardware. Signed-off-by: Joerg Roedel <joe...@am...> --- arch/x86/kvm/svm.c | 37 ++++++++++++++++++++++++++++++++++--- 1 files changed, 34 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 094a9c2..ebf75bf 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -919,7 +919,30 @@ static void svm_set_segment(struct kvm_vcpu *vcpu, static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg, unsigned long dr7) { - return -EOPNOTSUPP; + struct vcpu_svm *svm = to_svm(vcpu); + + if (vcpu->guest_debug.enabled) { + vcpu->guest_debug.singlestep = dbg->singlestep; + svm->vmcb->control.intercept_exceptions |= (1 << DB_VECTOR); + } else { + vcpu->guest_debug.singlestep = 0; + svm->vmcb->control.intercept_exceptions &= ~(1 << DB_VECTOR); + } + + if (!vcpu->guest_debug.singlestep) + svm->vmcb->save.rflags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF); + + svm->vmcb->save.dr7 = dr7; + + return 0; +} + +static void svm_guest_debug_pre(struct kvm_vcpu *vcpu) +{ + struct vcpu_svm *svm = to_svm(vcpu); + + if (vcpu->guest_debug.singlestep) + svm->vmcb->save.rflags |= X86_EFLAGS_TF | X86_EFLAGS_RF; } static int svm_get_irq(struct kvm_vcpu *vcpu) @@ -1019,6 +1042,12 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) return kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code); } +static int db_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) +{ + kvm_run->exit_reason = KVM_EXIT_DEBUG; + return 0; +} + static int ud_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) { int er; @@ -1350,6 +1379,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm, [SVM_EXIT_WRITE_DR3] = emulate_on_interception, [SVM_EXIT_WRITE_DR5] = emulate_on_interception, [SVM_EXIT_WRITE_DR7] = emulate_on_interception, + [SVM_EXIT_EXCP_BASE + DB_VECTOR] = db_interception, [SVM_EXIT_EXCP_BASE + UD_VECTOR] = ud_interception, [SVM_EXIT_EXCP_BASE + PF_VECTOR] = pf_interception, [SVM_EXIT_EXCP_BASE + NM_VECTOR] = nm_interception, @@ -1612,7 +1642,7 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) if (npt_enabled) svm->vmcb->save.cr3 = vcpu->arch.cr3; - if (svm->vmcb->save.dr7 & 0xff) { + if (!vcpu->guest_debug.enabled && svm->vmcb->save.dr7 & 0xff) { write_dr7(0); save_db_regs(svm->host_db_regs); load_db_regs(svm->db_regs); @@ -1727,7 +1757,7 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) #endif ); - if ((svm->vmcb->save.dr7 & 0xff)) + if (!vcpu->guest_debug.enabled && (svm->vmcb->save.dr7 & 0xff)) load_db_regs(svm->host_db_regs); vcpu->arch.cr2 = svm->vmcb->save.cr2; @@ -1822,6 +1852,7 @@ static struct kvm_x86_ops svm_x86_ops = { .vcpu_decache = svm_vcpu_decache, .set_guest_debug = svm_guest_debug, + .guest_debug_pre = svm_guest_debug_pre, .get_msr = svm_get_msr, .set_msr = svm_set_msr, .get_segment_base = svm_get_segment_base, -- 1.5.3.7 |