Mailing List Archive

Move Xen CPU hotplug code into new file cpu_hotplug.c.
# HG changeset patch
# User kaf24@firebug.cl.cam.ac.uk
# Node ID 606db2959bd6dc7fc178e9792f0ef345e48dd35e
# Parent 2d08d6db792b71be471689f5f2381920c441f1ec
Move Xen CPU hotplug code into new file cpu_hotplug.c.
Cleaner and allows use by architectures which aren't currently
using Xen's smpboot.c.

Based on an original patch by Tristan Gingold.

Signed-off-by: Keir Fraser <keir@xensource.com>
---
linux-2.6-xen-sparse/drivers/xen/core/Makefile | 11 -
linux-2.6-xen-sparse/drivers/xen/core/cpu_hotplug.c | 185 +++++++++++++++++
linux-2.6-xen-sparse/drivers/xen/core/reboot.c | 9
linux-2.6-xen-sparse/drivers/xen/core/smpboot.c | 215 +-------------------
linux-2.6-xen-sparse/include/xen/cpu_hotplug.h | 42 +++
5 files changed, 254 insertions(+), 208 deletions(-)

diff -r 2d08d6db792b -r 606db2959bd6 linux-2.6-xen-sparse/drivers/xen/core/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/core/Makefile Mon May 22 15:08:26 2006 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/core/Makefile Tue May 23 12:05:08 2006 +0100
@@ -4,8 +4,9 @@

obj-y := evtchn.o reboot.o gnttab.o features.o

-obj-$(CONFIG_PROC_FS) += xen_proc.o
-obj-$(CONFIG_NET) += skbuff.o
-obj-$(CONFIG_SMP) += smpboot.o
-obj-$(CONFIG_SYSFS) += hypervisor_sysfs.o
-obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o
+obj-$(CONFIG_PROC_FS) += xen_proc.o
+obj-$(CONFIG_NET) += skbuff.o
+obj-$(CONFIG_SMP) += smpboot.o
+obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o
+obj-$(CONFIG_SYSFS) += hypervisor_sysfs.o
+obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o
diff -r 2d08d6db792b -r 606db2959bd6 linux-2.6-xen-sparse/drivers/xen/core/reboot.c
--- a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c Mon May 22 15:08:26 2006 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c Tue May 23 12:05:08 2006 +0100
@@ -17,6 +17,7 @@
#include <linux/kthread.h>
#include <xen/gnttab.h>
#include <xen/xencons.h>
+#include <xen/cpu_hotplug.h>

#if defined(__i386__) || defined(__x86_64__)
/*
@@ -80,14 +81,6 @@ static int shutting_down = SHUTDOWN_INVA
static int shutting_down = SHUTDOWN_INVALID;
static void __shutdown_handler(void *unused);
static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
-
-#ifdef CONFIG_SMP
-int smp_suspend(void);
-void smp_resume(void);
-#else
-#define smp_suspend() (0)
-#define smp_resume() ((void)0)
-#endif

/* Ensure we run on the idle task page tables so that we will
switch page tables before running user space. This is needed
diff -r 2d08d6db792b -r 606db2959bd6 linux-2.6-xen-sparse/drivers/xen/core/smpboot.c
--- a/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c Mon May 22 15:08:26 2006 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c Tue May 23 12:05:08 2006 +0100
@@ -23,6 +23,7 @@
#include <asm/pgalloc.h>
#include <xen/evtchn.h>
#include <xen/interface/vcpu.h>
+#include <xen/cpu_hotplug.h>
#include <xen/xenbus.h>

#ifdef CONFIG_SMP_ALTERNATIVES
@@ -78,15 +79,6 @@ EXPORT_SYMBOL(x86_cpu_to_apicid);
#elif !defined(CONFIG_X86_IO_APIC)
unsigned int maxcpus = NR_CPUS;
#endif
-
-/*
- * Set of CPUs that remote admin software will allow us to bring online.
- * Notified to us via xenbus.
- */
-static cpumask_t xenbus_allowed_cpumask;
-
-/* Set of CPUs that local admin will allow us to bring online. */
-static cpumask_t local_allowed_cpumask = CPU_MASK_ALL;

