The flag xen_have_vcpu_info_placement was needed to support Xen
hypervisors older than version 3.4. Today the Linux kernel requires
at least Xen 4.0 to be able to run, so xen_have_vcpu_info_placement
can be dropped.
This allows to let some functions return void now, as they can never
fail.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
arch/x86/xen/enlighten.c | 97 +++++++++---------------------------
arch/x86/xen/enlighten_hvm.c | 6 +--
arch/x86/xen/enlighten_pv.c | 28 ++---------
arch/x86/xen/smp.c | 24 ---------
arch/x86/xen/xen-ops.h | 4 +-
5 files changed, 33 insertions(+), 126 deletions(-)
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index c79bd0af2e8c..8a7bd3f4591e 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -81,21 +81,6 @@ EXPORT_SYMBOL(xen_start_flags);
*/
struct shared_info *HYPERVISOR_shared_info = &xen_dummy_shared_info;
-/*
- * Flag to determine whether vcpu info placement is available on all
- * VCPUs. We assume it is to start with, and then set it to zero on
- * the first failure. This is because it can succeed on some VCPUs
- * and not others, since it can involve hypervisor memory allocation,
- * or because the guest failed to guarantee all the appropriate
- * constraints on all VCPUs (ie buffer can't cross a page boundary).
- *
- * Note that any particular CPU may be using a placed vcpu structure,
- * but we can only optimise if the all are.
- *
- * 0: not available, 1: available
- */
-int xen_have_vcpu_info_placement = 1;
-
static int xen_cpu_up_online(unsigned int cpu)
{
xen_init_lock_cpu(cpu);
@@ -121,10 +106,8 @@ int xen_cpuhp_setup(int (*cpu_up_prepare_cb)(unsigned int),
return rc >= 0 ? 0 : rc;
}
-static int xen_vcpu_setup_restore(int cpu)
+static void xen_vcpu_setup_restore(int cpu)
{
- int rc = 0;
-
/* Any per_cpu(xen_vcpu) is stale, so reset it */
xen_vcpu_info_reset(cpu);
@@ -133,11 +116,8 @@ static int xen_vcpu_setup_restore(int cpu)
* be handled by hotplug.
*/
if (xen_pv_domain() ||
- (xen_hvm_domain() && cpu_online(cpu))) {
- rc = xen_vcpu_setup(cpu);
- }
-
- return rc;
+ (xen_hvm_domain() && cpu_online(cpu)))
+ xen_vcpu_setup(cpu);
}
/*
@@ -147,7 +127,7 @@ static int xen_vcpu_setup_restore(int cpu)
*/
void xen_vcpu_restore(void)
{
- int cpu, rc;
+ int cpu;
for_each_possible_cpu(cpu) {
bool other_cpu = (cpu != smp_processor_id());
@@ -167,20 +147,9 @@ void xen_vcpu_restore(void)
if (xen_pv_domain() || xen_feature(XENFEAT_hvm_safe_pvclock))
xen_setup_runstate_info(cpu);
- rc = xen_vcpu_setup_restore(cpu);
- if (rc)
- pr_emerg_once("vcpu restore failed for cpu=%d err=%d. "
- "System will hang.\n", cpu, rc);
- /*
- * In case xen_vcpu_setup_restore() fails, do not bring up the
- * VCPU. This helps us avoid the resulting OOPS when the VCPU
- * accesses pvclock_vcpu_time via xen_vcpu (which is NULL.)
- * Note that this does not improve the situation much -- now the
- * VM hangs instead of OOPSing -- with the VCPUs that did not
- * fail, spinning in stop_machine(), waiting for the failed
- * VCPUs to come up.
- */
- if (other_cpu && is_up && (rc == 0) &&
+ xen_vcpu_setup_restore(cpu);
+
+ if (other_cpu && is_up &&
HYPERVISOR_vcpu_op(VCPUOP_up, xen_vcpu_nr(cpu), NULL))
BUG();
}
@@ -197,7 +166,7 @@ void xen_vcpu_info_reset(int cpu)
}
}
-int xen_vcpu_setup(int cpu)
+void xen_vcpu_setup(int cpu)
{
struct vcpu_register_vcpu_info info;
int err;
@@ -218,44 +187,26 @@ int xen_vcpu_setup(int cpu)
*/
if (xen_hvm_domain()) {
if (per_cpu(xen_vcpu, cpu) == &per_cpu(xen_vcpu_info, cpu))
- return 0;
+ return;
}
- if (xen_have_vcpu_info_placement) {
- vcpup = &per_cpu(xen_vcpu_info, cpu);
- info.mfn = arbitrary_virt_to_mfn(vcpup);
- info.offset = offset_in_page(vcpup);
+ vcpup = &per_cpu(xen_vcpu_info, cpu);
+ info.mfn = arbitrary_virt_to_mfn(vcpup);
+ info.offset = offset_in_page(vcpup);
- /*
- * Check to see if the hypervisor will put the vcpu_info
- * structure where we want it, which allows direct access via
- * a percpu-variable.
- * N.B. This hypercall can _only_ be called once per CPU.
- * Subsequent calls will error out with -EINVAL. This is due to
- * the fact that hypervisor has no unregister variant and this
- * hypercall does not allow to over-write info.mfn and
- * info.offset.
- */
- err = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info,
- xen_vcpu_nr(cpu), &info);
-
- if (err) {
- pr_warn_once("register_vcpu_info failed: cpu=%d err=%d\n",
- cpu, err);
- xen_have_vcpu_info_placement = 0;
- } else {
- /*
- * This cpu is using the registered vcpu info, even if
- * later ones fail to.
- */
- per_cpu(xen_vcpu, cpu) = vcpup;
- }
- }
-
- if (!xen_have_vcpu_info_placement)
- xen_vcpu_info_reset(cpu);
+ /*
+ * N.B. This hypercall can _only_ be called once per CPU.
+ * Subsequent calls will error out with -EINVAL. This is due to
+ * the fact that hypervisor has no unregister variant and this
+ * hypercall does not allow to over-write info.mfn and
+ * info.offset.
+ */
+ err = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, xen_vcpu_nr(cpu),
+ &info);
+ if (err)
+ panic("register_vcpu_info failed: cpu=%d err=%d\n", cpu, err);
- return ((per_cpu(xen_vcpu, cpu) == NULL) ? -ENODEV : 0);
+ per_cpu(xen_vcpu, cpu) = vcpup;
}
void xen_reboot(int reason)
diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c
index e68ea5f4ad1c..42300941ec29 100644
--- a/arch/x86/xen/enlighten_hvm.c
+++ b/arch/x86/xen/enlighten_hvm.c
@@ -163,9 +163,9 @@ static int xen_cpu_up_prepare_hvm(unsigned int cpu)
per_cpu(xen_vcpu_id, cpu) = cpu_acpi_id(cpu);
else
per_cpu(xen_vcpu_id, cpu) = cpu;
- rc = xen_vcpu_setup(cpu);
- if (rc || !xen_have_vector_callback)
- return rc;
+ xen_vcpu_setup(cpu);
+ if (!xen_have_vector_callback)
+ return 0;
if (xen_feature(XENFEAT_hvm_safe_pvclock))
xen_setup_timer(cpu);
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index 349f780a1567..6719963901e5 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -1018,31 +1018,13 @@ void __init xen_setup_vcpu_info_placement(void)
for_each_possible_cpu(cpu) {
/* Set up direct vCPU id mapping for PV guests. */
per_cpu(xen_vcpu_id, cpu) = cpu;
-
- /*
- * xen_vcpu_setup(cpu) can fail -- in which case it
- * falls back to the shared_info version for cpus
- * where xen_vcpu_nr(cpu) < MAX_VIRT_CPUS.
- *
- * xen_cpu_up_prepare_pv() handles the rest by failing
- * them in hotplug.
- */
- (void) xen_vcpu_setup(cpu);
+ xen_vcpu_setup(cpu);
}
- /*
- * xen_vcpu_setup managed to place the vcpu_info within the
- * percpu area for all cpus, so make use of it.
- */
- if (xen_have_vcpu_info_placement) {
- pv_ops.irq.save_fl = __PV_IS_CALLEE_SAVE(xen_save_fl_direct);
- pv_ops.irq.irq_disable =
- __PV_IS_CALLEE_SAVE(xen_irq_disable_direct);
- pv_ops.irq.irq_enable =
- __PV_IS_CALLEE_SAVE(xen_irq_enable_direct);
- pv_ops.mmu.read_cr2 =
- __PV_IS_CALLEE_SAVE(xen_read_cr2_direct);
- }
+ pv_ops.irq.save_fl = __PV_IS_CALLEE_SAVE(xen_save_fl_direct);
+ pv_ops.irq.irq_disable = __PV_IS_CALLEE_SAVE(xen_irq_disable_direct);
+ pv_ops.irq.irq_enable = __PV_IS_CALLEE_SAVE(xen_irq_enable_direct);
+ pv_ops.mmu.read_cr2 = __PV_IS_CALLEE_SAVE(xen_read_cr2_direct);
}
static const struct pv_info xen_info __initconst = {
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index c1b2f764b29a..bafa61b1482f 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -121,34 +121,10 @@ int xen_smp_intr_init(unsigned int cpu)
void __init xen_smp_cpus_done(unsigned int max_cpus)
{
- int cpu, rc, count = 0;
-
if (xen_hvm_domain())
native_smp_cpus_done(max_cpus);
else
calculate_max_logical_packages();
-
- if (xen_have_vcpu_info_placement)
- return;
-
- for_each_online_cpu(cpu) {
- if (xen_vcpu_nr(cpu) < MAX_VIRT_CPUS)
- continue;
-
- rc = remove_cpu(cpu);
-
- if (rc == 0) {
- /*
- * Reset vcpu_info so this cpu cannot be onlined again.
- */
- xen_vcpu_info_reset(cpu);
- count++;
- } else {
- pr_warn("%s: failed to bring CPU %d down, error %d\n",
- __func__, cpu, rc);
- }
- }
- WARN(count, "%s: brought %d CPUs offline\n", __func__, count);
}
void xen_smp_send_reschedule(int cpu)
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 8d7ec49a35fb..c2da84484b8d 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -75,9 +75,7 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id);
bool xen_vcpu_stolen(int vcpu);
-extern int xen_have_vcpu_info_placement;
-
-int xen_vcpu_setup(int cpu);
+void xen_vcpu_setup(int cpu);
void xen_vcpu_info_reset(int cpu);
void xen_setup_vcpu_info_placement(void);
--
2.26.2
On 9/22/21 6:31 AM, Juergen Gross wrote: > > - if (xen_have_vcpu_info_placement) { > - vcpup = &per_cpu(xen_vcpu_info, cpu); > - info.mfn = arbitrary_virt_to_mfn(vcpup); > - info.offset = offset_in_page(vcpup); > + vcpup = &per_cpu(xen_vcpu_info, cpu); > + info.mfn = arbitrary_virt_to_mfn(vcpup); > + info.offset = offset_in_page(vcpup); > > - /* > - * Check to see if the hypervisor will put the vcpu_info > - * structure where we want it, which allows direct access via > - * a percpu-variable. > - * N.B. This hypercall can _only_ be called once per CPU. > - * Subsequent calls will error out with -EINVAL. This is due to > - * the fact that hypervisor has no unregister variant and this > - * hypercall does not allow to over-write info.mfn and > - * info.offset. > - */ > - err = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, > - xen_vcpu_nr(cpu), &info); > - > - if (err) { > - pr_warn_once("register_vcpu_info failed: cpu=%d err=%d\n", > - cpu, err); > - xen_have_vcpu_info_placement = 0; > - } else { > - /* > - * This cpu is using the registered vcpu info, even if > - * later ones fail to. > - */ > - per_cpu(xen_vcpu, cpu) = vcpup; > - } > - } > - > - if (!xen_have_vcpu_info_placement) > - xen_vcpu_info_reset(cpu); > + /* > + * N.B. This hypercall can _only_ be called once per CPU. > + * Subsequent calls will error out with -EINVAL. This is due to > + * the fact that hypervisor has no unregister variant and this > + * hypercall does not allow to over-write info.mfn and > + * info.offset. > + */ > + err = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, xen_vcpu_nr(cpu), > + &info); > + if (err) > + panic("register_vcpu_info failed: cpu=%d err=%d\n", cpu, err); > This is change in behavior. Before if the hypercall failed we still try to boot. I am not sure we need to worry about this (since it's not clear it actually works) but I'd at least mention this in the commit message. -boris
On 22.09.21 23:43, Boris Ostrovsky wrote: > > On 9/22/21 6:31 AM, Juergen Gross wrote: >> >> - if (xen_have_vcpu_info_placement) { >> - vcpup = &per_cpu(xen_vcpu_info, cpu); >> - info.mfn = arbitrary_virt_to_mfn(vcpup); >> - info.offset = offset_in_page(vcpup); >> + vcpup = &per_cpu(xen_vcpu_info, cpu); >> + info.mfn = arbitrary_virt_to_mfn(vcpup); >> + info.offset = offset_in_page(vcpup); >> >> - /* >> - * Check to see if the hypervisor will put the vcpu_info >> - * structure where we want it, which allows direct access via >> - * a percpu-variable. >> - * N.B. This hypercall can _only_ be called once per CPU. >> - * Subsequent calls will error out with -EINVAL. This is due to >> - * the fact that hypervisor has no unregister variant and this >> - * hypercall does not allow to over-write info.mfn and >> - * info.offset. >> - */ >> - err = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, >> - xen_vcpu_nr(cpu), &info); >> - >> - if (err) { >> - pr_warn_once("register_vcpu_info failed: cpu=%d err=%d\n", >> - cpu, err); >> - xen_have_vcpu_info_placement = 0; >> - } else { >> - /* >> - * This cpu is using the registered vcpu info, even if >> - * later ones fail to. >> - */ >> - per_cpu(xen_vcpu, cpu) = vcpup; >> - } >> - } >> - >> - if (!xen_have_vcpu_info_placement) >> - xen_vcpu_info_reset(cpu); >> + /* >> + * N.B. This hypercall can _only_ be called once per CPU. >> + * Subsequent calls will error out with -EINVAL. This is due to >> + * the fact that hypervisor has no unregister variant and this >> + * hypercall does not allow to over-write info.mfn and >> + * info.offset. >> + */ >> + err = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, xen_vcpu_nr(cpu), >> + &info); >> + if (err) >> + panic("register_vcpu_info failed: cpu=%d err=%d\n", cpu, err); >> > > > This is change in behavior. Before if the hypercall failed we still try to boot. I am not sure we need to worry about this (since it's not clear it actually works) but I'd at least mention this in the commit message. Hmm, maybe I should have been more explicit saying that the hypercall was introduced in Xen 3.4, and only reason of failure is either an illegal vcpu, an invalid mapping specification, or a try to reissue the hypercall for a vcpu. None of those should ever happen. Juergen
On 9/23/21 12:44 AM, Juergen Gross wrote: > > Hmm, maybe I should have been more explicit saying that the hypercall > was introduced in Xen 3.4, and only reason of failure is either an > illegal vcpu, an invalid mapping specification, or a try to reissue the > hypercall for a vcpu. None of those should ever happen. > That last sentence -- famous last words ;-) But yes, sure. Assuming both patches adjust their commit messages and the typo Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
© 2016 - 2024 Red Hat, Inc.