ia64/xen-unstable

changeset 13384:866a167bcb49

[HVM][VMX] Some simplifications, particularly to vmx_load/save_cpu_regs.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Thu Jan 11 15:43:38 2007 +0000 (2007-01-11)
parents a84fc0de350d
children 2c73e6e647f3
files xen/arch/x86/hvm/vmx/vmx.c xen/arch/x86/hvm/vmx/x86_32/exits.S xen/arch/x86/hvm/vmx/x86_64/exits.S
line diff
     1.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Thu Jan 11 11:41:44 2007 +0000
     1.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Thu Jan 11 15:43:38 2007 +0000
     1.3 @@ -410,10 +410,6 @@ static void vmx_store_cpu_guest_regs(
     1.4          regs->eflags = __vmread(GUEST_RFLAGS);
     1.5          regs->ss = __vmread(GUEST_SS_SELECTOR);
     1.6          regs->cs = __vmread(GUEST_CS_SELECTOR);
     1.7 -        regs->ds = __vmread(GUEST_DS_SELECTOR);
     1.8 -        regs->es = __vmread(GUEST_ES_SELECTOR);
     1.9 -        regs->gs = __vmread(GUEST_GS_SELECTOR);
    1.10 -        regs->fs = __vmread(GUEST_FS_SELECTOR);
    1.11          regs->eip = __vmread(GUEST_RIP);
    1.12          regs->esp = __vmread(GUEST_RSP);
    1.13      }
    1.14 @@ -429,62 +425,39 @@ static void vmx_store_cpu_guest_regs(
    1.15      vmx_vmcs_exit(v);
    1.16  }
    1.17  
    1.18 -/*
    1.19 - * The VMX spec (section 4.3.1.2, Checks on Guest Segment
    1.20 - * Registers) says that virtual-8086 mode guests' segment
    1.21 - * base-address fields in the VMCS must be equal to their
    1.22 - * corresponding segment selector field shifted right by
    1.23 - * four bits upon vmentry.
    1.24 - *
    1.25 - * This function (called only for VM86-mode guests) fixes
    1.26 - * the bases to be consistent with the selectors in regs
    1.27 - * if they're not already.  Without this, we can fail the
    1.28 - * vmentry check mentioned above.
    1.29 - */
    1.30 -static void fixup_vm86_seg_bases(struct cpu_user_regs *regs)
    1.31 +static void vmx_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
    1.32  {
    1.33      unsigned long base;
    1.34  
    1.35 -    base = __vmread(GUEST_ES_BASE);
    1.36 -    if (regs->es << 4 != base)
    1.37 -        __vmwrite(GUEST_ES_BASE, regs->es << 4);
    1.38 -    base = __vmread(GUEST_CS_BASE);
    1.39 -    if (regs->cs << 4 != base)
    1.40 -        __vmwrite(GUEST_CS_BASE, regs->cs << 4);
    1.41 -    base = __vmread(GUEST_SS_BASE);
    1.42 -    if (regs->ss << 4 != base)
    1.43 -        __vmwrite(GUEST_SS_BASE, regs->ss << 4);
    1.44 -    base = __vmread(GUEST_DS_BASE);
    1.45 -    if (regs->ds << 4 != base)
    1.46 -        __vmwrite(GUEST_DS_BASE, regs->ds << 4);
    1.47 -    base = __vmread(GUEST_FS_BASE);
    1.48 -    if (regs->fs << 4 != base)
    1.49 -        __vmwrite(GUEST_FS_BASE, regs->fs << 4);
    1.50 -    base = __vmread(GUEST_GS_BASE);
    1.51 -    if (regs->gs << 4 != base)
    1.52 -        __vmwrite(GUEST_GS_BASE, regs->gs << 4);
    1.53 -}
    1.54 -
    1.55 -static void vmx_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
    1.56 -{
    1.57      vmx_vmcs_enter(v);
    1.58  
    1.59      __vmwrite(GUEST_SS_SELECTOR, regs->ss);
    1.60 -    __vmwrite(GUEST_DS_SELECTOR, regs->ds);
    1.61 -    __vmwrite(GUEST_ES_SELECTOR, regs->es);
    1.62 -    __vmwrite(GUEST_GS_SELECTOR, regs->gs);
    1.63 -    __vmwrite(GUEST_FS_SELECTOR, regs->fs);
    1.64 -
    1.65      __vmwrite(GUEST_RSP, regs->esp);
    1.66  
    1.67      /* NB. Bit 1 of RFLAGS must be set for VMENTRY to succeed. */
    1.68      __vmwrite(GUEST_RFLAGS, regs->eflags | 2UL);
    1.69 -    if (regs->eflags & EF_TF)
    1.70 +
    1.71 +    if ( regs->eflags & EF_TF )
    1.72          __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
    1.73      else
    1.74          __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
    1.75 -    if (regs->eflags & EF_VM)
    1.76 -        fixup_vm86_seg_bases(regs);
    1.77 +
    1.78 +    if ( regs->eflags & EF_VM )
    1.79 +    {
    1.80 +        /*
    1.81 +         * The VMX spec (section 4.3.1.2, Checks on Guest Segment
    1.82 +         * Registers) says that virtual-8086 mode guests' segment
    1.83 +         * base-address fields in the VMCS must be equal to their
    1.84 +         * corresponding segment selector field shifted right by
    1.85 +         * four bits upon vmentry.
    1.86 +         */
    1.87 +        base = __vmread(GUEST_CS_BASE);
    1.88 +        if ( (regs->cs << 4) != base )
    1.89 +            __vmwrite(GUEST_CS_BASE, regs->cs << 4);
    1.90 +        base = __vmread(GUEST_SS_BASE);
    1.91 +        if ( (regs->ss << 4) != base )
    1.92 +            __vmwrite(GUEST_SS_BASE, regs->ss << 4);
    1.93 +    }
    1.94  
    1.95      __vmwrite(GUEST_CS_SELECTOR, regs->cs);
    1.96      __vmwrite(GUEST_RIP, regs->eip);
    1.97 @@ -2251,47 +2224,54 @@ static void vmx_reflect_exception(struct
    1.98      }
    1.99  }
   1.100  
   1.101 +static void vmx_failed_vmentry(unsigned int exit_reason)
   1.102 +{
   1.103 +    unsigned int failed_vmentry_reason = (uint16_t)exit_reason;
   1.104 +    unsigned long exit_qualification;
   1.105 +
   1.106 +    exit_qualification = __vmread(EXIT_QUALIFICATION);
   1.107 +    printk("Failed vm entry (exit reason 0x%x) ", exit_reason);
   1.108 +    switch ( failed_vmentry_reason )
   1.109 +    {
   1.110 +    case EXIT_REASON_INVALID_GUEST_STATE:
   1.111 +        printk("caused by invalid guest state (%ld).\n", exit_qualification);
   1.112 +        break;
   1.113 +    case EXIT_REASON_MSR_LOADING:
   1.114 +        printk("caused by MSR entry %ld loading.\n", exit_qualification);
   1.115 +        break;
   1.116 +    case EXIT_REASON_MACHINE_CHECK:
   1.117 +        printk("caused by machine check.\n");
   1.118 +        break;
   1.119 +    default:
   1.120 +        printk("reason not known yet!");
   1.121 +        break;
   1.122 +    }
   1.123 +
   1.124 +    printk("************* VMCS Area **************\n");
   1.125 +    vmcs_dump_vcpu();
   1.126 +    printk("**************************************\n");
   1.127 +
   1.128 +    domain_crash(current->domain);
   1.129 +}
   1.130 +
   1.131  asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
   1.132  {
   1.133      unsigned int exit_reason;
   1.134      unsigned long exit_qualification, inst_len = 0;
   1.135      struct vcpu *v = current;
   1.136  
   1.137 +    TRACE_3D(TRC_VMX_VMEXIT + v->vcpu_id, 0, 0, 0);
   1.138 +
   1.139      exit_reason = __vmread(VM_EXIT_REASON);
   1.140  
   1.141      perfc_incra(vmexits, exit_reason);
   1.142 +    TRACE_VMEXIT(0, exit_reason);
   1.143  
   1.144      if ( exit_reason != EXIT_REASON_EXTERNAL_INTERRUPT )
   1.145          local_irq_enable();
   1.146  
   1.147      if ( unlikely(exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) )
   1.148 -    {
   1.149 -        unsigned int failed_vmentry_reason = exit_reason & 0xFFFF;
   1.150 -
   1.151 -        exit_qualification = __vmread(EXIT_QUALIFICATION);
   1.152 -        printk("Failed vm entry (exit reason 0x%x) ", exit_reason);
   1.153 -        switch ( failed_vmentry_reason ) {
   1.154 -        case EXIT_REASON_INVALID_GUEST_STATE:
   1.155 -            printk("caused by invalid guest state (%ld).\n", exit_qualification);
   1.156 -            break;
   1.157 -        case EXIT_REASON_MSR_LOADING:
   1.158 -            printk("caused by MSR entry %ld loading.\n", exit_qualification);
   1.159 -            break;
   1.160 -        case EXIT_REASON_MACHINE_CHECK:
   1.161 -            printk("caused by machine check.\n");
   1.162 -            break;
   1.163 -        default:
   1.164 -            printk("reason not known yet!");
   1.165 -            break;
   1.166 -        }
   1.167 -
   1.168 -        printk("************* VMCS Area **************\n");
   1.169 -        vmcs_dump_vcpu();
   1.170 -        printk("**************************************\n");
   1.171 -        goto exit_and_crash;
   1.172 -    }
   1.173 -
   1.174 -    TRACE_VMEXIT(0, exit_reason);
   1.175 +        return vmx_failed_vmentry(exit_reason);
   1.176  
   1.177      switch ( exit_reason )
   1.178      {
   1.179 @@ -2519,11 +2499,6 @@ asmlinkage void vmx_trace_vmentry(void)
   1.180      TRACE_VMEXIT(4, 0);
   1.181  }
   1.182  
   1.183 -asmlinkage void vmx_trace_vmexit (void)
   1.184 -{
   1.185 -    TRACE_3D(TRC_VMX_VMEXIT + current->vcpu_id, 0, 0, 0);
   1.186 -}
   1.187 -
   1.188  /*
   1.189   * Local variables:
   1.190   * mode: C
     2.1 --- a/xen/arch/x86/hvm/vmx/x86_32/exits.S	Thu Jan 11 11:41:44 2007 +0000
     2.2 +++ b/xen/arch/x86/hvm/vmx/x86_32/exits.S	Thu Jan 11 15:43:38 2007 +0000
     2.3 @@ -50,9 +50,7 @@
     2.4  
     2.5          ALIGN
     2.6  ENTRY(vmx_asm_vmexit_handler)
     2.7 -        /* selectors are restored/saved by VMX */
     2.8          HVM_SAVE_ALL_NOSEGREGS
     2.9 -        call vmx_trace_vmexit
    2.10          movl %esp,%eax
    2.11          push %eax
    2.12          call vmx_vmexit_handler
     3.1 --- a/xen/arch/x86/hvm/vmx/x86_64/exits.S	Thu Jan 11 11:41:44 2007 +0000
     3.2 +++ b/xen/arch/x86/hvm/vmx/x86_64/exits.S	Thu Jan 11 15:43:38 2007 +0000
     3.3 @@ -65,9 +65,7 @@
     3.4  
     3.5          ALIGN
     3.6  ENTRY(vmx_asm_vmexit_handler)
     3.7 -        /* selectors are restored/saved by VMX */
     3.8          HVM_SAVE_ALL_NOSEGREGS
     3.9 -        call vmx_trace_vmexit
    3.10          movq %rsp,%rdi
    3.11          call vmx_vmexit_handler
    3.12          jmp vmx_asm_do_vmentry