---
Changes in v3:
- rename ARM64_HAS_SB to ARM_HAS_SB
- define sb before including per arch macros
Changes in v2:
- fix commit message
- add comment to explain the extra nop
- add support for arm32 and move macro back to arm generic header
- fix macro comment indentation
- introduce cpu feature system instead of using errata
---
xen/arch/arm/cpufeature.c | 28 +++++++++++++++++++++++++++
xen/arch/arm/include/asm/cpufeature.h | 6 +++++-
xen/arch/arm/include/asm/macros.h | 19 +++++++++++++++++-
xen/arch/arm/setup.c | 3 +++
xen/arch/arm/smpboot.c | 1 +
5 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/xen/arch/arm/cpufeature.c b/xen/arch/arm/cpufeature.c
index a58965f7b9..62d5e1770a 100644
--- a/xen/arch/arm/cpufeature.c
+++ b/xen/arch/arm/cpufeature.c
@@ -26,6 +26,24 @@ DECLARE_BITMAP(cpu_hwcaps, ARM_NCAPS);
struct cpuinfo_arm __read_mostly guest_cpuinfo;
+#ifdef CONFIG_ARM_64
+static bool has_sb_instruction(const struct arm_cpu_capabilities *entry)
+{
+ return system_cpuinfo.isa64.sb;
+}
+#endif
+
+static const struct arm_cpu_capabilities arm_features[] = {
+#ifdef CONFIG_ARM_64
+ {
+ .desc = "Speculation barrier instruction (SB)",
+ .capability = ARM_HAS_SB,
+ .matches = has_sb_instruction,
+ },
+#endif
+ {},
+};
+
void update_cpu_capabilities(const struct arm_cpu_capabilities *caps,
const char *info)
{
@@ -70,6 +88,16 @@ void __init enable_cpu_capabilities(const struct
arm_cpu_capabilities *caps)
}
}
+void check_local_cpu_features(void)
+{
+ update_cpu_capabilities(arm_features, "enabled support for");
+}
+
+void __init enable_cpu_features(void)
+{
+ enable_cpu_capabilities(arm_features);
+}
+
/*
* Run through the enabled capabilities and enable() them on the calling CPU.
* If enabling of any capability fails the error is returned. After enabling a
diff --git a/xen/arch/arm/include/asm/cpufeature.h
b/xen/arch/arm/include/asm/cpufeature.h
index f7368766c0..24c01d2b9d 100644
--- a/xen/arch/arm/include/asm/cpufeature.h
+++ b/xen/arch/arm/include/asm/cpufeature.h
@@ -67,8 +67,9 @@
#define ARM_WORKAROUND_BHB_LOOP_24 13
#define ARM_WORKAROUND_BHB_LOOP_32 14
#define ARM_WORKAROUND_BHB_SMCC_3 15
+#define ARM_HAS_SB 16
-#define ARM_NCAPS 16
+#define ARM_NCAPS 17
#ifndef __ASSEMBLY__
@@ -78,6 +79,9 @@
extern DECLARE_BITMAP(cpu_hwcaps, ARM_NCAPS);
+void check_local_cpu_features(void);
+void enable_cpu_features(void);
+
static inline bool cpus_have_cap(unsigned int num)
{
if ( num >= ARM_NCAPS )
diff --git a/xen/arch/arm/include/asm/macros.h
b/xen/arch/arm/include/asm/macros.h
index 1aa373760f..dc791245df 100644
--- a/xen/arch/arm/include/asm/macros.h
+++ b/xen/arch/arm/include/asm/macros.h
@@ -5,13 +5,30 @@
# error "This file should only be included in assembly file"
#endif
+#include <asm/alternative.h>
+
/*
* Speculative barrier
- * XXX: Add support for the 'sb' instruction
*/
.macro sb
+alternative_if_not ARM_HAS_SB
dsb nsh
isb
+alternative_else
+ /*
+ * SB encoding in hexadecimal to prevent recursive macro.
+ * extra nop is required to keep same number of instructions on both sides
+ * of the alternative.
+ */
+#if defined(CONFIG_ARM_32)
+ .inst 0xf57ff070
+#elif defined(CONFIG_ARM_64)
+ .inst 0xd50330ff
+#else
+# error "missing sb encoding for ARM variant"
+#endif
+ nop
+alternative_endif
.endm
#if defined (CONFIG_ARM_32)
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 6016471d37..577c54e6fb 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -964,6 +964,8 @@ void __init start_xen(unsigned long boot_phys_offset,
*/
check_local_cpu_errata();
+ check_local_cpu_features();
+
init_xen_time();
gic_init();
@@ -1033,6 +1035,7 @@ void __init start_xen(unsigned long boot_phys_offset,
*/
apply_alternatives_all();
enable_errata_workarounds();
+ enable_cpu_features();
/* Create initial domain 0. */
if ( !is_dom0less_mode() )
diff --git a/xen/arch/arm/smpboot.c b/xen/arch/arm/smpboot.c
index 22fede6600..3f62f3a44f 100644
--- a/xen/arch/arm/smpboot.c
+++ b/xen/arch/arm/smpboot.c
@@ -395,6 +395,7 @@ void start_secondary(void)
local_abort_enable();
check_local_cpu_errata();
+ check_local_cpu_features();
printk(XENLOG_DEBUG "CPU %u booted.\n", smp_processor_id());