Browse Source

ARM: 6784/1: errata: no automatic Store Buffer drain on Cortex-A9

On revisions of the Cortex-A9 prior to r2p0, the Store Buffer does not
have any automatic draining mechanism and therefore a livelock may occur
if an external agent continuously polls a memory location waiting to
observe an update.

This workaround defines cpu_relax() as smp_mb(), preventing correctly
written polling loops from denying visibility of updates to memory.

Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Will Deacon 14 years ago
parent
commit
5dab26af1b
2 changed files with 12 additions and 1 deletions
  1. 11 0
      arch/arm/Kconfig
  2. 1 1
      arch/arm/include/asm/processor.h

+ 11 - 0
arch/arm/Kconfig

@@ -1213,6 +1213,17 @@ config ARM_ERRATA_754322
 	  the new ASID. This workaround places two dsb instructions in the mm
 	  the new ASID. This workaround places two dsb instructions in the mm
 	  switching code so that no page table walks can cross the ASID switch.
 	  switching code so that no page table walks can cross the ASID switch.
 
 
+config ARM_ERRATA_754327
+	bool "ARM errata: no automatic Store Buffer drain"
+	depends on CPU_V7 && SMP
+	help
+	  This option enables the workaround for the 754327 Cortex-A9 (prior to
+	  r2p0) erratum. The Store Buffer does not have any automatic draining
+	  mechanism and therefore a livelock may occur if an external agent
+	  continuously polls a memory location waiting to observe an update.
+	  This workaround defines cpu_relax() as smp_mb(), preventing correctly
+	  written polling loops from denying visibility of updates to memory.
+
 endmenu
 endmenu
 
 
 source "arch/arm/common/Kconfig"
 source "arch/arm/common/Kconfig"

+ 1 - 1
arch/arm/include/asm/processor.h

@@ -95,7 +95,7 @@ extern void release_thread(struct task_struct *);
 
 
 unsigned long get_wchan(struct task_struct *p);
 unsigned long get_wchan(struct task_struct *p);
 
 
-#if __LINUX_ARM_ARCH__ == 6
+#if __LINUX_ARM_ARCH__ == 6 || defined(CONFIG_ARM_ERRATA_754327)
 #define cpu_relax()			smp_mb()
 #define cpu_relax()			smp_mb()
 #else
 #else
 #define cpu_relax()			barrier()
 #define cpu_relax()			barrier()