All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/21] Big big real mode improvements
@ 2012-06-12 17:34 Avi Kivity
  2012-06-12 17:34 ` [PATCH 01/21] KVM: VMX: Return correct CPL during transition to protected mode Avi Kivity
                   ` (20 more replies)
  0 siblings, 21 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

This patchset fixes several bugs in the emulator and in vmx invalid guest
state emulation.  They are sufficient to boot several Linux and Windows
guests, so the last patch turns vmx invalid guest state emulation on by
default.

The first patch is a little hacky; we should try to emulate svm here by making
cpl a state, not a cache.

Avi Kivity (21):
  KVM: VMX: Return correct CPL during transition to protected mode
  KVM: Split cpuid register access from computation
  KVM: x86 emulator: change ->get_cpuid() accessor to use the x86
    semantics
  KVM: x86 emulator: emulate cpuid
  KVM: x86 emulator: allow loading null SS in long mode
  KVM: x86 emulator: fix LIDT/LGDT in long mode
  KVM: VMX: Relax check on unusable segment
  KVM: VMX: Limit iterations with emulator_invalid_guest_state
  KVM: x86 emulator: emulate LEAVE
  KVM: x86 emulator: initialize memop
  KVM: Fix SS default ESP/EBP based addressing
  KVM: x86 emulator: emulate SGDT/SIDT
  KVM: VMX: Fix interrupt exit condition during emulation
  KVM: VMX: Continue emulating after batch exhausted
  KVM: x86 emulator: emulate LAHF
  KVM: x86 emulator: fix byte-sized MOVZX/MOVSX
  KVM: x86 emulator: split push logic from push opcode emulation
  KVM: x86 emulator: implement ENTER
  KVM: VMX: Stop invalid guest state emulation on pending event
  KVM: VMX: Improve error reporting during invalid guest state
    emulation
  KVM: VMX: Emulate invalid guest state by default

 arch/x86/include/asm/kvm_emulate.h |    6 +-
 arch/x86/kvm/cpuid.c               |   38 ++++---
 arch/x86/kvm/cpuid.h               |    1 +
 arch/x86/kvm/emulate.c             |  191 ++++++++++++++++++++++++++++--------
 arch/x86/kvm/vmx.c                 |   38 ++++---
 arch/x86/kvm/x86.c                 |   20 +---
 6 files changed, 209 insertions(+), 85 deletions(-)

-- 
1.7.10.1


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 01/21] KVM: VMX: Return correct CPL during transition to protected mode
  2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
@ 2012-06-12 17:34 ` Avi Kivity
  2012-06-12 17:34 ` [PATCH 02/21] KVM: Split cpuid register access from computation Avi Kivity
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

In protected mode, the CPL is defined as the lower two bits of CS, as set by
the last far jump.  But during the transition to protected mode, there is no
last far jump, so we need to return zero (the inherited real mode CPL).

Fix by reading CPL from the cache during the transition.  This isn't 100%
correct since we don't set the CPL cache on a far jump, but since protected
mode transition will always jump to a segment with RPL=0, it will always
work.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/vmx.c |   15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index eeeb4a2..8f2ddd9 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -3175,11 +3175,22 @@ static int __vmx_get_cpl(struct kvm_vcpu *vcpu)
 
 static int vmx_get_cpl(struct kvm_vcpu *vcpu)
 {
+	struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+	/*
+	 * If we enter real mode with cs.sel & 3 != 0, the normal CPL calculations
+	 * fail; use the cache instead.
+	 */
+	if (unlikely(vmx->emulation_required && emulate_invalid_guest_state)) {
+		return vmx->cpl;
+	}
+
 	if (!test_bit(VCPU_EXREG_CPL, (ulong *)&vcpu->arch.regs_avail)) {
 		__set_bit(VCPU_EXREG_CPL, (ulong *)&vcpu->arch.regs_avail);
-		to_vmx(vcpu)->cpl = __vmx_get_cpl(vcpu);
+		vmx->cpl = __vmx_get_cpl(vcpu);
 	}
-	return to_vmx(vcpu)->cpl;
+
+	return vmx->cpl;
 }
 
 
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 02/21] KVM: Split cpuid register access from computation
  2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
  2012-06-12 17:34 ` [PATCH 01/21] KVM: VMX: Return correct CPL during transition to protected mode Avi Kivity
@ 2012-06-12 17:34 ` Avi Kivity
  2012-06-12 17:34 ` [PATCH 03/21] KVM: x86 emulator: change ->get_cpuid() accessor to use the x86 semantics Avi Kivity
                   ` (18 subsequent siblings)
  20 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

Introduce kvm_cpuid() to perform the leaf limit check and calculate
register values, and let kvm_emulate_cpuid() just handle reading and
writing the registers from/to the vcpu.  This allows us to reuse
kvm_cpuid() in a context where directly reading and writing registers
is not desired.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/cpuid.c |   38 ++++++++++++++++++++++++--------------
 arch/x86/kvm/cpuid.h |    1 +
 2 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 7df1c6d..44476fb 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -639,33 +639,43 @@ static struct kvm_cpuid_entry2* check_cpuid_limit(struct kvm_vcpu *vcpu,
 	return kvm_find_cpuid_entry(vcpu, maxlevel->eax, index);
 }
 
