diff options
author | Jan Kiszka <jan.kiszka@siemens.com> | 2012-09-20 23:42:55 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2012-09-23 09:00:07 -0400 |
commit | c863901075a42d50678616d8ee4b96ef13080498 (patch) | |
tree | 947ffa1bd109f15b9cb483c8257fb028d0ed7df3 /arch/x86/kvm/x86.c | |
parent | 7a84428af7ca6a847f058c9ff244a18a2664fd1b (diff) |
KVM: x86: Fix guest debug across vcpu INIT reset
If we reset a vcpu on INIT, we so far overwrote dr7 as provided by
KVM_SET_GUEST_DEBUG, and we also cleared switch_db_regs unconditionally.
Fix this by saving the dr7 used for guest debugging and calculating the
effective register value as well as switch_db_regs on any potential
change. This will change to focus of the set_guest_debug vendor op to
update_dp_bp_intercept.
Found while trying to stop on start_secondary.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 7d44204c6041..b16d4a5bfa41 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -692,6 +692,18 @@ unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu) | |||
692 | } | 692 | } |
693 | EXPORT_SYMBOL_GPL(kvm_get_cr8); | 693 | EXPORT_SYMBOL_GPL(kvm_get_cr8); |
694 | 694 | ||
695 | static void kvm_update_dr7(struct kvm_vcpu *vcpu) | ||
696 | { | ||
697 | unsigned long dr7; | ||
698 | |||
699 | if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) | ||
700 | dr7 = vcpu->arch.guest_debug_dr7; | ||
701 | else | ||
702 | dr7 = vcpu->arch.dr7; | ||
703 | kvm_x86_ops->set_dr7(vcpu, dr7); | ||
704 | vcpu->arch.switch_db_regs = (dr7 & DR7_BP_EN_MASK); | ||
705 | } | ||
706 | |||
695 | static int __kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val) | 707 | static int __kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val) |
696 | { | 708 | { |
697 | switch (dr) { | 709 | switch (dr) { |
@@ -717,10 +729,7 @@ static int __kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val) | |||
717 | if (val & 0xffffffff00000000ULL) | 729 | if (val & 0xffffffff00000000ULL) |
718 | return -1; /* #GP */ | 730 | return -1; /* #GP */ |
719 | vcpu->arch.dr7 = (val & DR7_VOLATILE) | DR7_FIXED_1; | 731 | vcpu->arch.dr7 = (val & DR7_VOLATILE) | DR7_FIXED_1; |
720 | if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) { | 732 | kvm_update_dr7(vcpu); |
721 | kvm_x86_ops->set_dr7(vcpu, vcpu->arch.dr7); | ||
722 | vcpu->arch.switch_db_regs = (val & DR7_BP_EN_MASK); | ||
723 | } | ||
724 | break; | 733 | break; |
725 | } | 734 | } |
726 | 735 | ||
@@ -5851,13 +5860,12 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, | |||
5851 | if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) { | 5860 | if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) { |
5852 | for (i = 0; i < KVM_NR_DB_REGS; ++i) | 5861 | for (i = 0; i < KVM_NR_DB_REGS; ++i) |
5853 | vcpu->arch.eff_db[i] = dbg->arch.debugreg[i]; | 5862 | vcpu->arch.eff_db[i] = dbg->arch.debugreg[i]; |
5854 | vcpu->arch.switch_db_regs = | 5863 | vcpu->arch.guest_debug_dr7 = dbg->arch.debugreg[7]; |
5855 | (dbg->arch.debugreg[7] & DR7_BP_EN_MASK); | ||
5856 | } else { | 5864 | } else { |
5857 | for (i = 0; i < KVM_NR_DB_REGS; i++) | 5865 | for (i = 0; i < KVM_NR_DB_REGS; i++) |
5858 | vcpu->arch.eff_db[i] = vcpu->arch.db[i]; | 5866 | vcpu->arch.eff_db[i] = vcpu->arch.db[i]; |
5859 | vcpu->arch.switch_db_regs = (vcpu->arch.dr7 & DR7_BP_EN_MASK); | ||
5860 | } | 5867 | } |
5868 | kvm_update_dr7(vcpu); | ||
5861 | 5869 | ||
5862 | if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) | 5870 | if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) |
5863 | vcpu->arch.singlestep_rip = kvm_rip_read(vcpu) + | 5871 | vcpu->arch.singlestep_rip = kvm_rip_read(vcpu) + |
@@ -5869,7 +5877,7 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, | |||
5869 | */ | 5877 | */ |
5870 | kvm_set_rflags(vcpu, rflags); | 5878 | kvm_set_rflags(vcpu, rflags); |
5871 | 5879 | ||
5872 | kvm_x86_ops->set_guest_debug(vcpu, dbg); | 5880 | kvm_x86_ops->update_db_bp_intercept(vcpu); |
5873 | 5881 | ||
5874 | r = 0; | 5882 | r = 0; |
5875 | 5883 | ||
@@ -6045,10 +6053,10 @@ int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu) | |||
6045 | vcpu->arch.nmi_pending = 0; | 6053 | vcpu->arch.nmi_pending = 0; |
6046 | vcpu->arch.nmi_injected = false; | 6054 | vcpu->arch.nmi_injected = false; |
6047 | 6055 | ||
6048 | vcpu->arch.switch_db_regs = 0; | ||
6049 | memset(vcpu->arch.db, 0, sizeof(vcpu->arch.db)); | 6056 | memset(vcpu->arch.db, 0, sizeof(vcpu->arch.db)); |
6050 | vcpu->arch.dr6 = DR6_FIXED_1; | 6057 | vcpu->arch.dr6 = DR6_FIXED_1; |
6051 | vcpu->arch.dr7 = DR7_FIXED_1; | 6058 | vcpu->arch.dr7 = DR7_FIXED_1; |
6059 | kvm_update_dr7(vcpu); | ||
6052 | 6060 | ||
6053 | kvm_make_request(KVM_REQ_EVENT, vcpu); | 6061 | kvm_make_request(KVM_REQ_EVENT, vcpu); |
6054 | vcpu->arch.apf.msr_val = 0; | 6062 | vcpu->arch.apf.msr_val = 0; |