On Mon, 18 Feb 2008 10:39:31 +0100
Alexander Graf <[EMAIL PROTECTED]> wrote:


> > So if you want to see a VMentry failure, just remove the SS patching
> > and you'll see one. My guess would be that you see a lot of problems
> > with otherwise working code too then, though, as SS can be anything in
> > that state.

So I made some tests and you were right, removing the SS patching
showed VM entry failure but it also generated lots of problems. Thus I
tried to modify a little bit the code and with the following patch (see
the end of the email) I can detect VM Entry failures without generating
other problems. It works when you use a distribution that is
"big-real-mode free". I pasted the patch just to show the idea. 

It's interesting because we can continue to use the virtual mode for the
majority of distribution and we can detect when a VM entry failure is
detected it means that we need to switch from virtual mode to full real
mode emulation. Such failure is caught in handle_vmentry_failure() when
patch applied. If it's doable, the next step is the modification of the
SS segment selector to succeed the vm-entry and the switch from virtual
mode to a real mode emulation that could be done in
handle_vmentry_failure(). Does it make sense?

Regards,
Guillaume

---

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 46e0e58..c2c3897 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -1166,15 +1166,13 @@ static void enter_pmode(struct kvm_vcpu *vcpu)
                        (vmcs_readl(CR4_READ_SHADOW) & X86_CR4_VME));
 
        update_exception_bitmap(vcpu);
-
+ 
+       fix_pmode_dataseg(VCPU_SREG_SS, &vcpu->arch.rmode.ss);
        fix_pmode_dataseg(VCPU_SREG_ES, &vcpu->arch.rmode.es);
        fix_pmode_dataseg(VCPU_SREG_DS, &vcpu->arch.rmode.ds);
        fix_pmode_dataseg(VCPU_SREG_GS, &vcpu->arch.rmode.gs);
        fix_pmode_dataseg(VCPU_SREG_FS, &vcpu->arch.rmode.fs);
 
-       vmcs_write16(GUEST_SS_SELECTOR, 0);
-       vmcs_write32(GUEST_SS_AR_BYTES, 0x93);
-
        vmcs_write16(GUEST_CS_SELECTOR,
                     vmcs_read16(GUEST_CS_SELECTOR) & ~SELECTOR_RPL_MASK);
        vmcs_write32(GUEST_CS_AR_BYTES, 0x9b);
@@ -1228,20 +1226,12 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
        vmcs_writel(GUEST_CR4, vmcs_readl(GUEST_CR4) | X86_CR4_VME);
        update_exception_bitmap(vcpu);
 
-       vmcs_write16(GUEST_SS_SELECTOR, vmcs_readl(GUEST_SS_BASE) >> 4);
-       vmcs_write32(GUEST_SS_LIMIT, 0xffff);
-       vmcs_write32(GUEST_SS_AR_BYTES, 0xf3);
-
-       vmcs_write32(GUEST_CS_AR_BYTES, 0xf3);
-       vmcs_write32(GUEST_CS_LIMIT, 0xffff);
-       if (vmcs_readl(GUEST_CS_BASE) == 0xffff0000)
-               vmcs_writel(GUEST_CS_BASE, 0xf0000);
-       vmcs_write16(GUEST_CS_SELECTOR, vmcs_readl(GUEST_CS_BASE) >> 4);
-
+       fix_rmode_seg(VCPU_SREG_CS, &vcpu->arch.rmode.cs);
        fix_rmode_seg(VCPU_SREG_ES, &vcpu->arch.rmode.es);
        fix_rmode_seg(VCPU_SREG_DS, &vcpu->arch.rmode.ds);
        fix_rmode_seg(VCPU_SREG_GS, &vcpu->arch.rmode.gs);
        fix_rmode_seg(VCPU_SREG_FS, &vcpu->arch.rmode.fs);
+       fix_rmode_seg(VCPU_SREG_SS, &vcpu->arch.rmode.ss);
 
        kvm_mmu_reset_context(vcpu);
        init_rmode_tss(vcpu->kvm);
@@ -2257,6 +2247,39 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu 
*vcpu,
 static const int kvm_vmx_max_exit_handlers =
        ARRAY_SIZE(kvm_vmx_exit_handlers);
 
+static int handle_vmentry_failure(u32 exit_reason, struct kvm_vcpu *vcpu)
+{
+       unsigned long exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
+       u32 info_field = vmcs_read32(VMX_INSTRUCTION_INFO);
+       unsigned int basic_exit_reason = (uint16_t) exit_reason;
+
+       printk("%s: exit reason 0x%x  \n", __FUNCTION__, exit_reason);
+       printk("%s: vmentry failure reason %u  \n", __FUNCTION__, 
basic_exit_reason);
+       printk("%s: VMX-instruction Information field 0x%x  \n", __FUNCTION__, 
info_field);
+
+       switch (basic_exit_reason) {
+               case EXIT_REASON_INVALID_GUEST_STATE:
+                       printk("caused by invalid guest state (%ld).\n", 
exit_qualification);
+                       /* At this point we need to modify SS selector to pass 
vmentry test.
+                        * This modification prevent the usage of virtual mode 
to emulate real 
+                        * mode so we need to pass in big real mode emulation
+                        * with somehting like:
+                        * vcpu->arch.rmode.emulate = 1
+                        */
+                       break;
+               case EXIT_REASON_MSR_LOADING:
+                       printk("caused by MSR entry %ld loading.\n", 
exit_qualification);
+                       break;
+               case EXIT_REASON_MACHINE_CHECK:
+                       printk("caused by machine check.\n");
+                       break;
+               default:
+                       printk("reason not known yet!\n");
+                       break;
+       }
+       return 0;
+}
+
 /*
  * The guest has exited.  See if we can fix it or if we need userspace
  * assistance.
@@ -2274,6 +2297,9 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, 
struct kvm_vcpu *vcpu)
                return 0;
        }
 
+       if (unlikely(exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY)) 
+               return handle_vmentry_failure(exit_reason, vcpu);
+
        if ((vectoring_info & VECTORING_INFO_VALID_MASK) &&
                                exit_reason != EXIT_REASON_EXCEPTION_NMI)
                printk(KERN_WARNING "%s: unexpected, valid vectoring info and "
diff --git a/arch/x86/kvm/vmx.h b/arch/x86/kvm/vmx.h
index 5dff460..200c0f8 100644
--- a/arch/x86/kvm/vmx.h
+++ b/arch/x86/kvm/vmx.h
@@ -223,7 +223,10 @@ enum vmcs_field {
 #define EXIT_REASON_IO_INSTRUCTION      30
 #define EXIT_REASON_MSR_READ            31
 #define EXIT_REASON_MSR_WRITE           32
+#define EXIT_REASON_INVALID_GUEST_STATE 33
+#define EXIT_REASON_MSR_LOADING         34
 #define EXIT_REASON_MWAIT_INSTRUCTION   36
+#define EXIT_REASON_MACHINE_CHECK       41
 #define EXIT_REASON_TPR_BELOW_THRESHOLD 43
 #define EXIT_REASON_APIC_ACCESS         44
 #define EXIT_REASON_WBINVD             54
diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h
index 024b57c..b6e4006 100644
--- a/include/asm-x86/kvm_host.h
+++ b/include/asm-x86/kvm_host.h
@@ -261,7 +261,7 @@ struct kvm_vcpu_arch {
                        unsigned long base;
                        u32 limit;
                        u32 ar;
-               } tr, es, ds, fs, gs;
+               } tr, cs, es, ds, fs, gs, ss;
        } rmode;
        int halt_request; /* real mode on Intel only */
 
 

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
kvm-devel mailing list
kvm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-devel

Reply via email to