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