1 #include <linux/init.h>
2 #include <linux/kernel.h>
3 #include <linux/sched.h>
4 #include <linux/kobject.h>
5 #include <linux/notifier.h>
7 #include <xen/cpu_hotplug.h>
8 #include <xen/xenbus.h>
11 * Set of CPUs that remote admin software will allow us to bring online.
12 * Notified to us via xenbus.
14 static cpumask_var_t xenbus_allowed_cpumask;
16 /* Set of CPUs that local admin will allow us to bring online. */
17 static cpumask_var_t local_allowed_cpumask;
19 static int local_cpu_hotplug_request(void)
22 * We assume a CPU hotplug request comes from local admin if it is made
23 * via a userspace process (i.e., one with a real mm_struct).
25 return (current->mm != NULL);
28 static void __cpuinit vcpu_hotplug(unsigned int cpu, struct device *dev)
31 char dir[32], state[32];
33 if ((cpu >= NR_CPUS) || !cpu_possible(cpu))
36 sprintf(dir, "cpu/%u", cpu);
37 err = xenbus_scanf(XBT_NIL, dir, "availability", "%s", state);
39 pr_err("XENBUS: Unable to read cpu state\n");
43 if (strcmp(state, "online") == 0) {
44 cpumask_set_cpu(cpu, xenbus_allowed_cpumask);
45 if (!cpu_up(cpu) && dev)
46 kobject_uevent(&dev->kobj, KOBJ_ONLINE);
47 } else if (strcmp(state, "offline") == 0) {
48 cpumask_clear_cpu(cpu, xenbus_allowed_cpumask);
49 if (!cpu_down(cpu) && dev)
50 kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
52 pr_err("XENBUS: unknown state(%s) on CPU%d\n",
57 static void __cpuinit handle_vcpu_hotplug_event(
58 struct xenbus_watch *watch, const char **vec, unsigned int len)
62 const char *node = vec[XS_WATCH_PATH];
64 if ((cpustr = strstr(node, "cpu/")) != NULL) {
65 sscanf(cpustr, "cpu/%u", &cpu);
66 vcpu_hotplug(cpu, get_cpu_device(cpu));
70 static int smpboot_cpu_notify(struct notifier_block *notifier,
71 unsigned long action, void *hcpu)
73 unsigned int cpu = (long)hcpu;
76 * We do this in a callback notifier rather than __cpu_disable()
77 * because local_cpu_hotplug_request() does not work in the latter
78 * as it's always executed from within a stopmachine kthread.
80 if ((action == CPU_DOWN_PREPARE) && local_cpu_hotplug_request())
81 cpumask_clear_cpu(cpu, local_allowed_cpumask);
86 static int __cpuinit setup_cpu_watcher(struct notifier_block *notifier,
87 unsigned long event, void *data)
91 static struct xenbus_watch __cpuinitdata cpu_watch = {
93 .callback = handle_vcpu_hotplug_event,
94 .flags = XBWF_new_thread };
95 (void)register_xenbus_watch(&cpu_watch);
97 if (!is_initial_xendomain()) {
98 for_each_possible_cpu(i)
99 vcpu_hotplug(i, get_cpu_device(i));
100 pr_info("Brought up %ld CPUs\n", (long)num_online_cpus());
106 static int __init setup_vcpu_hotplug_event(void)
108 static struct notifier_block hotplug_cpu = {
109 .notifier_call = smpboot_cpu_notify };
110 static struct notifier_block __cpuinitdata xsn_cpu = {
111 .notifier_call = setup_cpu_watcher };
113 if (!is_running_on_xen())
116 register_cpu_notifier(&hotplug_cpu);
117 register_xenstore_notifier(&xsn_cpu);
122 arch_initcall(setup_vcpu_hotplug_event);
124 int __ref smp_suspend(void)
129 for_each_online_cpu(cpu) {
134 pr_crit("Failed to take all CPUs down: %d\n", err);
135 for_each_possible_cpu(cpu)
136 vcpu_hotplug(cpu, NULL);
144 void __ref smp_resume(void)
148 for_each_possible_cpu(cpu) {
151 vcpu_hotplug(cpu, NULL);
155 int cpu_up_check(unsigned int cpu)
159 if (local_cpu_hotplug_request()) {
160 cpumask_set_cpu(cpu, local_allowed_cpumask);
161 if (!cpumask_test_cpu(cpu, xenbus_allowed_cpumask)) {
162 pr_warning("%s: attempt to bring up CPU %u disallowed "
163 "by remote admin.\n", __FUNCTION__, cpu);
166 } else if (!cpumask_test_cpu(cpu, local_allowed_cpumask) ||
167 !cpumask_test_cpu(cpu, xenbus_allowed_cpumask)) {
174 void __init init_xenbus_allowed_cpumask(void)
176 if (!alloc_cpumask_var(&xenbus_allowed_cpumask, GFP_KERNEL))
178 cpumask_copy(xenbus_allowed_cpumask, cpu_present_mask);
179 if (!alloc_cpumask_var(&local_allowed_cpumask, GFP_KERNEL))
181 cpumask_setall(local_allowed_cpumask);