aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMohammed Gamal <m.gamal005@gmail.com>2010-09-19 08:34:07 -0400
committerAvi Kivity <avi@redhat.com>2010-10-24 04:53:01 -0400
commita92601bb707f6f49fd5563ef3d09928e70cc222e (patch)
tree4c3f344957d5ee77dc91091ea186eab1169e0fc1
parent63995653ade16deacaea5b49ceaf6376314593ac (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.c65
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 */
3835static 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
3852static void __vmx_complete_interrupts(struct vcpu_vmx *vmx, 3802static 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;