diff --git a/xen/arch/arm/cpuerrata.c b/xen/arch/arm/cpuerrata.c index 03ae7b496c..563cc7a0e4 100644 --- a/xen/arch/arm/cpuerrata.c +++ b/xen/arch/arm/cpuerrata.c @@ -24,6 +24,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 diff --git a/xen/arch/arm/cpufeature.c b/xen/arch/arm/cpufeature.c index 088625bbac..c1cd425067 100644 --- a/xen/arch/arm/cpufeature.c +++ b/xen/arch/arm/cpufeature.c @@ -20,6 +20,7 @@ #include #include #include +#include #include DECLARE_BITMAP(cpu_hwcaps, ARM_NCAPS); @@ -40,6 +41,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 diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c index e329ac708a..ba899d792c 100644 --- a/xen/arch/arm/setup.c +++ b/xen/arch/arm/setup.c @@ -829,6 +829,8 @@ void __init start_xen(unsigned long boot_phys_offset, do_initcalls(); + enable_errata_workarounds(); + /* Create initial domain 0. */ /* The vGIC for DOM0 is exactly emulating the hardware GIC */ config.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE; diff --git a/xen/include/asm-arm/cpuerrata.h b/xen/include/asm-arm/cpuerrata.h index c495ee5009..5d66194fa7 100644 --- a/xen/include/asm-arm/cpuerrata.h +++ b/xen/include/asm-arm/cpuerrata.h @@ -2,6 +2,7 @@ #define __ARM_CPUERRATA_H__ void check_local_cpu_errata(void); +void enable_errata_workarounds(void); #endif /* __ARM_CPUERRATA_H__ */ /* diff --git a/xen/include/asm-arm/cpufeature.h b/xen/include/asm-arm/cpufeature.h index fb57295ec5..1802499e29 100644 --- a/xen/include/asm-arm/cpufeature.h +++ b/xen/include/asm-arm/cpufeature.h @@ -66,6 +66,7 @@ struct arm_cpu_capabilities { const char *desc; u16 capability; bool_t (*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; @@ -77,6 +78,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