diff options
-rw-r--r-- | arch/x86/kvm/vmx.c | 34 |
1 files changed, 21 insertions, 13 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 541f0d2412b4..3237f6cc930d 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -182,7 +182,7 @@ static int init_rmode(struct kvm *kvm); | |||
182 | static u64 construct_eptp(unsigned long root_hpa); | 182 | static u64 construct_eptp(unsigned long root_hpa); |
183 | static void kvm_cpu_vmxon(u64 addr); | 183 | static void kvm_cpu_vmxon(u64 addr); |
184 | static void kvm_cpu_vmxoff(void); | 184 | static void kvm_cpu_vmxoff(void); |
185 | static void fixup_rmode_irq(struct vcpu_vmx *vmx); | 185 | static void fixup_rmode_irq(struct vcpu_vmx *vmx, u32 *idt_vectoring_info); |
186 | 186 | ||
187 | static DEFINE_PER_CPU(struct vmcs *, vmxarea); | 187 | static DEFINE_PER_CPU(struct vmcs *, vmxarea); |
188 | static DEFINE_PER_CPU(struct vmcs *, current_vmcs); | 188 | static DEFINE_PER_CPU(struct vmcs *, current_vmcs); |
@@ -3827,17 +3827,18 @@ static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx) | |||
3827 | ktime_to_ns(ktime_sub(ktime_get(), vmx->entry_time)); | 3827 | ktime_to_ns(ktime_sub(ktime_get(), vmx->entry_time)); |
3828 | } | 3828 | } |
3829 | 3829 | ||
3830 | static void vmx_complete_interrupts(struct vcpu_vmx *vmx) | 3830 | static void __vmx_complete_interrupts(struct vcpu_vmx *vmx, |
3831 | u32 idt_vectoring_info, | ||
3832 | int instr_len_field, | ||
3833 | int error_code_field) | ||
3831 | { | 3834 | { |
3832 | u32 idt_vectoring_info; | ||
3833 | u8 vector; | 3835 | u8 vector; |
3834 | int type; | 3836 | int type; |
3835 | bool idtv_info_valid; | 3837 | bool idtv_info_valid; |
3836 | 3838 | ||
3837 | if (vmx->rmode.irq.pending) | 3839 | if (vmx->rmode.irq.pending) |
3838 | fixup_rmode_irq(vmx); | 3840 | fixup_rmode_irq(vmx, &idt_vectoring_info); |
3839 | 3841 | ||
3840 | idt_vectoring_info = vmx->idt_vectoring_info; | ||
3841 | idtv_info_valid = idt_vectoring_info & VECTORING_INFO_VALID_MASK; | 3842 | idtv_info_valid = idt_vectoring_info & VECTORING_INFO_VALID_MASK; |
3842 | 3843 | ||
3843 | vmx->vcpu.arch.nmi_injected = false; | 3844 | vmx->vcpu.arch.nmi_injected = false; |
@@ -3865,18 +3866,18 @@ static void vmx_complete_interrupts(struct vcpu_vmx *vmx) | |||
3865 | break; | 3866 | break; |
3866 | case INTR_TYPE_SOFT_EXCEPTION: | 3867 | case INTR_TYPE_SOFT_EXCEPTION: |
3867 | vmx->vcpu.arch.event_exit_inst_len = | 3868 | vmx->vcpu.arch.event_exit_inst_len = |
3868 | vmcs_read32(VM_EXIT_INSTRUCTION_LEN); | 3869 | vmcs_read32(instr_len_field); |
3869 | /* fall through */ | 3870 | /* fall through */ |
3870 | case INTR_TYPE_HARD_EXCEPTION: | 3871 | case INTR_TYPE_HARD_EXCEPTION: |
3871 | if (idt_vectoring_info & VECTORING_INFO_DELIVER_CODE_MASK) { | 3872 | if (idt_vectoring_info & VECTORING_INFO_DELIVER_CODE_MASK) { |
3872 | u32 err = vmcs_read32(IDT_VECTORING_ERROR_CODE); | 3873 | u32 err = vmcs_read32(error_code_field); |
3873 | kvm_queue_exception_e(&vmx->vcpu, vector, err); | 3874 | kvm_queue_exception_e(&vmx->vcpu, vector, err); |
3874 | } else | 3875 | } else |
3875 | kvm_queue_exception(&vmx->vcpu, vector); | 3876 | kvm_queue_exception(&vmx->vcpu, vector); |
3876 | break; | 3877 | break; |
3877 | case INTR_TYPE_SOFT_INTR: | 3878 | case INTR_TYPE_SOFT_INTR: |
3878 | vmx->vcpu.arch.event_exit_inst_len = | 3879 | vmx->vcpu.arch.event_exit_inst_len = |
3879 | vmcs_read32(VM_EXIT_INSTRUCTION_LEN); | 3880 | vmcs_read32(instr_len_field); |
3880 | /* fall through */ | 3881 | /* fall through */ |
3881 | case INTR_TYPE_EXT_INTR: | 3882 | case INTR_TYPE_EXT_INTR: |
3882 | kvm_queue_interrupt(&vmx->vcpu, vector, | 3883 | kvm_queue_interrupt(&vmx->vcpu, vector, |
@@ -3887,24 +3888,31 @@ static void vmx_complete_interrupts(struct vcpu_vmx *vmx) | |||
3887 | } | 3888 | } |
3888 | } | 3889 | } |
3889 | 3890 | ||
3891 | static void vmx_complete_interrupts(struct vcpu_vmx *vmx) | ||
3892 | { | ||
3893 | __vmx_complete_interrupts(vmx, vmx->idt_vectoring_info, | ||
3894 | VM_EXIT_INSTRUCTION_LEN, | ||
3895 | IDT_VECTORING_ERROR_CODE); | ||
3896 | } | ||
3897 | |||
3890 | /* | 3898 | /* |
3891 | * Failure to inject an interrupt should give us the information | 3899 | * Failure to inject an interrupt should give us the information |
3892 | * in IDT_VECTORING_INFO_FIELD. However, if the failure occurs | 3900 | * in IDT_VECTORING_INFO_FIELD. However, if the failure occurs |
3893 | * when fetching the interrupt redirection bitmap in the real-mode | 3901 | * when fetching the interrupt redirection bitmap in the real-mode |
3894 | * tss, this doesn't happen. So we do it ourselves. | 3902 | * tss, this doesn't happen. So we do it ourselves. |
3895 | */ | 3903 | */ |
3896 | static void fixup_rmode_irq(struct vcpu_vmx *vmx) | 3904 | static void fixup_rmode_irq(struct vcpu_vmx *vmx, u32 *idt_vectoring_info) |
3897 | { | 3905 | { |
3898 | vmx->rmode.irq.pending = 0; | 3906 | vmx->rmode.irq.pending = 0; |
3899 | if (kvm_rip_read(&vmx->vcpu) + 1 != vmx->rmode.irq.rip) | 3907 | if (kvm_rip_read(&vmx->vcpu) + 1 != vmx->rmode.irq.rip) |
3900 | return; | 3908 | return; |
3901 | kvm_rip_write(&vmx->vcpu, vmx->rmode.irq.rip); | 3909 | kvm_rip_write(&vmx->vcpu, vmx->rmode.irq.rip); |
3902 | if (vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK) { | 3910 | if (*idt_vectoring_info & VECTORING_INFO_VALID_MASK) { |
3903 | vmx->idt_vectoring_info &= ~VECTORING_INFO_TYPE_MASK; | 3911 | *idt_vectoring_info &= ~VECTORING_INFO_TYPE_MASK; |
3904 | vmx->idt_vectoring_info |= INTR_TYPE_EXT_INTR; | 3912 | *idt_vectoring_info |= INTR_TYPE_EXT_INTR; |
3905 | return; | 3913 | return; |
3906 | } | 3914 | } |
3907 | vmx->idt_vectoring_info = | 3915 | *idt_vectoring_info = |
3908 | VECTORING_INFO_VALID_MASK | 3916 | VECTORING_INFO_VALID_MASK |
3909 | | INTR_TYPE_EXT_INTR | 3917 | | INTR_TYPE_EXT_INTR |
3910 | | vmx->rmode.irq.vector; | 3918 | | vmx->rmode.irq.vector; |