void __init prefill_possible_map(void)
{
@@ -167,17 +159,17 @@ static void cpu_bringup(void)
cpu_idle();
}

-static void vcpu_prepare(int vcpu)
+void cpu_initialize_context(unsigned int cpu)
{
vcpu_guest_context_t ctxt;
- struct task_struct *idle = idle_task(vcpu);
+ struct task_struct *idle = idle_task(cpu);
#ifdef __x86_64__
- struct desc_ptr *gdt_descr = &cpu_gdt_descr[vcpu];
+ struct desc_ptr *gdt_descr = &cpu_gdt_descr[cpu];
#else
- struct Xgt_desc_struct *gdt_descr = &per_cpu(cpu_gdt_descr, vcpu);
-#endif
-
- if (vcpu == 0)
+ struct Xgt_desc_struct *gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
+#endif
+
+ if (cpu == 0)
return;

memset(&ctxt, 0, sizeof(ctxt));
@@ -226,10 +218,10 @@ static void vcpu_prepare(int vcpu)

ctxt.ctrlreg[3] = virt_to_mfn(init_level4_pgt) << PAGE_SHIFT;

- ctxt.gs_base_kernel = (unsigned long)(cpu_pda(vcpu));
-#endif
-
- BUG_ON(HYPERVISOR_vcpu_op(VCPUOP_initialise, vcpu, &ctxt));
+ ctxt.gs_base_kernel = (unsigned long)(cpu_pda(cpu));
+#endif
+
+ BUG_ON(HYPERVISOR_vcpu_op(VCPUOP_initialise, cpu, &ctxt));
}

void __init smp_prepare_cpus(unsigned int max_cpus)
@@ -304,10 +296,10 @@ void __init smp_prepare_cpus(unsigned in
cpu_set(cpu, cpu_present_map);
#endif

- vcpu_prepare(cpu);
- }
-
- xenbus_allowed_cpumask = cpu_present_map;
+ cpu_initialize_context(cpu);
+ }
+
+ init_xenbus_allowed_cpumask();

