aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/svm.c
diff options
context:
space:
mode:
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,