-void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
+void kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
 {
-	u32 function, index;
+	u32 function = *eax, index = *ecx;
 	struct kvm_cpuid_entry2 *best;
 
-	function = kvm_register_read(vcpu, VCPU_REGS_RAX);
-	index = kvm_register_read(vcpu, VCPU_REGS_RCX);
-	kvm_register_write(vcpu, VCPU_REGS_RAX, 0);
-	kvm_register_write(vcpu, VCPU_REGS_RBX, 0);
-	kvm_register_write(vcpu, VCPU_REGS_RCX, 0);
-	kvm_register_write(vcpu, VCPU_REGS_RDX, 0);
 	best = kvm_find_cpuid_entry(vcpu, function, index);
 
 	if (!best)
 		best = check_cpuid_limit(vcpu, function, index);
 
 	if (best) {
-		kvm_register_write(vcpu, VCPU_REGS_RAX, best->eax);
-		kvm_register_write(vcpu, VCPU_REGS_RBX, best->ebx);
-		kvm_register_write(vcpu, VCPU_REGS_RCX, best->ecx);
-		kvm_register_write(vcpu, VCPU_REGS_RDX, best->edx);
-	}
-	kvm_x86_ops->skip_emulated_instruction(vcpu);
+		*eax = best->eax;
+		*ebx = best->ebx;
+		*ecx = best->ecx;
+		*edx = best->edx;
+	} else
+		*eax = *ebx = *ecx = *edx = 0;
+
 	trace_kvm_cpuid(function,
 			kvm_register_read(vcpu, VCPU_REGS_RAX),
 			kvm_register_read(vcpu, VCPU_REGS_RBX),
 			kvm_register_read(vcpu, VCPU_REGS_RCX),
 			kvm_register_read(vcpu, VCPU_REGS_RDX));
 }
+
+void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
+{
+	u32 function, eax, ebx, ecx, edx;
+
+	function = eax = kvm_register_read(vcpu, VCPU_REGS_RAX);
+	ecx = kvm_register_read(vcpu, VCPU_REGS_RCX);
+	kvm_cpuid(vcpu, &eax, &ebx, &ecx, &edx);
+	kvm_register_write(vcpu, VCPU_REGS_RAX, eax);
+	kvm_register_write(vcpu, VCPU_REGS_RBX, ebx);
+	kvm_register_write(vcpu, VCPU_REGS_RCX, ecx);
+	kvm_register_write(vcpu, VCPU_REGS_RDX, edx);
+	kvm_x86_ops->skip_emulated_instruction(vcpu);
+	trace_kvm_cpuid(function, eax, ebx, ecx, edx);
+}
 EXPORT_SYMBOL_GPL(kvm_emulate_cpuid);
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
index 26d1fb4..f449edc 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -17,6 +17,7 @@ int kvm_vcpu_ioctl_set_cpuid2(struct kvm_vcpu *vcpu,
 int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu,
 			      struct kvm_cpuid2 *cpuid,
 			      struct kvm_cpuid_entry2 __user *entries);
+void kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
 
 
 static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu)
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 03/21] KVM: x86 emulator: change ->get_cpuid() accessor to use the x86 semantics
  2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
  2012-06-12 17:34 ` [PATCH 01/21] KVM: VMX: Return correct CPL during transition to protected mode Avi Kivity
  2012-06-12 17:34 ` [PATCH 02/21] KVM: Split cpuid register access from computation Avi Kivity
@ 2012-06-12 17:34 ` Avi Kivity
  2012-06-12 17:34 ` [PATCH 04/21] KVM: x86 emulator: emulate cpuid Avi Kivity
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

Instead of getting an exact leaf, follow the spec and fall back to the last
main leaf instead.  This lets us easily emulate the cpuid instruction in the
emulator.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/include/asm/kvm_emulate.h |    4 +--
 arch/x86/kvm/emulate.c             |   53 ++++++++++++++++++------------------
 arch/x86/kvm/x86.c                 |   20 ++------------
 3 files changed, 30 insertions(+), 47 deletions(-)

diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index 1ac46c22..cd5c96b 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -192,8 +192,8 @@ struct x86_emulate_ops {
 			 struct x86_instruction_info *info,
 			 enum x86_intercept_stage stage);
 
-	bool (*get_cpuid)(struct x86_emulate_ctxt *ctxt,
-			 u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
+	void (*get_cpuid)(struct x86_emulate_ctxt *ctxt,
+			  u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
 };
 
 typedef u32 __attribute__((vector_size(16))) sse128_t;
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index f95d242..ba1f8ec 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1993,8 +1993,8 @@ static bool vendor_intel(struct x86_emulate_ctxt *ctxt)
 	u32 eax, ebx, ecx, edx;
 
 	eax = ecx = 0;
-	return ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx)
-		&& ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx
+	ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx);
+	return ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx
 		&& ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx
 		&& edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx;
 }
@@ -2013,32 +2013,31 @@ static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt)
 
 	eax = 0x00000000;
 	ecx = 0x00000000;
-	if (ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx)) {
-		/*
-		 * Intel ("GenuineIntel")
-		 * remark: Intel CPUs only support "syscall" in 64bit
-		 * longmode. Also an 64bit guest with a
-		 * 32bit compat-app running will #UD !! While this
-		 * behaviour can be fixed (by emulating) into AMD
-		 * response - CPUs of AMD can't behave like Intel.
-		 */
-		if (ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx &&
-		    ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx &&
-		    edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx)
-			return false;
+	ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx);
+	/*
+	 * Intel ("GenuineIntel")
+	 * remark: Intel CPUs only support "syscall" in 64bit
+	 * longmode. Also an 64bit guest with a
+	 * 32bit compat-app running will #UD !! While this
+	 * behaviour can be fixed (by emulating) into AMD
+	 * response - CPUs of AMD can't behave like Intel.
+	 */
+	if (ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx &&
+	    ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx &&
+	    edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx)
+		return false;
 
-		/* AMD ("AuthenticAMD") */
-		if (ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx &&
-		    ecx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx &&
-		    edx == X86EMUL_CPUID_VENDOR_AuthenticAMD_edx)
-			return true;
-
-		/* AMD ("AMDisbetter!") */
-		if (ebx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx &&
-		    ecx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx &&
-		    edx == X86EMUL_CPUID_VENDOR_AMDisbetterI_edx)
-			return true;
-	}
+	/* AMD ("AuthenticAMD") */
+	if (ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx &&
+	    ecx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx &&
+	    edx == X86EMUL_CPUID_VENDOR_AuthenticAMD_edx)
+		return true;
+
+	/* AMD ("AMDisbetter!") */
+	if (ebx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx &&
+	    ecx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx &&
+	    edx == X86EMUL_CPUID_VENDOR_AMDisbetterI_edx)
+		return true;
 
 	/* default: (not Intel, not AMD), apply Intel's stricter rules... */
 	return false;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index a01a424..016cec5 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4297,26 +4297,10 @@ static int emulator_intercept(struct x86_emulate_ctxt *ctxt,
 	return kvm_x86_ops->check_intercept(emul_to_vcpu(ctxt), info, stage);
 }
 
-static bool emulator_get_cpuid(struct x86_emulate_ctxt *ctxt,
+static void emulator_get_cpuid(struct x86_emulate_ctxt *ctxt,
 			       u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
 {
-	struct kvm_cpuid_entry2 *cpuid = NULL;
-
-	if (eax && ecx)
-		cpuid = kvm_find_cpuid_entry(emul_to_vcpu(ctxt),
-					    *eax, *ecx);
-
-	if (cpuid) {
-		*eax = cpuid->eax;
-		*ecx = cpuid->ecx;
-		if (ebx)
-			*ebx = cpuid->ebx;
-		if (edx)
-			*edx = cpuid->edx;
-		return true;
-	}
-
-	return false;
+	kvm_cpuid(emul_to_vcpu(ctxt), eax, ebx, ecx, edx);
 }
 
 static struct x86_emulate_ops emulate_ops = {
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 04/21] KVM: x86 emulator: emulate cpuid
  2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
                   ` (2 preceding siblings ...)
  2012-06-12 17:34 ` [PATCH 03/21] KVM: x86 emulator: change ->get_cpuid() accessor to use the x86 semantics Avi Kivity
@ 2012-06-12 17:34 ` Avi Kivity
  2012-06-12 17:34 ` [PATCH 05/21] KVM: x86 emulator: allow loading null SS in long mode Avi Kivity
                   ` (16 subsequent siblings)
  20 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

Opcode 0F A2.

Used by Linux during the mode change trampoline while in a state that is
not virtualizable on vmx without unrestricted_guest, so we need to emulate
it is emulate_invalid_guest_state=1.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/emulate.c |   16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index ba1f8ec..db95a55 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -3142,6 +3142,20 @@ static int em_bsr(struct x86_emulate_ctxt *ctxt)
 	return X86EMUL_CONTINUE;
 }
 
+static int em_cpuid(struct x86_emulate_ctxt *ctxt)
+{
+	u32 eax, ebx, ecx, edx;
+
+	eax = ctxt->regs[VCPU_REGS_RAX];
+	ecx = ctxt->regs[VCPU_REGS_RCX];
+	ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx);
+	ctxt->regs[VCPU_REGS_RAX] = eax;
+	ctxt->regs[VCPU_REGS_RBX] = ebx;
+	ctxt->regs[VCPU_REGS_RCX] = ecx;
+	ctxt->regs[VCPU_REGS_RDX] = edx;
+	return X86EMUL_CONTINUE;
+}
+
 static bool valid_cr(int nr)
 {
 	switch (nr) {
@@ -3634,7 +3648,7 @@ static int check_perm_out(struct x86_emulate_ctxt *ctxt)
 	X16(D(ByteOp | DstMem | SrcNone | ModRM| Mov)),
 	/* 0xA0 - 0xA7 */
 	I(Stack | Src2FS, em_push_sreg), I(Stack | Src2FS, em_pop_sreg),
-	DI(ImplicitOps, cpuid), I(DstMem | SrcReg | ModRM | BitOp, em_bt),
+	II(ImplicitOps, em_cpuid, cpuid), I(DstMem | SrcReg | ModRM | BitOp, em_bt),
 	D(DstMem | SrcReg | Src2ImmByte | ModRM),
 	D(DstMem | SrcReg | Src2CL | ModRM), N, N,
 	/* 0xA8 - 0xAF */
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 05/21] KVM: x86 emulator: allow loading null SS in long mode
  2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
                   ` (3 preceding siblings ...)
  2012-06-12 17:34 ` [PATCH 04/21] KVM: x86 emulator: emulate cpuid Avi Kivity
@ 2012-06-12 17:34 ` Avi Kivity
  2012-06-18 14:14   ` Kevin Wolf
  2012-06-12 17:34 ` [PATCH 06/21] KVM: x86 emulator: fix LIDT/LGDT " Avi Kivity
                   ` (15 subsequent siblings)
  20 siblings, 1 reply; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

Null SS is valid in long mode; allow loading it.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/emulate.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index db95a55..9a95132 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1325,7 +1325,9 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
 	}
 
 	/* NULL selector is not valid for TR, CS and SS */
-	if ((seg == VCPU_SREG_CS || seg == VCPU_SREG_SS || seg == VCPU_SREG_TR)
+	if ((seg == VCPU_SREG_CS
+	     || (seg == VCPU_SREG_SS && ctxt->mode != X86EMUL_MODE_PROT64)
+	     || seg == VCPU_SREG_TR)
 	    && null_selector)
 		goto exception;
 
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 06/21] KVM: x86 emulator: fix LIDT/LGDT in long mode
  2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
                   ` (4 preceding siblings ...)
  2012-06-12 17:34 ` [PATCH 05/21] KVM: x86 emulator: allow loading null SS in long mode Avi Kivity
@ 2012-06-12 17:34 ` Avi Kivity
  2012-06-12 17:34 ` [PATCH 07/21] KVM: VMX: Relax check on unusable segment Avi Kivity
                   ` (14 subsequent siblings)
  20 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

The operand size for these instructions is 8 bytes in long mode, even without
a REX prefix.  Set it explicitly.

Triggered while booting Linux with emulate_invalid_guest_state=1.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/emulate.c |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 9a95132..c24da8d 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -2995,6 +2995,8 @@ static int em_lgdt(struct x86_emulate_ctxt *ctxt)
 	struct desc_ptr desc_ptr;
 	int rc;
 
+	if (ctxt->mode == X86EMUL_MODE_PROT64)
+		ctxt->op_bytes = 8;
 	rc = read_descriptor(ctxt, ctxt->src.addr.mem,
 			     &desc_ptr.size, &desc_ptr.address,
 			     ctxt->op_bytes);
@@ -3022,6 +3024,8 @@ static int em_lidt(struct x86_emulate_ctxt *ctxt)
 	struct desc_ptr desc_ptr;
 	int rc;
 
+	if (ctxt->mode == X86EMUL_MODE_PROT64)
+		ctxt->op_bytes = 8;
 	rc = read_descriptor(ctxt, ctxt->src.addr.mem,
 			     &desc_ptr.size, &desc_ptr.address,
 			     ctxt->op_bytes);
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 07/21] KVM: VMX: Relax check on unusable segment
  2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
                   ` (5 preceding siblings ...)
  2012-06-12 17:34 ` [PATCH 06/21] KVM: x86 emulator: fix LIDT/LGDT " Avi Kivity
@ 2012-06-12 17:34 ` Avi Kivity
  2012-06-12 17:34 ` [PATCH 08/21] KVM: VMX: Limit iterations with emulator_invalid_guest_state Avi Kivity
                   ` (13 subsequent siblings)
  20 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

Some userspace (e.g. QEMU 1.1) munge the d and g bits of segment
descriptors, causing us not to recognize them as unusable segments
with emulate_invalid_guest_state=1.  Relax the check by testing for
segment not present (a non-present segment cannot be usable).

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/vmx.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 8f2ddd9..a9c0e40 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -3198,7 +3198,7 @@ static u32 vmx_segment_access_rights(struct kvm_segment *var)
 {
 	u32 ar;
 
-	if (var->unusable)
+	if (var->unusable || !var->present)
 		ar = 1 << 16;
 	else {
 		ar = var->type & 15;
@@ -3210,8 +3210,6 @@ static u32 vmx_segment_access_rights(struct kvm_segment *var)
 		ar |= (var->db & 1) << 14;
 		ar |= (var->g & 1) << 15;
 	}
-	if (ar == 0) /* a 0 value means unusable */
-		ar = AR_UNUSABLE_MASK;
 
 	return ar;
 }
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 08/21] KVM: VMX: Limit iterations with emulator_invalid_guest_state
  2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
                   ` (6 preceding siblings ...)
  2012-06-12 17:34 ` [PATCH 07/21] KVM: VMX: Relax check on unusable segment Avi Kivity
@ 2012-06-12 17:34 ` Avi Kivity
  2012-06-12 17:34 ` [PATCH 09/21] KVM: x86 emulator: emulate LEAVE Avi Kivity
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

Otherwise, if the guest ends up looping, we never exit the srcu critical
section, which causes synchronize_srcu() to hang.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/vmx.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index a9c0e40..8c4c336 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -4977,11 +4977,12 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu)
 	int ret = 1;
 	u32 cpu_exec_ctrl;
 	bool intr_window_requested;
+	unsigned count = 130;
 
 	cpu_exec_ctrl = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
 	intr_window_requested = cpu_exec_ctrl & CPU_BASED_VIRTUAL_INTR_PENDING;
 
-	while (!guest_state_valid(vcpu)) {
+	while (!guest_state_valid(vcpu) && count-- != 0) {
 		if (intr_window_requested
 		    && (kvm_get_rflags(&vmx->vcpu) & X86_EFLAGS_IF))
 			return handle_interrupt_window(&vmx->vcpu);
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 09/21] KVM: x86 emulator: emulate LEAVE
  2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
                   ` (7 preceding siblings ...)
  2012-06-12 17:34 ` [PATCH 08/21] KVM: VMX: Limit iterations with emulator_invalid_guest_state Avi Kivity
@ 2012-06-12 17:34 ` Avi Kivity
  2012-06-12 17:34 ` [PATCH 10/21] KVM: x86 emulator: initialize memop Avi Kivity
                   ` (11 subsequent siblings)
  20 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

Opcode c9; used by some variants of Windows during boot, in big real mode.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/emulate.c |   25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index c24da8d..5b6f99d 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -433,11 +433,27 @@ static int emulator_check_intercept(struct x86_emulate_ctxt *ctxt,
 	return ctxt->ops->intercept(ctxt, &info, stage);
 }
 
+static void assign_masked(ulong *dest, ulong src, ulong mask)
+{
+	*dest = (*dest & ~mask) | (src & mask);
+}
+
 static inline unsigned long ad_mask(struct x86_emulate_ctxt *ctxt)
 {
 	return (1UL << (ctxt->ad_bytes << 3)) - 1;
 }
 
+static ulong stack_mask(struct x86_emulate_ctxt *ctxt)
+{
+	u16 sel;
+	struct desc_struct ss;
+
+	if (ctxt->mode == X86EMUL_MODE_PROT64)
+		return ~0UL;
+	ctxt->ops->get_segment(ctxt, &sel, &ss, NULL, VCPU_SREG_SS);
+	return ~0U >> ((ss.d ^ 1) * 16);  /* d=0: 0xffff; d=1: 0xffffffff */
+}
+
 /* Access/update address held in a register, based on addressing mode. */
 static inline unsigned long
 address_mask(struct x86_emulate_ctxt *ctxt, unsigned long reg)
@@ -1558,6 +1574,13 @@ static int em_popf(struct x86_emulate_ctxt *ctxt)
 	return emulate_popf(ctxt, &ctxt->dst.val, ctxt->op_bytes);
 }
 
+static int em_leave(struct x86_emulate_ctxt *ctxt)
+{
+	assign_masked(&ctxt->regs[VCPU_REGS_RSP], ctxt->regs[VCPU_REGS_RBP],
+		      stack_mask(ctxt));
+	return emulate_pop(ctxt, &ctxt->regs[VCPU_REGS_RBP], ctxt->op_bytes);
+}
+
 static int em_push_sreg(struct x86_emulate_ctxt *ctxt)
 {
 	int seg = ctxt->src2.val;
@@ -3580,7 +3603,7 @@ static int check_perm_out(struct x86_emulate_ctxt *ctxt)
 	I(DstReg | SrcMemFAddr | ModRM | No64 | Src2DS, em_lseg),
 	G(ByteOp, group11), G(0, group11),
 	/* 0xC8 - 0xCF */
-	N, N, N, I(ImplicitOps | Stack, em_ret_far),
+	N, I(Stack, em_leave), N, I(ImplicitOps | Stack, em_ret_far),
 	D(ImplicitOps), DI(SrcImmByte, intn),
 	D(ImplicitOps | No64), II(ImplicitOps, em_iret, iret),
 	/* 0xD0 - 0xD7 */
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 10/21] KVM: x86 emulator: initialize memop
  2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
                   ` (8 preceding siblings ...)
  2012-06-12 17:34 ` [PATCH 09/21] KVM: x86 emulator: emulate LEAVE Avi Kivity
@ 2012-06-12 17:34 ` Avi Kivity
  2012-06-12 17:34 ` [PATCH 11/21] KVM: Fix SS default ESP/EBP based addressing Avi Kivity
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

memop is not initialized; this can lead to a two-byte operation
following a 4-byte operation to see garbage values.  Usually
truncation fixes things fot us later on, but at least in one case
(call abs) it doesn't.

Fix by moving memop to the auto-initialized field area.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/include/asm/kvm_emulate.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index cd5c96b..c764f43 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -280,9 +280,9 @@ struct x86_emulate_ctxt {
 	u8 modrm_seg;
 	bool rip_relative;
 	unsigned long _eip;
+	struct operand memop;
 	/* Fields above regs are cleared together. */
 	unsigned long regs[NR_VCPU_REGS];
-	struct operand memop;
 	struct operand *memopp;
 	struct fetch_cache fetch;
 	struct read_cache io_read;
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 11/21] KVM: Fix SS default ESP/EBP based addressing
  2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
                   ` (9 preceding siblings ...)
  2012-06-12 17:34 ` [PATCH 10/21] KVM: x86 emulator: initialize memop Avi Kivity
@ 2012-06-12 17:34 ` Avi Kivity
  2012-06-12 17:34 ` [PATCH 12/21] KVM: x86 emulator: emulate SGDT/SIDT Avi Kivity
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

We correctly default to SS when BP is used as a base in 16-bit address mode,
but we don't do that for 32-bit mode.

Fix by adjusting the default to SS when either ESP or EBP is used as the base
register.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/emulate.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 5b6f99d..0088e2d 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1077,8 +1077,12 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
 
 			if ((base_reg & 7) == 5 && ctxt->modrm_mod == 0)
 				modrm_ea += insn_fetch(s32, ctxt);
-			else
+			else {
 				modrm_ea += ctxt->regs[base_reg];
+				if (base_reg == VCPU_REGS_RSP
+				    || base_reg == VCPU_REGS_RBP)
+					ctxt->modrm_seg = VCPU_SREG_SS;
+			}
 			if (index_reg != 4)
 				modrm_ea += ctxt->regs[index_reg] << scale;
 		} else if ((ctxt->modrm_rm & 7) == 5 && ctxt->modrm_mod == 0) {
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 12/21] KVM: x86 emulator: emulate SGDT/SIDT
  2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
                   ` (10 preceding siblings ...)
  2012-06-12 17:34 ` [PATCH 11/21] KVM: Fix SS default ESP/EBP based addressing Avi Kivity
@ 2012-06-12 17:34 ` Avi Kivity
  2012-06-12 17:34 ` [PATCH 13/21] KVM: VMX: Fix interrupt exit condition during emulation Avi Kivity
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

Opcodes 0F 01 /0 and 0F 01 /1

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/emulate.c |   33 +++++++++++++++++++++++++++++++--
 1 file changed, 31 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 0088e2d..46bbc9d 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -3017,6 +3017,35 @@ static int em_vmcall(struct x86_emulate_ctxt *ctxt)
 	return X86EMUL_CONTINUE;
 }
 
+static int emulate_store_desc_ptr(struct x86_emulate_ctxt *ctxt,
+				  void (*get)(struct x86_emulate_ctxt *ctxt,
+					      struct desc_ptr *ptr))
+{
+	struct desc_ptr desc_ptr;
+
+	if (ctxt->mode == X86EMUL_MODE_PROT64)
+		ctxt->op_bytes = 8;
+	get(ctxt, &desc_ptr);
+	if (ctxt->op_bytes == 2) {
+		ctxt->op_bytes = 4;
+		desc_ptr.address &= 0x00ffffff;
+	}
+	/* Disable writeback. */
+	ctxt->dst.type = OP_NONE;
+	return segmented_write(ctxt, ctxt->dst.addr.mem,
+			       &desc_ptr, 2 + ctxt->op_bytes);
+}
+
+static int em_sgdt(struct x86_emulate_ctxt *ctxt)
+{
+	return emulate_store_desc_ptr(ctxt, ctxt->ops->get_gdt);
+}
+
+static int em_sidt(struct x86_emulate_ctxt *ctxt)
+{
+	return emulate_store_desc_ptr(ctxt, ctxt->ops->get_idt);
+}
+
 static int em_lgdt(struct x86_emulate_ctxt *ctxt)
 {
 	struct desc_ptr desc_ptr;
@@ -3476,8 +3505,8 @@ static int check_perm_out(struct x86_emulate_ctxt *ctxt)
 };
 
 static struct group_dual group7 = { {
-	DI(Mov | DstMem | Priv,			sgdt),
-	DI(Mov | DstMem | Priv,			sidt),
+	II(Mov | DstMem | Priv,			em_sgdt, sgdt),
+	II(Mov | DstMem | Priv,			em_sidt, sidt),
 	II(SrcMem | Priv,			em_lgdt, lgdt),
 	II(SrcMem | Priv,			em_lidt, lidt),
 	II(SrcNone | DstMem | Mov,		em_smsw, smsw), N,
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 13/21] KVM: VMX: Fix interrupt exit condition during emulation
  2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
                   ` (11 preceding siblings ...)
  2012-06-12 17:34 ` [PATCH 12/21] KVM: x86 emulator: emulate SGDT/SIDT Avi Kivity
@ 2012-06-12 17:34 ` Avi Kivity
  2012-06-12 17:34 ` [PATCH 14/21] KVM: VMX: Continue emulating after batch exhausted Avi Kivity
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

Checking EFLAGS.IF is incorrect as we might be in interrupt shadow.  If
that is the case, the main loop will notice that and not inject the interrupt,
causing an endless loop.

Fix by using vmx_interrupt_allowed() to check if we can inject an interrupt
instead.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/vmx.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 8c4c336..d2d12f2 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -4983,8 +4983,7 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu)
 	intr_window_requested = cpu_exec_ctrl & CPU_BASED_VIRTUAL_INTR_PENDING;
 
 	while (!guest_state_valid(vcpu) && count-- != 0) {
-		if (intr_window_requested
-		    && (kvm_get_rflags(&vmx->vcpu) & X86_EFLAGS_IF))
+		if (intr_window_requested && vmx_interrupt_allowed(vcpu))
 			return handle_interrupt_window(&vmx->vcpu);
 
 		err = emulate_instruction(vcpu, 0);
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 14/21] KVM: VMX: Continue emulating after batch exhausted
  2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
                   ` (12 preceding siblings ...)
  2012-06-12 17:34 ` [PATCH 13/21] KVM: VMX: Fix interrupt exit condition during emulation Avi Kivity
@ 2012-06-12 17:34 ` Avi Kivity
  2012-06-12 17:34 ` [PATCH 15/21] KVM: x86 emulator: emulate LAHF Avi Kivity
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

If we return early from an invalid guest state emulation loop, make
sure we return to it later if the guest state is still invalid.

Signed-off-by: Avi Kivity <avi@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 d2d12f2..26e6bdf 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -5002,7 +5002,7 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu)
 			schedule();
 	}
 
-	vmx->emulation_required = 0;
+	vmx->emulation_required = !guest_state_valid(vcpu);
 out:
 	return ret;
 }
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 15/21] KVM: x86 emulator: emulate LAHF
  2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
                   ` (13 preceding siblings ...)
  2012-06-12 17:34 ` [PATCH 14/21] KVM: VMX: Continue emulating after batch exhausted Avi Kivity
@ 2012-06-12 17:34 ` Avi Kivity
  2012-06-12 17:34 ` [PATCH 16/21] KVM: x86 emulator: fix byte-sized MOVZX/MOVSX Avi Kivity
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

Opcode 9F.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/emulate.c |    9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 46bbc9d..f23f504 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -3218,6 +3218,13 @@ static int em_cpuid(struct x86_emulate_ctxt *ctxt)
 	return X86EMUL_CONTINUE;
 }
 
+static int em_lahf(struct x86_emulate_ctxt *ctxt)
+{
+	ctxt->regs[VCPU_REGS_RAX] &= ~0xff00UL;
+	ctxt->regs[VCPU_REGS_RAX] |= (ctxt->eflags & 0xff) << 8;
+	return X86EMUL_CONTINUE;
+}
+
 static bool valid_cr(int nr)
 {
 	switch (nr) {
@@ -3613,7 +3620,7 @@ static int check_perm_out(struct x86_emulate_ctxt *ctxt)
 	D(DstAcc | SrcNone), I(ImplicitOps | SrcAcc, em_cwd),
 	I(SrcImmFAddr | No64, em_call_far), N,
 	II(ImplicitOps | Stack, em_pushf, pushf),
-	II(ImplicitOps | Stack, em_popf, popf), N, N,
+	II(ImplicitOps | Stack, em_popf, popf), N, I(ImplicitOps, em_lahf),
 	/* 0xA0 - 0xA7 */
 	I2bv(DstAcc | SrcMem | Mov | MemAbs, em_mov),
 	I2bv(DstMem | SrcAcc | Mov | MemAbs | PageTable, em_mov),
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 16/21] KVM: x86 emulator: fix byte-sized MOVZX/MOVSX
  2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
                   ` (14 preceding siblings ...)
  2012-06-12 17:34 ` [PATCH 15/21] KVM: x86 emulator: emulate LAHF Avi Kivity
@ 2012-06-12 17:34 ` Avi Kivity
  2012-06-12 17:34 ` [PATCH 17/21] KVM: x86 emulator: split push logic from push opcode emulation Avi Kivity
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

Commit 2adb5ad9fe1 removed ByteOp from MOVZX/MOVSX, replacing them by
SrcMem8, but neglected to fix the dependency in the emulation code
on ByteOp.  This caused the instruction not to have any effect in
some circumstances.

Fix by replacing the check for ByteOp with the equivalent src.op_bytes == 1.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/emulate.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index f23f504..25eab1b 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -4508,12 +4508,12 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
 		break;
 	case 0xb6 ... 0xb7:	/* movzx */
 		ctxt->dst.bytes = ctxt->op_bytes;
-		ctxt->dst.val = (ctxt->d & ByteOp) ? (u8) ctxt->src.val
+		ctxt->dst.val = (ctxt->src.bytes == 1) ? (u8) ctxt->src.val
 						       : (u16) ctxt->src.val;
 		break;
 	case 0xbe ... 0xbf:	/* movsx */
 		ctxt->dst.bytes = ctxt->op_bytes;
-		ctxt->dst.val = (ctxt->d & ByteOp) ? (s8) ctxt->src.val :
+		ctxt->dst.val = (ctxt->src.bytes == 1) ? (s8) ctxt->src.val :
 							(s16) ctxt->src.val;
 		break;
 	case 0xc0 ... 0xc1:	/* xadd */
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 17/21] KVM: x86 emulator: split push logic from push opcode emulation
  2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
                   ` (15 preceding siblings ...)
  2012-06-12 17:34 ` [PATCH 16/21] KVM: x86 emulator: fix byte-sized MOVZX/MOVSX Avi Kivity
@ 2012-06-12 17:34 ` Avi Kivity
  2012-06-12 17:34 ` [PATCH 18/21] KVM: x86 emulator: implement ENTER Avi Kivity
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

This allows us to reuse the code without populating ctxt->src and
overriding ctxt->op_bytes.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/emulate.c |   11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 25eab1b..8d3167c 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1496,17 +1496,22 @@ static int writeback(struct x86_emulate_ctxt *ctxt)
 	return X86EMUL_CONTINUE;
 }
 