/* Currently, Xen gives no dynamic NUMA/HT info. */
for (cpu = 1; cpu < NR_CPUS; cpu++) {
@@ -332,15 +324,6 @@ void __devinit smp_prepare_boot_cpu(void
cpu_online_map = cpumask_of_cpu(0);
}

-static int local_cpu_hotplug_request(void)
-{
- /*
- * We assume a CPU hotplug request comes from local admin if it is made
- * via a userspace process (i.e., one with a real mm_struct).
- */
- return (current->mm != NULL);
-}
-
#ifdef CONFIG_HOTPLUG_CPU

/*
@@ -355,141 +338,6 @@ static int __init initialize_cpu_present
}
core_initcall(initialize_cpu_present_map);

-static void vcpu_hotplug(unsigned int cpu)
-{
- int err;
- char dir[32], state[32];
-
- if ((cpu >= NR_CPUS) || !cpu_possible(cpu))
- return;
-
- sprintf(dir, "cpu/%d", cpu);
- err = xenbus_scanf(XBT_NULL, dir, "availability", "%s", state);
- if (err != 1) {
- printk(KERN_ERR "XENBUS: Unable to read cpu state\n");
- return;
- }
-
- if (strcmp(state, "online") == 0) {
- cpu_set(cpu, xenbus_allowed_cpumask);
- (void)cpu_up(cpu);
- } else if (strcmp(state, "offline") == 0) {
- cpu_clear(cpu, xenbus_allowed_cpumask);
- (void)cpu_down(cpu);
- } else {
- printk(KERN_ERR "XENBUS: unknown state(%s) on CPU%d\n",
- state, cpu);
- }
-}
-
-static void handle_vcpu_hotplug_event(
- struct xenbus_watch *watch, const char **vec, unsigned int len)
-{
- int cpu;
- char *cpustr;
- const char *node = vec[XS_WATCH_PATH];
-
- if ((cpustr = strstr(node, "cpu/")) != NULL) {
- sscanf(cpustr, "cpu/%d", &cpu);
- vcpu_hotplug(cpu);
- }
-}
-
-static int smpboot_cpu_notify(struct notifier_block *notifier,
- unsigned long action, void *hcpu)
-{
- int cpu = (long)hcpu;
-
- /*
- * We do this in a callback notifier rather than __cpu_disable()
- * because local_cpu_hotplug_request() does not work in the latter
- * as it's always executed from within a stopmachine kthread.
- */
- if ((action == CPU_DOWN_PREPARE) && local_cpu_hotplug_request())
- cpu_clear(cpu, local_allowed_cpumask);
-
- return NOTIFY_OK;
-}
-
-static int setup_cpu_watcher(struct notifier_block *notifier,
- unsigned long event, void *data)
-{
- int i;
-
- static struct xenbus_watch cpu_watch = {
- .node = "cpu",
- .callback = handle_vcpu_hotplug_event,
- .flags = XBWF_new_thread };
- (void)register_xenbus_watch(&cpu_watch);
-
- if (!(xen_start_info->flags & SIF_INITDOMAIN)) {
- for_each_cpu(i)
- vcpu_hotplug(i);
- printk(KERN_INFO "Brought up %ld CPUs\n",
- (long)num_online_cpus());
- }
-
- return NOTIFY_DONE;
-}
-
-static int __init setup_vcpu_hotplug_event(void)
-{
- static struct notifier_block hotplug_cpu = {
- .notifier_call = smpboot_cpu_notify };
- static struct notifier_block xsn_cpu = {
- .notifier_call = setup_cpu_watcher };
-
- register_cpu_notifier(&hotplug_cpu);
- register_xenstore_notifier(&xsn_cpu);
-
- return 0;
-}
-
-arch_initcall(setup_vcpu_hotplug_event);
-
-int smp_suspend(void)
-{
- int i, err;
-
- lock_cpu_hotplug();
-
- /*
- * Take all other CPUs offline. We hold the hotplug mutex to
- * avoid other processes bringing up CPUs under our feet.
- */
- while (num_online_cpus() > 1) {
- unlock_cpu_hotplug();
- for_each_online_cpu(i) {
- if (i == 0)
- continue;
- err = cpu_down(i);
- if (err) {
- printk(KERN_CRIT "Failed to take all CPUs "
- "down: %d.\n", err);
- for_each_cpu(i)
- vcpu_hotplug(i);
- return err;
- }
- }
- lock_cpu_hotplug();
- }
-
- return 0;
-}
-
-void smp_resume(void)
-{
- int i;
-
- for_each_cpu(i)
- vcpu_prepare(i);
-
- unlock_cpu_hotplug();
-
- for_each_cpu(i)
- vcpu_hotplug(i);
-}
-
static void
remove_siblinginfo(int cpu)
{
@@ -536,20 +384,6 @@ void __cpu_die(unsigned int cpu)

#else /* !CONFIG_HOTPLUG_CPU */

-int smp_suspend(void)
-{
- if (num_online_cpus() > 1) {
- printk(KERN_WARNING "Can't suspend SMP guests "
- "without CONFIG_HOTPLUG_CPU\n");
- return -EOPNOTSUPP;
- }
- return 0;
-}
-
-void smp_resume(void)
-{
-}
-
int __cpu_disable(void)
{
return -ENOSYS;
@@ -566,17 +400,9 @@ int __devinit __cpu_up(unsigned int cpu)
{
int rc;

- if (local_cpu_hotplug_request()) {
- cpu_set(cpu, local_allowed_cpumask);
- if (!cpu_isset(cpu, xenbus_allowed_cpumask)) {
- printk("%s: attempt to bring up CPU %u disallowed by "
- "remote admin.\n", __FUNCTION__, cpu);
- return -EBUSY;
- }
- } else if (!cpu_isset(cpu, local_allowed_cpumask) ||
- !cpu_isset(cpu, xenbus_allowed_cpumask)) {
- return -EBUSY;
- }
+ rc = cpu_up_is_allowed(cpu);
+ if (rc)
+ return rc;

#ifdef CONFIG_SMP_ALTERNATIVES
if (num_online_cpus() == 1)
@@ -591,8 +417,7 @@ int __devinit __cpu_up(unsigned int cpu)
cpu_set(cpu, cpu_online_map);

rc = HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL);
- if (rc != 0)
- BUG();
+ BUG_ON(rc);

return 0;
}
diff -r 2d08d6db792b -r 606db2959bd6 linux-2.6-xen-sparse/drivers/xen/core/cpu_hotplug.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/drivers/xen/core/cpu_hotplug.c Tue May 23 12:05:08 2006 +0100
@@ -0,0 +1,185 @@
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <xen/cpu_hotplug.h>
+#include <xen/xenbus.h>
+
+/*
+ * Set of CPUs that remote admin software will allow us to bring online.
+ * Notified to us via xenbus.
+ */
+static cpumask_t xenbus_allowed_cpumask;
+
+/* Set of CPUs that local admin will allow us to bring online. */
+static cpumask_t local_allowed_cpumask = CPU_MASK_ALL;
+
+static int local_cpu_hotplug_request(void)
+{
+ /*
+ * We assume a CPU hotplug request comes from local admin if it is made
+ * via a userspace process (i.e., one with a real mm_struct).
+ */
+ return (current->mm != NULL);
+}
+
+static void vcpu_hotplug(unsigned int cpu)
+{
+ int err;
+ char dir[32], state[32];
+
+ if ((cpu >= NR_CPUS) || !cpu_possible(cpu))
+ return;
+
+ sprintf(dir, "cpu/%d", cpu);
+ err = xenbus_scanf(XBT_NULL, dir, "availability", "%s", state);
+ if (err != 1) {
+ printk(KERN_ERR "XENBUS: Unable to read cpu state\n");
+ return;
+ }
+
+ if (strcmp(state, "online") == 0) {
+ cpu_set(cpu, xenbus_allowed_cpumask);
+ (void)cpu_up(cpu);
+ } else if (strcmp(state, "offline") == 0) {
+ cpu_clear(cpu, xenbus_allowed_cpumask);
+ (void)cpu_down(cpu);
+ } else {
+ printk(KERN_ERR "XENBUS: unknown state(%s) on CPU%d\n",
+ state, cpu);
+ }
+}
+
+static void handle_vcpu_hotplug_event(
+ struct xenbus_watch *watch, const char **vec, unsigned int len)
+{
+ int cpu;
+ char *cpustr;
+ const char *node = vec[XS_WATCH_PATH];
+
+ if ((cpustr = strstr(node, "cpu/")) != NULL) {
+ sscanf(cpustr, "cpu/%d", &cpu);
+ vcpu_hotplug(cpu);
+ }
+}
+
+static int smpboot_cpu_notify(struct notifier_block *notifier,
+ unsigned long action, void *hcpu)
+{
+ int cpu = (long)hcpu;
+
+ /*
+ * We do this in a callback notifier rather than __cpu_disable()
+ * because local_cpu_hotplug_request() does not work in the latter
+ * as it's always executed from within a stopmachine kthread.
+ */
+ if ((action == CPU_DOWN_PREPARE) && local_cpu_hotplug_request())
+ cpu_clear(cpu, local_allowed_cpumask);
+
+ return NOTIFY_OK;
+}
+
+static int setup_cpu_watcher(struct notifier_block *notifier,
+ unsigned long event, void *data)
+{
+ int i;
+
+ static struct xenbus_watch cpu_watch = {
+ .node = "cpu",
+ .callback = handle_vcpu_hotplug_event,
+ .flags = XBWF_new_thread };
+ (void)register_xenbus_watch(&cpu_watch);
+
+ if (!(xen_start_info->flags & SIF_INITDOMAIN)) {
+ for_each_cpu(i)
+ vcpu_hotplug(i);
+ printk(KERN_INFO "Brought up %ld CPUs\n",
+ (long)num_online_cpus());
+ }
+
+ return NOTIFY_DONE;
+}
+
+static int __init setup_vcpu_hotplug_event(void)
+{
+ static struct notifier_block hotplug_cpu = {
+ .notifier_call = smpboot_cpu_notify };
+ static struct notifier_block xsn_cpu = {
+ .notifier_call = setup_cpu_watcher };
+
+ register_cpu_notifier(&hotplug_cpu);
+ register_xenstore_notifier(&xsn_cpu);
+
+ return 0;
+}
+
+arch_initcall(setup_vcpu_hotplug_event);
+
+int smp_suspend(void)
+{
+ int i, err;
+
+ lock_cpu_hotplug();
+
+ /*
+ * Take all other CPUs offline. We hold the hotplug mutex to
+ * avoid other processes bringing up CPUs under our feet.
+ */
+ while (num_online_cpus() > 1) {
+ unlock_cpu_hotplug();
+ for_each_online_cpu(i) {
+ if (i == 0)
+ continue;
+ err = cpu_down(i);
+ if (err) {
+ printk(KERN_CRIT "Failed to take all CPUs "
+ "down: %d.\n", err);
+ for_each_cpu(i)
+ vcpu_hotplug(i);
+ return err;
+ }
+ }
+ lock_cpu_hotplug();
+ }
+
+ return 0;
+}
+
+void smp_resume(void)
+{
+ int cpu;
+
+ for_each_cpu(cpu)
+ cpu_initialize_context(cpu);
+
+ unlock_cpu_hotplug();
+
+ for_each_cpu(cpu)
+ vcpu_hotplug(cpu);
+}
+
+int cpu_up_is_allowed(unsigned int cpu)
+{
+ int rc = 0;
+
+ if (local_cpu_hotplug_request()) {
+ cpu_set(cpu, local_allowed_cpumask);
+ if (!cpu_isset(cpu, xenbus_allowed_cpumask)) {
+ printk("%s: attempt to bring up CPU %u disallowed by "
+ "remote admin.\n", __FUNCTION__, cpu);
+ rc = -EBUSY;
+ }
+ } else if (!cpu_isset(cpu, local_allowed_cpumask) ||
+ !cpu_isset(cpu, xenbus_allowed_cpumask)) {
+ rc = -EBUSY;
+ }
+
+ return rc;
+}
+
+void init_xenbus_allowed_cpumask(void)
+{
+ xenbus_allowed_cpumask = cpu_present_map;
+}
diff -r 2d08d6db792b -r 606db2959bd6 linux-2.6-xen-sparse/include/xen/cpu_hotplug.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/include/xen/cpu_hotplug.h Tue May 23 12:05:08 2006 +0100
@@ -0,0 +1,42 @@
+#ifndef __XEN_CPU_HOTPLUG_H__
+#define __XEN_CPU_HOTPLUG_H__
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/cpumask.h>
+
+#if defined(CONFIG_HOTPLUG_CPU)
+
+#if defined(CONFIG_X86)
+void cpu_initialize_context(unsigned int cpu);
+#else
+#define cpu_initialize_context(cpu) ((void)0)
+#endif
+
+int cpu_up_is_allowed(unsigned int cpu);
+void init_xenbus_allowed_cpumask(void);
+int smp_suspend(void);
+void smp_resume(void);
+
+#else /* !defined(CONFIG_HOTPLUG_CPU) */
+
+#define cpu_up_is_allowed(cpu) (1)
+#define init_xenbus_allowed_cpumask() ((void)0)
+
+static inline int smp_suspend(void)
+{
+ if (num_online_cpus() > 1) {
+ printk(KERN_WARNING "Can't suspend SMP guests "
+ "without CONFIG_HOTPLUG_CPU\n");
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+static inline void smp_resume(void)
+{
+}
+
+#endif /* !defined(CONFIG_HOTPLUG_CPU) */
+
+#endif /* __XEN_CPU_HOTPLUG_H__ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog