aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/vmx.c
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@web.de>2008-07-14 06:28:51 -0400
committerAvi Kivity <avi@qumranet.com>2008-10-15 04:15:14 -0400
commit77ab6db0a1c403387b403e9351ab3f5ae1df83e6 (patch)
tree8f2aa6dd842afbc45f52904cc25a575a92765e98 /arch/x86/kvm/vmx.c
parent19bd8afdc4e6fbb47e4841f8d771f8cb29916d9f (diff)
KVM: VMX: Reinject real mode exception
As we execute real mode guests in VM86 mode, exception have to be reinjected appropriately when the guest triggered them. For this purpose the patch adopts the real-mode injection pattern used in vmx_inject_irq to vmx_queue_exception, additionally taking care that the IP is set correctly for #BP exceptions. Furthermore it extends handle_rmode_exception to reinject all those exceptions that can be raised in real mode. This fixes the execution of himem.exe from FreeDOS and also makes its debug.com work properly. Note that guest debugging in real mode is broken now. This has to be fixed by the scheduled debugging infrastructure rework (will be done once base patches for QEMU have been accepted). Signed-off-by: Jan Kiszka <jan.kiszka@web.de> Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r--arch/x86/kvm/vmx.c41
1 files changed, 39 insertions, 2 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 5c9dac567a74..2879880076d0 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -735,12 +735,30 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
735static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr, 735static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
736 bool has_error_code, u32 error_code) 736 bool has_error_code, u32 error_code)
737{ 737{
738 struct vcpu_vmx *vmx = to_vmx(vcpu);
739
740 if (has_error_code)
741 vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
742
743 if (vcpu->arch.rmode.active) {
744 vmx->rmode.irq.pending = true;
745 vmx->rmode.irq.vector = nr;
746 vmx->rmode.irq.rip = kvm_rip_read(vcpu);
747 if (nr == BP_VECTOR)
748 vmx->rmode.irq.rip++;
749 vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
750 nr | INTR_TYPE_SOFT_INTR
751 | (has_error_code ? INTR_INFO_DELIVER_CODE_MASK : 0)
752 | INTR_INFO_VALID_MASK);
753 vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, 1);
754 kvm_rip_write(vcpu, vmx->rmode.irq.rip - 1);
755 return;
756 }
757
738 vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 758 vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
739 nr | INTR_TYPE_EXCEPTION 759 nr | INTR_TYPE_EXCEPTION
740 | (has_error_code ? INTR_INFO_DELIVER_CODE_MASK : 0) 760 | (has_error_code ? INTR_INFO_DELIVER_CODE_MASK : 0)
741 | INTR_INFO_VALID_MASK); 761 | INTR_INFO_VALID_MASK);
742 if (has_error_code)
743 vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
744} 762}
745 763
746static bool vmx_exception_injected(struct kvm_vcpu *vcpu) 764static bool vmx_exception_injected(struct kvm_vcpu *vcpu)
@@ -2231,6 +2249,25 @@ static int handle_rmode_exception(struct kvm_vcpu *vcpu,
2231 if (((vec == GP_VECTOR) || (vec == SS_VECTOR)) && err_code == 0) 2249 if (((vec == GP_VECTOR) || (vec == SS_VECTOR)) && err_code == 0)
2232 if (emulate_instruction(vcpu, NULL, 0, 0, 0) == EMULATE_DONE) 2250 if (emulate_instruction(vcpu, NULL, 0, 0, 0) == EMULATE_DONE)
2233 return 1; 2251 return 1;
2252 /*
2253 * Forward all other exceptions that are valid in real mode.
2254 * FIXME: Breaks guest debugging in real mode, needs to be fixed with
2255 * the required debugging infrastructure rework.
2256 */
2257 switch (vec) {
2258 case DE_VECTOR:
2259 case DB_VECTOR:
2260 case BP_VECTOR:
2261 case OF_VECTOR:
2262 case BR_VECTOR:
2263 case UD_VECTOR:
2264 case DF_VECTOR:
2265 case SS_VECTOR:
2266 case GP_VECTOR:
2267 case MF_VECTOR:
2268 kvm_queue_exception(vcpu, vec);
2269 return 1;
2270 }
2234 return 0; 2271 return 0;
2235} 2272}
2236 2273