aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/x86.c
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@siemens.com>2008-12-15 07:52:10 -0500
committerAvi Kivity <avi@redhat.com>2009-03-24 05:02:49 -0400
commit42dbaa5a057736bf8b5c22aa42dbe975bf1080e5 (patch)
treea7e625373c1ff7477e8f6f3cd835f633f161689f /arch/x86/kvm/x86.c
parent55934c0bd3bb232a9cf902820dd63ad18ed65e49 (diff)
KVM: x86: Virtualize debug registers
So far KVM only had basic x86 debug register support, once introduced to realize guest debugging that way. The guest itself was not able to use those registers. This patch now adds (almost) full support for guest self-debugging via hardware registers. It refactors the code, moving generic parts out of SVM (VMX was already cleaned up by the KVM_SET_GUEST_DEBUG patches), and it ensures that the registers are properly switched between host and guest. This patch also prepares debug register usage by the host. The latter will (once wired-up by the following patch) allow for hardware breakpoints/watchpoints in guest code. If this is enabled, the guest will only see faked debug registers without functionality, but with content reflecting the guest's modifications. Tested on Intel only, but SVM /should/ work as well, but who knows... Known limitations: Trapping on tss switch won't work - most probably on Intel. Credits also go to Joerg Roedel - I used his once posted debugging series as platform for this patch. 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.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index e990d164b56..300bc4d42ab 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3025,10 +3025,34 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
3025 3025
3026 kvm_guest_enter(); 3026 kvm_guest_enter();
3027 3027
3028 get_debugreg(vcpu->arch.host_dr6, 6);
3029 get_debugreg(vcpu->arch.host_dr7, 7);
3030 if (unlikely(vcpu->arch.switch_db_regs)) {
3031 get_debugreg(vcpu->arch.host_db[0], 0);
3032 get_debugreg(vcpu->arch.host_db[1], 1);
3033 get_debugreg(vcpu->arch.host_db[2], 2);
3034 get_debugreg(vcpu->arch.host_db[3], 3);
3035
3036 set_debugreg(0, 7);
3037 set_debugreg(vcpu->arch.eff_db[0], 0);
3038 set_debugreg(vcpu->arch.eff_db[1], 1);
3039 set_debugreg(vcpu->arch.eff_db[2], 2);
3040 set_debugreg(vcpu->arch.eff_db[3], 3);
3041 }
3028 3042
3029 KVMTRACE_0D(VMENTRY, vcpu, entryexit); 3043 KVMTRACE_0D(VMENTRY, vcpu, entryexit);
3030 kvm_x86_ops->run(vcpu, kvm_run); 3044 kvm_x86_ops->run(vcpu, kvm_run);
3031 3045
3046 if (unlikely(vcpu->arch.switch_db_regs)) {
3047 set_debugreg(0, 7);
3048 set_debugreg(vcpu->arch.host_db[0], 0);
3049 set_debugreg(vcpu->arch.host_db[1], 1);
3050 set_debugreg(vcpu->arch.host_db[2], 2);
3051 set_debugreg(vcpu->arch.host_db[3], 3);
3052 }
3053 set_debugreg(vcpu->arch.host_dr6, 6);
3054 set_debugreg(vcpu->arch.host_dr7, 7);
3055
3032 vcpu->guest_mode = 0; 3056 vcpu->guest_mode = 0;
3033 local_irq_enable(); 3057 local_irq_enable();
3034 3058
@@ -4035,6 +4059,11 @@ int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu)
4035 vcpu->arch.nmi_pending = false; 4059 vcpu->arch.nmi_pending = false;
4036 vcpu->arch.nmi_injected = false; 4060 vcpu->arch.nmi_injected = false;
4037 4061
4062 vcpu->arch.switch_db_regs = 0;
4063 memset(vcpu->arch.db, 0, sizeof(vcpu->arch.db));
4064 vcpu->arch.dr6 = DR6_FIXED_1;
4065 vcpu->arch.dr7 = DR7_FIXED_1;
4066
4038 return kvm_x86_ops->vcpu_reset(vcpu); 4067 return kvm_x86_ops->vcpu_reset(vcpu);
4039} 4068}
4040 4069