* [PATCH 0/4] VMX: Fix emulate_invalid_guest_state=0
@ 2012-12-11 13:14 Gleb Natapov
2012-12-11 13:14 ` [PATCH 1/4] KVM: VMX: fix DPL during entry to protected mode Gleb Natapov
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Gleb Natapov @ 2012-12-11 13:14 UTC (permalink / raw)
To: kvm; +Cc: mtosatti
eigse=0 was broken during 3.7 development cycle. Although eigse=1 is
default now it is important to keep eigse=0 working since it can be used
as a workaround when instruction that KVM does not know how to emulate
is encountered.
Gleb Natapov (4):
KVM: VMX: fix DPL during entry to protected mode.
VMX: remove unneeded enable_unrestricted_guest check.
KVM: emulator: fix real mode segment checks in address linearization.
KVM: VMX: return correct segment limit and flags for CS/SS registers
in real mode
arch/x86/kvm/emulate.c | 5 +++--
arch/x86/kvm/vmx.c | 10 +++++-----
2 files changed, 8 insertions(+), 7 deletions(-)
--
1.7.10.4
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH 1/4] KVM: VMX: fix DPL during entry to protected mode. 2012-12-11 13:14 [PATCH 0/4] VMX: Fix emulate_invalid_guest_state=0 Gleb Natapov @ 2012-12-11 13:14 ` Gleb Natapov 2012-12-11 13:14 ` [PATCH 2/4] VMX: remove unneeded enable_unrestricted_guest check Gleb Natapov ` (2 subsequent siblings) 3 siblings, 0 replies; 7+ messages in thread From: Gleb Natapov @ 2012-12-11 13:14 UTC (permalink / raw) To: kvm; +Cc: mtosatti On CPUs without support for unrestricted guests DPL cannot be smaller than RPL for data segments during guest entry, but this state can occurs if a data segment selector changes while vcpu is in real mode to a value with lowest two bits != 00. Fix that by forcing DPL == RPL on transition to protected mode. This is a regression introduced by c865c43de66dc97. Signed-off-by: Gleb Natapov <gleb@redhat.com> --- arch/x86/kvm/vmx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 94833e2..ad80f29 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -2709,6 +2709,7 @@ static void fix_pmode_dataseg(struct kvm_vcpu *vcpu, int seg, struct kvm_segment if (!(vmcs_readl(sf->base) == tmp.base && tmp.s)) { tmp.base = vmcs_readl(sf->base); tmp.selector = vmcs_read16(sf->selector); + tmp.dpl = tmp.selector & SELECTOR_RPL_MASK; tmp.s = 1; } vmx_set_segment(vcpu, &tmp, seg); -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/4] VMX: remove unneeded enable_unrestricted_guest check. 2012-12-11 13:14 [PATCH 0/4] VMX: Fix emulate_invalid_guest_state=0 Gleb Natapov 2012-12-11 13:14 ` [PATCH 1/4] KVM: VMX: fix DPL during entry to protected mode Gleb Natapov @ 2012-12-11 13:14 ` Gleb Natapov 2012-12-11 13:14 ` [PATCH 3/4] KVM: emulator: fix real mode segment checks in address linearization Gleb Natapov 2012-12-11 13:14 ` [PATCH 4/4] KVM: VMX: return correct segment limit and flags for CS/SS registers in real mode Gleb Natapov 3 siblings, 0 replies; 7+ messages in thread From: Gleb Natapov @ 2012-12-11 13:14 UTC (permalink / raw) To: kvm; +Cc: mtosatti If enable_unrestricted_guest is true vmx->rmode.vm86_active will always be false. Signed-off-by: Gleb Natapov <gleb@redhat.com> --- arch/x86/kvm/vmx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index ad80f29..cf11c40 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -3259,7 +3259,7 @@ static void vmx_set_segment(struct kvm_vcpu *vcpu, * unrestricted guest like Westmere to older host that don't have * unrestricted guest like Nehelem. */ - if (!enable_unrestricted_guest && vmx->rmode.vm86_active) { + if (vmx->rmode.vm86_active) { switch (seg) { case VCPU_SREG_CS: vmcs_write32(GUEST_CS_AR_BYTES, 0xf3); -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/4] KVM: emulator: fix real mode segment checks in address linearization. 2012-12-11 13:14 [PATCH 0/4] VMX: Fix emulate_invalid_guest_state=0 Gleb Natapov 2012-12-11 13:14 ` [PATCH 1/4] KVM: VMX: fix DPL during entry to protected mode Gleb Natapov 2012-12-11 13:14 ` [PATCH 2/4] VMX: remove unneeded enable_unrestricted_guest check Gleb Natapov @ 2012-12-11 13:14 ` Gleb Natapov 2012-12-11 13:14 ` [PATCH 4/4] KVM: VMX: return correct segment limit and flags for CS/SS registers in real mode Gleb Natapov 3 siblings, 0 replies; 7+ messages in thread From: Gleb Natapov @ 2012-12-11 13:14 UTC (permalink / raw) To: kvm; +Cc: mtosatti In real mode CS register is writable, so do not #GP on write. Signed-off-by: Gleb Natapov <gleb@redhat.com> --- arch/x86/kvm/emulate.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 39171cb..979869f 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -677,8 +677,9 @@ static int __linearize(struct x86_emulate_ctxt *ctxt, addr.seg); if (!usable) goto bad; - /* code segment or read-only data segment */ - if (((desc.type & 8) || !(desc.type & 2)) && write) + /* code segment in protected mode or read-only data segment */ + if ((((ctxt->mode != X86EMUL_MODE_REAL) && (desc.type & 8)) + || !(desc.type & 2)) && write) goto bad; /* unreadable code segment */ if (!fetch && (desc.type & 8) && !(desc.type & 2)) -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/4] KVM: VMX: return correct segment limit and flags for CS/SS registers in real mode 2012-12-11 13:14 [PATCH 0/4] VMX: Fix emulate_invalid_guest_state=0 Gleb Natapov ` (2 preceding siblings ...) 2012-12-11 13:14 ` [PATCH 3/4] KVM: emulator: fix real mode segment checks in address linearization Gleb Natapov @ 2012-12-11 13:14 ` Gleb Natapov 2012-12-12 3:07 ` Marcelo Tosatti 3 siblings, 1 reply; 7+ messages in thread From: Gleb Natapov @ 2012-12-11 13:14 UTC (permalink / raw) To: kvm; +Cc: mtosatti 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@redhat.com> --- 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)) -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 4/4] KVM: VMX: return correct segment limit and flags for CS/SS registers in real mode 2012-12-11 13:14 ` [PATCH 4/4] KVM: VMX: return correct segment limit and flags for CS/SS registers in real mode Gleb Natapov @ 2012-12-12 3:07 ` Marcelo Tosatti 2012-12-12 17:14 ` Gleb Natapov 0 siblings, 1 reply; 7+ messages in thread From: Marcelo Tosatti @ 2012-12-12 3:07 UTC (permalink / raw) To: Gleb Natapov; +Cc: kvm 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@redhat.com> > --- > 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 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 4/4] KVM: VMX: return correct segment limit and flags for CS/SS registers in real mode 2012-12-12 3:07 ` Marcelo Tosatti @ 2012-12-12 17:14 ` Gleb Natapov 0 siblings, 0 replies; 7+ messages in thread From: Gleb Natapov @ 2012-12-12 17:14 UTC (permalink / raw) To: Marcelo Tosatti; +Cc: kvm On Wed, Dec 12, 2012 at 01:07:13AM -0200, Marcelo Tosatti wrote: > 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@redhat.com> > > --- > > 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 > Now we emulate to much. Just sent another series that should address that. But ultimately, the more correct we want vmx in real mode be the more we need to emulate :( > 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 > -- Gleb. ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2012-12-12 17:14 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-12-11 13:14 [PATCH 0/4] VMX: Fix emulate_invalid_guest_state=0 Gleb Natapov 2012-12-11 13:14 ` [PATCH 1/4] KVM: VMX: fix DPL during entry to protected mode Gleb Natapov 2012-12-11 13:14 ` [PATCH 2/4] VMX: remove unneeded enable_unrestricted_guest check Gleb Natapov 2012-12-11 13:14 ` [PATCH 3/4] KVM: emulator: fix real mode segment checks in address linearization Gleb Natapov 2012-12-11 13:14 ` [PATCH 4/4] KVM: VMX: return correct segment limit and flags for CS/SS registers in real mode Gleb Natapov 2012-12-12 3:07 ` Marcelo Tosatti 2012-12-12 17:14 ` Gleb Natapov
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).