PPC fixes for SMP; also fix the stack overflow detection, remove
[opensuse:kernel.git] / include / asm-ppc / bitops.h
1 /*
2  * BK Id: %F% %I% %G% %U% %#%
3  */
4 /*
5  * bitops.h: Bit string operations on the ppc
6  */
7
8 #ifdef __KERNEL__
9 #ifndef _PPC_BITOPS_H
10 #define _PPC_BITOPS_H
11
12 #include <linux/config.h>
13 #include <linux/compiler.h>
14 #include <asm/byteorder.h>
15 #include <asm/atomic.h>
16
17 /*
18  * The test_and_*_bit operations are taken to imply a memory barrier
19  * on SMP systems.
20  */
21 #ifdef CONFIG_SMP
22 #define SMP_WMB         "eieio\n"
23 #define SMP_MB          "\nsync"
24 #else
25 #define SMP_WMB
26 #define SMP_MB
27 #endif /* CONFIG_SMP */
28
29 /*
30  * These used to be if'd out here because using : "cc" as a constraint
31  * resulted in errors from egcs.  Things appear to be OK with gcc-2.95.
32  */
33 static __inline__ void set_bit(int nr, volatile void * addr)
34 {
35         unsigned long old;
36         unsigned long mask = 1 << (nr & 0x1f);
37         unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
38         
39         __asm__ __volatile__("\n\
40 1:      lwarx   %0,0,%3 \n\
41         or      %0,%0,%2 \n"
42         PPC405_ERR77(0,%3)
43 "       stwcx.  %0,0,%3 \n\
44         bne-    1b"
45         : "=&r" (old), "=m" (*p)
46         : "r" (mask), "r" (p), "m" (*p)
47         : "cc" );
48 }
49
50 /*
51  * non-atomic version
52  */
53 static __inline__ void __set_bit(int nr, volatile void *addr)
54 {
55         unsigned long mask = 1 << (nr & 0x1f);
56         unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
57
58         *p |= mask;
59 }
60
61 /*
62  * clear_bit doesn't imply a memory barrier
63  */
64 #define smp_mb__before_clear_bit()      smp_mb()
65 #define smp_mb__after_clear_bit()       smp_mb()
66
67 static __inline__ void clear_bit(int nr, volatile void *addr)
68 {
69         unsigned long old;
70         unsigned long mask = 1 << (nr & 0x1f);
71         unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
72
73         __asm__ __volatile__("\n\
74 1:      lwarx   %0,0,%3 \n\
75         andc    %0,%0,%2 \n"
76         PPC405_ERR77(0,%3)
77 "       stwcx.  %0,0,%3 \n\
78         bne-    1b"
79         : "=&r" (old), "=m" (*p)
80         : "r" (mask), "r" (p), "m" (*p)
81         : "cc");
82 }
83
84 /*
85  * non-atomic version
86  */
87 static __inline__ void __clear_bit(int nr, volatile void *addr)
88 {
89         unsigned long mask = 1 << (nr & 0x1f);
90         unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
91
92         *p &= ~mask;
93 }
94
95 static __inline__ void change_bit(int nr, volatile void *addr)
96 {
97         unsigned long old;
98         unsigned long mask = 1 << (nr & 0x1f);
99         unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
100
101         __asm__ __volatile__("\n\
102 1:      lwarx   %0,0,%3 \n\
103         xor     %0,%0,%2 \n"
104         PPC405_ERR77(0,%3)
105 "       stwcx.  %0,0,%3 \n\
106         bne-    1b"
107         : "=&r" (old), "=m" (*p)
108         : "r" (mask), "r" (p), "m" (*p)
109         : "cc");
110 }
111
112 /*
113  * non-atomic version
114  */
115 static __inline__ void __change_bit(int nr, volatile void *addr)
116 {
117         unsigned long mask = 1 << (nr & 0x1f);
118         unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
119
120         *p ^= mask;
121 }
122
123 /*
124  * test_and_*_bit do imply a memory barrier (?)
125  */
126 static __inline__ int test_and_set_bit(int nr, volatile void *addr)
127 {
128         unsigned int old, t;
129         unsigned int mask = 1 << (nr & 0x1f);
130         volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
131
132         __asm__ __volatile__(SMP_WMB "\n\
133 1:      lwarx   %0,0,%4 \n\
134         or      %1,%0,%3 \n"
135         PPC405_ERR77(0,%4)
136 "       stwcx.  %1,0,%4 \n\
137         bne     1b"
138         SMP_MB
139         : "=&r" (old), "=&r" (t), "=m" (*p)
140         : "r" (mask), "r" (p), "m" (*p)
141         : "cc", "memory");
142
143         return (old & mask) != 0;
144 }
145
146 /*
147  * non-atomic version
148  */
149 static __inline__ int __test_and_set_bit(int nr, volatile void *addr)
150 {
151         unsigned long mask = 1 << (nr & 0x1f);
152         unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
153         unsigned long old = *p;
154
155         *p = old | mask;
156         return (old & mask) != 0;
157 }
158
159 static __inline__ int test_and_clear_bit(int nr, volatile void *addr)
160 {
161         unsigned int old, t;
162         unsigned int mask = 1 << (nr & 0x1f);
163         volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
164
165         __asm__ __volatile__(SMP_WMB "\n\
166 1:      lwarx   %0,0,%4 \n\
167         andc    %1,%0,%3 \n"
168         PPC405_ERR77(0,%4)
169 "       stwcx.  %1,0,%4 \n\
170         bne     1b"
171         SMP_MB
172         : "=&r" (old), "=&r" (t), "=m" (*p)
173         : "r" (mask), "r" (p), "m" (*p)
174         : "cc", "memory");
175
176         return (old & mask) != 0;
177 }
178
179 /*
180  * non-atomic version
181  */
182 static __inline__ int __test_and_clear_bit(int nr, volatile void *addr)
183 {
184         unsigned long mask = 1 << (nr & 0x1f);
185         unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
186         unsigned long old = *p;
187
188         *p = old & ~mask;
189         return (old & mask) != 0;
190 }
191
192 static __inline__ int test_and_change_bit(int nr, volatile void *addr)
193 {
194         unsigned int old, t;
195         unsigned int mask = 1 << (nr & 0x1f);
196         volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
197
198         __asm__ __volatile__(SMP_WMB "\n\
199 1:      lwarx   %0,0,%4 \n\
200         xor     %1,%0,%3 \n"
201         PPC405_ERR77(0,%4)
202 "       stwcx.  %1,0,%4 \n\
203         bne     1b"
204         SMP_MB
205         : "=&r" (old), "=&r" (t), "=m" (*p)
206         : "r" (mask), "r" (p), "m" (*p)
207         : "cc", "memory");
208
209         return (old & mask) != 0;
210 }
211
212 /*
213  * non-atomic version
214  */
215 static __inline__ int __test_and_change_bit(int nr, volatile void *addr)
216 {
217         unsigned long mask = 1 << (nr & 0x1f);
218         unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
219         unsigned long old = *p;
220
221         *p = old ^ mask;
222         return (old & mask) != 0;
223 }
224
225 static __inline__ int test_bit(int nr, __const__ volatile void *addr)
226 {
227         __const__ unsigned int *p = (__const__ unsigned int *) addr;
228
229         return ((p[nr >> 5] >> (nr & 0x1f)) & 1) != 0;
230 }
231
232 /* Return the bit position of the most significant 1 bit in a word */
233 static __inline__ int __ilog2(unsigned int x)
234 {
235         int lz;
236
237         asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x));
238         return 31 - lz;
239 }
240
241 static __inline__ int ffz(unsigned int x)
242 {
243         if ((x = ~x) == 0)
244                 return 32;
245         return __ilog2(x & -x);
246 }
247
248 #ifdef __KERNEL__
249
250 static inline int __ffs(unsigned long x)
251 {
252         return __ilog2(x & -x);
253 }
254
255 /*
256  * ffs: find first bit set. This is defined the same way as
257  * the libc and compiler builtin ffs routines, therefore
258  * differs in spirit from the above ffz (man ffs).
259  */
260 static __inline__ int ffs(int x)
261 {
262         return __ilog2(x & -x) + 1;
263 }
264
265 /*
266  * hweightN: returns the hamming weight (i.e. the number
267  * of bits set) of a N-bit word
268  */
269
270 #define hweight32(x) generic_hweight32(x)
271 #define hweight16(x) generic_hweight16(x)
272 #define hweight8(x) generic_hweight8(x)
273
274 #endif /* __KERNEL__ */
275
276 /*
277  * Find the first bit set in a 140-bit bitmap.
278  * The first 100 bits are unlikely to be set.
279  */
280 static inline int sched_find_first_bit(unsigned long *b)
281 {
282         if (unlikely(b[0]))
283                 return __ffs(b[0]);
284         if (unlikely(b[1]))
285                 return __ffs(b[1]) + 32;
286         if (unlikely(b[2]))
287                 return __ffs(b[2]) + 64;
288         if (b[3])
289                 return __ffs(b[3]) + 96;
290         return __ffs(b[4]) + 128;
291 }
292
293 /**
294  * find_next_bit - find the next set bit in a memory region
295  * @addr: The address to base the search on
296  * @offset: The bitnumber to start searching at
297  * @size: The maximum size to search
298  */
299 static __inline__ unsigned long find_next_bit(void *addr,
300         unsigned long size, unsigned long offset)
301 {
302         unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
303         unsigned int result = offset & ~31UL;
304         unsigned int tmp;
305
306         if (offset >= size)
307                 return size;
308         size -= result;
309         offset &= 31UL;
310         if (offset) {
311                 tmp = *p++;
312                 tmp &= ~0UL << offset;
313                 if (size < 32)
314                         goto found_first;
315                 if (tmp)
316                         goto found_middle;
317                 size -= 32;
318                 result += 32;
319         }
320         while (size >= 32) {
321                 if ((tmp = *p++) != 0)
322                         goto found_middle;
323                 result += 32;
324                 size -= 32;
325         }
326         if (!size)
327                 return result;
328         tmp = *p;
329
330 found_first:
331         tmp &= ~0UL >> (32 - size);
332         if (tmp == 0UL)        /* Are any bits set? */
333                 return result + size; /* Nope. */
334 found_middle:
335         return result + __ffs(tmp);
336 }
337
338 /**
339  * find_first_bit - find the first set bit in a memory region
340  * @addr: The address to start the search at
341  * @size: The maximum size to search
342  *
343  * Returns the bit-number of the first set bit, not the number of the byte
344  * containing a bit.
345  */
346 #define find_first_bit(addr, size) \
347         find_next_bit((addr), (size), 0)
348
349 /*
350  * This implementation of find_{first,next}_zero_bit was stolen from
351  * Linus' asm-alpha/bitops.h.
352  */
353 #define find_first_zero_bit(addr, size) \
354         find_next_zero_bit((addr), (size), 0)
355
356 static __inline__ unsigned long find_next_zero_bit(void * addr,
357         unsigned long size, unsigned long offset)
358 {
359         unsigned int * p = ((unsigned int *) addr) + (offset >> 5);
360         unsigned int result = offset & ~31UL;
361         unsigned int tmp;
362
363         if (offset >= size)
364                 return size;
365         size -= result;
366         offset &= 31UL;
367         if (offset) {
368                 tmp = *p++;
369                 tmp |= ~0UL >> (32-offset);
370                 if (size < 32)
371                         goto found_first;
372                 if (tmp != ~0U)
373                         goto found_middle;
374                 size -= 32;
375                 result += 32;
376         }
377         while (size >= 32) {
378                 if ((tmp = *p++) != ~0U)
379                         goto found_middle;
380                 result += 32;
381                 size -= 32;
382         }
383         if (!size)
384                 return result;
385         tmp = *p;
386 found_first:
387         tmp |= ~0UL << size;
388         if (tmp == ~0UL)        /* Are any bits zero? */
389                 return result + size; /* Nope. */
390 found_middle:
391         return result + ffz(tmp);
392 }
393
394
395 #ifdef __KERNEL__
396
397 #define ext2_set_bit(nr, addr)          __test_and_set_bit((nr) ^ 0x18, addr)
398 #define ext2_clear_bit(nr, addr)        __test_and_clear_bit((nr) ^ 0x18, addr)
399
400 static __inline__ int ext2_test_bit(int nr, __const__ void * addr)
401 {
402         __const__ unsigned char *ADDR = (__const__ unsigned char *) addr;
403
404         return (ADDR[nr >> 3] >> (nr & 7)) & 1;
405 }
406
407 /*
408  * This implementation of ext2_find_{first,next}_zero_bit was stolen from
409  * Linus' asm-alpha/bitops.h and modified for a big-endian machine.
410  */
411
412 #define ext2_find_first_zero_bit(addr, size) \
413         ext2_find_next_zero_bit((addr), (size), 0)
414
415 static __inline__ unsigned long ext2_find_next_zero_bit(void *addr,
416         unsigned long size, unsigned long offset)
417 {
418         unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
419         unsigned int result = offset & ~31UL;
420         unsigned int tmp;
421
422         if (offset >= size)
423                 return size;
424         size -= result;
425         offset &= 31UL;
426         if (offset) {
427                 tmp = cpu_to_le32p(p++);
428                 tmp |= ~0UL >> (32-offset);
429                 if (size < 32)
430                         goto found_first;
431                 if (tmp != ~0U)
432                         goto found_middle;
433                 size -= 32;
434                 result += 32;
435         }
436         while (size >= 32) {
437                 if ((tmp = cpu_to_le32p(p++)) != ~0U)
438                         goto found_middle;
439                 result += 32;
440                 size -= 32;
441         }
442         if (!size)
443                 return result;
444         tmp = cpu_to_le32p(p);
445 found_first:
446         tmp |= ~0U << size;
447         if (tmp == ~0UL)        /* Are any bits zero? */
448                 return result + size; /* Nope. */
449 found_middle:
450         return result + ffz(tmp);
451 }
452
453 /* Bitmap functions for the minix filesystem.  */
454 #define minix_test_and_set_bit(nr,addr) ext2_set_bit(nr,addr)
455 #define minix_set_bit(nr,addr) ((void)ext2_set_bit(nr,addr))
456 #define minix_test_and_clear_bit(nr,addr) ext2_clear_bit(nr,addr)
457 #define minix_test_bit(nr,addr) ext2_test_bit(nr,addr)
458 #define minix_find_first_zero_bit(addr,size) ext2_find_first_zero_bit(addr,size)
459
460 #endif  /* __KERNEL__ */
461
462 #endif /* _PPC_BITOPS_H */
463 #endif /* __KERNEL__ */