Commit 2501cf76 authored by David Howells's avatar David Howells

m68k: Fix xchg/cmpxchg to fail to link if given an inappropriate pointer

Fix the m68k versions of xchg() and cmpxchg() to fail to link if given an
inappropriately sized pointer rather than BUG()'ing at runtime.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Acked-by: default avatarGreg Ungerer <gerg@uclinux.org>
cc: linux-m68k@lists.linux-m68k.org
parent c9034c3a
...@@ -68,6 +68,8 @@ asmlinkage void resume(void); ...@@ -68,6 +68,8 @@ asmlinkage void resume(void);
struct __xchg_dummy { unsigned long a[100]; }; struct __xchg_dummy { unsigned long a[100]; };
#define __xg(x) ((volatile struct __xchg_dummy *)(x)) #define __xg(x) ((volatile struct __xchg_dummy *)(x))
extern unsigned long __invalid_xchg_size(unsigned long, volatile void *, int);
#ifndef CONFIG_RMW_INSNS #ifndef CONFIG_RMW_INSNS
static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
{ {
...@@ -92,7 +94,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz ...@@ -92,7 +94,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
x = tmp; x = tmp;
break; break;
default: default:
BUG(); tmp = __invalid_xchg_size(x, ptr, size);
break;
} }
local_irq_restore(flags); local_irq_restore(flags);
...@@ -102,7 +105,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz ...@@ -102,7 +105,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
{ {
switch (size) { switch (size) {
case 1: case 1:
__asm__ __volatile__ __asm__ __volatile__
("moveb %2,%0\n\t" ("moveb %2,%0\n\t"
"1:\n\t" "1:\n\t"
...@@ -110,7 +113,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz ...@@ -110,7 +113,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
"jne 1b" "jne 1b"
: "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory"); : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
break; break;
case 2: case 2:
__asm__ __volatile__ __asm__ __volatile__
("movew %2,%0\n\t" ("movew %2,%0\n\t"
"1:\n\t" "1:\n\t"
...@@ -118,7 +121,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz ...@@ -118,7 +121,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
"jne 1b" "jne 1b"
: "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory"); : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
break; break;
case 4: case 4:
__asm__ __volatile__ __asm__ __volatile__
("movel %2,%0\n\t" ("movel %2,%0\n\t"
"1:\n\t" "1:\n\t"
...@@ -126,6 +129,9 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz ...@@ -126,6 +129,9 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
"jne 1b" "jne 1b"
: "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory"); : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
break; break;
default:
x = __invalid_xchg_size(x, ptr, size);
break;
} }
return x; return x;
} }
...@@ -135,6 +141,9 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz ...@@ -135,6 +141,9 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
extern unsigned long __invalid_cmpxchg_size(volatile void *,
unsigned long, unsigned long, int);
/* /*
* Atomic compare and exchange. Compare OLD with MEM, if identical, * Atomic compare and exchange. Compare OLD with MEM, if identical,
* store NEW in MEM. Return the initial value in MEM. Success is * store NEW in MEM. Return the initial value in MEM. Success is
...@@ -162,6 +171,9 @@ static inline unsigned long __cmpxchg(volatile void *p, unsigned long old, ...@@ -162,6 +171,9 @@ static inline unsigned long __cmpxchg(volatile void *p, unsigned long old,
: "=d" (old), "=m" (*(int *)p) : "=d" (old), "=m" (*(int *)p)
: "d" (new), "0" (old), "m" (*(int *)p)); : "d" (new), "0" (old), "m" (*(int *)p));
break; break;
default:
old = __invalid_cmpxchg_size(p, old, new, size);
break;
} }
return old; return old;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment