diff options
author | Avi Kivity <avi@redhat.com> | 2010-07-20 07:43:23 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-10-24 04:52:52 -0400 |
commit | 83422e17c19d61399cab7dbf9bf40ff9af2a7dd2 (patch) | |
tree | 66baed88c811ca2f2a453254af08eb980ee3c842 /arch/x86 | |
parent | 537b37e2674b7e4390a490e03cae53ca9ca99e30 (diff) |
KVM: VMX: Parameterize vmx_complete_interrupts() for both exit and entry
Currently vmx_complete_interrupts() can decode event information from vmx
exit fields into the generic kvm event queues. Make it able to decode
the information from the entry fields as well by parametrizing it.
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86')
-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; |