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/svm.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/svm.c')
| -rw-r--r-- | arch/x86/kvm/svm.c | 23 |
1 files changed, 4 insertions, 19 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 818fceb3091e..d017df3899ef 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
| @@ -1146,7 +1146,6 @@ static void init_vmcb(struct vcpu_svm *svm) | |||
| 1146 | 1146 | ||
| 1147 | svm_set_efer(&svm->vcpu, 0); | 1147 | svm_set_efer(&svm->vcpu, 0); |
| 1148 | save->dr6 = 0xffff0ff0; | 1148 | save->dr6 = 0xffff0ff0; |
| 1149 | save->dr7 = 0x400; | ||
| 1150 | kvm_set_rflags(&svm->vcpu, 2); | 1149 | kvm_set_rflags(&svm->vcpu, 2); |
| 1151 | save->rip = 0x0000fff0; | 1150 | save->rip = 0x0000fff0; |
| 1152 | svm->vcpu.arch.regs[VCPU_REGS_RIP] = save->rip; | 1151 | svm->vcpu.arch.regs[VCPU_REGS_RIP] = save->rip; |
| @@ -1643,7 +1642,7 @@ static void svm_set_segment(struct kvm_vcpu *vcpu, | |||
| 1643 | mark_dirty(svm->vmcb, VMCB_SEG); | 1642 | mark_dirty(svm->vmcb, VMCB_SEG); |
| 1644 | } | 1643 | } |
| 1645 | 1644 | ||
| 1646 | static void update_db_intercept(struct kvm_vcpu *vcpu) | 1645 | static void update_db_bp_intercept(struct kvm_vcpu *vcpu) |
| 1647 | { | 1646 | { |
| 1648 | struct vcpu_svm *svm = to_svm(vcpu); | 1647 | struct vcpu_svm *svm = to_svm(vcpu); |
| 1649 | 1648 | ||
| @@ -1663,20 +1662,6 @@ static void update_db_intercept(struct kvm_vcpu *vcpu) | |||
| 1663 | vcpu->guest_debug = 0; | 1662 | vcpu->guest_debug = 0; |
| 1664 | } | 1663 | } |
| 1665 | 1664 | ||
| 1666 | static void svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg) | ||
| 1667 | { | ||
| 1668 | struct vcpu_svm *svm = to_svm(vcpu); | ||
| 1669 | |||
| 1670 | if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) | ||
| 1671 | svm->vmcb->save.dr7 = dbg->arch.debugreg[7]; | ||
| 1672 | else | ||
| 1673 | svm->vmcb->save.dr7 = vcpu->arch.dr7; | ||
| 1674 | |||
| 1675 | mark_dirty(svm->vmcb, VMCB_DR); | ||
| 1676 | |||
| 1677 | update_db_intercept(vcpu); | ||
| 1678 | } | ||
| 1679 | |||
| 1680 | static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *sd) | 1665 | static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *sd) |
| 1681 | { | 1666 | { |
| 1682 | if (sd->next_asid > sd->max_asid) { | 1667 | if (sd->next_asid > sd->max_asid) { |
| @@ -1748,7 +1733,7 @@ static int db_interception(struct vcpu_svm *svm) | |||
| 1748 | if (!(svm->vcpu.guest_debug & KVM_GUESTDBG_SINGLESTEP)) | 1733 | if (!(svm->vcpu.guest_debug & KVM_GUESTDBG_SINGLESTEP)) |
| 1749 | svm->vmcb->save.rflags &= | 1734 | svm->vmcb->save.rflags &= |
| 1750 | ~(X86_EFLAGS_TF | X86_EFLAGS_RF); | 1735 | ~(X86_EFLAGS_TF | X86_EFLAGS_RF); |
| 1751 | update_db_intercept(&svm->vcpu); | 1736 | update_db_bp_intercept(&svm->vcpu); |
| 1752 | } | 1737 | } |
| 1753 | 1738 | ||
| 1754 | if (svm->vcpu.guest_debug & | 1739 | if (svm->vcpu.guest_debug & |
| @@ -3659,7 +3644,7 @@ static void enable_nmi_window(struct kvm_vcpu *vcpu) | |||
| 3659 | */ | 3644 | */ |
| 3660 | svm->nmi_singlestep = true; | 3645 | svm->nmi_singlestep = true; |
| 3661 | svm->vmcb->save.rflags |= (X86_EFLAGS_TF | X86_EFLAGS_RF); | 3646 | svm->vmcb->save.rflags |= (X86_EFLAGS_TF | X86_EFLAGS_RF); |
| 3662 | update_db_intercept(vcpu); | 3647 | update_db_bp_intercept(vcpu); |
| 3663 | } | 3648 | } |
| 3664 | 3649 | ||
| 3665 | static int svm_set_tss_addr(struct kvm *kvm, unsigned int addr) | 3650 | static int svm_set_tss_addr(struct kvm *kvm, unsigned int addr) |
| @@ -4253,7 +4238,7 @@ static struct kvm_x86_ops svm_x86_ops = { | |||
| 4253 | .vcpu_load = svm_vcpu_load, | 4238 | .vcpu_load = svm_vcpu_load, |
| 4254 | .vcpu_put = svm_vcpu_put, | 4239 | .vcpu_put = svm_vcpu_put, |
| 4255 | 4240 | ||
| 4256 | .set_guest_debug = svm_guest_debug, | 4241 | .update_db_bp_intercept = update_db_bp_intercept, |
| 4257 | .get_msr = svm_get_msr, | 4242 | .get_msr = svm_get_msr, |
| 4258 | .set_msr = svm_set_msr, | 4243 | .set_msr = svm_set_msr, |
| 4259 | .get_segment_base = svm_get_segment_base, | 4244 | .get_segment_base = svm_get_segment_base, |
