diff mbox

Fix up vmx_set_segment for booting older guests.

Message ID 1256025040-4941-1-git-send-email-clalance@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Chris Lalancette Oct. 20, 2009, 7:50 a.m. UTC
None
diff mbox

Patch

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 364263a..311afd4 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -1846,7 +1846,22 @@  static void vmx_set_segment(struct kvm_vcpu *vcpu,
 		vmx->rmode.tr.ar = vmx_segment_access_rights(var);
 		return;
 	}
-	vmcs_writel(sf->base, var->base);
+
+	/* Intel 64 and IA-32 Architecture Software Developer's Manual Vol. 3b,
+	 * section 22.3.1.2 states that VMENTRY will fail if bits 63:32 of the
+	 * base address for CS, SS, DS, ES are not 0 and the register is usable.
+	 *
+	 * If var->base happens to have bit 31 set, then it will get sign
+	 * extended on the vmcs_writel(), causing this check to fail.  Make
+	 * sure to use the 32-bit version where appropriate.
+	 */
+	if (sf->base == GUEST_CS_BASE ||
+	    ((~sf->ar_bytes & 0x00010000) && (sf->base == GUEST_SS_BASE ||
+					      sf->base == GUEST_DS_BASE ||
+					      sf->base == GUEST_ES_BASE)))
+		vmcs_write32(sf->base, var->base);
+	else
+		vmcs_writel(sf->base, var->base);
 	vmcs_write32(sf->limit, var->limit);
 	vmcs_write16(sf->selector, var->selector);
 	if (vmx->rmode.vm86_active && var->s) {