xen/arm: Introduce enable callback to enable a capabilities on each online CPU
authorJulien Grall <julien.grall@linaro.org>
Tue, 16 Jan 2018 14:23:33 +0000 (14:23 +0000)
committerStefano Stabellini <sstabellini@kernel.org>
Wed, 17 Jan 2018 21:44:29 +0000 (13:44 -0800)
Once Xen knows what features/workarounds present on the platform, it
might be necessary to configure each online CPU.

Introduce a new callback "enable" that will be called on each online CPU to
configure the "capability".

The code is based on Linux v4.14 (where cpufeature.c comes from), the
explanation of why using stop_machine_run is kept as we have similar
problem in the future.

Lastly introduce enable_errata_workaround that will be called once CPUs
have booted and before the hardware domain is created.

This is part of XSA-254.

Signed-of-by: Julien Grall <julien.grall@linaro.org>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
xen/arch/arm/cpuerrata.c
xen/arch/arm/cpufeature.c
xen/arch/arm/setup.c
xen/include/asm-arm/cpuerrata.h
xen/include/asm-arm/cpufeature.h

index fe9e9facbe64aedcd076b2b4f220df3d35c33e17..772587c05a0642ccd034ee2e56cf13fdaf04b88d 100644 (file)
@@ -64,6 +64,12 @@ void check_local_cpu_errata(void)
 {
     update_cpu_capabilities(arm_errata, "enabled workaround for");
 }
+
+void __init enable_errata_workarounds(void)
+{
+    enable_cpu_capabilities(arm_errata);
+}
+
 /*
  * Local variables:
  * mode: C
index 479c9fb0119fb8b9844cedfe1a2093182ae776ce..525b45e22fc4145d82d4069ebdf3080e90e0910f 100644 (file)
@@ -19,6 +19,7 @@
 #include <xen/types.h>
 #include <xen/init.h>
 #include <xen/smp.h>
+#include <xen/stop_machine.h>
 #include <asm/cpufeature.h>
 
 DECLARE_BITMAP(cpu_hwcaps, ARM_NCAPS);
@@ -39,6 +40,34 @@ void update_cpu_capabilities(const struct arm_cpu_capabilities *caps,
     }
 }
 
+/*
+ * Run through the enabled capabilities and enable() it on all active
+ * CPUs.
+ */
+void __init enable_cpu_capabilities(const struct arm_cpu_capabilities *caps)
+{
+    for ( ; caps->matches; caps++ )
+    {
+        if ( !cpus_have_cap(caps->capability) )
+            continue;
+
+        if ( caps->enable )
+        {
+            int ret;
+
+            /*
+             * Use stop_machine_run() as it schedules the work allowing
+             * us to modify PSTATE, instead of on_each_cpu() which uses
+             * an IPI, giving us a PSTATE that disappears when we
+             * return.
+             */
+            ret = stop_machine_run(caps->enable, (void *)caps, NR_CPUS);
+            /* stop_machine_run should never fail at this stage of the boot. */
+            BUG_ON(ret);
+        }
+    }
+}
+
 /*
  * Local variables:
  * mode: C
index 16a3b1be8e75cdb39a460ca640623689f3daa4b3..032a6a882d9cda4c2b925349543261ed3df714cb 100644 (file)
@@ -849,6 +849,7 @@ void __init start_xen(unsigned long boot_phys_offset,
      * stop_machine (tasklets initialized via an initcall).
      */
     apply_alternatives_all();
+    enable_errata_workarounds();
 
     /* Create initial domain 0. */
     /* The vGIC for DOM0 is exactly emulating the hardware GIC */
index 8b158429c7881854fecdc5b6bf88ab6c902bd3c1..7de68361ff2c7d8ff47e674ac52829b3e41355ce 100644 (file)
@@ -5,6 +5,7 @@
 #include <asm/alternative.h>
 
 void check_local_cpu_errata(void);
+void enable_errata_workarounds(void);
 
 #ifdef CONFIG_HAS_ALTERNATIVE
 
index f00b6dbd39e01e0e5c4ed0782e6c96e7ae523df8..21c65e198c9790291b04d3a9635400d93a876a3a 100644 (file)
@@ -74,6 +74,7 @@ struct arm_cpu_capabilities {
     const char *desc;
     u16 capability;
     bool (*matches)(const struct arm_cpu_capabilities *);
+    int (*enable)(void *); /* Called on every active CPUs */
     union {
         struct {    /* To be used for eratum handling only */
             u32 midr_model;
@@ -85,6 +86,8 @@ struct arm_cpu_capabilities {
 void update_cpu_capabilities(const struct arm_cpu_capabilities *caps,
                              const char *info);
 
+void enable_cpu_capabilities(const struct arm_cpu_capabilities *caps);
+
 #endif /* __ASSEMBLY__ */
 
 #endif