ia64/xen-unstable

changeset 9922:e1409c2ace46

Ensure segment bases are consistent with their
selectors for VMX guests in VM86 mode.

Signed-off-by: David Lively <dlively@virtualiron.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed May 03 10:56:19 2006 +0100 (2006-05-03)
parents 3f69d30f697d
children 47442d409d8e
files xen/arch/x86/hvm/vmx/vmx.c
line diff
     1.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Wed May 03 07:44:20 2006 +0100
     1.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Wed May 03 10:56:19 2006 +0100
     1.3 @@ -475,6 +475,45 @@ static void vmx_store_cpu_guest_regs(
     1.4          __vmptrld(virt_to_maddr(current->arch.hvm_vmx.vmcs));
     1.5  }
     1.6  
     1.7 +/*
     1.8 + * The VMX spec (section 4.3.1.2, Checks on Guest Segment
     1.9 + * Registers) says that virtual-8086 mode guests' segment
    1.10 + * base-address fields in the VMCS must be equal to their
    1.11 + * corresponding segment selector field shifted right by
    1.12 + * four bits upon vmentry.
    1.13 + *
    1.14 + * This function (called only for VM86-mode guests) fixes
    1.15 + * the bases to be consistent with the selectors in regs
    1.16 + * if they're not already.  Without this, we can fail the
    1.17 + * vmentry check mentioned above.
    1.18 + */
    1.19 +static void fixup_vm86_seg_bases(struct cpu_user_regs *regs)
    1.20 +{
    1.21 +    int err = 0;
    1.22 +    unsigned long base;
    1.23 +
    1.24 +    err |= __vmread(GUEST_ES_BASE, &base);
    1.25 +    if (regs->es << 4 != base)
    1.26 +        err |= __vmwrite(GUEST_ES_BASE, regs->es << 4);
    1.27 +    err |= __vmread(GUEST_CS_BASE, &base);
    1.28 +    if (regs->cs << 4 != base)
    1.29 +        err |= __vmwrite(GUEST_CS_BASE, regs->cs << 4);
    1.30 +    err |= __vmread(GUEST_SS_BASE, &base);
    1.31 +    if (regs->ss << 4 != base)
    1.32 +        err |= __vmwrite(GUEST_SS_BASE, regs->ss << 4);
    1.33 +    err |= __vmread(GUEST_DS_BASE, &base);
    1.34 +    if (regs->ds << 4 != base)
    1.35 +        err |= __vmwrite(GUEST_DS_BASE, regs->ds << 4);
    1.36 +    err |= __vmread(GUEST_FS_BASE, &base);
    1.37 +    if (regs->fs << 4 != base)
    1.38 +        err |= __vmwrite(GUEST_FS_BASE, regs->fs << 4);
    1.39 +    err |= __vmread(GUEST_GS_BASE, &base);
    1.40 +    if (regs->gs << 4 != base)
    1.41 +        err |= __vmwrite(GUEST_GS_BASE, regs->gs << 4);
    1.42 +
    1.43 +    BUG_ON(err);
    1.44 +}
    1.45 +
    1.46  void vmx_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
    1.47  {
    1.48      if ( v != current )
    1.49 @@ -511,6 +550,8 @@ void vmx_load_cpu_guest_regs(struct vcpu
    1.50          __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
    1.51      else
    1.52          __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
    1.53 +    if (regs->rflags & EF_VM)
    1.54 +        fixup_vm86_seg_bases(regs);
    1.55  
    1.56      __vmwrite(GUEST_CS_SELECTOR, regs->cs);
    1.57      __vmwrite(GUEST_RIP, regs->eip);