aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/svm.c
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@siemens.com>2010-02-23 11:47:56 -0500
committerAvi Kivity <avi@redhat.com>2010-04-25 06:00:43 -0400
commit66b7138f913635b40822890ba8913548f8b285b8 (patch)
tree1dd5faf941e04ae911e0bc9e9f00869f6a0aebd2 /arch/x86/kvm/svm.c
parentf92653eeb496fe8624ac4b0d628c916a06a3d25c (diff)
KVM: SVM: Emulate nRIP feature when reinjecting INT3
When in guest debugging mode, we have to reinject those #BP software exceptions that are caused by guest-injected INT3. As older AMD processors do not support the required nRIP VMCB field, try to emulate it by moving RIP past the instruction on exception injection. Fix it up again in case the injection failed and we were able to catch this. This does not work for unintercepted faults, but it is better than doing nothing. 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.c38
1 files changed, 35 insertions, 3 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 908ec61895ce..468ff6e721ce 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -47,6 +47,7 @@ MODULE_LICENSE("GPL");
47#define SVM_FEATURE_NPT (1 << 0) 47#define SVM_FEATURE_NPT (1 << 0)
48#define SVM_FEATURE_LBRV (1 << 1) 48#define SVM_FEATURE_LBRV (1 << 1)
49#define SVM_FEATURE_SVML (1 << 2) 49#define SVM_FEATURE_SVML (1 << 2)
50#define SVM_FEATURE_NRIP (1 << 3)
50#define SVM_FEATURE_PAUSE_FILTER (1 << 10) 51#define SVM_FEATURE_PAUSE_FILTER (1 << 10)
51 52
52#define NESTED_EXIT_HOST 0 /* Exit handled on host level */ 53#define NESTED_EXIT_HOST 0 /* Exit handled on host level */
@@ -110,6 +111,9 @@ struct vcpu_svm {
110 struct nested_state nested; 111 struct nested_state nested;
111 112
112 bool nmi_singlestep; 113 bool nmi_singlestep;
114
115 unsigned int3_injected;
116 unsigned long int3_rip;
113}; 117};
114 118
115/* enable NPT for AMD64 and X86 with PAE */ 119/* enable NPT for AMD64 and X86 with PAE */
@@ -291,6 +295,22 @@ static void svm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
291 if (nested_svm_check_exception(svm, nr, has_error_code, error_code)) 295 if (nested_svm_check_exception(svm, nr, has_error_code, error_code))
292 return; 296 return;
293 297
298 if (nr == BP_VECTOR && !svm_has(SVM_FEATURE_NRIP)) {
299 unsigned long rip, old_rip = kvm_rip_read(&svm->vcpu);
300
301 /*
302 * For guest debugging where we have to reinject #BP if some
303 * INT3 is guest-owned:
304 * Emulate nRIP by moving RIP forward. Will fail if injection
305 * raises a fault that is not intercepted. Still better than
306 * failing in all cases.
307 */
308 skip_emulated_instruction(&svm->vcpu);
309 rip = kvm_rip_read(&svm->vcpu);
310 svm->int3_rip = rip + svm->vmcb->save.cs.base;
311 svm->int3_injected = rip - old_rip;
312 }
313
294 svm->vmcb->control.event_inj = nr 314 svm->vmcb->control.event_inj = nr
295 | SVM_EVTINJ_VALID 315 | SVM_EVTINJ_VALID
296 | (has_error_code ? SVM_EVTINJ_VALID_ERR : 0) 316 | (has_error_code ? SVM_EVTINJ_VALID_ERR : 0)
@@ -2701,6 +2721,9 @@ static void svm_complete_interrupts(struct vcpu_svm *svm)
2701 u8 vector; 2721 u8 vector;
2702 int type; 2722 int type;
2703 u32 exitintinfo = svm->vmcb->control.exit_int_info; 2723 u32 exitintinfo = svm->vmcb->control.exit_int_info;
2724 unsigned int3_injected = svm->int3_injected;
2725
2726 svm->int3_injected = 0;
2704 2727
2705 if (svm->vcpu.arch.hflags & HF_IRET_MASK) 2728 if (svm->vcpu.arch.hflags & HF_IRET_MASK)
2706 svm->vcpu.arch.hflags &= ~(HF_NMI_MASK | HF_IRET_MASK); 2729 svm->vcpu.arch.hflags &= ~(HF_NMI_MASK | HF_IRET_MASK);
@@ -2720,12 +2743,21 @@ static void svm_complete_interrupts(struct vcpu_svm *svm)
2720 svm->vcpu.arch.nmi_injected = true; 2743 svm->vcpu.arch.nmi_injected = true;
2721 break; 2744 break;
2722 case SVM_EXITINTINFO_TYPE_EXEPT: 2745 case SVM_EXITINTINFO_TYPE_EXEPT:
2723 /* In case of software exception do not reinject an exception
2724 vector, but re-execute and instruction instead */
2725 if (is_nested(svm)) 2746 if (is_nested(svm))
2726 break; 2747 break;
2727 if (kvm_exception_is_soft(vector)) 2748 /*
2749 * In case of software exceptions, do not reinject the vector,
2750 * but re-execute the instruction instead. Rewind RIP first
2751 * if we emulated INT3 before.
2752 */
2753 if (kvm_exception_is_soft(vector)) {
2754 if (vector == BP_VECTOR && int3_injected &&
2755 kvm_is_linear_rip(&svm->vcpu, svm->int3_rip))
2756 kvm_rip_write(&svm->vcpu,
2757 kvm_rip_read(&svm->vcpu) -
2758 int3_injected);
2728 break; 2759 break;
2760 }
2729 if (exitintinfo & SVM_EXITINTINFO_VALID_ERR) { 2761 if (exitintinfo & SVM_EXITINTINFO_VALID_ERR) {
2730 u32 err = svm->vmcb->control.exit_int_info_err; 2762 u32 err = svm->vmcb->control.exit_int_info_err;
2731 kvm_queue_exception_e(&svm->vcpu, vector, err); 2763 kvm_queue_exception_e(&svm->vcpu, vector, err);