On Feb 18, 2008, at 10:17 AM, Guillaume Thouvenin wrote:

> On Sat, 16 Feb 2008 14:34:09 +0100
> Alexander Graf <[EMAIL PROTECTED]> wrote:
>
>>> Whenever the register state becomes consistent with VT again.
>>> vmx_set_segment() looks like the right point for turning it off.
>>
>> Sounds good. As basically the only problem we have are the sanity
>> checks done on VMENTER, this should work.
>
> Hello,
>
> I tried to detect VMentry failure in order to do real mode emulation.
> I tested the patch (pasted at the end of this message) with the
> installation of OpenSuse 10.3 but it failed to detect the VMentry
> failure. I suspect that on my computer the failure is not due to a
> VMentry failure. Can you test the patch and tell me if it detects a
> VMentry failure?

You won't receive any VMentry failure as is. I'll try to explain the  
real problem to you.

This is the real-mode to protected-mode switch. I will comment the  
assembler commands if important for the issue.

Real mode segments are mere offsets. They get lshifted by 4 (as far as  
I remember) and just added to the offset. SS is on some value here  
(can be 0x0, can be 0x5380, can be whatever)

[...]
0x0000000000046e26:  cli
0x0000000000046e27:  movw   %ss,%cs:2256
0x0000000000046e2c:  movw   %ds,%cs:2260
0x0000000000046e31:  movw   %es,%cs:2262
0x0000000000046e36:  movw   %fs,%cs:2264
0x0000000000046e3b:  movw   %gs,%cs:2266
0x0000000000046e40:  or     $0x1,%al

enable protected mode flag in eax

0x0000000000046e42:  lgdtl  %cs:2250
0x0000000000046e49:  lidtl  %cs:2238
0x0000000000046e50:  mov    %eax,%cr0

enable protected mode in cr0 by writing the pm flag
-- we have a vmexit here --

0x0000000000046e53:  ljmp   $0x18,$0x6e18

ljmp to the protected mode segment 0x18 (CS), so we really are in  
protected mode

0x0000000000046e58:  mov    $0x20,%ax
0x0000000000046e5c:  mov    %eax,%ds
0x0000000000046e5e:  mov    %ss,%eax

read SS
and calculate the segment based on the address

0x0000000000046e60:  and    $0xffff,%esp
0x0000000000046e66:  shl    $0x4,%eax
0x0000000000046e69:  add    %eax,%esp
0x0000000000046e6b:  mov    $0x8,%ax
0x0000000000046e6f:  mov    %eax,%ss
0x0000000000046e71:  mov    %eax,%es
0x0000000000046e73:  mov    %eax,%fs
0x0000000000046e75:  mov    %eax,%gs

set the segments to the selector we just calculated

[...]

So what could be the problem with this code? It looks slightly hacky,  
but works on most x86 computers (some VIAs choke here too).

After the vmexit on writing cr0, we are in a somewhat undefined state.  
For most of it, we are in protected mode by now. But the segments have  
not been set to something meaningful in protected mode, so they still  
are on their old values.

Unfortunately VMX does a lot of sanity checks, if the virtual machine  
is actually valid and can be entered into, when trying to do so. One  
of these checks is 'CS.RPL == SS.RPL'. The RPL are lowest 2 bits (I am  
not too sure about this, read in the manuals if you really need to  
know) of the selector. We don't have a real selector in this  
transitioning phase though, but instead have real mode offsets in  
them. This means, if CS was on 0x0 and SS on 0x1235, there is no way  
the RPL equals condition can be met.

This is why in the vmx.c you can find in enter_pmode() code like this:

         vmcs_write16(GUEST_SS_SELECTOR, 0);
         vmcs_write32(GUEST_SS_AR_BYTES, 0x93);

This sets SS to 0 whenever the above mov to cr0 occurs. As most code  
does not rely on SS being available after a PM transition, but instead  
simply writes a sane value to it, that's fine for 99.9% of all code  
out there. Unfortunately it is not for gfxboot.

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.

I hope this helped,

Alex

>
>
> Thanks for your help,
> Regards,
>
> Guillaume
>
> ---
> Index: kvm/arch/x86/kvm/vmx.c
> ===================================================================
> --- kvm.orig/arch/x86/kvm/vmx.c       2008-02-18 09:22:53.000000000 +0100
> +++ kvm/arch/x86/kvm/vmx.c    2008-02-18 09:43:13.000000000 +0100
> @@ -2255,6 +2255,15 @@
> static const int kvm_vmx_max_exit_handlers =
>       ARRAY_SIZE(kvm_vmx_exit_handlers);
>
> +static int kvm_handle_vmentry_failure(struct kvm_run *kvm_run,  
> struct kvm_vcpu *vcpu)
> +{
> +     printk(KERN_WARNING "VMENTRY failure detected \n");
> +     if (vcpu->arch.rmode.active)
> +             printk(KERN_WARNING "Big Real Mode emulation needed \n");
> +
> +     return 0;
> +}
> +
> /*
>  * The guest has exited.  See if we can fix it or if we need userspace
>  * assistance.
> @@ -2265,6 +2274,9 @@
>       struct vcpu_vmx *vmx = to_vmx(vcpu);
>       u32 vectoring_info = vmx->idt_vectoring_info;
>
> +     if (unlikely(exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY))
> +             return kvm_handle_vmentry_failure(kvm_run, vcpu);
> +
>       if (unlikely(vmx->fail)) {
>               kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
>               kvm_run->fail_entry.hardware_entry_failure_reason
>
> -------------------------------------------------------------------------
> 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


-------------------------------------------------------------------------
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