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