* [RFC PATCH v2 3/4] VMX: Emulated real mode interrupt injection
2010-08-14 0:19 [RFC PATCH v2 2/4] x86: Add inject_realmode_interrupt() wrapper Mohammed Gamal
@ 2010-08-14 0:19 ` Mohammed Gamal
2010-08-14 0:19 ` [RFC PATCH v2 4/4] x86 emulator: Eagerly commit emulation ctxt eip in emulate_int_real() Mohammed Gamal
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Mohammed Gamal @ 2010-08-14 0:19 UTC (permalink / raw)
To: avi; +Cc: mtosatti, kvm, Mohammed Gamal
Signed-off-by: Mohammed Gamal <m.gamal005@gmail.com>
---
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 652d317..1f4387b 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -155,11 +155,6 @@ struct vcpu_vmx {
u32 limit;
u32 ar;
} tr, es, ds, fs, gs;
- struct {
- bool pending;
- u8 vector;
- unsigned rip;
- } irq;
} rmode;
int vpid;
bool emulation_required;
@@ -1048,16 +1043,8 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
}
if (vmx->rmode.vm86_active) {
- vmx->rmode.irq.pending = true;
- vmx->rmode.irq.vector = nr;
- vmx->rmode.irq.rip = kvm_rip_read(vcpu);
- if (kvm_exception_is_soft(nr))
- vmx->rmode.irq.rip +=
- vmx->vcpu.arch.event_exit_inst_len;
- intr_info |= INTR_TYPE_SOFT_INTR;
- vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info);
- vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, 1);
- kvm_rip_write(vcpu, vmx->rmode.irq.rip - 1);
+ if (inject_realmode_interrupt(vcpu, nr) != EMULATE_DONE)
+ kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
return;
}
@@ -2838,16 +2825,8 @@ static void vmx_inject_irq(struct kvm_vcpu *vcpu)
++vcpu->stat.irq_injections;
if (vmx->rmode.vm86_active) {
- vmx->rmode.irq.pending = true;
- vmx->rmode.irq.vector = irq;
- vmx->rmode.irq.rip = kvm_rip_read(vcpu);
- if (vcpu->arch.interrupt.soft)
- vmx->rmode.irq.rip +=
- vmx->vcpu.arch.event_exit_inst_len;
- vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
- irq | INTR_TYPE_SOFT_INTR | INTR_INFO_VALID_MASK);
- vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, 1);
- kvm_rip_write(vcpu, vmx->rmode.irq.rip - 1);
+ if (inject_realmode_interrupt(vcpu, irq) != EMULATE_DONE)
+ kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
return;
}
intr = irq | INTR_INFO_VALID_MASK;
@@ -2879,14 +2858,8 @@ static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
++vcpu->stat.nmi_injections;
if (vmx->rmode.vm86_active) {
- vmx->rmode.irq.pending = true;
- vmx->rmode.irq.vector = NMI_VECTOR;
- vmx->rmode.irq.rip = kvm_rip_read(vcpu);
- vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
- NMI_VECTOR | INTR_TYPE_SOFT_INTR |
- INTR_INFO_VALID_MASK);
- vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, 1);
- kvm_rip_write(vcpu, vmx->rmode.irq.rip - 1);
+ if (inject_realmode_interrupt(vcpu, NMI_VECTOR) != EMULATE_DONE)
+ kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
return;
}
vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
@@ -3848,29 +3821,6 @@ static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx)
ktime_to_ns(ktime_sub(ktime_get(), vmx->entry_time));
}
-/*
- * Failure to inject an interrupt should give us the information
- * in IDT_VECTORING_INFO_FIELD. However, if the failure occurs
- * when fetching the interrupt redirection bitmap in the real-mode
- * tss, this doesn't happen. So we do it ourselves.
- */
-static void fixup_rmode_irq(struct vcpu_vmx *vmx, u32 *idt_vectoring_info)
-{
- vmx->rmode.irq.pending = 0;
- if (kvm_rip_read(&vmx->vcpu) + 1 != vmx->rmode.irq.rip)
- return;
- kvm_rip_write(&vmx->vcpu, vmx->rmode.irq.rip);
- if (*idt_vectoring_info & VECTORING_INFO_VALID_MASK) {
- *idt_vectoring_info &= ~VECTORING_INFO_TYPE_MASK;
- *idt_vectoring_info |= INTR_TYPE_EXT_INTR;
- return;
- }
- *idt_vectoring_info =
- VECTORING_INFO_VALID_MASK
- | INTR_TYPE_EXT_INTR
- | vmx->rmode.irq.vector;
-}
-
static void __vmx_complete_interrupts(struct vcpu_vmx *vmx,
u32 idt_vectoring_info,
int instr_len_field,
@@ -3880,9 +3830,6 @@ static void __vmx_complete_interrupts(struct vcpu_vmx *vmx,
int type;
bool idtv_info_valid;
- if (vmx->rmode.irq.pending)
- fixup_rmode_irq(vmx, &idt_vectoring_info);
-
idtv_info_valid = idt_vectoring_info & VECTORING_INFO_VALID_MASK;
vmx->vcpu.arch.nmi_injected = false;
--
1.7.0.4
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [RFC PATCH v2 2/4] x86: Add inject_realmode_interrupt() wrapper
2010-08-14 0:19 [RFC PATCH v2 2/4] x86: Add inject_realmode_interrupt() wrapper Mohammed Gamal
2010-08-14 0:19 ` [RFC PATCH v2 3/4] VMX: Emulated real mode interrupt injection Mohammed Gamal
2010-08-14 0:19 ` [RFC PATCH v2 4/4] x86 emulator: Eagerly commit emulation ctxt eip in emulate_int_real() Mohammed Gamal
@ 2010-08-15 7:41 ` Gleb Natapov
2010-08-15 12:37 ` Avi Kivity
3 siblings, 0 replies; 6+ messages in thread
From: Gleb Natapov @ 2010-08-15 7:41 UTC (permalink / raw)
To: Mohammed Gamal; +Cc: avi, mtosatti, kvm
On Sat, Aug 14, 2010 at 03:19:39AM +0300, Mohammed Gamal wrote:
> This adds a wrapper function inject_realmode_interrupt() around the
> emulator function emulate_int_real() to allow real mode interrupt injection.
>
> Signed-off-by: Mohammed Gamal <m.gamal005@gmail.com>
> ---
> arch/x86/kvm/x86.c | 33 +++++++++++++++++++++++++++++++++
> arch/x86/kvm/x86.h | 1 +
> 2 files changed, 34 insertions(+), 0 deletions(-)
>
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 1722d37..d3ba1c3 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -3936,6 +3936,39 @@ static void inject_emulated_exception(struct kvm_vcpu *vcpu)
> kvm_queue_exception(vcpu, ctxt->exception);
> }
>
> +int inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq)
> +{
> + struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode;
> + int cs_db, cs_l, ret;
> + cache_all_regs(vcpu);
> +
> + kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
> +
> + vcpu->arch.emulate_ctxt.vcpu = vcpu;
> + vcpu->arch.emulate_ctxt.eflags = kvm_x86_ops->get_rflags(vcpu);
> + vcpu->arch.emulate_ctxt.eip = kvm_rip_read(vcpu);
> + vcpu->arch.emulate_ctxt.mode =
> + (!is_protmode(vcpu)) ? X86EMUL_MODE_REAL :
> + (vcpu->arch.emulate_ctxt.eflags & X86_EFLAGS_VM)
> + ? X86EMUL_MODE_VM86 : cs_l
> + ? X86EMUL_MODE_PROT64 : cs_db
> + ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
> + memset(c, 0, sizeof(struct decode_cache));
> + memcpy(c->regs, vcpu->arch.regs, sizeof c->regs);
> +
We have this code in 2 places already: kvm_task_switch() and emulate_instruction().
This will be the third one. Should be moved to separate function.
> + ret = emulate_int_real(&vcpu->arch.emulate_ctxt, &emulate_ops, irq);
> +
> + if (ret != X86EMUL_CONTINUE)
> + return EMULATE_FAIL;
> +
> + memcpy(vcpu->arch.regs, c->regs, sizeof c->regs);
> + kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip);
> + kvm_x86_ops->set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags);
> +
> + return EMULATE_DONE;
> +}
> +EXPORT_SYMBOL_GPL(inject_realmode_interrupt);
> +
> static int handle_emulation_failure(struct kvm_vcpu *vcpu)
> {
> ++vcpu->stat.insn_emulation_fail;
> diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
> index b7a4047..c6e8a4d 100644
> --- a/arch/x86/kvm/x86.h
> +++ b/arch/x86/kvm/x86.h
> @@ -67,5 +67,6 @@ static inline int is_paging(struct kvm_vcpu *vcpu)
>
> void kvm_before_handle_nmi(struct kvm_vcpu *vcpu);
> void kvm_after_handle_nmi(struct kvm_vcpu *vcpu);
> +int inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq);
>
> #endif
> --
> 1.7.0.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Gleb.
^ permalink raw reply [flat|nested] 6+ messages in thread