direct-io.hg

changeset 12248:b2668cc03914

[HVM] Move VMX VMCS initialisation to vcpu-initialisation time.
Simplify context initialisation (e.g., no need for selectors to
be given dummy non-zero values).
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Mon Nov 06 13:13:04 2006 +0000 (2006-11-06)
parents 29bfe8852dce
children 1db00df48218
files tools/libxc/xc_hvm_build.c xen/arch/x86/domain.c xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/svm/vmcb.c xen/arch/x86/hvm/vmx/vmcs.c xen/arch/x86/hvm/vmx/vmx.c xen/include/asm-x86/hvm/support.h
line diff
     1.1 --- a/tools/libxc/xc_hvm_build.c	Mon Nov 06 11:36:38 2006 +0000
     1.2 +++ b/tools/libxc/xc_hvm_build.c	Mon Nov 06 13:13:04 2006 +0000
     1.3 @@ -309,8 +309,8 @@ static int xc_hvm_build_internal(int xc_
     1.4                                   unsigned long *store_mfn)
     1.5  {
     1.6      struct xen_domctl launch_domctl, domctl;
     1.7 -    int rc, i;
     1.8 -    vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt;
     1.9 +    vcpu_guest_context_t ctxt;
    1.10 +    int rc;
    1.11  
    1.12      if ( (image == NULL) || (image_size == 0) )
    1.13      {
    1.14 @@ -318,12 +318,6 @@ static int xc_hvm_build_internal(int xc_
    1.15          goto error_out;
    1.16      }
    1.17  
    1.18 -    if ( lock_pages(&st_ctxt, sizeof(st_ctxt) ) )
    1.19 -    {
    1.20 -        PERROR("%s: ctxt mlock failed", __func__);
    1.21 -        return 1;
    1.22 -    }
    1.23 -
    1.24      domctl.cmd = XEN_DOMCTL_getdomaininfo;
    1.25      domctl.domain = (domid_t)domid;
    1.26      if ( (xc_domctl(xc_handle, &domctl) < 0) ||
    1.27 @@ -333,56 +327,31 @@ static int xc_hvm_build_internal(int xc_
    1.28          goto error_out;
    1.29      }
    1.30  
    1.31 -    memset(ctxt, 0, sizeof(*ctxt));
    1.32 +    memset(&ctxt, 0, sizeof(ctxt));
    1.33  
    1.34      if ( setup_guest(xc_handle, domid, memsize, image, image_size,
    1.35 -                     ctxt, domctl.u.getdomaininfo.shared_info_frame,
    1.36 +                     &ctxt, domctl.u.getdomaininfo.shared_info_frame,
    1.37                       vcpus, pae, acpi, store_evtchn, store_mfn) < 0)
    1.38      {
    1.39          ERROR("Error constructing guest OS");
    1.40          goto error_out;
    1.41      }
    1.42  
    1.43 -    /* FPU is set up to default initial state. */
    1.44 -    memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
    1.45 -
    1.46 -    /* Virtual IDT is empty at start-of-day. */
    1.47 -    for ( i = 0; i < 256; i++ )
    1.48 +    if ( lock_pages(&ctxt, sizeof(ctxt) ) )
    1.49      {
    1.50 -        ctxt->trap_ctxt[i].vector = i;
    1.51 -        ctxt->trap_ctxt[i].cs     = FLAT_KERNEL_CS;
    1.52 +        PERROR("%s: ctxt mlock failed", __func__);
    1.53 +        goto error_out;
    1.54      }
    1.55  
    1.56 -    /* No LDT. */
    1.57 -    ctxt->ldt_ents = 0;
    1.58 -
    1.59 -    /* Use the default Xen-provided GDT. */
    1.60 -    ctxt->gdt_ents = 0;
    1.61 -
    1.62 -    /* No debugging. */
    1.63 -    memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
    1.64 -
    1.65 -    /* No callback handlers. */
    1.66 -#if defined(__i386__)
    1.67 -    ctxt->event_callback_cs     = FLAT_KERNEL_CS;
    1.68 -    ctxt->event_callback_eip    = 0;
    1.69 -    ctxt->failsafe_callback_cs  = FLAT_KERNEL_CS;
    1.70 -    ctxt->failsafe_callback_eip = 0;
    1.71 -#elif defined(__x86_64__)
    1.72 -    ctxt->event_callback_eip    = 0;
    1.73 -    ctxt->failsafe_callback_eip = 0;
    1.74 -    ctxt->syscall_callback_eip  = 0;
    1.75 -#endif
    1.76 -
    1.77      memset(&launch_domctl, 0, sizeof(launch_domctl));
    1.78 -
    1.79      launch_domctl.domain = (domid_t)domid;
    1.80      launch_domctl.u.vcpucontext.vcpu   = 0;
    1.81 -    set_xen_guest_handle(launch_domctl.u.vcpucontext.ctxt, ctxt);
    1.82 -
    1.83 +    set_xen_guest_handle(launch_domctl.u.vcpucontext.ctxt, &ctxt);
    1.84      launch_domctl.cmd = XEN_DOMCTL_setvcpucontext;
    1.85      rc = xc_domctl(xc_handle, &launch_domctl);
    1.86  
    1.87 +    unlock_pages(&ctxt, sizeof(ctxt));
    1.88 +
    1.89      return rc;
    1.90  
    1.91   error_out:
     2.1 --- a/xen/arch/x86/domain.c	Mon Nov 06 11:36:38 2006 +0000
     2.2 +++ b/xen/arch/x86/domain.c	Mon Nov 06 13:13:04 2006 +0000
     2.3 @@ -311,7 +311,7 @@ int arch_set_info_guest(
     2.4          /* Ensure real hardware interrupts are enabled. */
     2.5          v->arch.guest_context.user_regs.eflags |= EF_IE;
     2.6      }
     2.7 -    else if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) )
     2.8 +    else
     2.9      {
    2.10          hvm_load_cpu_guest_regs(v, &v->arch.guest_context.user_regs);
    2.11      }
     3.1 --- a/xen/arch/x86/hvm/svm/svm.c	Mon Nov 06 11:36:38 2006 +0000
     3.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Mon Nov 06 13:13:04 2006 +0000
     3.3 @@ -530,30 +530,10 @@ static void svm_set_tsc_offset(struct vc
     3.4  }
     3.5  
     3.6  
     3.7 -/* SVM-specific intitialization code for VCPU application processors */
     3.8 -static void svm_init_ap_context(struct vcpu_guest_context *ctxt, 
     3.9 -                                int vcpuid, int trampoline_vector)
    3.10 +static void svm_init_ap_context(
    3.11 +    struct vcpu_guest_context *ctxt, int vcpuid, int trampoline_vector)
    3.12  {
    3.13 -    int i;
    3.14 -    struct vcpu *v, *bsp = current;
    3.15 -    struct domain *d = bsp->domain;
    3.16 -    cpu_user_regs_t *regs;;
    3.17 -
    3.18 -  
    3.19 -    if ((v = d->vcpu[vcpuid]) == NULL)
    3.20 -    {
    3.21 -        printk("vcpuid %d is invalid!  good-bye.\n", vcpuid);
    3.22 -        domain_crash_synchronous();
    3.23 -    }
    3.24 -    regs = &v->arch.guest_context.user_regs;
    3.25 -
    3.26      memset(ctxt, 0, sizeof(*ctxt));
    3.27 -    for (i = 0; i < 256; ++i)
    3.28 -    {
    3.29 -        ctxt->trap_ctxt[i].vector = i;
    3.30 -        ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS;
    3.31 -    }
    3.32 -
    3.33  
    3.34      /*
    3.35       * We execute the trampoline code in real mode. The trampoline vector
    3.36 @@ -691,7 +671,7 @@ static void svm_load_cpu_user_regs(struc
    3.37      vmcb->rax      = regs->eax;
    3.38      vmcb->ss.sel   = regs->ss;
    3.39      vmcb->rsp      = regs->esp;   
    3.40 -    vmcb->rflags   = regs->eflags;
    3.41 +    vmcb->rflags   = regs->eflags | 2UL;
    3.42      vmcb->cs.sel   = regs->cs;
    3.43      vmcb->rip      = regs->eip;
    3.44      if (regs->eflags & EF_TF)
     4.1 --- a/xen/arch/x86/hvm/svm/vmcb.c	Mon Nov 06 11:36:38 2006 +0000
     4.2 +++ b/xen/arch/x86/hvm/svm/vmcb.c	Mon Nov 06 13:13:04 2006 +0000
     4.3 @@ -160,7 +160,6 @@ static int construct_init_vmcb_guest(str
     4.4      unsigned long crn;
     4.5      segment_attributes_t attrib;
     4.6      unsigned long dr7;
     4.7 -    unsigned long eflags;
     4.8      unsigned long shadow_cr;
     4.9      struct vmcb_struct *vmcb = arch_svm->vmcb;
    4.10  
    4.11 @@ -254,10 +253,7 @@ static int construct_init_vmcb_guest(str
    4.12      vmcb->rsp = 0;
    4.13      vmcb->rip = regs->eip;
    4.14  
    4.15 -    eflags = regs->eflags & ~HVM_EFLAGS_RESERVED_0; /* clear 0s */
    4.16 -    eflags |= HVM_EFLAGS_RESERVED_1; /* set 1s */
    4.17 -
    4.18 -    vmcb->rflags = eflags;
    4.19 +    vmcb->rflags = regs->eflags | 2UL; /* inc. reserved bit */
    4.20  
    4.21      __asm__ __volatile__ ("mov %%dr7, %0\n" : "=r" (dr7));
    4.22      vmcb->dr7 = dr7;
     5.1 --- a/xen/arch/x86/hvm/vmx/vmcs.c	Mon Nov 06 11:36:38 2006 +0000
     5.2 +++ b/xen/arch/x86/hvm/vmx/vmcs.c	Mon Nov 06 13:13:04 2006 +0000
     5.3 @@ -233,10 +233,7 @@ void vmx_free_host_vmcs(struct vmcs_stru
     5.4      vmx_free_vmcs(vmcs);
     5.5  }
     5.6  
     5.7 -#define GUEST_LAUNCH_DS         0x08
     5.8 -#define GUEST_LAUNCH_CS         0x10
     5.9  #define GUEST_SEGMENT_LIMIT     0xffffffff
    5.10 -#define HOST_SEGMENT_LIMIT      0xffffffff
    5.11  
    5.12  struct host_execution_env {
    5.13      /* selectors */
    5.14 @@ -353,12 +350,14 @@ static void vmx_do_launch(struct vcpu *v
    5.15      v->arch.schedule_tail = arch_vmx_do_resume;
    5.16  }
    5.17  
    5.18 -static int construct_vmcs(struct vcpu *v, cpu_user_regs_t *regs)
    5.19 +static int construct_vmcs(struct vcpu *v)
    5.20  {
    5.21      int error = 0;
    5.22 -    unsigned long tmp, eflags;
    5.23 +    unsigned long tmp;
    5.24      union vmcs_arbytes arbytes;
    5.25  
    5.26 +    vmx_vmcs_enter(v);
    5.27 +
    5.28      /* VMCS controls. */
    5.29      error |= __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control);
    5.30      error |= __vmwrite(VM_EXIT_CONTROLS, vmx_vmexit_control);
    5.31 @@ -405,14 +404,6 @@ static int construct_vmcs(struct vcpu *v
    5.32  
    5.33      error |= __vmwrite(GUEST_ACTIVITY_STATE, 0);
    5.34  
    5.35 -    /* Guest selectors. */
    5.36 -    error |= __vmwrite(GUEST_ES_SELECTOR, GUEST_LAUNCH_DS);
    5.37 -    error |= __vmwrite(GUEST_SS_SELECTOR, GUEST_LAUNCH_DS);
    5.38 -    error |= __vmwrite(GUEST_DS_SELECTOR, GUEST_LAUNCH_DS);
    5.39 -    error |= __vmwrite(GUEST_FS_SELECTOR, GUEST_LAUNCH_DS);
    5.40 -    error |= __vmwrite(GUEST_GS_SELECTOR, GUEST_LAUNCH_DS);
    5.41 -    error |= __vmwrite(GUEST_CS_SELECTOR, GUEST_LAUNCH_CS);
    5.42 -
    5.43      /* Guest segment bases. */
    5.44      error |= __vmwrite(GUEST_ES_BASE, 0);
    5.45      error |= __vmwrite(GUEST_SS_BASE, 0);
    5.46 @@ -463,14 +454,6 @@ static int construct_vmcs(struct vcpu *v
    5.47      arbytes.fields.seg_type = 0xb;          /* 32-bit TSS (busy) */
    5.48      error |= __vmwrite(GUEST_TR_AR_BYTES, arbytes.bytes);
    5.49  
    5.50 -    error |= __vmwrite(GUEST_RSP, 0);
    5.51 -    error |= __vmwrite(GUEST_RIP, regs->eip);
    5.52 -
    5.53 -    /* Guest EFLAGS. */
    5.54 -    eflags = regs->eflags & ~HVM_EFLAGS_RESERVED_0; /* clear 0s */
    5.55 -    eflags |= HVM_EFLAGS_RESERVED_1; /* set 1s */
    5.56 -    error |= __vmwrite(GUEST_RFLAGS, eflags);
    5.57 -
    5.58      error |= __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
    5.59      __asm__ __volatile__ ("mov %%dr7, %0\n" : "=r" (tmp));
    5.60      error |= __vmwrite(GUEST_DR7, tmp);
    5.61 @@ -482,10 +465,7 @@ static int construct_vmcs(struct vcpu *v
    5.62      error |= __vmwrite(EXCEPTION_BITMAP,
    5.63                         MONITOR_DEFAULT_EXCEPTION_BITMAP);
    5.64  
    5.65 -    if ( regs->eflags & EF_TF )
    5.66 -        error |= __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
    5.67 -    else
    5.68 -        error |= __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
    5.69 +    vmx_vmcs_exit(v);
    5.70  
    5.71      return error;
    5.72  }
    5.73 @@ -494,7 +474,16 @@ int vmx_create_vmcs(struct vcpu *v)
    5.74  {
    5.75      if ( (v->arch.hvm_vmx.vmcs = vmx_alloc_vmcs()) == NULL )
    5.76          return -ENOMEM;
    5.77 + 
    5.78      __vmx_clear_vmcs(v);
    5.79 +    
    5.80 +    if ( construct_vmcs(v) != 0 )
    5.81 +    {
    5.82 +        vmx_free_vmcs(v->arch.hvm_vmx.vmcs);
    5.83 +        v->arch.hvm_vmx.vmcs = NULL;
    5.84 +        return -EINVAL;
    5.85 +    }
    5.86 +
    5.87      return 0;
    5.88  }
    5.89  
    5.90 @@ -547,20 +536,7 @@ void arch_vmx_do_resume(struct vcpu *v)
    5.91  
    5.92  void arch_vmx_do_launch(struct vcpu *v)
    5.93  {
    5.94 -    cpu_user_regs_t *regs = &current->arch.guest_context.user_regs;
    5.95 -
    5.96      vmx_load_vmcs(v);
    5.97 -
    5.98 -    if ( construct_vmcs(v, regs) < 0 )
    5.99 -    {
   5.100 -        if ( v->vcpu_id == 0 ) {
   5.101 -            printk("Failed to construct VMCS for BSP.\n");
   5.102 -        } else {
   5.103 -            printk("Failed to construct VMCS for AP %d.\n", v->vcpu_id);
   5.104 -        }
   5.105 -        domain_crash_synchronous();
   5.106 -    }
   5.107 -
   5.108      vmx_do_launch(v);
   5.109      reset_stack_and_jump(vmx_asm_do_vmentry);
   5.110  }
     6.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Mon Nov 06 11:36:38 2006 +0000
     6.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Mon Nov 06 13:13:04 2006 +0000
     6.3 @@ -57,6 +57,8 @@ static int vmx_vcpu_initialise(struct vc
     6.4  {
     6.5      int rc;
     6.6  
     6.7 +    spin_lock_init(&v->arch.hvm_vmx.vmcs_lock);
     6.8 +
     6.9      v->arch.schedule_tail    = arch_vmx_do_launch;
    6.10      v->arch.ctxt_switch_from = vmx_ctxt_switch_from;
    6.11      v->arch.ctxt_switch_to   = vmx_ctxt_switch_to;
    6.12 @@ -69,8 +71,6 @@ static int vmx_vcpu_initialise(struct vc
    6.13          return rc;
    6.14      }
    6.15  
    6.16 -    spin_lock_init(&v->arch.hvm_vmx.vmcs_lock);
    6.17 -
    6.18      return 0;
    6.19  }
    6.20  
    6.21 @@ -534,7 +534,8 @@ static void vmx_load_cpu_guest_regs(stru
    6.22  
    6.23      __vmwrite(GUEST_RSP, regs->esp);
    6.24  
    6.25 -    __vmwrite(GUEST_RFLAGS, regs->eflags);
    6.26 +    /* NB. Bit 1 of RFLAGS must be set for VMENTRY to succeed. */
    6.27 +    __vmwrite(GUEST_RFLAGS, regs->eflags | 2UL);
    6.28      if (regs->eflags & EF_TF)
    6.29          __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
    6.30      else
    6.31 @@ -599,33 +600,13 @@ static void vmx_set_tsc_offset(struct vc
    6.32      vmx_vmcs_exit(v);
    6.33  }
    6.34  
    6.35 -/* SMP VMX guest support */
    6.36 -static void vmx_init_ap_context(struct vcpu_guest_context *ctxt,
    6.37 -                         int vcpuid, int trampoline_vector)
    6.38 +static void vmx_init_ap_context(
    6.39 +    struct vcpu_guest_context *ctxt, int vcpuid, int trampoline_vector)
    6.40  {
    6.41 -    int i;
    6.42 -
    6.43      memset(ctxt, 0, sizeof(*ctxt));
    6.44 -
    6.45 -    /*
    6.46 -     * Initial register values:
    6.47 -     */
    6.48      ctxt->user_regs.eip = VMXASSIST_BASE;
    6.49      ctxt->user_regs.edx = vcpuid;
    6.50      ctxt->user_regs.ebx = trampoline_vector;
    6.51 -
    6.52 -    /* Virtual IDT is empty at start-of-day. */
    6.53 -    for ( i = 0; i < 256; i++ )
    6.54 -    {
    6.55 -        ctxt->trap_ctxt[i].vector = i;
    6.56 -        ctxt->trap_ctxt[i].cs     = FLAT_KERNEL_CS;
    6.57 -    }
    6.58 -
    6.59 -    /* No callback handlers. */
    6.60 -#if defined(__i386__)
    6.61 -    ctxt->event_callback_cs     = FLAT_KERNEL_CS;
    6.62 -    ctxt->failsafe_callback_cs  = FLAT_KERNEL_CS;
    6.63 -#endif
    6.64  }
    6.65  
    6.66  void do_nmi(struct cpu_user_regs *);
     7.1 --- a/xen/include/asm-x86/hvm/support.h	Mon Nov 06 11:36:38 2006 +0000
     7.2 +++ b/xen/include/asm-x86/hvm/support.h	Mon Nov 06 13:13:04 2006 +0000
     7.3 @@ -94,13 +94,6 @@ enum hval_bitmaps {
     7.4  
     7.5  #define VMX_DELIVER_NO_ERROR_CODE  -1
     7.6  
     7.7 -/*
     7.8 - * This works for both 32bit & 64bit eflags filteration
     7.9 - * done in construct_init_vmc[sb]_guest()
    7.10 - */
    7.11 -#define HVM_EFLAGS_RESERVED_0          0xffc08028 /* bitmap for 0 */
    7.12 -#define HVM_EFLAGS_RESERVED_1          0x00000002 /* bitmap for 1 */
    7.13 -
    7.14  #if HVM_DEBUG
    7.15  #define DBG_LEVEL_0                 (1 << 0)
    7.16  #define DBG_LEVEL_1                 (1 << 1)