Okay - revised patch attached.
Thanks,
Dave
Keir Fraser wrote:
On 2 May 2006, at 15:58, David Lively wrote:
I've been getting a "Failed VMEntry" when trying to boot a second
VMX guest (while the first one is still running, but is no longer in
real mode). This patch fixes it.
Please `or' the vmread/vmwrite error returns together into an error
variable and BUG_ON(error) just once at the bottom of the function.
Also extend the comment a little to explicitly explain that this is
working around a VMENTRY validation check.
Apart from that it looks good.
-- Keir
Ensure segment bases are consistent with their
selectors for VMX guests in VM86 mode.
Signed-off-by: David Lively <dlively@xxxxxxxxxxxxxxx>
diff -r 880433ba7487 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c Mon May 1 17:08:02 2006 -0400
+++ b/xen/arch/x86/hvm/vmx/vmx.c Tue May 2 12:43:47 2006 -0400
@@ -487,6 +487,44 @@ static void vmx_store_cpu_guest_regs(
__vmptrld(virt_to_maddr(current->arch.hvm_vmx.vmcs));
}
+/* The VMX spec (section 4.3.1.2, Checks on Guest Segment
+ * Registers) says that virtual-8086 mode guests' segment
+ * base-address fields in the VMCS must be equal to their
+ * corresponding segment selector field shifted right by
+ * four bits upon vmentry.
+ *
+ * This function (called only for VM86-mode guests) fixes
+ * the bases to be consistent with the selectors in regs
+ * if they're not already. Without this, we can fail the
+ * vmentry check mentioned above.
+ */
+static void fixup_vm86_seg_bases(struct cpu_user_regs *regs)
+{
+ int err = 0;
+ unsigned long base;
+
+ err |= __vmread(GUEST_ES_BASE, &base);
+ if (regs->es << 4 != base)
+ err |= __vmwrite(GUEST_ES_BASE, regs->es << 4);
+ err |= __vmread(GUEST_CS_BASE, &base);
+ if (regs->cs << 4 != base)
+ err |= __vmwrite(GUEST_CS_BASE, regs->cs << 4);
+ err |= __vmread(GUEST_SS_BASE, &base);
+ if (regs->ss << 4 != base)
+ err |= __vmwrite(GUEST_SS_BASE, regs->ss << 4);
+ err |= __vmread(GUEST_DS_BASE, &base);
+ if (regs->ds << 4 != base)
+ err |= __vmwrite(GUEST_DS_BASE, regs->ds << 4);
+ err |= __vmread(GUEST_FS_BASE, &base);
+ if (regs->fs << 4 != base)
+ err |= __vmwrite(GUEST_FS_BASE, regs->fs << 4);
+ err |= __vmread(GUEST_GS_BASE, &base);
+ if (regs->gs << 4 != base)
+ err |= __vmwrite(GUEST_GS_BASE, regs->gs << 4);
+
+ BUG_ON(err);
+}
+
void vmx_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
{
if ( v != current )
@@ -523,6 +561,8 @@ void vmx_load_cpu_guest_regs(struct vcpu
__vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
else
__vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
+ if (regs->rflags & EF_VM)
+ fixup_vm86_seg_bases(regs);
__vmwrite(GUEST_CS_SELECTOR, regs->cs);
__vmwrite(GUEST_RIP, regs->rip);
@@ -540,6 +580,8 @@ void vmx_load_cpu_guest_regs(struct vcpu
__vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
else
__vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
+ if (regs->eflags & EF_VM)
+ fixup_vm86_seg_bases(regs);
__vmwrite(GUEST_CS_SELECTOR, regs->cs);
__vmwrite(GUEST_RIP, regs->eip);
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|