diff options
author | Mohammed Gamal <m.gamal005@gmail.com> | 2010-09-19 08:34:07 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-10-24 04:53:01 -0400 |
commit | a92601bb707f6f49fd5563ef3d09928e70cc222e (patch) | |
tree | 4c3f344957d5ee77dc91091ea186eab1169e0fc1 | |
parent | 63995653ade16deacaea5b49ceaf6376314593ac (diff) |
KVM: VMX: Emulated real mode interrupt injection
Replace the inject-as-software-interrupt hack we currently have with
emulated injection.
Signed-off-by: Mohammed Gamal <m.gamal005@gmail.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r-- | arch/x86/kvm/vmx.c | 65 |
1 files changed, 6 insertions, 59 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 32315935201a..9d3f972aa19c 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -155,11 +155,6 @@ struct vcpu_vmx { | |||
155 | u32 limit; | 155 | u32 limit; |
156 | u32 ar; | 156 | u32 ar; |
157 | } tr, es, ds, fs, gs; | 157 | } tr, es, ds, fs, gs; |
158 | struct { | ||
159 | bool pending; | ||
160 | u8 vector; | ||
161 | unsigned rip; | ||
162 | } irq; | ||
163 | } rmode; | 158 | } rmode; |
164 | int vpid; | 159 | int vpid; |
165 | bool emulation_required; | 160 | bool emulation_required; |
@@ -1028,16 +1023,8 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr, | |||
1028 | } | 1023 | } |
1029 | 1024 | ||
1030 | if (vmx->rmode.vm86_active) { | 1025 | if (vmx->rmode.vm86_active) { |
1031 | vmx->rmode.irq.pending = true; | 1026 | if (kvm_inject_realmode_interrupt(vcpu, nr) != EMULATE_DONE) |
1032 | vmx->rmode.irq.vector = nr; | 1027 | kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); |
1033 | vmx->rmode.irq.rip = kvm_rip_read(vcpu); | ||
1034 | if (kvm_exception_is_soft(nr)) | ||
1035 | vmx->rmode.irq.rip += | ||
1036 | vmx->vcpu.arch.event_exit_inst_len; | ||
1037 | intr_info |= INTR_TYPE_SOFT_INTR; | ||
1038 | vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info); | ||
1039 | vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, 1); | ||
1040 | kvm_rip_write(vcpu, vmx->rmode.irq.rip - 1); | ||
1041 | return; | 1028 | return; |
1042 | } | 1029 | } |
1043 | 1030 | ||
@@ -2816,16 +2803,8 @@ static void vmx_inject_irq(struct kvm_vcpu *vcpu) | |||
2816 | 2803 | ||
2817 | ++vcpu->stat.irq_injections; | 2804 | ++vcpu->stat.irq_injections; |
2818 | if (vmx->rmode.vm86_active) { | 2805 | if (vmx->rmode.vm86_active) { |
2819 | vmx->rmode.irq.pending = true; | 2806 | if (kvm_inject_realmode_interrupt(vcpu, irq) != EMULATE_DONE) |
2820 | vmx->rmode.irq.vector = irq; | 2807 | kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); |
2821 | vmx->rmode.irq.rip = kvm_rip_read(vcpu); | ||
2822 | if (vcpu->arch.interrupt.soft) | ||
2823 | vmx->rmode.irq.rip += | ||
2824 | vmx->vcpu.arch.event_exit_inst_len; | ||
2825 | vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, | ||
2826 | irq | INTR_TYPE_SOFT_INTR | INTR_INFO_VALID_MASK); | ||
2827 | vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, 1); | ||
2828 | kvm_rip_write(vcpu, vmx->rmode.irq.rip - 1); | ||
2829 | return; | 2808 | return; |
2830 | } | 2809 | } |
2831 | intr = irq | INTR_INFO_VALID_MASK; | 2810 | intr = irq | INTR_INFO_VALID_MASK; |
@@ -2857,14 +2836,8 @@ static void vmx_inject_nmi(struct kvm_vcpu *vcpu) | |||
2857 | 2836 | ||
2858 | ++vcpu->stat.nmi_injections; | 2837 | ++vcpu->stat.nmi_injections; |
2859 | if (vmx->rmode.vm86_active) { | 2838 | if (vmx->rmode.vm86_active) { |
2860 | vmx->rmode.irq.pending = true; | 2839 | if (kvm_inject_realmode_interrupt(vcpu, NMI_VECTOR) != EMULATE_DONE) |
2861 | vmx->rmode.irq.vector = NMI_VECTOR; | 2840 | kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); |
2862 | vmx->rmode.irq.rip = kvm_rip_read(vcpu); | ||
2863 | vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, | ||
2864 | NMI_VECTOR | INTR_TYPE_SOFT_INTR | | ||
2865 | INTR_INFO_VALID_MASK); | ||
2866 | vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, 1); | ||
2867 | kvm_rip_write(vcpu, vmx->rmode.irq.rip - 1); | ||
2868 | return; | 2841 | return; |
2869 | } | 2842 | } |
2870 | vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, | 2843 | vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, |
@@ -3826,29 +3799,6 @@ static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx) | |||
3826 | ktime_to_ns(ktime_sub(ktime_get(), vmx->entry_time)); | 3799 | ktime_to_ns(ktime_sub(ktime_get(), vmx->entry_time)); |
3827 | } | 3800 | } |
3828 | 3801 | ||
3829 | /* | ||
3830 | * Failure to inject an interrupt should give us the information | ||
3831 | * in IDT_VECTORING_INFO_FIELD. However, if the failure occurs | ||
3832 | * when fetching the interrupt redirection bitmap in the real-mode | ||
3833 | * tss, this doesn't happen. So we do it ourselves. | ||
3834 | */ | ||
3835 | static void fixup_rmode_irq(struct vcpu_vmx *vmx, u32 *idt_vectoring_info) | ||
3836 | { | ||
3837 | vmx->rmode.irq.pending = 0; | ||
3838 | if (kvm_rip_read(&vmx->vcpu) + 1 != vmx->rmode.irq.rip) | ||
3839 | return; | ||
3840 | kvm_rip_write(&vmx->vcpu, vmx->rmode.irq.rip); | ||
3841 | if (*idt_vectoring_info & VECTORING_INFO_VALID_MASK) { | ||
3842 | *idt_vectoring_info &= ~VECTORING_INFO_TYPE_MASK; | ||
3843 | *idt_vectoring_info |= INTR_TYPE_EXT_INTR; | ||
3844 | return; | ||
3845 | } | ||
3846 | *idt_vectoring_info = | ||
3847 | VECTORING_INFO_VALID_MASK | ||
3848 | | INTR_TYPE_EXT_INTR | ||
3849 | | vmx->rmode.irq.vector; | ||
3850 | } | ||
3851 | |||
3852 | static void __vmx_complete_interrupts(struct vcpu_vmx *vmx, | 3802 | static void __vmx_complete_interrupts(struct vcpu_vmx *vmx, |
3853 | u32 idt_vectoring_info, | 3803 | u32 idt_vectoring_info, |
3854 | int instr_len_field, | 3804 | int instr_len_field, |
@@ -3858,9 +3808,6 @@ static void __vmx_complete_interrupts(struct vcpu_vmx *vmx, | |||
3858 | int type; | 3808 | int type; |
3859 | bool idtv_info_valid; | 3809 | bool idtv_info_valid; |
3860 | 3810 | ||
3861 | if (vmx->rmode.irq.pending) | ||
3862 | fixup_rmode_irq(vmx, &idt_vectoring_info); | ||
3863 | |||
3864 | idtv_info_valid = idt_vectoring_info & VECTORING_INFO_VALID_MASK; | 3811 | idtv_info_valid = idt_vectoring_info & VECTORING_INFO_VALID_MASK; |
3865 | 3812 | ||
3866 | vmx->vcpu.arch.nmi_injected = false; | 3813 | vmx->vcpu.arch.nmi_injected = false; |