On Thu, Jul 23, 2009 at 06:45:53PM -0300, Marcelo Tosatti wrote:
> On Wed, Jul 22, 2009 at 11:53:26PM +0200, Jan Kiszka wrote:
> > Release and re-acquire preemption and IRQ lock in the same order as
> > vcpu_enter_guest does.
> 
> This should happen in vcpu_enter_guest, before it decides to disable
> preemption/irqs (so you consolidate the control there).
> 
> Maybe add a new member to x86_ops?

Why don't do something like this ?


Index: kvm-requests/arch/x86/include/asm/kvm_host.h
===================================================================
--- kvm-requests.orig/arch/x86/include/asm/kvm_host.h
+++ kvm-requests/arch/x86/include/asm/kvm_host.h
@@ -529,6 +529,7 @@ struct kvm_x86_ops {
        int (*set_tss_addr)(struct kvm *kvm, unsigned int addr);
        int (*get_tdp_level)(void);
        u64 (*get_mt_mask)(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio);
+       int (*emulate_guest_state)(struct kvm_vcpu *vcpu, struct kvm_run *run);
        const struct trace_print_flags *exit_reasons_str;
 };
 
Index: kvm-requests/arch/x86/kvm/vmx.c
===================================================================
--- kvm-requests.orig/arch/x86/kvm/vmx.c
+++ kvm-requests/arch/x86/kvm/vmx.c
@@ -106,8 +106,6 @@ struct vcpu_vmx {
                } irq;
        } rmode;
        int vpid;
-       bool emulation_required;
-       enum emulation_result invalid_state_emulation_result;
 
        /* Support for vnmi-less CPUs */
        int soft_vnmi_blocked;
