[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Make xm save/restore work for SMP guest domains.
# HG changeset patch # User sos22@xxxxxxxxxxxxxxxxxxxx # Node ID 6e6cedc1763db80ac68fefbe6062594416c75aa1 # Parent 69f00d6ab5dcdfb440482315715522ee85e86f84 Make xm save/restore work for SMP guest domains. Signed-off-by: Steven Smith, sos22@xxxxxxxxx diff -r 69f00d6ab5dc -r 6e6cedc1763d linux-2.6-xen-sparse/arch/xen/kernel/reboot.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Wed Aug 17 13:34:42 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Wed Aug 17 14:37:22 2005 @@ -16,6 +16,8 @@ #include <asm-xen/queues.h> #include <asm-xen/xenbus.h> #include <asm-xen/ctrl_if.h> +#include <linux/cpu.h> +#include <linux/kthread.h> #define SHUTDOWN_INVALID -1 #define SHUTDOWN_POWEROFF 0 @@ -58,7 +60,12 @@ /* Ignore multiple shutdown requests. */ static int shutting_down = SHUTDOWN_INVALID; -static void __do_suspend(void) +#ifndef CONFIG_HOTPLUG_CPU +#define cpu_down(x) (-EOPNOTSUPP) +#define cpu_up(x) (-EOPNOTSUPP) +#endif + +static int __do_suspend(void *ignore) { int i, j; suspend_record_t *suspend_record; @@ -104,10 +111,49 @@ extern unsigned long max_pfn; extern unsigned int *pfn_to_mfn_frame_list; + cpumask_t feasible_cpus; + int err = 0; + + BUG_ON(smp_processor_id() != 0); + BUG_ON(in_interrupt()); + +#if defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU) + if (num_online_cpus() > 1) { + printk(KERN_WARNING "Can't suspend SMP guests without CONFIG_HOTPLUG_CPU\n"); + return -EOPNOTSUPP; + } +#endif + suspend_record = (suspend_record_t *)__get_free_page(GFP_KERNEL); if ( suspend_record == NULL ) goto out; + /* Take all of the other cpus offline. We need to be careful not + to get preempted between the final test for num_online_cpus() + == 1 and disabling interrupts, since otherwise userspace could + bring another cpu online, and then we'd be stuffed. At the + same time, cpu_down can reschedule, so we need to enable + preemption while doing that. This kind of sucks, but should be + correct. */ + /* (We don't need to worry about other cpus bringing stuff up, + since by the time num_online_cpus() == 1, there aren't any + other cpus) */ + cpus_clear(feasible_cpus); + preempt_disable(); + while (num_online_cpus() > 1) { + preempt_enable(); + for_each_online_cpu(i) { + if (i == 0) + continue; + err = cpu_down(i); + if (err != 0) { + printk(KERN_CRIT "Failed to take all CPUs down: %d.\n", err); + goto out_reenable_cpus; + } + cpu_set(i, feasible_cpus); + } + } + suspend_record->nr_pfns = max_pfn; /* final number of pfns */ __cli(); @@ -141,7 +187,10 @@ memcpy(&suspend_record->resume_info, &xen_start_info, sizeof(xen_start_info)); + /* We'll stop somewhere inside this hypercall. When it returns, + we'll start resuming after the restore. */ HYPERVISOR_suspend(virt_to_machine(suspend_record) >> PAGE_SHIFT); + shutting_down = SHUTDOWN_INVALID; @@ -182,11 +231,26 @@ usbif_resume(); + preempt_enable(); + __sti(); + + out_reenable_cpus: + while (!cpus_empty(feasible_cpus)) { + i = first_cpu(feasible_cpus); + j = cpu_up(i); + if (j != 0) { + printk(KERN_CRIT "Failed to bring cpu %d back up (%d).\n", + i, j); + err = j; + } + cpu_clear(i, feasible_cpus); + } out: if ( suspend_record != NULL ) free_page((unsigned long)suspend_record); + return err; } static int shutdown_process(void *__unused) @@ -233,6 +297,18 @@ return 0; } +static struct task_struct *kthread_create_on_cpu(int (*f)(void *arg), + void *arg, + const char *name, + int cpu) +{ + struct task_struct *p; + p = kthread_create(f, arg, name); + kthread_bind(p, cpu); + wake_up_process(p); + return p; +} + static void __shutdown_handler(void *unused) { int err; @@ -245,7 +321,7 @@ } else { - __do_suspend(); + kthread_create_on_cpu(__do_suspend, NULL, "suspender", 0); } } _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |