aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/svm.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
commitd0bfb940ecabf0b44fb1fd80d8d60594e569e5ec (patch)
treeb5927d44937a54ec23d2a28d59db06a0262c0412 /arch/x86/kvm/svm.c
parent8ab2d2e231062814bd89bba2d6d92563190aa2bb (diff)
KVM: New guest debug interface
This rips out the support for KVM_DEBUG_GUEST and introduces a new IOCTL instead: KVM_SET_GUEST_DEBUG. The IOCTL payload consists of a generic part, controlling the "main switch" and the single-step feature. The arch specific part adds an x86 interface for intercepting both types of debug exceptions separately and re-injecting them when the host was not interested. Moveover, the foundation for guest debugging via debug registers is layed. To signal breakpoint events properly back to userland, an arch-specific data block is now returned along KVM_EXIT_DEBUG. For x86, the arch block contains the PC, the debug exception, and relevant debug registers to tell debug events properly apart. The availability of this new interface is signaled by KVM_CAP_SET_GUEST_DEBUG. Empty stubs for not yet supported archs are provided. Note that both SVM and VTX are supported, but only the latter was tested yet. Based on the experience with all those VTX corner case, I would be fairly surprised if SVM will work out of the box. 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.c50
1 files changed, 48 insertions, 2 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 0fbbde54ecae..88d9062f4545 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -968,9 +968,32 @@ static void svm_set_segment(struct kvm_vcpu *vcpu,
968 968
969} 969}
970 970
971static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg) 971static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg)
972{ 972{
973 return -EOPNOTSUPP; 973 int old_debug = vcpu->guest_debug;
974 struct vcpu_svm *svm = to_svm(vcpu);
975
976 vcpu->guest_debug = dbg->control;
977
978 svm->vmcb->control.intercept_exceptions &=
979 ~((1 << DB_VECTOR) | (1 << BP_VECTOR));
980 if (vcpu->guest_debug & KVM_GUESTDBG_ENABLE) {
981 if (vcpu->guest_debug &
982 (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))
983 svm->vmcb->control.intercept_exceptions |=
984 1 << DB_VECTOR;
985 if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
986 svm->vmcb->control.intercept_exceptions |=
987 1 << BP_VECTOR;
988 } else
989 vcpu->guest_debug = 0;
990
991 if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
992 svm->vmcb->save.rflags |= X86_EFLAGS_TF | X86_EFLAGS_RF;
993 else if (old_debug & KVM_GUESTDBG_SINGLESTEP)
994 svm->vmcb->save.rflags &= ~(X86_EFLAGS_TF | X86_EFLAGS_RF);
995
996 return 0;
974} 997}
975 998
976static int svm_get_irq(struct kvm_vcpu *vcpu) 999static int svm_get_irq(struct kvm_vcpu *vcpu)
@@ -1094,6 +1117,27 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
1094 return kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code); 1117 return kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code);
1095} 1118}
1096 1119
1120static int db_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
1121{
1122 if (!(svm->vcpu.guest_debug &
1123 (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))) {
1124 kvm_queue_exception(&svm->vcpu, DB_VECTOR);
1125 return 1;
1126 }
1127 kvm_run->exit_reason = KVM_EXIT_DEBUG;
1128 kvm_run->debug.arch.pc = svm->vmcb->save.cs.base + svm->vmcb->save.rip;
1129 kvm_run->debug.arch.exception = DB_VECTOR;
1130 return 0;
1131}
1132
1133static int bp_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
1134{
1135 kvm_run->exit_reason = KVM_EXIT_DEBUG;
1136 kvm_run->debug.arch.pc = svm->vmcb->save.cs.base + svm->vmcb->save.rip;
1137 kvm_run->debug.arch.exception = BP_VECTOR;
1138 return 0;
1139}
1140
1097static int ud_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run) 1141static int ud_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
1098{ 1142{
1099 int er; 1143 int er;
@@ -2050,6 +2094,8 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm,
2050 [SVM_EXIT_WRITE_DR3] = emulate_on_interception, 2094 [SVM_EXIT_WRITE_DR3] = emulate_on_interception,
2051 [SVM_EXIT_WRITE_DR5] = emulate_on_interception, 2095 [SVM_EXIT_WRITE_DR5] = emulate_on_interception,
2052 [SVM_EXIT_WRITE_DR7] = emulate_on_interception, 2096 [SVM_EXIT_WRITE_DR7] = emulate_on_interception,
2097 [SVM_EXIT_EXCP_BASE + DB_VECTOR] = db_interception,
2098 [SVM_EXIT_EXCP_BASE + BP_VECTOR] = bp_interception,
2053 [SVM_EXIT_EXCP_BASE + UD_VECTOR] = ud_interception, 2099 [SVM_EXIT_EXCP_BASE + UD_VECTOR] = ud_interception,
2054 [SVM_EXIT_EXCP_BASE + PF_VECTOR] = pf_interception, 2100 [SVM_EXIT_EXCP_BASE + PF_VECTOR] = pf_interception,
2055 [SVM_EXIT_EXCP_BASE + NM_VECTOR] = nm_interception, 2101 [SVM_EXIT_EXCP_BASE + NM_VECTOR] = nm_interception,