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