diff options
-rw-r--r-- | arch/x86/kvm/svm.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 86d802be602d..a449c3d76cba 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <asm/perf_event.h> | 34 | #include <asm/perf_event.h> |
35 | #include <asm/tlbflush.h> | 35 | #include <asm/tlbflush.h> |
36 | #include <asm/desc.h> | 36 | #include <asm/desc.h> |
37 | #include <asm/debugreg.h> | ||
37 | #include <asm/kvm_para.h> | 38 | #include <asm/kvm_para.h> |
38 | 39 | ||
39 | #include <asm/virtext.h> | 40 | #include <asm/virtext.h> |
@@ -1683,6 +1684,21 @@ static void svm_set_dr6(struct kvm_vcpu *vcpu, unsigned long value) | |||
1683 | mark_dirty(svm->vmcb, VMCB_DR); | 1684 | mark_dirty(svm->vmcb, VMCB_DR); |
1684 | } | 1685 | } |
1685 | 1686 | ||
1687 | static void svm_sync_dirty_debug_regs(struct kvm_vcpu *vcpu) | ||
1688 | { | ||
1689 | struct vcpu_svm *svm = to_svm(vcpu); | ||
1690 | |||
1691 | get_debugreg(vcpu->arch.db[0], 0); | ||
1692 | get_debugreg(vcpu->arch.db[1], 1); | ||
1693 | get_debugreg(vcpu->arch.db[2], 2); | ||
1694 | get_debugreg(vcpu->arch.db[3], 3); | ||
1695 | vcpu->arch.dr6 = svm_get_dr6(vcpu); | ||
1696 | vcpu->arch.dr7 = svm->vmcb->save.dr7; | ||
1697 | |||
1698 | vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_WONT_EXIT; | ||
1699 | set_dr_intercepts(svm); | ||
1700 | } | ||
1701 | |||
1686 | static void svm_set_dr7(struct kvm_vcpu *vcpu, unsigned long value) | 1702 | static void svm_set_dr7(struct kvm_vcpu *vcpu, unsigned long value) |
1687 | { | 1703 | { |
1688 | struct vcpu_svm *svm = to_svm(vcpu); | 1704 | struct vcpu_svm *svm = to_svm(vcpu); |
@@ -2974,6 +2990,17 @@ static int dr_interception(struct vcpu_svm *svm) | |||
2974 | unsigned long val; | 2990 | unsigned long val; |
2975 | int err; | 2991 | int err; |
2976 | 2992 | ||
2993 | if (svm->vcpu.guest_debug == 0) { | ||
2994 | /* | ||
2995 | * No more DR vmexits; force a reload of the debug registers | ||
2996 | * and reenter on this instruction. The next vmexit will | ||
2997 | * retrieve the full state of the debug registers. | ||
2998 | */ | ||
2999 | clr_dr_intercepts(svm); | ||
3000 | svm->vcpu.arch.switch_db_regs |= KVM_DEBUGREG_WONT_EXIT; | ||
3001 | return 1; | ||
3002 | } | ||
3003 | |||
2977 | if (!boot_cpu_has(X86_FEATURE_DECODEASSISTS)) | 3004 | if (!boot_cpu_has(X86_FEATURE_DECODEASSISTS)) |
2978 | return emulate_on_interception(svm); | 3005 | return emulate_on_interception(svm); |
2979 | 3006 | ||
@@ -4300,6 +4327,7 @@ static struct kvm_x86_ops svm_x86_ops = { | |||
4300 | .get_dr6 = svm_get_dr6, | 4327 | .get_dr6 = svm_get_dr6, |
4301 | .set_dr6 = svm_set_dr6, | 4328 | .set_dr6 = svm_set_dr6, |
4302 | .set_dr7 = svm_set_dr7, | 4329 | .set_dr7 = svm_set_dr7, |
4330 | .sync_dirty_debug_regs = svm_sync_dirty_debug_regs, | ||
4303 | .cache_reg = svm_cache_reg, | 4331 | .cache_reg = svm_cache_reg, |
4304 | .get_rflags = svm_get_rflags, | 4332 | .get_rflags = svm_get_rflags, |
4305 | .set_rflags = svm_set_rflags, | 4333 | .set_rflags = svm_set_rflags, |