x86: Implement cpu hotplug notifiers. Use them.
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 14 May 2010 14:22:48 +0000 (15:22 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 14 May 2010 14:22:48 +0000 (15:22 +0100)
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
27 files changed:
xen/arch/ia64/xen/xen.lds.S
xen/arch/ia64/xen/xensetup.c
xen/arch/x86/cpu/mcheck/mce_intel.c
xen/arch/x86/domain.c
xen/arch/x86/hvm/hvm.c
xen/arch/x86/platform_hypercall.c
xen/arch/x86/setup.c
xen/arch/x86/smpboot.c
xen/arch/x86/xen.lds.S
xen/common/cpu.c
xen/common/cpupool.c
xen/common/gdbstub.c
xen/common/kernel.c
xen/common/notifier.c
xen/common/rcupdate.c
xen/common/tasklet.c
xen/drivers/cpufreq/cpufreq.c
xen/include/asm-x86/hvm/hvm.h
xen/include/asm-x86/processor.h
xen/include/asm-x86/smp.h
xen/include/xen/cpu.h [new file with mode: 0644]
xen/include/xen/gdbstub.h
xen/include/xen/init.h
xen/include/xen/notifier.h
xen/include/xen/rcupdate.h
xen/include/xen/sched.h
xen/include/xen/tasklet.h

index 547790f800ae1f03cf490aa7fb4ad17898dbd273..f642a93dc05329debab52c0a5b96b42a51a85356 100644 (file)
@@ -139,6 +139,8 @@ SECTIONS
   .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET)
        {
          __initcall_start = .;
+         *(.initcallpresmp.init)
+         __presmp_initcall_end = .;
          *(.initcall1.init)
          *(.initcall2.init)
          *(.initcall3.init)
index 82b758b7884e61c4750e940f1a17d7de5b04b0ba..a7e4791771a4886b83069ebc3c25036ca0ea9ef6 100644 (file)
@@ -89,13 +89,6 @@ xen_count_pages(u64 start, u64 end, void *arg)
     return 0;
 }
 
-static void __init do_initcalls(void)
-{
-    initcall_t *call;
-    for ( call = &__initcall_start; call < &__initcall_end; call++ )
-        (*call)();
-}
-
 /*
  * IPF loader only supports one command line currently, for
  * both xen and guest kernel. This function provides pre-parse
@@ -612,15 +605,15 @@ skip_move:
     /*  Enable IRQ to receive IPI (needed for ITC sync).  */
     local_irq_enable();
 
+    do_presmp_initcalls();
+
 printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus);
     for_each_present_cpu ( i )
     {
         if ( num_online_cpus() >= max_cpus )
             break;
-        if ( !cpu_online(i) ) {
-            rcu_online_cpu(i);
-            __cpu_up(i);
-       }
+        if ( !cpu_online(i) )
+            cpu_up(i);
     }
 
     local_irq_disable();
@@ -629,8 +622,6 @@ printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus);
     smp_cpus_done(max_cpus);
 #endif
 
-    initialise_gdb(); /* could be moved earlier */
-
     iommu_setup();    /* setup iommu if available */
 
     do_initcalls();
index ccd1d7da9f697d5083e7c24d6c35103e5a913485..21c756c366fc95db020a58c5909cf45b74c81365 100644 (file)
@@ -6,6 +6,7 @@
 #include <xen/delay.h>
 #include <xen/smp.h>
 #include <xen/mm.h>
+#include <xen/cpu.h>
 #include <asm/processor.h> 
 #include <public/sysctl.h>
 #include <asm/system.h>
@@ -788,7 +789,7 @@ static void __cpu_mcheck_distribute_cmci(void *unused)
     cmci_discover();
 }
 
-void cpu_mcheck_distribute_cmci(void)
+static void cpu_mcheck_distribute_cmci(void)
 {
     if (cmci_support && !mce_disabled)
         on_each_cpu(__cpu_mcheck_distribute_cmci, NULL, 0);
@@ -816,7 +817,7 @@ static void clear_cmci(void)
     }
 }
 
-void cpu_mcheck_disable(void)
+static void cpu_mcheck_disable(void)
 {
     clear_in_cr4(X86_CR4_MCE);
 
@@ -1007,4 +1008,31 @@ int intel_mce_rdmsr(uint32_t msr, uint64_t *val)
     return ret;
 }
 
+static int cpu_callback(
+    struct notifier_block *nfb, unsigned long action, void *hcpu)
+{
+    switch ( action )
+    {
+    case CPU_DYING:
+        cpu_mcheck_disable();
+        break;
+    case CPU_DEAD:
+        cpu_mcheck_distribute_cmci();
+        break;
+    default:
+        break;
+    }
 
+    return NOTIFY_DONE;
+}
+
+static struct notifier_block cpu_nfb = {
+    .notifier_call = cpu_callback
+};
+
+static int __init intel_mce_initcall(void)
+{
+    register_cpu_notifier(&cpu_nfb);
+    return 0;
+}
+presmp_initcall(intel_mce_initcall);
index 2570e77b14b95bb3fd78c2b5a8216926c1fbeeff..57b54f21be8039baecc12cd3b8f463329c5d147d 100644 (file)
@@ -32,6 +32,7 @@
 #include <xen/acpi.h>
 #include <xen/pci.h>
 #include <xen/paging.h>
+#include <xen/cpu.h>
 #include <public/sysctl.h>
 #include <asm/regs.h>
 #include <asm/mc146818rtc.h>
index 9d86b85ae915e1fc812c8d242a72ff14eb57bf68..cfa0643f959b79c7f170c4c0c76c283363f2a876 100644 (file)
@@ -33,6 +33,7 @@
 #include <xen/guest_access.h>
 #include <xen/event.h>
 #include <xen/paging.h>
+#include <xen/cpu.h>
 #include <asm/shadow.h>
 #include <asm/hap.h>
 #include <asm/current.h>
@@ -70,6 +71,28 @@ struct hvm_function_table hvm_funcs __read_mostly;
 unsigned long __attribute__ ((__section__ (".bss.page_aligned")))
     hvm_io_bitmap[3*PAGE_SIZE/BYTES_PER_LONG];
 
+static int cpu_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:
+        rc = hvm_funcs.cpu_prepare(cpu);
+        break;
+    default:
+        break;
+    }
+
+    return !rc ? NOTIFY_DONE : notifier_from_errno(rc);
+}
+
+static struct notifier_block cpu_nfb = {
+    .notifier_call = cpu_callback
+};
+
 void hvm_enable(struct hvm_function_table *fns)
 {
     extern int hvm_port80_allowed;
@@ -91,6 +114,8 @@ void hvm_enable(struct hvm_function_table *fns)
 
     if ( hvm_funcs.hap_supported )
         printk("HVM: Hardware Assisted Paging detected.\n");
+
+    register_cpu_notifier(&cpu_nfb);
 }
 
 /*
index 67a5fbb73c36b870554436d99157c7cc4cc78309..b3ab4b7446417252606155d9e00a35cebb9e457d 100644 (file)
@@ -19,6 +19,7 @@
 #include <xen/iocap.h>
 #include <xen/guest_access.h>
 #include <xen/acpi.h>
+#include <xen/cpu.h>
 #include <asm/current.h>
 #include <public/platform.h>
 #include <acpi/cpufreq/processor_perf.h>
index 4eabbbf6e4c62864dd19971e693680f4950ad827..d6c07f0895141d43ac389cf6aa8bd2f117c5a47c 100644 (file)
@@ -156,13 +156,6 @@ static void __init parse_acpi_param(char *s)
     }
 }
 
-static void __init do_initcalls(void)
-{
-    initcall_t *call;
-    for ( call = &__initcall_start; call < &__initcall_end; call++ )
-        (*call)();
-}
-
 #define EARLY_FAIL(f, a...) do {                \
     printk( f , ## a );                         \
     for ( ; ; ) halt();                         \
@@ -1070,15 +1063,14 @@ void __init __start_xen(unsigned long mbi_p)
 
     console_init_postirq();
 
+    do_presmp_initcalls();
+
     for_each_present_cpu ( i )
     {
         if ( num_online_cpus() >= max_cpus )
             break;
         if ( !cpu_online(i) )
-        {
-            rcu_online_cpu(i);
-            __cpu_up(i);
-        }
+            cpu_up(i);
 
         /* Set up cpu_to_node[]. */
         srat_detect_node(i);
@@ -1089,8 +1081,6 @@ void __init __start_xen(unsigned long mbi_p)
     printk("Brought up %ld CPUs\n", (long)num_online_cpus());
     smp_cpus_done(max_cpus);
 
-    initialise_gdb(); /* could be moved earlier */
-
     do_initcalls();
 
     if ( opt_watchdog ) 
@@ -1099,11 +1089,6 @@ void __init __start_xen(unsigned long mbi_p)
     if ( !tboot_protect_mem_regions() )
         panic("Could not protect TXT memory regions\n");
 
-    /* Create initial cpupool 0. */
-    cpupool0 = cpupool_create(0, NULL);
-    if ( (cpupool0 == NULL) || cpupool0_cpu_assign(cpupool0) )
-        panic("Error creating cpupool 0\n");
-
     /* Create initial domain 0. */
     dom0 = domain_create(0, DOMCRF_s3_integrity, DOM0_SSIDREF);
     if ( (dom0 == NULL) || (alloc_dom0_vcpu0() == NULL) )
index b6583fe4abe896f84a5de296c4fe784480802771..8b857b38097075f847e0821b3a6de18f6ea8f7e0 100644 (file)
@@ -47,6 +47,7 @@
 #include <xen/serial.h>
 #include <xen/numa.h>
 #include <xen/event.h>
+#include <xen/cpu.h>
 #include <asm/current.h>
 #include <asm/mc146818rtc.h>
 #include <asm/desc.h>
@@ -106,7 +107,6 @@ static void map_cpu_to_logical_apicid(void);
 DEFINE_PER_CPU(int, cpu_state) = { 0 };
 
 void *stack_base[NR_CPUS];
-DEFINE_SPINLOCK(cpu_add_remove_lock);
 
 /*
  * The bootstrap kernel entry code has set these up. Save them for
@@ -1272,17 +1272,6 @@ int __cpu_disable(void)
 {
        int cpu = smp_processor_id();
 
-       /*
-        * Perhaps use cpufreq to drop frequency, but that could go
-        * into generic code.
-        *
-        * We won't take down the boot processor on i386 due to some
-        * interrupts only being able to be serviced by the BSP.
-        * Especially so if we're not using an IOAPIC   -zwane
-        */
-       if (cpu == 0)
-               return -EBUSY;
-
        local_irq_disable();
        clear_local_APIC();
        /* Allow any queued timer interrupts to get serviced */
@@ -1292,8 +1281,6 @@ int __cpu_disable(void)
 
        time_suspend();
 
-       cpu_mcheck_disable();
-
        remove_siblinginfo(cpu);
 
        /* It's now safe to remove this processor from the online map */
@@ -1313,10 +1300,8 @@ void __cpu_die(unsigned int cpu)
 
        for (;;) {
                /* They ack this in play_dead by setting CPU_DEAD */
-               if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
-                       printk ("CPU %u is now offline\n", cpu);
+               if (per_cpu(cpu_state, cpu) == CPU_DEAD)
                        return;
-               }
                mdelay(100);
                mb();
                process_pending_softirqs();
@@ -1327,7 +1312,19 @@ void __cpu_die(unsigned int cpu)
 
 static int take_cpu_down(void *unused)
 {
-       return __cpu_disable();
+       void *hcpu = (void *)(long)smp_processor_id();
+       int rc;
+
+       spin_lock(&cpu_add_remove_lock);
+
+       if (cpu_notifier_call_chain(CPU_DYING, hcpu) != NOTIFY_DONE)
+               BUG();
+
+       rc = __cpu_disable();
+
+       spin_unlock(&cpu_add_remove_lock);
+
+       return rc;
 }
 
 /*
@@ -1339,7 +1336,8 @@ static cpumask_t cpu_offlining;
 
 int cpu_down(unsigned int cpu)
 {
-       int err = 0;
+       int err, notifier_rc, nr_calls;
+       void *hcpu = (void *)(long)cpu;
 
        spin_lock(&cpu_add_remove_lock);
 
@@ -1350,32 +1348,42 @@ int cpu_down(unsigned int cpu)
 
        cpu_set(cpu, cpu_offlining);
 
-       err = cpupool_cpu_remove(cpu);
-       if (err)
-               goto out;
-
        printk("Prepare to bring CPU%d down...\n", cpu);
 
-       cpufreq_del_cpu(cpu);
+       notifier_rc = __cpu_notifier_call_chain(
+               CPU_DOWN_PREPARE, hcpu, -1, &nr_calls);
+       if (notifier_rc != NOTIFY_DONE) {
+               err = notifier_to_errno(notifier_rc);
+               nr_calls--;
+               notifier_rc = __cpu_notifier_call_chain(
+                       CPU_DOWN_FAILED, hcpu, nr_calls, NULL);
+               BUG_ON(notifier_rc != NOTIFY_DONE);
+               goto out;
+       }
 
        spin_unlock(&cpu_add_remove_lock);
        err = stop_machine_run(take_cpu_down, NULL, cpu);
        spin_lock(&cpu_add_remove_lock);
 
        if (err < 0) {
-               cpupool_cpu_add(cpu);
+               notifier_rc = cpu_notifier_call_chain(CPU_DOWN_FAILED, hcpu);
+               BUG_ON(notifier_rc != NOTIFY_DONE);
                goto out;
        }
 
        __cpu_die(cpu);
        BUG_ON(cpu_online(cpu));
 
-       migrate_tasklets_from_cpu(cpu);
-       cpu_mcheck_distribute_cmci();
+       notifier_rc = cpu_notifier_call_chain(CPU_DEAD, hcpu);
+       BUG_ON(notifier_rc != NOTIFY_DONE);
 
 out:
-       if (!err)
+       if (!err) {
+               printk("CPU %u is now offline\n", cpu);
                send_guest_global_virq(dom0, VIRQ_PCPU_STATE);
+       } else {
+               printk("Failed to take down CPU %u (error %d)\n", cpu, err);
+       }
        cpu_clear(cpu, cpu_offlining);
        spin_unlock(&cpu_add_remove_lock);
        return err;
@@ -1392,8 +1400,6 @@ int cpu_up(unsigned int cpu)
                goto out;
        }
 
-       rcu_online_cpu(cpu);
-
        err = __cpu_up(cpu);
        if (err < 0)
                goto out;
@@ -1525,11 +1531,16 @@ int cpu_add(uint32_t apic_id, uint32_t acpi_id, uint32_t pxm)
 
 int __devinit __cpu_up(unsigned int cpu)
 {
-       int ret;
-
-       ret = hvm_cpu_prepare(cpu);
-       if (ret)
-               return ret;
+       int notifier_rc, ret = 0, nr_calls;
+       void *hcpu = (void *)(long)cpu;
+
+       notifier_rc = __cpu_notifier_call_chain(
+               CPU_UP_PREPARE, hcpu, -1, &nr_calls);
+       if (notifier_rc != NOTIFY_DONE) {
+               ret = notifier_to_errno(notifier_rc);
+               nr_calls--;
+               goto fail;
+       }
 
        /*
         * We do warm boot only on cpus that had booted earlier
@@ -1542,18 +1553,18 @@ int __devinit __cpu_up(unsigned int cpu)
                smpboot_restore_warm_reset_vector();
        }
 
-       if (ret)
-               return -EIO;
+       if (ret) {
+               ret = -EIO;
+               goto fail;
+       }
 
        /* In case one didn't come up */
        if (!cpu_isset(cpu, cpu_callin_map)) {
                printk(KERN_DEBUG "skipping cpu%d, didn't come online\n", cpu);
-               local_irq_enable();
-               return -EIO;
+               ret = -EIO;
+               goto fail;
        }
 
-       local_irq_enable();
-       /*per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;*/
        /* Unleash the CPU! */
        cpu_set(cpu, smp_commenced_mask);
        while (!cpu_isset(cpu, cpu_online_map)) {
@@ -1561,9 +1572,15 @@ int __devinit __cpu_up(unsigned int cpu)
                process_pending_softirqs();
        }
 
-       cpupool_cpu_add(cpu);
-       cpufreq_add_cpu(cpu);
+       notifier_rc = cpu_notifier_call_chain(CPU_ONLINE, hcpu);
+       BUG_ON(notifier_rc != NOTIFY_DONE);
        return 0;
+
+ fail:
+       notifier_rc = __cpu_notifier_call_chain(
+               CPU_UP_CANCELED, hcpu, nr_calls, NULL);
+       BUG_ON(notifier_rc != NOTIFY_DONE);
+       return ret;
 }
 
 
index 20f9f2dca4f9390836296e5be4157ca3aa15c642..31ac018e71069af82b5ab289d9fb75a6c0a5b77c 100644 (file)
@@ -89,6 +89,8 @@ SECTIONS
   } :text
   .initcall.init : {
        __initcall_start = .;
+       *(.initcallpresmp.init)
+       __presmp_initcall_end = .;
        *(.initcall1.init)
        __initcall_end = .;
   } :text
index 96cba72e9e9439c2b47e64d8b223c40c386f44ac..8a04dd449ea206ba3fe008511de2b2ffc73ee090 100644 (file)
@@ -1,5 +1,6 @@
 #include <xen/config.h>
 #include <xen/cpumask.h>
+#include <xen/cpu.h>
 
 /*
  * cpu_bit_bitmap[] is a special, "compressed" data structure that
@@ -24,3 +25,36 @@ const unsigned long cpu_bit_bitmap[BITS_PER_LONG+1][BITS_TO_LONGS(NR_CPUS)] = {
     MASK_DECLARE_8(48), MASK_DECLARE_8(56),
 #endif
 };
+
+DEFINE_SPINLOCK(cpu_add_remove_lock);
+
+static RAW_NOTIFIER_HEAD(cpu_chain);
+
+int register_cpu_notifier(struct notifier_block *nb)
+{
+    int ret;
+    spin_lock(&cpu_add_remove_lock);
+    ret = raw_notifier_chain_register(&cpu_chain, nb);
+    spin_unlock(&cpu_add_remove_lock);
+    return ret;
+}
+
+void unregister_cpu_notifier(struct notifier_block *nb)
+{
+    spin_lock(&cpu_add_remove_lock);
+    raw_notifier_chain_unregister(&cpu_chain, nb);
+    spin_unlock(&cpu_add_remove_lock);
+}
+
+int cpu_notifier_call_chain(unsigned long val, void *v)
+{
+    BUG_ON(!spin_is_locked(&cpu_add_remove_lock));
+    return raw_notifier_call_chain(&cpu_chain, val, v);
+}
+
+int __cpu_notifier_call_chain(
+    unsigned long val, void *v, int nr_to_call, int *nr_calls)
+{
+    BUG_ON(!spin_is_locked(&cpu_add_remove_lock));
+    return __raw_notifier_call_chain(&cpu_chain, val, v, nr_to_call, nr_calls);
+}
index 8c049c183059d9d4dca551d6166c35b646753a73..e8301f466cd08d96f3d2fe77e1af75d12341bc0e 100644 (file)
@@ -17,6 +17,7 @@
 #include <xen/percpu.h>
 #include <xen/sched.h>
 #include <xen/sched-if.h>
+#include <xen/cpu.h>
 
 #define for_each_cpupool(ptr)    \
     for ((ptr) = &cpupool_list; *(ptr) != NULL; (ptr) = &((*(ptr))->next))
@@ -178,10 +179,8 @@ static int cpupool_assign_cpu_locked(struct cpupool *c, unsigned int cpu)
  */
 int cpupool_assign_ncpu(struct cpupool *c, int ncpu)
 {
-    int i;
-    int n;
+    int i, n = 0;
 
-    n = 0;
     spin_lock(&cpupool_lock);
     for_each_cpu_mask(i, cpupool_free_cpus)
     {
@@ -293,21 +292,6 @@ out:
     return ret;
 }
 
-/*
- * assign cpus to the default cpupool
- * default are all cpus, less cpus may be specified as boot parameter
- * possible failures:
- * - no cpu assigned
- */
-int __init cpupool0_cpu_assign(struct cpupool *c)
-{
-    if ( (cpupool0_max_cpus == 0) || (cpupool0_max_cpus > num_online_cpus()) )
-        cpupool0_max_cpus = num_online_cpus();
-    if ( !cpupool_assign_ncpu(cpupool0, cpupool0_max_cpus) )
-        return 1;
-    return 0;
-}
-
 /*
  * add a new domain to a cpupool
  * possible failures:
@@ -363,16 +347,14 @@ void cpupool_rm_domain(struct domain *d)
  * called to add a new cpu to pool admin
  * we add a hotplugged cpu to the cpupool0 to be able to add it to dom0
  */
-void cpupool_cpu_add(unsigned int cpu)
+static void cpupool_cpu_add(unsigned int cpu)
 {
-    if ( cpupool0 == NULL )
-        return;
     spin_lock(&cpupool_lock);
     cpu_clear(cpu, cpupool_locked_cpus);
     cpu_set(cpu, cpupool_free_cpus);
-    cpupool_assign_cpu_locked(cpupool0, cpu);
+    if ( cpupool0 != NULL )
+        cpupool_assign_cpu_locked(cpupool0, cpu);
     spin_unlock(&cpupool_lock);
-    return;
 }
 
 /*
@@ -380,7 +362,7 @@ void cpupool_cpu_add(unsigned int cpu)
  * the cpu to be removed is locked to avoid removing it from dom0
  * returns failure if not in pool0
  */
-int cpupool_cpu_remove(unsigned int cpu)
+static int cpupool_cpu_remove(unsigned int cpu)
 {
     int ret = 0;
        
@@ -588,10 +570,52 @@ void dump_runq(unsigned char key)
     spin_unlock(&cpupool_lock);
 }
 
+static int cpu_callback(
+    struct notifier_block *nfb, unsigned long action, void *hcpu)
+{
+    unsigned int cpu = (unsigned long)hcpu;
+    int rc = 0;
+
+    switch ( action )
+    {
+    case CPU_DOWN_FAILED:
+    case CPU_ONLINE:
+        cpupool_cpu_add(cpu);
+        break;
+    case CPU_DOWN_PREPARE:
+        rc = cpupool_cpu_remove(cpu);
+        break;
+    default:
+        break;
+    }
+
+    return !rc ? NOTIFY_DONE : notifier_from_errno(rc);
+}
+
+static struct notifier_block cpu_nfb = {
+    .notifier_call = cpu_callback
+};
+
+static int __init cpupool_presmp_init(void)
+{
+    void *cpu = (void *)(long)smp_processor_id();
+    cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
+    register_cpu_notifier(&cpu_nfb);
+    return 0;
+}
+presmp_initcall(cpupool_presmp_init);
+
 static int __init cpupool_init(void)
 {
-    cpupool_free_cpus = cpu_online_map;
-    cpupool_list = NULL;
+    cpupool0 = cpupool_create(0, NULL);
+    BUG_ON(cpupool0 == NULL);
+
+    if ( (cpupool0_max_cpus == 0) || (cpupool0_max_cpus > num_online_cpus()) )
+        cpupool0_max_cpus = num_online_cpus();
+
+    if ( !cpupool_assign_ncpu(cpupool0, cpupool0_max_cpus) )
+        BUG();
+
     return 0;
 }
 __initcall(cpupool_init);
index cf03139d7f14555f4b6bab9ad853d961ffae7acc..51129206bfb8f09b285be5cd266571dbbe32adf3 100644 (file)
@@ -44,6 +44,7 @@
 #include <xen/console.h>
 #include <xen/errno.h>
 #include <xen/delay.h>
+#include <xen/init.h>
 #include <asm/byteorder.h>
 
 /* Printk isn't particularly safe just after we've trapped to the
@@ -639,23 +640,25 @@ __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie)
     return rc;
 }
 
-void __init
-initialise_gdb(void)
+static int __init initialise_gdb(void)
 {
     if ( *opt_gdb == '\0' )
-        return;
+        return 0;
 
     gdb_ctx->serhnd = serial_parse_handle(opt_gdb);
     if ( gdb_ctx->serhnd == -1 )
     {
         printk("Bad gdb= option '%s'\n", opt_gdb);
-        return;
+        return 0;
     }
 
     serial_start_sync(gdb_ctx->serhnd);
 
     printk("GDB stub initialised.\n");
+
+    return 0;
 }
+presmp_initcall(initialise_gdb);
 
 static void gdb_pause_this_cpu(void *unused)
 {
index 3a0c40fce4a190d2e4af4f4488df07fecdc4b10a..61a798df4ea4c7a725d2939c6093e487e014d039 100644 (file)
@@ -147,6 +147,22 @@ void add_taint(unsigned flag)
     tainted |= flag;
 }
 
+extern initcall_t __initcall_start, __presmp_initcall_end, __initcall_end;
+
+void __init do_presmp_initcalls(void)
+{
+    initcall_t *call;
+    for ( call = &__initcall_start; call < &__presmp_initcall_end; call++ )
+        (*call)();
+}
+
+void __init do_initcalls(void)
+{
+    initcall_t *call;
+    for ( call = &__presmp_initcall_end; call < &__initcall_end; call++ )
+        (*call)();
+}
+
 # define DO(fn) long do_##fn
 
 #endif
index 320bca0b5836c01a90b7b48aee1fe2aff5985375..fe1c507a7a3bab198a1a2a7317c0a070fb945e54 100644 (file)
@@ -65,6 +65,9 @@ static int notifier_call_chain(
     int ret = NOTIFY_DONE;
     struct notifier_block *nb, *next_nb;
 
+    if ( nr_calls )
+        *nr_calls = 0;
+
     nb = rcu_dereference(*nl);
 
     while ( nb && nr_to_call )
index 676da1efe59a55e903bb451102de98aa9a483854..31c5f6f39b275af76fc000ec38bea9012685596a 100644 (file)
@@ -43,6 +43,7 @@
 #include <xen/bitops.h>
 #include <xen/percpu.h>
 #include <xen/softirq.h>
+#include <xen/cpu.h>
 
 /* Definition for rcupdate control block. */
 struct rcu_ctrlblk rcu_ctrlblk = {
@@ -334,15 +335,33 @@ static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp,
     rdp->blimit = blimit;
 }
 
-void __devinit rcu_online_cpu(int cpu)
+static int cpu_callback(
+    struct notifier_block *nfb, unsigned long action, void *hcpu)
 {
-    struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
+    unsigned int cpu = (unsigned long)hcpu;
+
+    switch ( action )
+    {
+    case CPU_UP_PREPARE: {
+        struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
+        rcu_init_percpu_data(cpu, &rcu_ctrlblk, rdp);
+        break;
+    }
+    default:
+        break;
+    }
 
-    rcu_init_percpu_data(cpu, &rcu_ctrlblk, rdp);
+    return NOTIFY_DONE;
 }
 
+static struct notifier_block cpu_nfb = {
+    .notifier_call = cpu_callback
+};
+
 void __init rcu_init(void)
 {
-    rcu_online_cpu(smp_processor_id());
+    void *cpu = (void *)(long)smp_processor_id();
+    cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
+    register_cpu_notifier(&cpu_nfb);
     open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
 }
index 7a6717e55bde602eefbf5bb85f9f3a98d533d101..f9b889d717c10be18e082ad11971d559bc0626f1 100644 (file)
 #include <xen/sched.h>
 #include <xen/softirq.h>
 #include <xen/tasklet.h>
+#include <xen/cpu.h>
 
 /* Some subsystems call into us before we are initialised. We ignore them. */
-static bool_t tasklets_initialised;
+static cpumask_t tasklets_initialised;
 
 DEFINE_PER_CPU(unsigned long, tasklet_work_to_do);
 
@@ -43,7 +44,7 @@ void tasklet_schedule_on_cpu(struct tasklet *t, unsigned int cpu)
 
     spin_lock_irqsave(&tasklet_lock, flags);
 
-    if ( tasklets_initialised && !t->is_dead )
+    if ( cpu_isset(cpu, tasklets_initialised) && !t->is_dead )
     {
         t->scheduled_on = cpu;
         if ( !t->is_running )
@@ -135,7 +136,7 @@ void tasklet_kill(struct tasklet *t)
     spin_unlock_irqrestore(&tasklet_lock, flags);
 }
 
-void migrate_tasklets_from_cpu(unsigned int cpu)
+static void migrate_tasklets_from_cpu(unsigned int cpu)
 {
     struct list_head *list = &per_cpu(tasklet_list, cpu);
     unsigned long flags;
@@ -165,14 +166,36 @@ void tasklet_init(
     t->data = data;
 }
 
-void __init tasklet_subsys_init(void)
+static int cpu_callback(
+    struct notifier_block *nfb, unsigned long action, void *hcpu)
 {
-    unsigned int cpu;
+    unsigned int cpu = (unsigned long)hcpu;
+
+    switch ( action )
+    {
+    case CPU_UP_PREPARE:
+        if ( !cpu_test_and_set(cpu, tasklets_initialised) )
+            INIT_LIST_HEAD(&per_cpu(tasklet_list, cpu));
+        break;
+    case CPU_DEAD:
+        migrate_tasklets_from_cpu(cpu);
+        break;
+    default:
+        break;
+    }
 
-    for_each_possible_cpu ( cpu )
-        INIT_LIST_HEAD(&per_cpu(tasklet_list, cpu));
+    return NOTIFY_DONE;
+}
+
+static struct notifier_block cpu_nfb = {
+    .notifier_call = cpu_callback
+};
 
-    tasklets_initialised = 1;
+void __init tasklet_subsys_init(void)
+{
+    void *hcpu = (void *)(long)smp_processor_id();
+    cpu_callback(&cpu_nfb, CPU_UP_PREPARE, hcpu);
+    register_cpu_notifier(&cpu_nfb);
 }
 
 /*
index 627435d88c1146326badd27ceb189d1173c5a0ea..d81a9528159b6f769cf8011550695b7e4dae3a07 100644 (file)
@@ -38,6 +38,7 @@
 #include <xen/xmalloc.h>
 #include <xen/guest_access.h>
 #include <xen/domain.h>
+#include <xen/cpu.h>
 #include <asm/bug.h>
 #include <asm/io.h>
 #include <asm/config.h>
@@ -582,3 +583,38 @@ void __init cpufreq_cmdline_parse(char *str)
         str = end;
     } while (str);
 }
+
+static int cpu_callback(
+    struct notifier_block *nfb, unsigned long action, void *hcpu)
+{
+    unsigned int cpu = (unsigned long)hcpu;
+
+    switch ( action )
+    {
+    case CPU_DOWN_FAILED:
+    case CPU_ONLINE:
+        (void)cpufreq_add_cpu(cpu);
+        break;
+    case CPU_DOWN_PREPARE:
+        (void)cpufreq_del_cpu(cpu);
+        break;
+    default:
+        break;
+    }
+
+    return NOTIFY_DONE;
+}
+
+static struct notifier_block cpu_nfb = {
+    .notifier_call = cpu_callback
+};
+
+static int __init cpufreq_presmp_init(void)
+{
+    void *cpu = (void *)(long)smp_processor_id();
+    cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
+    register_cpu_notifier(&cpu_nfb);
+    return 0;
+}
+presmp_initcall(cpufreq_presmp_init);
+
index 58a27e738f32dbe5965d60229f800c86c91b2513..e5d3fdbab651b1b80daf7a2a518fd977e2bea8b3 100644 (file)
@@ -295,12 +295,6 @@ uint8_t hvm_combine_hw_exceptions(uint8_t vec1, uint8_t vec2);
 
 void hvm_set_rdtsc_exiting(struct domain *d, bool_t enable);
 
-static inline int
-hvm_cpu_prepare(unsigned int cpu)
-{
-    return (hvm_funcs.cpu_prepare ? hvm_funcs.cpu_prepare(cpu) : 0);
-}
-
 static inline int hvm_cpu_up(void)
 {
     return (hvm_funcs.cpu_up ? hvm_funcs.cpu_up() : 1);
index a17eb93c42c4ad30eba54b0aa3363643ea88efbc..03791206aaa40f7f1b04cd15dd7f6d4646ddfdf0 100644 (file)
@@ -551,8 +551,6 @@ extern void mtrr_bp_init(void);
 
 void mcheck_init(struct cpuinfo_x86 *c);
 asmlinkage void do_machine_check(struct cpu_user_regs *regs);
-void cpu_mcheck_distribute_cmci(void);
-void cpu_mcheck_disable(void);
 
 int cpuid_hypervisor_leaves( uint32_t idx, uint32_t sub_idx,
           uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
index 6f5200dbedcee0e54e287d71cec5ffa5df8e85c9..d67165493af274490620ea8cc759bdf376697a41 100644 (file)
@@ -53,10 +53,7 @@ extern u32 cpu_2_logical_apicid[];
 #define cpu_physical_id(cpu)   x86_cpu_to_apicid[cpu]
 
 /* State of each CPU. */
-#define CPU_ONLINE     0x0002  /* CPU is up */
-#define CPU_DEAD       0x0004  /* CPU is dead */
 DECLARE_PER_CPU(int, cpu_state);
-extern spinlock_t(cpu_add_remove_lock);
 
 #define cpu_is_offline(cpu) unlikely(!cpu_online(cpu))
 extern int cpu_down(unsigned int cpu);
diff --git a/xen/include/xen/cpu.h b/xen/include/xen/cpu.h
new file mode 100644 (file)
index 0000000..521559e
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef __XEN_CPU_H__
+#define __XEN_CPU_H__
+
+#include <xen/types.h>
+#include <xen/spinlock.h>
+#include <xen/notifier.h>
+
+extern spinlock_t cpu_add_remove_lock;
+
+int register_cpu_notifier(struct notifier_block *nb);
+void unregister_cpu_notifier(struct notifier_block *nb);
+int cpu_notifier_call_chain(unsigned long val, void *v);
+int __cpu_notifier_call_chain(
+    unsigned long val, void *v, int nr_to_call, int *nr_calls);
+
+/*
+ * Notification actions: note that only CPU_{UP,DOWN}_PREPARE may fail ---
+ * all other handlers *must* return NOTIFY_DONE.
+ */
+#define CPU_UP_PREPARE   0x0002 /* CPU is coming up */
+#define CPU_UP_CANCELED  0x0003 /* CPU is no longer coming up */
+#define CPU_ONLINE       0x0004 /* CPU is up */
+#define CPU_DOWN_PREPARE 0x0005 /* CPU is going down */
+#define CPU_DOWN_FAILED  0x0006 /* CPU is no longer going down */
+#define CPU_DYING        0x0007 /* CPU is nearly dead (in stop_machine ctxt) */
+#define CPU_DEAD         0x0008 /* CPU is dead */
+
+#endif /* __XEN_CPU_H__ */
index e9f0cd5a27896d96fa7946caf9a4a44a5ca6aac8..7ff9dd80a0d4e275db54e0d43fdad24f2ce32f7e 100644 (file)
@@ -88,12 +88,6 @@ void gdb_arch_exit(struct cpu_user_regs *regs);
 #define SIGALRM         14
 #define SIGTERM         15
 
-void initialise_gdb(void);
-
-#else
-
-#define initialise_gdb() ((void)0)
-
 #endif
 
 #endif /* __XEN_GDBSTUB_H__ */
index fdfdb55835ce6d9b5d3212ac1a1940abd54b19d7..220d464fc7343135f8f498a5b719a9e98dac4f8a 100644 (file)
@@ -18,8 +18,8 @@
     __attribute_used__ __attribute__ ((__section__ (".exit.data")))
 #define __initsetup  \
     __attribute_used__ __attribute__ ((__section__ (".init.setup")))
-#define __init_call  \
-    __attribute_used__ __attribute__ ((__section__ (".initcall1.init")))
+#define __init_call(lvl)  \
+    __attribute_used__ __attribute__ ((__section__ (".initcall" lvl ".init")))
 #define __exit_call  \
     __attribute_used__ __attribute__ ((__section__ (".exitcall.exit")))
 
 typedef int (*initcall_t)(void);
 typedef void (*exitcall_t)(void);
 
-extern initcall_t __initcall_start, __initcall_end;
-
+#define presmp_initcall(fn) \
+    static initcall_t __initcall_##fn __init_call("presmp") = fn
 #define __initcall(fn) \
-    static initcall_t __initcall_##fn __init_call = fn
+    static initcall_t __initcall_##fn __init_call("1") = fn
 #define __exitcall(fn) \
     static exitcall_t __exitcall_##fn __exit_call = fn
 
+void do_presmp_initcalls(void);
+void do_initcalls(void);
+
 /*
  * Used for kernel command line parameter setup
  */
index 84ec50f92bcee4e4559fd617bc5015d91d1304d1..a8276538492a3832e1cdc495009a86e5faca108d 100644 (file)
@@ -52,38 +52,21 @@ int __raw_notifier_call_chain(
     struct raw_notifier_head *nh, unsigned long val, void *v,
     int nr_to_call, int *nr_calls);
 
-#define NOTIFY_DONE  0x0000  /* Don't care */
-#define NOTIFY_OK  0x0001  /* Suits me */
-#define NOTIFY_STOP_MASK 0x8000  /* Don't call further */
-#define NOTIFY_BAD  (NOTIFY_STOP_MASK|0x0002)
-/* Bad/Veto action */
-/*
- * Clean way to return from the notifier and stop further calls.
- */
-#define NOTIFY_STOP  (NOTIFY_OK|NOTIFY_STOP_MASK)
+#define NOTIFY_DONE      0x0000
+#define NOTIFY_STOP_MASK 0x8000
+#define NOTIFY_STOP      (NOTIFY_STOP_MASK|NOTIFY_DONE)
+#define NOTIFY_BAD       (NOTIFY_STOP_MASK|EINVAL)
 
-/* Encapsulate (negative) errno value (in particular, NOTIFY_BAD <=> EPERM). */
+/* Encapsulate (negative) errno value. */
 static inline int notifier_from_errno(int err)
 {
-    return NOTIFY_STOP_MASK | (NOTIFY_OK - err);
+    return NOTIFY_STOP_MASK | -err;
 }
 
 /* Restore (negative) errno value from notify return value. */
 static inline int notifier_to_errno(int ret)
 {
-    ret &= ~NOTIFY_STOP_MASK;
-    return ret > NOTIFY_OK ? NOTIFY_OK - ret : 0;
+    return -(ret & ~NOTIFY_STOP_MASK);
 }
 
-#define CPU_ONLINE  0x0002 /* CPU (unsigned)v is up */
-#define CPU_UP_PREPARE  0x0003 /* CPU (unsigned)v coming up */
-#define CPU_UP_CANCELED  0x0004 /* CPU (unsigned)v NOT coming up */
-#define CPU_DOWN_PREPARE 0x0005 /* CPU (unsigned)v going down */
-#define CPU_DOWN_FAILED  0x0006 /* CPU (unsigned)v NOT going down */
-#define CPU_DEAD  0x0007 /* CPU (unsigned)v dead */
-#define CPU_DYING  0x0008 /* CPU (unsigned)v not running any task,
-                           * not handling interrupts, soon dead */
-#define CPU_POST_DEAD  0x0009 /* CPU (unsigned)v dead, cpu_hotplug
-                               * lock is dropped */
-
 #endif /* __XEN_NOTIFIER_H__ */
index 587a32e2b760e5bb0ff78e7f940545302298e688..285e574e28d6a30b54b90b9c3b9d1b627d727da6 100644 (file)
@@ -190,7 +190,6 @@ typedef struct _rcu_read_lock rcu_read_lock_t;
 #define rcu_assign_pointer(p, v) ({ smp_wmb(); (p) = (v); })
 
 void rcu_init(void);
-void __devinit rcu_online_cpu(int cpu);
 void rcu_check_callbacks(int cpu);
 
 /* Exported interfaces */
index 4bcc7f1bf2352abf1c11bfcd02df547fbb4761bb..a8e086521a4d0599f8039abda989e7b90b5f54bc 100644 (file)
@@ -622,10 +622,7 @@ extern enum cpufreq_controller {
 
 struct cpupool *cpupool_create(int poolid, char *sched);
 int cpupool_destroy(struct cpupool *c);
-int cpupool0_cpu_assign(struct cpupool *c);
 int cpupool_assign_ncpu(struct cpupool *c, int ncpu);
-void cpupool_cpu_add(unsigned int cpu);
-int cpupool_cpu_remove(unsigned int cpu);
 int cpupool_add_domain(struct domain *d, int poolid);
 void cpupool_rm_domain(struct domain *d);
 int cpupool_do_sysctl(struct xen_sysctl_cpupool_op *op);
index d324fb39c12a3bfd103e34e01f7f92abdfc840d4..e8d6e96b0fd45f5ac75222169a7918d7ec9e76fe 100644 (file)
@@ -35,7 +35,6 @@ void tasklet_schedule_on_cpu(struct tasklet *t, unsigned int cpu);
 void tasklet_schedule(struct tasklet *t);
 void do_tasklet(void);
 void tasklet_kill(struct tasklet *t);
-void migrate_tasklets_from_cpu(unsigned int cpu);
 void tasklet_init(
     struct tasklet *t, void (*func)(unsigned long), unsigned long data);
 void tasklet_subsys_init(void);