1d68d82afSAlex Nixon #include <linux/notifier.h> 2d68d82afSAlex Nixon 3d68d82afSAlex Nixon #include <xen/xenbus.h> 4d68d82afSAlex Nixon 5*bb898558SAl Viro #include <asm/xen/hypervisor.h> 6d68d82afSAlex Nixon #include <asm/cpu.h> 7d68d82afSAlex Nixon 8d68d82afSAlex Nixon static void enable_hotplug_cpu(int cpu) 9d68d82afSAlex Nixon { 10d68d82afSAlex Nixon if (!cpu_present(cpu)) 11d68d82afSAlex Nixon arch_register_cpu(cpu); 12d68d82afSAlex Nixon 13d68d82afSAlex Nixon cpu_set(cpu, cpu_present_map); 14d68d82afSAlex Nixon } 15d68d82afSAlex Nixon 16d68d82afSAlex Nixon static void disable_hotplug_cpu(int cpu) 17d68d82afSAlex Nixon { 18d68d82afSAlex Nixon if (cpu_present(cpu)) 19d68d82afSAlex Nixon arch_unregister_cpu(cpu); 20d68d82afSAlex Nixon 21d68d82afSAlex Nixon cpu_clear(cpu, cpu_present_map); 22d68d82afSAlex Nixon } 23d68d82afSAlex Nixon 24d68d82afSAlex Nixon static void vcpu_hotplug(unsigned int cpu) 25d68d82afSAlex Nixon { 26d68d82afSAlex Nixon int err; 27d68d82afSAlex Nixon char dir[32], state[32]; 28d68d82afSAlex Nixon 29d68d82afSAlex Nixon if (!cpu_possible(cpu)) 30d68d82afSAlex Nixon return; 31d68d82afSAlex Nixon 32d68d82afSAlex Nixon sprintf(dir, "cpu/%u", cpu); 33d68d82afSAlex Nixon err = xenbus_scanf(XBT_NIL, dir, "availability", "%s", state); 34d68d82afSAlex Nixon if (err != 1) { 35d68d82afSAlex Nixon printk(KERN_ERR "XENBUS: Unable to read cpu state\n"); 36d68d82afSAlex Nixon return; 37d68d82afSAlex Nixon } 38d68d82afSAlex Nixon 39d68d82afSAlex Nixon if (strcmp(state, "online") == 0) { 40d68d82afSAlex Nixon enable_hotplug_cpu(cpu); 41d68d82afSAlex Nixon } else if (strcmp(state, "offline") == 0) { 42d68d82afSAlex Nixon (void)cpu_down(cpu); 43d68d82afSAlex Nixon disable_hotplug_cpu(cpu); 44d68d82afSAlex Nixon } else { 45d68d82afSAlex Nixon printk(KERN_ERR "XENBUS: unknown state(%s) on CPU%d\n", 46d68d82afSAlex Nixon state, cpu); 47d68d82afSAlex Nixon } 48d68d82afSAlex Nixon } 49d68d82afSAlex Nixon 50d68d82afSAlex Nixon static void handle_vcpu_hotplug_event(struct xenbus_watch *watch, 51d68d82afSAlex Nixon const char **vec, unsigned int len) 52d68d82afSAlex Nixon { 53d68d82afSAlex Nixon unsigned int cpu; 54d68d82afSAlex Nixon char *cpustr; 55d68d82afSAlex Nixon const char *node = vec[XS_WATCH_PATH]; 56d68d82afSAlex Nixon 57d68d82afSAlex Nixon cpustr = strstr(node, "cpu/"); 58d68d82afSAlex Nixon if (cpustr != NULL) { 59d68d82afSAlex Nixon sscanf(cpustr, "cpu/%u", &cpu); 60d68d82afSAlex Nixon vcpu_hotplug(cpu); 61d68d82afSAlex Nixon } 62d68d82afSAlex Nixon } 63d68d82afSAlex Nixon 64d68d82afSAlex Nixon static int setup_cpu_watcher(struct notifier_block *notifier, 65d68d82afSAlex Nixon unsigned long event, void *data) 66d68d82afSAlex Nixon { 67d68d82afSAlex Nixon static struct xenbus_watch cpu_watch = { 68d68d82afSAlex Nixon .node = "cpu", 69d68d82afSAlex Nixon .callback = handle_vcpu_hotplug_event}; 70d68d82afSAlex Nixon 71d68d82afSAlex Nixon (void)register_xenbus_watch(&cpu_watch); 72d68d82afSAlex Nixon 73d68d82afSAlex Nixon return NOTIFY_DONE; 74d68d82afSAlex Nixon } 75d68d82afSAlex Nixon 76d68d82afSAlex Nixon static int __init setup_vcpu_hotplug_event(void) 77d68d82afSAlex Nixon { 78d68d82afSAlex Nixon static struct notifier_block xsn_cpu = { 79d68d82afSAlex Nixon .notifier_call = setup_cpu_watcher }; 80d68d82afSAlex Nixon 815c51c637SAlex Nixon if (!xen_pv_domain()) 82d68d82afSAlex Nixon return -ENODEV; 83d68d82afSAlex Nixon 84d68d82afSAlex Nixon register_xenstore_notifier(&xsn_cpu); 85d68d82afSAlex Nixon 86d68d82afSAlex Nixon return 0; 87d68d82afSAlex Nixon } 88d68d82afSAlex Nixon 89d68d82afSAlex Nixon arch_initcall(setup_vcpu_hotplug_event); 90d68d82afSAlex Nixon 91