Re: [PATCH 4/4] KVM: VMX: return correct segment limit and flags for CS/SS registers in real mode

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Dec 11, 2012 at 03:14:13PM +0200, Gleb Natapov wrote:
> VMX without unrestricted mode cannot virtualize real mode, so if
> emulate_invalid_guest_state=0 kvm uses vm86 mode to approximate
> it. Sometimes, when guest moves from protected mode to real mode, it
> leaves segment descriptors in a state not suitable for use by vm86 mode
> virtualization, so we keep shadow copy of segment descriptors for internal
> use and load fake register to VMCS for guest entry to succeed. Till
> now we kept shadow for all segments except SS and CS (for SS and CS we
> returned parameters directly from VMCS), but since commit a5625189f6810
> emulator enforces segment limits in real mode. This causes #GP during move
> from protected mode to real mode when emulator fetches first instruction
> after moving to real mode since it uses incorrect CS base and limit to
> linearize the %rip. Fix by keeping shadow for SS and CS too.
> 
> Signed-off-by: Gleb Natapov <gleb@xxxxxxxxxx>
> ---
>  arch/x86/kvm/vmx.c |    7 +++----
>  1 file changed, 3 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> index cf11c40..44b0a94 100644
> --- a/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -2799,6 +2799,8 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
>  	vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_DS], VCPU_SREG_DS);
>  	vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_FS], VCPU_SREG_FS);
>  	vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_GS], VCPU_SREG_GS);
> +	vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_SS], VCPU_SREG_SS);
> +	vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_CS], VCPU_SREG_CS);
>  
>  	vmx->emulation_required = 1;
>  	vmx->rmode.vm86_active = 1;
> @@ -3114,10 +3116,7 @@ static void vmx_get_segment(struct kvm_vcpu *vcpu,
>  	struct vcpu_vmx *vmx = to_vmx(vcpu);
>  	u32 ar;
>  
> -	if (vmx->rmode.vm86_active
> -	    && (seg == VCPU_SREG_TR || seg == VCPU_SREG_ES
> -		|| seg == VCPU_SREG_DS || seg == VCPU_SREG_FS
> -		|| seg == VCPU_SREG_GS)) {
> +	if (vmx->rmode.vm86_active && seg != VCPU_SREG_LDTR) {
>  		*var = vmx->rmode.segs[seg];
>  		if (seg == VCPU_SREG_TR
>  		    || var->selector == vmx_read_guest_seg_selector(vmx, seg))

Fedora 8 32 fails with

KVM internal error. Suberror: 1
emulation failure
EAX=00001c0d EBX=0000c008 ECX=00000005 EDX=00000000
ESI=00009f75 EDI=00000000 EBP=00007ba6 ESP=00007ba0
EIP=00009775 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0000 00000000 0000ffff 00009300
CS =0000 00000000 0000ffff 00009b00
SS =0000 00000000 0000ffff 00009300
DS =0000 00000000 0000ffff 00009300
FS =0000 00000000 0000ffff 00009300
GS =0000 00000000 0000ffff 00009300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT=     00004810 0000002f
IDT=     00000000 0000ffff
CR0=00000012 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000
DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
EFER=0000000000000000
Code=d3 ec c3 b4 10 cd 16 3c e0 75 02 30 c0 20 c0 74 04 bb 08 c0 <d7> c3
bf 04 b4 e8 42 fd c6 45 ff 00 c3 bf 08 bc e8 37 fd 81 ef 09 bc 89 3e fa
9f c3 bf 08

QEMU 1.2.50 monitor - type 'help' for more information
(qemu) x /20i 0x00009775 
0x0000000000009775:  xlat   %ds:(%bx)
0x0000000000009776:  ret    


--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux