x86/smp: Don't ever patch back to UP if we unplug cpus
[pandora-kernel.git] / arch / x86 / xen / smp.c
index 041d4fe..a8991d4 100644 (file)
@@ -172,6 +172,7 @@ static void __init xen_fill_possible_map(void)
 static void __init xen_filter_cpu_maps(void)
 {
        int i, rc;
+       unsigned int subtract = 0;
 
        if (!xen_initial_domain())
                return;
@@ -186,8 +187,22 @@ static void __init xen_filter_cpu_maps(void)
                } else {
                        set_cpu_possible(i, false);
                        set_cpu_present(i, false);
+                       subtract++;
                }
        }
+#ifdef CONFIG_HOTPLUG_CPU
+       /* This is akin to using 'nr_cpus' on the Linux command line.
+        * Which is OK as when we use 'dom0_max_vcpus=X' we can only
+        * have up to X, while nr_cpu_ids is greater than X. This
+        * normally is not a problem, except when CPU hotplugging
+        * is involved and then there might be more than X CPUs
+        * in the guest - which will not work as there is no
+        * hypercall to expand the max number of VCPUs an already
+        * running guest has. So cap it up to X. */
+       if (subtract)
+               nr_cpu_ids = nr_cpu_ids - subtract;
+#endif
+
 }
 
 static void __init xen_smp_prepare_boot_cpu(void)
@@ -353,7 +368,8 @@ static int __cpuinit xen_cpu_up(unsigned int cpu)
                return rc;
 
        if (num_online_cpus() == 1)
-               alternatives_smp_switch(1);
+               /* Just in case we booted with a single CPU. */
+               alternatives_enable_smp();
 
        rc = xen_smp_intr_init(cpu);
        if (rc)
@@ -399,9 +415,6 @@ static void xen_cpu_die(unsigned int cpu)
        unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), NULL);
        xen_uninit_lock_cpu(cpu);
        xen_teardown_timer(cpu);
-
-       if (num_online_cpus() == 1)
-               alternatives_smp_switch(0);
 }
 
 static void __cpuinit xen_play_dead(void) /* used only with HOTPLUG_CPU */
@@ -548,6 +561,8 @@ static void xen_hvm_cpu_die(unsigned int cpu)
        unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL);
        unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL);
        unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), NULL);
+       xen_uninit_lock_cpu(cpu);
+       xen_teardown_timer(cpu);
        native_cpu_die(cpu);
 }