[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [XEN] Re-jig VCPU initialisation -- VMX init requires generic VCPU



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID e793dad2114d678b9ce8ebd36145f205943bf1cb
# Parent  31985f348d2e388d973500816899fde97c4dbeda
[XEN] Re-jig VCPU initialisation -- VMX init requires generic VCPU
fields to already be allocated. This has led to a general cleanup of
domain and vcpu initialisation and destruction.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/ia64/xen/domain.c  |  103 ++++++++++++++-------------
 xen/arch/powerpc/domain.c   |   23 +++---
 xen/arch/x86/domain.c       |   44 ++++++-----
 xen/arch/x86/hvm/vmx/vmcs.c |  163 ++++++++++++--------------------------------
 xen/arch/x86/hvm/vmx/vmx.c  |   12 ---
 xen/common/domain.c         |   30 +++++---
 xen/common/sched_credit.c   |   81 ++++++++++-----------
 xen/common/sched_sedf.c     |   35 +++++----
 xen/common/schedule.c       |   21 +++--
 xen/include/xen/domain.h    |   14 +++
 xen/include/xen/sched-if.h  |    5 +
 xen/include/xen/sched.h     |    4 -
 12 files changed, 253 insertions(+), 282 deletions(-)

diff -r 31985f348d2e -r e793dad2114d xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c        Mon Nov 06 09:46:13 2006 +0000
+++ b/xen/arch/ia64/xen/domain.c        Mon Nov 06 11:03:04 2006 +0000
@@ -275,40 +275,61 @@ void hlt_timer_fn(void *data)
        vcpu_unblock(v);
 }
 
-struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id)
+void relinquish_vcpu_resources(struct vcpu *v)
+{
+    if (HAS_PERVCPU_VHPT(v->domain))
+        pervcpu_vhpt_free(v);
+    if (v->arch.privregs != NULL) {
+        free_xenheap_pages(v->arch.privregs,
+                           get_order_from_shift(XMAPPEDREGS_SHIFT));
+        v->arch.privregs = NULL;
+    }
+    kill_timer(&v->arch.hlt_timer);
+}
+
+struct vcpu *alloc_vcpu_struct(void)
 {
        struct vcpu *v;
        struct thread_info *ti;
-
-       /* Still keep idle vcpu0 static allocated at compilation, due
-        * to some code from Linux still requires it in early phase.
+       static int first_allocation = 1;
+
+       if (first_allocation) {
+               first_allocation = 0;
+               /* Still keep idle vcpu0 static allocated at compilation, due
+                * to some code from Linux still requires it in early phase.
+                */
+               return idle_vcpu[0];
+       }
+
+       if ((v = alloc_xenheap_pages(KERNEL_STACK_SIZE_ORDER)) == NULL)
+               return NULL;
+       memset(v, 0, sizeof(*v)); 
+
+       ti = alloc_thread_info(v);
+       /* Clear thread_info to clear some important fields, like
+        * preempt_count
         */
-       if (is_idle_domain(d) && !vcpu_id)
-           v = idle_vcpu[0];
-       else {
-           if ((v = alloc_xenheap_pages(KERNEL_STACK_SIZE_ORDER)) == NULL)
-               return NULL;
-           memset(v, 0, sizeof(*v)); 
-
-           ti = alloc_thread_info(v);
-           /* Clear thread_info to clear some important fields, like
-            * preempt_count
-            */
-           memset(ti, 0, sizeof(struct thread_info));
-           init_switch_stack(v);
-       }
+       memset(ti, 0, sizeof(struct thread_info));
+       init_switch_stack(v);
+
+       return v;
+}
+
+void free_vcpu_struct(struct vcpu *v)
+{
+       free_xenheap_pages(v, KERNEL_STACK_SIZE_ORDER);
+}
+
+int vcpu_initialise(struct vcpu *v)
+{
+       struct domain *d = v->domain;
+       int rc, order, i;
 
        if (!is_idle_domain(d)) {
            if (!d->arch.is_vti) {
-               int order;
-               int i;
-               // vti domain has its own vhpt policy.
-               if (HAS_PERVCPU_VHPT(d)) {
-                       if (pervcpu_vhpt_alloc(v) < 0) {
-                               free_xenheap_pages(v, KERNEL_STACK_SIZE_ORDER);
-                               return NULL;
-                       }
-               }
+               if (HAS_PERVCPU_VHPT(d))
+                       if ((rc = pervcpu_vhpt_alloc(v)) != 0)
+                               return rc;
 
                /* Create privregs page only if not VTi. */
                order = get_order_from_shift(XMAPPEDREGS_SHIFT);
@@ -344,34 +365,20 @@ struct vcpu *alloc_vcpu_struct(struct do
            v->arch.breakimm = d->arch.breakimm;
            v->arch.last_processor = INVALID_PROCESSOR;
        }
-       if (!VMX_DOMAIN(v)){
+
+       if (!VMX_DOMAIN(v))
                init_timer(&v->arch.hlt_timer, hlt_timer_fn, v,
                           first_cpu(cpu_online_map));
-       }
-
-       return v;
-}
-
-void relinquish_vcpu_resources(struct vcpu *v)
-{
-    if (HAS_PERVCPU_VHPT(v->domain))
-        pervcpu_vhpt_free(v);
-    if (v->arch.privregs != NULL) {
-        free_xenheap_pages(v->arch.privregs,
-                           get_order_from_shift(XMAPPEDREGS_SHIFT));
-        v->arch.privregs = NULL;
-    }
-    kill_timer(&v->arch.hlt_timer);
-}
-
-void free_vcpu_struct(struct vcpu *v)
+
+       return 0;
+}
+
+void vcpu_destroy(struct vcpu *v)
 {
        if (v->domain->arch.is_vti)
                vmx_relinquish_vcpu_resources(v);
        else
                relinquish_vcpu_resources(v);
-
-       free_xenheap_pages(v, KERNEL_STACK_SIZE_ORDER);
 }
 
 static void init_switch_stack(struct vcpu *v)
diff -r 31985f348d2e -r e793dad2114d xen/arch/powerpc/domain.c
--- a/xen/arch/powerpc/domain.c Mon Nov 06 09:46:13 2006 +0000
+++ b/xen/arch/powerpc/domain.c Mon Nov 06 11:03:04 2006 +0000
@@ -109,25 +109,26 @@ void machine_restart(char * __unused)
     while(1);
 }
 
-struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id)
+struct vcpu *alloc_vcpu_struct(void)
 {
     struct vcpu *v;
-
-    if ( (v = xmalloc(struct vcpu)) == NULL )
-        return NULL;
-
-    memset(v, 0, sizeof(*v));
-    v->vcpu_id = vcpu_id;
-
+    if ( (v = xmalloc(struct vcpu)) != NULL )
+        memset(v, 0, sizeof(*v));
     return v;
 }
 
 void free_vcpu_struct(struct vcpu *v)
 {
-    BUG_ON(v->next_in_list != NULL);
-    if ( v->vcpu_id != 0 )
-        v->domain->vcpu[v->vcpu_id - 1]->next_in_list = NULL;
     xfree(v);
+}
+
+int vcpu_initialise(struct vcpu *v)
+{
+    return 0;
+}
+
+void vcpu_destroy(struct vcpu *v)
+{
 }
 
 int arch_set_info_guest(struct vcpu *v, vcpu_guest_context_t *c)
diff -r 31985f348d2e -r e793dad2114d xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Mon Nov 06 09:46:13 2006 +0000
+++ b/xen/arch/x86/domain.c     Mon Nov 06 11:03:04 2006 +0000
@@ -114,27 +114,30 @@ void dump_pageframe_info(struct domain *
     }
 }
 
-struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id)
+struct vcpu *alloc_vcpu_struct(void)
 {
     struct vcpu *v;
-
-    if ( (v = xmalloc(struct vcpu)) == NULL )
-        return NULL;
-
-    memset(v, 0, sizeof(*v));
-
-    v->vcpu_id = vcpu_id;
-    v->domain  = d;
+    if ( (v = xmalloc(struct vcpu)) != NULL )
+        memset(v, 0, sizeof(*v));
+    return v;
+}
+
+void free_vcpu_struct(struct vcpu *v)
+{
+    xfree(v);
+}
+
+int vcpu_initialise(struct vcpu *v)
+{
+    struct domain *d = v->domain;
+    int rc;
 
     v->arch.flags = TF_kernel_mode;
 
     if ( is_hvm_domain(d) )
     {
-        if ( hvm_vcpu_initialise(v) != 0 )
-        {
-            xfree(v);
-            return NULL;
-        }
+        if ( (rc = hvm_vcpu_initialise(v)) != 0 )
+            return rc;
     }
     else
     {
@@ -150,16 +153,15 @@ struct vcpu *alloc_vcpu_struct(struct do
     }
 
     v->arch.perdomain_ptes =
-        d->arch.mm_perdomain_pt + (vcpu_id << GDT_LDT_VCPU_SHIFT);
+        d->arch.mm_perdomain_pt + (v->vcpu_id << GDT_LDT_VCPU_SHIFT);
 
     pae_l3_cache_init(&v->arch.pae_l3_cache);
 
-    return v;
-}
-
-void free_vcpu_struct(struct vcpu *v)
-{
-    xfree(v);
+    return 0;
+}
+
+void vcpu_destroy(struct vcpu *v)
+{
 }
 
 int arch_domain_create(struct domain *d)
diff -r 31985f348d2e -r e793dad2114d xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c       Mon Nov 06 09:46:13 2006 +0000
+++ b/xen/arch/x86/hvm/vmx/vmcs.c       Mon Nov 06 11:03:04 2006 +0000
@@ -193,11 +193,9 @@ void vmx_vmcs_enter(struct vcpu *v)
 {
     /*
      * NB. We must *always* run an HVM VCPU on its own VMCS, except for
-     * vmx_vmcs_enter/exit critical regions. This leads to some XXX TODOs XXX:
-     *  1. Move construct_vmcs() much earlier, to domain creation or
-     *     context initialisation.
-     *  2. VMPTRLD as soon as we context-switch to a HVM VCPU.
-     *  3. VMCS destruction needs to happen later (from domain_destroy()).
+     * vmx_vmcs_enter/exit critical regions. This leads to some TODOs:
+     *  1. VMPTRLD as soon as we context-switch to a HVM VCPU.
+     *  2. VMCS destruction needs to happen later (from domain_destroy()).
      * We can relax this a bit if a paused VCPU always commits its
      * architectural state to a software structure.
      */
@@ -233,17 +231,6 @@ void vmx_free_host_vmcs(struct vmcs_stru
 void vmx_free_host_vmcs(struct vmcs_struct *vmcs)
 {
     vmx_free_vmcs(vmcs);
-}
-
-static inline int construct_vmcs_controls(struct arch_vmx_struct *arch_vmx)
-{
-    int error = 0;
-
-    error |= __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control);
-    error |= __vmwrite(VM_EXIT_CONTROLS, vmx_vmexit_control);
-    error |= __vmwrite(VM_ENTRY_CONTROLS, vmx_vmentry_control);
-
-    return error;
 }
 
 #define GUEST_LAUNCH_DS         0x08
@@ -366,17 +353,40 @@ static void vmx_do_launch(struct vcpu *v
     v->arch.schedule_tail = arch_vmx_do_resume;
 }
 
-/*
- * Initially set the same environement as host.
- */
-static inline int construct_init_vmcs_guest(cpu_user_regs_t *regs)
+static int construct_vmcs(struct vcpu *v, cpu_user_regs_t *regs)
 {
     int error = 0;
+    unsigned long tmp, eflags;
     union vmcs_arbytes arbytes;
-    unsigned long dr7;
-    unsigned long eflags;
-
-    /* MSR */
+
+    /* VMCS controls. */
+    error |= __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control);
+    error |= __vmwrite(VM_EXIT_CONTROLS, vmx_vmexit_control);
+    error |= __vmwrite(VM_ENTRY_CONTROLS, vmx_vmentry_control);
+
+    /* Host data selectors. */
+    error |= __vmwrite(HOST_SS_SELECTOR, __HYPERVISOR_DS);
+    error |= __vmwrite(HOST_DS_SELECTOR, __HYPERVISOR_DS);
+    error |= __vmwrite(HOST_ES_SELECTOR, __HYPERVISOR_DS);
+#if defined(__i386__)
+    error |= __vmwrite(HOST_FS_SELECTOR, __HYPERVISOR_DS);
+    error |= __vmwrite(HOST_GS_SELECTOR, __HYPERVISOR_DS);
+    error |= __vmwrite(HOST_FS_BASE, 0);
+    error |= __vmwrite(HOST_GS_BASE, 0);
+#elif defined(__x86_64__)
+    rdmsrl(MSR_FS_BASE, tmp); error |= __vmwrite(HOST_FS_BASE, tmp);
+    rdmsrl(MSR_GS_BASE, tmp); error |= __vmwrite(HOST_GS_BASE, tmp);
+#endif
+
+    /* Host control registers. */
+    error |= __vmwrite(HOST_CR0, read_cr0());
+    error |= __vmwrite(HOST_CR4, read_cr4());
+
+    /* Host CS:RIP. */
+    error |= __vmwrite(HOST_CS_SELECTOR, __HYPERVISOR_CS);
+    error |= __vmwrite(HOST_RIP, (unsigned long)vmx_asm_vmexit_handler);
+
+    /* MSR intercepts. */
     error |= __vmwrite(VM_EXIT_MSR_LOAD_ADDR, 0);
     error |= __vmwrite(VM_EXIT_MSR_STORE_ADDR, 0);
     error |= __vmwrite(VM_EXIT_MSR_STORE_COUNT, 0);
@@ -395,7 +405,7 @@ static inline int construct_init_vmcs_gu
 
     error |= __vmwrite(GUEST_ACTIVITY_STATE, 0);
 
-    /* Guest Selectors */
+    /* Guest selectors. */
     error |= __vmwrite(GUEST_ES_SELECTOR, GUEST_LAUNCH_DS);
     error |= __vmwrite(GUEST_SS_SELECTOR, GUEST_LAUNCH_DS);
     error |= __vmwrite(GUEST_DS_SELECTOR, GUEST_LAUNCH_DS);
@@ -403,7 +413,7 @@ static inline int construct_init_vmcs_gu
     error |= __vmwrite(GUEST_GS_SELECTOR, GUEST_LAUNCH_DS);
     error |= __vmwrite(GUEST_CS_SELECTOR, GUEST_LAUNCH_CS);
 
-    /* Guest segment bases */
+    /* Guest segment bases. */
     error |= __vmwrite(GUEST_ES_BASE, 0);
     error |= __vmwrite(GUEST_SS_BASE, 0);
     error |= __vmwrite(GUEST_DS_BASE, 0);
@@ -411,7 +421,7 @@ static inline int construct_init_vmcs_gu
     error |= __vmwrite(GUEST_GS_BASE, 0);
     error |= __vmwrite(GUEST_CS_BASE, 0);
 
-    /* Guest segment Limits */
+    /* Guest segment limits. */
     error |= __vmwrite(GUEST_ES_LIMIT, GUEST_SEGMENT_LIMIT);
     error |= __vmwrite(GUEST_SS_LIMIT, GUEST_SEGMENT_LIMIT);
     error |= __vmwrite(GUEST_DS_LIMIT, GUEST_SEGMENT_LIMIT);
@@ -419,7 +429,7 @@ static inline int construct_init_vmcs_gu
     error |= __vmwrite(GUEST_GS_LIMIT, GUEST_SEGMENT_LIMIT);
     error |= __vmwrite(GUEST_CS_LIMIT, GUEST_SEGMENT_LIMIT);
 
-    /* Guest segment AR bytes */
+    /* Guest segment AR bytes. */
     arbytes.bytes = 0;
     arbytes.fields.seg_type = 0x3;          /* type = 3 */
     arbytes.fields.s = 1;                   /* code or data, i.e. not system */
@@ -428,131 +438,54 @@ static inline int construct_init_vmcs_gu
     arbytes.fields.default_ops_size = 1;    /* 32-bit */
     arbytes.fields.g = 1;
     arbytes.fields.null_bit = 0;            /* not null */
-
     error |= __vmwrite(GUEST_ES_AR_BYTES, arbytes.bytes);
     error |= __vmwrite(GUEST_SS_AR_BYTES, arbytes.bytes);
     error |= __vmwrite(GUEST_DS_AR_BYTES, arbytes.bytes);
     error |= __vmwrite(GUEST_FS_AR_BYTES, arbytes.bytes);
     error |= __vmwrite(GUEST_GS_AR_BYTES, arbytes.bytes);
-
     arbytes.fields.seg_type = 0xb;          /* type = 0xb */
     error |= __vmwrite(GUEST_CS_AR_BYTES, arbytes.bytes);
 
-    /* Guest GDT */
+    /* Guest GDT. */
     error |= __vmwrite(GUEST_GDTR_BASE, 0);
     error |= __vmwrite(GUEST_GDTR_LIMIT, 0);
 
-    /* Guest IDT */
+    /* Guest IDT. */
     error |= __vmwrite(GUEST_IDTR_BASE, 0);
     error |= __vmwrite(GUEST_IDTR_LIMIT, 0);
 
-    /* Guest LDT & TSS */
+    /* Guest LDT and TSS. */
     arbytes.fields.s = 0;                   /* not code or data segement */
     arbytes.fields.seg_type = 0x2;          /* LTD */
     arbytes.fields.default_ops_size = 0;    /* 16-bit */
     arbytes.fields.g = 0;
     error |= __vmwrite(GUEST_LDTR_AR_BYTES, arbytes.bytes);
-
     arbytes.fields.seg_type = 0xb;          /* 32-bit TSS (busy) */
     error |= __vmwrite(GUEST_TR_AR_BYTES, arbytes.bytes);
-    /* CR3 is set in vmx_final_setup_guest */
 
     error |= __vmwrite(GUEST_RSP, 0);
     error |= __vmwrite(GUEST_RIP, regs->eip);
 
-    /* Guest EFLAGS */
+    /* Guest EFLAGS. */
     eflags = regs->eflags & ~HVM_EFLAGS_RESERVED_0; /* clear 0s */
     eflags |= HVM_EFLAGS_RESERVED_1; /* set 1s */
     error |= __vmwrite(GUEST_RFLAGS, eflags);
 
     error |= __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
-    __asm__ __volatile__ ("mov %%dr7, %0\n" : "=r" (dr7));
-    error |= __vmwrite(GUEST_DR7, dr7);
+    __asm__ __volatile__ ("mov %%dr7, %0\n" : "=r" (tmp));
+    error |= __vmwrite(GUEST_DR7, tmp);
     error |= __vmwrite(VMCS_LINK_POINTER, ~0UL);
 #if defined(__i386__)
     error |= __vmwrite(VMCS_LINK_POINTER_HIGH, ~0UL);
 #endif
 
-    return error;
-}
-
-static inline int construct_vmcs_host(void)
-{
-    int error = 0;
-#ifdef __x86_64__
-    unsigned long fs_base;
-    unsigned long gs_base;
-#endif
-    unsigned long crn;
-
-    /* Host Selectors */
-    error |= __vmwrite(HOST_ES_SELECTOR, __HYPERVISOR_DS);
-    error |= __vmwrite(HOST_SS_SELECTOR, __HYPERVISOR_DS);
-    error |= __vmwrite(HOST_DS_SELECTOR, __HYPERVISOR_DS);
-#if defined(__i386__)
-    error |= __vmwrite(HOST_FS_SELECTOR, __HYPERVISOR_DS);
-    error |= __vmwrite(HOST_GS_SELECTOR, __HYPERVISOR_DS);
-    error |= __vmwrite(HOST_FS_BASE, 0);
-    error |= __vmwrite(HOST_GS_BASE, 0);
-
-#else
-    rdmsrl(MSR_FS_BASE, fs_base);
-    rdmsrl(MSR_GS_BASE, gs_base);
-    error |= __vmwrite(HOST_FS_BASE, fs_base);
-    error |= __vmwrite(HOST_GS_BASE, gs_base);
-
-#endif
-    error |= __vmwrite(HOST_CS_SELECTOR, __HYPERVISOR_CS);
-
-    __asm__ __volatile__ ("mov %%cr0,%0" : "=r" (crn) : );
-    error |= __vmwrite(HOST_CR0, crn); /* same CR0 */
-
-    /* CR3 is set in vmx_final_setup_hostos */
-    __asm__ __volatile__ ("mov %%cr4,%0" : "=r" (crn) : );
-    error |= __vmwrite(HOST_CR4, crn);
-
-    error |= __vmwrite(HOST_RIP, (unsigned long) vmx_asm_vmexit_handler);
-
-    return error;
-}
-
-/*
- * the working VMCS pointer has been set properly
- * just before entering this function.
- */
-static int construct_vmcs(struct vcpu *v,
-                          cpu_user_regs_t *regs)
-{
-    struct arch_vmx_struct *arch_vmx = &v->arch.hvm_vmx;
-    int error;
-
-    if ( (error = construct_vmcs_controls(arch_vmx)) ) {
-        printk("construct_vmcs: construct_vmcs_controls failed.\n");
-        return error;
-    }
-
-    /* host selectors */
-    if ( (error = construct_vmcs_host()) ) {
-        printk("construct_vmcs: construct_vmcs_host failed.\n");
-        return error;
-    }
-
-    /* guest selectors */
-    if ( (error = construct_init_vmcs_guest(regs)) ) {
-        printk("construct_vmcs: construct_vmcs_guest failed.\n");
-        return error;
-    }
-
-    if ( (error = __vmwrite(EXCEPTION_BITMAP,
-                            MONITOR_DEFAULT_EXCEPTION_BITMAP)) ) {
-        printk("construct_vmcs: setting exception bitmap failed.\n");
-        return error;
-    }
+    error |= __vmwrite(EXCEPTION_BITMAP,
+                       MONITOR_DEFAULT_EXCEPTION_BITMAP);
 
     if ( regs->eflags & EF_TF )
-        error = __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
+        error |= __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
     else
-        error = __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
+        error |= __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
 
     return error;
 }
diff -r 31985f348d2e -r e793dad2114d xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Mon Nov 06 09:46:13 2006 +0000
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Mon Nov 06 11:03:04 2006 +0000
@@ -566,8 +566,6 @@ static unsigned long vmx_get_ctrl_reg(st
     return 0;                   /* dummy */
 }
 
-
-
 /* Make sure that xen intercepts any FP accesses from current */
 static void vmx_stts(struct vcpu *v)
 {
@@ -591,19 +589,15 @@ static void vmx_stts(struct vcpu *v)
     }
 }
 
-
 static void vmx_set_tsc_offset(struct vcpu *v, u64 offset)
 {
-    /* VMX depends on operating on the current vcpu */
-    ASSERT(v == current);
-
+    vmx_vmcs_enter(v);
     __vmwrite(TSC_OFFSET, offset);
 #if defined (__i386__)
     __vmwrite(TSC_OFFSET_HIGH, offset >> 32);
 #endif
-}
-
-
+    vmx_vmcs_exit(v);
+}
 
 /* SMP VMX guest support */
 static void vmx_init_ap_context(struct vcpu_guest_context *ctxt,
diff -r 31985f348d2e -r e793dad2114d xen/common/domain.c
--- a/xen/common/domain.c       Mon Nov 06 09:46:13 2006 +0000
+++ b/xen/common/domain.c       Mon Nov 06 11:03:04 2006 +0000
@@ -64,12 +64,16 @@ void free_domain(struct domain *d)
     struct vcpu *v;
     int i;
 
+    for ( i = MAX_VIRT_CPUS-1; i >= 0; i-- )
+    {
+        if ( (v = d->vcpu[i]) == NULL )
+            continue;
+        vcpu_destroy(v);
+        sched_destroy_vcpu(v);
+        free_vcpu_struct(v);
+    }
+
     sched_destroy_domain(d);
-
-    for ( i = MAX_VIRT_CPUS-1; i >= 0; i-- )
-        if ( (v = d->vcpu[i]) != NULL )
-            free_vcpu_struct(v);
-
     xfree(d);
 }
 
@@ -80,7 +84,7 @@ struct vcpu *alloc_vcpu(
 
     BUG_ON(d->vcpu[vcpu_id] != NULL);
 
-    if ( (v = alloc_vcpu_struct(d, vcpu_id)) == NULL )
+    if ( (v = alloc_vcpu_struct()) == NULL )
         return NULL;
 
     v->domain = d;
@@ -94,8 +98,15 @@ struct vcpu *alloc_vcpu(
     if ( (vcpu_id != 0) && !is_idle_domain(d) )
         set_bit(_VCPUF_down, &v->vcpu_flags);
 
-    if ( sched_init_vcpu(v, cpu_id) < 0 )
-    {
+    if ( sched_init_vcpu(v, cpu_id) != 0 )
+    {
+        free_vcpu_struct(v);
+        return NULL;
+    }
+
+    if ( vcpu_initialise(v) != 0 )
+    {
+        sched_destroy_vcpu(v);
         free_vcpu_struct(v);
         return NULL;
     }
@@ -151,6 +162,9 @@ struct domain *domain_create(domid_t dom
     d->iomem_caps = rangeset_new(d, "I/O Memory", RANGESETF_prettyprint_hex);
     d->irq_caps   = rangeset_new(d, "Interrupts", 0);
     if ( (d->iomem_caps == NULL) || (d->irq_caps == NULL) )
+        goto fail4;
+
+    if ( sched_init_domain(d) != 0 )
         goto fail4;
 
     if ( !is_idle_domain(d) )
diff -r 31985f348d2e -r e793dad2114d xen/common/sched_credit.c
--- a/xen/common/sched_credit.c Mon Nov 06 09:46:13 2006 +0000
+++ b/xen/common/sched_credit.c Mon Nov 06 11:03:04 2006 +0000
@@ -115,8 +115,10 @@
     _MACRO(steal_peer_idle)                 \
     _MACRO(steal_peer_running)              \
     _MACRO(steal_peer_pinned)               \
+    _MACRO(dom_init)                        \
+    _MACRO(dom_destroy)                     \
     _MACRO(vcpu_init)                       \
-    _MACRO(dom_destroy)
+    _MACRO(vcpu_destroy)
 
 #ifndef NDEBUG
 #define CSCHED_STATS_EXPAND_CHECKS(_MACRO)  \
@@ -454,43 +456,14 @@ csched_vcpu_init(struct vcpu *vc)
 csched_vcpu_init(struct vcpu *vc)
 {
     struct domain * const dom = vc->domain;
-    struct csched_dom *sdom;
+    struct csched_dom *sdom = CSCHED_DOM(dom);
     struct csched_vcpu *svc;
-    int16_t pri;
 
     CSCHED_STAT_CRANK(vcpu_init);
-
-    /* Allocate, if appropriate, per-domain info */
-    if ( is_idle_vcpu(vc) )
-    {
-        sdom = NULL;
-        pri = CSCHED_PRI_IDLE;
-    }
-    else if ( CSCHED_DOM(dom) )
-    {
-        sdom = CSCHED_DOM(dom);
-        pri = CSCHED_PRI_TS_UNDER;
-    }
-    else 
-    {
-        sdom = xmalloc(struct csched_dom);
-        if ( !sdom )
-            return -1;
-
-        /* Initialize credit and weight */
-        INIT_LIST_HEAD(&sdom->active_vcpu);
-        sdom->active_vcpu_count = 0;
-        INIT_LIST_HEAD(&sdom->active_sdom_elem);
-        sdom->dom = dom;
-        sdom->weight = CSCHED_DEFAULT_WEIGHT;
-        sdom->cap = 0U;
-        dom->sched_priv = sdom;
-        pri = CSCHED_PRI_TS_UNDER;
-    }
 
     /* Allocate per-VCPU info */
     svc = xmalloc(struct csched_vcpu);
-    if ( !svc )
+    if ( svc == NULL )
         return -1;
 
     INIT_LIST_HEAD(&svc->runq_elem);
@@ -498,7 +471,7 @@ csched_vcpu_init(struct vcpu *vc)
     svc->sdom = sdom;
     svc->vcpu = vc;
     atomic_set(&svc->credit, 0);
-    svc->pri = pri;
+    svc->pri = is_idle_domain(dom) ? CSCHED_PRI_IDLE : CSCHED_PRI_TS_UNDER;
     memset(&svc->stats, 0, sizeof(svc->stats));
     vc->sched_priv = svc;
 
@@ -521,11 +494,13 @@ csched_vcpu_init(struct vcpu *vc)
 }
 
 static void
-csched_vcpu_free(struct vcpu *vc)
+csched_vcpu_destroy(struct vcpu *vc)
 {
     struct csched_vcpu * const svc = CSCHED_VCPU(vc);
     struct csched_dom * const sdom = svc->sdom;
     unsigned long flags;
+
+    CSCHED_STAT_CRANK(vcpu_destroy);
 
     BUG_ON( sdom == NULL );
     BUG_ON( !list_empty(&svc->runq_elem) );
@@ -641,19 +616,38 @@ csched_dom_cntl(
     return 0;
 }
 
+static int
+csched_dom_init(struct domain *dom)
+{
+    struct csched_dom *sdom;
+
+    CSCHED_STAT_CRANK(dom_init);
+
+    if ( is_idle_domain(dom) )
+        return 0;
+
+    sdom = xmalloc(struct csched_dom);
+    if ( sdom == NULL )
+        return -ENOMEM;
+
+    /* Initialize credit and weight */
+    INIT_LIST_HEAD(&sdom->active_vcpu);
+    sdom->active_vcpu_count = 0;
+    INIT_LIST_HEAD(&sdom->active_sdom_elem);
+    sdom->dom = dom;
+    sdom->weight = CSCHED_DEFAULT_WEIGHT;
+    sdom->cap = 0U;
+    dom->sched_priv = sdom;
+
+    return 0;
+}
+
 static void
 csched_dom_destroy(struct domain *dom)
 {
     struct csched_dom * const sdom = CSCHED_DOM(dom);
-    int i;
 
     CSCHED_STAT_CRANK(dom_destroy);
-
-    for ( i = 0; i < MAX_VIRT_CPUS; i++ )
-    {
-        if ( dom->vcpu[i] )
-            csched_vcpu_free(dom->vcpu[i]);
-    }
 
     xfree(sdom);
 }
@@ -1226,8 +1220,11 @@ struct scheduler sched_credit_def = {
     .opt_name       = "credit",
     .sched_id       = XEN_SCHEDULER_CREDIT,
 
+    .init_domain    = csched_dom_init,
+    .destroy_domain = csched_dom_destroy,
+
     .init_vcpu      = csched_vcpu_init,
-    .destroy_domain = csched_dom_destroy,
+    .destroy_vcpu   = csched_vcpu_destroy,
 
     .sleep          = csched_vcpu_sleep,
     .wake           = csched_vcpu_wake,
diff -r 31985f348d2e -r e793dad2114d xen/common/sched_sedf.c
--- a/xen/common/sched_sedf.c   Mon Nov 06 09:46:13 2006 +0000
+++ b/xen/common/sched_sedf.c   Mon Nov 06 11:03:04 2006 +0000
@@ -333,14 +333,6 @@ static int sedf_init_vcpu(struct vcpu *v
 {
     struct sedf_vcpu_info *inf;
 
-    if ( v->domain->sched_priv == NULL )
-    {
-        v->domain->sched_priv = xmalloc(struct sedf_dom_info);
-        if ( v->domain->sched_priv == NULL )
-            return -1;
-        memset(v->domain->sched_priv, 0, sizeof(struct sedf_dom_info));
-    }
-
     if ( (v->sched_priv = xmalloc(struct sedf_vcpu_info)) == NULL )
         return -1;
     memset(v->sched_priv, 0, sizeof(struct sedf_vcpu_info));
@@ -398,15 +390,25 @@ static int sedf_init_vcpu(struct vcpu *v
     return 0;
 }
 
+static void sedf_destroy_vcpu(struct vcpu *v)
+{
+    xfree(v->sched_priv);
+}
+
+static int sedf_init_domain(struct domain *d)
+{
+    d->sched_priv = xmalloc(struct sedf_dom_info);
+    if ( d->sched_priv == NULL )
+        return -ENOMEM;
+
+    memset(d->sched_priv, 0, sizeof(struct sedf_dom_info));
+
+    return 0;
+}
+
 static void sedf_destroy_domain(struct domain *d)
 {
-    int i;
-
     xfree(d->sched_priv);
- 
-    for ( i = 0; i < MAX_VIRT_CPUS; i++ )
-        if ( d->vcpu[i] )
-            xfree(d->vcpu[i]->sched_priv);
 }
 
 /*
@@ -1427,8 +1429,11 @@ struct scheduler sched_sedf_def = {
     .opt_name = "sedf",
     .sched_id = XEN_SCHEDULER_SEDF,
     
+    .init_domain    = sedf_init_domain,
+    .destroy_domain = sedf_destroy_domain,
+
     .init_vcpu      = sedf_init_vcpu,
-    .destroy_domain = sedf_destroy_domain,
+    .destroy_vcpu   = sedf_destroy_vcpu,
 
     .do_schedule    = sedf_do_schedule,
     .dump_cpu_state = sedf_dump_cpu_state,
diff -r 31985f348d2e -r e793dad2114d xen/common/schedule.c
--- a/xen/common/schedule.c     Mon Nov 06 09:46:13 2006 +0000
+++ b/xen/common/schedule.c     Mon Nov 06 11:03:04 2006 +0000
@@ -132,17 +132,20 @@ int sched_init_vcpu(struct vcpu *v, unsi
     return SCHED_OP(init_vcpu, v);
 }
 
+void sched_destroy_vcpu(struct vcpu *v)
+{
+    kill_timer(&v->timer);
+    kill_timer(&v->poll_timer);
+    SCHED_OP(destroy_vcpu, v);
+}
+
+int sched_init_domain(struct domain *d)
+{
+    return SCHED_OP(init_domain, d);
+}
+
 void sched_destroy_domain(struct domain *d)
 {
-    struct vcpu *v;
-
-    for_each_vcpu ( d, v )
-    {
-        kill_timer(&v->timer);
-        kill_timer(&v->poll_timer);
-        TRACE_2D(TRC_SCHED_DOM_REM, v->domain->domain_id, v->vcpu_id);
-    }
-
     SCHED_OP(destroy_domain, d);
 }
 
diff -r 31985f348d2e -r e793dad2114d xen/include/xen/domain.h
--- a/xen/include/xen/domain.h  Mon Nov 06 09:46:13 2006 +0000
+++ b/xen/include/xen/domain.h  Mon Nov 06 11:03:04 2006 +0000
@@ -15,9 +15,19 @@ void free_domain(struct domain *d);
  * Arch-specifics.
  */
 
-struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id);
+/* Allocate/free a VCPU structure. */
+struct vcpu *alloc_vcpu_struct(void);
+void free_vcpu_struct(struct vcpu *v);
 
-void free_vcpu_struct(struct vcpu *v);
+/*
+ * Initialise/destroy arch-specific details of a VCPU.
+ *  - vcpu_initialise() is called after the basic generic fields of the
+ *    VCPU structure are initialised. Many operations can be applied to the
+ *    VCPU at this point (e.g., vcpu_pause()).
+ *  - vcpu_destroy() is called only if vcpu_initialise() previously succeeded.
+ */
+int  vcpu_initialise(struct vcpu *v);
+void vcpu_destroy(struct vcpu *v);
 
 int arch_domain_create(struct domain *d);
 
diff -r 31985f348d2e -r e793dad2114d xen/include/xen/sched-if.h
--- a/xen/include/xen/sched-if.h        Mon Nov 06 09:46:13 2006 +0000
+++ b/xen/include/xen/sched-if.h        Mon Nov 06 11:03:04 2006 +0000
@@ -63,8 +63,11 @@ struct scheduler {
     void         (*init)           (void);
     void         (*tick)           (unsigned int cpu);
 
+    int          (*init_domain)    (struct domain *);
+    void         (*destroy_domain) (struct domain *);
+
     int          (*init_vcpu)      (struct vcpu *);
-    void         (*destroy_domain) (struct domain *);
+    void         (*destroy_vcpu)   (struct vcpu *);
 
     void         (*sleep)          (struct vcpu *);
     void         (*wake)           (struct vcpu *);
diff -r 31985f348d2e -r e793dad2114d xen/include/xen/sched.h
--- a/xen/include/xen/sched.h   Mon Nov 06 09:46:13 2006 +0000
+++ b/xen/include/xen/sched.h   Mon Nov 06 11:03:04 2006 +0000
@@ -291,7 +291,9 @@ void scheduler_init(void);
 void scheduler_init(void);
 void schedulers_start(void);
 int  sched_init_vcpu(struct vcpu *v, unsigned int processor);
-void sched_destroy_domain(struct domain *);
+void sched_destroy_vcpu(struct vcpu *v);
+int  sched_init_domain(struct domain *d);
+void sched_destroy_domain(struct domain *d);
 long sched_adjust(struct domain *, struct xen_domctl_scheduler_op *);
 int  sched_id(void);
 void vcpu_wake(struct vcpu *d);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.