aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/vmx.c
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2009-05-11 06:35:50 -0400
committerAvi Kivity <avi@redhat.com>2009-06-10 04:48:58 -0400
commit66fd3f7f901f29a557a473af595bf11b270b9ac2 (patch)
tree6adc1e94de39238a357980068f599070428767d8 /arch/x86/kvm/vmx.c
parentf629cf8485c9e1063fd8b915fa3bde80917400a1 (diff)
KVM: Do not re-execute INTn instruction.
Re-inject event instead. This is what Intel suggest. Also use correct instruction length when re-injecting soft fault/interrupt. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r--arch/x86/kvm/vmx.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 8981654ad061..29b49f09a019 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -801,8 +801,9 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
801 return; 801 return;
802 } 802 }
803 803
804 if (nr == BP_VECTOR || nr == OF_VECTOR) { 804 if (kvm_exception_is_soft(nr)) {
805 vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, 1); 805 vmcs_write32(VM_ENTRY_INSTRUCTION_LEN,
806 vmx->vcpu.arch.event_exit_inst_len);
806 intr_info |= INTR_TYPE_SOFT_EXCEPTION; 807 intr_info |= INTR_TYPE_SOFT_EXCEPTION;
807 } else 808 } else
808 intr_info |= INTR_TYPE_HARD_EXCEPTION; 809 intr_info |= INTR_TYPE_HARD_EXCEPTION;
@@ -2445,9 +2446,11 @@ static void enable_nmi_window(struct kvm_vcpu *vcpu)
2445 vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control); 2446 vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
2446} 2447}
2447 2448
2448static void vmx_inject_irq(struct kvm_vcpu *vcpu, int irq) 2449static void vmx_inject_irq(struct kvm_vcpu *vcpu)
2449{ 2450{
2450 struct vcpu_vmx *vmx = to_vmx(vcpu); 2451 struct vcpu_vmx *vmx = to_vmx(vcpu);
2452 uint32_t intr;
2453 int irq = vcpu->arch.interrupt.nr;
2451 2454
2452 KVMTRACE_1D(INJ_VIRQ, vcpu, (u32)irq, handler); 2455 KVMTRACE_1D(INJ_VIRQ, vcpu, (u32)irq, handler);
2453 2456
@@ -2462,8 +2465,14 @@ static void vmx_inject_irq(struct kvm_vcpu *vcpu, int irq)
2462 kvm_rip_write(vcpu, vmx->rmode.irq.rip - 1); 2465 kvm_rip_write(vcpu, vmx->rmode.irq.rip - 1);
2463 return; 2466 return;
2464 } 2467 }
2465 vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 2468 intr = irq | INTR_INFO_VALID_MASK;
2466 irq | INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK); 2469 if (vcpu->arch.interrupt.soft) {
2470 intr |= INTR_TYPE_SOFT_INTR;
2471 vmcs_write32(VM_ENTRY_INSTRUCTION_LEN,
2472 vmx->vcpu.arch.event_exit_inst_len);
2473 } else
2474 intr |= INTR_TYPE_EXT_INTR;
2475 vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr);
2467} 2476}
2468 2477
2469static void vmx_inject_nmi(struct kvm_vcpu *vcpu) 2478static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
@@ -3024,6 +3033,7 @@ static int handle_task_switch(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
3024 GUEST_INTR_STATE_NMI); 3033 GUEST_INTR_STATE_NMI);
3025 break; 3034 break;
3026 case INTR_TYPE_EXT_INTR: 3035 case INTR_TYPE_EXT_INTR:
3036 case INTR_TYPE_SOFT_INTR:
3027 kvm_clear_interrupt_queue(vcpu); 3037 kvm_clear_interrupt_queue(vcpu);
3028 break; 3038 break;
3029 case INTR_TYPE_HARD_EXCEPTION: 3039 case INTR_TYPE_HARD_EXCEPTION:
@@ -3295,16 +3305,24 @@ static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
3295 vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO, 3305 vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
3296 GUEST_INTR_STATE_NMI); 3306 GUEST_INTR_STATE_NMI);
3297 break; 3307 break;
3298 case INTR_TYPE_HARD_EXCEPTION:
3299 case INTR_TYPE_SOFT_EXCEPTION: 3308 case INTR_TYPE_SOFT_EXCEPTION:
3309 vmx->vcpu.arch.event_exit_inst_len =
3310 vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
3311 /* fall through */
3312 case INTR_TYPE_HARD_EXCEPTION:
3300 if (idt_vectoring_info & VECTORING_INFO_DELIVER_CODE_MASK) { 3313 if (idt_vectoring_info & VECTORING_INFO_DELIVER_CODE_MASK) {
3301 u32 err = vmcs_read32(IDT_VECTORING_ERROR_CODE); 3314 u32 err = vmcs_read32(IDT_VECTORING_ERROR_CODE);
3302 kvm_queue_exception_e(&vmx->vcpu, vector, err); 3315 kvm_queue_exception_e(&vmx->vcpu, vector, err);
3303 } else 3316 } else
3304 kvm_queue_exception(&vmx->vcpu, vector); 3317 kvm_queue_exception(&vmx->vcpu, vector);
3305 break; 3318 break;
3319 case INTR_TYPE_SOFT_INTR:
3320 vmx->vcpu.arch.event_exit_inst_len =
3321 vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
3322 /* fall through */
3306 case INTR_TYPE_EXT_INTR: 3323 case INTR_TYPE_EXT_INTR:
3307 kvm_queue_interrupt(&vmx->vcpu, vector); 3324 kvm_queue_interrupt(&vmx->vcpu, vector,
3325 type == INTR_TYPE_SOFT_INTR);
3308 break; 3326 break;
3309 default: 3327 default:
3310 break; 3328 break;