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