MCF547X/8X cache vs TAS instruction.
Alan Gilgenbach
agilgenbach at elutions.com
Thu May 28 14:18:41 UTC 2009
Problem solved?
Sincerely,
Alan Gilgenbach
Elutions
414 918 4269
From: Mike Hench
Sent: Thursday, May 28, 2009 9:17 AM
To: coldfire-gnu-discuss at codesourcery.com
Cc: Rick Johnson; Alan Gilgenbach
Subject: MCF547X/8X cache vs TAS instruction.
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/a0d2e7b1/attachment.html>
More information about the coldfire-gnu-discuss
mailing list