MCF547X/8X cache vs TAS instruction.

Mike Hench mhench at elutions.com
Thu May 28 14:17:01 UTC 2009


The 'TAS' (test and set) instruction on the MCF548X cpu's bypasses the
cache

See section 5.5.1 of the reference manual.

 

It is used in a few places for atomic locks.

It doesn't play nice with the cache enabled.

(for some horrible reason, the cache isn't enabled by default in
freescale kernels, but that can be fixed)

 

Locks are generally cleared with a simple write

Which won't get to TAS readable (main) memory wirhout a flush.

So

 

TAS memory location --> to get a lock, main  mem now has the bit set
which may conflict with cached mem.

Write 0 to clear lock (this is now only in cache, main  mem still has
lock bit set)

TAS again to get a new lock and it see's the old bit in main mem since
the cache has not been flushed to write the clear.

The cache cannot be flushed/invalidated from user space because it uses
privileged instructions.

 

So the symptom is a hang waiting for a spinlock.

 

'bset' does a very similar thing however it is not SMP safe

I don't see how that matters, who builds SMP boxes out of
microcontrollers anyway?

Bset is used for atomic locking in many places in the m68k code.

 

 

Anyway this fixes the problem: (at least the ones I have seen)

 

diff -aur
glibc-linuxthreads-2.5.orig/linuxthreads/sysdeps/m68k/pspinlock.c
glibc-linuxthreads-2.5/linuxthreads/sysdeps/m68k/pspinlock.c

--- glibc-linuxthreads-2.5.orig/linuxthreads/sysdeps/m68k/pspinlock.c
2008-09-24 08:41:10.000000000 -0500

+++ glibc-linuxthreads-2.5/linuxthreads/sysdeps/m68k/pspinlock.c
2009-05-26 16:37:17.000000000 -0500

@@ -28,7 +28,7 @@

   unsigned int val;

 

   do

-    asm volatile ("tas %1; sne %0"

+    asm volatile ("bset.b #7, %1; sne %0"

              : "=dm" (val), "=m" (*lock)

              : "m" (*lock)

              : "cc");

@@ -44,7 +44,7 @@

 {

   unsigned int val;

 

-  asm volatile ("tas %1; sne %0"

+  asm volatile ("bset.b #7, %1; sne %0"

            : "=dm" (val), "=m" (*lock)

            : "m" (*lock)

            : "cc");

diff -aur
glibc-linuxthreads-2.5.orig/linuxthreads/sysdeps/m68k/pt-machine.h
glibc-linuxthreads-2.5/linuxthreads/sysdeps/m68k/pt-machine.h

--- glibc-linuxthreads-2.5.orig/linuxthreads/sysdeps/m68k/pt-machine.h
2008-09-24 08:41:10.000000000 -0500

+++ glibc-linuxthreads-2.5/linuxthreads/sysdeps/m68k/pt-machine.h
2009-05-26 16:36:25.000000000 -0500

@@ -37,7 +37,7 @@

 {

   char ret;

 

-  __asm__ __volatile__("tas %1; sne %0"

+  __asm__ __volatile__("bset.b #7, %1; sne %0"

        : "=dm"(ret), "=m"(*spinlock)

        : "m"(*spinlock)

        : "cc");

 

 

diff -aur gcc-4.3.orig/libstdc++-v3/config/cpu/m68k/atomicity.h
gcc-4.3/libstdc++-v3/config/cpu/m68k/atomicity.h

--- gcc-4.3.orig/libstdc++-v3/config/cpu/m68k/atomicity.h   2008-09-24
08:22:07.000000000 -0500

+++ gcc-4.3/libstdc++-v3/config/cpu/m68k/atomicity.h  2009-05-27
10:18:28.000000000 -0500

@@ -89,14 +89,14 @@

     _Atomic_word __result;

     

     // bset with no immediate addressing (not SMP-safe)

-#if defined(__mcfisaa__) || defined(__mcfisaaplus__)

+#if defined(__mcfisaa__) || defined(__mcfisaaplus__) ||
defined(__mcfisab__)

     __asm__ __volatile__("1: bset.b #7,%0@\n\tjbne 1b"

                   : /* no outputs */

                   : "a"(&_Atomicity_lock<0>::_S_atomicity_lock)

                   : "cc", "memory");

     

     // CPU32 and CF ISAs B & C support test-and-set (SMP-safe).

-#elif defined(__mcpu32__) || defined(__mcfisab__) || defined
(__mcfisac__)

+#elif defined(__mcpu32__) || defined (__mcfisac__)

     __asm__ __volatile__("1: tas %0\n\tjbne 1b"

                   : "+m"(_Atomicity_lock<0>::_S_atomicity_lock)

                   : /* none */

 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://sourcerytools.com/pipermail/coldfire-gnu-discuss/attachments/20090528/9c55c259/attachment.html>


More information about the coldfire-gnu-discuss mailing list