xen/arm: arm64: Add cortex-A57 erratum 832075 workaround
authorJulien Grall <julien.grall@arm.com>
Wed, 27 Jul 2016 16:37:10 +0000 (17:37 +0100)
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Wed, 3 Aug 2016 19:47:07 +0000 (15:47 -0400)
The ARM erratum 832075 applies to certain revisions of Cortex-A57, one
of the workarounds is to change device loads into using load-acquire
semantics.

Use the alternative framework to enable the workaround only on affected
cores.

Whilst a guest could trigger the deadlock, it can be broken when the
processor is receiving an interrupt. As the Xen scheduler will always setup
a timer (firing to every 1ms to 300ms depending on the running time
slice) on each processor, the deadlock would last only few milliseconds
and only affects the guest time slice.

Therefore a malicious guest could only hurt itself. Note that all the
guests should implement/enable the workaround for the affected cores.

Signed-off-by: Julien Grall <julien.grall@arm.com>
Acked-by: Stefano Stabellini <sstabellini@kernel.org>
docs/misc/arm/silicon-errata.txt
xen/arch/arm/Kconfig
xen/arch/arm/cpuerrata.c
xen/include/asm-arm/arm64/io.h
xen/include/asm-arm/cpufeature.h
xen/include/asm-arm/processor.h

index 546ccd7d8eb84a4bcebb0115abeaee362ab61df5..220f724e7860f687682d745fa58b7c540774b64c 100644 (file)
@@ -46,3 +46,4 @@ stable hypervisors.
 | ARM            | Cortex-A53      | #824069         | ARM64_ERRATUM_824069    |
 | ARM            | Cortex-A53      | #819472         | ARM64_ERRATUM_819472    |
 | ARM            | Cortex-A57      | #852523         | N/A                     |
+| ARM            | Cortex-A57      | #832075         | ARM64_ERRATUM_832075    |
index a473d9cb92b77ee4f49cfdfa0e6687e8a4d48ed1..e26c4c8e051dcf447df1b2deb294fc6694bfc45a 100644 (file)
@@ -122,6 +122,26 @@ config ARM64_ERRATUM_819472
          the kernel if an affected CPU is detected.
 
          If unsure, say Y.
+
+config ARM64_ERRATUM_832075
+       bool "Cortex-A57: 832075: possible deadlock on mixing exclusive memory accesses with device loads"
+       default y
+       depends on ARM_64
+       help
+         This option adds an alternative code sequence to work around ARM
+         erratum 832075 on Cortex-A57 parts up to r1p2.
+
+         Affected Cortex-A57 parts might deadlock when exclusive load/store
+         instructions to Write-Back memory are mixed with Device loads.
+
+         The workaround is to promote device loads to use Load-Acquire
+         semantics.
+         Please note that this does not necessarily enable the workaround,
+         as it depends on the alternative framework, which will only patch
+         the kernel if an affected CPU is detected.
+
+         If unsure, say Y.
+
 endmenu
 
 source "common/Kconfig"
index 121788d7d524738f225df246342e9d0c1ecdf692..3ac97b30fd8d72c4c89720c5b66bf1356ca00181 100644 (file)
@@ -33,6 +33,15 @@ static const struct arm_cpu_capabilities arm_errata[] = {
         .capability = ARM64_WORKAROUND_CLEAN_CACHE,
         MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x01),
     },
+#endif
+#ifdef CONFIG_ARM64_ERRATUM_832075
+    {
+        /* Cortex-A57 r0p0 - r1p2 */
+        .desc = "ARM erratum 832075",
+        .capability = ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE,
+        MIDR_RANGE(MIDR_CORTEX_A57, 0x00,
+                   (1 << MIDR_VARIANT_SHIFT) | 2),
+    },
 #endif
     {},
 };
index f80156f56e2694354b56849e0fa2e16e296d5701..30bfc78d9e7f75db83a9adf1c64a212ad0429e46 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <asm/system.h>
 #include <asm/byteorder.h>
+#include <asm/alternative.h>
 
 /*
  * Generic IO read/write.  These perform native-endian accesses.
@@ -49,28 +50,40 @@ static inline void __raw_writeq(u64 val, volatile void __iomem *addr)
 static inline u8 __raw_readb(const volatile void __iomem *addr)
 {
         u8 val;
-        asm volatile("ldrb %w0, [%1]" : "=r" (val) : "r" (addr));
+        asm volatile(ALTERNATIVE("ldrb %w0, [%1]",
+                                 "ldarb %w0, [%1]",
+                                 ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
+                     : "=r" (val) : "r" (addr));
         return val;
 }
 
 static inline u16 __raw_readw(const volatile void __iomem *addr)
 {
         u16 val;
-        asm volatile("ldrh %w0, [%1]" : "=r" (val) : "r" (addr));
+        asm volatile(ALTERNATIVE("ldrh %w0, [%1]",
+                                 "ldarh %w0, [%1]",
+                                 ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
+                     : "=r" (val) : "r" (addr));
         return val;
 }
 
 static inline u32 __raw_readl(const volatile void __iomem *addr)
 {
         u32 val;
-        asm volatile("ldr %w0, [%1]" : "=r" (val) : "r" (addr));
+        asm volatile(ALTERNATIVE("ldr %w0, [%1]",
+                                 "ldar %w0, [%1]",
+                                 ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
+                     : "=r" (val) : "r" (addr));
         return val;
 }
 
 static inline u64 __raw_readq(const volatile void __iomem *addr)
 {
         u64 val;
-        asm volatile("ldr %0, [%1]" : "=r" (val) : "r" (addr));
+        asm volatile(ALTERNATIVE("ldr %0, [%1]",
+                                 "ldar %0, [%1]",
+                                 ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
+                     : "=r" (val) : "r" (addr));
         return val;
 }
 
index 474a778bef8c592dfd3b425114de489a0c316929..78e22633dea69a29e68120110161f918c8433dad 100644 (file)
@@ -36,8 +36,9 @@
 #define cpu_has_security  (boot_cpu_feature32(security) > 0)
 
 #define ARM64_WORKAROUND_CLEAN_CACHE    0
+#define ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE    1
 
-#define ARM_NCAPS           1
+#define ARM_NCAPS           2
 
 #ifndef __ASSEMBLY__
 
index 5089bfd75d72c151e74b6fc8f0a9ef0251fa8ae5..170825362dc064a923e2c3a64ea6a6475780df9f 100644 (file)
 #define ARM_CPU_IMP_ARM             0x41
 
 #define ARM_CPU_PART_CORTEX_A53     0xD03
+#define ARM_CPU_PART_CORTEX_A57     0xD07
 
 #define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
+#define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
 
 /* MPIDR Multiprocessor Affinity Register */
 #define _MPIDR_UP           (30)