Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v4.14-rc7 121 lines 2.3 kB view raw
1#define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt 2 3#include <linux/notifier.h> 4 5#include <xen/xen.h> 6#include <xen/xenbus.h> 7 8#include <asm/xen/hypervisor.h> 9#include <asm/cpu.h> 10 11static void enable_hotplug_cpu(int cpu) 12{ 13 if (!cpu_present(cpu)) 14 xen_arch_register_cpu(cpu); 15 16 set_cpu_present(cpu, true); 17} 18 19static void disable_hotplug_cpu(int cpu) 20{ 21 if (cpu_online(cpu)) { 22 lock_device_hotplug(); 23 device_offline(get_cpu_device(cpu)); 24 unlock_device_hotplug(); 25 } 26 if (cpu_present(cpu)) 27 xen_arch_unregister_cpu(cpu); 28 29 set_cpu_present(cpu, false); 30} 31 32static int vcpu_online(unsigned int cpu) 33{ 34 int err; 35 char dir[16], state[16]; 36 37 sprintf(dir, "cpu/%u", cpu); 38 err = xenbus_scanf(XBT_NIL, dir, "availability", "%15s", state); 39 if (err != 1) { 40 if (!xen_initial_domain()) 41 pr_err("Unable to read cpu state\n"); 42 return err; 43 } 44 45 if (strcmp(state, "online") == 0) 46 return 1; 47 else if (strcmp(state, "offline") == 0) 48 return 0; 49 50 pr_err("unknown state(%s) on CPU%d\n", state, cpu); 51 return -EINVAL; 52} 53static void vcpu_hotplug(unsigned int cpu) 54{ 55 if (!cpu_possible(cpu)) 56 return; 57 58 switch (vcpu_online(cpu)) { 59 case 1: 60 enable_hotplug_cpu(cpu); 61 break; 62 case 0: 63 disable_hotplug_cpu(cpu); 64 break; 65 default: 66 break; 67 } 68} 69 70static void handle_vcpu_hotplug_event(struct xenbus_watch *watch, 71 const char *path, const char *token) 72{ 73 unsigned int cpu; 74 char *cpustr; 75 76 cpustr = strstr(path, "cpu/"); 77 if (cpustr != NULL) { 78 sscanf(cpustr, "cpu/%u", &cpu); 79 vcpu_hotplug(cpu); 80 } 81} 82 83static int setup_cpu_watcher(struct notifier_block *notifier, 84 unsigned long event, void *data) 85{ 86 int cpu; 87 static struct xenbus_watch cpu_watch = { 88 .node = "cpu", 89 .callback = handle_vcpu_hotplug_event}; 90 91 (void)register_xenbus_watch(&cpu_watch); 92 93 for_each_possible_cpu(cpu) { 94 if (vcpu_online(cpu) == 0) { 95 (void)cpu_down(cpu); 96 set_cpu_present(cpu, false); 97 } 98 } 99 100 return NOTIFY_DONE; 101} 102 103static int __init setup_vcpu_hotplug_event(void) 104{ 105 static struct notifier_block xsn_cpu = { 106 .notifier_call = setup_cpu_watcher }; 107 108#ifdef CONFIG_X86 109 if (!xen_pv_domain() && !xen_pvh_domain()) 110#else 111 if (!xen_domain()) 112#endif 113 return -ENODEV; 114 115 register_xenstore_notifier(&xsn_cpu); 116 117 return 0; 118} 119 120arch_initcall(setup_vcpu_hotplug_event); 121