diff options
author | Avi Kivity <avi@qumranet.com> | 2008-07-03 09:14:28 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-10-15 04:15:13 -0400 |
commit | f7d9238f5dc9306fd3bf1653c2939eef72f94d06 (patch) | |
tree | 2f3e03f2b6ed46450e27bc465efa8f4926cd373f /arch/x86/kvm/vmx.c | |
parent | 937a7eaef9f08342958d17055a350982b7bd92cb (diff) |
KVM: VMX: Move interrupt post-processing to vmx_complete_interrupts()
Instead of looking at failed injections in the vm entry path, move
processing to the exit path in vmx_complete_interrupts(). This simplifes
the logic and removes any state that is hidden in vmx registers.
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r-- | arch/x86/kvm/vmx.c | 77 |
1 files changed, 20 insertions, 57 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index ed4fe8e72ad0..e8fed9b8756e 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -1002,17 +1002,9 @@ static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg) | |||
1002 | 1002 | ||
1003 | static int vmx_get_irq(struct kvm_vcpu *vcpu) | 1003 | static int vmx_get_irq(struct kvm_vcpu *vcpu) |
1004 | { | 1004 | { |
1005 | struct vcpu_vmx *vmx = to_vmx(vcpu); | 1005 | if (!vcpu->arch.interrupt.pending) |
1006 | u32 idtv_info_field; | 1006 | return -1; |
1007 | 1007 | return vcpu->arch.interrupt.nr; | |
1008 | idtv_info_field = vmx->idt_vectoring_info; | ||
1009 | if (idtv_info_field & INTR_INFO_VALID_MASK) { | ||
1010 | if (is_external_interrupt(idtv_info_field)) | ||
1011 | return idtv_info_field & VECTORING_INFO_VECTOR_MASK; | ||
1012 | else | ||
1013 | printk(KERN_DEBUG "pending exception: not handled yet\n"); | ||
1014 | } | ||
1015 | return -1; | ||
1016 | } | 1008 | } |
1017 | 1009 | ||
1018 | static __init int cpu_has_kvm_support(void) | 1010 | static __init int cpu_has_kvm_support(void) |
@@ -2293,7 +2285,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
2293 | cr2 = vmcs_readl(EXIT_QUALIFICATION); | 2285 | cr2 = vmcs_readl(EXIT_QUALIFICATION); |
2294 | KVMTRACE_3D(PAGE_FAULT, vcpu, error_code, (u32)cr2, | 2286 | KVMTRACE_3D(PAGE_FAULT, vcpu, error_code, (u32)cr2, |
2295 | (u32)((u64)cr2 >> 32), handler); | 2287 | (u32)((u64)cr2 >> 32), handler); |
2296 | if (vect_info & VECTORING_INFO_VALID_MASK) | 2288 | if (vcpu->arch.interrupt.pending || vcpu->arch.exception.pending) |
2297 | kvm_mmu_unprotect_page_virt(vcpu, cr2); | 2289 | kvm_mmu_unprotect_page_virt(vcpu, cr2); |
2298 | return kvm_mmu_page_fault(vcpu, cr2, error_code); | 2290 | return kvm_mmu_page_fault(vcpu, cr2, error_code); |
2299 | } | 2291 | } |
@@ -2864,51 +2856,20 @@ static void vmx_complete_interrupts(struct vcpu_vmx *vmx) | |||
2864 | kvm_queue_exception(&vmx->vcpu, vector); | 2856 | kvm_queue_exception(&vmx->vcpu, vector); |
2865 | vmx->idt_vectoring_info = 0; | 2857 | vmx->idt_vectoring_info = 0; |
2866 | } | 2858 | } |
2859 | kvm_clear_interrupt_queue(&vmx->vcpu); | ||
2860 | if (idtv_info_valid && type == INTR_TYPE_EXT_INTR) { | ||
2861 | kvm_queue_interrupt(&vmx->vcpu, vector); | ||
2862 | vmx->idt_vectoring_info = 0; | ||
2863 | } | ||
2867 | } | 2864 | } |
2868 | 2865 | ||
2869 | static void vmx_intr_assist(struct kvm_vcpu *vcpu) | 2866 | static void vmx_intr_assist(struct kvm_vcpu *vcpu) |
2870 | { | 2867 | { |
2871 | struct vcpu_vmx *vmx = to_vmx(vcpu); | 2868 | u32 intr_info_field; |
2872 | u32 idtv_info_field, intr_info_field; | ||
2873 | int vector; | ||
2874 | 2869 | ||
2875 | update_tpr_threshold(vcpu); | 2870 | update_tpr_threshold(vcpu); |
2876 | 2871 | ||
2877 | intr_info_field = vmcs_read32(VM_ENTRY_INTR_INFO_FIELD); | 2872 | intr_info_field = vmcs_read32(VM_ENTRY_INTR_INFO_FIELD); |
2878 | idtv_info_field = vmx->idt_vectoring_info; | ||
2879 | if (intr_info_field & INTR_INFO_VALID_MASK) { | ||
2880 | if (idtv_info_field & INTR_INFO_VALID_MASK) { | ||
2881 | /* TODO: fault when IDT_Vectoring */ | ||
2882 | if (printk_ratelimit()) | ||
2883 | printk(KERN_ERR "Fault when IDT_Vectoring\n"); | ||
2884 | } | ||
2885 | enable_intr_window(vcpu); | ||
2886 | return; | ||
2887 | } | ||
2888 | if (unlikely(idtv_info_field & INTR_INFO_VALID_MASK)) { | ||
2889 | if ((idtv_info_field & VECTORING_INFO_TYPE_MASK) | ||
2890 | == INTR_TYPE_EXT_INTR | ||
2891 | && vcpu->arch.rmode.active) { | ||
2892 | u8 vect = idtv_info_field & VECTORING_INFO_VECTOR_MASK; | ||
2893 | |||
2894 | vmx_inject_irq(vcpu, vect); | ||
2895 | enable_intr_window(vcpu); | ||
2896 | return; | ||
2897 | } | ||
2898 | |||
2899 | KVMTRACE_1D(REDELIVER_EVT, vcpu, idtv_info_field, handler); | ||
2900 | |||
2901 | vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, idtv_info_field | ||
2902 | & ~INTR_INFO_RESVD_BITS_MASK); | ||
2903 | vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, | ||
2904 | vmcs_read32(VM_EXIT_INSTRUCTION_LEN)); | ||
2905 | |||
2906 | if (unlikely(idtv_info_field & INTR_INFO_DELIVER_CODE_MASK)) | ||
2907 | vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, | ||
2908 | vmcs_read32(IDT_VECTORING_ERROR_CODE)); | ||
2909 | enable_intr_window(vcpu); | ||
2910 | return; | ||
2911 | } | ||
2912 | if (cpu_has_virtual_nmis()) { | 2873 | if (cpu_has_virtual_nmis()) { |
2913 | if (vcpu->arch.nmi_pending && !vcpu->arch.nmi_injected) { | 2874 | if (vcpu->arch.nmi_pending && !vcpu->arch.nmi_injected) { |
2914 | if (vmx_nmi_enabled(vcpu)) { | 2875 | if (vmx_nmi_enabled(vcpu)) { |
@@ -2925,14 +2886,16 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu) | |||
2925 | return; | 2886 | return; |
2926 | } | 2887 | } |
2927 | } | 2888 | } |
2928 | if (!kvm_cpu_has_interrupt(vcpu)) | 2889 | if (!vcpu->arch.interrupt.pending && kvm_cpu_has_interrupt(vcpu)) { |
2929 | return; | 2890 | if (vmx_irq_enabled(vcpu)) |
2930 | if (vmx_irq_enabled(vcpu)) { | 2891 | kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu)); |
2931 | vector = kvm_cpu_get_interrupt(vcpu); | 2892 | else |
2932 | vmx_inject_irq(vcpu, vector); | 2893 | enable_irq_window(vcpu); |
2933 | kvm_timer_intr_post(vcpu, vector); | 2894 | } |
2934 | } else | 2895 | if (vcpu->arch.interrupt.pending) { |
2935 | enable_irq_window(vcpu); | 2896 | vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr); |
2897 | kvm_timer_intr_post(vcpu, vcpu->arch.interrupt.nr); | ||
2898 | } | ||
2936 | } | 2899 | } |
2937 | 2900 | ||
2938 | /* | 2901 | /* |