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