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

[Xen-changelog] [xen-unstable] Fix CPU hotplug after percpu data handling changes.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1274264126 -3600
# Node ID abc9f8e809e555b00d16a94fa4a1635803591fc9
# Parent  f67ae6f9d4107f091d062fc1501a96f873671d10
Fix CPU hotplug after percpu data handling changes.

Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/ia64/linux-xen/smpboot.c |    2 
 xen/arch/ia64/xen/xensetup.c      |   10 ---
 xen/arch/x86/setup.c              |   13 ----
 xen/arch/x86/smpboot.c            |    3 
 xen/common/domain.c               |    6 -
 xen/common/sched_sedf.c           |    2 
 xen/common/schedule.c             |  116 ++++++++++++++++++++++----------------
 xen/include/xen/domain.h          |    1 
 xen/include/xen/sched-if.h        |    4 -
 9 files changed, 73 insertions(+), 84 deletions(-)

diff -r f67ae6f9d410 -r abc9f8e809e5 xen/arch/ia64/linux-xen/smpboot.c
--- a/xen/arch/ia64/linux-xen/smpboot.c Wed May 19 08:22:06 2010 +0100
+++ b/xen/arch/ia64/linux-xen/smpboot.c Wed May 19 11:15:26 2010 +0100
@@ -526,7 +526,7 @@ do_rest:
 #else
        struct vcpu *v;
 
-       v = alloc_idle_vcpu(cpu);
+       v = idle_vcpu[cpu];
        BUG_ON(v == NULL);
 
        //printf ("do_boot_cpu: cpu=%d, domain=%p, vcpu=%p\n", cpu, idle, v);
diff -r f67ae6f9d410 -r abc9f8e809e5 xen/arch/ia64/xen/xensetup.c
--- a/xen/arch/ia64/xen/xensetup.c      Wed May 19 08:22:06 2010 +0100
+++ b/xen/arch/ia64/xen/xensetup.c      Wed May 19 11:15:26 2010 +0100
@@ -341,7 +341,6 @@ void __init start_kernel(void)
     unsigned long dom0_memory_start, dom0_memory_size;
     unsigned long dom0_initrd_start, dom0_initrd_size;
     unsigned long md_end, relo_start, relo_end, relo_size = 0;
-    struct domain *idle_domain;
     struct vcpu *dom0_vcpu0;
     efi_memory_desc_t *kern_md, *last_md, *md;
     unsigned long xenheap_phys_end;
@@ -560,15 +559,8 @@ skip_move:
 
     late_setup_arch(&cmdline);
 
+    idle_vcpu[0] = (struct vcpu*) ia64_r13;
     scheduler_init();
-    idle_vcpu[0] = (struct vcpu*) ia64_r13;
-    idle_domain = domain_create(IDLE_DOMAIN_ID, 0, 0);
-    if ( idle_domain == NULL )
-        BUG();
-    idle_domain->vcpu = idle_vcpu;
-    idle_domain->max_vcpus = NR_CPUS;
-    if ( alloc_vcpu(idle_domain, 0, 0) == NULL )
-        BUG();
 
     alloc_dom_xen_and_dom_io();
     setup_per_cpu_areas();
diff -r f67ae6f9d410 -r abc9f8e809e5 xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Wed May 19 08:22:06 2010 +0100
+++ b/xen/arch/x86/setup.c      Wed May 19 11:15:26 2010 +0100
@@ -189,22 +189,9 @@ extern char __init_begin[], __init_end[]
 
 static void __init init_idle_domain(void)
 {
-    struct domain *idle_domain;
-
-    /* Domain creation requires that scheduler structures are initialised. */
     scheduler_init();
-
-    idle_domain = domain_create(IDLE_DOMAIN_ID, 0, 0);
-    if ( idle_domain == NULL )
-        BUG();
-    idle_domain->vcpu = idle_vcpu;
-    idle_domain->max_vcpus = NR_CPUS;
-    if ( alloc_vcpu(idle_domain, 0, 0) == NULL )
-        BUG();
-
     set_current(idle_vcpu[0]);
     this_cpu(curr_vcpu) = current;
-
     setup_idle_pagetable();
 }
 
diff -r f67ae6f9d410 -r abc9f8e809e5 xen/arch/x86/smpboot.c
--- a/xen/arch/x86/smpboot.c    Wed May 19 08:22:06 2010 +0100
+++ b/xen/arch/x86/smpboot.c    Wed May 19 11:15:26 2010 +0100
@@ -678,9 +678,6 @@ static int cpu_smpboot_alloc(unsigned in
     struct page_info *page;
 #endif
 
-    if ( alloc_idle_vcpu(cpu) == NULL )
-        goto oom;
-
     stack_base[cpu] = alloc_xenheap_pages(STACK_ORDER, 0);
     if ( stack_base[cpu] == NULL )
         goto oom;
diff -r f67ae6f9d410 -r abc9f8e809e5 xen/common/domain.c
--- a/xen/common/domain.c       Wed May 19 08:22:06 2010 +0100
+++ b/xen/common/domain.c       Wed May 19 11:15:26 2010 +0100
@@ -194,12 +194,6 @@ struct vcpu *alloc_vcpu(
     return v;
 }
 
-struct vcpu *alloc_idle_vcpu(unsigned int cpu_id)
-{
-    return idle_vcpu[cpu_id] ?: alloc_vcpu(idle_vcpu[0]->domain,
-                                           cpu_id, cpu_id);
-}
-
 static unsigned int __read_mostly extra_dom0_irqs = 256;
 static unsigned int __read_mostly extra_domU_irqs = 32;
 static void __init parse_extra_guest_irqs(const char *s)
diff -r f67ae6f9d410 -r abc9f8e809e5 xen/common/sched_sedf.c
--- a/xen/common/sched_sedf.c   Wed May 19 08:22:06 2010 +0100
+++ b/xen/common/sched_sedf.c   Wed May 19 11:15:26 2010 +0100
@@ -123,7 +123,7 @@ struct sedf_cpu_info {
 #define RUNQ(cpu)      (&CPU_INFO(cpu)->runnableq)
 #define WAITQ(cpu)     (&CPU_INFO(cpu)->waitq)
 #define EXTRAQ(cpu,i)  (&(CPU_INFO(cpu)->extraq[i]))
-#define IDLETASK(cpu)  ((struct vcpu *)per_cpu(schedule_data, cpu).idle)
+#define IDLETASK(cpu)  (idle_vcpu[cpu])
 
 #define PERIOD_BEGIN(inf) ((inf)->deadl_abs - (inf)->period)
 
diff -r f67ae6f9d410 -r abc9f8e809e5 xen/common/schedule.c
--- a/xen/common/schedule.c     Wed May 19 08:22:06 2010 +0100
+++ b/xen/common/schedule.c     Wed May 19 11:15:26 2010 +0100
@@ -211,27 +211,14 @@ int sched_init_vcpu(struct vcpu *v, unsi
     if ( is_idle_domain(d) )
     {
         per_cpu(schedule_data, v->processor).curr = v;
-        per_cpu(schedule_data, v->processor).idle = v;
         v->is_running = 1;
     }
 
     TRACE_2D(TRC_SCHED_DOM_ADD, v->domain->domain_id, v->vcpu_id);
-
-    if ( unlikely(per_cpu(schedule_data, v->processor).sched_priv == NULL)
-         && (DOM2OP(d)->alloc_pdata != NULL) )
-    {
-        per_cpu(schedule_data, v->processor).sched_priv =
-            SCHED_OP(DOM2OP(d), alloc_pdata, processor);
-        if ( per_cpu(schedule_data, v->processor).sched_priv == NULL )
-            return 1;
-    }
 
     v->sched_priv = SCHED_OP(DOM2OP(d), alloc_vdata, v, d->sched_priv);
     if ( v->sched_priv == NULL )
         return 1;
-
-    if ( is_idle_domain(d) )
-        per_cpu(schedule_data, v->processor).sched_idlevpriv = v->sched_priv;
 
     return 0;
 }
@@ -1090,39 +1077,73 @@ const struct scheduler *scheduler_get_by
     return NULL;
 }
 
-static int cpu_callback(
+static int cpu_schedule_up(unsigned int cpu)
+{
+    struct schedule_data *sd = &per_cpu(schedule_data, cpu);
+
+    per_cpu(scheduler, cpu) = &ops;
+    spin_lock_init(&sd->_lock);
+    sd->schedule_lock = &sd->_lock;
+    sd->curr = idle_vcpu[cpu];
+    init_timer(&sd->s_timer, s_timer_fn, NULL, cpu);
+    atomic_set(&sd->urgent_count, 0);
+
+    /* Boot CPU is dealt with later in schedule_init(). */
+    if ( cpu == 0 )
+        return 0;
+
+    if ( idle_vcpu[cpu] == NULL )
+        alloc_vcpu(idle_vcpu[0]->domain, cpu, cpu);
+    if ( idle_vcpu[cpu] == NULL )
+        return -ENOMEM;
+
+    if ( (ops.alloc_pdata != NULL) &&
+         ((sd->sched_priv = ops.alloc_pdata(&ops, cpu)) == NULL) )
+        return -ENOMEM;
+
+    return 0;
+}
+
+static void cpu_schedule_down(unsigned int cpu)
+{
+    struct schedule_data *sd = &per_cpu(schedule_data, cpu);
+
+    if ( sd->sched_priv != NULL )
+        SCHED_OP(&ops, free_pdata, sd->sched_priv, cpu);
+
+    kill_timer(&sd->s_timer);
+}
+
+static int cpu_schedule_callback(
     struct notifier_block *nfb, unsigned long action, void *hcpu)
 {
     unsigned int cpu = (unsigned long)hcpu;
+    int rc = 0;
 
     switch ( action )
     {
     case CPU_UP_PREPARE:
-        per_cpu(scheduler, cpu) = &ops;
-        spin_lock_init(&per_cpu(schedule_data, cpu)._lock);
-        per_cpu(schedule_data, cpu).schedule_lock
-            = &per_cpu(schedule_data, cpu)._lock;
-        init_timer(&per_cpu(schedule_data, cpu).s_timer,
-                   s_timer_fn, NULL, cpu);
+        rc = cpu_schedule_up(cpu);
         break;
+    case CPU_UP_CANCELED:
     case CPU_DEAD:
-        kill_timer(&per_cpu(schedule_data, cpu).s_timer);
+        cpu_schedule_down(cpu);
         break;
     default:
         break;
     }
 
-    return NOTIFY_DONE;
-}
-
-static struct notifier_block cpu_nfb = {
-    .notifier_call = cpu_callback
+    return !rc ? NOTIFY_DONE : notifier_from_errno(rc);
+}
+
+static struct notifier_block cpu_schedule_nfb = {
+    .notifier_call = cpu_schedule_callback
 };
 
 /* Initialise the data structures. */
 void __init scheduler_init(void)
 {
-    void *hcpu = (void *)(long)smp_processor_id();
+    struct domain *idle_domain;
     int i;
 
     open_softirq(SCHEDULE_SOFTIRQ, schedule);
@@ -1140,53 +1161,54 @@ void __init scheduler_init(void)
         ops = *schedulers[0];
     }
 
-    cpu_callback(&cpu_nfb, CPU_UP_PREPARE, hcpu);
-    register_cpu_notifier(&cpu_nfb);
+    if ( cpu_schedule_up(0) )
+        BUG();
+    register_cpu_notifier(&cpu_schedule_nfb);
 
     printk("Using scheduler: %s (%s)\n", ops.name, ops.opt_name);
     if ( SCHED_OP(&ops, init) )
         panic("scheduler returned error on init\n");
+
+    idle_domain = domain_create(IDLE_DOMAIN_ID, 0, 0);
+    BUG_ON(idle_domain == NULL);
+    idle_domain->vcpu = idle_vcpu;
+    idle_domain->max_vcpus = NR_CPUS;
+    if ( alloc_vcpu(idle_domain, 0, 0) == NULL )
+        BUG();
+    if ( ops.alloc_pdata &&
+         !(this_cpu(schedule_data).sched_priv = ops.alloc_pdata(&ops, 0)) )
+        BUG();
 }
 
 void schedule_cpu_switch(unsigned int cpu, struct cpupool *c)
 {
     unsigned long flags;
-    struct vcpu *v;
-    void *ppriv, *ppriv_old, *vpriv = NULL;
+    struct vcpu *idle;
+    void *ppriv, *ppriv_old, *vpriv, *vpriv_old;
     struct scheduler *old_ops = per_cpu(scheduler, cpu);
     struct scheduler *new_ops = (c == NULL) ? &ops : c->sched;
 
     if ( old_ops == new_ops )
         return;
 
-    v = per_cpu(schedule_data, cpu).idle;
+    idle = idle_vcpu[cpu];
     ppriv = SCHED_OP(new_ops, alloc_pdata, cpu);
-    if ( c != NULL )
-        vpriv = SCHED_OP(new_ops, alloc_vdata, v, v->domain->sched_priv);
+    vpriv = SCHED_OP(new_ops, alloc_vdata, idle, idle->domain->sched_priv);
 
     spin_lock_irqsave(per_cpu(schedule_data, cpu).schedule_lock, flags);
 
-    if ( c == NULL )
-    {
-        vpriv = v->sched_priv;
-        v->sched_priv = per_cpu(schedule_data, cpu).sched_idlevpriv;
-    }
-    else
-    {
-        v->sched_priv = vpriv;
-        vpriv = NULL;
-    }
     SCHED_OP(old_ops, tick_suspend, cpu);
+    vpriv_old = idle->sched_priv;
+    idle->sched_priv = vpriv;
     per_cpu(scheduler, cpu) = new_ops;
     ppriv_old = per_cpu(schedule_data, cpu).sched_priv;
     per_cpu(schedule_data, cpu).sched_priv = ppriv;
     SCHED_OP(new_ops, tick_resume, cpu);
-    SCHED_OP(new_ops, insert_vcpu, v);
+    SCHED_OP(new_ops, insert_vcpu, idle);
 
     spin_unlock_irqrestore(per_cpu(schedule_data, cpu).schedule_lock, flags);
 
-    if ( vpriv != NULL )
-        SCHED_OP(old_ops, free_vdata, vpriv);
+    SCHED_OP(old_ops, free_vdata, vpriv);
     SCHED_OP(old_ops, free_pdata, ppriv_old, cpu);
 }
 
diff -r f67ae6f9d410 -r abc9f8e809e5 xen/include/xen/domain.h
--- a/xen/include/xen/domain.h  Wed May 19 08:22:06 2010 +0100
+++ b/xen/include/xen/domain.h  Wed May 19 11:15:26 2010 +0100
@@ -14,7 +14,6 @@ struct vcpu *alloc_vcpu(
     struct domain *d, unsigned int vcpu_id, unsigned int cpu_id);
 int boot_vcpu(
     struct domain *d, int vcpuid, vcpu_guest_context_u ctxt);
-struct vcpu *alloc_idle_vcpu(unsigned int cpu_id);
 struct vcpu *alloc_dom0_vcpu0(void);
 void vcpu_reset(struct vcpu *v);
 
diff -r f67ae6f9d410 -r abc9f8e809e5 xen/include/xen/sched-if.h
--- a/xen/include/xen/sched-if.h        Wed May 19 08:22:06 2010 +0100
+++ b/xen/include/xen/sched-if.h        Wed May 19 11:15:26 2010 +0100
@@ -30,12 +30,10 @@ struct schedule_data {
     spinlock_t         *schedule_lock,
                        _lock;
     struct vcpu        *curr;           /* current task                    */
-    struct vcpu        *idle;           /* idle task for this cpu          */
     void               *sched_priv;
-    void               *sched_idlevpriv; /* default scheduler vcpu data    */
     struct timer        s_timer;        /* scheduling timer                */
     atomic_t            urgent_count;   /* how many urgent vcpus           */
-} __cacheline_aligned;
+};
 
 DECLARE_PER_CPU(struct schedule_data, schedule_data);
 DECLARE_PER_CPU(struct scheduler *, scheduler);

_______________________________________________
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®.