diff options
author | Alex Nixon <alex.nixon@citrix.com> | 2008-08-22 06:52:15 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-08-25 05:25:14 -0400 |
commit | d68d82afd4c88e25763b23cd9cd4974573a3706f (patch) | |
tree | 42a3fb93a5cef70db7ad01fda1ed0dc68dbe6110 /arch/x86/xen/smp.c | |
parent | 8227dce7dc2cfdcc28ee0eadfb482a7ee77fba03 (diff) |
xen: implement CPU hotplugging
Note the changes from 2.6.18-xen CPU hotplugging:
A vcpu_down request from the remote admin via Xenbus both hotunplugs the
CPU, and disables it by removing it from the cpu_present map, and removing
its entry in /sys.
A vcpu_up request from the remote admin only re-enables the CPU, and does
not immediately bring the CPU up. A udev event is emitted, which can be
caught by the user if he wishes to automatically re-up CPUs when available,
or implement a more complex policy.
Signed-off-by: Alex Nixon <alex.nixon@citrix.com>
Acked-by: Jeremy Fitzhardinge <jeremy@goop.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/xen/smp.c')
-rw-r--r-- | arch/x86/xen/smp.c | 60 |
1 files changed, 48 insertions, 12 deletions
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index baca7f2fbd8a..be5cbb2b7c60 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c | |||
@@ -11,8 +11,6 @@ | |||
11 | * useful topology information for the kernel to make use of. As a | 11 | * useful topology information for the kernel to make use of. As a |
12 | * result, all CPUs are treated as if they're single-core and | 12 | * result, all CPUs are treated as if they're single-core and |
13 | * single-threaded. | 13 | * single-threaded. |
14 | * | ||
15 | * This does not handle HOTPLUG_CPU yet. | ||
16 | */ | 14 | */ |
17 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
18 | #include <linux/err.h> | 16 | #include <linux/err.h> |
@@ -61,11 +59,12 @@ static irqreturn_t xen_reschedule_interrupt(int irq, void *dev_id) | |||
61 | return IRQ_HANDLED; | 59 | return IRQ_HANDLED; |
62 | } | 60 | } |
63 | 61 | ||
64 | static __cpuinit void cpu_bringup_and_idle(void) | 62 | static __cpuinit void cpu_bringup(void) |
65 | { | 63 | { |
66 | int cpu = smp_processor_id(); | 64 | int cpu = smp_processor_id(); |
67 | 65 | ||
68 | cpu_init(); | 66 | cpu_init(); |
67 | touch_softlockup_watchdog(); | ||
69 | preempt_disable(); | 68 | preempt_disable(); |
70 | 69 | ||
71 | xen_enable_sysenter(); | 70 | xen_enable_sysenter(); |
@@ -86,6 +85,11 @@ static __cpuinit void cpu_bringup_and_idle(void) | |||
86 | local_irq_enable(); | 85 | local_irq_enable(); |
87 | 86 | ||
88 | wmb(); /* make sure everything is out */ | 87 | wmb(); /* make sure everything is out */ |
88 | } | ||
89 | |||
90 | static __cpuinit void cpu_bringup_and_idle(void) | ||
91 | { | ||
92 | cpu_bringup(); | ||
89 | cpu_idle(); | 93 | cpu_idle(); |
90 | } | 94 | } |
91 | 95 | ||
@@ -209,8 +213,6 @@ static void __init xen_smp_prepare_cpus(unsigned int max_cpus) | |||
209 | 213 | ||
210 | cpu_set(cpu, cpu_present_map); | 214 | cpu_set(cpu, cpu_present_map); |
211 | } | 215 | } |
212 | |||
213 | //init_xenbus_allowed_cpumask(); | ||
214 | } | 216 | } |
215 | 217 | ||
216 | static __cpuinit int | 218 | static __cpuinit int |
@@ -278,12 +280,6 @@ static int __cpuinit xen_cpu_up(unsigned int cpu) | |||
278 | struct task_struct *idle = idle_task(cpu); | 280 | struct task_struct *idle = idle_task(cpu); |
279 | int rc; | 281 | int rc; |
280 | 282 | ||
281 | #if 0 | ||
282 | rc = cpu_up_check(cpu); | ||
283 | if (rc) | ||
284 | return rc; | ||
285 | #endif | ||
286 | |||
287 | #ifdef CONFIG_X86_64 | 283 | #ifdef CONFIG_X86_64 |
288 | /* Allocate node local memory for AP pdas */ | 284 | /* Allocate node local memory for AP pdas */ |
289 | WARN_ON(cpu == 0); | 285 | WARN_ON(cpu == 0); |
@@ -336,6 +332,42 @@ static void xen_smp_cpus_done(unsigned int max_cpus) | |||
336 | { | 332 | { |
337 | } | 333 | } |
338 | 334 | ||
335 | int xen_cpu_disable(void) | ||
336 | { | ||
337 | unsigned int cpu = smp_processor_id(); | ||
338 | if (cpu == 0) | ||
339 | return -EBUSY; | ||
340 | |||
341 | cpu_disable_common(); | ||
342 | |||
343 | load_cr3(swapper_pg_dir); | ||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | void xen_cpu_die(unsigned int cpu) | ||
348 | { | ||
349 | while (HYPERVISOR_vcpu_op(VCPUOP_is_up, cpu, NULL)) { | ||
350 | current->state = TASK_UNINTERRUPTIBLE; | ||
351 | schedule_timeout(HZ/10); | ||
352 | } | ||
353 | unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL); | ||
354 | unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL); | ||
355 | unbind_from_irqhandler(per_cpu(debug_irq, cpu), NULL); | ||
356 | unbind_from_irqhandler(per_cpu(callfuncsingle_irq, cpu), NULL); | ||
357 | xen_uninit_lock_cpu(cpu); | ||
358 | xen_teardown_timer(cpu); | ||
359 | |||
360 | if (num_online_cpus() == 1) | ||
361 | alternatives_smp_switch(0); | ||
362 | } | ||
363 | |||
364 | void xen_play_dead(void) | ||
365 | { | ||
366 | play_dead_common(); | ||
367 | HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL); | ||
368 | cpu_bringup(); | ||
369 | } | ||
370 | |||
339 | static void stop_self(void *v) | 371 | static void stop_self(void *v) |
340 | { | 372 | { |
341 | int cpu = smp_processor_id(); | 373 | int cpu = smp_processor_id(); |
@@ -419,9 +451,13 @@ static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id) | |||
419 | static const struct smp_ops xen_smp_ops __initdata = { | 451 | static const struct smp_ops xen_smp_ops __initdata = { |
420 | .smp_prepare_boot_cpu = xen_smp_prepare_boot_cpu, | 452 | .smp_prepare_boot_cpu = xen_smp_prepare_boot_cpu, |
421 | .smp_prepare_cpus = xen_smp_prepare_cpus, | 453 | .smp_prepare_cpus = xen_smp_prepare_cpus, |
422 | .cpu_up = xen_cpu_up, | ||
423 | .smp_cpus_done = xen_smp_cpus_done, | 454 | .smp_cpus_done = xen_smp_cpus_done, |
424 | 455 | ||
456 | .cpu_up = xen_cpu_up, | ||
457 | .cpu_die = xen_cpu_die, | ||
458 | .cpu_disable = xen_cpu_disable, | ||
459 | .play_dead = xen_play_dead, | ||
460 | |||
425 | .smp_send_stop = xen_smp_send_stop, | 461 | .smp_send_stop = xen_smp_send_stop, |
426 | .smp_send_reschedule = xen_smp_send_reschedule, | 462 | .smp_send_reschedule = xen_smp_send_reschedule, |
427 | 463 | ||