-static int em_push(struct x86_emulate_ctxt *ctxt)
+static int push(struct x86_emulate_ctxt *ctxt, void *data, int bytes)
 {
 	struct segmented_address addr;
 
-	register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP], -ctxt->op_bytes);
+	register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP], -bytes);
 	addr.ea = register_address(ctxt, ctxt->regs[VCPU_REGS_RSP]);
 	addr.seg = VCPU_SREG_SS;
 
+	return segmented_write(ctxt, addr, data, bytes);
+}
+
+static int em_push(struct x86_emulate_ctxt *ctxt)
+{
 	/* Disable writeback. */
 	ctxt->dst.type = OP_NONE;
-	return segmented_write(ctxt, addr, &ctxt->src.val, ctxt->op_bytes);
+	return push(ctxt, &ctxt->src.val, ctxt->op_bytes);
 }
 
 static int emulate_pop(struct x86_emulate_ctxt *ctxt,
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 18/21] KVM: x86 emulator: implement ENTER
  2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
                   ` (16 preceding siblings ...)
  2012-06-12 17:34 ` [PATCH 17/21] KVM: x86 emulator: split push logic from push opcode emulation Avi Kivity
@ 2012-06-12 17:34 ` Avi Kivity
  2012-06-12 17:34 ` [PATCH 19/21] KVM: VMX: Stop invalid guest state emulation on pending event Avi Kivity
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

Opcode C8.

Only ENTER with lexical nesting depth 0 is implemented, since others are
very rare.  We'll fail emulation if nonzero lexical depth is used so data
is not corrupted.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/emulate.c |   28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 8d3167c..c804db2 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -454,6 +454,11 @@ static ulong stack_mask(struct x86_emulate_ctxt *ctxt)
 	return ~0U >> ((ss.d ^ 1) * 16);  /* d=0: 0xffff; d=1: 0xffffffff */
 }
 
+static int stack_size(struct x86_emulate_ctxt *ctxt)
+{
+	return fls(stack_mask(ctxt)) >> 3;
+}
+
 /* Access/update address held in a register, based on addressing mode. */
 static inline unsigned long
 address_mask(struct x86_emulate_ctxt *ctxt, unsigned long reg)
@@ -1583,6 +1588,26 @@ static int em_popf(struct x86_emulate_ctxt *ctxt)
 	return emulate_popf(ctxt, &ctxt->dst.val, ctxt->op_bytes);
 }
 
+static int em_enter(struct x86_emulate_ctxt *ctxt)
+{
+	int rc;
+	unsigned frame_size = ctxt->src.val;
+	unsigned nesting_level = ctxt->src2.val & 31;
+
+	if (nesting_level)
+		return X86EMUL_UNHANDLEABLE;
+
+	rc = push(ctxt, &ctxt->regs[VCPU_REGS_RBP], stack_size(ctxt));
+	if (rc != X86EMUL_CONTINUE)
+		return rc;
+	assign_masked(&ctxt->regs[VCPU_REGS_RBP], ctxt->regs[VCPU_REGS_RSP],
+		      stack_mask(ctxt));
+	assign_masked(&ctxt->regs[VCPU_REGS_RSP],
+		      ctxt->regs[VCPU_REGS_RSP] - frame_size,
+		      stack_mask(ctxt));
+	return X86EMUL_CONTINUE;
+}
+
 static int em_leave(struct x86_emulate_ctxt *ctxt)
 {
 	assign_masked(&ctxt->regs[VCPU_REGS_RSP], ctxt->regs[VCPU_REGS_RBP],
@@ -3648,7 +3673,8 @@ static int check_perm_out(struct x86_emulate_ctxt *ctxt)
 	I(DstReg | SrcMemFAddr | ModRM | No64 | Src2DS, em_lseg),
 	G(ByteOp, group11), G(0, group11),
 	/* 0xC8 - 0xCF */
-	N, I(Stack, em_leave), N, I(ImplicitOps | Stack, em_ret_far),
+	I(Stack | SrcImmU16 | Src2ImmByte, em_enter), I(Stack, em_leave),
+	N, I(ImplicitOps | Stack, em_ret_far),
 	D(ImplicitOps), DI(SrcImmByte, intn),
 	D(ImplicitOps | No64), II(ImplicitOps, em_iret, iret),
 	/* 0xD0 - 0xD7 */
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 19/21] KVM: VMX: Stop invalid guest state emulation on pending event
  2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
                   ` (17 preceding siblings ...)
  2012-06-12 17:34 ` [PATCH 18/21] KVM: x86 emulator: implement ENTER Avi Kivity
@ 2012-06-12 17:34 ` Avi Kivity
  2012-06-12 17:34 ` [PATCH 20/21] KVM: VMX: Improve error reporting during invalid guest state emulation Avi Kivity
  2012-06-12 17:34 ` [PATCH 21/21] KVM: VMX: Emulate invalid guest state by default Avi Kivity
  20 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

Process the event, possibly injecting an interrupt, before continuing.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/vmx.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 26e6bdf..661df185 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -4986,6 +4986,9 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu)
 		if (intr_window_requested && vmx_interrupt_allowed(vcpu))
 			return handle_interrupt_window(&vmx->vcpu);
 
+		if (test_bit(KVM_REQ_EVENT, &vcpu->requests))
+			return 1;
+
 		err = emulate_instruction(vcpu, 0);
 
 		if (err == EMULATE_DO_MMIO) {
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 20/21] KVM: VMX: Improve error reporting during invalid guest state emulation
  2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
                   ` (18 preceding siblings ...)
  2012-06-12 17:34 ` [PATCH 19/21] KVM: VMX: Stop invalid guest state emulation on pending event Avi Kivity
@ 2012-06-12 17:34 ` Avi Kivity
  2012-06-12 17:34 ` [PATCH 21/21] KVM: VMX: Emulate invalid guest state by default Avi Kivity
  20 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

If instruction emulation fails, report it properly to userspace.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/vmx.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 661df185..591dcea 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -4996,8 +4996,12 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu)
 			goto out;
 		}
 
-		if (err != EMULATE_DONE)
+		if (err != EMULATE_DONE) {
+			vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
+			vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION;
+			vcpu->run->internal.ndata = 0;
 			return 0;
+		}
 
 		if (signal_pending(current))
 			goto out;
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 21/21] KVM: VMX: Emulate invalid guest state by default
  2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
                   ` (19 preceding siblings ...)
  2012-06-12 17:34 ` [PATCH 20/21] KVM: VMX: Improve error reporting during invalid guest state emulation Avi Kivity
@ 2012-06-12 17:34 ` Avi Kivity
  20 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-12 17:34 UTC (permalink / raw)
  To: Marcelo Tosatti, kvm

Our emulation should be complete enough that we can emulate guests
while they are in big real mode, or in a mode transition that is not
virtualizable without unrestricted guest support.

Signed-off-by: Avi Kivity <avi@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 591dcea..e68a8fb 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -74,7 +74,7 @@
 static bool __read_mostly enable_ept_ad_bits = 1;
 module_param_named(eptad, enable_ept_ad_bits, bool, S_IRUGO);
 
-static bool __read_mostly emulate_invalid_guest_state = 0;
+static bool __read_mostly emulate_invalid_guest_state = true;
 module_param(emulate_invalid_guest_state, bool, S_IRUGO);
 
 static bool __read_mostly vmm_exclusive = 1;
-- 
1.7.10.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH 05/21] KVM: x86 emulator: allow loading null SS in long mode
  2012-06-12 17:34 ` [PATCH 05/21] KVM: x86 emulator: allow loading null SS in long mode Avi Kivity
@ 2012-06-18 14:14   ` Kevin Wolf
  2012-06-18 14:27     ` Avi Kivity
  0 siblings, 1 reply; 24+ messages in thread
From: Kevin Wolf @ 2012-06-18 14:14 UTC (permalink / raw)
  To: Avi Kivity; +Cc: Marcelo Tosatti, kvm

Am 12.06.2012 19:34, schrieb Avi Kivity:
> Null SS is valid in long mode; allow loading it.
> 
> Signed-off-by: Avi Kivity <avi@redhat.com>

The documentation suggests that trying to load it in CPL 3 should still
fail in long mode.

Kevin

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 05/21] KVM: x86 emulator: allow loading null SS in long mode
  2012-06-18 14:14   ` Kevin Wolf