@@ -1416,7 +1414,6 @@ static void enter_pmode(struct kvm_vcpu 
        unsigned long flags;
        struct vcpu_vmx *vmx = to_vmx(vcpu);
 
-       vmx->emulation_required = 1;
        vmx->rmode.vm86_active = 0;
 
        vmcs_writel(GUEST_TR_BASE, vmx->rmode.tr.base);
@@ -1433,8 +1430,10 @@ static void enter_pmode(struct kvm_vcpu 
 
        update_exception_bitmap(vcpu);
 
-       if (emulate_invalid_guest_state)
+       if (emulate_invalid_guest_state) {
+               set_bit(KVM_REQ_EMULATE, &vcpu->requests);
                return;
+       }
 
        fix_pmode_dataseg(VCPU_SREG_ES, &vmx->rmode.es);
        fix_pmode_dataseg(VCPU_SREG_DS, &vmx->rmode.ds);
@@ -1481,7 +1480,6 @@ static void enter_rmode(struct kvm_vcpu 
        if (enable_unrestricted_guest)
                return;
 
-       vmx->emulation_required = 1;
        vmx->rmode.vm86_active = 1;
 
        vmx->rmode.tr.base = vmcs_readl(GUEST_TR_BASE);
@@ -1503,8 +1501,10 @@ static void enter_rmode(struct kvm_vcpu 
        vmcs_writel(GUEST_CR4, vmcs_readl(GUEST_CR4) | X86_CR4_VME);
        update_exception_bitmap(vcpu);
 
-       if (emulate_invalid_guest_state)
+       if (emulate_invalid_guest_state) {
+               set_bit(KVM_REQ_EMULATE, &vcpu->requests);
                goto continue_rmode;
+       }
 
        vmcs_write16(GUEST_SS_SELECTOR, vmcs_readl(GUEST_SS_BASE) >> 4);
        vmcs_write32(GUEST_SS_LIMIT, 0xffff);
@@ -2517,9 +2517,6 @@ static int vmx_vcpu_reset(struct kvm_vcp
 
        ret = 0;
 
-       /* HACK: Don't enable emulation on guest boot/reset */
-       vmx->emulation_required = 0;
-
 out:
        up_read(&vcpu->kvm->slots_lock);
        return ret;
@@ -3319,15 +3316,11 @@ static int handle_nmi_window(struct kvm_
        return 1;
 }
 
-static void handle_invalid_guest_state(struct kvm_vcpu *vcpu,
+static int handle_invalid_guest_state(struct kvm_vcpu *vcpu,
                                struct kvm_run *kvm_run)
 {
-       struct vcpu_vmx *vmx = to_vmx(vcpu);
        enum emulation_result err = EMULATE_DONE;
 
-       local_irq_enable();
-       preempt_enable();
-
        while (!guest_state_valid(vcpu)) {
                err = emulate_instruction(vcpu, kvm_run, 0, 0, 0);
 
@@ -3345,10 +3338,10 @@ static void handle_invalid_guest_state(s
                        schedule();
        }
 
-       preempt_disable();
-       local_irq_disable();
+       if (!guest_state_valid(vcpu))
+               set_bit(KVM_REQ_EMULATE, &vcpu->requests);
 
-       vmx->invalid_state_emulation_result = err;
+       return (err != EMULATE_DO_MMIO);
 }
 
 /*
@@ -3405,14 +3398,6 @@ static int vmx_handle_exit(struct kvm_ru
 
        trace_kvm_exit(exit_reason, kvm_rip_read(vcpu));
 
-       /* If we need to emulate an MMIO from handle_invalid_guest_state
-        * we just return 0 */
-       if (vmx->emulation_required && emulate_invalid_guest_state) {
-               if (guest_state_valid(vcpu))
-                       vmx->emulation_required = 0;
-               return vmx->invalid_state_emulation_result != EMULATE_DO_MMIO;
-       }
-
        /* Access CR3 don't cause VMExit in paging mode, so we need
         * to sync with guest real CR3. */
        if (enable_ept && is_paging(vcpu))
@@ -3606,12 +3591,6 @@ static void vmx_vcpu_run(struct kvm_vcpu
        if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked))
                vmx->entry_time = ktime_get();
 
-       /* Handle invalid guest state instead of entering VMX */
-       if (vmx->emulation_required && emulate_invalid_guest_state) {
-               handle_invalid_guest_state(vcpu, kvm_run);
-               return;
-       }
-
        if (test_bit(VCPU_REGS_RSP, (unsigned long *)&vcpu->arch.regs_dirty))
                vmcs_writel(GUEST_RSP, vcpu->arch.regs[VCPU_REGS_RSP]);
        if (test_bit(VCPU_REGS_RIP, (unsigned long *)&vcpu->arch.regs_dirty))
@@ -3967,6 +3946,7 @@ static struct kvm_x86_ops vmx_x86_ops = 
        .set_tss_addr = vmx_set_tss_addr,
        .get_tdp_level = get_ept_level,
        .get_mt_mask = vmx_get_mt_mask,
+       .emulate_guest_state = handle_invalid_guest_state,
 
        .exit_reasons_str = vmx_exit_reasons_str,
 };
Index: kvm-requests/arch/x86/kvm/x86.c
===================================================================
--- kvm-requests.orig/arch/x86/kvm/x86.c
+++ kvm-requests/arch/x86/kvm/x86.c
@@ -3556,6 +3556,11 @@ static int vcpu_enter_guest(struct kvm_v
                        kvm_mmu_sync_roots(vcpu);
                if (test_and_clear_bit(KVM_REQ_TLB_FLUSH, &vcpu->requests))
                        kvm_x86_ops->tlb_flush(vcpu);
+               if (test_and_clear_bit(KVM_REQ_EMULATE, &vcpu->requests)) {
+                       r = kvm_x86_ops->emulate_guest_state(vcpu, kvm_run);
+                       goto out;
+               }
+
                if (test_and_clear_bit(KVM_REQ_REPORT_TPR_ACCESS,
                                       &vcpu->requests)) {
                        kvm_run->exit_reason = KVM_EXIT_TPR_ACCESS;
Index: kvm-requests/include/linux/kvm_host.h
===================================================================
--- kvm-requests.orig/include/linux/kvm_host.h
+++ kvm-requests/include/linux/kvm_host.h
@@ -39,6 +39,7 @@
 #define KVM_REQ_MMU_SYNC           7
 #define KVM_REQ_KVMCLOCK_UPDATE    8
 #define KVM_REQ_KICK               9
+#define KVM_REQ_EMULATE                   10
 
 #define KVM_USERSPACE_IRQ_SOURCE_ID    0
 
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to