xen: honour VCPU availability on boot

If a VM is booted with offline VCPUs then unplug them during boot. Determining
the availability of a VCPU requires access to XenStore which is not available
at the point smp_prepare_cpus() is called, therefore we bring up all VCPUS
initially and unplug the offline ones as soon as XenStore becomes available.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>

authored by

Ian Campbell and committed by
Jeremy Fitzhardinge
d745562c 2b2a7334

+30 -10
+30 -10
drivers/xen/cpu_hotplug.c
··· 21 21 set_cpu_present(cpu, false); 22 22 } 23 23 24 - static void vcpu_hotplug(unsigned int cpu) 24 + static int vcpu_online(unsigned int cpu) 25 25 { 26 26 int err; 27 27 char dir[32], state[32]; 28 - 29 - if (!cpu_possible(cpu)) 30 - return; 31 28 32 29 sprintf(dir, "cpu/%u", cpu); 33 30 err = xenbus_scanf(XBT_NIL, dir, "availability", "%s", state); 34 31 if (err != 1) { 35 32 printk(KERN_ERR "XENBUS: Unable to read cpu state\n"); 36 - return; 33 + return err; 37 34 } 38 35 39 - if (strcmp(state, "online") == 0) { 36 + if (strcmp(state, "online") == 0) 37 + return 1; 38 + else if (strcmp(state, "offline") == 0) 39 + return 0; 40 + 41 + printk(KERN_ERR "XENBUS: unknown state(%s) on CPU%d\n", state, cpu); 42 + return -EINVAL; 43 + } 44 + static void vcpu_hotplug(unsigned int cpu) 45 + { 46 + if (!cpu_possible(cpu)) 47 + return; 48 + 49 + switch (vcpu_online(cpu)) { 50 + case 1: 40 51 enable_hotplug_cpu(cpu); 41 - } else if (strcmp(state, "offline") == 0) { 52 + break; 53 + case 0: 42 54 (void)cpu_down(cpu); 43 55 disable_hotplug_cpu(cpu); 44 - } else { 45 - printk(KERN_ERR "XENBUS: unknown state(%s) on CPU%d\n", 46 - state, cpu); 56 + break; 57 + default: 58 + break; 47 59 } 48 60 } 49 61 ··· 76 64 static int setup_cpu_watcher(struct notifier_block *notifier, 77 65 unsigned long event, void *data) 78 66 { 67 + int cpu; 79 68 static struct xenbus_watch cpu_watch = { 80 69 .node = "cpu", 81 70 .callback = handle_vcpu_hotplug_event}; 82 71 83 72 (void)register_xenbus_watch(&cpu_watch); 73 + 74 + for_each_possible_cpu(cpu) { 75 + if (vcpu_online(cpu) == 0) { 76 + (void)cpu_down(cpu); 77 + cpu_clear(cpu, cpu_present_map); 78 + } 79 + } 84 80 85 81 return NOTIFY_DONE; 86 82 }