aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2012-03-28 13:30:02 -0400
committerDavid Howells <dhowells@redhat.com>2012-03-28 13:30:02 -0400
commit2501cf768e4009a06287a5ee842fd93dd4fd690e (patch)
tree06fa9a44fe28710000539d25ede65fd7e0c1f6ec
parentc9034c3a1d67486284b3b569595a4bd377aaf8cc (diff)
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: David Howells <dhowells@redhat.com> Acked-by: Greg Ungerer <gerg@uclinux.org> cc: linux-m68k@lists.linux-m68k.org
-rw-r--r--arch/m68k/include/asm/system.h20
1 files changed, 16 insertions, 4 deletions
diff --git a/arch/m68k/include/asm/system.h b/arch/m68k/include/asm/system.h
index 47b01f4726bc..a10c4d1241de 100644
--- a/arch/m68k/include/asm/system.h
+++ b/arch/m68k/include/asm/system.h
@@ -68,6 +68,8 @@ asmlinkage void resume(void);
68struct __xchg_dummy { unsigned long a[100]; }; 68struct __xchg_dummy { unsigned long a[100]; };
69#define __xg(x) ((volatile struct __xchg_dummy *)(x)) 69#define __xg(x) ((volatile struct __xchg_dummy *)(x))
70 70
71extern unsigned long __invalid_xchg_size(unsigned long, volatile void *, int);
72
71#ifndef CONFIG_RMW_INSNS 73#ifndef CONFIG_RMW_INSNS
72static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) 74static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
73{ 75{
@@ -92,7 +94,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
92 x = tmp; 94 x = tmp;
93 break; 95 break;
94 default: 96 default:
95 BUG(); 97 tmp = __invalid_xchg_size(x, ptr, size);
98 break;
96 } 99 }
97 100
98 local_irq_restore(flags); 101 local_irq_restore(flags);
@@ -102,7 +105,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
102static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) 105static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
103{ 106{
104 switch (size) { 107 switch (size) {
105 case 1: 108 case 1:
106 __asm__ __volatile__ 109 __asm__ __volatile__
107 ("moveb %2,%0\n\t" 110 ("moveb %2,%0\n\t"
108 "1:\n\t" 111 "1:\n\t"
@@ -110,7 +113,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
110 "jne 1b" 113 "jne 1b"
111 : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory"); 114 : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
112 break; 115 break;
113 case 2: 116 case 2:
114 __asm__ __volatile__ 117 __asm__ __volatile__
115 ("movew %2,%0\n\t" 118 ("movew %2,%0\n\t"
116 "1:\n\t" 119 "1:\n\t"
@@ -118,7 +121,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
118 "jne 1b" 121 "jne 1b"
119 : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory"); 122 : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
120 break; 123 break;
121 case 4: 124 case 4:
122 __asm__ __volatile__ 125 __asm__ __volatile__
123 ("movel %2,%0\n\t" 126 ("movel %2,%0\n\t"
124 "1:\n\t" 127 "1:\n\t"
@@ -126,6 +129,9 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
126 "jne 1b" 129 "jne 1b"
127 : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory"); 130 : "=&d" (x) : "d" (x), "m" (*__xg(ptr)) : "memory");
128 break; 131 break;
132 default:
133 x = __invalid_xchg_size(x, ptr, size);
134 break;
129 } 135 }
130 return x; 136 return x;
131} 137}
@@ -135,6 +141,9 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
135 141
136#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) 142#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
137 143
144extern unsigned long __invalid_cmpxchg_size(volatile void *,
145 unsigned long, unsigned long, int);
146
138/* 147/*
139 * Atomic compare and exchange. Compare OLD with MEM, if identical, 148 * Atomic compare and exchange. Compare OLD with MEM, if identical,
140 * store NEW in MEM. Return the initial value in MEM. Success is 149 * 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 : "=d" (old), "=m" (*(int *)p) 171 : "=d" (old), "=m" (*(int *)p)
163 : "d" (new), "0" (old), "m" (*(int *)p)); 172 : "d" (new), "0" (old), "m" (*(int *)p));
164 break; 173 break;
174 default:
175 old = __invalid_cmpxchg_size(p, old, new, size);
176 break;
165 } 177 }
166 return old; 178 return old;
167} 179}