Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cpu_hotplug.c
Go to the documentation of this file.
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 
9 static 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 
17 static 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 
25 static 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  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 }
46 static 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 
64 static 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 
78 static 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 
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 
98 static 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 
111 arch_initcall(setup_vcpu_hotplug_event);
112