|
@@ -106,6 +106,21 @@ int xen_cpuhp_setup(int (*cpu_up_prepare_cb)(unsigned int),
|
|
|
return rc >= 0 ? 0 : rc;
|
|
|
}
|
|
|
|
|
|
+static void xen_vcpu_setup_restore(int cpu)
|
|
|
+{
|
|
|
+ /* Any per_cpu(xen_vcpu) is stale, so reset it */
|
|
|
+ xen_vcpu_info_reset(cpu);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * For PVH and PVHVM, setup online VCPUs only. The rest will
|
|
|
+ * be handled by hotplug.
|
|
|
+ */
|
|
|
+ if (xen_pv_domain() ||
|
|
|
+ (xen_hvm_domain() && cpu_online(cpu))) {
|
|
|
+ xen_vcpu_setup(cpu);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* On restore, set the vcpu placement up again.
|
|
|
* If it fails, then we're in a bad state, since
|
|
@@ -117,17 +132,23 @@ void xen_vcpu_restore(void)
|
|
|
|
|
|
for_each_possible_cpu(cpu) {
|
|
|
bool other_cpu = (cpu != smp_processor_id());
|
|
|
- bool is_up = HYPERVISOR_vcpu_op(VCPUOP_is_up, xen_vcpu_nr(cpu),
|
|
|
- NULL);
|
|
|
+ bool is_up;
|
|
|
+
|
|
|
+ if (xen_vcpu_nr(cpu) == XEN_VCPU_ID_INVALID)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ /* Only Xen 4.5 and higher support this. */
|
|
|
+ is_up = HYPERVISOR_vcpu_op(VCPUOP_is_up,
|
|
|
+ xen_vcpu_nr(cpu), NULL) > 0;
|
|
|
|
|
|
if (other_cpu && is_up &&
|
|
|
HYPERVISOR_vcpu_op(VCPUOP_down, xen_vcpu_nr(cpu), NULL))
|
|
|
BUG();
|
|
|
|
|
|
- xen_setup_runstate_info(cpu);
|
|
|
+ if (xen_pv_domain() || xen_feature(XENFEAT_hvm_safe_pvclock))
|
|
|
+ xen_setup_runstate_info(cpu);
|
|
|
|
|
|
- if (xen_have_vcpu_info_placement)
|
|
|
- xen_vcpu_setup(cpu);
|
|
|
+ xen_vcpu_setup_restore(cpu);
|
|
|
|
|
|
if (other_cpu && is_up &&
|
|
|
HYPERVISOR_vcpu_op(VCPUOP_up, xen_vcpu_nr(cpu), NULL))
|
|
@@ -163,11 +184,11 @@ void xen_vcpu_setup(int cpu)
|
|
|
BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info);
|
|
|
|
|
|
/*
|
|
|
- * This path is called twice on PVHVM - first during bootup via
|
|
|
- * smp_init -> xen_hvm_cpu_notify, and then if the VCPU is being
|
|
|
- * hotplugged: cpu_up -> xen_hvm_cpu_notify.
|
|
|
- * As we can only do the VCPUOP_register_vcpu_info once lets
|
|
|
- * not over-write its result.
|
|
|
+ * This path is called on PVHVM at bootup (xen_hvm_smp_prepare_boot_cpu)
|
|
|
+ * and at restore (xen_vcpu_restore). Also called for hotplugged
|
|
|
+ * VCPUs (cpu_init -> xen_hvm_cpu_prepare_hvm).
|
|
|
+ * However, the hypercall can only be done once (see below) so if a VCPU
|
|
|
+ * is offlined and comes back online then let's not redo the hypercall.
|
|
|
*
|
|
|
* For PV it is called during restore (xen_vcpu_restore) and bootup
|
|
|
* (xen_setup_vcpu_info_placement). The hotplug mechanism does not
|
|
@@ -178,8 +199,6 @@ void xen_vcpu_setup(int cpu)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- xen_vcpu_info_reset(cpu);
|
|
|
-
|
|
|
if (xen_have_vcpu_info_placement) {
|
|
|
vcpup = &per_cpu(xen_vcpu_info, cpu);
|
|
|
info.mfn = arbitrary_virt_to_mfn(vcpup);
|
|
@@ -214,7 +233,7 @@ void xen_vcpu_setup(int cpu)
|
|
|
if (!xen_have_vcpu_info_placement) {
|
|
|
if (cpu >= MAX_VIRT_CPUS)
|
|
|
clamp_max_cpus();
|
|
|
- return;
|
|
|
+ xen_vcpu_info_reset(cpu);
|
|
|
}
|
|
|
}
|
|
|
|