Port-arm archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: OMAP2/ARM1136 cache aliasing issue



On Mon, Jul 21, 2008 at 04:21:41PM +0300, Imre Deak wrote:
> [ ... ] 
> It turns out to be a silicon bug. The errata suggests a workaround for this,
> which involves switching on partial low interrupt latency mode. How about the
> following patch?
> 

Resending it with a typo fixed.



ARM: ARM1136 r0pX cache corruption bug fix

Workaround for ARM1136 r0px errata #364296. The bug causes random
cache corruption. The workaround involves switching on partial
low interrupt latency mode, which is currently undocumented by
TRM.
---
 sys/arch/arm/arm/cpufunc.c    |   29 +++++++++++++++++++++++++++++
 sys/arch/arm/include/armreg.h |    9 +++++++++
 2 files changed, 38 insertions(+), 0 deletions(-)

diff --git a/sys/arch/arm/arm/cpufunc.c b/sys/arch/arm/arm/cpufunc.c
index b95c942..ed1ba08 100644
--- a/sys/arch/arm/arm/cpufunc.c
+++ b/sys/arch/arm/arm/cpufunc.c
@@ -2373,7 +2373,10 @@ void
 arm1136_setup(char *args)
 {
        int cpuctrl, cpuctrl_wax;
+       uint32_t auxctrl, auxctrl_wax;
+       uint32_t tmp, tmp2;
        uint32_t sbz=0;
+       uint32_t cpuid;
 
 #if defined(PROCESS_ID_IS_CURCPU)
        /* set curcpu() */
@@ -2383,6 +2386,8 @@ arm1136_setup(char *args)
         __asm("mcr\tp15, 0, %0, c13, c0, 4" : : "r"(&lwp0)); 
 #endif
 
+       cpuid = cpu_id();
+
        cpuctrl =
                CPU_CONTROL_MMU_ENABLE  |
                CPU_CONTROL_DC_ENABLE   |
@@ -2418,6 +2423,22 @@ arm1136_setup(char *args)
        if (vector_page == ARM_VECTORS_HIGH)
                cpuctrl |= CPU_CONTROL_VECRELOC;
 
+       auxctrl = 0;
+       auxctrl_wax = ~0;
+       /* This options enables the workaround for the 364296 ARM1136
+        * r0pX errata (possible cache data corruption with
+        * hit-under-miss enabled). It sets the undocumented bit 31 in
+        * the auxiliary control register and the FI bit in the control
+        * register, thus disabling hit-under-miss without putting the
+        * processor into full low interrupt latency mode. ARM11MPCore
+        * is not affected.
+        */
+       if ((cpuid & CPU_ID_CPU_MASK) == CPU_ID_ARM1136JS) { /* ARM1136JSr0pX */
+               cpuctrl |= CPU_CONTROL_FI_ENABLE;
+               auxctrl = ARM11R0_AUXCTL_PFI;
+               auxctrl_wax = ~ARM11R0_AUXCTL_PFI;
+       }
+
        /* Clear out the cache */
        cpu_idcache_wbinv_all();
 
@@ -2428,6 +2449,14 @@ arm1136_setup(char *args)
        curcpu()->ci_ctrl = cpuctrl;
        cpu_control(~cpuctrl_wax, cpuctrl);
 
+       __asm volatile ("mrc    p15, 0, %0, c1, c0, 1\n\t"
+                       "bic    %1, %0, %2\n\t"
+                       "eor    %1, %0, %3\n\t"
+                       "teq    %0, %1\n\t"
+                       "mcrne  p15, 0, %1, c1, c0, 1\n\t"
+                       : "=r"(tmp), "=r"(tmp2) :
+                         "r"(~auxctrl_wax), "r"(auxctrl));
+
        /* And again. */
        cpu_idcache_wbinv_all();
 }
diff --git a/sys/arch/arm/include/armreg.h b/sys/arch/arm/include/armreg.h
index 18170a0..055ebe0 100644
--- a/sys/arch/arm/include/armreg.h
+++ b/sys/arch/arm/include/armreg.h
@@ -292,9 +292,18 @@
 #define CPU_CONTROL_V4COMPAT   0x00008000 /* L4: ARMv4 compat LDR R15 etc */
 #define CPU_CONTROL_UNAL_ENABLE        0x00040000 /* U: unaligned data access 
*/
 #define CPU_CONTROL_XP_ENABLE  0x00080000 /* XP: extended page table */
+#define CPU_CONTROL_FI_ENABLE  0x00200000 /* FI: Low interrupt latency */
 
 #define CPU_CONTROL_IDC_ENABLE CPU_CONTROL_DC_ENABLE
 
+/* ARM11r0 Auxillary Control Register (CP15 register 1, opcode2 1) */
+#define ARM11R0_AUXCTL_PFI     0x80000000 /* PFI: partial FI mode. */
+                                          /* This is an undocumented flag
+                                           * used to work around a cache bug
+                                           * in r0 steppings. See errata
+                                           * 364296.
+                                           */
+
 /* XScale Auxillary Control Register (CP15 register 1, opcode2 1) */
 #define        XSCALE_AUXCTL_K         0x00000001 /* dis. write buffer 
coalescing */
 #define        XSCALE_AUXCTL_P         0x00000002 /* ECC protect page table 
access */
-- 
1.5.6.56.g29b0d



Home | Main Index | Thread Index | Old Index