kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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).