diff options
author | Gleb Natapov <gleb@redhat.com> | 2009-05-11 06:35:50 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-06-10 04:48:58 -0400 |
commit | 66fd3f7f901f29a557a473af595bf11b270b9ac2 (patch) | |
tree | 6adc1e94de39238a357980068f599070428767d8 /arch/x86/kvm/vmx.c | |
parent | f629cf8485c9e1063fd8b915fa3bde80917400a1 (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.c | 32 |
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 | ||
2448 | static void vmx_inject_irq(struct kvm_vcpu *vcpu, int irq) | 2449 | static 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 | ||
2469 | static void vmx_inject_nmi(struct kvm_vcpu *vcpu) | 2478 | static 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; |