diff options
| author | Matthew Wilcox <willy@debian.org> | 2003-09-08 23:38:49 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.osdl.org> | 2003-09-08 23:38:49 -0700 |
| commit | 36eaa6e4c0e0b6950136b956b72fd08155b92ca3 (patch) | |
| tree | bcdb3628f3d6256b5603cf7c3788d606ed16bac0 /include | |
| parent | 8b318c7cccb30852fc5b4b34f936dcccafdf7889 (diff) | |
[PATCH] PA-RISC update for 2.6.0-test5
PA-RISC updates for 2.6.0-test5.
Contributions from Paul Bame, James Bottomley, Randolph Chung, Helge
Deller, Grant Grundler, LaMont Jones, Matthew Wilcox
Diffstat (limited to 'include')
| -rw-r--r-- | include/asm-parisc/atomic.h | 17 | ||||
| -rw-r--r-- | include/asm-parisc/bitops.h | 109 | ||||
| -rw-r--r-- | include/asm-parisc/byteorder.h | 50 | ||||
| -rw-r--r-- | include/asm-parisc/cacheflush.h | 5 | ||||
| -rw-r--r-- | include/asm-parisc/elf.h | 1 | ||||
| -rw-r--r-- | include/asm-parisc/hil.h | 26 | ||||
| -rw-r--r-- | include/asm-parisc/io.h | 7 | ||||
| -rw-r--r-- | include/asm-parisc/local.h | 40 | ||||
| -rw-r--r-- | include/asm-parisc/sections.h | 7 | ||||
| -rw-r--r-- | include/asm-parisc/uaccess.h | 17 |
10 files changed, 177 insertions, 102 deletions
diff --git a/include/asm-parisc/atomic.h b/include/asm-parisc/atomic.h index d50c506dd8a4..808373512d6c 100644 --- a/include/asm-parisc/atomic.h +++ b/include/asm-parisc/atomic.h @@ -49,27 +49,14 @@ extern spinlock_t __atomic_hash[ATOMIC_HASH_SIZE]; * Cache-line alignment would conflict with, for example, linux/module.h */ -typedef struct { - volatile int counter; -} atomic_t; +typedef struct { volatile long counter; } atomic_t; -/* -** xchg/cmpxchg moved from asm/system.h - ggg -*/ - -#if 1 /* This should get optimized out since it's never called. ** Or get a link error if xchg is used "wrong". */ extern void __xchg_called_with_bad_pointer(void); -#else -static inline void __xchg_called_with_bad_pointer(void) -{ - extern void panic(const char * fmt, ...); - panic("xchg called with bad pointer"); -} -#endif + /* __xchg32/64 defined in arch/parisc/lib/bitops.c */ extern unsigned long __xchg8(char, char *); diff --git a/include/asm-parisc/bitops.h b/include/asm-parisc/bitops.h index 711e7d154afa..51f4871ac6ce 100644 --- a/include/asm-parisc/bitops.h +++ b/include/asm-parisc/bitops.h @@ -203,55 +203,102 @@ static __inline__ int test_bit(int nr, const void *address) return !!(*addr & mask); } -extern __inline__ unsigned long ffz(unsigned long word) -{ - unsigned long result; - - result = 0; - while (word & 1) { - result++; - word >>= 1; - } - - return result; -} - #ifdef __KERNEL__ /** - * __ffs - find first bit in word. + * __ffs - find first bit in word. returns 0 to "BITS_PER_LONG-1". * @word: The word to search * - * Undefined if no bit exists, so code should check against 0 first. + * __ffs() return is undefined if no bit is set. + * + * 32-bit fast __ffs by LaMont Jones "lamont At hp com". + * 64-bit enhancement by Grant Grundler "grundler At parisc-linux org". + * (with help from willy/jejb to get the semantics right) + * + * This algorithm avoids branches by making use of nullification. + * One side effect of "extr" instructions is it sets PSW[N] bit. + * How PSW[N] (nullify next insn) gets set is determined by the + * "condition" field (eg "<>" or "TR" below) in the extr* insn. + * Only the 1st and one of either the 2cd or 3rd insn will get executed. + * Each set of 3 insn will get executed in 2 cycles on PA8x00 vs 16 or so + * cycles for each mispredicted branch. */ -static __inline__ unsigned long __ffs(unsigned long word) -{ - unsigned long result = 0; - while (!(word & 1UL)) { - result++; - word >>= 1; - } - return result; +static __inline__ unsigned long __ffs(unsigned long x) +{ + unsigned long ret; + + __asm__( +#if BITS_PER_LONG > 32 + " ldi 63,%1\n" + " extrd,u,*<> %0,63,32,%%r0\n" + " extrd,u,*TR %0,31,32,%0\n" + " addi -32,%1,%1\n" +#else + " ldi 31,%1\n" +#endif + " extru,<> %0,31,16,%%r0\n" + " extru,TR %0,15,16,%0\n" + " addi -16,%1,%1\n" + " extru,<> %0,31,8,%%r0\n" + " extru,TR %0,23,8,%0\n" + " addi -8,%1,%1\n" + " extru,<> %0,31,4,%%r0\n" + " extru,TR %0,27,4,%0\n" + " addi -4,%1,%1\n" + " extru,<> %0,31,2,%%r0\n" + " extru,TR %0,29,2,%0\n" + " addi -2,%1,%1\n" + " extru,= %0,31,1,%%r0\n" + " addi -1,%1,%1\n" + : "+r" (x), "=r" (ret) ); + return ret; } +/* Undefined if no bit is zero. */ +#define ffz(x) __ffs(~x) + /* - * ffs: find first bit set. This is defined the same way as - * the libc and compiler builtin ffs routines, therefore - * differs in spirit from the above ffz (man ffs). + * ffs: find first bit set. returns 1 to BITS_PER_LONG or 0 (if none set) + * This is defined the same way as the libc and compiler builtin + * ffs routines, therefore differs in spirit from the above ffz (man ffs). */ static __inline__ int ffs(int x) { - if (!x) - return 0; - return __ffs((unsigned long)x); + return x ? (__ffs((unsigned long)x) + 1) : 0; } /* - * fls: find last bit set. + * fls: find last (most significant) bit set. + * fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. */ -#define fls(x) generic_fls(x) +static __inline__ int fls(int x) +{ + int ret; + if (!x) + return 0; + + __asm__( + " ldi 1,%1\n" + " extru,<> %0,15,16,%%r0\n" + " zdep,TR %0,15,16,%0\n" /* xxxx0000 */ + " addi 16,%1,%1\n" + " extru,<> %0,7,8,%%r0\n" + " zdep,TR %0,23,24,%0\n" /* xx000000 */ + " addi 8,%1,%1\n" + " extru,<> %0,3,4,%%r0\n" + " zdep,TR %0,27,28,%0\n" /* x0000000 */ + " addi 4,%1,%1\n" + " extru,<> %0,1,2,%%r0\n" + " zdep,TR %0,29,30,%0\n" /* y0000000 (y&3 = 0 */ + " addi 2,%1,%1\n" + " extru,= %0,0,1,%%r0\n" + " addi 1,%1,%1\n" /* if y & 8, add 1 */ + : "+r" (x), "=r" (ret) ); + + return ret; +} /* * hweightN: returns the hamming weight (i.e. the number diff --git a/include/asm-parisc/byteorder.h b/include/asm-parisc/byteorder.h index 9ddeab1777a5..352b3146f7b0 100644 --- a/include/asm-parisc/byteorder.h +++ b/include/asm-parisc/byteorder.h @@ -5,6 +5,25 @@ #ifdef __GNUC__ +static __inline__ __const__ __u16 ___arch__swab16(__u16 x) +{ + __asm__("dep %0, 15, 8, %0\n\t" /* deposit 00ab -> 0bab */ + "shd %%r0, %0, 8, %0" /* shift 000000ab -> 00ba */ + : "=r" (x) + : "0" (x)); + return x; +} + +static __inline__ __const__ __u32 ___arch__swab24(__u32 x) +{ + __asm__("shd %0, %0, 8, %0\n\t" /* shift xabcxabc -> cxab */ + "dep %0, 15, 8, %0\n\t" /* deposit cxab -> cbab */ + "shd %%r0, %0, 8, %0" /* shift 0000cbab -> 0cba */ + : "=r" (x) + : "0" (x)); + return x; +} + static __inline__ __const__ __u32 ___arch__swab32(__u32 x) { unsigned int temp; @@ -39,34 +58,21 @@ static __inline__ __const__ __u64 ___arch__swab64(__u64 x) { return x; } #define __arch__swab64(x) ___arch__swab64(x) -#else +#define __BYTEORDER_HAS_U64__ +#elif !defined(__STRICT_ANSI__) static __inline__ __const__ __u64 ___arch__swab64(__u64 x) { - __u32 t1 = (__u32) x; - __u32 t2 = (__u32) ((x) >> 32); - ___arch__swab32(t1); - ___arch__swab32(t2); - return (((__u64) t1 << 32) + ((__u64) t2)); + __u32 t1 = ___arch__swab32((__u32) x); + __u32 t2 = ___arch__swab32((__u32) (x >> 32)); + return (((__u64) t1 << 32) | t2); } +#define __arch__swab64(x) ___arch__swab64(x) +#define __BYTEORDER_HAS_U64__ #endif - -static __inline__ __const__ __u16 ___arch__swab16(__u16 x) -{ - __asm__("dep %0, 15, 8, %0\n\t" /* deposit 00ab -> 0bab */ - "shd %r0, %0, 8, %0" /* shift 000000ab -> 00ba */ - : "=r" (x) - : "0" (x)); - return x; -} - -#define __arch__swab32(x) ___arch__swab32(x) #define __arch__swab16(x) ___arch__swab16(x) - -#if !defined(__STRICT_ANSI__) || defined(__KERNEL__) -# define __BYTEORDER_HAS_U64__ -# define __SWAB_64_THRU_32__ -#endif +#define __arch__swab24(x) ___arch__swab24(x) +#define __arch__swab32(x) ___arch__swab32(x) #endif /* __GNUC__ */ diff --git a/include/asm-parisc/cacheflush.h b/include/asm-parisc/cacheflush.h index 5392339e549b..b88200337cca 100644 --- a/include/asm-parisc/cacheflush.h +++ b/include/asm-parisc/cacheflush.h @@ -78,8 +78,9 @@ static inline void flush_dcache_page(struct page *page) #define flush_icache_range(s,e) do { flush_kernel_dcache_range_asm(s,e); flush_kernel_icache_range_asm(s,e); } while (0) -#define flush_icache_user_range(vma, page, addr, len) \ - flush_icache_page((vma), (page)) +#define flush_icache_user_range(vma, page, addr, len) do { \ + flush_user_dcache_range(addr, addr + len); \ + flush_user_icache_range(addr, addr + len); } while (0) static inline void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) diff --git a/include/asm-parisc/elf.h b/include/asm-parisc/elf.h index b9f6090b78f2..a01e946dfc57 100644 --- a/include/asm-parisc/elf.h +++ b/include/asm-parisc/elf.h @@ -283,6 +283,7 @@ struct pt_regs; /* forward declaration... */ */ #define ELF_DATA ELFDATA2MSB #define ELF_ARCH EM_PARISC +#define ELF_OSABI ELFOSABI_LINUX /* %r23 is set by ld.so to a pointer to a function which might be registered using atexit. This provides a mean for the dynamic diff --git a/include/asm-parisc/hil.h b/include/asm-parisc/hil.h deleted file mode 100644 index 97cd5553f22f..000000000000 --- a/include/asm-parisc/hil.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _ASM_HIL_H -#define _ASM_HIL_H - -/* - * linux/asm-parisc/hil.h - * - * (c) 1999 Matthew Wilcox - */ - -extern unsigned long hil_base; /* declared in drivers/parisc/hil.c */ -extern unsigned int hil_irq; - -#define HILBASE hil_base /* 0xf0821000 (old) or 0xf0201000 (new) */ -#define HIL_DATA 0x800 -#define HIL_CMD 0x801 - -#define HIL_IRQ hil_irq - -#define hil_busy() (gsc_readb(HILBASE + HIL_CMD) & HIL_BUSY) -#define hil_data_available() (gsc_readb(HILBASE + HIL_CMD) & HIL_DATA_RDY) -#define hil_status() (gsc_readb(HILBASE + HIL_CMD)) -#define hil_command(x) do { gsc_writeb((x), HILBASE + HIL_CMD); } while (0) -#define hil_read_data() (gsc_readb(HILBASE + HIL_DATA)) -#define hil_write_data(x) do { gsc_writeb((x), HILBASE + HIL_DATA); } while (0) - -#endif diff --git a/include/asm-parisc/io.h b/include/asm-parisc/io.h index 69933ab23159..0350f0198995 100644 --- a/include/asm-parisc/io.h +++ b/include/asm-parisc/io.h @@ -291,4 +291,11 @@ extern void outsl (unsigned long port, const void *src, unsigned long count); #define dma_cache_wback(_start,_size) do { flush_kernel_dcache_range(_start,_size); } while (0) #define dma_cache_wback_inv(_start,_size) do { flush_kernel_dcache_range(_start,_size); } while (0) +/* PA machines have an MM I/O space from 0xf0000000-0xffffffff in 32 + * bit mode and from 0xfffffffff0000000-0xfffffffffffffff in 64 bit + * mode (essentially just sign extending. This macro takes in a 32 + * bit I/O address (still with the leading f) and outputs the correct + * value for either 32 or 64 bit mode */ +#define F_EXTEND(x) ((unsigned long)((x) | (0xffffffff00000000ULL))) + #endif diff --git a/include/asm-parisc/local.h b/include/asm-parisc/local.h new file mode 100644 index 000000000000..892b3b2c4962 --- /dev/null +++ b/include/asm-parisc/local.h @@ -0,0 +1,40 @@ +#ifndef _ARCH_PARISC_LOCAL_H +#define _ARCH_PARISC_LOCAL_H + +#include <linux/percpu.h> +#include <asm/atomic.h> + +typedef atomic_t local_t; + +#define LOCAL_INIT(i) ATOMIC_INIT(i) +#define local_read(v) atomic_read(v) +#define local_set(v,i) atomic_set(v,i) + +#define local_inc(v) atomic_inc(v) +#define local_dec(v) atomic_dec(v) +#define local_add(i, v) atomic_add(i, v) +#define local_sub(i, v) atomic_sub(i, v) + +#define __local_inc(v) ((v)->counter++) +#define __local_dec(v) ((v)->counter--) +#define __local_add(i,v) ((v)->counter+=(i)) +#define __local_sub(i,v) ((v)->counter-=(i)) + +/* Use these for per-cpu local_t variables: on some archs they are + * much more efficient than these naive implementations. Note they take + * a variable, not an address. + */ +#define cpu_local_read(v) local_read(&__get_cpu_var(v)) +#define cpu_local_set(v, i) local_set(&__get_cpu_var(v), (i)) + +#define cpu_local_inc(v) local_inc(&__get_cpu_var(v)) +#define cpu_local_dec(v) local_dec(&__get_cpu_var(v)) +#define cpu_local_add(i, v) local_add((i), &__get_cpu_var(v)) +#define cpu_local_sub(i, v) local_sub((i), &__get_cpu_var(v)) + +#define __cpu_local_inc(v) __local_inc(&__get_cpu_var(v)) +#define __cpu_local_dec(v) __local_dec(&__get_cpu_var(v)) +#define __cpu_local_add(i, v) __local_add((i), &__get_cpu_var(v)) +#define __cpu_local_sub(i, v) __local_sub((i), &__get_cpu_var(v)) + +#endif /* _ARCH_PARISC_LOCAL_H */ diff --git a/include/asm-parisc/sections.h b/include/asm-parisc/sections.h new file mode 100644 index 000000000000..fdd43ec42ec5 --- /dev/null +++ b/include/asm-parisc/sections.h @@ -0,0 +1,7 @@ +#ifndef _PARISC_SECTIONS_H +#define _PARISC_SECTIONS_H + +/* nothing to see, move along */ +#include <asm-generic/sections.h> + +#endif diff --git a/include/asm-parisc/uaccess.h b/include/asm-parisc/uaccess.h index 8bd1067c4a50..cc9e311cabd1 100644 --- a/include/asm-parisc/uaccess.h +++ b/include/asm-parisc/uaccess.h @@ -28,6 +28,11 @@ * that put_user is the same as __put_user, etc. */ +extern int __get_kernel_bad(void); +extern int __get_user_bad(void); +extern int __put_kernel_bad(void); +extern int __put_user_bad(void); + #define access_ok(type,addr,size) (1) #define verify_area(type,addr,size) (0) @@ -35,8 +40,8 @@ #define get_user __get_user #if BITS_PER_LONG == 32 -#define LDD_KERNEL(ptr) BUG() -#define LDD_USER(ptr) BUG() +#define LDD_KERNEL(ptr) __get_kernel_bad(); +#define LDD_USER(ptr) __get_user_bad(); #define STD_KERNEL(x, ptr) __put_kernel_asm64((u32)x,ptr) #define STD_USER(x, ptr) __put_user_asm64((u32)x,ptr) #else @@ -72,7 +77,7 @@ struct exception_table_entry { case 2: __get_kernel_asm("ldh",ptr); break; \ case 4: __get_kernel_asm("ldw",ptr); break; \ case 8: LDD_KERNEL(ptr); break; \ - default: BUG(); break; \ + default: __get_kernel_bad(); break; \ } \ } \ else { \ @@ -81,7 +86,7 @@ struct exception_table_entry { case 2: __get_user_asm("ldh",ptr); break; \ case 4: __get_user_asm("ldw",ptr); break; \ case 8: LDD_USER(ptr); break; \ - default: BUG(); break; \ + default: __get_user_bad(); break; \ } \ } \ \ @@ -141,7 +146,7 @@ struct exception_table_entry { case 2: __put_kernel_asm("sth",x,ptr); break; \ case 4: __put_kernel_asm("stw",x,ptr); break; \ case 8: STD_KERNEL(x,ptr); break; \ - default: BUG(); break; \ + default: __put_kernel_bad(); break; \ } \ } \ else { \ @@ -150,7 +155,7 @@ struct exception_table_entry { case 2: __put_user_asm("sth",x,ptr); break; \ case 4: __put_user_asm("stw",x,ptr); break; \ case 8: STD_USER(x,ptr); break; \ - default: BUG(); break; \ + default: __put_user_bad(); break; \ } \ } \ \ |