@ 2012-06-18 14:27     ` Avi Kivity
  0 siblings, 0 replies; 24+ messages in thread
From: Avi Kivity @ 2012-06-18 14:27 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: Marcelo Tosatti, kvm

On 06/18/2012 05:14 PM, Kevin Wolf wrote:
> Am 12.06.2012 19:34, schrieb Avi Kivity:
>> Null SS is valid in long mode; allow loading it.
>> 
>> Signed-off-by: Avi Kivity <avi@redhat.com>
> 
> The documentation suggests that trying to load it in CPL 3 should still
> fail in long mode.

Right, good catch.

-- 
error compiling committee.c: too many arguments to function



^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2012-06-18 14:27 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-12 17:34 [PATCH 00/21] Big big real mode improvements Avi Kivity
2012-06-12 17:34 ` [PATCH 01/21] KVM: VMX: Return correct CPL during transition to protected mode Avi Kivity
2012-06-12 17:34 ` [PATCH 02/21] KVM: Split cpuid register access from computation Avi Kivity
2012-06-12 17:34 ` [PATCH 03/21] KVM: x86 emulator: change ->get_cpuid() accessor to use the x86 semantics Avi Kivity
2012-06-12 17:34 ` [PATCH 04/21] KVM: x86 emulator: emulate cpuid Avi Kivity
2012-06-12 17:34 ` [PATCH 05/21] KVM: x86 emulator: allow loading null SS in long mode Avi Kivity
2012-06-18 14:14   ` Kevin Wolf
2012-06-18 14:27     ` Avi Kivity
2012-06-12 17:34 ` [PATCH 06/21] KVM: x86 emulator: fix LIDT/LGDT " Avi Kivity
2012-06-12 17:34 ` [PATCH 07/21] KVM: VMX: Relax check on unusable segment Avi Kivity
2012-06-12 17:34 ` [PATCH 08/21] KVM: VMX: Limit iterations with emulator_invalid_guest_state Avi Kivity
2012-06-12 17:34 ` [PATCH 09/21] KVM: x86 emulator: emulate LEAVE Avi Kivity
2012-06-12 17:34 ` [PATCH 10/21] KVM: x86 emulator: initialize memop Avi Kivity
2012-06-12 17:34 ` [PATCH 11/21] KVM: Fix SS default ESP/EBP based addressing Avi Kivity
2012-06-12 17:34 ` [PATCH 12/21] KVM: x86 emulator: emulate SGDT/SIDT Avi Kivity
2012-06-12 17:34 ` [PATCH 13/21] KVM: VMX: Fix interrupt exit condition during emulation Avi Kivity
2012-06-12 17:34 ` [PATCH 14/21] KVM: VMX: Continue emulating after batch exhausted Avi Kivity
2012-06-12 17:34 ` [PATCH 15/21] KVM: x86 emulator: emulate LAHF Avi Kivity
2012-06-12 17:34 ` [PATCH 16/21] KVM: x86 emulator: fix byte-sized MOVZX/MOVSX Avi Kivity
2012-06-12 17:34 ` [PATCH 17/21] KVM: x86 emulator: split push logic from push opcode emulation Avi Kivity
2012-06-12 17:34 ` [PATCH 18/21] KVM: x86 emulator: implement ENTER Avi Kivity
2012-06-12 17:34 ` [PATCH 19/21] KVM: VMX: Stop invalid guest state emulation on pending event Avi Kivity
2012-06-12 17:34 ` [PATCH 20/21] KVM: VMX: Improve error reporting during invalid guest state emulation Avi Kivity
2012-06-12 17:34 ` [PATCH 21/21] KVM: VMX: Emulate invalid guest state by default Avi Kivity

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.