diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-17 00:20:36 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-17 00:20:36 +0200 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /include/asm-ppc64 | |
download | linux-1da177e4c3f41524e886b7f1b8a0c1fc7321cac2.tar.xz linux-1da177e4c3f41524e886b7f1b8a0c1fc7321cac2.zip |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'include/asm-ppc64')
166 files changed, 16954 insertions, 0 deletions
diff --git a/include/asm-ppc64/8253pit.h b/include/asm-ppc64/8253pit.h new file mode 100644 index 000000000000..285f78488ccb --- /dev/null +++ b/include/asm-ppc64/8253pit.h @@ -0,0 +1,10 @@ +/* + * 8253/8254 Programmable Interval Timer + */ + +#ifndef _8253PIT_H +#define _8253PIT_H + +#define PIT_TICK_RATE 1193182UL + +#endif diff --git a/include/asm-ppc64/a.out.h b/include/asm-ppc64/a.out.h new file mode 100644 index 000000000000..802338efcb19 --- /dev/null +++ b/include/asm-ppc64/a.out.h @@ -0,0 +1,41 @@ +#ifndef __PPC64_A_OUT_H__ +#define __PPC64_A_OUT_H__ + +#include <asm/ppcdebug.h> + +/* + * c 2001 PPC 64 Team, IBM Corp + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +struct exec +{ + unsigned long a_info; /* Use macros N_MAGIC, etc for access */ + unsigned a_text; /* length of text, in bytes */ + unsigned a_data; /* length of data, in bytes */ + unsigned a_bss; /* length of uninitialized data area for file, in bytes */ + unsigned a_syms; /* length of symbol table data in file, in bytes */ + unsigned a_entry; /* start address */ + unsigned a_trsize; /* length of relocation info for text, in bytes */ + unsigned a_drsize; /* length of relocation info for data, in bytes */ +}; + +#define N_TRSIZE(a) ((a).a_trsize) +#define N_DRSIZE(a) ((a).a_drsize) +#define N_SYMSIZE(a) ((a).a_syms) + +#ifdef __KERNEL__ + +#define STACK_TOP_USER64 TASK_SIZE_USER64 +#define STACK_TOP_USER32 TASK_SIZE_USER32 + +#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \ + STACK_TOP_USER32 : STACK_TOP_USER64) + +#endif /* __KERNEL__ */ + +#endif /* __PPC64_A_OUT_H__ */ diff --git a/include/asm-ppc64/abs_addr.h b/include/asm-ppc64/abs_addr.h new file mode 100644 index 000000000000..6d4e8e787058 --- /dev/null +++ b/include/asm-ppc64/abs_addr.h @@ -0,0 +1,108 @@ +#ifndef _ABS_ADDR_H +#define _ABS_ADDR_H + +#include <linux/config.h> + +/* + * c 2001 PPC 64 Team, IBM Corp + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <asm/types.h> +#include <asm/page.h> +#include <asm/prom.h> +#include <asm/lmb.h> + +typedef u32 msChunks_entry; +struct msChunks { + unsigned long num_chunks; + unsigned long chunk_size; + unsigned long chunk_shift; + unsigned long chunk_mask; + msChunks_entry *abs; +}; + +extern struct msChunks msChunks; + +extern unsigned long msChunks_alloc(unsigned long, unsigned long, unsigned long); +extern unsigned long reloc_offset(void); + +#ifdef CONFIG_MSCHUNKS + +static inline unsigned long +chunk_to_addr(unsigned long chunk) +{ + unsigned long offset = reloc_offset(); + struct msChunks *_msChunks = PTRRELOC(&msChunks); + + return chunk << _msChunks->chunk_shift; +} + +static inline unsigned long +addr_to_chunk(unsigned long addr) +{ + unsigned long offset = reloc_offset(); + struct msChunks *_msChunks = PTRRELOC(&msChunks); + + return addr >> _msChunks->chunk_shift; +} + +static inline unsigned long +chunk_offset(unsigned long addr) +{ + unsigned long offset = reloc_offset(); + struct msChunks *_msChunks = PTRRELOC(&msChunks); + + return addr & _msChunks->chunk_mask; +} + +static inline unsigned long +abs_chunk(unsigned long pchunk) +{ + unsigned long offset = reloc_offset(); + struct msChunks *_msChunks = PTRRELOC(&msChunks); + if ( pchunk >= _msChunks->num_chunks ) { + return pchunk; + } + return PTRRELOC(_msChunks->abs)[pchunk]; +} + +/* A macro so it can take pointers or unsigned long. */ +#define phys_to_abs(pa) \ + ({ unsigned long _pa = (unsigned long)(pa); \ + chunk_to_addr(abs_chunk(addr_to_chunk(_pa))) + chunk_offset(_pa); \ + }) + +static inline unsigned long +physRpn_to_absRpn(unsigned long rpn) +{ + unsigned long pa = rpn << PAGE_SHIFT; + unsigned long aa = phys_to_abs(pa); + return (aa >> PAGE_SHIFT); +} + +/* A macro so it can take pointers or unsigned long. */ +#define abs_to_phys(aa) lmb_abs_to_phys((unsigned long)(aa)) + +#else /* !CONFIG_MSCHUNKS */ + +#define chunk_to_addr(chunk) ((unsigned long)(chunk)) +#define addr_to_chunk(addr) (addr) +#define chunk_offset(addr) (0) +#define abs_chunk(pchunk) (pchunk) + +#define phys_to_abs(pa) (pa) +#define physRpn_to_absRpn(rpn) (rpn) +#define abs_to_phys(aa) (aa) + +#endif /* !CONFIG_MSCHUNKS */ + +/* Convenience macros */ +#define virt_to_abs(va) phys_to_abs(__pa(va)) +#define abs_to_virt(aa) __va(abs_to_phys(aa)) + +#endif /* _ABS_ADDR_H */ diff --git a/include/asm-ppc64/agp.h b/include/asm-ppc64/agp.h new file mode 100644 index 000000000000..be27cfa8c5b0 --- /dev/null +++ b/include/asm-ppc64/agp.h @@ -0,0 +1,13 @@ +#ifndef AGP_H +#define AGP_H 1 + +#include <asm/io.h> + +/* nothing much needed here */ + +#define map_page_into_agp(page) +#define unmap_page_from_agp(page) +#define flush_agp_mappings() +#define flush_agp_cache() mb() + +#endif diff --git a/include/asm-ppc64/atomic.h b/include/asm-ppc64/atomic.h new file mode 100644 index 000000000000..0e5f25e83bc0 --- /dev/null +++ b/include/asm-ppc64/atomic.h @@ -0,0 +1,197 @@ +/* + * PowerPC64 atomic operations + * + * Copyright (C) 2001 Paul Mackerras <paulus@au.ibm.com>, IBM + * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_PPC64_ATOMIC_H_ +#define _ASM_PPC64_ATOMIC_H_ + +#include <asm/memory.h> + +typedef struct { volatile int counter; } atomic_t; + +#define ATOMIC_INIT(i) { (i) } + +#define atomic_read(v) ((v)->counter) +#define atomic_set(v,i) (((v)->counter) = (i)) + +static __inline__ void atomic_add(int a, atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%3 # atomic_add\n\ + add %0,%2,%0\n\ + stwcx. %0,0,%3\n\ + bne- 1b" + : "=&r" (t), "=m" (v->counter) + : "r" (a), "r" (&v->counter), "m" (v->counter) + : "cc"); +} + +static __inline__ int atomic_add_return(int a, atomic_t *v) +{ + int t; + + __asm__ __volatile__( + EIEIO_ON_SMP +"1: lwarx %0,0,%2 # atomic_add_return\n\ + add %0,%1,%0\n\ + stwcx. %0,0,%2\n\ + bne- 1b" + ISYNC_ON_SMP + : "=&r" (t) + : "r" (a), "r" (&v->counter) + : "cc", "memory"); + + return t; +} + +#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) + +static __inline__ void atomic_sub(int a, atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%3 # atomic_sub\n\ + subf %0,%2,%0\n\ + stwcx. %0,0,%3\n\ + bne- 1b" + : "=&r" (t), "=m" (v->counter) + : "r" (a), "r" (&v->counter), "m" (v->counter) + : "cc"); +} + +static __inline__ int atomic_sub_return(int a, atomic_t *v) +{ + int t; + + __asm__ __volatile__( + EIEIO_ON_SMP +"1: lwarx %0,0,%2 # atomic_sub_return\n\ + subf %0,%1,%0\n\ + stwcx. %0,0,%2\n\ + bne- 1b" + ISYNC_ON_SMP + : "=&r" (t) + : "r" (a), "r" (&v->counter) + : "cc", "memory"); + + return t; +} + +static __inline__ void atomic_inc(atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%2 # atomic_inc\n\ + addic %0,%0,1\n\ + stwcx. %0,0,%2\n\ + bne- 1b" + : "=&r" (t), "=m" (v->counter) + : "r" (&v->counter), "m" (v->counter) + : "cc"); +} + +static __inline__ int atomic_inc_return(atomic_t *v) +{ + int t; + + __asm__ __volatile__( + EIEIO_ON_SMP +"1: lwarx %0,0,%1 # atomic_inc_return\n\ + addic %0,%0,1\n\ + stwcx. %0,0,%1\n\ + bne- 1b" + ISYNC_ON_SMP + : "=&r" (t) + : "r" (&v->counter) + : "cc", "memory"); + + return t; +} + +/* + * atomic_inc_and_test - increment and test + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1 + * and returns true if the result is zero, or false for all + * other cases. + */ +#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) + +static __inline__ void atomic_dec(atomic_t *v) +{ + int t; + + __asm__ __volatile__( +"1: lwarx %0,0,%2 # atomic_dec\n\ + addic %0,%0,-1\n\ + stwcx. %0,0,%2\n\ + bne- 1b" + : "=&r" (t), "=m" (v->counter) + : "r" (&v->counter), "m" (v->counter) + : "cc"); +} + +static __inline__ int atomic_dec_return(atomic_t *v) +{ + int t; + + __asm__ __volatile__( + EIEIO_ON_SMP +"1: lwarx %0,0,%1 # atomic_dec_return\n\ + addic %0,%0,-1\n\ + stwcx. %0,0,%1\n\ + bne- 1b" + ISYNC_ON_SMP + : "=&r" (t) + : "r" (&v->counter) + : "cc", "memory"); + + return t; +} + +#define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0) +#define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0) + +/* + * Atomically test *v and decrement if it is greater than 0. + * The function returns the old value of *v minus 1. + */ +static __inline__ int atomic_dec_if_positive(atomic_t *v) +{ + int t; + + __asm__ __volatile__( + EIEIO_ON_SMP +"1: lwarx %0,0,%1 # atomic_dec_if_positive\n\ + addic. %0,%0,-1\n\ + blt- 2f\n\ + stwcx. %0,0,%1\n\ + bne- 1b" + ISYNC_ON_SMP + "\n\ +2:" : "=&r" (t) + : "r" (&v->counter) + : "cc", "memory"); + + return t; +} + +#define smp_mb__before_atomic_dec() smp_mb() +#define smp_mb__after_atomic_dec() smp_mb() +#define smp_mb__before_atomic_inc() smp_mb() +#define smp_mb__after_atomic_inc() smp_mb() + +#endif /* _ASM_PPC64_ATOMIC_H_ */ diff --git a/include/asm-ppc64/bitops.h b/include/asm-ppc64/bitops.h new file mode 100644 index 000000000000..a0f831224f96 --- /dev/null +++ b/include/asm-ppc64/bitops.h @@ -0,0 +1,360 @@ +/* + * PowerPC64 atomic bit operations. + * Dave Engebretsen, Todd Inglett, Don Reed, Pat McCarthy, Peter Bergner, + * Anton Blanchard + * + * Originally taken from the 32b PPC code. Modified to use 64b values for + * the various counters & memory references. + * + * Bitops are odd when viewed on big-endian systems. They were designed + * on little endian so the size of the bitset doesn't matter (low order bytes + * come first) as long as the bit in question is valid. + * + * Bits are "tested" often using the C expression (val & (1<<nr)) so we do + * our best to stay compatible with that. The assumption is that val will + * be unsigned long for such tests. As such, we assume the bits are stored + * as an array of unsigned long (the usual case is a single unsigned long, + * of course). Here's an example bitset with bit numbering: + * + * |63..........0|127........64|195.......128|255.......196| + * + * This leads to a problem. If an int, short or char is passed as a bitset + * it will be a bad memory reference since we want to store in chunks + * of unsigned long (64 bits here) size. + * + * There are a few little-endian macros used mostly for filesystem bitmaps, + * these work on similar bit arrays layouts, but byte-oriented: + * + * |7...0|15...8|23...16|31...24|39...32|47...40|55...48|63...56| + * + * The main difference is that bit 3-5 in the bit number field needs to be + * reversed compared to the big-endian bit fields. This can be achieved + * by XOR with 0b111000 (0x38). + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _PPC64_BITOPS_H +#define _PPC64_BITOPS_H + +#ifdef __KERNEL__ + +#include <asm/memory.h> + +/* + * clear_bit doesn't imply a memory barrier + */ +#define smp_mb__before_clear_bit() smp_mb() +#define smp_mb__after_clear_bit() smp_mb() + +static __inline__ int test_bit(unsigned long nr, __const__ volatile unsigned long *addr) +{ + return (1UL & (addr[nr >> 6] >> (nr & 63))); +} + +static __inline__ void set_bit(unsigned long nr, volatile unsigned long *addr) +{ + unsigned long old; + unsigned long mask = 1UL << (nr & 0x3f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 6); + + __asm__ __volatile__( +"1: ldarx %0,0,%3 # set_bit\n\ + or %0,%0,%2\n\ + stdcx. %0,0,%3\n\ + bne- 1b" + : "=&r" (old), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) + : "cc"); +} + +static __inline__ void clear_bit(unsigned long nr, volatile unsigned long *addr) +{ + unsigned long old; + unsigned long mask = 1UL << (nr & 0x3f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 6); + + __asm__ __volatile__( +"1: ldarx %0,0,%3 # clear_bit\n\ + andc %0,%0,%2\n\ + stdcx. %0,0,%3\n\ + bne- 1b" + : "=&r" (old), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) + : "cc"); +} + +static __inline__ void change_bit(unsigned long nr, volatile unsigned long *addr) +{ + unsigned long old; + unsigned long mask = 1UL << (nr & 0x3f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 6); + + __asm__ __volatile__( +"1: ldarx %0,0,%3 # change_bit\n\ + xor %0,%0,%2\n\ + stdcx. %0,0,%3\n\ + bne- 1b" + : "=&r" (old), "=m" (*p) + : "r" (mask), "r" (p), "m" (*p) + : "cc"); +} + +static __inline__ int test_and_set_bit(unsigned long nr, volatile unsigned long *addr) +{ + unsigned long old, t; + unsigned long mask = 1UL << (nr & 0x3f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 6); + + __asm__ __volatile__( + EIEIO_ON_SMP +"1: ldarx %0,0,%3 # test_and_set_bit\n\ + or %1,%0,%2 \n\ + stdcx. %1,0,%3 \n\ + bne- 1b" + ISYNC_ON_SMP + : "=&r" (old), "=&r" (t) + : "r" (mask), "r" (p) + : "cc", "memory"); + + return (old & mask) != 0; +} + +static __inline__ int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr) +{ + unsigned long old, t; + unsigned long mask = 1UL << (nr & 0x3f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 6); + + __asm__ __volatile__( + EIEIO_ON_SMP +"1: ldarx %0,0,%3 # test_and_clear_bit\n\ + andc %1,%0,%2\n\ + stdcx. %1,0,%3\n\ + bne- 1b" + ISYNC_ON_SMP + : "=&r" (old), "=&r" (t) + : "r" (mask), "r" (p) + : "cc", "memory"); + + return (old & mask) != 0; +} + +static __inline__ int test_and_change_bit(unsigned long nr, volatile unsigned long *addr) +{ + unsigned long old, t; + unsigned long mask = 1UL << (nr & 0x3f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 6); + + __asm__ __volatile__( + EIEIO_ON_SMP +"1: ldarx %0,0,%3 # test_and_change_bit\n\ + xor %1,%0,%2\n\ + stdcx. %1,0,%3\n\ + bne- 1b" + ISYNC_ON_SMP + : "=&r" (old), "=&r" (t) + : "r" (mask), "r" (p) + : "cc", "memory"); + + return (old & mask) != 0; +} + +static __inline__ void set_bits(unsigned long mask, unsigned long *addr) +{ + unsigned long old; + + __asm__ __volatile__( +"1: ldarx %0,0,%3 # set_bit\n\ + or %0,%0,%2\n\ + stdcx. %0,0,%3\n\ + bne- 1b" + : "=&r" (old), "=m" (*addr) + : "r" (mask), "r" (addr), "m" (*addr) + : "cc"); +} + +/* + * non-atomic versions + */ +static __inline__ void __set_bit(unsigned long nr, volatile unsigned long *addr) +{ + unsigned long mask = 1UL << (nr & 0x3f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 6); + + *p |= mask; +} + +static __inline__ void __clear_bit(unsigned long nr, volatile unsigned long *addr) +{ + unsigned long mask = 1UL << (nr & 0x3f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 6); + + *p &= ~mask; +} + +static __inline__ void __change_bit(unsigned long nr, volatile unsigned long *addr) +{ + unsigned long mask = 1UL << (nr & 0x3f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 6); + + *p ^= mask; +} + +static __inline__ int __test_and_set_bit(unsigned long nr, volatile unsigned long *addr) +{ + unsigned long mask = 1UL << (nr & 0x3f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 6); + unsigned long old = *p; + + *p = old | mask; + return (old & mask) != 0; +} + +static __inline__ int __test_and_clear_bit(unsigned long nr, volatile unsigned long *addr) +{ + unsigned long mask = 1UL << (nr & 0x3f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 6); + unsigned long old = *p; + + *p = old & ~mask; + return (old & mask) != 0; +} + +static __inline__ int __test_and_change_bit(unsigned long nr, volatile unsigned long *addr) +{ + unsigned long mask = 1UL << (nr & 0x3f); + unsigned long *p = ((unsigned long *)addr) + (nr >> 6); + unsigned long old = *p; + + *p = old ^ mask; + return (old & mask) != 0; +} + +/* + * Return the zero-based bit position (from RIGHT TO LEFT, 63 -> 0) of the + * most significant (left-most) 1-bit in a double word. + */ +static __inline__ int __ilog2(unsigned long x) +{ + int lz; + + asm ("cntlzd %0,%1" : "=r" (lz) : "r" (x)); + return 63 - lz; +} + +/* + * Determines the bit position of the least significant (rightmost) 0 bit + * in the specified double word. The returned bit position will be zero-based, + * starting from the right side (63 - 0). + */ +static __inline__ unsigned long ffz(unsigned long x) +{ + /* no zero exists anywhere in the 8 byte area. */ + if ((x = ~x) == 0) + return 64; + + /* + * Calculate the bit position of the least signficant '1' bit in x + * (since x has been changed this will actually be the least signficant + * '0' bit in * the original x). Note: (x & -x) gives us a mask that + * is the least significant * (RIGHT-most) 1-bit of the value in x. + */ + return __ilog2(x & -x); +} + +static __inline__ int __ffs(unsigned long x) +{ + return __ilog2(x & -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). + */ +static __inline__ int ffs(int x) +{ + unsigned long i = (unsigned long)x; + return __ilog2(i & -i) + 1; +} + +/* + * fls: find last (most-significant) bit set. + * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. + */ +#define fls(x) generic_fls(x) + +/* + * hweightN: returns the hamming weight (i.e. the number + * of bits set) of a N-bit word + */ +#define hweight64(x) generic_hweight64(x) +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) + +extern unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, unsigned long offset); +#define find_first_zero_bit(addr, size) \ + find_next_zero_bit((addr), (size), 0) + +extern unsigned long find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset); +#define find_first_bit(addr, size) \ + find_next_bit((addr), (size), 0) + +extern unsigned long find_next_zero_le_bit(const unsigned long *addr, unsigned long size, unsigned long offset); +#define find_first_zero_le_bit(addr, size) \ + find_next_zero_le_bit((addr), (size), 0) + +static __inline__ int test_le_bit(unsigned long nr, __const__ unsigned long * addr) +{ + __const__ unsigned char *ADDR = (__const__ unsigned char *) addr; + return (ADDR[nr >> 3] >> (nr & 7)) & 1; +} + +#define test_and_clear_le_bit(nr, addr) \ + test_and_clear_bit((nr) ^ 0x38, (addr)) +#define test_and_set_le_bit(nr, addr) \ + test_and_set_bit((nr) ^ 0x38, (addr)) + +/* + * non-atomic versions + */ + +#define __set_le_bit(nr, addr) \ + __set_bit((nr) ^ 0x38, (addr)) +#define __clear_le_bit(nr, addr) \ + __clear_bit((nr) ^ 0x38, (addr)) +#define __test_and_clear_le_bit(nr, addr) \ + __test_and_clear_bit((nr) ^ 0x38, (addr)) +#define __test_and_set_le_bit(nr, addr) \ + __test_and_set_bit((nr) ^ 0x38, (addr)) + +#define ext2_set_bit(nr,addr) \ + __test_and_set_le_bit((nr), (unsigned long*)addr) +#define ext2_clear_bit(nr, addr) \ + __test_and_clear_le_bit((nr), (unsigned long*)addr) + +#define ext2_set_bit_atomic(lock, nr, addr) \ + test_and_set_le_bit((nr), (unsigned long*)addr) +#define ext2_clear_bit_atomic(lock, nr, addr) \ + test_and_clear_le_bit((nr), (unsigned long*)addr) + + +#define ext2_test_bit(nr, addr) test_le_bit((nr),(unsigned long*)addr) +#define ext2_find_first_zero_bit(addr, size) \ + find_first_zero_le_bit((unsigned long*)addr, size) +#define ext2_find_next_zero_bit(addr, size, off) \ + find_next_zero_le_bit((unsigned long*)addr, size, off) + +#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr) +#define minix_set_bit(nr,addr) set_bit(nr,addr) +#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr) +#define minix_test_bit(nr,addr) test_bit(nr,addr) +#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) + +#endif /* __KERNEL__ */ +#endif /* _PPC64_BITOPS_H */ diff --git a/include/asm-ppc64/bootinfo.h b/include/asm-ppc64/bootinfo.h new file mode 100644 index 000000000000..f55e7cb48f46 --- /dev/null +++ b/include/asm-ppc64/bootinfo.h @@ -0,0 +1,70 @@ +/* + * Non-machine dependent bootinfo structure. Basic idea + * borrowed from the m68k. + * + * Copyright (C) 1999 Cort Dougan <cort@ppc.kernel.org> + * Copyright (c) 2001 PPC64 Team, IBM Corp + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + + +#ifndef _PPC64_BOOTINFO_H +#define _PPC64_BOOTINFO_H + +#include <asm/types.h> + +/* We use a u32 for the type of the fields since they're written by + * the bootloader which is a 32-bit process and read by the kernel + * which is a 64-bit process. This way they can both agree on the + * size of the type. + */ +typedef u32 bi_rec_field; + +struct bi_record { + bi_rec_field tag; /* tag ID */ + bi_rec_field size; /* size of record (in bytes) */ + bi_rec_field data[0]; /* data */ +}; + +#define BI_FIRST 0x1010 /* first record - marker */ +#define BI_LAST 0x1011 /* last record - marker */ +#define BI_CMD_LINE 0x1012 +#define BI_BOOTLOADER_ID 0x1013 +#define BI_INITRD 0x1014 +#define BI_SYSMAP 0x1015 +#define BI_MACHTYPE 0x1016 + +static __inline__ struct bi_record * bi_rec_init(unsigned long addr) +{ + struct bi_record *bi_recs; + bi_recs = (struct bi_record *)_ALIGN(addr, PAGE_SIZE); + bi_recs->size = 0; + return bi_recs; +} + +static __inline__ struct bi_record * bi_rec_alloc(struct bi_record *rec, + unsigned long args) +{ + rec = (struct bi_record *)((unsigned long)rec + rec->size); + rec->size = sizeof(struct bi_record) + args*sizeof(bi_rec_field); + return rec; +} + +static __inline__ struct bi_record * bi_rec_alloc_bytes(struct bi_record *rec, + unsigned long bytes) +{ + rec = (struct bi_record *)((unsigned long)rec + rec->size); + rec->size = sizeof(struct bi_record) + bytes; + return rec; +} + +static __inline__ struct bi_record * bi_rec_next(struct bi_record *rec) +{ + return (struct bi_record *)((unsigned long)rec + rec->size); +} + +#endif /* _PPC64_BOOTINFO_H */ diff --git a/include/asm-ppc64/btext.h b/include/asm-ppc64/btext.h new file mode 100644 index 000000000000..67aef0cc72c0 --- /dev/null +++ b/include/asm-ppc64/btext.h @@ -0,0 +1,26 @@ +/* + * Definitions for using the procedures in btext.c. + * + * Benjamin Herrenschmidt <benh@kernel.crashing.org> + */ +#ifndef __PPC_BTEXT_H +#define __PPC_BTEXT_H +#ifdef __KERNEL__ + +extern void btext_clearscreen(void); +extern void btext_flushscreen(void); + +extern int boot_text_mapped; + +extern int btext_initialize(struct device_node *np); + +extern void map_boot_text(void); +extern void btext_update_display(unsigned long phys, int width, int height, + int depth, int pitch); + +extern void btext_drawchar(char c); +extern void btext_drawstring(const char *str); +extern void btext_drawhex(unsigned long v); + +#endif /* __KERNEL__ */ +#endif /* __PPC_BTEXT_H */ diff --git a/include/asm-ppc64/bug.h b/include/asm-ppc64/bug.h new file mode 100644 index 000000000000..db31dd22233c --- /dev/null +++ b/include/asm-ppc64/bug.h @@ -0,0 +1,65 @@ +#ifndef _PPC64_BUG_H +#define _PPC64_BUG_H + +/* + * Define an illegal instr to trap on the bug. + * We don't use 0 because that marks the end of a function + * in the ELF ABI. That's "Boo Boo" in case you wonder... + */ +#define BUG_OPCODE .long 0x00b00b00 /* For asm */ +#define BUG_ILLEGAL_INSTR "0x00b00b00" /* For BUG macro */ + +#ifndef __ASSEMBLY__ + +struct bug_entry { + unsigned long bug_addr; + long line; + const char *file; + const char *function; +}; + +struct bug_entry *find_bug(unsigned long bugaddr); + +/* + * If this bit is set in the line number it means that the trap + * is for WARN_ON rather than BUG or BUG_ON. + */ +#define BUG_WARNING_TRAP 0x1000000 + +#define BUG() do { \ + __asm__ __volatile__( \ + "1: twi 31,0,0\n" \ + ".section __bug_table,\"a\"\n\t" \ + " .llong 1b,%0,%1,%2\n" \ + ".previous" \ + : : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \ +} while (0) + +#define BUG_ON(x) do { \ + __asm__ __volatile__( \ + "1: tdnei %0,0\n" \ + ".section __bug_table,\"a\"\n\t" \ + " .llong 1b,%1,%2,%3\n" \ + ".previous" \ + : : "r" (x), "i" (__LINE__), "i" (__FILE__), \ + "i" (__FUNCTION__)); \ +} while (0) + +#define WARN_ON(x) do { \ + __asm__ __volatile__( \ + "1: tdnei %0,0\n" \ + ".section __bug_table,\"a\"\n\t" \ + " .llong 1b,%1,%2,%3\n" \ + ".previous" \ + : : "r" (x), "i" (__LINE__ + BUG_WARNING_TRAP), \ + "i" (__FILE__), "i" (__FUNCTION__)); \ +} while (0) + +#endif + +#define HAVE_ARCH_BUG +#define HAVE_ARCH_BUG_ON +#define HAVE_ARCH_WARN_ON +#include <asm-generic/bug.h> + +#endif diff --git a/include/asm-ppc64/bugs.h b/include/asm-ppc64/bugs.h new file mode 100644 index 000000000000..861074b3cf71 --- /dev/null +++ b/include/asm-ppc64/bugs.h @@ -0,0 +1,12 @@ +/* + * This file is included by 'init/main.c' to check for architecture-dependent + * bugs. + * + */ +#ifndef _ASM_PPC64_BUGS_H +#define _ASM_PPC64_BUGS_H + +static void check_bugs(void) { +} + +#endif /* _ASM_PPC64_BUGS_H */ diff --git a/include/asm-ppc64/byteorder.h b/include/asm-ppc64/byteorder.h new file mode 100644 index 000000000000..80327532de64 --- /dev/null +++ b/include/asm-ppc64/byteorder.h @@ -0,0 +1,96 @@ +#ifndef _PPC64_BYTEORDER_H +#define _PPC64_BYTEORDER_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <asm/types.h> +#include <linux/compiler.h> + +#ifdef __GNUC__ +#ifdef __KERNEL__ + +static __inline__ __u16 ld_le16(const volatile __u16 *addr) +{ + __u16 val; + + __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr)); + return val; +} + +static __inline__ void st_le16(volatile __u16 *addr, const __u16 val) +{ + __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); +} + +static __inline__ __u32 ld_le32(const volatile __u32 *addr) +{ + __u32 val; + + __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr)); + return val; +} + +static __inline__ void st_le32(volatile __u32 *addr, const __u32 val) +{ + __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); +} + +#if 0 +static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 value) +{ + __u16 result; + + __asm__("rlwimi %0,%1,8,16,23" + : "=r" (result) + : "r" (value), "0" (value >> 8)); + return result; +} + +static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 value) +{ + __u32 result; + + __asm__("rlwimi %0,%1,24,16,23\n\t" + "rlwimi %0,%1,8,8,15\n\t" + "rlwimi %0,%1,24,0,7" + : "=r" (result) + : "r" (value), "0" (value >> 24)); + return result; +} + +static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 value) +{ + __u64 result; +#error implement me +} + +#define __arch__swab16(x) ___arch__swab16(x) +#define __arch__swab32(x) ___arch__swab32(x) +#define __arch__swab64(x) ___arch__swab64(x) + +#endif + +/* The same, but returns converted value from the location pointer by addr. */ +#define __arch__swab16p(addr) ld_le16(addr) +#define __arch__swab32p(addr) ld_le32(addr) + +/* The same, but do the conversion in situ, ie. put the value back to addr. */ +#define __arch__swab16s(addr) st_le16(addr,*addr) +#define __arch__swab32s(addr) st_le32(addr,*addr) + +#endif /* __KERNEL__ */ + +#ifndef __STRICT_ANSI__ +#define __BYTEORDER_HAS_U64__ +#endif + +#endif /* __GNUC__ */ + +#include <linux/byteorder/big_endian.h> + +#endif /* _PPC64_BYTEORDER_H */ diff --git a/include/asm-ppc64/cache.h b/include/asm-ppc64/cache.h new file mode 100644 index 000000000000..92140a7efbd1 --- /dev/null +++ b/include/asm-ppc64/cache.h @@ -0,0 +1,36 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef __ARCH_PPC64_CACHE_H +#define __ARCH_PPC64_CACHE_H + +#include <asm/types.h> + +/* bytes per L1 cache line */ +#define L1_CACHE_SHIFT 7 +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) + +#define SMP_CACHE_BYTES L1_CACHE_BYTES +#define L1_CACHE_SHIFT_MAX 7 /* largest L1 which this arch supports */ + +#ifndef __ASSEMBLY__ + +struct ppc64_caches { + u32 dsize; /* L1 d-cache size */ + u32 dline_size; /* L1 d-cache line size */ + u32 log_dline_size; + u32 dlines_per_page; + u32 isize; /* L1 i-cache size */ + u32 iline_size; /* L1 i-cache line size */ + u32 log_iline_size; + u32 ilines_per_page; +}; + +extern struct ppc64_caches ppc64_caches; + +#endif + +#endif diff --git a/include/asm-ppc64/cacheflush.h b/include/asm-ppc64/cacheflush.h new file mode 100644 index 000000000000..ffbc08be8e52 --- /dev/null +++ b/include/asm-ppc64/cacheflush.h @@ -0,0 +1,48 @@ +#ifndef _PPC64_CACHEFLUSH_H +#define _PPC64_CACHEFLUSH_H + +#include <linux/mm.h> +#include <asm/cputable.h> + +/* + * No cache flushing is required when address mappings are + * changed, because the caches on PowerPCs are physically + * addressed. + */ +#define flush_cache_all() do { } while (0) +#define flush_cache_mm(mm) do { } while (0) +#define flush_cache_range(vma, start, end) do { } while (0) +#define flush_cache_page(vma, vmaddr, pfn) do { } while (0) +#define flush_icache_page(vma, page) do { } while (0) +#define flush_cache_vmap(start, end) do { } while (0) +#define flush_cache_vunmap(start, end) do { } while (0) + +extern void flush_dcache_page(struct page *page); +#define flush_dcache_mmap_lock(mapping) do { } while (0) +#define flush_dcache_mmap_unlock(mapping) do { } while (0) + +extern void __flush_icache_range(unsigned long, unsigned long); +extern void flush_icache_user_range(struct vm_area_struct *vma, + struct page *page, unsigned long addr, + int len); + +extern void flush_dcache_range(unsigned long start, unsigned long stop); +extern void flush_dcache_phys_range(unsigned long start, unsigned long stop); +extern void flush_inval_dcache_range(unsigned long start, unsigned long stop); + +#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ +do { memcpy(dst, src, len); \ + flush_icache_user_range(vma, page, vaddr, len); \ +} while (0) +#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ + memcpy(dst, src, len) + +extern void __flush_dcache_icache(void *page_va); + +static inline void flush_icache_range(unsigned long start, unsigned long stop) +{ + if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) + __flush_icache_range(start, stop); +} + +#endif /* _PPC64_CACHEFLUSH_H */ diff --git a/include/asm-ppc64/checksum.h b/include/asm-ppc64/checksum.h new file mode 100644 index 000000000000..d22d4469de43 --- /dev/null +++ b/include/asm-ppc64/checksum.h @@ -0,0 +1,107 @@ +#ifndef _PPC64_CHECKSUM_H +#define _PPC64_CHECKSUM_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +/* + * This is a version of ip_compute_csum() optimized for IP headers, + * which always checksum on 4 octet boundaries. ihl is the number + * of 32-bit words and is always >= 5. + */ +extern unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl); + +/* + * computes the checksum of the TCP/UDP pseudo-header + * returns a 16-bit checksum, already complemented + */ +extern unsigned short csum_tcpudp_magic(unsigned long saddr, + unsigned long daddr, + unsigned short len, + unsigned short proto, + unsigned int sum); + +/* + * computes the checksum of a memory block at buff, length len, + * and adds in "sum" (32-bit) + * + * returns a 32-bit number suitable for feeding into itself + * or csum_tcpudp_magic + * + * this function must be called with even lengths, except + * for the last fragment, which may be odd + * + * it's best to have buff aligned on a 32-bit boundary + */ +extern unsigned int csum_partial(const unsigned char * buff, int len, + unsigned int sum); + +/* + * the same as csum_partial, but copies from src to dst while it + * checksums + */ +extern unsigned int csum_partial_copy_generic(const char *src, char *dst, + int len, unsigned int sum, + int *src_err, int *dst_err); +/* + * the same as csum_partial, but copies from src to dst while it + * checksums. + */ + +unsigned int csum_partial_copy_nocheck(const char *src, + char *dst, + int len, + unsigned int sum); + +/* + * turns a 32-bit partial checksum (e.g. from csum_partial) into a + * 1's complement 16-bit checksum. + */ +static inline unsigned int csum_fold(unsigned int sum) +{ + unsigned int tmp; + + /* swap the two 16-bit halves of sum */ + __asm__("rlwinm %0,%1,16,0,31" : "=r" (tmp) : "r" (sum)); + /* if there is a carry from adding the two 16-bit halves, + it will carry from the lower half into the upper half, + giving us the correct sum in the upper half. */ + sum = ~(sum + tmp) >> 16; + return sum; +} + +/* + * this routine is used for miscellaneous IP-like checksums, mainly + * in icmp.c + */ +static inline unsigned short ip_compute_csum(unsigned char * buff, int len) +{ + return csum_fold(csum_partial(buff, len, 0)); +} + +#define csum_partial_copy_from_user(src, dst, len, sum, errp) \ + csum_partial_copy_generic((src), (dst), (len), (sum), (errp), NULL) + +#define csum_partial_copy_nocheck(src, dst, len, sum) \ + csum_partial_copy_generic((src), (dst), (len), (sum), NULL, NULL) + +static inline u32 csum_tcpudp_nofold(u32 saddr, + u32 daddr, + unsigned short len, + unsigned short proto, + unsigned int sum) +{ + unsigned long s = sum; + + s += saddr; + s += daddr; + s += (proto << 16) + len; + s += (s >> 32); + return (u32) s; +} + +#endif diff --git a/include/asm-ppc64/compat.h b/include/asm-ppc64/compat.h new file mode 100644 index 000000000000..09c28d28ce6c --- /dev/null +++ b/include/asm-ppc64/compat.h @@ -0,0 +1,202 @@ +#ifndef _ASM_PPC64_COMPAT_H +#define _ASM_PPC64_COMPAT_H +/* + * Architecture specific compatibility types + */ +#include <linux/types.h> +#include <linux/sched.h> + +#define COMPAT_USER_HZ 100 + +typedef u32 compat_size_t; +typedef s32 compat_ssize_t; +typedef s32 compat_time_t; +typedef s32 compat_clock_t; +typedef s32 compat_pid_t; +typedef u32 compat_uid_t; +typedef u32 compat_gid_t; +typedef u32 compat_mode_t; +typedef u32 compat_ino_t; +typedef u32 compat_dev_t; +typedef s32 compat_off_t; +typedef s64 compat_loff_t; +typedef s16 compat_nlink_t; +typedef u16 compat_ipc_pid_t; +typedef s32 compat_daddr_t; +typedef u32 compat_caddr_t; +typedef __kernel_fsid_t compat_fsid_t; +typedef s32 compat_key_t; + +typedef s32 compat_int_t; +typedef s32 compat_long_t; +typedef u32 compat_uint_t; +typedef u32 compat_ulong_t; + +struct compat_timespec { + compat_time_t tv_sec; + s32 tv_nsec; +}; + +struct compat_timeval { + compat_time_t tv_sec; + s32 tv_usec; +}; + +struct compat_stat { + compat_dev_t st_dev; + compat_ino_t st_ino; + compat_mode_t st_mode; + compat_nlink_t st_nlink; + compat_uid_t st_uid; + compat_gid_t st_gid; + compat_dev_t st_rdev; + compat_off_t st_size; + compat_off_t st_blksize; + compat_off_t st_blocks; + compat_time_t st_atime; + u32 st_atime_nsec; + compat_time_t st_mtime; + u32 st_mtime_nsec; + compat_time_t st_ctime; + u32 st_ctime_nsec; + u32 __unused4[2]; +}; + +struct compat_flock { + short l_type; + short l_whence; + compat_off_t l_start; + compat_off_t l_len; + compat_pid_t l_pid; +}; + +#define F_GETLK64 12 /* using 'struct flock64' */ +#define F_SETLK64 13 +#define F_SETLKW64 14 + +struct compat_flock64 { + short l_type; + short l_whence; + compat_loff_t l_start; + compat_loff_t l_len; + compat_pid_t l_pid; +}; + +struct compat_statfs { + int f_type; + int f_bsize; + int f_blocks; + int f_bfree; + int f_bavail; + int f_files; + int f_ffree; + compat_fsid_t f_fsid; + int f_namelen; /* SunOS ignores this field. */ + int f_frsize; + int f_spare[5]; +}; + +#define COMPAT_RLIM_OLD_INFINITY 0x7fffffff +#define COMPAT_RLIM_INFINITY 0xffffffff + +typedef u32 compat_old_sigset_t; + +#define _COMPAT_NSIG 64 +#define _COMPAT_NSIG_BPW 32 + +typedef u32 compat_sigset_word; + +#define COMPAT_OFF_T_MAX 0x7fffffff +#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL + +/* + * A pointer passed in from user mode. This should not + * be used for syscall parameters, just declare them + * as pointers because the syscall entry code will have + * appropriately comverted them already. + */ +typedef u32 compat_uptr_t; + +static inline void __user *compat_ptr(compat_uptr_t uptr) +{ + return (void __user *)(unsigned long)uptr; +} + +static inline void __user *compat_alloc_user_space(long len) +{ + struct pt_regs *regs = current->thread.regs; + unsigned long usp = regs->gpr[1]; + + /* + * We cant access below the stack pointer in the 32bit ABI and + * can access 288 bytes in the 64bit ABI + */ + if (!(test_thread_flag(TIF_32BIT))) + usp -= 288; + + return (void __user *) (usp - len); +} + +/* + * ipc64_perm is actually 32/64bit clean but since the compat layer refers to + * it we may as well define it. + */ +struct compat_ipc64_perm { + compat_key_t key; + compat_uid_t uid; + compat_gid_t gid; + compat_uid_t cuid; + compat_gid_t cgid; + compat_mode_t mode; + unsigned int seq; + unsigned int __pad2; + unsigned long __unused1; /* yes they really are 64bit pads */ + unsigned long __unused2; +}; + +struct compat_semid64_ds { + struct compat_ipc64_perm sem_perm; + unsigned int __unused1; + compat_time_t sem_otime; + unsigned int __unused2; + compat_time_t sem_ctime; + compat_ulong_t sem_nsems; + compat_ulong_t __unused3; + compat_ulong_t __unused4; +}; + +struct compat_msqid64_ds { + struct compat_ipc64_perm msg_perm; + unsigned int __unused1; + compat_time_t msg_stime; + unsigned int __unused2; + compat_time_t msg_rtime; + unsigned int __unused3; + compat_time_t msg_ctime; + compat_ulong_t msg_cbytes; + compat_ulong_t msg_qnum; + compat_ulong_t msg_qbytes; + compat_pid_t msg_lspid; + compat_pid_t msg_lrpid; + compat_ulong_t __unused4; + compat_ulong_t __unused5; +}; + +struct compat_shmid64_ds { + struct compat_ipc64_perm shm_perm; + unsigned int __unused1; + compat_time_t shm_atime; + unsigned int __unused2; + compat_time_t shm_dtime; + unsigned int __unused3; + compat_time_t shm_ctime; + unsigned int __unused4; + compat_size_t shm_segsz; + compat_pid_t shm_cpid; + compat_pid_t shm_lpid; + compat_ulong_t shm_nattch; + compat_ulong_t __unused5; + compat_ulong_t __unused6; +}; + +#endif /* _ASM_PPC64_COMPAT_H */ diff --git a/include/asm-ppc64/cputable.h b/include/asm-ppc64/cputable.h new file mode 100644 index 000000000000..cbbfbec78b6b --- /dev/null +++ b/include/asm-ppc64/cputable.h @@ -0,0 +1,197 @@ +/* + * include/asm-ppc64/cputable.h + * + * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org) + * + * Modifications for ppc64: + * Copyright (C) 2003 Dave Engebretsen <engebret@us.ibm.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef __ASM_PPC_CPUTABLE_H +#define __ASM_PPC_CPUTABLE_H + +#include <linux/config.h> +#include <asm/page.h> /* for ASM_CONST */ + +/* Exposed to userland CPU features - Must match ppc32 definitions */ +#define PPC_FEATURE_32 0x80000000 +#define PPC_FEATURE_64 0x40000000 +#define PPC_FEATURE_601_INSTR 0x20000000 +#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 +#define PPC_FEATURE_HAS_FPU 0x08000000 +#define PPC_FEATURE_HAS_MMU 0x04000000 +#define PPC_FEATURE_HAS_4xxMAC 0x02000000 +#define PPC_FEATURE_UNIFIED_CACHE 0x01000000 + +#ifdef __KERNEL__ + +#ifndef __ASSEMBLY__ + +/* This structure can grow, it's real size is used by head.S code + * via the mkdefs mechanism. + */ +struct cpu_spec; + +typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec); + +struct cpu_spec { + /* CPU is matched via (PVR & pvr_mask) == pvr_value */ + unsigned int pvr_mask; + unsigned int pvr_value; + + char *cpu_name; + unsigned long cpu_features; /* Kernel features */ + unsigned int cpu_user_features; /* Userland features */ + + /* cache line sizes */ + unsigned int icache_bsize; + unsigned int dcache_bsize; + + /* this is called to initialize various CPU bits like L1 cache, + * BHT, SPD, etc... from head.S before branching to identify_machine + */ + cpu_setup_t cpu_setup; + + /* This is used to identify firmware features which are available + * to the kernel. + */ + unsigned long firmware_features; +}; + +extern struct cpu_spec cpu_specs[]; +extern struct cpu_spec *cur_cpu_spec; + +static inline unsigned long cpu_has_feature(unsigned long feature) +{ + return cur_cpu_spec->cpu_features & feature; +} + + +/* firmware feature bitmask values */ +#define FIRMWARE_MAX_FEATURES 63 + +#define FW_FEATURE_PFT (1UL<<0) +#define FW_FEATURE_TCE (1UL<<1) +#define FW_FEATURE_SPRG0 (1UL<<2) +#define FW_FEATURE_DABR (1UL<<3) +#define FW_FEATURE_COPY (1UL<<4) +#define FW_FEATURE_ASR (1UL<<5) +#define FW_FEATURE_DEBUG (1UL<<6) +#define FW_FEATURE_TERM (1UL<<7) +#define FW_FEATURE_PERF (1UL<<8) +#define FW_FEATURE_DUMP (1UL<<9) +#define FW_FEATURE_INTERRUPT (1UL<<10) +#define FW_FEATURE_MIGRATE (1UL<<11) +#define FW_FEATURE_PERFMON (1UL<<12) +#define FW_FEATURE_CRQ (1UL<<13) +#define FW_FEATURE_VIO (1UL<<14) +#define FW_FEATURE_RDMA (1UL<<15) +#define FW_FEATURE_LLAN (1UL<<16) +#define FW_FEATURE_BULK (1UL<<17) +#define FW_FEATURE_XDABR (1UL<<18) +#define FW_FEATURE_MULTITCE (1UL<<19) +#define FW_FEATURE_SPLPAR (1UL<<20) + +typedef struct { + unsigned long val; + char * name; +} firmware_feature_t; + +extern firmware_feature_t firmware_features_table[]; + +#endif /* __ASSEMBLY__ */ + +/* CPU kernel features */ + +/* Retain the 32b definitions for the time being - use bottom half of word */ +#define CPU_FTR_SPLIT_ID_CACHE ASM_CONST(0x0000000000000001) +#define CPU_FTR_L2CR ASM_CONST(0x0000000000000002) +#define CPU_FTR_SPEC7450 ASM_CONST(0x0000000000000004) +#define CPU_FTR_ALTIVEC ASM_CONST(0x0000000000000008) +#define CPU_FTR_TAU ASM_CONST(0x0000000000000010) +#define CPU_FTR_CAN_DOZE ASM_CONST(0x0000000000000020) +#define CPU_FTR_USE_TB ASM_CONST(0x0000000000000040) +#define CPU_FTR_604_PERF_MON ASM_CONST(0x0000000000000080) +#define CPU_FTR_601 ASM_CONST(0x0000000000000100) +#define CPU_FTR_HPTE_TABLE ASM_CONST(0x0000000000000200) +#define CPU_FTR_CAN_NAP ASM_CONST(0x0000000000000400) +#define CPU_FTR_L3CR ASM_CONST(0x0000000000000800) +#define CPU_FTR_L3_DISABLE_NAP ASM_CONST(0x0000000000001000) +#define CPU_FTR_NAP_DISABLE_L2_PR ASM_CONST(0x0000000000002000) +#define CPU_FTR_DUAL_PLL_750FX ASM_CONST(0x0000000000004000) + +/* Add the 64b processor unique features in the top half of the word */ +#define CPU_FTR_SLB ASM_CONST(0x0000000100000000) +#define CPU_FTR_16M_PAGE ASM_CONST(0x0000000200000000) +#define CPU_FTR_TLBIEL ASM_CONST(0x0000000400000000) +#define CPU_FTR_NOEXECUTE ASM_CONST(0x0000000800000000) +#define CPU_FTR_NODSISRALIGN ASM_CONST(0x0000001000000000) +#define CPU_FTR_IABR ASM_CONST(0x0000002000000000) +#define CPU_FTR_MMCRA ASM_CONST(0x0000004000000000) +#define CPU_FTR_PMC8 ASM_CONST(0x0000008000000000) +#define CPU_FTR_SMT ASM_CONST(0x0000010000000000) +#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000020000000000) +#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0000040000000000) +#define CPU_FTR_MMCRA_SIHV ASM_CONST(0x0000080000000000) + +/* Platform firmware features */ +#define FW_FTR_ ASM_CONST(0x0000000000000001) + +#ifndef __ASSEMBLY__ +#define COMMON_USER_PPC64 (PPC_FEATURE_32 | PPC_FEATURE_64 | \ + PPC_FEATURE_HAS_FPU | PPC_FEATURE_HAS_MMU) + +#define CPU_FTR_PPCAS_ARCH_V2_BASE (CPU_FTR_SLB | \ + CPU_FTR_TLBIEL | CPU_FTR_NOEXECUTE | \ + CPU_FTR_NODSISRALIGN) + +/* iSeries doesn't support large pages */ +#ifdef CONFIG_PPC_ISERIES +#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE) +#else +#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_PPCAS_ARCH_V2_BASE | CPU_FTR_16M_PAGE) +#endif + +#define COMMON_PPC64_FW (0) +#endif + +#ifdef __ASSEMBLY__ + +#define BEGIN_FTR_SECTION 98: + +#define END_FTR_SECTION(msk, val) \ +99: \ + .section __ftr_fixup,"a"; \ + .align 3; \ + .llong msk; \ + .llong val; \ + .llong 98b; \ + .llong 99b; \ + .previous + +#else + +#define BEGIN_FTR_SECTION "98:\n" +#define END_FTR_SECTION(msk, val) \ +"99:\n" \ +" .section __ftr_fixup,\"a\";\n" \ +" .align 3;\n" \ +" .llong "#msk";\n" \ +" .llong "#val";\n" \ +" .llong 98b;\n" \ +" .llong 99b;\n" \ +" .previous\n" + +#endif /* __ASSEMBLY__ */ + +#define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk)) +#define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0) + +#endif /* __ASM_PPC_CPUTABLE_H */ +#endif /* __KERNEL__ */ + diff --git a/include/asm-ppc64/cputime.h b/include/asm-ppc64/cputime.h new file mode 100644 index 000000000000..8e9faf5ce720 --- /dev/null +++ b/include/asm-ppc64/cputime.h @@ -0,0 +1,6 @@ +#ifndef __PPC_CPUTIME_H +#define __PPC_CPUTIME_H + +#include <asm-generic/cputime.h> + +#endif /* __PPC_CPUTIME_H */ diff --git a/include/asm-ppc64/current.h b/include/asm-ppc64/current.h new file mode 100644 index 000000000000..52ddc60c8b65 --- /dev/null +++ b/include/asm-ppc64/current.h @@ -0,0 +1,16 @@ +#ifndef _PPC64_CURRENT_H +#define _PPC64_CURRENT_H + +#include <asm/paca.h> + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#define get_current() (get_paca()->__current) +#define current get_current() + +#endif /* !(_PPC64_CURRENT_H) */ diff --git a/include/asm-ppc64/dbdma.h b/include/asm-ppc64/dbdma.h new file mode 100644 index 000000000000..f2d5d5dc3377 --- /dev/null +++ b/include/asm-ppc64/dbdma.h @@ -0,0 +1,2 @@ +#include <asm-ppc/dbdma.h> + diff --git a/include/asm-ppc64/delay.h b/include/asm-ppc64/delay.h new file mode 100644 index 000000000000..05f198cf73d9 --- /dev/null +++ b/include/asm-ppc64/delay.h @@ -0,0 +1,48 @@ +#ifndef _PPC64_DELAY_H +#define _PPC64_DELAY_H + +/* + * Copyright 1996, Paul Mackerras. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * PPC64 Support added by Dave Engebretsen, Todd Inglett, Mike Corrigan, + * Anton Blanchard. + */ + +extern unsigned long tb_ticks_per_usec; + +/* define these here to prevent circular dependencies */ +#define __HMT_low() asm volatile("or 1,1,1") +#define __HMT_medium() asm volatile("or 2,2,2") +#define __barrier() asm volatile("":::"memory") + +static inline unsigned long __get_tb(void) +{ + unsigned long rval; + + asm volatile("mftb %0" : "=r" (rval)); + return rval; +} + +static inline void __delay(unsigned long loops) +{ + unsigned long start = __get_tb(); + + while((__get_tb()-start) < loops) + __HMT_low(); + __HMT_medium(); + __barrier(); +} + +static inline void udelay(unsigned long usecs) +{ + unsigned long loops = tb_ticks_per_usec * usecs; + + __delay(loops); +} + +#endif /* _PPC64_DELAY_H */ diff --git a/include/asm-ppc64/div64.h b/include/asm-ppc64/div64.h new file mode 100644 index 000000000000..6cd978cefb28 --- /dev/null +++ b/include/asm-ppc64/div64.h @@ -0,0 +1 @@ +#include <asm-generic/div64.h> diff --git a/include/asm-ppc64/dma-mapping.h b/include/asm-ppc64/dma-mapping.h new file mode 100644 index 000000000000..9ad8adee0067 --- /dev/null +++ b/include/asm-ppc64/dma-mapping.h @@ -0,0 +1,136 @@ +/* Copyright (C) 2004 IBM + * + * Implements the generic device dma API for ppc64. Handles + * the pci and vio busses + */ + +#ifndef _ASM_DMA_MAPPING_H +#define _ASM_DMA_MAPPING_H + +#include <linux/types.h> +#include <linux/cache.h> +/* need struct page definitions */ +#include <linux/mm.h> +#include <asm/scatterlist.h> +#include <asm/bug.h> + +#define DMA_ERROR_CODE (~(dma_addr_t)0x0) + +extern int dma_supported(struct device *dev, u64 mask); +extern int dma_set_mask(struct device *dev, u64 dma_mask); +extern void *dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, unsigned int __nocast flag); +extern void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, + dma_addr_t dma_handle); +extern dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, + size_t size, enum dma_data_direction direction); +extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, + size_t size, enum dma_data_direction direction); +extern dma_addr_t dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, + enum dma_data_direction direction); +extern void dma_unmap_page(struct device *dev, dma_addr_t dma_address, + size_t size, enum dma_data_direction direction); +extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction direction); +extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg, + int nhwentries, enum dma_data_direction direction); + +static inline void +dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); + /* nothing to do */ +} + +static inline void +dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); + /* nothing to do */ +} + +static inline void +dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); + /* nothing to do */ +} + +static inline void +dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); + /* nothing to do */ +} + +static inline int dma_mapping_error(dma_addr_t dma_addr) +{ + return (dma_addr == DMA_ERROR_CODE); +} + +/* Now for the API extensions over the pci_ one */ + +#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) +#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) +#define dma_is_consistent(d) (1) + +static inline int +dma_get_cache_alignment(void) +{ + /* no easy way to get cache size on all processors, so return + * the maximum possible, to be safe */ + return (1 << L1_CACHE_SHIFT_MAX); +} + +static inline void +dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); + /* nothing to do */ +} + +static inline void +dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); + /* nothing to do */ +} + +static inline void +dma_cache_sync(void *vaddr, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); + /* nothing to do */ +} + +/* + * DMA operations are abstracted for G5 vs. i/pSeries, PCI vs. VIO + */ +struct dma_mapping_ops { + void * (*alloc_coherent)(struct device *dev, size_t size, + dma_addr_t *dma_handle, unsigned int __nocast flag); + void (*free_coherent)(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle); + dma_addr_t (*map_single)(struct device *dev, void *ptr, + size_t size, enum dma_data_direction direction); + void (*unmap_single)(struct device *dev, dma_addr_t dma_addr, + size_t size, enum dma_data_direction direction); + int (*map_sg)(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction direction); + void (*unmap_sg)(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction direction); + int (*dma_supported)(struct device *dev, u64 mask); + int (*dac_dma_supported)(struct device *dev, u64 mask); +}; + +#endif /* _ASM_DMA_MAPPING_H */ diff --git a/include/asm-ppc64/dma.h b/include/asm-ppc64/dma.h new file mode 100644 index 000000000000..d693b8026bc3 --- /dev/null +++ b/include/asm-ppc64/dma.h @@ -0,0 +1,326 @@ +/* + * linux/include/asm/dma.h: Defines for using and allocating dma channels. + * Written by Hennus Bergman, 1992. + * High DMA channel support & info by Hannu Savolainen + * and John Boyd, Nov. 1992. + * Changes for ppc sound by Christoph Nadig + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_DMA_H +#define _ASM_DMA_H + +#include <linux/config.h> +#include <asm/io.h> +#include <linux/spinlock.h> +#include <asm/system.h> + +#ifndef MAX_DMA_CHANNELS +#define MAX_DMA_CHANNELS 8 +#endif + +/* The maximum address that we can perform a DMA transfer to on this platform */ +/* Doesn't really apply... */ +#define MAX_DMA_ADDRESS (~0UL) + +#define dma_outb outb +#define dma_inb inb + +/* + * NOTES about DMA transfers: + * + * controller 1: channels 0-3, byte operations, ports 00-1F + * controller 2: channels 4-7, word operations, ports C0-DF + * + * - ALL registers are 8 bits only, regardless of transfer size + * - channel 4 is not used - cascades 1 into 2. + * - channels 0-3 are byte - addresses/counts are for physical bytes + * - channels 5-7 are word - addresses/counts are for physical words + * - transfers must not cross physical 64K (0-3) or 128K (5-7) boundaries + * - transfer count loaded to registers is 1 less than actual count + * - controller 2 offsets are all even (2x offsets for controller 1) + * - page registers for 5-7 don't use data bit 0, represent 128K pages + * - page registers for 0-3 use bit 0, represent 64K pages + * + * On PReP, DMA transfers are limited to the lower 16MB of _physical_ memory. + * On CHRP, the W83C553F (and VLSI Tollgate?) support full 32 bit addressing. + * Note that addresses loaded into registers must be _physical_ addresses, + * not logical addresses (which may differ if paging is active). + * + * Address mapping for channels 0-3: + * + * A23 ... A16 A15 ... A8 A7 ... A0 (Physical addresses) + * | ... | | ... | | ... | + * | ... | | ... | | ... | + * | ... | | ... | | ... | + * P7 ... P0 A7 ... A0 A7 ... A0 + * | Page | Addr MSB | Addr LSB | (DMA registers) + * + * Address mapping for channels 5-7: + * + * A23 ... A17 A16 A15 ... A9 A8 A7 ... A1 A0 (Physical addresses) + * | ... | \ \ ... \ \ \ ... \ \ + * | ... | \ \ ... \ \ \ ... \ (not used) + * | ... | \ \ ... \ \ \ ... \ + * P7 ... P1 (0) A7 A6 ... A0 A7 A6 ... A0 + * | Page | Addr MSB | Addr LSB | (DMA registers) + * + * Again, channels 5-7 transfer _physical_ words (16 bits), so addresses + * and counts _must_ be word-aligned (the lowest address bit is _ignored_ at + * the hardware level, so odd-byte transfers aren't possible). + * + * Transfer count (_not # bytes_) is limited to 64K, represented as actual + * count - 1 : 64K => 0xFFFF, 1 => 0x0000. Thus, count is always 1 or more, + * and up to 128K bytes may be transferred on channels 5-7 in one operation. + * + */ + +/* 8237 DMA controllers */ +#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ +#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */ + +/* DMA controller registers */ +#define DMA1_CMD_REG 0x08 /* command register (w) */ +#define DMA1_STAT_REG 0x08 /* status register (r) */ +#define DMA1_REQ_REG 0x09 /* request register (w) */ +#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */ +#define DMA1_MODE_REG 0x0B /* mode register (w) */ +#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */ +#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */ +#define DMA1_RESET_REG 0x0D /* Master Clear (w) */ +#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */ +#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */ + +#define DMA2_CMD_REG 0xD0 /* command register (w) */ +#define DMA2_STAT_REG 0xD0 /* status register (r) */ +#define DMA2_REQ_REG 0xD2 /* request register (w) */ +#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */ +#define DMA2_MODE_REG 0xD6 /* mode register (w) */ +#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */ +#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */ +#define DMA2_RESET_REG 0xDA /* Master Clear (w) */ +#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */ +#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */ + +#define DMA_ADDR_0 0x00 /* DMA address registers */ +#define DMA_ADDR_1 0x02 +#define DMA_ADDR_2 0x04 +#define DMA_ADDR_3 0x06 +#define DMA_ADDR_4 0xC0 +#define DMA_ADDR_5 0xC4 +#define DMA_ADDR_6 0xC8 +#define DMA_ADDR_7 0xCC + +#define DMA_CNT_0 0x01 /* DMA count registers */ +#define DMA_CNT_1 0x03 +#define DMA_CNT_2 0x05 +#define DMA_CNT_3 0x07 +#define DMA_CNT_4 0xC2 +#define DMA_CNT_5 0xC6 +#define DMA_CNT_6 0xCA +#define DMA_CNT_7 0xCE + +#define DMA_LO_PAGE_0 0x87 /* DMA page registers */ +#define DMA_LO_PAGE_1 0x83 +#define DMA_LO_PAGE_2 0x81 +#define DMA_LO_PAGE_3 0x82 +#define DMA_LO_PAGE_5 0x8B +#define DMA_LO_PAGE_6 0x89 +#define DMA_LO_PAGE_7 0x8A + +#define DMA_HI_PAGE_0 0x487 /* DMA page registers */ +#define DMA_HI_PAGE_1 0x483 +#define DMA_HI_PAGE_2 0x481 +#define DMA_HI_PAGE_3 0x482 +#define DMA_HI_PAGE_5 0x48B +#define DMA_HI_PAGE_6 0x489 +#define DMA_HI_PAGE_7 0x48A + +#define DMA1_EXT_REG 0x40B +#define DMA2_EXT_REG 0x4D6 + +#define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */ +#define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */ +#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */ + +#define DMA_AUTOINIT 0x10 + +extern spinlock_t dma_spin_lock; + +static __inline__ unsigned long claim_dma_lock(void) +{ + unsigned long flags; + spin_lock_irqsave(&dma_spin_lock, flags); + return flags; +} + +static __inline__ void release_dma_lock(unsigned long flags) +{ + spin_unlock_irqrestore(&dma_spin_lock, flags); +} + +/* enable/disable a specific DMA channel */ +static __inline__ void enable_dma(unsigned int dmanr) +{ + unsigned char ucDmaCmd=0x00; + + if (dmanr != 4) + { + dma_outb(0, DMA2_MASK_REG); /* This may not be enabled */ + dma_outb(ucDmaCmd, DMA2_CMD_REG); /* Enable group */ + } + if (dmanr<=3) + { + dma_outb(dmanr, DMA1_MASK_REG); + dma_outb(ucDmaCmd, DMA1_CMD_REG); /* Enable group */ + } else + { + dma_outb(dmanr & 3, DMA2_MASK_REG); + } +} + +static __inline__ void disable_dma(unsigned int dmanr) +{ + if (dmanr<=3) + dma_outb(dmanr | 4, DMA1_MASK_REG); + else + dma_outb((dmanr & 3) | 4, DMA2_MASK_REG); +} + +/* Clear the 'DMA Pointer Flip Flop'. + * Write 0 for LSB/MSB, 1 for MSB/LSB access. + * Use this once to initialize the FF to a known state. + * After that, keep track of it. :-) + * --- In order to do that, the DMA routines below should --- + * --- only be used while interrupts are disabled! --- + */ +static __inline__ void clear_dma_ff(unsigned int dmanr) +{ + if (dmanr<=3) + dma_outb(0, DMA1_CLEAR_FF_REG); + else + dma_outb(0, DMA2_CLEAR_FF_REG); +} + +/* set mode (above) for a specific DMA channel */ +static __inline__ void set_dma_mode(unsigned int dmanr, char mode) +{ + if (dmanr<=3) + dma_outb(mode | dmanr, DMA1_MODE_REG); + else + dma_outb(mode | (dmanr&3), DMA2_MODE_REG); +} + +/* Set only the page register bits of the transfer address. + * This is used for successive transfers when we know the contents of + * the lower 16 bits of the DMA current address register, but a 64k boundary + * may have been crossed. + */ +static __inline__ void set_dma_page(unsigned int dmanr, int pagenr) +{ + switch(dmanr) { + case 0: + dma_outb(pagenr, DMA_LO_PAGE_0); + dma_outb(pagenr>>8, DMA_HI_PAGE_0); + break; + case 1: + dma_outb(pagenr, DMA_LO_PAGE_1); + dma_outb(pagenr>>8, DMA_HI_PAGE_1); + break; + case 2: + dma_outb(pagenr, DMA_LO_PAGE_2); + dma_outb(pagenr>>8, DMA_HI_PAGE_2); + break; + case 3: + dma_outb(pagenr, DMA_LO_PAGE_3); + dma_outb(pagenr>>8, DMA_HI_PAGE_3); + break; + case 5: + dma_outb(pagenr & 0xfe, DMA_LO_PAGE_5); + dma_outb(pagenr>>8, DMA_HI_PAGE_5); + break; + case 6: + dma_outb(pagenr & 0xfe, DMA_LO_PAGE_6); + dma_outb(pagenr>>8, DMA_HI_PAGE_6); + break; + case 7: + dma_outb(pagenr & 0xfe, DMA_LO_PAGE_7); + dma_outb(pagenr>>8, DMA_HI_PAGE_7); + break; + } +} + + +/* Set transfer address & page bits for specific DMA channel. + * Assumes dma flipflop is clear. + */ +static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int phys) +{ + if (dmanr <= 3) { + dma_outb( phys & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); + dma_outb( (phys>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); + } else { + dma_outb( (phys>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); + dma_outb( (phys>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); + } + set_dma_page(dmanr, phys>>16); +} + + +/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for + * a specific DMA channel. + * You must ensure the parameters are valid. + * NOTE: from a manual: "the number of transfers is one more + * than the initial word count"! This is taken into account. + * Assumes dma flip-flop is clear. + * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7. + */ +static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count) +{ + count--; + if (dmanr <= 3) { + dma_outb( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); + dma_outb( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); + } else { + dma_outb( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); + dma_outb( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); + } +} + + +/* Get DMA residue count. After a DMA transfer, this + * should return zero. Reading this while a DMA transfer is + * still in progress will return unpredictable results. + * If called before the channel has been used, it may return 1. + * Otherwise, it returns the number of _bytes_ left to transfer. + * + * Assumes DMA flip-flop is clear. + */ +static __inline__ int get_dma_residue(unsigned int dmanr) +{ + unsigned int io_port = (dmanr<=3)? ((dmanr&3)<<1) + 1 + IO_DMA1_BASE + : ((dmanr&3)<<2) + 2 + IO_DMA2_BASE; + + /* using short to get 16-bit wrap around */ + unsigned short count; + + count = 1 + dma_inb(io_port); + count += dma_inb(io_port) << 8; + + return (dmanr <= 3)? count : (count<<1); +} + +/* These are in kernel/dma.c: */ +extern int request_dma(unsigned int dmanr, const char * device_id); /* reserve a DMA channel */ +extern void free_dma(unsigned int dmanr); /* release it again */ + +#ifdef CONFIG_PCI +extern int isa_dma_bridge_buggy; +#else +#define isa_dma_bridge_buggy (0) +#endif +#endif /* _ASM_DMA_H */ diff --git a/include/asm-ppc64/eeh.h b/include/asm-ppc64/eeh.h new file mode 100644 index 000000000000..94298b106a4b --- /dev/null +++ b/include/asm-ppc64/eeh.h @@ -0,0 +1,383 @@ +/* + * eeh.h + * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _PPC64_EEH_H +#define _PPC64_EEH_H + +#include <linux/config.h> +#include <linux/init.h> +#include <linux/list.h> +#include <linux/string.h> + +struct pci_dev; +struct device_node; +struct device_node; +struct notifier_block; + +#ifdef CONFIG_EEH + +/* Values for eeh_mode bits in device_node */ +#define EEH_MODE_SUPPORTED (1<<0) +#define EEH_MODE_NOCHECK (1<<1) +#define EEH_MODE_ISOLATED (1<<2) + +void __init eeh_init(void); +unsigned long eeh_check_failure(const volatile void __iomem *token, + unsigned long val); +int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev); +void __init pci_addr_cache_build(void); + +/** + * eeh_add_device_early + * eeh_add_device_late + * + * Perform eeh initialization for devices added after boot. + * Call eeh_add_device_early before doing any i/o to the + * device (including config space i/o). Call eeh_add_device_late + * to finish the eeh setup for this device. + */ +void eeh_add_device_early(struct device_node *); +void eeh_add_device_late(struct pci_dev *); + +/** + * eeh_remove_device - undo EEH setup for the indicated pci device + * @dev: pci device to be removed + * + * This routine should be when a device is removed from a running + * system (e.g. by hotplug or dlpar). + */ +void eeh_remove_device(struct pci_dev *); + +#define EEH_DISABLE 0 +#define EEH_ENABLE 1 +#define EEH_RELEASE_LOADSTORE 2 +#define EEH_RELEASE_DMA 3 + +/** + * Notifier event flags. + */ +#define EEH_NOTIFY_FREEZE 1 + +/** EEH event -- structure holding pci slot data that describes + * a change in the isolation status of a PCI slot. A pointer + * to this struct is passed as the data pointer in a notify callback. + */ +struct eeh_event { + struct list_head list; + struct pci_dev *dev; + struct device_node *dn; + int reset_state; +}; + +/** Register to find out about EEH events. */ +int eeh_register_notifier(struct notifier_block *nb); +int eeh_unregister_notifier(struct notifier_block *nb); + +/** + * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure. + * + * If this macro yields TRUE, the caller relays to eeh_check_failure() + * which does further tests out of line. + */ +#define EEH_POSSIBLE_ERROR(val, type) ((val) == (type)~0) + +/* + * Reads from a device which has been isolated by EEH will return + * all 1s. This macro gives an all-1s value of the given size (in + * bytes: 1, 2, or 4) for comparing with the result of a read. + */ +#define EEH_IO_ERROR_VALUE(size) (~0U >> ((4 - (size)) * 8)) + +#else /* !CONFIG_EEH */ +static inline void eeh_init(void) { } + +static inline unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val) +{ + return val; +} + +static inline int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) +{ + return 0; +} + +static inline void pci_addr_cache_build(void) { } + +static inline void eeh_add_device_early(struct device_node *dn) { } + +static inline void eeh_add_device_late(struct pci_dev *dev) { } + +static inline void eeh_remove_device(struct pci_dev *dev) { } + +#define EEH_POSSIBLE_ERROR(val, type) (0) +#define EEH_IO_ERROR_VALUE(size) (-1UL) +#endif /* CONFIG_EEH */ + +/* + * MMIO read/write operations with EEH support. + */ +static inline u8 eeh_readb(const volatile void __iomem *addr) +{ + u8 val = in_8(addr); + if (EEH_POSSIBLE_ERROR(val, u8)) + return eeh_check_failure(addr, val); + return val; +} +static inline void eeh_writeb(u8 val, volatile void __iomem *addr) +{ + out_8(addr, val); +} + +static inline u16 eeh_readw(const volatile void __iomem *addr) +{ + u16 val = in_le16(addr); + if (EEH_POSSIBLE_ERROR(val, u16)) + return eeh_check_failure(addr, val); + return val; +} +static inline void eeh_writew(u16 val, volatile void __iomem *addr) +{ + out_le16(addr, val); +} +static inline u16 eeh_raw_readw(const volatile void __iomem *addr) +{ + u16 val = in_be16(addr); + if (EEH_POSSIBLE_ERROR(val, u16)) + return eeh_check_failure(addr, val); + return val; +} +static inline void eeh_raw_writew(u16 val, volatile void __iomem *addr) { + volatile u16 __iomem *vaddr = (volatile u16 __iomem *) addr; + out_be16(vaddr, val); +} + +static inline u32 eeh_readl(const volatile void __iomem *addr) +{ + u32 val = in_le32(addr); + if (EEH_POSSIBLE_ERROR(val, u32)) + return eeh_check_failure(addr, val); + return val; +} +static inline void eeh_writel(u32 val, volatile void __iomem *addr) +{ + out_le32(addr, val); +} +static inline u32 eeh_raw_readl(const volatile void __iomem *addr) +{ + u32 val = in_be32(addr); + if (EEH_POSSIBLE_ERROR(val, u32)) + return eeh_check_failure(addr, val); + return val; +} +static inline void eeh_raw_writel(u32 val, volatile void __iomem *addr) +{ + out_be32(addr, val); +} + +static inline u64 eeh_readq(const volatile void __iomem *addr) +{ + u64 val = in_le64(addr); + if (EEH_POSSIBLE_ERROR(val, u64)) + return eeh_check_failure(addr, val); + return val; +} +static inline void eeh_writeq(u64 val, volatile void __iomem *addr) +{ + out_le64(addr, val); +} +static inline u64 eeh_raw_readq(const volatile void __iomem *addr) +{ + u64 val = in_be64(addr); + if (EEH_POSSIBLE_ERROR(val, u64)) + return eeh_check_failure(addr, val); + return val; +} +static inline void eeh_raw_writeq(u64 val, volatile void __iomem *addr) +{ + out_be64(addr, val); +} + +#define EEH_CHECK_ALIGN(v,a) \ + ((((unsigned long)(v)) & ((a) - 1)) == 0) + +static inline void eeh_memset_io(volatile void __iomem *addr, int c, + unsigned long n) +{ + u32 lc = c; + lc |= lc << 8; + lc |= lc << 16; + + while(n && !EEH_CHECK_ALIGN(addr, 4)) { + *((volatile u8 *)addr) = c; + addr = (void *)((unsigned long)addr + 1); + n--; + } + while(n >= 4) { + *((volatile u32 *)addr) = lc; + addr = (void *)((unsigned long)addr + 4); + n -= 4; + } + while(n) { + *((volatile u8 *)addr) = c; + addr = (void *)((unsigned long)addr + 1); + n--; + } + __asm__ __volatile__ ("sync" : : : "memory"); +} +static inline void eeh_memcpy_fromio(void *dest, const volatile void __iomem *src, + unsigned long n) +{ + void *vsrc = (void __force *) src; + void *destsave = dest; + unsigned long nsave = n; + + while(n && (!EEH_CHECK_ALIGN(vsrc, 4) || !EEH_CHECK_ALIGN(dest, 4))) { + *((u8 *)dest) = *((volatile u8 *)vsrc); + __asm__ __volatile__ ("eieio" : : : "memory"); + vsrc = (void *)((unsigned long)vsrc + 1); + dest = (void *)((unsigned long)dest + 1); + n--; + } + while(n > 4) { + *((u32 *)dest) = *((volatile u32 *)vsrc); + __asm__ __volatile__ ("eieio" : : : "memory"); + vsrc = (void *)((unsigned long)vsrc + 4); + dest = (void *)((unsigned long)dest + 4); + n -= 4; + } + while(n) { + *((u8 *)dest) = *((volatile u8 *)vsrc); + __asm__ __volatile__ ("eieio" : : : "memory"); + vsrc = (void *)((unsigned long)vsrc + 1); + dest = (void *)((unsigned long)dest + 1); + n--; + } + __asm__ __volatile__ ("sync" : : : "memory"); + + /* Look for ffff's here at dest[n]. Assume that at least 4 bytes + * were copied. Check all four bytes. + */ + if ((nsave >= 4) && + (EEH_POSSIBLE_ERROR((*((u32 *) destsave+nsave-4)), u32))) { + eeh_check_failure(src, (*((u32 *) destsave+nsave-4))); + } +} + +static inline void eeh_memcpy_toio(volatile void __iomem *dest, const void *src, + unsigned long n) +{ + void *vdest = (void __force *) dest; + + while(n && (!EEH_CHECK_ALIGN(vdest, 4) || !EEH_CHECK_ALIGN(src, 4))) { + *((volatile u8 *)vdest) = *((u8 *)src); + src = (void *)((unsigned long)src + 1); + vdest = (void *)((unsigned long)vdest + 1); + n--; + } + while(n > 4) { + *((volatile u32 *)vdest) = *((volatile u32 *)src); + src = (void *)((unsigned long)src + 4); + vdest = (void *)((unsigned long)vdest + 4); + n-=4; + } + while(n) { + *((volatile u8 *)vdest) = *((u8 *)src); + src = (void *)((unsigned long)src + 1); + vdest = (void *)((unsigned long)vdest + 1); + n--; + } + __asm__ __volatile__ ("sync" : : : "memory"); +} + +#undef EEH_CHECK_ALIGN + +static inline u8 eeh_inb(unsigned long port) +{ + u8 val; + if (!_IO_IS_VALID(port)) + return ~0; + val = in_8((u8 __iomem *)(port+pci_io_base)); + if (EEH_POSSIBLE_ERROR(val, u8)) + return eeh_check_failure((void __iomem *)(port), val); + return val; +} + +static inline void eeh_outb(u8 val, unsigned long port) +{ + if (_IO_IS_VALID(port)) + out_8((u8 __iomem *)(port+pci_io_base), val); +} + +static inline u16 eeh_inw(unsigned long port) +{ + u16 val; + if (!_IO_IS_VALID(port)) + return ~0; + val = in_le16((u16 __iomem *)(port+pci_io_base)); + if (EEH_POSSIBLE_ERROR(val, u16)) + return eeh_check_failure((void __iomem *)(port), val); + return val; +} + +static inline void eeh_outw(u16 val, unsigned long port) +{ + if (_IO_IS_VALID(port)) + out_le16((u16 __iomem *)(port+pci_io_base), val); +} + +static inline u32 eeh_inl(unsigned long port) +{ + u32 val; + if (!_IO_IS_VALID(port)) + return ~0; + val = in_le32((u32 __iomem *)(port+pci_io_base)); + if (EEH_POSSIBLE_ERROR(val, u32)) + return eeh_check_failure((void __iomem *)(port), val); + return val; +} + +static inline void eeh_outl(u32 val, unsigned long port) +{ + if (_IO_IS_VALID(port)) + out_le32((u32 __iomem *)(port+pci_io_base), val); +} + +/* in-string eeh macros */ +static inline void eeh_insb(unsigned long port, void * buf, int ns) +{ + _insb((u8 __iomem *)(port+pci_io_base), buf, ns); + if (EEH_POSSIBLE_ERROR((*(((u8*)buf)+ns-1)), u8)) + eeh_check_failure((void __iomem *)(port), *(u8*)buf); +} + +static inline void eeh_insw_ns(unsigned long port, void * buf, int ns) +{ + _insw_ns((u16 __iomem *)(port+pci_io_base), buf, ns); + if (EEH_POSSIBLE_ERROR((*(((u16*)buf)+ns-1)), u16)) + eeh_check_failure((void __iomem *)(port), *(u16*)buf); +} + +static inline void eeh_insl_ns(unsigned long port, void * buf, int nl) +{ + _insl_ns((u32 __iomem *)(port+pci_io_base), buf, nl); + if (EEH_POSSIBLE_ERROR((*(((u32*)buf)+nl-1)), u32)) + eeh_check_failure((void __iomem *)(port), *(u32*)buf); +} + +#endif /* _PPC64_EEH_H */ diff --git a/include/asm-ppc64/elf.h b/include/asm-ppc64/elf.h new file mode 100644 index 000000000000..8457d90244fb --- /dev/null +++ b/include/asm-ppc64/elf.h @@ -0,0 +1,399 @@ +#ifndef __PPC64_ELF_H +#define __PPC64_ELF_H + +#include <asm/types.h> +#include <asm/ptrace.h> +#include <asm/cputable.h> + +/* PowerPC relocations defined by the ABIs */ +#define R_PPC_NONE 0 +#define R_PPC_ADDR32 1 /* 32bit absolute address */ +#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ +#define R_PPC_ADDR16 3 /* 16bit absolute address */ +#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ +#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ +#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ +#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 /* PC relative 26 bit */ +#define R_PPC_REL14 11 /* PC relative 16 bit */ +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 + +/* PowerPC relocations defined for the TLS access ABI. */ +#define R_PPC_TLS 67 /* none (sym+add)@tls */ +#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */ +#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */ +#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ +#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ +#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ +#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */ +#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */ +#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ +#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ +#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ +#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */ +#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ +#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ +#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ +#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ +#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ +#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ +#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ +#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ +#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */ +#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */ +#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ +#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ +#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */ +#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */ +#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */ +#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */ + +/* Keep this the last entry. */ +#define R_PPC_NUM 95 + +/* + * ELF register definitions.. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include <asm/ptrace.h> + +#define ELF_NGREG 48 /* includes nip, msr, lr, etc. */ +#define ELF_NFPREG 33 /* includes fpscr */ +#define ELF_NVRREG32 33 /* includes vscr & vrsave stuffed together */ +#define ELF_NVRREG 34 /* includes vscr & vrsave in split vectors */ + +typedef unsigned long elf_greg_t64; +typedef elf_greg_t64 elf_gregset_t64[ELF_NGREG]; + +typedef unsigned int elf_greg_t32; +typedef elf_greg_t32 elf_gregset_t32[ELF_NGREG]; + +/* + * These are used to set parameters in the core dumps. + */ +#ifndef ELF_ARCH +# define ELF_ARCH EM_PPC64 +# define ELF_CLASS ELFCLASS64 +# define ELF_DATA ELFDATA2MSB + typedef elf_greg_t64 elf_greg_t; + typedef elf_gregset_t64 elf_gregset_t; +# define elf_addr_t unsigned long +#else + /* Assumption: ELF_ARCH == EM_PPC and ELF_CLASS == ELFCLASS32 */ + typedef elf_greg_t32 elf_greg_t; + typedef elf_gregset_t32 elf_gregset_t; +# define elf_addr_t u32 +#endif + +typedef double elf_fpreg_t; +typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + +/* Altivec registers */ +/* + * The entries with indexes 0-31 contain the corresponding vector registers. + * The entry with index 32 contains the vscr as the last word (offset 12) + * within the quadword. This allows the vscr to be stored as either a + * quadword (since it must be copied via a vector register to/from storage) + * or as a word. The entry with index 33 contains the vrsave as the first + * word (offset 0) within the quadword. + * + * This definition of the VMX state is compatible with the current PPC32 + * ptrace interface. This allows signal handling and ptrace to use the same + * structures. This also simplifies the implementation of a bi-arch + * (combined (32- and 64-bit) gdb. + * + * Note that it's _not_ compatible with 32 bits ucontext which stuffs the + * vrsave along with vscr and so only uses 33 vectors for the register set + */ +typedef __vector128 elf_vrreg_t; +typedef elf_vrreg_t elf_vrregset_t[ELF_NVRREG]; +typedef elf_vrreg_t elf_vrregset_t32[ELF_NVRREG32]; + +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(x) ((x)->e_machine == ELF_ARCH) + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE 4096 + +/* This is the location that an ET_DYN program is loaded if exec'ed. Typical + use of this is to invoke "./ld.so someprog" to test out a new version of + the loader. We need to make sure that it is out of the way of the program + that it will "exec", and that there is sufficient room for the brk. */ + +#define ELF_ET_DYN_BASE (0x08000000) + +#ifdef __KERNEL__ + +/* Common routine for both 32-bit and 64-bit processes */ +static inline void ppc64_elf_core_copy_regs(elf_gregset_t elf_regs, + struct pt_regs *regs) +{ + int i; + int gprs = sizeof(struct pt_regs)/sizeof(elf_greg_t64); + + if (gprs > ELF_NGREG) + gprs = ELF_NGREG; + + for (i=0; i < gprs; i++) + elf_regs[i] = (elf_greg_t)((elf_greg_t64 *)regs)[i]; +} +#define ELF_CORE_COPY_REGS(gregs, regs) ppc64_elf_core_copy_regs(gregs, regs); + +static inline int dump_task_regs(struct task_struct *tsk, + elf_gregset_t *elf_regs) +{ + struct pt_regs *regs = tsk->thread.regs; + if (regs) + ppc64_elf_core_copy_regs(*elf_regs, regs); + + return 1; +} +#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs) + +extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *); +#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs) + +/* XXX Should we define the XFPREGS using altivec ??? */ + +#endif + +/* This yields a mask that user programs can use to figure out what + instruction set this cpu supports. This could be done in userspace, + but it's not easy, and we've already done it here. */ + +#define ELF_HWCAP (cur_cpu_spec->cpu_user_features) + +/* This yields a string that ld.so will use to load implementation + specific libraries for optimization. This is more specific in + intent than poking at uname or /proc/cpuinfo. + + For the moment, we have only optimizations for the Intel generations, + but that could change... */ + +#define ELF_PLATFORM (NULL) + +#define ELF_PLAT_INIT(_r, load_addr) do { \ + memset(_r->gpr, 0, sizeof(_r->gpr)); \ + _r->ctr = _r->link = _r->xer = _r->ccr = 0; \ + _r->gpr[2] = load_addr; \ +} while (0) + +#ifdef __KERNEL__ +#define SET_PERSONALITY(ex, ibcs2) \ +do { \ + unsigned long new_flags = 0; \ + if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \ + new_flags = _TIF_32BIT; \ + if ((current_thread_info()->flags & _TIF_32BIT) \ + != new_flags) \ + set_thread_flag(TIF_ABI_PENDING); \ + else \ + clear_thread_flag(TIF_ABI_PENDING); \ + if (ibcs2) \ + set_personality(PER_SVR4); \ + else if (current->personality != PER_LINUX32) \ + set_personality(PER_LINUX); \ +} while (0) + +/* + * An executable for which elf_read_implies_exec() returns TRUE will + * have the READ_IMPLIES_EXEC personality flag set automatically. + */ +#define elf_read_implies_exec(ex, exec_stk) (exec_stk != EXSTACK_DISABLE_X) + +#endif + +/* + * We need to put in some extra aux table entries to tell glibc what + * the cache block size is, so it can use the dcbz instruction safely. + */ +#define AT_DCACHEBSIZE 19 +#define AT_ICACHEBSIZE 20 +#define AT_UCACHEBSIZE 21 +/* A special ignored type value for PPC, for glibc compatibility. */ +#define AT_IGNOREPPC 22 + +/* The vDSO location. We have to use the same value as x86 for glibc's + * sake :-) + */ +#define AT_SYSINFO_EHDR 33 + +extern int dcache_bsize; +extern int icache_bsize; +extern int ucache_bsize; + +/* We do have an arch_setup_additional_pages for vDSO matters */ +#define ARCH_HAS_SETUP_ADDITIONAL_PAGES +struct linux_binprm; +extern int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack); + +/* + * The requirements here are: + * - keep the final alignment of sp (sp & 0xf) + * - make sure the 32-bit value at the first 16 byte aligned position of + * AUXV is greater than 16 for glibc compatibility. + * AT_IGNOREPPC is used for that. + * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC, + * even if DLINFO_ARCH_ITEMS goes to zero or is undefined. + */ +#define ARCH_DLINFO \ +do { \ + /* Handle glibc compatibility. */ \ + NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ + NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ + /* Cache size items */ \ + NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize); \ + NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize); \ + NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize); \ + /* vDSO base */ \ + NEW_AUX_ENT(AT_SYSINFO_EHDR, current->thread.vdso_base); \ + } while (0) + +/* PowerPC64 relocations defined by the ABIs */ +#define R_PPC64_NONE R_PPC_NONE +#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address. */ +#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned. */ +#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address. */ +#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of abs. address. */ +#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of abs. address. */ +#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */ +#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned. */ +#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN +#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN +#define R_PPC64_REL24 R_PPC_REL24 /* PC relative 26 bit, word aligned. */ +#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit. */ +#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN +#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN +#define R_PPC64_GOT16 R_PPC_GOT16 +#define R_PPC64_GOT16_LO R_PPC_GOT16_LO +#define R_PPC64_GOT16_HI R_PPC_GOT16_HI +#define R_PPC64_GOT16_HA R_PPC_GOT16_HA + +#define R_PPC64_COPY R_PPC_COPY +#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT +#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT +#define R_PPC64_RELATIVE R_PPC_RELATIVE + +#define R_PPC64_UADDR32 R_PPC_UADDR32 +#define R_PPC64_UADDR16 R_PPC_UADDR16 +#define R_PPC64_REL32 R_PPC_REL32 +#define R_PPC64_PLT32 R_PPC_PLT32 +#define R_PPC64_PLTREL32 R_PPC_PLTREL32 +#define R_PPC64_PLT16_LO R_PPC_PLT16_LO +#define R_PPC64_PLT16_HI R_PPC_PLT16_HI +#define R_PPC64_PLT16_HA R_PPC_PLT16_HA + +#define R_PPC64_SECTOFF R_PPC_SECTOFF +#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO +#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI +#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA +#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2. */ +#define R_PPC64_ADDR64 38 /* doubleword64 S + A. */ +#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A). */ +#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A). */ +#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A). */ +#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A). */ +#define R_PPC64_UADDR64 43 /* doubleword64 S + A. */ +#define R_PPC64_REL64 44 /* doubleword64 S + A - P. */ +#define R_PPC64_PLT64 45 /* doubleword64 L + A. */ +#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P. */ +#define R_PPC64_TOC16 47 /* half16* S + A - .TOC. */ +#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.). */ +#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.). */ +#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.). */ +#define R_PPC64_TOC 51 /* doubleword64 .TOC. */ +#define R_PPC64_PLTGOT16 52 /* half16* M + A. */ +#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A). */ +#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A). */ +#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A). */ + +#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2. */ +#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2. */ +#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2. */ +#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2. */ +#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2. */ +#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2. */ +#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2. */ +#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2. */ +#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2. */ +#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2. */ +#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2. */ + +/* PowerPC64 relocations defined for the TLS access ABI. */ +#define R_PPC64_TLS 67 /* none (sym+add)@tls */ +#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */ +#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */ +#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ +#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ +#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ +#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */ +#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */ +#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ +#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ +#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ +#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */ +#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ +#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ +#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ +#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ +#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ +#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ +#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ +#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ +#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */ +#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */ +#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ +#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ +#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */ +#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */ +#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */ +#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */ +#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */ +#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */ +#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */ +#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */ +#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */ +#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */ +#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */ +#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */ +#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */ +#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */ +#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */ +#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */ + +/* Keep this the last entry. */ +#define R_PPC64_NUM 107 + +#endif /* __PPC64_ELF_H */ diff --git a/include/asm-ppc64/errno.h b/include/asm-ppc64/errno.h new file mode 100644 index 000000000000..69bc3b0c6cbe --- /dev/null +++ b/include/asm-ppc64/errno.h @@ -0,0 +1,18 @@ +#ifndef _PPC64_ERRNO_H +#define _PPC64_ERRNO_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <asm-generic/errno.h> + +#undef EDEADLOCK +#define EDEADLOCK 58 /* File locking deadlock error */ + +#define _LAST_ERRNO 516 + +#endif diff --git a/include/asm-ppc64/fcntl.h b/include/asm-ppc64/fcntl.h new file mode 100644 index 000000000000..842560d50656 --- /dev/null +++ b/include/asm-ppc64/fcntl.h @@ -0,0 +1,89 @@ +#ifndef _PPC64_FCNTL_H +#define _PPC64_FCNTL_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define FASYNC 020000 /* fcntl, for BSD compatibility */ +#define O_DIRECTORY 040000 /* must be a directory */ +#define O_NOFOLLOW 0100000 /* don't follow links */ +#define O_LARGEFILE 0200000 +#define O_DIRECT 0400000 /* direct disk access hint */ +#define O_NOATIME 01000000 + +#define F_DUPFD 0 /* dup */ +#define F_GETFD 1 /* get close_on_exec */ +#define F_SETFD 2 /* set/clear close_on_exec */ +#define F_GETFL 3 /* get file->f_flags */ +#define F_SETFL 4 /* set file->f_flags */ +#define F_GETLK 5 +#define F_SETLK 6 +#define F_SETLKW 7 + +#define F_SETOWN 8 /* for sockets. */ +#define F_GETOWN 9 /* for sockets. */ +#define F_SETSIG 10 /* for sockets. */ +#define F_GETSIG 11 /* for sockets. */ + +/* for F_[GET|SET]FL */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* for posix fcntl() and lockf() */ +#define F_RDLCK 0 +#define F_WRLCK 1 +#define F_UNLCK 2 + +/* for old implementation of bsd flock () */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +/* for leases */ +#define F_INPROGRESS 16 + +/* operations for bsd flock(), also used by the kernel implementation */ +#define LOCK_SH 1 /* shared lock */ +#define LOCK_EX 2 /* exclusive lock */ +#define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +#define LOCK_UN 8 /* remove lock */ + +#define LOCK_MAND 32 /* This is a mandatory flock */ +#define LOCK_READ 64 /* ... Which allows concurrent read operations */ +#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */ +#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */ + +#ifdef __KERNEL__ +#define F_POSIX 1 +#define F_FLOCK 2 +#define F_BROKEN 4 /* broken flock() emulation */ +#endif /* __KERNEL__ */ + +struct flock { + short l_type; + short l_whence; + off_t l_start; + off_t l_len; + pid_t l_pid; +}; + +#define F_LINUX_SPECIFIC_BASE 1024 + +#endif /* _PPC64_FCNTL_H */ diff --git a/include/asm-ppc64/floppy.h b/include/asm-ppc64/floppy.h new file mode 100644 index 000000000000..5c497b588e54 --- /dev/null +++ b/include/asm-ppc64/floppy.h @@ -0,0 +1,106 @@ +/* + * Architecture specific parts of the Floppy driver + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995 + */ +#ifndef __ASM_PPC64_FLOPPY_H +#define __ASM_PPC64_FLOPPY_H + +#include <linux/config.h> +#include <asm/machdep.h> + +#define fd_inb(port) inb_p(port) +#define fd_outb(value,port) outb_p(value,port) + +#define fd_enable_dma() enable_dma(FLOPPY_DMA) +#define fd_disable_dma() disable_dma(FLOPPY_DMA) +#define fd_request_dma() request_dma(FLOPPY_DMA,"floppy") +#define fd_free_dma() free_dma(FLOPPY_DMA) +#define fd_clear_dma_ff() clear_dma_ff(FLOPPY_DMA) +#define fd_set_dma_mode(mode) set_dma_mode(FLOPPY_DMA,mode) +#define fd_set_dma_count(count) set_dma_count(FLOPPY_DMA,count) +#define fd_enable_irq() enable_irq(FLOPPY_IRQ) +#define fd_disable_irq() disable_irq(FLOPPY_IRQ) +#define fd_cacheflush(addr,size) /* nothing */ +#define fd_request_irq() request_irq(FLOPPY_IRQ, floppy_interrupt, \ + SA_INTERRUPT|SA_SAMPLE_RANDOM, \ + "floppy", NULL) +#define fd_free_irq() free_irq(FLOPPY_IRQ, NULL); + +#ifdef CONFIG_PCI + +#include <linux/pci.h> + +#define fd_dma_setup(addr,size,mode,io) ppc64_fd_dma_setup(addr,size,mode,io) + +static __inline__ int +ppc64_fd_dma_setup(char *addr, unsigned long size, int mode, int io) +{ + static unsigned long prev_size; + static dma_addr_t bus_addr = 0; + static char *prev_addr; + static int prev_dir; + int dir; + + dir = (mode == DMA_MODE_READ) ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE; + + if (bus_addr + && (addr != prev_addr || size != prev_size || dir != prev_dir)) { + /* different from last time -- unmap prev */ + pci_unmap_single(NULL, bus_addr, prev_size, prev_dir); + bus_addr = 0; + } + + if (!bus_addr) /* need to map it */ { + bus_addr = pci_map_single(NULL, addr, size, dir); + } + + /* remember this one as prev */ + prev_addr = addr; + prev_size = size; + prev_dir = dir; + + fd_clear_dma_ff(); + fd_cacheflush(addr, size); + fd_set_dma_mode(mode); + set_dma_addr(FLOPPY_DMA, bus_addr); + fd_set_dma_count(size); + virtual_dma_port = io; + fd_enable_dma(); + + return 0; +} + +#endif /* CONFIG_PCI */ + +__inline__ void virtual_dma_init(void) +{ + /* Nothing to do on PowerPC */ +} + +static int FDC1 = 0x3f0; +static int FDC2 = -1; + +/* + * Again, the CMOS information not available + */ +#define FLOPPY0_TYPE 6 +#define FLOPPY1_TYPE 0 + +#define N_FDC 2 /* Don't change this! */ +#define N_DRIVE 8 + +#define FLOPPY_MOTOR_MASK 0xf0 + +/* + * The PowerPC has no problems with floppy DMA crossing 64k borders. + */ +#define CROSS_64KB(a,s) (0) + +#define EXTRA_FLOPPY_PARAMS + +#endif /* __ASM_PPC64_FLOPPY_H */ diff --git a/include/asm-ppc64/hardirq.h b/include/asm-ppc64/hardirq.h new file mode 100644 index 000000000000..4ee72bb1fd48 --- /dev/null +++ b/include/asm-ppc64/hardirq.h @@ -0,0 +1,27 @@ +#ifndef __ASM_HARDIRQ_H +#define __ASM_HARDIRQ_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/config.h> +#include <linux/cache.h> +#include <linux/preempt.h> + +typedef struct { + unsigned int __softirq_pending; +} ____cacheline_aligned irq_cpustat_t; + +#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ + +static inline void ack_bad_irq(int irq) +{ + printk(KERN_CRIT "illegal vector %d received!\n", irq); + BUG(); +} + +#endif /* __ASM_HARDIRQ_H */ diff --git a/include/asm-ppc64/hdreg.h b/include/asm-ppc64/hdreg.h new file mode 100644 index 000000000000..7f7fd1af0af3 --- /dev/null +++ b/include/asm-ppc64/hdreg.h @@ -0,0 +1 @@ +#include <asm-generic/hdreg.h> diff --git a/include/asm-ppc64/hvcall.h b/include/asm-ppc64/hvcall.h new file mode 100644 index 000000000000..4f668a4baff0 --- /dev/null +++ b/include/asm-ppc64/hvcall.h @@ -0,0 +1,167 @@ +#ifndef _PPC64_HVCALL_H +#define _PPC64_HVCALL_H + +#define HVSC .long 0x44000022 + +#define H_Success 0 +#define H_Busy 1 /* Hardware busy -- retry later */ +#define H_Constrained 4 /* Resource request constrained to max allowed */ +#define H_LongBusyStartRange 9900 /* Start of long busy range */ +#define H_LongBusyOrder1msec 9900 /* Long busy, hint that 1msec is a good time to retry */ +#define H_LongBusyOrder10msec 9901 /* Long busy, hint that 10msec is a good time to retry */ +#define H_LongBusyOrder100msec 9902 /* Long busy, hint that 100msec is a good time to retry */ +#define H_LongBusyOrder1sec 9903 /* Long busy, hint that 1sec is a good time to retry */ +#define H_LongBusyOrder10sec 9904 /* Long busy, hint that 10sec is a good time to retry */ +#define H_LongBusyOrder100sec 9905 /* Long busy, hint that 100sec is a good time to retry */ +#define H_LongBusyEndRange 9905 /* End of long busy range */ +#define H_Hardware -1 /* Hardware error */ +#define H_Function -2 /* Function not supported */ +#define H_Privilege -3 /* Caller not privileged */ +#define H_Parameter -4 /* Parameter invalid, out-of-range or conflicting */ +#define H_Bad_Mode -5 /* Illegal msr value */ +#define H_PTEG_Full -6 /* PTEG is full */ +#define H_Not_Found -7 /* PTE was not found" */ +#define H_Reserved_DABR -8 /* DABR address is reserved by the hypervisor on this processor" */ +#define H_NoMem -9 +#define H_Authority -10 +#define H_Permission -11 +#define H_Dropped -12 +#define H_SourceParm -13 +#define H_DestParm -14 +#define H_RemoteParm -15 +#define H_Resource -16 + +/* Long Busy is a condition that can be returned by the firmware + * when a call cannot be completed now, but the identical call + * should be retried later. This prevents calls blocking in the + * firmware for long periods of time. Annoyingly the firmware can return + * a range of return codes, hinting at how long we should wait before + * retrying. If you don't care for the hint, the macro below is a good + * way to check for the long_busy return codes + */ +#define H_isLongBusy(x) ((x >= H_LongBusyStartRange) && (x <= H_LongBusyEndRange)) + +/* Flags */ +#define H_LARGE_PAGE (1UL<<(63-16)) +#define H_EXACT (1UL<<(63-24)) /* Use exact PTE or return H_PTEG_FULL */ +#define H_R_XLATE (1UL<<(63-25)) /* include a valid logical page num in the pte if the valid bit is set */ +#define H_READ_4 (1UL<<(63-26)) /* Return 4 PTEs */ +#define H_AVPN (1UL<<(63-32)) /* An avpn is provided as a sanity test */ +#define H_ANDCOND (1UL<<(63-33)) +#define H_ICACHE_INVALIDATE (1UL<<(63-40)) /* icbi, etc. (ignored for IO pages) */ +#define H_ICACHE_SYNCHRONIZE (1UL<<(63-41)) /* dcbst, icbi, etc (ignored for IO pages */ +#define H_ZERO_PAGE (1UL<<(63-48)) /* zero the page before mapping (ignored for IO pages) */ +#define H_COPY_PAGE (1UL<<(63-49)) +#define H_N (1UL<<(63-61)) +#define H_PP1 (1UL<<(63-62)) +#define H_PP2 (1UL<<(63-63)) + +/* pSeries hypervisor opcodes */ +#define H_REMOVE 0x04 +#define H_ENTER 0x08 +#define H_READ 0x0c +#define H_CLEAR_MOD 0x10 +#define H_CLEAR_REF 0x14 +#define H_PROTECT 0x18 +#define H_GET_TCE 0x1c +#define H_PUT_TCE 0x20 +#define H_SET_SPRG0 0x24 +#define H_SET_DABR 0x28 +#define H_PAGE_INIT 0x2c +#define H_SET_ASR 0x30 +#define H_ASR_ON 0x34 +#define H_ASR_OFF 0x38 +#define H_LOGICAL_CI_LOAD 0x3c +#define H_LOGICAL_CI_STORE 0x40 +#define H_LOGICAL_CACHE_LOAD 0x44 +#define H_LOGICAL_CACHE_STORE 0x48 +#define H_LOGICAL_ICBI 0x4c +#define H_LOGICAL_DCBF 0x50 +#define H_GET_TERM_CHAR 0x54 +#define H_PUT_TERM_CHAR 0x58 +#define H_REAL_TO_LOGICAL 0x5c +#define H_HYPERVISOR_DATA 0x60 +#define H_EOI 0x64 +#define H_CPPR 0x68 +#define H_IPI 0x6c +#define H_IPOLL 0x70 +#define H_XIRR 0x74 +#define H_PERFMON 0x7c +#define H_MIGRATE_DMA 0x78 +#define H_REGISTER_VPA 0xDC +#define H_CEDE 0xE0 +#define H_CONFER 0xE4 +#define H_PROD 0xE8 +#define H_GET_PPP 0xEC +#define H_SET_PPP 0xF0 +#define H_PURR 0xF4 +#define H_PIC 0xF8 +#define H_REG_CRQ 0xFC +#define H_FREE_CRQ 0x100 +#define H_VIO_SIGNAL 0x104 +#define H_SEND_CRQ 0x108 +#define H_COPY_RDMA 0x110 +#define H_STUFF_TCE 0x138 +#define H_PUT_TCE_INDIRECT 0x13C +#define H_VTERM_PARTNER_INFO 0x150 +#define H_REGISTER_VTERM 0x154 +#define H_FREE_VTERM 0x158 +#define H_POLL_PENDING 0x1D8 + +#ifndef __ASSEMBLY__ + +/* plpar_hcall() -- Generic call interface using above opcodes + * + * The actual call interface is a hypervisor call instruction with + * the opcode in R3 and input args in R4-R7. + * Status is returned in R3 with variable output values in R4-R11. + * Only H_PTE_READ with H_READ_4 uses R6-R11 so we ignore it for now + * and return only two out args which MUST ALWAYS BE PROVIDED. + */ +long plpar_hcall(unsigned long opcode, + unsigned long arg1, + unsigned long arg2, + unsigned long arg3, + unsigned long arg4, + unsigned long *out1, + unsigned long *out2, + unsigned long *out3); + +/* Same as plpar_hcall but for those opcodes that return no values + * other than status. Slightly more efficient. + */ +long plpar_hcall_norets(unsigned long opcode, ...); + +/* + * Special hcall interface for ibmveth support. + * Takes 8 input parms. Returns a rc and stores the + * R4 return value in *out1. + */ +long plpar_hcall_8arg_2ret(unsigned long opcode, + unsigned long arg1, + unsigned long arg2, + unsigned long arg3, + unsigned long arg4, + unsigned long arg5, + unsigned long arg6, + unsigned long arg7, + unsigned long arg8, + unsigned long *out1); + +/* plpar_hcall_4out() + * + * same as plpar_hcall except with 4 output arguments. + * + */ +long plpar_hcall_4out(unsigned long opcode, + unsigned long arg1, + unsigned long arg2, + unsigned long arg3, + unsigned long arg4, + unsigned long *out1, + unsigned long *out2, + unsigned long *out3, + unsigned long *out4); + +#endif /* __ASSEMBLY__ */ +#endif /* _PPC64_HVCALL_H */ diff --git a/include/asm-ppc64/hvconsole.h b/include/asm-ppc64/hvconsole.h new file mode 100644 index 000000000000..d89d94c91815 --- /dev/null +++ b/include/asm-ppc64/hvconsole.h @@ -0,0 +1,40 @@ +/* + * hvconsole.h + * Copyright (C) 2004 Ryan S Arnold, IBM Corporation + * + * LPAR console support. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _PPC64_HVCONSOLE_H +#define _PPC64_HVCONSOLE_H + +/* + * This is the max number of console adapters that can/will be found as + * console devices on first stage console init. Any number beyond this range + * can't be used as a console device but is still a valid tty device. + */ +#define MAX_NR_HVC_CONSOLES 16 + +extern int hvc_get_chars(uint32_t vtermno, char *buf, int count); +extern int hvc_put_chars(uint32_t vtermno, const char *buf, int count); + +/* Early discovery of console adapters. */ +extern int hvc_find_vtys(void); + +/* Implemented by a console driver */ +extern int hvc_instantiate(uint32_t vtermno, int index); +#endif /* _PPC64_HVCONSOLE_H */ diff --git a/include/asm-ppc64/hvcserver.h b/include/asm-ppc64/hvcserver.h new file mode 100644 index 000000000000..aecba9665796 --- /dev/null +++ b/include/asm-ppc64/hvcserver.h @@ -0,0 +1,57 @@ +/* + * hvcserver.h + * Copyright (C) 2004 Ryan S Arnold, IBM Corporation + * + * PPC64 virtual I/O console server support. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _PPC64_HVCSERVER_H +#define _PPC64_HVCSERVER_H + +#include <linux/list.h> + +/* Converged Location Code length */ +#define HVCS_CLC_LENGTH 79 + +/** + * hvcs_partner_info - an element in a list of partner info + * @node: list_head denoting this partner_info struct's position in the list of + * partner info. + * @unit_address: The partner unit address of this entry. + * @partition_ID: The partner partition ID of this entry. + * @location_code: The converged location code of this entry + 1 char for the + * null-term. + * + * This structure outlines the format that partner info is presented to a caller + * of the hvcs partner info fetching functions. These are strung together into + * a list using linux kernel lists. + */ +struct hvcs_partner_info { + struct list_head node; + uint32_t unit_address; + uint32_t partition_ID; + char location_code[HVCS_CLC_LENGTH + 1]; /* CLC + 1 null-term char */ +}; + +extern int hvcs_free_partner_info(struct list_head *head); +extern int hvcs_get_partner_info(uint32_t unit_address, + struct list_head *head, unsigned long *pi_buff); +extern int hvcs_register_connection(uint32_t unit_address, + uint32_t p_partition_ID, uint32_t p_unit_address); +extern int hvcs_free_connection(uint32_t unit_address); + +#endif /* _PPC64_HVCSERVER_H */ diff --git a/include/asm-ppc64/hw_irq.h b/include/asm-ppc64/hw_irq.h new file mode 100644 index 000000000000..baea40e695ec --- /dev/null +++ b/include/asm-ppc64/hw_irq.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu> + * + * Use inline IRQs where possible - Anton Blanchard <anton@au.ibm.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifdef __KERNEL__ +#ifndef _PPC64_HW_IRQ_H +#define _PPC64_HW_IRQ_H + +#include <linux/config.h> +#include <linux/errno.h> +#include <asm/irq.h> + +int timer_interrupt(struct pt_regs *); +extern void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq); + +#ifdef CONFIG_PPC_ISERIES + +extern unsigned long local_get_flags(void); +extern unsigned long local_irq_disable(void); +extern void local_irq_restore(unsigned long); + +#define local_irq_enable() local_irq_restore(1) +#define local_save_flags(flags) ((flags) = local_get_flags()) +#define local_irq_save(flags) ((flags) = local_irq_disable()) + +#define irqs_disabled() (local_get_flags() == 0) + +#else + +#define local_save_flags(flags) ((flags) = mfmsr()) +#define local_irq_restore(flags) do { \ + __asm__ __volatile__("": : :"memory"); \ + __mtmsrd((flags), 1); \ +} while(0) + +static inline void local_irq_disable(void) +{ + unsigned long msr; + msr = mfmsr(); + __mtmsrd(msr & ~MSR_EE, 1); + __asm__ __volatile__("": : :"memory"); +} + +static inline void local_irq_enable(void) +{ + unsigned long msr; + __asm__ __volatile__("": : :"memory"); + msr = mfmsr(); + __mtmsrd(msr | MSR_EE, 1); +} + +static inline void __do_save_and_cli(unsigned long *flags) +{ + unsigned long msr; + msr = mfmsr(); + *flags = msr; + __mtmsrd(msr & ~MSR_EE, 1); + __asm__ __volatile__("": : :"memory"); +} + +#define local_irq_save(flags) __do_save_and_cli(&flags) + +#define irqs_disabled() \ +({ \ + unsigned long flags; \ + local_save_flags(flags); \ + !(flags & MSR_EE); \ +}) + +#endif /* CONFIG_PPC_ISERIES */ + +#define mask_irq(irq) \ + ({ \ + irq_desc_t *desc = get_irq_desc(irq); \ + if (desc->handler && desc->handler->disable) \ + desc->handler->disable(irq); \ + }) +#define unmask_irq(irq) \ + ({ \ + irq_desc_t *desc = get_irq_desc(irq); \ + if (desc->handler && desc->handler->enable) \ + desc->handler->enable(irq); \ + }) +#define ack_irq(irq) \ + ({ \ + irq_desc_t *desc = get_irq_desc(irq); \ + if (desc->handler && desc->handler->ack) \ + desc->handler->ack(irq); \ + }) + +/* Should we handle this via lost interrupts and IPIs or should we don't care like + * we do now ? --BenH. + */ +struct hw_interrupt_type; +static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {} + +#endif /* _PPC64_HW_IRQ_H */ +#endif /* __KERNEL__ */ diff --git a/include/asm-ppc64/iSeries/HvCall.h b/include/asm-ppc64/iSeries/HvCall.h new file mode 100644 index 000000000000..d9a2e74e2399 --- /dev/null +++ b/include/asm-ppc64/iSeries/HvCall.h @@ -0,0 +1,205 @@ +/* + * HvCall.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +//=========================================================================== +// +// This file contains the "hypervisor call" interface which is used to +// drive the hypervisor from the OS. +// +//=========================================================================== +#ifndef _HVCALL_H +#define _HVCALL_H + +//------------------------------------------------------------------- +// Standard Includes +//------------------------------------------------------------------- +#include <asm/iSeries/HvCallSc.h> +#include <asm/iSeries/HvTypes.h> +#include <asm/paca.h> + +/* +enum HvCall_ReturnCode +{ + HvCall_Good = 0, + HvCall_Partial = 1, + HvCall_NotOwned = 2, + HvCall_NotFreed = 3, + HvCall_UnspecifiedError = 4 +}; + +enum HvCall_TypeOfSIT +{ + HvCall_ReduceOnly = 0, + HvCall_Unconditional = 1 +}; + +enum HvCall_TypeOfYield +{ + HvCall_YieldTimed = 0, // Yield until specified time + HvCall_YieldToActive = 1, // Yield until all active procs have run + HvCall_YieldToProc = 2 // Yield until the specified processor has run +}; + +enum HvCall_InterruptMasks +{ + HvCall_MaskIPI = 0x00000001, + HvCall_MaskLpEvent = 0x00000002, + HvCall_MaskLpProd = 0x00000004, + HvCall_MaskTimeout = 0x00000008 +}; + +enum HvCall_VaryOffChunkRc +{ + HvCall_VaryOffSucceeded = 0, + HvCall_VaryOffWithdrawn = 1, + HvCall_ChunkInLoadArea = 2, + HvCall_ChunkInHPT = 3, + HvCall_ChunkNotAccessible = 4, + HvCall_ChunkInUse = 5 +}; +*/ + +/* Type of yield for HvCallBaseYieldProcessor */ +#define HvCall_YieldTimed 0 // Yield until specified time (tb) +#define HvCall_YieldToActive 1 // Yield until all active procs have run +#define HvCall_YieldToProc 2 // Yield until the specified processor has run + +/* interrupt masks for setEnabledInterrupts */ +#define HvCall_MaskIPI 0x00000001 +#define HvCall_MaskLpEvent 0x00000002 +#define HvCall_MaskLpProd 0x00000004 +#define HvCall_MaskTimeout 0x00000008 + +/* Log buffer formats */ +#define HvCall_LogBuffer_ASCII 0 +#define HvCall_LogBuffer_EBCDIC 1 + +#define HvCallBaseAckDeferredInts HvCallBase + 0 +#define HvCallBaseCpmPowerOff HvCallBase + 1 +#define HvCallBaseGetHwPatch HvCallBase + 2 +#define HvCallBaseReIplSpAttn HvCallBase + 3 +#define HvCallBaseSetASR HvCallBase + 4 +#define HvCallBaseSetASRAndRfi HvCallBase + 5 +#define HvCallBaseSetIMR HvCallBase + 6 +#define HvCallBaseSendIPI HvCallBase + 7 +#define HvCallBaseTerminateMachine HvCallBase + 8 +#define HvCallBaseTerminateMachineSrc HvCallBase + 9 +#define HvCallBaseProcessPlicInterrupts HvCallBase + 10 +#define HvCallBaseIsPrimaryCpmOrMsdIpl HvCallBase + 11 +#define HvCallBaseSetVirtualSIT HvCallBase + 12 +#define HvCallBaseVaryOffThisProcessor HvCallBase + 13 +#define HvCallBaseVaryOffMemoryChunk HvCallBase + 14 +#define HvCallBaseVaryOffInteractivePercentage HvCallBase + 15 +#define HvCallBaseSendLpProd HvCallBase + 16 +#define HvCallBaseSetEnabledInterrupts HvCallBase + 17 +#define HvCallBaseYieldProcessor HvCallBase + 18 +#define HvCallBaseVaryOffSharedProcUnits HvCallBase + 19 +#define HvCallBaseSetVirtualDecr HvCallBase + 20 +#define HvCallBaseClearLogBuffer HvCallBase + 21 +#define HvCallBaseGetLogBufferCodePage HvCallBase + 22 +#define HvCallBaseGetLogBufferFormat HvCallBase + 23 +#define HvCallBaseGetLogBufferLength HvCallBase + 24 +#define HvCallBaseReadLogBuffer HvCallBase + 25 +#define HvCallBaseSetLogBufferFormatAndCodePage HvCallBase + 26 +#define HvCallBaseWriteLogBuffer HvCallBase + 27 +#define HvCallBaseRouter28 HvCallBase + 28 +#define HvCallBaseRouter29 HvCallBase + 29 +#define HvCallBaseRouter30 HvCallBase + 30 +#define HvCallBaseSetDebugBus HvCallBase + 31 + +#define HvCallCcSetDABR HvCallCc + 7 + +//===================================================================================== +static inline void HvCall_setVirtualDecr(void) +{ + /* Ignore any error return codes - most likely means that the target value for the + * LP has been increased and this vary off would bring us below the new target. */ + HvCall0(HvCallBaseSetVirtualDecr); +} +//===================================================================== +static inline void HvCall_yieldProcessor(unsigned typeOfYield, u64 yieldParm) +{ + HvCall2( HvCallBaseYieldProcessor, typeOfYield, yieldParm ); +} +//===================================================================== +static inline void HvCall_setEnabledInterrupts(u64 enabledInterrupts) +{ + HvCall1(HvCallBaseSetEnabledInterrupts,enabledInterrupts); +} + +//===================================================================== +static inline void HvCall_clearLogBuffer(HvLpIndex lpindex) +{ + HvCall1(HvCallBaseClearLogBuffer,lpindex); +} + +//===================================================================== +static inline u32 HvCall_getLogBufferCodePage(HvLpIndex lpindex) +{ + u32 retVal = HvCall1(HvCallBaseGetLogBufferCodePage,lpindex); + return retVal; +} + +//===================================================================== +static inline int HvCall_getLogBufferFormat(HvLpIndex lpindex) +{ + int retVal = HvCall1(HvCallBaseGetLogBufferFormat,lpindex); + return retVal; +} + +//===================================================================== +static inline u32 HvCall_getLogBufferLength(HvLpIndex lpindex) +{ + u32 retVal = HvCall1(HvCallBaseGetLogBufferLength,lpindex); + return retVal; +} + +//===================================================================== +static inline void HvCall_setLogBufferFormatAndCodepage(int format, u32 codePage) +{ + HvCall2(HvCallBaseSetLogBufferFormatAndCodePage,format, codePage); +} + +//===================================================================== +int HvCall_readLogBuffer(HvLpIndex lpindex, void *buffer, u64 bufLen); +void HvCall_writeLogBuffer(const void *buffer, u64 bufLen); + +//===================================================================== +static inline void HvCall_sendIPI(struct paca_struct * targetPaca) +{ + HvCall1( HvCallBaseSendIPI, targetPaca->paca_index ); +} + +//===================================================================== +static inline void HvCall_terminateMachineSrc(void) +{ + HvCall0( HvCallBaseTerminateMachineSrc ); +} + +static inline void HvCall_setDABR(unsigned long val) +{ + HvCall1(HvCallCcSetDABR, val); +} + +static inline void HvCall_setDebugBus(unsigned long val) +{ + HvCall1(HvCallBaseSetDebugBus, val); +} + +#endif /* _HVCALL_H */ diff --git a/include/asm-ppc64/iSeries/HvCallCfg.h b/include/asm-ppc64/iSeries/HvCallCfg.h new file mode 100644 index 000000000000..9f40f16de533 --- /dev/null +++ b/include/asm-ppc64/iSeries/HvCallCfg.h @@ -0,0 +1,213 @@ +/* + * HvCallCfg.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +//===================================================================================== +// +// This file contains the "hypervisor call" interface which is used to +// drive the hypervisor from the OS. +// +//===================================================================================== +#ifndef _HVCALLCFG_H +#define _HVCALLCFG_H + +//------------------------------------------------------------------- +// Standard Includes +//------------------------------------------------------------------- +#include <asm/iSeries/HvCallSc.h> +#include <asm/iSeries/HvTypes.h> + +//------------------------------------------------------------------------------------- +// Constants +//------------------------------------------------------------------------------------- + +enum HvCallCfg_ReqQual +{ + HvCallCfg_Cur = 0, + HvCallCfg_Init = 1, + HvCallCfg_Max = 2, + HvCallCfg_Min = 3 +}; + +#define HvCallCfgGetLps HvCallCfg + 0 +#define HvCallCfgGetActiveLpMap HvCallCfg + 1 +#define HvCallCfgGetLpVrmIndex HvCallCfg + 2 +#define HvCallCfgGetLpMinSupportedPlicVrmIndex HvCallCfg + 3 +#define HvCallCfgGetLpMinCompatablePlicVrmIndex HvCallCfg + 4 +#define HvCallCfgGetLpVrmName HvCallCfg + 5 +#define HvCallCfgGetSystemPhysicalProcessors HvCallCfg + 6 +#define HvCallCfgGetPhysicalProcessors HvCallCfg + 7 +#define HvCallCfgGetSystemMsChunks HvCallCfg + 8 +#define HvCallCfgGetMsChunks HvCallCfg + 9 +#define HvCallCfgGetInteractivePercentage HvCallCfg + 10 +#define HvCallCfgIsBusDedicated HvCallCfg + 11 +#define HvCallCfgGetBusOwner HvCallCfg + 12 +#define HvCallCfgGetBusAllocation HvCallCfg + 13 +#define HvCallCfgGetBusUnitOwner HvCallCfg + 14 +#define HvCallCfgGetBusUnitAllocation HvCallCfg + 15 +#define HvCallCfgGetVirtualBusPool HvCallCfg + 16 +#define HvCallCfgGetBusUnitInterruptProc HvCallCfg + 17 +#define HvCallCfgGetConfiguredBusUnitsForIntProc HvCallCfg + 18 +#define HvCallCfgGetRioSanBusPool HvCallCfg + 19 +#define HvCallCfgGetSharedPoolIndex HvCallCfg + 20 +#define HvCallCfgGetSharedProcUnits HvCallCfg + 21 +#define HvCallCfgGetNumProcsInSharedPool HvCallCfg + 22 +#define HvCallCfgRouter23 HvCallCfg + 23 +#define HvCallCfgRouter24 HvCallCfg + 24 +#define HvCallCfgRouter25 HvCallCfg + 25 +#define HvCallCfgRouter26 HvCallCfg + 26 +#define HvCallCfgRouter27 HvCallCfg + 27 +#define HvCallCfgGetMinRuntimeMsChunks HvCallCfg + 28 +#define HvCallCfgSetMinRuntimeMsChunks HvCallCfg + 29 +#define HvCallCfgGetVirtualLanIndexMap HvCallCfg + 30 +#define HvCallCfgGetLpExecutionMode HvCallCfg + 31 +#define HvCallCfgGetHostingLpIndex HvCallCfg + 32 + +//==================================================================== +static inline HvLpIndex HvCallCfg_getLps(void) +{ + HvLpIndex retVal = HvCall0(HvCallCfgGetLps); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} +//==================================================================== +static inline int HvCallCfg_isBusDedicated(u64 busIndex) +{ + int retVal = HvCall1(HvCallCfgIsBusDedicated,busIndex); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} +//==================================================================== +static inline HvLpIndex HvCallCfg_getBusOwner(u64 busIndex) +{ + HvLpIndex retVal = HvCall1(HvCallCfgGetBusOwner,busIndex); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} +//==================================================================== +static inline HvLpIndexMap HvCallCfg_getBusAllocation(u64 busIndex) +{ + HvLpIndexMap retVal = HvCall1(HvCallCfgGetBusAllocation,busIndex); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} +//==================================================================== +static inline HvLpIndexMap HvCallCfg_getActiveLpMap(void) +{ + HvLpIndexMap retVal = HvCall0(HvCallCfgGetActiveLpMap); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} +//==================================================================== +static inline HvLpVirtualLanIndexMap HvCallCfg_getVirtualLanIndexMap(HvLpIndex lp) +{ + // This is a new function in V5R1 so calls to this on older + // hypervisors will return -1 + u64 retVal = HvCall1(HvCallCfgGetVirtualLanIndexMap, lp); + if(retVal == -1) + retVal = 0; + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} +//=================================================================== +static inline u64 HvCallCfg_getSystemMsChunks(void) +{ + u64 retVal = HvCall0(HvCallCfgGetSystemMsChunks); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} +//=================================================================== +static inline u64 HvCallCfg_getMsChunks(HvLpIndex lp,enum HvCallCfg_ReqQual qual) +{ + u64 retVal = HvCall2(HvCallCfgGetMsChunks,lp,qual); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} +//=================================================================== +static inline u64 HvCallCfg_getMinRuntimeMsChunks(HvLpIndex lp) +{ + // NOTE: This function was added in v5r1 so older hypervisors will return a -1 value + u64 retVal = HvCall1(HvCallCfgGetMinRuntimeMsChunks,lp); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} +//=================================================================== +static inline u64 HvCallCfg_setMinRuntimeMsChunks(u64 chunks) +{ + u64 retVal = HvCall1(HvCallCfgSetMinRuntimeMsChunks,chunks); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} +//=================================================================== +static inline u64 HvCallCfg_getSystemPhysicalProcessors(void) +{ + u64 retVal = HvCall0(HvCallCfgGetSystemPhysicalProcessors); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} +//=================================================================== +static inline u64 HvCallCfg_getPhysicalProcessors(HvLpIndex lp,enum HvCallCfg_ReqQual qual) +{ + u64 retVal = HvCall2(HvCallCfgGetPhysicalProcessors,lp,qual); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} +//=================================================================== +static inline u64 HvCallCfg_getConfiguredBusUnitsForInterruptProc(HvLpIndex lp, + u16 hvLogicalProcIndex) +{ + u64 retVal = HvCall2(HvCallCfgGetConfiguredBusUnitsForIntProc,lp,hvLogicalProcIndex); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; + +} +//================================================================== +static inline HvLpSharedPoolIndex HvCallCfg_getSharedPoolIndex(HvLpIndex lp) +{ + HvLpSharedPoolIndex retVal = + HvCall1(HvCallCfgGetSharedPoolIndex,lp); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; + +} +//================================================================== +static inline u64 HvCallCfg_getSharedProcUnits(HvLpIndex lp,enum HvCallCfg_ReqQual qual) +{ + u64 retVal = HvCall2(HvCallCfgGetSharedProcUnits,lp,qual); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; + +} +//================================================================== +static inline u64 HvCallCfg_getNumProcsInSharedPool(HvLpSharedPoolIndex sPI) +{ + u16 retVal = HvCall1(HvCallCfgGetNumProcsInSharedPool,sPI); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; + +} +//================================================================== +static inline HvLpIndex HvCallCfg_getHostingLpIndex(HvLpIndex lp) +{ + u64 retVal = HvCall1(HvCallCfgGetHostingLpIndex,lp); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; + +} + +#endif /* _HVCALLCFG_H */ diff --git a/include/asm-ppc64/iSeries/HvCallEvent.h b/include/asm-ppc64/iSeries/HvCallEvent.h new file mode 100644 index 000000000000..191ddce0c2c6 --- /dev/null +++ b/include/asm-ppc64/iSeries/HvCallEvent.h @@ -0,0 +1,297 @@ +/* + * HvCallEvent.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * This file contains the "hypervisor call" interface which is used to + * drive the hypervisor from the OS. + */ +#ifndef _HVCALLEVENT_H +#define _HVCALLEVENT_H + +/* + * Standard Includes + */ +#include <asm/iSeries/HvCallSc.h> +#include <asm/iSeries/HvTypes.h> +#include <asm/abs_addr.h> + +struct HvLpEvent; + +typedef u8 HvLpEvent_Type; +typedef u8 HvLpEvent_AckInd; +typedef u8 HvLpEvent_AckType; + +struct HvCallEvent_PackedParms { + u8 xAckType:1; + u8 xAckInd:1; + u8 xRsvd:1; + u8 xTargetLp:5; + u8 xType; + u16 xSubtype; + HvLpInstanceId xSourceInstId; + HvLpInstanceId xTargetInstId; +}; + +typedef u8 HvLpDma_Direction; +typedef u8 HvLpDma_AddressType; + +struct HvCallEvent_PackedDmaParms { + u8 xDirection:1; + u8 xLocalAddrType:1; + u8 xRemoteAddrType:1; + u8 xRsvd1:5; + HvLpIndex xRemoteLp; + u8 xType; + u8 xRsvd2; + HvLpInstanceId xLocalInstId; + HvLpInstanceId xRemoteInstId; +}; + +typedef u64 HvLpEvent_Rc; +typedef u64 HvLpDma_Rc; + +#define HvCallEventAckLpEvent HvCallEvent + 0 +#define HvCallEventCancelLpEvent HvCallEvent + 1 +#define HvCallEventCloseLpEventPath HvCallEvent + 2 +#define HvCallEventDmaBufList HvCallEvent + 3 +#define HvCallEventDmaSingle HvCallEvent + 4 +#define HvCallEventDmaToSp HvCallEvent + 5 +#define HvCallEventGetOverflowLpEvents HvCallEvent + 6 +#define HvCallEventGetSourceLpInstanceId HvCallEvent + 7 +#define HvCallEventGetTargetLpInstanceId HvCallEvent + 8 +#define HvCallEventOpenLpEventPath HvCallEvent + 9 +#define HvCallEventSetLpEventStack HvCallEvent + 10 +#define HvCallEventSignalLpEvent HvCallEvent + 11 +#define HvCallEventSignalLpEventParms HvCallEvent + 12 +#define HvCallEventSetInterLpQueueIndex HvCallEvent + 13 +#define HvCallEventSetLpEventQueueInterruptProc HvCallEvent + 14 +#define HvCallEventRouter15 HvCallEvent + 15 + +static inline void HvCallEvent_getOverflowLpEvents(u8 queueIndex) +{ + HvCall1(HvCallEventGetOverflowLpEvents,queueIndex); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); +} + +static inline void HvCallEvent_setInterLpQueueIndex(u8 queueIndex) +{ + HvCall1(HvCallEventSetInterLpQueueIndex,queueIndex); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); +} + +static inline void HvCallEvent_setLpEventStack(u8 queueIndex, + char *eventStackAddr, u32 eventStackSize) +{ + u64 abs_addr; + + abs_addr = virt_to_abs(eventStackAddr); + HvCall3(HvCallEventSetLpEventStack, queueIndex, abs_addr, + eventStackSize); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); +} + +static inline void HvCallEvent_setLpEventQueueInterruptProc(u8 queueIndex, + u16 lpLogicalProcIndex) +{ + HvCall2(HvCallEventSetLpEventQueueInterruptProc, queueIndex, + lpLogicalProcIndex); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); +} + +static inline HvLpEvent_Rc HvCallEvent_signalLpEvent(struct HvLpEvent *event) +{ + u64 abs_addr; + HvLpEvent_Rc retVal; + +#ifdef DEBUG_SENDEVENT + printk("HvCallEvent_signalLpEvent: *event = %016lx\n ", + (unsigned long)event); +#endif + abs_addr = virt_to_abs(event); + retVal = (HvLpEvent_Rc)HvCall1(HvCallEventSignalLpEvent, abs_addr); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} + +static inline HvLpEvent_Rc HvCallEvent_signalLpEventFast(HvLpIndex targetLp, + HvLpEvent_Type type, u16 subtype, HvLpEvent_AckInd ackInd, + HvLpEvent_AckType ackType, HvLpInstanceId sourceInstanceId, + HvLpInstanceId targetInstanceId, u64 correlationToken, + u64 eventData1, u64 eventData2, u64 eventData3, + u64 eventData4, u64 eventData5) +{ + HvLpEvent_Rc retVal; + + // Pack the misc bits into a single Dword to pass to PLIC + union { + struct HvCallEvent_PackedParms parms; + u64 dword; + } packed; + packed.parms.xAckType = ackType; + packed.parms.xAckInd = ackInd; + packed.parms.xRsvd = 0; + packed.parms.xTargetLp = targetLp; + packed.parms.xType = type; + packed.parms.xSubtype = subtype; + packed.parms.xSourceInstId = sourceInstanceId; + packed.parms.xTargetInstId = targetInstanceId; + + retVal = (HvLpEvent_Rc)HvCall7(HvCallEventSignalLpEventParms, + packed.dword, correlationToken, eventData1,eventData2, + eventData3,eventData4, eventData5); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} + +static inline HvLpEvent_Rc HvCallEvent_ackLpEvent(struct HvLpEvent *event) +{ + u64 abs_addr; + HvLpEvent_Rc retVal; + + abs_addr = virt_to_abs(event); + retVal = (HvLpEvent_Rc)HvCall1(HvCallEventAckLpEvent, abs_addr); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} + +static inline HvLpEvent_Rc HvCallEvent_cancelLpEvent(struct HvLpEvent *event) +{ + u64 abs_addr; + HvLpEvent_Rc retVal; + + abs_addr = virt_to_abs(event); + retVal = (HvLpEvent_Rc)HvCall1(HvCallEventCancelLpEvent, abs_addr); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} + +static inline HvLpInstanceId HvCallEvent_getSourceLpInstanceId( + HvLpIndex targetLp, HvLpEvent_Type type) +{ + HvLpInstanceId retVal; + + retVal = HvCall2(HvCallEventGetSourceLpInstanceId, targetLp, type); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} + +static inline HvLpInstanceId HvCallEvent_getTargetLpInstanceId( + HvLpIndex targetLp, HvLpEvent_Type type) +{ + HvLpInstanceId retVal; + + retVal = HvCall2(HvCallEventGetTargetLpInstanceId, targetLp, type); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} + +static inline void HvCallEvent_openLpEventPath(HvLpIndex targetLp, + HvLpEvent_Type type) +{ + HvCall2(HvCallEventOpenLpEventPath, targetLp, type); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); +} + +static inline void HvCallEvent_closeLpEventPath(HvLpIndex targetLp, + HvLpEvent_Type type) +{ + HvCall2(HvCallEventCloseLpEventPath, targetLp, type); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); +} + +static inline HvLpDma_Rc HvCallEvent_dmaBufList(HvLpEvent_Type type, + HvLpIndex remoteLp, HvLpDma_Direction direction, + HvLpInstanceId localInstanceId, + HvLpInstanceId remoteInstanceId, + HvLpDma_AddressType localAddressType, + HvLpDma_AddressType remoteAddressType, + /* Do these need to be converted to absolute addresses? */ + u64 localBufList, u64 remoteBufList, u32 transferLength) +{ + HvLpDma_Rc retVal; + // Pack the misc bits into a single Dword to pass to PLIC + union { + struct HvCallEvent_PackedDmaParms parms; + u64 dword; + } packed; + + packed.parms.xDirection = direction; + packed.parms.xLocalAddrType = localAddressType; + packed.parms.xRemoteAddrType = remoteAddressType; + packed.parms.xRsvd1 = 0; + packed.parms.xRemoteLp = remoteLp; + packed.parms.xType = type; + packed.parms.xRsvd2 = 0; + packed.parms.xLocalInstId = localInstanceId; + packed.parms.xRemoteInstId = remoteInstanceId; + + retVal = (HvLpDma_Rc)HvCall4(HvCallEventDmaBufList, + packed.dword, localBufList, remoteBufList, + transferLength); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} + +static inline HvLpDma_Rc HvCallEvent_dmaSingle(HvLpEvent_Type type, + HvLpIndex remoteLp, HvLpDma_Direction direction, + HvLpInstanceId localInstanceId, + HvLpInstanceId remoteInstanceId, + HvLpDma_AddressType localAddressType, + HvLpDma_AddressType remoteAddressType, + u64 localAddrOrTce, u64 remoteAddrOrTce, u32 transferLength) +{ + HvLpDma_Rc retVal; + // Pack the misc bits into a single Dword to pass to PLIC + union { + struct HvCallEvent_PackedDmaParms parms; + u64 dword; + } packed; + + packed.parms.xDirection = direction; + packed.parms.xLocalAddrType = localAddressType; + packed.parms.xRemoteAddrType = remoteAddressType; + packed.parms.xRsvd1 = 0; + packed.parms.xRemoteLp = remoteLp; + packed.parms.xType = type; + packed.parms.xRsvd2 = 0; + packed.parms.xLocalInstId = localInstanceId; + packed.parms.xRemoteInstId = remoteInstanceId; + + retVal = (HvLpDma_Rc)HvCall4(HvCallEventDmaSingle, + packed.dword, localAddrOrTce, remoteAddrOrTce, + transferLength); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} + +static inline HvLpDma_Rc HvCallEvent_dmaToSp(void* local, u32 remote, + u32 length, HvLpDma_Direction dir) +{ + u64 abs_addr; + HvLpDma_Rc retVal; + + abs_addr = virt_to_abs(local); + retVal = (HvLpDma_Rc)HvCall4(HvCallEventDmaToSp, abs_addr, remote, + length, dir); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} + + +#endif /* _HVCALLEVENT_H */ diff --git a/include/asm-ppc64/iSeries/HvCallHpt.h b/include/asm-ppc64/iSeries/HvCallHpt.h new file mode 100644 index 000000000000..da769873d18b --- /dev/null +++ b/include/asm-ppc64/iSeries/HvCallHpt.h @@ -0,0 +1,127 @@ +/* + * HvCallHpt.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _HVCALLHPT_H +#define _HVCALLHPT_H + +//============================================================================ +// +// This file contains the "hypervisor call" interface which is used to +// drive the hypervisor from the OS. +// +//============================================================================ + +#include <asm/iSeries/HvCallSc.h> +#include <asm/iSeries/HvTypes.h> +#include <asm/mmu.h> + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +#define HvCallHptGetHptAddress HvCallHpt + 0 +#define HvCallHptGetHptPages HvCallHpt + 1 +#define HvCallHptSetPp HvCallHpt + 5 +#define HvCallHptSetSwBits HvCallHpt + 6 +#define HvCallHptUpdate HvCallHpt + 7 +#define HvCallHptInvalidateNoSyncICache HvCallHpt + 8 +#define HvCallHptGet HvCallHpt + 11 +#define HvCallHptFindNextValid HvCallHpt + 12 +#define HvCallHptFindValid HvCallHpt + 13 +#define HvCallHptAddValidate HvCallHpt + 16 +#define HvCallHptInvalidateSetSwBitsGet HvCallHpt + 18 + + +//============================================================================ +static inline u64 HvCallHpt_getHptAddress(void) +{ + u64 retval = HvCall0(HvCallHptGetHptAddress); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retval; +} +//============================================================================ +static inline u64 HvCallHpt_getHptPages(void) +{ + u64 retval = HvCall0(HvCallHptGetHptPages); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retval; +} +//============================================================================= +static inline void HvCallHpt_setPp(u32 hpteIndex, u8 value) +{ + HvCall2( HvCallHptSetPp, hpteIndex, value ); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); +} +//============================================================================= +static inline void HvCallHpt_setSwBits(u32 hpteIndex, u8 bitson, u8 bitsoff ) +{ + HvCall3( HvCallHptSetSwBits, hpteIndex, bitson, bitsoff ); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); +} +//============================================================================= +static inline void HvCallHpt_invalidateNoSyncICache(u32 hpteIndex) + +{ + HvCall1( HvCallHptInvalidateNoSyncICache, hpteIndex ); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); +} +//============================================================================= +static inline u64 HvCallHpt_invalidateSetSwBitsGet(u32 hpteIndex, u8 bitson, u8 bitsoff ) + +{ + u64 compressedStatus; + compressedStatus = HvCall4( HvCallHptInvalidateSetSwBitsGet, hpteIndex, bitson, bitsoff, 1 ); + HvCall1( HvCallHptInvalidateNoSyncICache, hpteIndex ); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return compressedStatus; +} +//============================================================================= +static inline u64 HvCallHpt_findValid( HPTE *hpte, u64 vpn ) +{ + u64 retIndex = HvCall3Ret16( HvCallHptFindValid, hpte, vpn, 0, 0 ); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retIndex; +} +//============================================================================= +static inline u64 HvCallHpt_findNextValid( HPTE *hpte, u32 hpteIndex, u8 bitson, u8 bitsoff ) +{ + u64 retIndex = HvCall3Ret16( HvCallHptFindNextValid, hpte, hpteIndex, bitson, bitsoff ); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retIndex; +} +//============================================================================= +static inline void HvCallHpt_get( HPTE *hpte, u32 hpteIndex ) +{ + HvCall2Ret16( HvCallHptGet, hpte, hpteIndex, 0 ); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); +} +//============================================================================ +static inline void HvCallHpt_addValidate( u32 hpteIndex, + u32 hBit, + HPTE *hpte ) + +{ + HvCall4( HvCallHptAddValidate, hpteIndex, + hBit, (*((u64 *)hpte)), (*(((u64 *)hpte)+1)) ); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); +} + + +//============================================================================= + +#endif /* _HVCALLHPT_H */ diff --git a/include/asm-ppc64/iSeries/HvCallPci.h b/include/asm-ppc64/iSeries/HvCallPci.h new file mode 100644 index 000000000000..6887b619288e --- /dev/null +++ b/include/asm-ppc64/iSeries/HvCallPci.h @@ -0,0 +1,673 @@ +/************************************************************************/ +/* Provides the Hypervisor PCI calls for iSeries Linux Parition. */ +/* Copyright (C) 2001 <Wayne G Holm> <IBM Corporation> */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the: */ +/* Free Software Foundation, Inc., */ +/* 59 Temple Place, Suite 330, */ +/* Boston, MA 02111-1307 USA */ +/************************************************************************/ +/* Change Activity: */ +/* Created, Jan 9, 2001 */ +/************************************************************************/ + +#ifndef _HVCALLPCI_H +#define _HVCALLPCI_H + +#include <asm/iSeries/HvCallSc.h> +#include <asm/iSeries/HvTypes.h> + +/* + * DSA == Direct Select Address + * this struct must be 64 bits in total + */ +struct HvCallPci_DsaAddr { + u16 busNumber; /* PHB index? */ + u8 subBusNumber; /* PCI bus number? */ + u8 deviceId; /* device and function? */ + u8 barNumber; + u8 reserved[3]; +}; + +union HvDsaMap { + u64 DsaAddr; + struct HvCallPci_DsaAddr Dsa; +}; + +struct HvCallPci_LoadReturn { + u64 rc; + u64 value; +}; + +enum HvCallPci_DeviceType { + HvCallPci_NodeDevice = 1, + HvCallPci_SpDevice = 2, + HvCallPci_IopDevice = 3, + HvCallPci_BridgeDevice = 4, + HvCallPci_MultiFunctionDevice = 5, + HvCallPci_IoaDevice = 6 +}; + + +struct HvCallPci_DeviceInfo { + u32 deviceType; // See DeviceType enum for values +}; + +struct HvCallPci_BusUnitInfo { + u32 sizeReturned; // length of data returned + u32 deviceType; // see DeviceType enum for values +}; + +struct HvCallPci_BridgeInfo { + struct HvCallPci_BusUnitInfo busUnitInfo; // Generic bus unit info + u8 subBusNumber; // Bus number of secondary bus + u8 maxAgents; // Max idsels on secondary bus + u8 maxSubBusNumber; // Max Sub Bus + u8 logicalSlotNumber; // Logical Slot Number for IOA +}; + + +// Maximum BusUnitInfo buffer size. Provided for clients so they can allocate +// a buffer big enough for any type of bus unit. Increase as needed. +enum {HvCallPci_MaxBusUnitInfoSize = 128}; + +struct HvCallPci_BarParms { + u64 vaddr; + u64 raddr; + u64 size; + u64 protectStart; + u64 protectEnd; + u64 relocationOffset; + u64 pciAddress; + u64 reserved[3]; +}; + +enum HvCallPci_VpdType { + HvCallPci_BusVpd = 1, + HvCallPci_BusAdapterVpd = 2 +}; + +#define HvCallPciConfigLoad8 HvCallPci + 0 +#define HvCallPciConfigLoad16 HvCallPci + 1 +#define HvCallPciConfigLoad32 HvCallPci + 2 +#define HvCallPciConfigStore8 HvCallPci + 3 +#define HvCallPciConfigStore16 HvCallPci + 4 +#define HvCallPciConfigStore32 HvCallPci + 5 +#define HvCallPciEoi HvCallPci + 16 +#define HvCallPciGetBarParms HvCallPci + 18 +#define HvCallPciMaskFisr HvCallPci + 20 +#define HvCallPciUnmaskFisr HvCallPci + 21 +#define HvCallPciSetSlotReset HvCallPci + 25 +#define HvCallPciGetDeviceInfo HvCallPci + 27 +#define HvCallPciGetCardVpd HvCallPci + 28 +#define HvCallPciBarLoad8 HvCallPci + 40 +#define HvCallPciBarLoad16 HvCallPci + 41 +#define HvCallPciBarLoad32 HvCallPci + 42 +#define HvCallPciBarLoad64 HvCallPci + 43 +#define HvCallPciBarStore8 HvCallPci + 44 +#define HvCallPciBarStore16 HvCallPci + 45 +#define HvCallPciBarStore32 HvCallPci + 46 +#define HvCallPciBarStore64 HvCallPci + 47 +#define HvCallPciMaskInterrupts HvCallPci + 48 +#define HvCallPciUnmaskInterrupts HvCallPci + 49 +#define HvCallPciGetBusUnitInfo HvCallPci + 50 + +//============================================================================ +static inline u64 HvCallPci_configLoad8(u16 busNumber, u8 subBusNumber, + u8 deviceId, u32 offset, + u8 *value) +{ + struct HvCallPci_DsaAddr dsa; + struct HvCallPci_LoadReturn retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumber; + dsa.subBusNumber = subBusNumber; + dsa.deviceId = deviceId; + + HvCall3Ret16(HvCallPciConfigLoad8, &retVal, *(u64 *)&dsa, offset, 0); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + *value = retVal.value; + + return retVal.rc; +} +//============================================================================ +static inline u64 HvCallPci_configLoad16(u16 busNumber, u8 subBusNumber, + u8 deviceId, u32 offset, + u16 *value) +{ + struct HvCallPci_DsaAddr dsa; + struct HvCallPci_LoadReturn retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumber; + dsa.subBusNumber = subBusNumber; + dsa.deviceId = deviceId; + + HvCall3Ret16(HvCallPciConfigLoad16, &retVal, *(u64 *)&dsa, offset, 0); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + *value = retVal.value; + + return retVal.rc; +} +//============================================================================ +static inline u64 HvCallPci_configLoad32(u16 busNumber, u8 subBusNumber, + u8 deviceId, u32 offset, + u32 *value) +{ + struct HvCallPci_DsaAddr dsa; + struct HvCallPci_LoadReturn retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumber; + dsa.subBusNumber = subBusNumber; + dsa.deviceId = deviceId; + + HvCall3Ret16(HvCallPciConfigLoad32, &retVal, *(u64 *)&dsa, offset, 0); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + *value = retVal.value; + + return retVal.rc; +} +//============================================================================ +static inline u64 HvCallPci_configStore8(u16 busNumber, u8 subBusNumber, + u8 deviceId, u32 offset, + u8 value) +{ + struct HvCallPci_DsaAddr dsa; + u64 retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumber; + dsa.subBusNumber = subBusNumber; + dsa.deviceId = deviceId; + + retVal = HvCall4(HvCallPciConfigStore8, *(u64 *)&dsa, offset, value, 0); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + return retVal; +} +//============================================================================ +static inline u64 HvCallPci_configStore16(u16 busNumber, u8 subBusNumber, + u8 deviceId, u32 offset, + u16 value) +{ + struct HvCallPci_DsaAddr dsa; + u64 retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumber; + dsa.subBusNumber = subBusNumber; + dsa.deviceId = deviceId; + + retVal = HvCall4(HvCallPciConfigStore16, *(u64 *)&dsa, offset, value, 0); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + return retVal; +} +//============================================================================ +static inline u64 HvCallPci_configStore32(u16 busNumber, u8 subBusNumber, + u8 deviceId, u32 offset, + u32 value) +{ + struct HvCallPci_DsaAddr dsa; + u64 retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumber; + dsa.subBusNumber = subBusNumber; + dsa.deviceId = deviceId; + + retVal = HvCall4(HvCallPciConfigStore32, *(u64 *)&dsa, offset, value, 0); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + return retVal; +} +//============================================================================ +static inline u64 HvCallPci_barLoad8(u16 busNumberParm, + u8 subBusParm, + u8 deviceIdParm, + u8 barNumberParm, + u64 offsetParm, + u8* valueParm) +{ + struct HvCallPci_DsaAddr dsa; + struct HvCallPci_LoadReturn retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumberParm; + dsa.subBusNumber = subBusParm; + dsa.deviceId = deviceIdParm; + dsa.barNumber = barNumberParm; + + HvCall3Ret16(HvCallPciBarLoad8, &retVal, *(u64 *)&dsa, offsetParm, 0); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + *valueParm = retVal.value; + + return retVal.rc; +} +//============================================================================ +static inline u64 HvCallPci_barLoad16(u16 busNumberParm, + u8 subBusParm, + u8 deviceIdParm, + u8 barNumberParm, + u64 offsetParm, + u16* valueParm) +{ + struct HvCallPci_DsaAddr dsa; + struct HvCallPci_LoadReturn retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumberParm; + dsa.subBusNumber = subBusParm; + dsa.deviceId = deviceIdParm; + dsa.barNumber = barNumberParm; + + HvCall3Ret16(HvCallPciBarLoad16, &retVal, *(u64 *)&dsa, offsetParm, 0); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + *valueParm = retVal.value; + + return retVal.rc; +} +//============================================================================ +static inline u64 HvCallPci_barLoad32(u16 busNumberParm, + u8 subBusParm, + u8 deviceIdParm, + u8 barNumberParm, + u64 offsetParm, + u32* valueParm) +{ + struct HvCallPci_DsaAddr dsa; + struct HvCallPci_LoadReturn retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumberParm; + dsa.subBusNumber = subBusParm; + dsa.deviceId = deviceIdParm; + dsa.barNumber = barNumberParm; + + HvCall3Ret16(HvCallPciBarLoad32, &retVal, *(u64 *)&dsa, offsetParm, 0); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + *valueParm = retVal.value; + + return retVal.rc; +} +//============================================================================ +static inline u64 HvCallPci_barLoad64(u16 busNumberParm, + u8 subBusParm, + u8 deviceIdParm, + u8 barNumberParm, + u64 offsetParm, + u64* valueParm) +{ + struct HvCallPci_DsaAddr dsa; + struct HvCallPci_LoadReturn retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumberParm; + dsa.subBusNumber = subBusParm; + dsa.deviceId = deviceIdParm; + dsa.barNumber = barNumberParm; + + HvCall3Ret16(HvCallPciBarLoad64, &retVal, *(u64 *)&dsa, offsetParm, 0); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + *valueParm = retVal.value; + + return retVal.rc; +} +//============================================================================ +static inline u64 HvCallPci_barStore8(u16 busNumberParm, + u8 subBusParm, + u8 deviceIdParm, + u8 barNumberParm, + u64 offsetParm, + u8 valueParm) +{ + struct HvCallPci_DsaAddr dsa; + u64 retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumberParm; + dsa.subBusNumber = subBusParm; + dsa.deviceId = deviceIdParm; + dsa.barNumber = barNumberParm; + + retVal = HvCall4(HvCallPciBarStore8, *(u64 *)&dsa, offsetParm, valueParm, 0); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + return retVal; +} +//============================================================================ +static inline u64 HvCallPci_barStore16(u16 busNumberParm, + u8 subBusParm, + u8 deviceIdParm, + u8 barNumberParm, + u64 offsetParm, + u16 valueParm) +{ + struct HvCallPci_DsaAddr dsa; + u64 retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumberParm; + dsa.subBusNumber = subBusParm; + dsa.deviceId = deviceIdParm; + dsa.barNumber = barNumberParm; + + retVal = HvCall4(HvCallPciBarStore16, *(u64 *)&dsa, offsetParm, valueParm, 0); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + return retVal; +} +//============================================================================ +static inline u64 HvCallPci_barStore32(u16 busNumberParm, + u8 subBusParm, + u8 deviceIdParm, + u8 barNumberParm, + u64 offsetParm, + u32 valueParm) +{ + struct HvCallPci_DsaAddr dsa; + u64 retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumberParm; + dsa.subBusNumber = subBusParm; + dsa.deviceId = deviceIdParm; + dsa.barNumber = barNumberParm; + + retVal = HvCall4(HvCallPciBarStore32, *(u64 *)&dsa, offsetParm, valueParm, 0); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + return retVal; +} +//============================================================================ +static inline u64 HvCallPci_barStore64(u16 busNumberParm, + u8 subBusParm, + u8 deviceIdParm, + u8 barNumberParm, + u64 offsetParm, + u64 valueParm) +{ + struct HvCallPci_DsaAddr dsa; + u64 retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumberParm; + dsa.subBusNumber = subBusParm; + dsa.deviceId = deviceIdParm; + dsa.barNumber = barNumberParm; + + retVal = HvCall4(HvCallPciBarStore64, *(u64 *)&dsa, offsetParm, valueParm, 0); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + return retVal; +} +//============================================================================ +static inline u64 HvCallPci_eoi(u16 busNumberParm, + u8 subBusParm, + u8 deviceIdParm) +{ + struct HvCallPci_DsaAddr dsa; + struct HvCallPci_LoadReturn retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumberParm; + dsa.subBusNumber = subBusParm; + dsa.deviceId = deviceIdParm; + + HvCall1Ret16(HvCallPciEoi, &retVal, *(u64*)&dsa); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + return retVal.rc; +} +//============================================================================ +static inline u64 HvCallPci_getBarParms(u16 busNumberParm, + u8 subBusParm, + u8 deviceIdParm, + u8 barNumberParm, + u64 parms, + u32 sizeofParms) +{ + struct HvCallPci_DsaAddr dsa; + u64 retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumberParm; + dsa.subBusNumber = subBusParm; + dsa.deviceId = deviceIdParm; + dsa.barNumber = barNumberParm; + + retVal = HvCall3(HvCallPciGetBarParms, *(u64*)&dsa, parms, sizeofParms); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + return retVal; +} +//============================================================================ +static inline u64 HvCallPci_maskFisr(u16 busNumberParm, + u8 subBusParm, + u8 deviceIdParm, + u64 fisrMask) +{ + struct HvCallPci_DsaAddr dsa; + u64 retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumberParm; + dsa.subBusNumber = subBusParm; + dsa.deviceId = deviceIdParm; + + retVal = HvCall2(HvCallPciMaskFisr, *(u64*)&dsa, fisrMask); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + return retVal; +} +//============================================================================ +static inline u64 HvCallPci_unmaskFisr(u16 busNumberParm, + u8 subBusParm, + u8 deviceIdParm, + u64 fisrMask) +{ + struct HvCallPci_DsaAddr dsa; + u64 retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumberParm; + dsa.subBusNumber = subBusParm; + dsa.deviceId = deviceIdParm; + + retVal = HvCall2(HvCallPciUnmaskFisr, *(u64*)&dsa, fisrMask); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + return retVal; +} +//============================================================================ +static inline u64 HvCallPci_setSlotReset(u16 busNumberParm, + u8 subBusParm, + u8 deviceIdParm, + u64 onNotOff) +{ + struct HvCallPci_DsaAddr dsa; + u64 retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumberParm; + dsa.subBusNumber = subBusParm; + dsa.deviceId = deviceIdParm; + + retVal = HvCall2(HvCallPciSetSlotReset, *(u64*)&dsa, onNotOff); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + return retVal; +} +//============================================================================ +static inline u64 HvCallPci_getDeviceInfo(u16 busNumberParm, + u8 subBusParm, + u8 deviceNumberParm, + u64 parms, + u32 sizeofParms) +{ + struct HvCallPci_DsaAddr dsa; + u64 retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumberParm; + dsa.subBusNumber = subBusParm; + dsa.deviceId = deviceNumberParm << 4; + + retVal = HvCall3(HvCallPciGetDeviceInfo, *(u64*)&dsa, parms, sizeofParms); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + return retVal; +} +//============================================================================ +static inline u64 HvCallPci_maskInterrupts(u16 busNumberParm, + u8 subBusParm, + u8 deviceIdParm, + u64 interruptMask) +{ + struct HvCallPci_DsaAddr dsa; + u64 retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumberParm; + dsa.subBusNumber = subBusParm; + dsa.deviceId = deviceIdParm; + + retVal = HvCall2(HvCallPciMaskInterrupts, *(u64*)&dsa, interruptMask); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + return retVal; +} +//============================================================================ +static inline u64 HvCallPci_unmaskInterrupts(u16 busNumberParm, + u8 subBusParm, + u8 deviceIdParm, + u64 interruptMask) +{ + struct HvCallPci_DsaAddr dsa; + u64 retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumberParm; + dsa.subBusNumber = subBusParm; + dsa.deviceId = deviceIdParm; + + retVal = HvCall2(HvCallPciUnmaskInterrupts, *(u64*)&dsa, interruptMask); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + return retVal; +} +//============================================================================ + +static inline u64 HvCallPci_getBusUnitInfo(u16 busNumberParm, + u8 subBusParm, + u8 deviceIdParm, + u64 parms, + u32 sizeofParms) +{ + struct HvCallPci_DsaAddr dsa; + u64 retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumberParm; + dsa.subBusNumber = subBusParm; + dsa.deviceId = deviceIdParm; + + retVal = HvCall3(HvCallPciGetBusUnitInfo, *(u64*)&dsa, parms, sizeofParms); + + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + + return retVal; +} +//============================================================================ + +static inline int HvCallPci_getBusVpd(u16 busNumParm, u64 destParm, u16 sizeParm) +{ + int xRetSize; + u64 xRc = HvCall4(HvCallPciGetCardVpd, busNumParm, destParm, sizeParm, HvCallPci_BusVpd); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + if (xRc == -1) + xRetSize = -1; + else + xRetSize = xRc & 0xFFFF; + return xRetSize; +} +//============================================================================ + +static inline int HvCallPci_getBusAdapterVpd(u16 busNumParm, u64 destParm, u16 sizeParm) +{ + int xRetSize; + u64 xRc = HvCall4(HvCallPciGetCardVpd, busNumParm, destParm, sizeParm, HvCallPci_BusAdapterVpd); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + if (xRc == -1) + xRetSize = -1; + else + xRetSize = xRc & 0xFFFF; + return xRetSize; +} +//============================================================================ +#endif /* _HVCALLPCI_H */ diff --git a/include/asm-ppc64/iSeries/HvCallSc.h b/include/asm-ppc64/iSeries/HvCallSc.h new file mode 100644 index 000000000000..eea258447642 --- /dev/null +++ b/include/asm-ppc64/iSeries/HvCallSc.h @@ -0,0 +1,51 @@ +/* + * HvCallSc.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _HVCALLSC_H +#define _HVCALLSC_H + +#include <asm/iSeries/HvTypes.h> + +#define HvCallBase 0x8000000000000000ul +#define HvCallCc 0x8001000000000000ul +#define HvCallCfg 0x8002000000000000ul +#define HvCallEvent 0x8003000000000000ul +#define HvCallHpt 0x8004000000000000ul +#define HvCallPci 0x8005000000000000ul +#define HvCallSm 0x8007000000000000ul +#define HvCallXm 0x8009000000000000ul + +u64 HvCall0( u64 ); +u64 HvCall1( u64, u64 ); +u64 HvCall2( u64, u64, u64 ); +u64 HvCall3( u64, u64, u64, u64 ); +u64 HvCall4( u64, u64, u64, u64, u64 ); +u64 HvCall5( u64, u64, u64, u64, u64, u64 ); +u64 HvCall6( u64, u64, u64, u64, u64, u64, u64 ); +u64 HvCall7( u64, u64, u64, u64, u64, u64, u64, u64 ); + +u64 HvCall0Ret16( u64, void * ); +u64 HvCall1Ret16( u64, void *, u64 ); +u64 HvCall2Ret16( u64, void *, u64, u64 ); +u64 HvCall3Ret16( u64, void *, u64, u64, u64 ); +u64 HvCall4Ret16( u64, void *, u64, u64, u64, u64 ); +u64 HvCall5Ret16( u64, void *, u64, u64, u64, u64, u64 ); +u64 HvCall6Ret16( u64, void *, u64, u64, u64, u64, u64, u64 ); +u64 HvCall7Ret16( u64, void *, u64, u64 ,u64 ,u64 ,u64 ,u64 ,u64 ); + +#endif /* _HVCALLSC_H */ diff --git a/include/asm-ppc64/iSeries/HvCallSm.h b/include/asm-ppc64/iSeries/HvCallSm.h new file mode 100644 index 000000000000..9050c94a529d --- /dev/null +++ b/include/asm-ppc64/iSeries/HvCallSm.h @@ -0,0 +1,52 @@ +/* + * HvCallSm.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _HVCALLSM_H +#define _HVCALLSM_H + +//============================================================================ +// +// This file contains the "hypervisor call" interface which is used to +// drive the hypervisor from the OS. +// +//============================================================================ + +//------------------------------------------------------------------- +// Standard Includes +//------------------------------------------------------------------- +#include <asm/iSeries/HvCallSc.h> +#include <asm/iSeries/HvTypes.h> + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +#define HvCallSmGet64BitsOfAccessMap HvCallSm + 11 + + +//============================================================================ +static inline u64 HvCallSm_get64BitsOfAccessMap( + HvLpIndex lpIndex, u64 indexIntoBitMap ) +{ + u64 retval = HvCall2(HvCallSmGet64BitsOfAccessMap, lpIndex, + indexIntoBitMap ); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retval; +} +//============================================================================ +#endif /* _HVCALLSM_H */ diff --git a/include/asm-ppc64/iSeries/HvCallXm.h b/include/asm-ppc64/iSeries/HvCallXm.h new file mode 100644 index 000000000000..bfb898f4db8d --- /dev/null +++ b/include/asm-ppc64/iSeries/HvCallXm.h @@ -0,0 +1,95 @@ +//============================================================================ +// Header File Id +// Name______________: HvCallXm.H +// +// Description_______: +// +// This file contains the "hypervisor call" interface which is used to +// drive the hypervisor from SLIC. +// +//============================================================================ +#ifndef _HVCALLXM_H +#define _HVCALLXM_H + +//------------------------------------------------------------------- +// Forward declarations +//------------------------------------------------------------------- + +//------------------------------------------------------------------- +// Standard Includes +//------------------------------------------------------------------- +#include <asm/iSeries/HvCallSc.h> +#include <asm/iSeries/HvTypes.h> + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +#define HvCallXmGetTceTableParms HvCallXm + 0 +#define HvCallXmTestBus HvCallXm + 1 +#define HvCallXmConnectBusUnit HvCallXm + 2 +#define HvCallXmLoadTod HvCallXm + 8 +#define HvCallXmTestBusUnit HvCallXm + 9 +#define HvCallXmSetTce HvCallXm + 11 +#define HvCallXmSetTces HvCallXm + 13 + + + +//============================================================================ +static inline void HvCallXm_getTceTableParms(u64 cb) +{ + HvCall1(HvCallXmGetTceTableParms, cb); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); +} +//============================================================================ +static inline u64 HvCallXm_setTce(u64 tceTableToken, u64 tceOffset, u64 tce) +{ + u64 retval = HvCall3(HvCallXmSetTce, tceTableToken, tceOffset, tce ); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retval; +} +//============================================================================ +static inline u64 HvCallXm_setTces(u64 tceTableToken, u64 tceOffset, u64 numTces, u64 tce1, u64 tce2, u64 tce3, u64 tce4) +{ + u64 retval = HvCall7(HvCallXmSetTces, tceTableToken, tceOffset, numTces, + tce1, tce2, tce3, tce4 ); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retval; +} +//============================================================================= +static inline u64 HvCallXm_testBus(u16 busNumber) +{ + u64 retVal = HvCall1(HvCallXmTestBus, busNumber); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} +//===================================================================================== +static inline u64 HvCallXm_testBusUnit(u16 busNumber, u8 subBusNumber, u8 deviceId) +{ + u64 busUnitNumber = (subBusNumber << 8) | deviceId; + u64 retVal = HvCall2(HvCallXmTestBusUnit, busNumber, busUnitNumber); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} +//===================================================================================== +static inline u64 HvCallXm_connectBusUnit(u16 busNumber, u8 subBusNumber, u8 deviceId, + u64 interruptToken) +{ + u64 busUnitNumber = (subBusNumber << 8) | deviceId; + u64 queueIndex = 0; // HvLpConfig::mapDsaToQueueIndex(HvLpDSA(busNumber, xBoard, xCard)); + + u64 retVal = HvCall5(HvCallXmConnectBusUnit, busNumber, busUnitNumber, + interruptToken, 0, queueIndex); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} +//===================================================================================== +static inline u64 HvCallXm_loadTod(void) +{ + u64 retVal = HvCall0(HvCallXmLoadTod); + // getPaca()->adjustHmtForNoOfSpinLocksHeld(); + return retVal; +} +//===================================================================================== + +#endif /* _HVCALLXM_H */ diff --git a/include/asm-ppc64/iSeries/HvLpConfig.h b/include/asm-ppc64/iSeries/HvLpConfig.h new file mode 100644 index 000000000000..bdbd70f42c9d --- /dev/null +++ b/include/asm-ppc64/iSeries/HvLpConfig.h @@ -0,0 +1,280 @@ +/* + * HvLpConfig.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _HVLPCONFIG_H +#define _HVLPCONFIG_H + +//=========================================================================== +// +// This file contains the interface to the LPAR configuration data +// to determine which resources should be allocated to each partition. +// +//=========================================================================== + +#include <asm/iSeries/HvCallCfg.h> +#include <asm/iSeries/HvTypes.h> +#include <asm/iSeries/ItLpNaca.h> +#include <asm/iSeries/LparData.h> + +//------------------------------------------------------------------- +// Constants +//------------------------------------------------------------------- + +extern HvLpIndex HvLpConfig_getLpIndex_outline(void); + +//=================================================================== +static inline HvLpIndex HvLpConfig_getLpIndex(void) +{ + return itLpNaca.xLpIndex; +} +//=================================================================== +static inline HvLpIndex HvLpConfig_getPrimaryLpIndex(void) +{ + return itLpNaca.xPrimaryLpIndex; +} +//================================================================= +static inline HvLpIndex HvLpConfig_getLps(void) +{ + return HvCallCfg_getLps(); +} +//================================================================= +static inline HvLpIndexMap HvLpConfig_getActiveLpMap(void) +{ + return HvCallCfg_getActiveLpMap(); +} +//================================================================= +static inline u64 HvLpConfig_getSystemMsMegs(void) +{ + return HvCallCfg_getSystemMsChunks() / HVCHUNKSPERMEG; +} +//================================================================= +static inline u64 HvLpConfig_getSystemMsChunks(void) +{ + return HvCallCfg_getSystemMsChunks(); +} +//================================================================= +static inline u64 HvLpConfig_getSystemMsPages(void) +{ + return HvCallCfg_getSystemMsChunks() * HVPAGESPERCHUNK; +} +//================================================================ +static inline u64 HvLpConfig_getMsMegs(void) +{ + return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Cur) / HVCHUNKSPERMEG; +} +//================================================================ +static inline u64 HvLpConfig_getMsChunks(void) +{ + return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Cur); +} +//================================================================ +static inline u64 HvLpConfig_getMsPages(void) +{ + return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Cur) * HVPAGESPERCHUNK; +} +//================================================================ +static inline u64 HvLpConfig_getMinMsMegs(void) +{ + return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Min) / HVCHUNKSPERMEG; +} +//================================================================ +static inline u64 HvLpConfig_getMinMsChunks(void) +{ + return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Min); +} +//================================================================ +static inline u64 HvLpConfig_getMinMsPages(void) +{ + return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Min) * HVPAGESPERCHUNK; +} +//================================================================ +static inline u64 HvLpConfig_getMinRuntimeMsMegs(void) +{ + return HvCallCfg_getMinRuntimeMsChunks(HvLpConfig_getLpIndex()) / HVCHUNKSPERMEG; +} +//=============================================================== +static inline u64 HvLpConfig_getMinRuntimeMsChunks(void) +{ + return HvCallCfg_getMinRuntimeMsChunks(HvLpConfig_getLpIndex()); +} +//=============================================================== +static inline u64 HvLpConfig_getMinRuntimeMsPages(void) +{ + return HvCallCfg_getMinRuntimeMsChunks(HvLpConfig_getLpIndex()) * HVPAGESPERCHUNK; +} +//=============================================================== +static inline u64 HvLpConfig_getMaxMsMegs(void) +{ + return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Max) / HVCHUNKSPERMEG; +} +//=============================================================== +static inline u64 HvLpConfig_getMaxMsChunks(void) +{ + return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Max); +} +//=============================================================== +static inline u64 HvLpConfig_getMaxMsPages(void) +{ + return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Max) * HVPAGESPERCHUNK; +} +//=============================================================== +static inline u64 HvLpConfig_getInitMsMegs(void) +{ + return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Init) / HVCHUNKSPERMEG; +} +//=============================================================== +static inline u64 HvLpConfig_getInitMsChunks(void) +{ + return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Init); +} +//=============================================================== +static inline u64 HvLpConfig_getInitMsPages(void) +{ return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Init) * HVPAGESPERCHUNK; +} +//=============================================================== +static inline u64 HvLpConfig_getSystemPhysicalProcessors(void) +{ + return HvCallCfg_getSystemPhysicalProcessors(); +} +//=============================================================== +static inline u64 HvLpConfig_getSystemLogicalProcessors(void) +{ + return HvCallCfg_getSystemPhysicalProcessors() * (/*getPaca()->getSecondaryThreadCount() +*/ 1); +} +//=============================================================== +static inline u64 HvLpConfig_getNumProcsInSharedPool(HvLpSharedPoolIndex sPI) +{ + return HvCallCfg_getNumProcsInSharedPool(sPI); +} +//=============================================================== +static inline u64 HvLpConfig_getPhysicalProcessors(void) +{ + return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Cur); +} +//=============================================================== +static inline u64 HvLpConfig_getLogicalProcessors(void) +{ + return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Cur) * (/*getPaca()->getSecondaryThreadCount() +*/ 1); +} +//=============================================================== +static inline HvLpSharedPoolIndex HvLpConfig_getSharedPoolIndex(void) +{ + return HvCallCfg_getSharedPoolIndex(HvLpConfig_getLpIndex()); +} +//=============================================================== +static inline u64 HvLpConfig_getSharedProcUnits(void) +{ + return HvCallCfg_getSharedProcUnits(HvLpConfig_getLpIndex(),HvCallCfg_Cur); +} +//=============================================================== +static inline u64 HvLpConfig_getMinSharedProcUnits(void) +{ + return HvCallCfg_getSharedProcUnits(HvLpConfig_getLpIndex(),HvCallCfg_Min); +} +//=============================================================== +static inline u64 HvLpConfig_getMaxSharedProcUnits(void) +{ + return HvCallCfg_getSharedProcUnits(HvLpConfig_getLpIndex(),HvCallCfg_Max); +} +//=============================================================== +static inline u64 HvLpConfig_getMinPhysicalProcessors(void) +{ + return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Min); +} +//=============================================================== +static inline u64 HvLpConfig_getMinLogicalProcessors(void) +{ + return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Min) * (/*getPaca()->getSecondaryThreadCount() +*/ 1); +} +//=============================================================== +static inline u64 HvLpConfig_getMaxPhysicalProcessors(void) +{ + return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Max); +} +//=============================================================== +static inline u64 HvLpConfig_getMaxLogicalProcessors(void) +{ + return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Max) * (/*getPaca()->getSecondaryThreadCount() +*/ 1); +} +//=============================================================== +static inline u64 HvLpConfig_getInitPhysicalProcessors(void) +{ + return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Init); +} +//=============================================================== +static inline u64 HvLpConfig_getInitLogicalProcessors(void) +{ + return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Init) * (/*getPaca()->getSecondaryThreadCount() +*/ 1); +} +//================================================================ +static inline HvLpVirtualLanIndexMap HvLpConfig_getVirtualLanIndexMap(void) +{ + return HvCallCfg_getVirtualLanIndexMap(HvLpConfig_getLpIndex_outline()); +} +//=============================================================== +static inline HvLpVirtualLanIndexMap HvLpConfig_getVirtualLanIndexMapForLp(HvLpIndex lp) +{ + return HvCallCfg_getVirtualLanIndexMap(lp); +} +//================================================================ +static inline HvLpIndex HvLpConfig_getBusOwner(HvBusNumber busNumber) +{ + return HvCallCfg_getBusOwner(busNumber); +} +//=============================================================== +static inline int HvLpConfig_isBusDedicated(HvBusNumber busNumber) +{ + return HvCallCfg_isBusDedicated(busNumber); +} +//================================================================ +static inline HvLpIndexMap HvLpConfig_getBusAllocation(HvBusNumber busNumber) +{ + return HvCallCfg_getBusAllocation(busNumber); +} +//================================================================ +// returns the absolute real address of the load area +static inline u64 HvLpConfig_getLoadAddress(void) +{ + return itLpNaca.xLoadAreaAddr & 0x7fffffffffffffff; +} +//================================================================ +static inline u64 HvLpConfig_getLoadPages(void) +{ + return itLpNaca.xLoadAreaChunks * HVPAGESPERCHUNK; +} +//================================================================ +static inline int HvLpConfig_isBusOwnedByThisLp(HvBusNumber busNumber) +{ + HvLpIndex busOwner = HvLpConfig_getBusOwner(busNumber); + return (busOwner == HvLpConfig_getLpIndex()); +} +//================================================================ +static inline int HvLpConfig_doLpsCommunicateOnVirtualLan(HvLpIndex lp1, HvLpIndex lp2) +{ + HvLpVirtualLanIndexMap virtualLanIndexMap1 = HvCallCfg_getVirtualLanIndexMap( lp1 ); + HvLpVirtualLanIndexMap virtualLanIndexMap2 = HvCallCfg_getVirtualLanIndexMap( lp2 ); + return ((virtualLanIndexMap1 & virtualLanIndexMap2) != 0); +} +//================================================================ +static inline HvLpIndex HvLpConfig_getHostingLpIndex(HvLpIndex lp) +{ + return HvCallCfg_getHostingLpIndex(lp); +} +//================================================================ + +#endif /* _HVLPCONFIG_H */ diff --git a/include/asm-ppc64/iSeries/HvLpEvent.h b/include/asm-ppc64/iSeries/HvLpEvent.h new file mode 100644 index 000000000000..30936e433064 --- /dev/null +++ b/include/asm-ppc64/iSeries/HvLpEvent.h @@ -0,0 +1,144 @@ +/* + * HvLpEvent.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +//====================================================================== +// +// This file contains the class for HV events in the system. +// +//===================================================================== +#ifndef _HVLPEVENT_H +#define _HVLPEVENT_H + +#include <asm/types.h> +#include <asm/ptrace.h> +#include <asm/iSeries/HvTypes.h> +#include <asm/iSeries/HvCallEvent.h> + +//===================================================================== +// +// HvLpEvent is the structure for Lp Event messages passed between +// partitions through PLIC. +// +//===================================================================== + +struct HvEventFlags +{ + u8 xValid:1; // Indicates a valid request x00-x00 + u8 xRsvd1:4; // Reserved ... + u8 xAckType:1; // Immediate or deferred ... + u8 xAckInd:1; // Indicates if ACK required ... + u8 xFunction:1; // Interrupt or Acknowledge ... +}; + + +struct HvLpEvent +{ + struct HvEventFlags xFlags; // Event flags x00-x00 + u8 xType; // Type of message x01-x01 + u16 xSubtype; // Subtype for event x02-x03 + u8 xSourceLp; // Source LP x04-x04 + u8 xTargetLp; // Target LP x05-x05 + u8 xSizeMinus1; // Size of Derived class - 1 x06-x06 + u8 xRc; // RC for Ack flows x07-x07 + u16 xSourceInstanceId; // Source sides instance id x08-x09 + u16 xTargetInstanceId; // Target sides instance id x0A-x0B + union { + u32 xSubtypeData; // Data usable by the subtype x0C-x0F + u16 xSubtypeDataShort[2]; // Data as 2 shorts + u8 xSubtypeDataChar[4]; // Data as 4 chars + } x; + + u64 xCorrelationToken; // Unique value for source/type x10-x17 +}; + +// Lp Event handler function +typedef void (*LpEventHandler)(struct HvLpEvent *, struct pt_regs *); + +// Register a handler for an event type +// returns 0 on success +extern int HvLpEvent_registerHandler( HvLpEvent_Type eventType, LpEventHandler hdlr); + +// Unregister a handler for an event type +// This call will sleep until the handler being removed is guaranteed to +// be no longer executing on any CPU. Do not call with locks held. +// +// returns 0 on success +// Unregister will fail if there are any paths open for the type +extern int HvLpEvent_unregisterHandler( HvLpEvent_Type eventType ); + +// Open an Lp Event Path for an event type +// returns 0 on success +// openPath will fail if there is no handler registered for the event type. +// The lpIndex specified is the partition index for the target partition +// (for VirtualIo, VirtualLan and SessionMgr) other types specify zero) +extern int HvLpEvent_openPath( HvLpEvent_Type eventType, HvLpIndex lpIndex ); + + +// Close an Lp Event Path for a type and partition +// returns 0 on sucess +extern int HvLpEvent_closePath( HvLpEvent_Type eventType, HvLpIndex lpIndex ); + +#define HvLpEvent_Type_Hypervisor 0 +#define HvLpEvent_Type_MachineFac 1 +#define HvLpEvent_Type_SessionMgr 2 +#define HvLpEvent_Type_SpdIo 3 +#define HvLpEvent_Type_VirtualBus 4 +#define HvLpEvent_Type_PciIo 5 +#define HvLpEvent_Type_RioIo 6 +#define HvLpEvent_Type_VirtualLan 7 +#define HvLpEvent_Type_VirtualIo 8 +#define HvLpEvent_Type_NumTypes 9 + +#define HvLpEvent_Rc_Good 0 +#define HvLpEvent_Rc_BufferNotAvailable 1 +#define HvLpEvent_Rc_Cancelled 2 +#define HvLpEvent_Rc_GenericError 3 +#define HvLpEvent_Rc_InvalidAddress 4 +#define HvLpEvent_Rc_InvalidPartition 5 +#define HvLpEvent_Rc_InvalidSize 6 +#define HvLpEvent_Rc_InvalidSubtype 7 +#define HvLpEvent_Rc_InvalidSubtypeData 8 +#define HvLpEvent_Rc_InvalidType 9 +#define HvLpEvent_Rc_PartitionDead 10 +#define HvLpEvent_Rc_PathClosed 11 +#define HvLpEvent_Rc_SubtypeError 12 + +#define HvLpEvent_Function_Ack 0 +#define HvLpEvent_Function_Int 1 + +#define HvLpEvent_AckInd_NoAck 0 +#define HvLpEvent_AckInd_DoAck 1 + +#define HvLpEvent_AckType_ImmediateAck 0 +#define HvLpEvent_AckType_DeferredAck 1 + +#define HvLpDma_Direction_LocalToRemote 0 +#define HvLpDma_Direction_RemoteToLocal 1 + +#define HvLpDma_AddressType_TceIndex 0 +#define HvLpDma_AddressType_RealAddress 1 + +#define HvLpDma_Rc_Good 0 +#define HvLpDma_Rc_Error 1 +#define HvLpDma_Rc_PartitionDead 2 +#define HvLpDma_Rc_PathClosed 3 +#define HvLpDma_Rc_InvalidAddress 4 +#define HvLpDma_Rc_InvalidLength 5 + +#endif // _HVLPEVENT_H diff --git a/include/asm-ppc64/iSeries/HvReleaseData.h b/include/asm-ppc64/iSeries/HvReleaseData.h new file mode 100644 index 000000000000..183e5e738c26 --- /dev/null +++ b/include/asm-ppc64/iSeries/HvReleaseData.h @@ -0,0 +1,65 @@ +/* + * HvReleaseData.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _HVRELEASEDATA_H +#define _HVRELEASEDATA_H + +//============================================================================= +// +// This control block contains the critical information about the +// release so that it can be changed in the future (ie, the virtual +// address of the OS's NACA). +// +#include <asm/types.h> +#include <asm/naca.h> + +//============================================================================= +// +// When we IPL a secondary partition, we will check if if the +// secondary xMinPlicVrmIndex > the primary xVrmIndex. +// If it is then this tells PLIC that this secondary is not +// supported running on this "old" of a level of PLIC. +// +// Likewise, we will compare the primary xMinSlicVrmIndex to +// the secondary xVrmIndex. +// If the primary xMinSlicVrmDelta > secondary xVrmDelta then we +// know that this PLIC does not support running an OS "that old". +// +//============================================================================= + +struct HvReleaseData +{ + u32 xDesc; // Descriptor "HvRD" ebcdic x00-x03 + u16 xSize; // Size of this control block x04-x05 + u16 xVpdAreasPtrOffset; // Offset in NACA of ItVpdAreas x06-x07 + struct naca_struct * xSlicNacaAddr; // Virt addr of SLIC NACA x08-x0F + u32 xMsNucDataOffset; // Offset of Linux Mapping Data x10-x13 + u32 xRsvd1; // Reserved x14-x17 + u16 xTagsMode:1; // 0 == tags active, 1 == tags inactive + u16 xAddressSize:1; // 0 == 64-bit, 1 == 32-bit + u16 xNoSharedProcs:1; // 0 == shared procs, 1 == no shared + u16 xNoHMT:1; // 0 == allow HMT, 1 == no HMT + u16 xRsvd2:12; // Reserved x18-x19 + u16 xVrmIndex; // VRM Index of OS image x1A-x1B + u16 xMinSupportedPlicVrmIndex;// Min PLIC level (soft) x1C-x1D + u16 xMinCompatablePlicVrmIndex;// Min PLIC levelP (hard) x1E-x1F + char xVrmName[12]; // Displayable name x20-x2B + char xRsvd3[20]; // Reserved x2C-x3F +}; + +#endif /* _HVRELEASEDATA_H */ diff --git a/include/asm-ppc64/iSeries/HvTypes.h b/include/asm-ppc64/iSeries/HvTypes.h new file mode 100644 index 000000000000..3ec49c1aec32 --- /dev/null +++ b/include/asm-ppc64/iSeries/HvTypes.h @@ -0,0 +1,127 @@ +/* + * HvTypes.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _HVTYPES_H +#define _HVTYPES_H + +//=========================================================================== +// Header File Id +// Name______________: HvTypes.H +// +// Description_______: +// +// General typedefs for the hypervisor. +// +// Declared Class(es): +// +//=========================================================================== + +#include <asm/types.h> + +//------------------------------------------------------------------- +// Typedefs +//------------------------------------------------------------------- +typedef u8 HvLpIndex; +typedef u16 HvLpInstanceId; +typedef u64 HvLpTOD; +typedef u64 HvLpSystemSerialNum; +typedef u8 HvLpDeviceSerialNum[12]; +typedef u16 HvLpSanHwSet; +typedef u16 HvLpBus; +typedef u16 HvLpBoard; +typedef u16 HvLpCard; +typedef u8 HvLpDeviceType[4]; +typedef u8 HvLpDeviceModel[3]; +typedef u64 HvIoToken; +typedef u8 HvLpName[8]; +typedef u32 HvIoId; +typedef u64 HvRealMemoryIndex; +typedef u32 HvLpIndexMap; // Must hold HvMaxArchitectedLps bits!!! +typedef u16 HvLpVrmIndex; +typedef u32 HvXmGenerationId; +typedef u8 HvLpBusPool; +typedef u8 HvLpSharedPoolIndex; +typedef u16 HvLpSharedProcUnitsX100; +typedef u8 HvLpVirtualLanIndex; +typedef u16 HvLpVirtualLanIndexMap; // Must hold HvMaxArchitectedVirtualLans bits!!! +typedef u16 HvBusNumber; // Hypervisor Bus Number +typedef u8 HvSubBusNumber; // Hypervisor SubBus Number +typedef u8 HvAgentId; // Hypervisor DevFn + + +#define HVMAXARCHITECTEDLPS 32 +#define HVMAXARCHITECTEDVIRTUALLANS 16 +#define HVMAXARCHITECTEDVIRTUALDISKS 32 +#define HVMAXARCHITECTEDVIRTUALCDROMS 8 +#define HVMAXARCHITECTEDVIRTUALTAPES 8 +#define HVCHUNKSIZE 256 * 1024 +#define HVPAGESIZE 4 * 1024 +#define HVLPMINMEGSPRIMARY 256 +#define HVLPMINMEGSSECONDARY 64 +#define HVCHUNKSPERMEG 4 +#define HVPAGESPERMEG 256 +#define HVPAGESPERCHUNK 64 + +#define HvMaxArchitectedLps ((HvLpIndex)HVMAXARCHITECTEDLPS) +#define HvMaxArchitectedVirtualLans ((HvLpVirtualLanIndex)16) +#define HvLpIndexInvalid ((HvLpIndex)0xff) + +//-------------------------------------------------------------------- +// Enums for the sub-components under PLIC +// Used in HvCall and HvPrimaryCall +//-------------------------------------------------------------------- +enum HvCallCompIds +{ + HvCallCompId = 0, + HvCallCpuCtlsCompId = 1, + HvCallCfgCompId = 2, + HvCallEventCompId = 3, + HvCallHptCompId = 4, + HvCallPciCompId = 5, + HvCallSlmCompId = 6, + HvCallSmCompId = 7, + HvCallSpdCompId = 8, + HvCallXmCompId = 9, + HvCallRioCompId = 10, + HvCallRsvd3CompId = 11, + HvCallRsvd2CompId = 12, + HvCallRsvd1CompId = 13, + HvCallMaxCompId = 14, + HvPrimaryCallCompId = 0, + HvPrimaryCallCfgCompId = 1, + HvPrimaryCallPciCompId = 2, + HvPrimaryCallSmCompId = 3, + HvPrimaryCallSpdCompId = 4, + HvPrimaryCallXmCompId = 5, + HvPrimaryCallRioCompId = 6, + HvPrimaryCallRsvd7CompId = 7, + HvPrimaryCallRsvd6CompId = 8, + HvPrimaryCallRsvd5CompId = 9, + HvPrimaryCallRsvd4CompId = 10, + HvPrimaryCallRsvd3CompId = 11, + HvPrimaryCallRsvd2CompId = 12, + HvPrimaryCallRsvd1CompId = 13, + HvPrimaryCallMaxCompId = HvCallMaxCompId +}; + +struct HvLpBufferList { + u64 addr; + u64 len; +}; + +#endif /* _HVTYPES_H */ diff --git a/include/asm-ppc64/iSeries/IoHriMainStore.h b/include/asm-ppc64/iSeries/IoHriMainStore.h new file mode 100644 index 000000000000..ff00e865f620 --- /dev/null +++ b/include/asm-ppc64/iSeries/IoHriMainStore.h @@ -0,0 +1,167 @@ +/* + * IoHriMainStore.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _IOHRIMAINSTORE_H +#define _IOHRIMAINSTORE_H + +/* Main Store Vpd for Condor,iStar,sStar */ +struct IoHriMainStoreSegment4 { + u8 msArea0Exists:1; + u8 msArea1Exists:1; + u8 msArea2Exists:1; + u8 msArea3Exists:1; + u8 reserved1:4; + u8 reserved2; + + u8 msArea0Functional:1; + u8 msArea1Functional:1; + u8 msArea2Functional:1; + u8 msArea3Functional:1; + u8 reserved3:4; + u8 reserved4; + + u32 totalMainStore; + + u64 msArea0Ptr; + u64 msArea1Ptr; + u64 msArea2Ptr; + u64 msArea3Ptr; + + u32 cardProductionLevel; + + u32 msAdrHole; + + u8 msArea0HasRiserVpd:1; + u8 msArea1HasRiserVpd:1; + u8 msArea2HasRiserVpd:1; + u8 msArea3HasRiserVpd:1; + u8 reserved5:4; + u8 reserved6; + u16 reserved7; + + u8 reserved8[28]; + + u64 nonInterleavedBlocksStartAdr; + u64 nonInterleavedBlocksEndAdr; +}; + +/* Main Store VPD for Power4 */ +struct IoHriMainStoreChipInfo1 { + u32 chipMfgID __attribute((packed)); + char chipECLevel[4] __attribute((packed)); +}; + +struct IoHriMainStoreVpdIdData { + char typeNumber[4]; + char modelNumber[4]; + char partNumber[12]; + char serialNumber[12]; +}; + +struct IoHriMainStoreVpdFruData { + char fruLabel[8] __attribute((packed)); + u8 numberOfSlots __attribute((packed)); + u8 pluggingType __attribute((packed)); + u16 slotMapIndex __attribute((packed)); +}; + +struct IoHriMainStoreAdrRangeBlock { + void * blockStart __attribute((packed)); + void * blockEnd __attribute((packed)); + u32 blockProcChipId __attribute((packed)); +}; + +#define MaxAreaAdrRangeBlocks 4 + +struct IoHriMainStoreArea4 { + u32 msVpdFormat __attribute((packed)); + u8 containedVpdType __attribute((packed)); + u8 reserved1 __attribute((packed)); + u16 reserved2 __attribute((packed)); + + u64 msExists __attribute((packed)); + u64 msFunctional __attribute((packed)); + + u32 memorySize __attribute((packed)); + u32 procNodeId __attribute((packed)); + + u32 numAdrRangeBlocks __attribute((packed)); + struct IoHriMainStoreAdrRangeBlock xAdrRangeBlock[MaxAreaAdrRangeBlocks] __attribute((packed)); + + struct IoHriMainStoreChipInfo1 chipInfo0 __attribute((packed)); + struct IoHriMainStoreChipInfo1 chipInfo1 __attribute((packed)); + struct IoHriMainStoreChipInfo1 chipInfo2 __attribute((packed)); + struct IoHriMainStoreChipInfo1 chipInfo3 __attribute((packed)); + struct IoHriMainStoreChipInfo1 chipInfo4 __attribute((packed)); + struct IoHriMainStoreChipInfo1 chipInfo5 __attribute((packed)); + struct IoHriMainStoreChipInfo1 chipInfo6 __attribute((packed)); + struct IoHriMainStoreChipInfo1 chipInfo7 __attribute((packed)); + + void * msRamAreaArray __attribute((packed)); + u32 msRamAreaArrayNumEntries __attribute((packed)); + u32 msRamAreaArrayEntrySize __attribute((packed)); + + u32 numaDimmExists __attribute((packed)); + u32 numaDimmFunctional __attribute((packed)); + void * numaDimmArray __attribute((packed)); + u32 numaDimmArrayNumEntries __attribute((packed)); + u32 numaDimmArrayEntrySize __attribute((packed)); + + struct IoHriMainStoreVpdIdData idData __attribute((packed)); + + u64 powerData __attribute((packed)); + u64 cardAssemblyPartNum __attribute((packed)); + u64 chipSerialNum __attribute((packed)); + + u64 reserved3 __attribute((packed)); + char reserved4[16] __attribute((packed)); + + struct IoHriMainStoreVpdFruData fruData __attribute((packed)); + + u8 vpdPortNum __attribute((packed)); + u8 reserved5 __attribute((packed)); + u8 frameId __attribute((packed)); + u8 rackUnit __attribute((packed)); + char asciiKeywordVpd[256] __attribute((packed)); + u32 reserved6 __attribute((packed)); +}; + + +struct IoHriMainStoreSegment5 { + u16 reserved1; + u8 reserved2; + u8 msVpdFormat; + + u32 totalMainStore; + u64 maxConfiguredMsAdr; + + struct IoHriMainStoreArea4* msAreaArray; + u32 msAreaArrayNumEntries; + u32 msAreaArrayEntrySize; + + u32 msAreaExists; + u32 msAreaFunctional; + + u64 reserved3; +}; + + + +#endif // _IOHRIMAINSTORE_H + diff --git a/include/asm-ppc64/iSeries/IoHriProcessorVpd.h b/include/asm-ppc64/iSeries/IoHriProcessorVpd.h new file mode 100644 index 000000000000..965433888653 --- /dev/null +++ b/include/asm-ppc64/iSeries/IoHriProcessorVpd.h @@ -0,0 +1,88 @@ +/* + * IoHriProcessorVpd.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _IOHRIPROCESSORVPD_H +#define _IOHRIPROCESSORVPD_H + +//=================================================================== +// +// This struct maps Processor Vpd that is DMAd to SLIC by CSP +// + +#include <asm/types.h> + +struct IoHriProcessorVpd +{ + + u8 xFormat; // VPD format indicator x00-x00 + u8 xProcStatus:8; // Processor State x01-x01 + u8 xSecondaryThreadCount; // Secondary thread cnt x02-x02 + u8 xSrcType:1; // Src Type x03-x03 + u8 xSrcSoft:1; // Src stay soft ... + u8 xSrcParable:1; // Src parable ... + u8 xRsvd1:5; // Reserved ... + u16 xHvPhysicalProcIndex; // Hypervisor physical proc index04-x05 + u16 xRsvd2; // Reserved x06-x07 + u32 xHwNodeId; // Hardware node id x08-x0B + u32 xHwProcId; // Hardware processor id x0C-x0F + + u32 xTypeNum; // Card Type/CCIN number x10-x13 + u32 xModelNum; // Model/Feature number x14-x17 + u64 xSerialNum; // Serial number x18-x1F + char xPartNum[12]; // Book Part or FPU number x20-x2B + char xMfgID[4]; // Manufacturing ID x2C-x2F + + u32 xProcFreq; // Processor Frequency x30-x33 + u32 xTimeBaseFreq; // Time Base Frequency x34-x37 + + u32 xChipEcLevel; // Chip EC Levels x38-x3B + u32 xProcIdReg; // PIR SPR value x3C-x3F + u32 xPVR; // PVR value x40-x43 + u8 xRsvd3[12]; // Reserved x44-x4F + + u32 xInstCacheSize; // Instruction cache size in KB x50-x53 + u32 xInstBlockSize; // Instruction cache block size x54-x57 + u32 xDataCacheOperandSize; // Data cache operand size x58-x5B + u32 xInstCacheOperandSize; // Inst cache operand size x5C-x5F + + u32 xDataL1CacheSizeKB; // L1 data cache size in KB x60-x63 + u32 xDataL1CacheLineSize; // L1 data cache block size x64-x67 + u64 xRsvd4; // Reserved x68-x6F + + u32 xDataL2CacheSizeKB; // L2 data cache size in KB x70-x73 + u32 xDataL2CacheLineSize; // L2 data cache block size x74-x77 + u64 xRsvd5; // Reserved x78-x7F + + u32 xDataL3CacheSizeKB; // L3 data cache size in KB x80-x83 + u32 xDataL3CacheLineSize; // L3 data cache block size x84-x87 + u64 xRsvd6; // Reserved x88-x8F + + u64 xFruLabel; // Card Location Label x90-x97 + u8 xSlotsOnCard; // Slots on card (0=no slots) x98-x98 + u8 xPartLocFlag; // Location flag (0-pluggable 1-imbedded) x99-x99 + u16 xSlotMapIndex; // Index in slot map table x9A-x9B + u8 xSmartCardPortNo; // Smart card port number x9C-x9C + u8 xRsvd7; // Reserved x9D-x9D + u16 xFrameIdAndRackUnit; // Frame ID and rack unit adr x9E-x9F + + u8 xRsvd8[24]; // Reserved xA0-xB7 + + char xProcSrc[72]; // CSP format SRC xB8-xFF +}; + +#endif /* _IOHRIPROCESSORVPD_H */ diff --git a/include/asm-ppc64/iSeries/ItExtVpdPanel.h b/include/asm-ppc64/iSeries/ItExtVpdPanel.h new file mode 100644 index 000000000000..dee6b1273031 --- /dev/null +++ b/include/asm-ppc64/iSeries/ItExtVpdPanel.h @@ -0,0 +1,58 @@ +/* + * ItExtVpdPanel.h + * Copyright (C) 2002 Dave Boutcher IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _ITEXTVPDPANEL_H +#define _ITEXTVPDPANEL_H + +/* + * + * This struct maps the panel information + * + * Warning: + * This data must match the architecture for the panel information + * + */ + + +/*------------------------------------------------------------------- + * Standard Includes + *------------------------------------------------------------------- +*/ +#include <asm/types.h> + +struct ItExtVpdPanel +{ + // Definition of the Extended Vpd On Panel Data Area + char systemSerial[8]; + char mfgID[4]; + char reserved1[24]; + char machineType[4]; + char systemID[6]; + char somUniqueCnt[4]; + char serialNumberCount; + char reserved2[7]; + u16 bbu3; + u16 bbu2; + u16 bbu1; + char xLocationLabel[8]; + u8 xRsvd1[6]; + u16 xFrameId; + u8 xRsvd2[48]; +}; + +#endif /* _ITEXTVPDPANEL_H */ diff --git a/include/asm-ppc64/iSeries/ItIplParmsReal.h b/include/asm-ppc64/iSeries/ItIplParmsReal.h new file mode 100644 index 000000000000..4d8b430ab12d --- /dev/null +++ b/include/asm-ppc64/iSeries/ItIplParmsReal.h @@ -0,0 +1,76 @@ +/* + * ItIplParmsReal.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _ITIPLPARMSREAL_H +#define _ITIPLPARMSREAL_H + +//============================================================================== +// +// This struct maps the IPL Parameters DMA'd from the SP. +// +// Warning: +// This data must map in exactly 64 bytes and match the architecture for +// the IPL parms +// +//============================================================================= + + +//------------------------------------------------------------------- +// Standard Includes +//------------------------------------------------------------------- +#include <asm/types.h> + +struct ItIplParmsReal +{ + u8 xFormat; // Defines format of IplParms x00-x00 + u8 xRsvd01:6; // Reserved x01-x01 + u8 xAlternateSearch:1; // Alternate search indicator ... + u8 xUaSupplied:1; // UA Supplied on programmed IPL ... + u8 xLsUaFormat; // Format byte for UA x02-x02 + u8 xRsvd02; // Reserved x03-x03 + u32 xLsUa; // LS UA x04-x07 + u32 xUnusedLsLid; // First OS LID to load x08-x0B + u16 xLsBusNumber; // LS Bus Number x0C-x0D + u8 xLsCardAdr; // LS Card Address x0E-x0E + u8 xLsBoardAdr; // LS Board Address x0F-x0F + u32 xRsvd03; // Reserved x10-x13 + u8 xSpcnPresent:1; // SPCN present x14-x14 + u8 xCpmPresent:1; // CPM present ... + u8 xRsvd04:6; // Reserved ... + u8 xRsvd05:4; // Reserved x15-x15 + u8 xKeyLock:4; // Keylock setting ... + u8 xRsvd06:6; // Reserved x16-x16 + u8 xIplMode:2; // Ipl mode (A|B|C|D) ... + u8 xHwIplType; // Fast v slow v slow EC HW IPL x17-x17 + u16 xCpmEnabledIpl:1; // CPM in effect when IPL initiated x18-x19 + u16 xPowerOnResetIpl:1; // Indicate POR condition ... + u16 xMainStorePreserved:1; // Main Storage is preserved ... + u16 xRsvd07:13; // Reserved ... + u16 xIplSource:16; // Ipl source x1A-x1B + u8 xIplReason:8; // Reason for this IPL x1C-x1C + u8 xRsvd08; // Reserved x1D-x1D + u16 xRsvd09; // Reserved x1E-x1F + u16 xSysBoxType; // System Box Type x20-x21 + u16 xSysProcType; // System Processor Type x22-x23 + u32 xRsvd10; // Reserved x24-x27 + u64 xRsvd11; // Reserved x28-x2F + u64 xRsvd12; // Reserved x30-x37 + u64 xRsvd13; // Reserved x38-x3F +}; + +#endif /* _ITIPLPARMSREAL_H */ diff --git a/include/asm-ppc64/iSeries/ItLpNaca.h b/include/asm-ppc64/iSeries/ItLpNaca.h new file mode 100644 index 000000000000..5baffddfae1b --- /dev/null +++ b/include/asm-ppc64/iSeries/ItLpNaca.h @@ -0,0 +1,88 @@ +/* + * ItLpNaca.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _ITLPNACA_H +#define _ITLPNACA_H + +//============================================================================= +// +// This control block contains the data that is shared between the +// hypervisor (PLIC) and the OS. +// +//============================================================================= + +struct ItLpNaca +{ +//============================================================================= +// CACHE_LINE_1 0x0000 - 0x007F Contains read-only data +//============================================================================= + u32 xDesc; // Eye catcher x00-x03 + u16 xSize; // Size of this class x04-x05 + u16 xIntHdlrOffset; // Offset to IntHdlr array x06-x07 + u8 xMaxIntHdlrEntries; // Number of entries in array x08-x08 + u8 xPrimaryLpIndex; // LP Index of Primary x09-x09 + u8 xServiceLpIndex; // LP Ind of Service Focal Pointx0A-x0A + u8 xLpIndex; // LP Index x0B-x0B + u16 xMaxLpQueues; // Number of allocated queues x0C-x0D + u16 xLpQueueOffset; // Offset to start of LP queues x0E-x0F + u8 xPirEnvironMode:8; // Piranha or hardware x10-x10 + u8 xPirConsoleMode:8; // Piranha console indicator x11-x11 + u8 xPirDasdMode:8; // Piranha dasd indicator x12-x12 + u8 xRsvd1_0[5]; // Reserved for Piranha related x13-x17 + u8 xLparInstalled:1; // Is LPAR installed on system x18-x1F + u8 xSysPartitioned:1; // Is the system partitioned ... + u8 xHwSyncedTBs:1; // Hardware synced TBs ... + u8 xIntProcUtilHmt:1; // Utilize HMT for interrupts ... + u8 xRsvd1_1:4; // Reserved ... + u8 xSpVpdFormat:8; // VPD areas are in CSP format ... + u8 xIntProcRatio:8; // Ratio of int procs to procs ... + u8 xRsvd1_2[5]; // Reserved ... + u16 xRsvd1_3; // Reserved x20-x21 + u16 xPlicVrmIndex; // VRM index of PLIC x22-x23 + u16 xMinSupportedSlicVrmInd;// Min supported OS VRM index x24-x25 + u16 xMinCompatableSlicVrmInd;// Min compatible OS VRM index x26-x27 + u64 xLoadAreaAddr; // ER address of load area x28-x2F + u32 xLoadAreaChunks; // Chunks for the load area x30-x33 + u32 xPaseSysCallCRMask; // Mask used to test CR before x34-x37 + // doing an ASR switch on PASE + // system call. + u64 xSlicSegmentTablePtr; // Pointer to Slic seg table. x38-x3f + u8 xRsvd1_4[64]; // x40-x7F + +//============================================================================= +// CACHE_LINE_2 0x0080 - 0x00FF Contains local read-write data +//============================================================================= + u8 xRsvd2_0[128]; // Reserved x00-x7F + +//============================================================================= +// CACHE_LINE_3-6 0x0100 - 0x02FF Contains LP Queue indicators +// NB: Padding required to keep xInterrruptHdlr at x300 which is required +// for v4r4 PLIC. +//============================================================================= + u8 xOldLpQueue[128]; // LP Queue needed for v4r4 100-17F + u8 xRsvd3_0[384]; // Reserved 180-2FF +//============================================================================= +// CACHE_LINE_7-8 0x0300 - 0x03FF Contains the address of the OS interrupt +// handlers +//============================================================================= + u64 xInterruptHdlr[32]; // Interrupt handlers 300-x3FF +}; + +//============================================================================= + +#endif /* _ITLPNACA_H */ diff --git a/include/asm-ppc64/iSeries/ItLpQueue.h b/include/asm-ppc64/iSeries/ItLpQueue.h new file mode 100644 index 000000000000..4f4dde2a638d --- /dev/null +++ b/include/asm-ppc64/iSeries/ItLpQueue.h @@ -0,0 +1,92 @@ +/* + * ItLpQueue.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _ITLPQUEUE_H +#define _ITLPQUEUE_H + +//============================================================================= +// +// This control block defines the simple LP queue structure that is +// shared between the hypervisor (PLIC) and the OS in order to send +// events to an LP. +// + +#include <asm/types.h> +#include <asm/ptrace.h> + +struct HvLpEvent; + +#define ITMaxLpQueues 8 + +#define NotUsed 0 // Queue will not be used by PLIC +#define DedicatedIo 1 // Queue dedicated to IO processor specified +#define DedicatedLp 2 // Queue dedicated to LP specified +#define Shared 3 // Queue shared for both IO and LP + +#define LpEventStackSize 4096 +#define LpEventMaxSize 256 +#define LpEventAlign 64 + +struct ItLpQueue +{ +// +// The xSlicCurEventPtr is the pointer to the next event stack entry that will +// become valid. The OS must peek at this entry to determine if it is valid. +// PLIC will set the valid indicator as the very last store into that entry. +// +// When the OS has completed processing of the event then it will mark the event +// as invalid so that PLIC knows it can store into that event location again. +// +// If the event stack fills and there are overflow events, then PLIC will set +// the xPlicOverflowIntPending flag in which case the OS will have to fetch the +// additional LP events once they have drained the event stack. +// +// The first 16-bytes are known by both the OS and PLIC. The remainder of the +// cache line is for use by the OS. +// +//============================================================================= + u8 xPlicOverflowIntPending;// 0x00 Overflow events are pending + u8 xPlicStatus; // 0x01 DedicatedIo or DedicatedLp or NotUsed + u16 xSlicLogicalProcIndex; // 0x02 Logical Proc Index for correlation + u8 xPlicRsvd[12]; // 0x04 + char* xSlicCurEventPtr; // 0x10 + char* xSlicLastValidEventPtr; // 0x18 + char* xSlicEventStackPtr; // 0x20 + u8 xIndex; // 0x28 unique sequential index. + u8 xSlicRsvd[3]; // 0x29-2b + u32 xInUseWord; // 0x2C + u64 xLpIntCount; // 0x30 Total Lp Int msgs processed + u64 xLpIntCountByType[9]; // 0x38-0x7F Event counts by type +}; + +extern struct ItLpQueue xItLpQueue; + +extern struct HvLpEvent * ItLpQueue_getNextLpEvent( struct ItLpQueue * ); +extern int ItLpQueue_isLpIntPending( struct ItLpQueue * ); +extern unsigned ItLpQueue_process( struct ItLpQueue *, struct pt_regs * ); +extern void ItLpQueue_clearValid( struct HvLpEvent * ); + +static __inline__ void process_iSeries_events( void ) +{ + __asm__ __volatile__ ( + " li 0,0x5555 \n\ + sc" + : : : "r0", "r3" ); +} + +#endif /* _ITLPQUEUE_H */ diff --git a/include/asm-ppc64/iSeries/ItLpRegSave.h b/include/asm-ppc64/iSeries/ItLpRegSave.h new file mode 100644 index 000000000000..dafc4c813788 --- /dev/null +++ b/include/asm-ppc64/iSeries/ItLpRegSave.h @@ -0,0 +1,87 @@ +/* + * ItLpRegSave.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _ITLPREGSAVE_H +#define _ITLPREGSAVE_H + +//===================================================================================== +// +// This control block contains the data that is shared between PLIC +// and the OS +// +// + +struct ItLpRegSave +{ + u32 xDesc; // Eye catcher "LpRS" ebcdic 000-003 + u16 xSize; // Size of this class 004-005 + u8 xInUse; // Area is live 006-007 + u8 xRsvd1[9]; // Reserved 007-00F + + u8 xFixedRegSave[352]; // Fixed Register Save Area 010-16F + u32 xCTRL; // Control Register 170-173 + u32 xDEC; // Decrementer 174-177 + u32 xFPSCR; // FP Status and Control Reg 178-17B + u32 xPVR; // Processor Version Number 17C-17F + + u64 xMMCR0; // Monitor Mode Control Reg 0 180-187 + u32 xPMC1; // Perf Monitor Counter 1 188-18B + u32 xPMC2; // Perf Monitor Counter 2 18C-18F + u32 xPMC3; // Perf Monitor Counter 3 190-193 + u32 xPMC4; // Perf Monitor Counter 4 194-197 + u32 xPIR; // Processor ID Reg 198-19B + + u32 xMMCR1; // Monitor Mode Control Reg 1 19C-19F + u32 xMMCRA; // Monitor Mode Control Reg A 1A0-1A3 + u32 xPMC5; // Perf Monitor Counter 5 1A4-1A7 + u32 xPMC6; // Perf Monitor Counter 6 1A8-1AB + u32 xPMC7; // Perf Monitor Counter 7 1AC-1AF + u32 xPMC8; // Perf Monitor Counter 8 1B0-1B3 + u32 xTSC; // Thread Switch Control 1B4-1B7 + u32 xTST; // Thread Switch Timeout 1B8-1BB + u32 xRsvd; // Reserved 1BC-1BF + + u64 xACCR; // Address Compare Control Reg 1C0-1C7 + u64 xIMR; // Instruction Match Register 1C8-1CF + u64 xSDR1; // Storage Description Reg 1 1D0-1D7 + u64 xSPRG0; // Special Purpose Reg General0 1D8-1DF + u64 xSPRG1; // Special Purpose Reg General1 1E0-1E7 + u64 xSPRG2; // Special Purpose Reg General2 1E8-1EF + u64 xSPRG3; // Special Purpose Reg General3 1F0-1F7 + u64 xTB; // Time Base Register 1F8-1FF + + u64 xFPR[32]; // Floating Point Registers 200-2FF + + u64 xMSR; // Machine State Register 300-307 + u64 xNIA; // Next Instruction Address 308-30F + + u64 xDABR; // Data Address Breakpoint Reg 310-317 + u64 xIABR; // Inst Address Breakpoint Reg 318-31F + + u64 xHID0; // HW Implementation Dependent0 320-327 + + u64 xHID4; // HW Implementation Dependent4 328-32F + u64 xSCOMd; // SCON Data Reg (SPRG4) 330-337 + u64 xSCOMc; // SCON Command Reg (SPRG5) 338-33F + u64 xSDAR; // Sample Data Address Register 340-347 + u64 xSIAR; // Sample Inst Address Register 348-34F + + u8 xRsvd3[176]; // Reserved 350-3FF +}; + +#endif /* _ITLPREGSAVE_H */ diff --git a/include/asm-ppc64/iSeries/ItSpCommArea.h b/include/asm-ppc64/iSeries/ItSpCommArea.h new file mode 100644 index 000000000000..f1b56f9e11e2 --- /dev/null +++ b/include/asm-ppc64/iSeries/ItSpCommArea.h @@ -0,0 +1,39 @@ +/* + * ItSpCommArea.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _ITSPCOMMAREA_H +#define _ITSPCOMMAREA_H + + +struct SpCommArea +{ + u32 xDesc; // Descriptor (only in new formats) 000-003 + u8 xFormat; // Format (only in new formats) 004-004 + u8 xRsvd1[11]; // Reserved 005-00F + u64 xRawTbAtIplStart; // Raw HW TB value when IPL is started 010-017 + u64 xRawTodAtIplStart; // Raw HW TOD value when IPL is started 018-01F + u64 xBcdTimeAtIplStart; // BCD time when IPL is started 020-027 + u64 xBcdTimeAtOsStart; // BCD time when OS passed control 028-02F + u8 xRsvd2[80]; // Reserved 030-07F +}; + +extern struct SpCommArea xSpCommArea; + +#endif /* _ITSPCOMMAREA_H */ diff --git a/include/asm-ppc64/iSeries/ItVpdAreas.h b/include/asm-ppc64/iSeries/ItVpdAreas.h new file mode 100644 index 000000000000..d120439f30a5 --- /dev/null +++ b/include/asm-ppc64/iSeries/ItVpdAreas.h @@ -0,0 +1,96 @@ +/* + * ItVpdAreas.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _ITVPDAREAS_H +#define _ITVPDAREAS_H + +//===================================================================================== +// +// This file defines the address and length of all of the VPD area passed to +// the OS from PLIC (most of which start from the SP). +// + +#include <asm/types.h> + +// VPD Entry index is carved in stone - cannot be changed (easily). +#define ItVpdCecVpd 0 +#define ItVpdDynamicSpace 1 +#define ItVpdExtVpd 2 +#define ItVpdExtVpdOnPanel 3 +#define ItVpdFirstPaca 4 +#define ItVpdIoVpd 5 +#define ItVpdIplParms 6 +#define ItVpdMsVpd 7 +#define ItVpdPanelVpd 8 +#define ItVpdLpNaca 9 +#define ItVpdBackplaneAndMaybeClockCardVpd 10 +#define ItVpdRecoveryLogBuffer 11 +#define ItVpdSpCommArea 12 +#define ItVpdSpLogBuffer 13 +#define ItVpdSpLogBufferSave 14 +#define ItVpdSpCardVpd 15 +#define ItVpdFirstProcVpd 16 +#define ItVpdApModelVpd 17 +#define ItVpdClockCardVpd 18 +#define ItVpdBusExtCardVpd 19 +#define ItVpdProcCapacityVpd 20 +#define ItVpdInteractiveCapacityVpd 21 +#define ItVpdFirstSlotLabel 22 +#define ItVpdFirstLpQueue 23 +#define ItVpdFirstL3CacheVpd 24 +#define ItVpdFirstProcFruVpd 25 + +#define ItVpdMaxEntries 26 + + +#define ItDmaMaxEntries 10 + +#define ItVpdAreasMaxSlotLabels 192 + + +struct SlicVpdAdrs { + u32 pad1; + void * vpdAddr; +}; + + +struct ItVpdAreas +{ + u32 xSlicDesc; // Descriptor 000-003 + u16 xSlicSize; // Size of this control block 004-005 + u16 xPlicAdjustVpdLens:1; // Flag to indicate new interface 006-007 + u16 xRsvd1:15; // Reserved bits ... + u16 xSlicVpdEntries; // Number of VPD entries 008-009 + u16 xSlicDmaEntries; // Number of DMA entries 00A-00B + u16 xSlicMaxLogicalProcs; // Maximum logical processors 00C-00D + u16 xSlicMaxPhysicalProcs; // Maximum physical processors 00E-00F + u16 xSlicDmaToksOffset; // Offset into this of array 010-011 + u16 xSlicVpdAdrsOffset; // Offset into this of array 012-013 + u16 xSlicDmaLensOffset; // Offset into this of array 014-015 + u16 xSlicVpdLensOffset; // Offset into this of array 016-017 + u16 xSlicMaxSlotLabels; // Maximum number of slot labels 018-019 + u16 xSlicMaxLpQueues; // Maximum number of LP Queues 01A-01B + u8 xRsvd2[4]; // Reserved 01C-01F + u64 xRsvd3[12]; // Reserved 020-07F + u32 xPlicDmaLens[ItDmaMaxEntries];// Array of DMA lengths 080-0A7 + u32 xPlicDmaToks[ItDmaMaxEntries];// Array of DMA tokens 0A8-0CF + u32 xSlicVpdLens[ItVpdMaxEntries];// Array of VPD lengths 0D0-12F + void * xSlicVpdAdrs[ItVpdMaxEntries];// Array of VPD buffers 130-1EF +}; + +#endif /* _ITVPDAREAS_H */ diff --git a/include/asm-ppc64/iSeries/LparData.h b/include/asm-ppc64/iSeries/LparData.h new file mode 100644 index 000000000000..e54f3b686e58 --- /dev/null +++ b/include/asm-ppc64/iSeries/LparData.h @@ -0,0 +1,49 @@ +/* + * LparData.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _LPARDATA_H +#define _LPARDATA_H + +#include <asm/types.h> +#include <asm/page.h> +#include <asm/abs_addr.h> + +#include <asm/iSeries/ItLpNaca.h> +#include <asm/iSeries/ItLpRegSave.h> +#include <asm/iSeries/HvReleaseData.h> +#include <asm/iSeries/LparMap.h> +#include <asm/iSeries/ItVpdAreas.h> +#include <asm/iSeries/ItIplParmsReal.h> +#include <asm/iSeries/ItExtVpdPanel.h> +#include <asm/iSeries/ItLpQueue.h> +#include <asm/iSeries/IoHriProcessorVpd.h> + +extern struct LparMap xLparMap; +extern struct HvReleaseData hvReleaseData; +extern struct ItLpNaca itLpNaca; +extern struct ItIplParmsReal xItIplParmsReal; +extern struct ItExtVpdPanel xItExtVpdPanel; +extern struct IoHriProcessorVpd xIoHriProcessorVpd[]; +extern struct ItLpQueue xItLpQueue; +extern struct ItVpdAreas itVpdAreas; +extern u64 xMsVpd[]; +extern struct msChunks msChunks; + + +#endif /* _LPARDATA_H */ diff --git a/include/asm-ppc64/iSeries/LparMap.h b/include/asm-ppc64/iSeries/LparMap.h new file mode 100644 index 000000000000..075205bb0f4a --- /dev/null +++ b/include/asm-ppc64/iSeries/LparMap.h @@ -0,0 +1,67 @@ +/* + * LparMap.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _LPARMAP_H +#define _LPARMAP_H + +#include <asm/types.h> + +/* The iSeries hypervisor will set up mapping for one or more + * ESID/VSID pairs (in SLB/segment registers) and will set up + * mappings of one or more ranges of pages to VAs. + * We will have the hypervisor set up the ESID->VSID mapping + * for the four kernel segments (C-F). With shared processors, + * the hypervisor will clear all segment registers and reload + * these four whenever the processor is switched from one + * partition to another. + */ + +/* The Vsid and Esid identified below will be used by the hypervisor + * to set up a memory mapping for part of the load area before giving + * control to the Linux kernel. The load area is 64 MB, but this must + * not attempt to map the whole load area. The Hashed Page Table may + * need to be located within the load area (if the total partition size + * is 64 MB), but cannot be mapped. Typically, this should specify + * to map half (32 MB) of the load area. + * + * The hypervisor will set up page table entries for the number of + * pages specified. + * + * In 32-bit mode, the hypervisor will load all four of the + * segment registers (identified by the low-order four bits of the + * Esid field. In 64-bit mode, the hypervisor will load one SLB + * entry to map the Esid to the Vsid. +*/ + +// Hypervisor initially maps 32MB of the load area +#define HvPagesToMap 8192 + +struct LparMap +{ + u64 xNumberEsids; // Number of ESID/VSID pairs (1) + u64 xNumberRanges; // Number of VA ranges to map (1) + u64 xSegmentTableOffs; // Page number within load area of seg table (0) + u64 xRsvd[5]; // Reserved (0) + u64 xKernelEsid; // Esid used to map kernel load (0x0C00000000) + u64 xKernelVsid; // Vsid used to map kernel load (0x0C00000000) + u64 xPages; // Number of pages to be mapped (8192) + u64 xOffset; // Offset from start of load area (0) + u64 xVPN; // Virtual Page Number (0x000C000000000000) +}; + +#endif /* _LPARMAP_H */ diff --git a/include/asm-ppc64/iSeries/XmPciLpEvent.h b/include/asm-ppc64/iSeries/XmPciLpEvent.h new file mode 100644 index 000000000000..a3d27f116e49 --- /dev/null +++ b/include/asm-ppc64/iSeries/XmPciLpEvent.h @@ -0,0 +1,18 @@ + +#ifndef __XMPCILPEVENT_H__ +#define __XMPCILPEVENT_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + +int XmPciLpEvent_init(void); +void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq); + + +#ifdef __cplusplus +} +#endif + +#endif /* __XMPCILPEVENT_H__ */ diff --git a/include/asm-ppc64/iSeries/iSeries_io.h b/include/asm-ppc64/iSeries/iSeries_io.h new file mode 100644 index 000000000000..f52b7599b372 --- /dev/null +++ b/include/asm-ppc64/iSeries/iSeries_io.h @@ -0,0 +1,46 @@ +#ifndef _ISERIES_IO_H +#define _ISERIES_IO_H + +#include <linux/config.h> + +#ifdef CONFIG_PPC_ISERIES +#include <linux/types.h> +/************************************************************************/ +/* File iSeries_io.h created by Allan Trautman on Thu Dec 28 2000. */ +/************************************************************************/ +/* Remaps the io.h for the iSeries Io */ +/* Copyright (C) 20yy Allan H Trautman, IBM Corporation */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the: */ +/* Free Software Foundation, Inc., */ +/* 59 Temple Place, Suite 330, */ +/* Boston, MA 02111-1307 USA */ +/************************************************************************/ +/* Change Activity: */ +/* Created December 28, 2000 */ +/* End Change Activity */ +/************************************************************************/ +extern u8 iSeries_Read_Byte(const volatile void __iomem * IoAddress); +extern u16 iSeries_Read_Word(const volatile void __iomem * IoAddress); +extern u32 iSeries_Read_Long(const volatile void __iomem * IoAddress); +extern void iSeries_Write_Byte(u8 IoData, volatile void __iomem * IoAddress); +extern void iSeries_Write_Word(u16 IoData, volatile void __iomem * IoAddress); +extern void iSeries_Write_Long(u32 IoData, volatile void __iomem * IoAddress); + +extern void iSeries_memset_io(volatile void __iomem *dest, char x, size_t n); +extern void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, size_t n); +extern void iSeries_memcpy_fromio(void *dest, const volatile void __iomem *source, size_t n); + +#endif /* CONFIG_PPC_ISERIES */ +#endif /* _ISERIES_IO_H */ diff --git a/include/asm-ppc64/iSeries/iSeries_irq.h b/include/asm-ppc64/iSeries/iSeries_irq.h new file mode 100644 index 000000000000..ff8ddede038c --- /dev/null +++ b/include/asm-ppc64/iSeries/iSeries_irq.h @@ -0,0 +1,19 @@ +#ifndef __ISERIES_IRQ_H__ +#define __ISERIES_IRQ_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void iSeries_init_IRQ(void); +int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, HvAgentId); +int iSeries_assign_IRQ(int, HvBusNumber, HvSubBusNumber, HvAgentId); +void iSeries_activate_IRQs(void); + +int XmPciLpEvent_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __ISERIES_IRQ_H__ */ diff --git a/include/asm-ppc64/iSeries/iSeries_pci.h b/include/asm-ppc64/iSeries/iSeries_pci.h new file mode 100644 index 000000000000..5769cff4c00c --- /dev/null +++ b/include/asm-ppc64/iSeries/iSeries_pci.h @@ -0,0 +1,112 @@ +#ifndef _ISERIES_64_PCI_H +#define _ISERIES_64_PCI_H + +/************************************************************************/ +/* File iSeries_pci.h created by Allan Trautman on Tue Feb 20, 2001. */ +/************************************************************************/ +/* Define some useful macros for the iSeries pci routines. */ +/* Copyright (C) 2001 Allan H Trautman, IBM Corporation */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the: */ +/* Free Software Foundation, Inc., */ +/* 59 Temple Place, Suite 330, */ +/* Boston, MA 02111-1307 USA */ +/************************************************************************/ +/* Change Activity: */ +/* Created Feb 20, 2001 */ +/* Added device reset, March 22, 2001 */ +/* Ported to ppc64, May 25, 2001 */ +/* End Change Activity */ +/************************************************************************/ + +#include <asm/iSeries/HvCallPci.h> +#include <asm/abs_addr.h> + +struct pci_dev; /* For Forward Reference */ +struct iSeries_Device_Node; + +/************************************************************************/ +/* Gets iSeries Bus, SubBus, DevFn using iSeries_Device_Node structure */ +/************************************************************************/ + +#define ISERIES_BUS(DevPtr) DevPtr->DsaAddr.Dsa.busNumber +#define ISERIES_SUBBUS(DevPtr) DevPtr->DsaAddr.Dsa.subBusNumber +#define ISERIES_DEVICE(DevPtr) DevPtr->DsaAddr.Dsa.deviceId +#define ISERIES_DSA(DevPtr) DevPtr->DsaAddr.DsaAddr +#define ISERIES_DEVFUN(DevPtr) DevPtr->DevFn +#define ISERIES_DEVNODE(PciDev) ((struct iSeries_Device_Node*)PciDev->sysdata) + +#define EADsMaxAgents 7 + +/************************************************************************/ +/* Decodes Linux DevFn to iSeries DevFn, bridge device, or function. */ +/* For Linux, see PCI_SLOT and PCI_FUNC in include/linux/pci.h */ +/************************************************************************/ + +#define ISERIES_PCI_AGENTID(idsel,func) ((idsel & 0x0F) << 4) | (func & 0x07) +#define ISERIES_ENCODE_DEVICE(agentid) ((0x10) | ((agentid&0x20)>>2) | (agentid&07)) + +#define ISERIES_GET_DEVICE_FROM_SUBBUS(subbus) ((subbus >> 5) & 0x7) +#define ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus) ((subbus >> 2) & 0x7) + +/* + * N.B. the ISERIES_DECODE_* macros are not used anywhere, and I think + * the 0x71 (at least) must be wrong - 0x78 maybe? -- paulus. + */ +#define ISERIES_DECODE_DEVFN(linuxdevfn) (((linuxdevfn & 0x71) << 1) | (linuxdevfn & 0x07)) +#define ISERIES_DECODE_DEVICE(linuxdevfn) (((linuxdevfn & 0x38) >> 3) |(((linuxdevfn & 0x40) >> 2) + 0x10)) +#define ISERIES_DECODE_FUNCTION(linuxdevfn) (linuxdevfn & 0x07) + +/************************************************************************/ +/* Converts Virtual Address to Real Address for Hypervisor calls */ +/************************************************************************/ + +#define ISERIES_HV_ADDR(virtaddr) (0x8000000000000000 | virt_to_abs(virtaddr)) + +/************************************************************************/ +/* iSeries Device Information */ +/************************************************************************/ + +struct iSeries_Device_Node { + struct list_head Device_List; + struct pci_dev* PciDev; /* Pointer to pci_dev structure*/ + union HvDsaMap DsaAddr; /* Direct Select Address */ + /* busNumber,subBusNumber, */ + /* deviceId, barNumber */ + HvAgentId AgentId; /* Hypervisor DevFn */ + int DevFn; /* Linux devfn */ + int BarOffset; + int Irq; /* Assigned IRQ */ + int ReturnCode; /* Return Code Holder */ + int IoRetry; /* Current Retry Count */ + int Flags; /* Possible flags(disable/bist)*/ + u16 Vendor; /* Vendor ID */ + u8 LogicalSlot; /* Hv Slot Index for Tces */ + struct iommu_table* iommu_table;/* Device TCE Table */ + u8 PhbId; /* Phb Card is on. */ + u16 Board; /* Board Number */ + u8 FrameId; /* iSeries spcn Frame Id */ + char CardLocation[4];/* Char format of planar vpd */ + char Location[20]; /* Frame 1, Card C10 */ +}; + +/************************************************************************/ +/* Functions */ +/************************************************************************/ + +extern int iSeries_Device_Information(struct pci_dev*,char*, int); +extern void iSeries_Get_Location_Code(struct iSeries_Device_Node*); +extern int iSeries_Device_ToggleReset(struct pci_dev* PciDev, int AssertTime, int DelayTime); + +#endif /* _ISERIES_64_PCI_H */ diff --git a/include/asm-ppc64/iSeries/iSeries_proc.h b/include/asm-ppc64/iSeries/iSeries_proc.h new file mode 100644 index 000000000000..adb6dc14dd4d --- /dev/null +++ b/include/asm-ppc64/iSeries/iSeries_proc.h @@ -0,0 +1,24 @@ +/* + * iSeries_proc.h + * Copyright (C) 2001 Kyle A. Lucke IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _ISERIES_PROC_H +#define _ISERIES_PROC_H + +extern void iSeries_proc_early_init(void); + +#endif /* _iSeries_PROC_H */ diff --git a/include/asm-ppc64/iSeries/mf.h b/include/asm-ppc64/iSeries/mf.h new file mode 100644 index 000000000000..2e59a8e15a0b --- /dev/null +++ b/include/asm-ppc64/iSeries/mf.h @@ -0,0 +1,57 @@ +/* + * mf.h + * Copyright (C) 2001 Troy D. Armstrong IBM Corporation + * Copyright (C) 2004 Stephen Rothwell IBM Corporation + * + * This modules exists as an interface between a Linux secondary partition + * running on an iSeries and the primary partition's Virtual Service + * Processor (VSP) object. The VSP has final authority over powering on/off + * all partitions in the iSeries. It also provides miscellaneous low-level + * machine facility type operations. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _ASM_PPC64_ISERIES_MF_H +#define _ASM_PPC64_ISERIES_MF_H + +#include <linux/types.h> + +#include <asm/iSeries/HvTypes.h> +#include <asm/iSeries/HvCallEvent.h> + +struct rtc_time; + +typedef void (*MFCompleteHandler)(void *clientToken, int returnCode); + +extern void mf_allocate_lp_events(HvLpIndex targetLp, HvLpEvent_Type type, + unsigned size, unsigned amount, MFCompleteHandler hdlr, + void *userToken); +extern void mf_deallocate_lp_events(HvLpIndex targetLp, HvLpEvent_Type type, + unsigned count, MFCompleteHandler hdlr, void *userToken); + +extern void mf_power_off(void); +extern void mf_reboot(void); + +extern void mf_display_src(u32 word); +extern void mf_display_progress(u16 value); +extern void mf_clear_src(void); + +extern void mf_init(void); + +extern int mf_get_rtc(struct rtc_time *tm); +extern int mf_set_rtc(struct rtc_time *tm); + +#endif /* _ASM_PPC64_ISERIES_MF_H */ diff --git a/include/asm-ppc64/iSeries/vio.h b/include/asm-ppc64/iSeries/vio.h new file mode 100644 index 000000000000..3e5766a849d6 --- /dev/null +++ b/include/asm-ppc64/iSeries/vio.h @@ -0,0 +1,129 @@ +/* -*- linux-c -*- + * drivers/char/vio.h + * + * iSeries Virtual I/O Message Path header + * + * Authors: Dave Boutcher <boutcher@us.ibm.com> + * Ryan Arnold <ryanarn@us.ibm.com> + * Colin Devilbiss <devilbis@us.ibm.com> + * + * (C) Copyright 2000 IBM Corporation + * + * This header file is used by the iSeries virtual I/O device + * drivers. It defines the interfaces to the common functions + * (implemented in drivers/char/viopath.h) as well as defining + * common functions and structures. Currently (at the time I + * wrote this comment) the iSeries virtual I/O device drivers + * that use this are + * drivers/block/viodasd.c + * drivers/char/viocons.c + * drivers/char/viotape.c + * drivers/cdrom/viocd.c + * + * The iSeries virtual ethernet support (veth.c) uses a whole + * different set of functions. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) anyu later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef _ISERIES_VIO_H +#define _ISERIES_VIO_H + +#include <asm/iSeries/HvTypes.h> +#include <asm/iSeries/HvLpEvent.h> + +/* iSeries virtual I/O events use the subtype field in + * HvLpEvent to figure out what kind of vio event is coming + * in. We use a table to route these, and this defines + * the maximum number of distinct subtypes + */ +#define VIO_MAX_SUBTYPES 8 + +/* Each subtype can register a handler to process their events. + * The handler must have this interface. + */ +typedef void (vio_event_handler_t) (struct HvLpEvent * event); + +int viopath_open(HvLpIndex remoteLp, int subtype, int numReq); +int viopath_close(HvLpIndex remoteLp, int subtype, int numReq); +int vio_setHandler(int subtype, vio_event_handler_t * beh); +int vio_clearHandler(int subtype); +int viopath_isactive(HvLpIndex lp); +HvLpInstanceId viopath_sourceinst(HvLpIndex lp); +HvLpInstanceId viopath_targetinst(HvLpIndex lp); +void vio_set_hostlp(void); +void *vio_get_event_buffer(int subtype); +void vio_free_event_buffer(int subtype, void *buffer); + +extern HvLpIndex viopath_hostLp; +extern HvLpIndex viopath_ourLp; + +#define VIOCHAR_MAX_DATA 200 + +#define VIOMAJOR_SUBTYPE_MASK 0xff00 +#define VIOMINOR_SUBTYPE_MASK 0x00ff +#define VIOMAJOR_SUBTYPE_SHIFT 8 + +#define VIOVERSION 0x0101 + +/* + * This is the general structure for VIO errors; each module should have + * a table of them, and each table should be terminated by an entry of + * { 0, 0, NULL }. Then, to find a specific error message, a module + * should pass its local table and the return code. + */ +struct vio_error_entry { + u16 rc; + int errno; + const char *msg; +}; +const struct vio_error_entry *vio_lookup_rc(const struct vio_error_entry + *local_table, u16 rc); + +enum viosubtypes { + viomajorsubtype_monitor = 0x0100, + viomajorsubtype_blockio = 0x0200, + viomajorsubtype_chario = 0x0300, + viomajorsubtype_config = 0x0400, + viomajorsubtype_cdio = 0x0500, + viomajorsubtype_tape = 0x0600, + viomajorsubtype_scsi = 0x0700 +}; + + +enum vioconfigsubtype { + vioconfigget = 0x0001, +}; + +enum viorc { + viorc_good = 0x0000, + viorc_noConnection = 0x0001, + viorc_noReceiver = 0x0002, + viorc_noBufferAvailable = 0x0003, + viorc_invalidMessageType = 0x0004, + viorc_invalidRange = 0x0201, + viorc_invalidToken = 0x0202, + viorc_DMAError = 0x0203, + viorc_useError = 0x0204, + viorc_releaseError = 0x0205, + viorc_invalidDisk = 0x0206, + viorc_openRejected = 0x0301 +}; + +struct device; + +extern struct device *iSeries_vio_dev; + +#endif /* _ISERIES_VIO_H */ diff --git a/include/asm-ppc64/ide.h b/include/asm-ppc64/ide.h new file mode 100644 index 000000000000..0aae1c590c0e --- /dev/null +++ b/include/asm-ppc64/ide.h @@ -0,0 +1,30 @@ +/* + * linux/include/asm-ppc/ide.h + * + * Copyright (C) 1994-1996 Linus Torvalds & authors + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +/* + * This file contains the ppc64 architecture specific IDE code. + */ + +#ifndef __ASMPPC64_IDE_H +#define __ASMPPC64_IDE_H + +#ifdef __KERNEL__ + +#ifndef MAX_HWIFS +# define MAX_HWIFS 10 +#endif + +#define IDE_ARCH_OBSOLETE_INIT +#define ide_default_io_ctl(base) ((base) + 0x206) /* obsolete */ + +#endif /* __KERNEL__ */ + +#endif /* __ASMPPC64_IDE_H */ diff --git a/include/asm-ppc64/io.h b/include/asm-ppc64/io.h new file mode 100644 index 000000000000..aba1dfa388ba --- /dev/null +++ b/include/asm-ppc64/io.h @@ -0,0 +1,458 @@ +#ifndef _PPC64_IO_H +#define _PPC64_IO_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/config.h> +#include <linux/compiler.h> +#include <asm/page.h> +#include <asm/byteorder.h> +#ifdef CONFIG_PPC_ISERIES +#include <asm/iSeries/iSeries_io.h> +#endif +#include <asm/memory.h> +#include <asm/delay.h> + +#include <asm-generic/iomap.h> + +#define __ide_mm_insw(p, a, c) _insw_ns((volatile u16 *)(p), (a), (c)) +#define __ide_mm_insl(p, a, c) _insl_ns((volatile u32 *)(p), (a), (c)) +#define __ide_mm_outsw(p, a, c) _outsw_ns((volatile u16 *)(p), (a), (c)) +#define __ide_mm_outsl(p, a, c) _outsl_ns((volatile u32 *)(p), (a), (c)) + + +#define SIO_CONFIG_RA 0x398 +#define SIO_CONFIG_RD 0x399 + +#define SLOW_DOWN_IO + +extern unsigned long isa_io_base; +extern unsigned long pci_io_base; +extern unsigned long io_page_mask; + +#define MAX_ISA_PORT 0x10000 + +#define _IO_IS_VALID(port) ((port) >= MAX_ISA_PORT || (1 << (port>>PAGE_SHIFT)) \ + & io_page_mask) + +#ifdef CONFIG_PPC_ISERIES +/* __raw_* accessors aren't supported on iSeries */ +#define __raw_readb(addr) { BUG(); 0; } +#define __raw_readw(addr) { BUG(); 0; } +#define __raw_readl(addr) { BUG(); 0; } +#define __raw_readq(addr) { BUG(); 0; } +#define __raw_writeb(v, addr) { BUG(); 0; } +#define __raw_writew(v, addr) { BUG(); 0; } +#define __raw_writel(v, addr) { BUG(); 0; } +#define __raw_writeq(v, addr) { BUG(); 0; } +#define readb(addr) iSeries_Read_Byte(addr) +#define readw(addr) iSeries_Read_Word(addr) +#define readl(addr) iSeries_Read_Long(addr) +#define writeb(data, addr) iSeries_Write_Byte((data),(addr)) +#define writew(data, addr) iSeries_Write_Word((data),(addr)) +#define writel(data, addr) iSeries_Write_Long((data),(addr)) +#define memset_io(a,b,c) iSeries_memset_io((a),(b),(c)) +#define memcpy_fromio(a,b,c) iSeries_memcpy_fromio((a), (b), (c)) +#define memcpy_toio(a,b,c) iSeries_memcpy_toio((a), (b), (c)) + +#define inb(addr) readb(((void __iomem *)(long)(addr))) +#define inw(addr) readw(((void __iomem *)(long)(addr))) +#define inl(addr) readl(((void __iomem *)(long)(addr))) +#define outb(data,addr) writeb(data,((void __iomem *)(long)(addr))) +#define outw(data,addr) writew(data,((void __iomem *)(long)(addr))) +#define outl(data,addr) writel(data,((void __iomem *)(long)(addr))) +/* + * The *_ns versions below don't do byte-swapping. + * Neither do the standard versions now, these are just here + * for older code. + */ +#define insw_ns(port, buf, ns) _insw_ns((u16 *)((port)+pci_io_base), (buf), (ns)) +#define insl_ns(port, buf, nl) _insl_ns((u32 *)((port)+pci_io_base), (buf), (nl)) +#else + +static inline unsigned char __raw_readb(const volatile void __iomem *addr) +{ + return *(volatile unsigned char __force *)addr; +} +static inline unsigned short __raw_readw(const volatile void __iomem *addr) +{ + return *(volatile unsigned short __force *)addr; +} +static inline unsigned int __raw_readl(const volatile void __iomem *addr) +{ + return *(volatile unsigned int __force *)addr; +} +static inline unsigned long __raw_readq(const volatile void __iomem *addr) +{ + return *(volatile unsigned long __force *)addr; +} +static inline void __raw_writeb(unsigned char v, volatile void __iomem *addr) +{ + *(volatile unsigned char __force *)addr = v; +} +static inline void __raw_writew(unsigned short v, volatile void __iomem *addr) +{ + *(volatile unsigned short __force *)addr = v; +} +static inline void __raw_writel(unsigned int v, volatile void __iomem *addr) +{ + *(volatile unsigned int __force *)addr = v; +} +static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr) +{ + *(volatile unsigned long __force *)addr = v; +} +#define readb(addr) eeh_readb(addr) +#define readw(addr) eeh_readw(addr) +#define readl(addr) eeh_readl(addr) +#define readq(addr) eeh_readq(addr) +#define writeb(data, addr) eeh_writeb((data), (addr)) +#define writew(data, addr) eeh_writew((data), (addr)) +#define writel(data, addr) eeh_writel((data), (addr)) +#define writeq(data, addr) eeh_writeq((data), (addr)) +#define memset_io(a,b,c) eeh_memset_io((a),(b),(c)) +#define memcpy_fromio(a,b,c) eeh_memcpy_fromio((a),(b),(c)) +#define memcpy_toio(a,b,c) eeh_memcpy_toio((a),(b),(c)) +#define inb(port) eeh_inb((unsigned long)port) +#define outb(val, port) eeh_outb(val, (unsigned long)port) +#define inw(port) eeh_inw((unsigned long)port) +#define outw(val, port) eeh_outw(val, (unsigned long)port) +#define inl(port) eeh_inl((unsigned long)port) +#define outl(val, port) eeh_outl(val, (unsigned long)port) + +/* + * The insw/outsw/insl/outsl macros don't do byte-swapping. + * They are only used in practice for transferring buffers which + * are arrays of bytes, and byte-swapping is not appropriate in + * that case. - paulus */ +#define insb(port, buf, ns) eeh_insb((port), (buf), (ns)) +#define insw(port, buf, ns) eeh_insw_ns((port), (buf), (ns)) +#define insl(port, buf, nl) eeh_insl_ns((port), (buf), (nl)) +#define insw_ns(port, buf, ns) eeh_insw_ns((port), (buf), (ns)) +#define insl_ns(port, buf, nl) eeh_insl_ns((port), (buf), (nl)) + +#define outsb(port, buf, ns) _outsb((u8 *)((port)+pci_io_base), (buf), (ns)) +#define outsw(port, buf, ns) _outsw_ns((u16 *)((port)+pci_io_base), (buf), (ns)) +#define outsl(port, buf, nl) _outsl_ns((u32 *)((port)+pci_io_base), (buf), (nl)) + +#endif + +#define readb_relaxed(addr) readb(addr) +#define readw_relaxed(addr) readw(addr) +#define readl_relaxed(addr) readl(addr) +#define readq_relaxed(addr) readq(addr) + +extern void _insb(volatile u8 *port, void *buf, int ns); +extern void _outsb(volatile u8 *port, const void *buf, int ns); +extern void _insw(volatile u16 *port, void *buf, int ns); +extern void _outsw(volatile u16 *port, const void *buf, int ns); +extern void _insl(volatile u32 *port, void *buf, int nl); +extern void _outsl(volatile u32 *port, const void *buf, int nl); +extern void _insw_ns(volatile u16 *port, void *buf, int ns); +extern void _outsw_ns(volatile u16 *port, const void *buf, int ns); +extern void _insl_ns(volatile u32 *port, void *buf, int nl); +extern void _outsl_ns(volatile u32 *port, const void *buf, int nl); + +#define mmiowb() + +/* + * output pause versions need a delay at least for the + * w83c105 ide controller in a p610. + */ +#define inb_p(port) inb(port) +#define outb_p(val, port) (udelay(1), outb((val), (port))) +#define inw_p(port) inw(port) +#define outw_p(val, port) (udelay(1), outw((val), (port))) +#define inl_p(port) inl(port) +#define outl_p(val, port) (udelay(1), outl((val), (port))) + +/* + * The *_ns versions below don't do byte-swapping. + * Neither do the standard versions now, these are just here + * for older code. + */ +#define outsw_ns(port, buf, ns) _outsw_ns((u16 *)((port)+pci_io_base), (buf), (ns)) +#define outsl_ns(port, buf, nl) _outsl_ns((u32 *)((port)+pci_io_base), (buf), (nl)) + + +#define IO_SPACE_LIMIT ~(0UL) + + +#ifdef __KERNEL__ +extern int __ioremap_explicit(unsigned long p_addr, unsigned long v_addr, + unsigned long size, unsigned long flags); +extern void __iomem *__ioremap(unsigned long address, unsigned long size, + unsigned long flags); + +/** + * ioremap - map bus memory into CPU space + * @address: bus address of the memory + * @size: size of the resource to map + * + * ioremap performs a platform specific sequence of operations to + * make bus memory CPU accessible via the readb/readw/readl/writeb/ + * writew/writel functions and the other mmio helpers. The returned + * address is not guaranteed to be usable directly as a virtual + * address. + */ +extern void __iomem *ioremap(unsigned long address, unsigned long size); + +#define ioremap_nocache(addr, size) ioremap((addr), (size)) +extern int iounmap_explicit(volatile void __iomem *addr, unsigned long size); +extern void iounmap(volatile void __iomem *addr); +extern void __iomem * reserve_phb_iospace(unsigned long size); + +/** + * virt_to_phys - map virtual addresses to physical + * @address: address to remap + * + * The returned physical address is the physical (CPU) mapping for + * the memory address given. It is only valid to use this function on + * addresses directly mapped or allocated via kmalloc. + * + * This function does not give bus mappings for DMA transfers. In + * almost all conceivable cases a device driver should not be using + * this function + */ +static inline unsigned long virt_to_phys(volatile void * address) +{ + return __pa((unsigned long)address); +} + +/** + * phys_to_virt - map physical address to virtual + * @address: address to remap + * + * The returned virtual address is a current CPU mapping for + * the memory address given. It is only valid to use this function on + * addresses that have a kernel mapping + * + * This function does not handle bus mappings for DMA transfers. In + * almost all conceivable cases a device driver should not be using + * this function + */ +static inline void * phys_to_virt(unsigned long address) +{ + return (void *)__va(address); +} + +/* + * Change "struct page" to physical address. + */ +#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) + +/* We do NOT want virtual merging, it would put too much pressure on + * our iommu allocator. Instead, we want drivers to be smart enough + * to coalesce sglists that happen to have been mapped in a contiguous + * way by the iommu + */ +#define BIO_VMERGE_BOUNDARY 0 + +#endif /* __KERNEL__ */ + +static inline void iosync(void) +{ + __asm__ __volatile__ ("sync" : : : "memory"); +} + +/* Enforce in-order execution of data I/O. + * No distinction between read/write on PPC; use eieio for all three. + */ +#define iobarrier_rw() eieio() +#define iobarrier_r() eieio() +#define iobarrier_w() eieio() + +/* + * 8, 16 and 32 bit, big and little endian I/O operations, with barrier. + * These routines do not perform EEH-related I/O address translation, + * and should not be used directly by device drivers. Use inb/readb + * instead. + */ +static inline int in_8(const volatile unsigned char __iomem *addr) +{ + int ret; + + __asm__ __volatile__("lbz%U1%X1 %0,%1; twi 0,%0,0; isync" + : "=r" (ret) : "m" (*addr)); + return ret; +} + +static inline void out_8(volatile unsigned char __iomem *addr, int val) +{ + __asm__ __volatile__("stb%U0%X0 %1,%0; sync" + : "=m" (*addr) : "r" (val)); +} + +static inline int in_le16(const volatile unsigned short __iomem *addr) +{ + int ret; + + __asm__ __volatile__("lhbrx %0,0,%1; twi 0,%0,0; isync" + : "=r" (ret) : "r" (addr), "m" (*addr)); + return ret; +} + +static inline int in_be16(const volatile unsigned short __iomem *addr) +{ + int ret; + + __asm__ __volatile__("lhz%U1%X1 %0,%1; twi 0,%0,0; isync" + : "=r" (ret) : "m" (*addr)); + return ret; +} + +static inline void out_le16(volatile unsigned short __iomem *addr, int val) +{ + __asm__ __volatile__("sthbrx %1,0,%2; sync" + : "=m" (*addr) : "r" (val), "r" (addr)); +} + +static inline void out_be16(volatile unsigned short __iomem *addr, int val) +{ + __asm__ __volatile__("sth%U0%X0 %1,%0; sync" + : "=m" (*addr) : "r" (val)); +} + +static inline unsigned in_le32(const volatile unsigned __iomem *addr) +{ + unsigned ret; + + __asm__ __volatile__("lwbrx %0,0,%1; twi 0,%0,0; isync" + : "=r" (ret) : "r" (addr), "m" (*addr)); + return ret; +} + +static inline unsigned in_be32(const volatile unsigned __iomem *addr) +{ + unsigned ret; + + __asm__ __volatile__("lwz%U1%X1 %0,%1; twi 0,%0,0; isync" + : "=r" (ret) : "m" (*addr)); + return ret; +} + +static inline void out_le32(volatile unsigned __iomem *addr, int val) +{ + __asm__ __volatile__("stwbrx %1,0,%2; sync" : "=m" (*addr) + : "r" (val), "r" (addr)); +} + +static inline void out_be32(volatile unsigned __iomem *addr, int val) +{ + __asm__ __volatile__("stw%U0%X0 %1,%0; sync" + : "=m" (*addr) : "r" (val)); +} + +static inline unsigned long in_le64(const volatile unsigned long __iomem *addr) +{ + unsigned long tmp, ret; + + __asm__ __volatile__( + "ld %1,0(%2)\n" + "twi 0,%1,0\n" + "isync\n" + "rldimi %0,%1,5*8,1*8\n" + "rldimi %0,%1,3*8,2*8\n" + "rldimi %0,%1,1*8,3*8\n" + "rldimi %0,%1,7*8,4*8\n" + "rldicl %1,%1,32,0\n" + "rlwimi %0,%1,8,8,31\n" + "rlwimi %0,%1,24,16,23\n" + : "=r" (ret) , "=r" (tmp) : "b" (addr) , "m" (*addr)); + return ret; +} + +static inline unsigned long in_be64(const volatile unsigned long __iomem *addr) +{ + unsigned long ret; + + __asm__ __volatile__("ld%U1%X1 %0,%1; twi 0,%0,0; isync" + : "=r" (ret) : "m" (*addr)); + return ret; +} + +static inline void out_le64(volatile unsigned long __iomem *addr, unsigned long val) +{ + unsigned long tmp; + + __asm__ __volatile__( + "rldimi %0,%1,5*8,1*8\n" + "rldimi %0,%1,3*8,2*8\n" + "rldimi %0,%1,1*8,3*8\n" + "rldimi %0,%1,7*8,4*8\n" + "rldicl %1,%1,32,0\n" + "rlwimi %0,%1,8,8,31\n" + "rlwimi %0,%1,24,16,23\n" + "std %0,0(%3)\n" + "sync" + : "=&r" (tmp) , "=&r" (val) : "1" (val) , "b" (addr) , "m" (*addr)); +} + +static inline void out_be64(volatile unsigned long __iomem *addr, unsigned long val) +{ + __asm__ __volatile__("std%U0%X0 %1,%0; sync" : "=m" (*addr) : "r" (val)); +} + +#ifndef CONFIG_PPC_ISERIES +#include <asm/eeh.h> +#endif + +#ifdef __KERNEL__ + +/** + * check_signature - find BIOS signatures + * @io_addr: mmio address to check + * @signature: signature block + * @length: length of signature + * + * Perform a signature comparison with the mmio address io_addr. This + * address should have been obtained by ioremap. + * Returns 1 on a match. + */ +static inline int check_signature(const volatile void __iomem * io_addr, + const unsigned char *signature, int length) +{ + int retval = 0; +#ifndef CONFIG_PPC_ISERIES + do { + if (readb(io_addr) != *signature) + goto out; + io_addr++; + signature++; + length--; + } while (length); + retval = 1; +out: +#endif + return retval; +} + +/* Nothing to do */ + +#define dma_cache_inv(_start,_size) do { } while (0) +#define dma_cache_wback(_start,_size) do { } while (0) +#define dma_cache_wback_inv(_start,_size) do { } while (0) + +/* Check of existence of legacy devices */ +extern int check_legacy_ioport(unsigned long base_port); + + +/* + * Convert a physical pointer to a virtual kernel pointer for /dev/mem + * access + */ +#define xlate_dev_mem_ptr(p) __va(p) + +/* + * Convert a virtual cached pointer to an uncached pointer + */ +#define xlate_dev_kmem_ptr(p) p + +#endif /* __KERNEL__ */ + +#endif /* _PPC64_IO_H */ diff --git a/include/asm-ppc64/ioctl.h b/include/asm-ppc64/ioctl.h new file mode 100644 index 000000000000..42b8c5da7fbc --- /dev/null +++ b/include/asm-ppc64/ioctl.h @@ -0,0 +1,74 @@ +#ifndef _PPC64_IOCTL_H +#define _PPC64_IOCTL_H + + +/* + * This was copied from the alpha as it's a bit cleaner there. + * -- Cort + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#define _IOC_NRBITS 8 +#define _IOC_TYPEBITS 8 +#define _IOC_SIZEBITS 13 +#define _IOC_DIRBITS 3 + +#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1) +#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1) +#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1) +#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1) + +#define _IOC_NRSHIFT 0 +#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) +#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) +#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) + +/* + * Direction bits _IOC_NONE could be 0, but OSF/1 gives it a bit. + * And this turns out useful to catch old ioctl numbers in header + * files for us. + */ +#define _IOC_NONE 1U +#define _IOC_READ 2U +#define _IOC_WRITE 4U + +#define _IOC(dir,type,nr,size) \ + (((dir) << _IOC_DIRSHIFT) | \ + ((type) << _IOC_TYPESHIFT) | \ + ((nr) << _IOC_NRSHIFT) | \ + ((size) << _IOC_SIZESHIFT)) + +/* provoke compile error for invalid uses of size argument */ +extern unsigned int __invalid_size_argument_for_IOC; +#define _IOC_TYPECHECK(t) \ + ((sizeof(t) == sizeof(t[1]) && \ + sizeof(t) < (1 << _IOC_SIZEBITS)) ? \ + sizeof(t) : __invalid_size_argument_for_IOC) + +/* used to create numbers */ +#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) +#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size))) +#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) +#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) +#define _IOR_BAD(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) +#define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) +#define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) + +/* used to decode them.. */ +#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) +#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) +#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) +#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) + +/* various drivers, such as the pcmcia stuff, need these... */ +#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT) +#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT) +#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT) +#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT) +#define IOCSIZE_SHIFT (_IOC_SIZESHIFT) + +#endif /* _PPC64_IOCTL_H */ diff --git a/include/asm-ppc64/ioctls.h b/include/asm-ppc64/ioctls.h new file mode 100644 index 000000000000..48796bf3e4fc --- /dev/null +++ b/include/asm-ppc64/ioctls.h @@ -0,0 +1,114 @@ +#ifndef _ASM_PPC64_IOCTLS_H +#define _ASM_PPC64_IOCTLS_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <asm/ioctl.h> + +#define FIOCLEX _IO('f', 1) +#define FIONCLEX _IO('f', 2) +#define FIOASYNC _IOW('f', 125, int) +#define FIONBIO _IOW('f', 126, int) +#define FIONREAD _IOR('f', 127, int) +#define TIOCINQ FIONREAD +#define FIOQSIZE _IOR('f', 128, loff_t) + +#define TIOCGETP _IOR('t', 8, struct sgttyb) +#define TIOCSETP _IOW('t', 9, struct sgttyb) +#define TIOCSETN _IOW('t', 10, struct sgttyb) /* TIOCSETP wo flush */ + +#define TIOCSETC _IOW('t', 17, struct tchars) +#define TIOCGETC _IOR('t', 18, struct tchars) +#define TCGETS _IOR('t', 19, struct termios) +#define TCSETS _IOW('t', 20, struct termios) +#define TCSETSW _IOW('t', 21, struct termios) +#define TCSETSF _IOW('t', 22, struct termios) + +#define TCGETA _IOR('t', 23, struct termio) +#define TCSETA _IOW('t', 24, struct termio) +#define TCSETAW _IOW('t', 25, struct termio) +#define TCSETAF _IOW('t', 28, struct termio) + +#define TCSBRK _IO('t', 29) +#define TCXONC _IO('t', 30) +#define TCFLSH _IO('t', 31) + +#define TIOCSWINSZ _IOW('t', 103, struct winsize) +#define TIOCGWINSZ _IOR('t', 104, struct winsize) +#define TIOCSTART _IO('t', 110) /* start output, like ^Q */ +#define TIOCSTOP _IO('t', 111) /* stop output, like ^S */ +#define TIOCOUTQ _IOR('t', 115, int) /* output queue size */ + +#define TIOCGLTC _IOR('t', 116, struct ltchars) +#define TIOCSLTC _IOW('t', 117, struct ltchars) +#define TIOCSPGRP _IOW('t', 118, int) +#define TIOCGPGRP _IOR('t', 119, int) + +#define TIOCEXCL 0x540C +#define TIOCNXCL 0x540D +#define TIOCSCTTY 0x540E + +#define TIOCSTI 0x5412 +#define TIOCMGET 0x5415 +#define TIOCMBIS 0x5416 +#define TIOCMBIC 0x5417 +#define TIOCMSET 0x5418 +# define TIOCM_LE 0x001 +# define TIOCM_DTR 0x002 +# define TIOCM_RTS 0x004 +# define TIOCM_ST 0x008 +# define TIOCM_SR 0x010 +# define TIOCM_CTS 0x020 +# define TIOCM_CAR 0x040 +# define TIOCM_RNG 0x080 +# define TIOCM_DSR 0x100 +# define TIOCM_CD TIOCM_CAR +# define TIOCM_RI TIOCM_RNG + +#define TIOCGSOFTCAR 0x5419 +#define TIOCSSOFTCAR 0x541A +#define TIOCLINUX 0x541C +#define TIOCCONS 0x541D +#define TIOCGSERIAL 0x541E +#define TIOCSSERIAL 0x541F +#define TIOCPKT 0x5420 +# define TIOCPKT_DATA 0 +# define TIOCPKT_FLUSHREAD 1 +# define TIOCPKT_FLUSHWRITE 2 +# define TIOCPKT_STOP 4 +# define TIOCPKT_START 8 +# define TIOCPKT_NOSTOP 16 +# define TIOCPKT_DOSTOP 32 + + +#define TIOCNOTTY 0x5422 +#define TIOCSETD 0x5423 +#define TIOCGETD 0x5424 +#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ +#define TIOCSBRK 0x5427 /* BSD compatibility */ +#define TIOCCBRK 0x5428 /* BSD compatibility */ +#define TIOCGSID 0x5429 /* Return the session ID of FD */ +#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ + +#define TIOCSERCONFIG 0x5453 +#define TIOCSERGWILD 0x5454 +#define TIOCSERSWILD 0x5455 +#define TIOCGLCKTRMIOS 0x5456 +#define TIOCSLCKTRMIOS 0x5457 +#define TIOCSERGSTRUCT 0x5458 /* For debugging only */ +#define TIOCSERGETLSR 0x5459 /* Get line status register */ + /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ +# define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ +#define TIOCSERGETMULTI 0x545A /* Get multiport config */ +#define TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ +#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ + +#endif /* _ASM_PPC64_IOCTLS_H */ diff --git a/include/asm-ppc64/iommu.h b/include/asm-ppc64/iommu.h new file mode 100644 index 000000000000..bd53ca4dcfa2 --- /dev/null +++ b/include/asm-ppc64/iommu.h @@ -0,0 +1,166 @@ +/* + * iommu.h + * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation + * Rewrite, cleanup: + * Copyright (C) 2004 Olof Johansson <olof@austin.ibm.com>, IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ASM_IOMMU_H +#define _ASM_IOMMU_H + +#include <asm/types.h> +#include <linux/spinlock.h> +#include <linux/device.h> +#include <linux/dma-mapping.h> + +/* + * IOMAP_MAX_ORDER defines the largest contiguous block + * of dma (tce) space we can get. IOMAP_MAX_ORDER = 13 + * allows up to 2**12 pages (4096 * 4096) = 16 MB + */ +#define IOMAP_MAX_ORDER 13 + +/* + * Tces come in two formats, one for the virtual bus and a different + * format for PCI + */ +#define TCE_VB 0 +#define TCE_PCI 1 + +/* tce_entry + * Used by pSeries (SMP) and iSeries/pSeries LPAR, but there it's + * abstracted so layout is irrelevant. + */ +union tce_entry { + unsigned long te_word; + struct { + unsigned int tb_cacheBits :6; /* Cache hash bits - not used */ + unsigned int tb_rsvd :6; + unsigned long tb_rpn :40; /* Real page number */ + unsigned int tb_valid :1; /* Tce is valid (vb only) */ + unsigned int tb_allio :1; /* Tce is valid for all lps (vb only) */ + unsigned int tb_lpindex :8; /* LpIndex for user of TCE (vb only) */ + unsigned int tb_pciwr :1; /* Write allowed (pci only) */ + unsigned int tb_rdwr :1; /* Read allowed (pci), Write allowed (vb) */ + } te_bits; +#define te_cacheBits te_bits.tb_cacheBits +#define te_rpn te_bits.tb_rpn +#define te_valid te_bits.tb_valid +#define te_allio te_bits.tb_allio +#define te_lpindex te_bits.tb_lpindex +#define te_pciwr te_bits.tb_pciwr +#define te_rdwr te_bits.tb_rdwr +}; + + +struct iommu_table { + unsigned long it_busno; /* Bus number this table belongs to */ + unsigned long it_size; /* Size of iommu table in entries */ + unsigned long it_offset; /* Offset into global table */ + unsigned long it_base; /* mapped address of tce table */ + unsigned long it_index; /* which iommu table this is */ + unsigned long it_type; /* type: PCI or Virtual Bus */ + unsigned long it_blocksize; /* Entries in each block (cacheline) */ + unsigned long it_hint; /* Hint for next alloc */ + unsigned long it_largehint; /* Hint for large allocs */ + unsigned long it_halfpoint; /* Breaking point for small/large allocs */ + spinlock_t it_lock; /* Protects it_map */ + unsigned long *it_map; /* A simple allocation bitmap for now */ +}; + +#ifdef CONFIG_PPC_ISERIES +struct iommu_table_cb { + unsigned long itc_busno; /* Bus number for this tce table */ + unsigned long itc_start; /* Will be NULL for secondary */ + unsigned long itc_totalsize; /* Size (in pages) of whole table */ + unsigned long itc_offset; /* Index into real tce table of the + start of our section */ + unsigned long itc_size; /* Size (in pages) of our section */ + unsigned long itc_index; /* Index of this tce table */ + unsigned short itc_maxtables; /* Max num of tables for partition */ + unsigned char itc_virtbus; /* Flag to indicate virtual bus */ + unsigned char itc_slotno; /* IOA Tce Slot Index */ + unsigned char itc_rsvd[4]; +}; + +extern struct iommu_table vio_tce_table; /* Tce table for virtual bus */ +#endif /* CONFIG_PPC_ISERIES */ + +struct scatterlist; + +#ifdef CONFIG_PPC_MULTIPLATFORM + +/* Walks all buses and creates iommu tables */ +extern void iommu_setup_pSeries(void); +extern void iommu_setup_u3(void); + +/* Frees table for an individual device node */ +extern void iommu_free_table(struct device_node *dn); + +#endif /* CONFIG_PPC_MULTIPLATFORM */ + +#ifdef CONFIG_PPC_PSERIES + +/* Creates table for an individual device node */ +extern void iommu_devnode_init_pSeries(struct device_node *dn); + +#endif /* CONFIG_PPC_PSERIES */ + +#ifdef CONFIG_PPC_ISERIES + +/* Walks all buses and creates iommu tables */ +extern void iommu_setup_iSeries(void); + +/* Initializes tables for bio buses */ +extern void __init iommu_vio_init(void); + +struct iSeries_Device_Node; +/* Creates table for an individual device node */ +extern void iommu_devnode_init_iSeries(struct iSeries_Device_Node *dn); + +#endif /* CONFIG_PPC_ISERIES */ + +/* Initializes an iommu_table based in values set in the passed-in + * structure + */ +extern struct iommu_table *iommu_init_table(struct iommu_table * tbl); + +extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl, + struct scatterlist *sglist, int nelems, + enum dma_data_direction direction); +extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, + int nelems, enum dma_data_direction direction); + +extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, + dma_addr_t *dma_handle, unsigned int __nocast flag); +extern void iommu_free_coherent(struct iommu_table *tbl, size_t size, + void *vaddr, dma_addr_t dma_handle); +extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, + size_t size, enum dma_data_direction direction); +extern void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle, + size_t size, enum dma_data_direction direction); + +extern void iommu_init_early_pSeries(void); +extern void iommu_init_early_iSeries(void); +extern void iommu_init_early_u3(void); + +extern void pci_iommu_init(void); +extern void pci_direct_iommu_init(void); + +extern void alloc_u3_dart_table(void); + +#endif /* _ASM_IOMMU_H */ diff --git a/include/asm-ppc64/ipc.h b/include/asm-ppc64/ipc.h new file mode 100644 index 000000000000..a46e3d9c2a3f --- /dev/null +++ b/include/asm-ppc64/ipc.h @@ -0,0 +1 @@ +#include <asm-generic/ipc.h> diff --git a/include/asm-ppc64/ipcbuf.h b/include/asm-ppc64/ipcbuf.h new file mode 100644 index 000000000000..fa393c8342af --- /dev/null +++ b/include/asm-ppc64/ipcbuf.h @@ -0,0 +1,28 @@ +#ifndef __PPC64_IPCBUF_H__ +#define __PPC64_IPCBUF_H__ + +/* + * The ipc64_perm structure for the PPC is identical to kern_ipc_perm + * as we have always had 32-bit UIDs and GIDs in the kernel. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +struct ipc64_perm +{ + __kernel_key_t key; + __kernel_uid_t uid; + __kernel_gid_t gid; + __kernel_uid_t cuid; + __kernel_gid_t cgid; + __kernel_mode_t mode; + unsigned int seq; + unsigned int __pad1; + unsigned long __unused1; + unsigned long __unused2; +}; + +#endif /* __PPC64_IPCBUF_H__ */ diff --git a/include/asm-ppc64/irq.h b/include/asm-ppc64/irq.h new file mode 100644 index 000000000000..570678b1da95 --- /dev/null +++ b/include/asm-ppc64/irq.h @@ -0,0 +1,115 @@ +#ifdef __KERNEL__ +#ifndef _ASM_IRQ_H +#define _ASM_IRQ_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/config.h> +#include <linux/threads.h> + +/* + * Maximum number of interrupt sources that we can handle. + */ +#define NR_IRQS 512 + +/* this number is used when no interrupt has been assigned */ +#define NO_IRQ (-1) + +/* + * These constants are used for passing information about interrupt + * signal polarity and level/edge sensing to the low-level PIC chip + * drivers. + */ +#define IRQ_SENSE_MASK 0x1 +#define IRQ_SENSE_LEVEL 0x1 /* interrupt on active level */ +#define IRQ_SENSE_EDGE 0x0 /* interrupt triggered by edge */ + +#define IRQ_POLARITY_MASK 0x2 +#define IRQ_POLARITY_POSITIVE 0x2 /* high level or low->high edge */ +#define IRQ_POLARITY_NEGATIVE 0x0 /* low level or high->low edge */ + +#define get_irq_desc(irq) (&irq_desc[(irq)]) + +/* Define a way to iterate across irqs. */ +#define for_each_irq(i) \ + for ((i) = 0; (i) < NR_IRQS; ++(i)) + +/* Interrupt numbers are virtual in case they are sparsely + * distributed by the hardware. + */ +extern unsigned int virt_irq_to_real_map[NR_IRQS]; + +/* Create a mapping for a real_irq if it doesn't already exist. + * Return the virtual irq as a convenience. + */ +int virt_irq_create_mapping(unsigned int real_irq); +void virt_irq_init(void); + +static inline unsigned int virt_irq_to_real(unsigned int virt_irq) +{ + return virt_irq_to_real_map[virt_irq]; +} + +extern unsigned int real_irq_to_virt_slowpath(unsigned int real_irq); + +/* + * Because many systems have two overlapping names spaces for + * interrupts (ISA and XICS for example), and the ISA interrupts + * have historically not been easy to renumber, we allow ISA + * interrupts to take values 0 - 15, and shift up the remaining + * interrupts by 0x10. + */ +#define NUM_ISA_INTERRUPTS 0x10 +extern int __irq_offset_value; + +static inline int irq_offset_up(int irq) +{ + return(irq + __irq_offset_value); +} + +static inline int irq_offset_down(int irq) +{ + return(irq - __irq_offset_value); +} + +static inline int irq_offset_value(void) +{ + return __irq_offset_value; +} + +static __inline__ int irq_canonicalize(int irq) +{ + return irq; +} + +extern int distribute_irqs; + +struct irqaction; +struct pt_regs; + +#ifdef CONFIG_IRQSTACKS +/* + * Per-cpu stacks for handling hard and soft interrupts. + */ +extern struct thread_info *hardirq_ctx[NR_CPUS]; +extern struct thread_info *softirq_ctx[NR_CPUS]; + +extern void irq_ctx_init(void); +extern void call_do_softirq(struct thread_info *tp); +extern int call_handle_IRQ_event(int irq, struct pt_regs *regs, + struct irqaction *action, struct thread_info *tp); + +#define __ARCH_HAS_DO_SOFTIRQ + +#else +#define irq_ctx_init() + +#endif /* CONFIG_IRQSTACKS */ + +#endif /* _ASM_IRQ_H */ +#endif /* __KERNEL__ */ diff --git a/include/asm-ppc64/kdebug.h b/include/asm-ppc64/kdebug.h new file mode 100644 index 000000000000..488634258a72 --- /dev/null +++ b/include/asm-ppc64/kdebug.h @@ -0,0 +1,43 @@ +#ifndef _PPC64_KDEBUG_H +#define _PPC64_KDEBUG_H 1 + +/* nearly identical to x86_64/i386 code */ + +#include <linux/notifier.h> + +struct pt_regs; + +struct die_args { + struct pt_regs *regs; + const char *str; + long err; + int trapnr; + int signr; +}; + +/* + Note - you should never unregister because that can race with NMIs. + If you really want to do it first unregister - then synchronize_kernel - + then free. + */ +int register_die_notifier(struct notifier_block *nb); +extern struct notifier_block *ppc64_die_chain; + +/* Grossly misnamed. */ +enum die_val { + DIE_OOPS = 1, + DIE_IABR_MATCH, + DIE_DABR_MATCH, + DIE_BPT, + DIE_SSTEP, + DIE_GPF, + DIE_PAGE_FAULT, +}; + +static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig) +{ + struct die_args args = { .regs=regs, .str=str, .err=err, .trapnr=trap,.signr=sig }; + return notifier_call_chain(&ppc64_die_chain, val, &args); +} + +#endif diff --git a/include/asm-ppc64/keylargo.h b/include/asm-ppc64/keylargo.h new file mode 100644 index 000000000000..4d78e3d0314c --- /dev/null +++ b/include/asm-ppc64/keylargo.h @@ -0,0 +1,2 @@ +#include <asm-ppc/keylargo.h> + diff --git a/include/asm-ppc64/kmap_types.h b/include/asm-ppc64/kmap_types.h new file mode 100644 index 000000000000..fd1574648223 --- /dev/null +++ b/include/asm-ppc64/kmap_types.h @@ -0,0 +1,23 @@ +#ifdef __KERNEL__ +#ifndef _ASM_KMAP_TYPES_H +#define _ASM_KMAP_TYPES_H + +enum km_type { + KM_BOUNCE_READ, + KM_SKB_SUNRPC_DATA, + KM_SKB_DATA_SOFTIRQ, + KM_USER0, + KM_USER1, + KM_BIO_SRC_IRQ, + KM_BIO_DST_IRQ, + KM_PTE0, + KM_PTE1, + KM_IRQ0, + KM_IRQ1, + KM_SOFTIRQ0, + KM_SOFTIRQ1, + KM_TYPE_NR +}; + +#endif +#endif /* __KERNEL__ */ diff --git a/include/asm-ppc64/kprobes.h b/include/asm-ppc64/kprobes.h new file mode 100644 index 000000000000..19b468bed059 --- /dev/null +++ b/include/asm-ppc64/kprobes.h @@ -0,0 +1,61 @@ +#ifndef _ASM_KPROBES_H +#define _ASM_KPROBES_H +/* + * Kernel Probes (KProbes) + * include/asm-ppc64/kprobes.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) IBM Corporation, 2002, 2004 + * + * 2002-Oct Created by Vamsi Krishna S <vamsi_krishna@in.ibm.com> Kernel + * Probes initial implementation ( includes suggestions from + * Rusty Russell). + * 2004-Nov Modified for PPC64 by Ananth N Mavinakayanahalli + * <ananth@in.ibm.com> + */ +#include <linux/types.h> +#include <linux/ptrace.h> + +struct pt_regs; + +typedef unsigned int kprobe_opcode_t; +#define BREAKPOINT_INSTRUCTION 0x7fe00008 /* trap */ +#define MAX_INSN_SIZE 1 + +#define IS_TW(instr) (((instr) & 0xfc0007fe) == 0x7c000008) +#define IS_TD(instr) (((instr) & 0xfc0007fe) == 0x7c000088) +#define IS_TDI(instr) (((instr) & 0xfc000000) == 0x08000000) +#define IS_TWI(instr) (((instr) & 0xfc000000) == 0x0c000000) + +#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)((func_descr_t *)pentry) + +/* Architecture specific copy of original instruction */ +struct arch_specific_insn { + /* copy of original instruction */ + kprobe_opcode_t insn[MAX_INSN_SIZE]; +}; + +#ifdef CONFIG_KPROBES +extern int kprobe_exceptions_notify(struct notifier_block *self, + unsigned long val, void *data); +#else /* !CONFIG_KPROBES */ +static inline int kprobe_exceptions_notify(struct notifier_block *self, + unsigned long val, void *data) +{ + return 0; +} +#endif +#endif /* _ASM_KPROBES_H */ diff --git a/include/asm-ppc64/linkage.h b/include/asm-ppc64/linkage.h new file mode 100644 index 000000000000..291c2d01c44f --- /dev/null +++ b/include/asm-ppc64/linkage.h @@ -0,0 +1,6 @@ +#ifndef __ASM_LINKAGE_H +#define __ASM_LINKAGE_H + +/* Nothing to see here... */ + +#endif diff --git a/include/asm-ppc64/lmb.h b/include/asm-ppc64/lmb.h new file mode 100644 index 000000000000..a6cbca21ac1d --- /dev/null +++ b/include/asm-ppc64/lmb.h @@ -0,0 +1,60 @@ +#ifndef _PPC64_LMB_H +#define _PPC64_LMB_H + +/* + * Definitions for talking to the Open Firmware PROM on + * Power Macintosh computers. + * + * Copyright (C) 2001 Peter Bergner, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/init.h> +#include <asm/prom.h> + +#define MAX_LMB_REGIONS 128 + +#define LMB_ALLOC_ANYWHERE 0 + +struct lmb_property { + unsigned long base; + unsigned long physbase; + unsigned long size; +}; + +struct lmb_region { + unsigned long cnt; + unsigned long size; + struct lmb_property region[MAX_LMB_REGIONS+1]; +}; + +struct lmb { + unsigned long debug; + unsigned long rmo_size; + struct lmb_region memory; + struct lmb_region reserved; +}; + +extern struct lmb lmb; + +extern void __init lmb_init(void); +extern void __init lmb_analyze(void); +extern long __init lmb_add(unsigned long, unsigned long); +extern long __init lmb_reserve(unsigned long, unsigned long); +extern unsigned long __init lmb_alloc(unsigned long, unsigned long); +extern unsigned long __init lmb_alloc_base(unsigned long, unsigned long, + unsigned long); +extern unsigned long __init lmb_phys_mem_size(void); +extern unsigned long __init lmb_end_of_DRAM(void); +extern unsigned long __init lmb_abs_to_phys(unsigned long); +extern void __init lmb_enforce_memory_limit(void); + +extern void lmb_dump_all(void); + +extern unsigned long io_hole_start; + +#endif /* _PPC64_LMB_H */ diff --git a/include/asm-ppc64/local.h b/include/asm-ppc64/local.h new file mode 100644 index 000000000000..c11c530f74d0 --- /dev/null +++ b/include/asm-ppc64/local.h @@ -0,0 +1 @@ +#include <asm-generic/local.h> diff --git a/include/asm-ppc64/lppaca.h b/include/asm-ppc64/lppaca.h new file mode 100644 index 000000000000..70766b5f26c1 --- /dev/null +++ b/include/asm-ppc64/lppaca.h @@ -0,0 +1,132 @@ +/* + * lppaca.h + * Copyright (C) 2001 Mike Corrigan IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _ASM_LPPACA_H +#define _ASM_LPPACA_H + +//============================================================================= +// +// This control block contains the data that is shared between the +// hypervisor (PLIC) and the OS. +// +// +//---------------------------------------------------------------------------- +#include <asm/types.h> + +struct lppaca +{ +//============================================================================= +// CACHE_LINE_1 0x0000 - 0x007F Contains read-only data +// NOTE: The xDynXyz fields are fields that will be dynamically changed by +// PLIC when preparing to bring a processor online or when dispatching a +// virtual processor! +//============================================================================= + u32 desc; // Eye catcher 0xD397D781 x00-x03 + u16 size; // Size of this struct x04-x05 + u16 reserved1; // Reserved x06-x07 + u16 reserved2:14; // Reserved x08-x09 + u8 shared_proc:1; // Shared processor indicator ... + u8 secondary_thread:1; // Secondary thread indicator ... + volatile u8 dyn_proc_status:8; // Dynamic Status of this proc x0A-x0A + u8 secondary_thread_count; // Secondary thread count x0B-x0B + volatile u16 dyn_hv_phys_proc_index;// Dynamic HV Physical Proc Index0C-x0D + volatile u16 dyn_hv_log_proc_index;// Dynamic HV Logical Proc Indexx0E-x0F + u32 decr_val; // Value for Decr programming x10-x13 + u32 pmc_val; // Value for PMC regs x14-x17 + volatile u32 dyn_hw_node_id; // Dynamic Hardware Node id x18-x1B + volatile u32 dyn_hw_proc_id; // Dynamic Hardware Proc Id x1C-x1F + volatile u32 dyn_pir; // Dynamic ProcIdReg value x20-x23 + u32 dsei_data; // DSEI data x24-x27 + u64 sprg3; // SPRG3 value x28-x2F + u8 reserved3[80]; // Reserved x30-x7F + +//============================================================================= +// CACHE_LINE_2 0x0080 - 0x00FF Contains local read-write data +//============================================================================= + // This Dword contains a byte for each type of interrupt that can occur. + // The IPI is a count while the others are just a binary 1 or 0. + union { + u64 any_int; + struct { + u16 reserved; // Reserved - cleared by #mpasmbl + u8 xirr_int; // Indicates xXirrValue is valid or Immed IO + u8 ipi_cnt; // IPI Count + u8 decr_int; // DECR interrupt occurred + u8 pdc_int; // PDC interrupt occurred + u8 quantum_int; // Interrupt quantum reached + u8 old_plic_deferred_ext_int; // Old PLIC has a deferred XIRR pending + } fields; + } int_dword; + + // Whenever any fields in this Dword are set then PLIC will defer the + // processing of external interrupts. Note that PLIC will store the + // XIRR directly into the xXirrValue field so that another XIRR will + // not be presented until this one clears. The layout of the low + // 4-bytes of this Dword is upto SLIC - PLIC just checks whether the + // entire Dword is zero or not. A non-zero value in the low order + // 2-bytes will result in SLIC being granted the highest thread + // priority upon return. A 0 will return to SLIC as medium priority. + u64 plic_defer_ints_area; // Entire Dword + + // Used to pass the real SRR0/1 from PLIC to SLIC as well as to + // pass the target SRR0/1 from SLIC to PLIC on a SetAsrAndRfid. + u64 saved_srr0; // Saved SRR0 x10-x17 + u64 saved_srr1; // Saved SRR1 x18-x1F + + // Used to pass parms from the OS to PLIC for SetAsrAndRfid + u64 saved_gpr3; // Saved GPR3 x20-x27 + u64 saved_gpr4; // Saved GPR4 x28-x2F + u64 saved_gpr5; // Saved GPR5 x30-x37 + + u8 reserved4; // Reserved x38-x38 + u8 cpuctls_task_attrs; // Task attributes for cpuctls x39-x39 + u8 fpregs_in_use; // FP regs in use x3A-x3A + u8 pmcregs_in_use; // PMC regs in use x3B-x3B + volatile u32 saved_decr; // Saved Decr Value x3C-x3F + volatile u64 emulated_time_base;// Emulated TB for this thread x40-x47 + volatile u64 cur_plic_latency; // Unaccounted PLIC latency x48-x4F + u64 tot_plic_latency; // Accumulated PLIC latency x50-x57 + u64 wait_state_cycles; // Wait cycles for this proc x58-x5F + u64 end_of_quantum; // TB at end of quantum x60-x67 + u64 pdc_saved_sprg1; // Saved SPRG1 for PMC int x68-x6F + u64 pdc_saved_srr0; // Saved SRR0 for PMC int x70-x77 + volatile u32 virtual_decr; // Virtual DECR for shared procsx78-x7B + u16 slb_count; // # of SLBs to maintain x7C-x7D + u8 idle; // Indicate OS is idle x7E + u8 reserved5; // Reserved x7F + + +//============================================================================= +// CACHE_LINE_3 0x0100 - 0x007F: This line is shared with other processors +//============================================================================= + // This is the yield_count. An "odd" value (low bit on) means that + // the processor is yielded (either because of an OS yield or a PLIC + // preempt). An even value implies that the processor is currently + // executing. + // NOTE: This value will ALWAYS be zero for dedicated processors and + // will NEVER be zero for shared processors (ie, initialized to a 1). + volatile u32 yield_count; // PLIC increments each dispatchx00-x03 + u8 reserved6[124]; // Reserved x04-x7F + +//============================================================================= +// CACHE_LINE_4-5 0x0100 - 0x01FF Contains PMC interrupt data +//============================================================================= + u8 pmc_save_area[256]; // PMC interrupt Area x00-xFF +}; + +#endif /* _ASM_LPPACA_H */ diff --git a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h new file mode 100644 index 000000000000..5d3cd9d042e2 --- /dev/null +++ b/include/asm-ppc64/machdep.h @@ -0,0 +1,185 @@ +#ifdef __KERNEL__ +#ifndef _PPC64_MACHDEP_H +#define _PPC64_MACHDEP_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/config.h> +#include <linux/seq_file.h> +#include <linux/init.h> +#include <linux/dma-mapping.h> + +#include <asm/setup.h> + +struct pt_regs; +struct pci_bus; +struct device_node; +struct iommu_table; +struct rtc_time; +struct file; + +#ifdef CONFIG_SMP +struct smp_ops_t { + void (*message_pass)(int target, int msg); + int (*probe)(void); + void (*kick_cpu)(int nr); + void (*setup_cpu)(int nr); + void (*take_timebase)(void); + void (*give_timebase)(void); + int (*cpu_enable)(unsigned int nr); + int (*cpu_disable)(void); + void (*cpu_die)(unsigned int nr); + int (*cpu_bootable)(unsigned int nr); +}; +#endif + +struct machdep_calls { + void (*hpte_invalidate)(unsigned long slot, + unsigned long va, + int large, + int local); + long (*hpte_updatepp)(unsigned long slot, + unsigned long newpp, + unsigned long va, + int large, + int local); + void (*hpte_updateboltedpp)(unsigned long newpp, + unsigned long ea); + long (*hpte_insert)(unsigned long hpte_group, + unsigned long va, + unsigned long prpn, + int secondary, + unsigned long hpteflags, + int bolted, + int large); + long (*hpte_remove)(unsigned long hpte_group); + void (*flush_hash_range)(unsigned long context, + unsigned long number, + int local); + /* special for kexec, to be called in real mode, linar mapping is + * destroyed as well */ + void (*hpte_clear_all)(void); + + void (*tce_build)(struct iommu_table * tbl, + long index, + long npages, + unsigned long uaddr, + enum dma_data_direction direction); + void (*tce_free)(struct iommu_table *tbl, + long index, + long npages); + void (*tce_flush)(struct iommu_table *tbl); + void (*iommu_dev_setup)(struct pci_dev *dev); + void (*iommu_bus_setup)(struct pci_bus *bus); + + int (*probe)(int platform); + void (*setup_arch)(void); + void (*init_early)(void); + /* Optional, may be NULL. */ + void (*get_cpuinfo)(struct seq_file *m); + + void (*init_IRQ)(void); + int (*get_irq)(struct pt_regs *); + + /* PCI stuff */ + void (*pcibios_fixup)(void); + + void (*restart)(char *cmd); + void (*power_off)(void); + void (*halt)(void); + void (*panic)(char *str); + void (*cpu_die)(void); + + int (*set_rtc_time)(struct rtc_time *); + void (*get_rtc_time)(struct rtc_time *); + void (*get_boot_time)(struct rtc_time *); + + void (*calibrate_decr)(void); + + void (*progress)(char *, unsigned short); + + /* Debug interface. Low level I/O to some terminal device */ + void (*udbg_putc)(unsigned char c); + unsigned char (*udbg_getc)(void); + int (*udbg_getc_poll)(void); + + /* Interface for platform error logging */ + void (*log_error)(char *buf, unsigned int err_type, int fatal); + + ssize_t (*nvram_write)(char *buf, size_t count, loff_t *index); + ssize_t (*nvram_read)(char *buf, size_t count, loff_t *index); + ssize_t (*nvram_size)(void); + int (*nvram_sync)(void); + + /* Exception handlers */ + void (*system_reset_exception)(struct pt_regs *regs); + int (*machine_check_exception)(struct pt_regs *regs); + + /* Motherboard/chipset features. This is a kind of general purpose + * hook used to control some machine specific features (like reset + * lines, chip power control, etc...). + */ + long (*feature_call)(unsigned int feature, ...); + + /* Check availability of legacy devices like i8042 */ + int (*check_legacy_ioport)(unsigned int baseport); + + /* Get legacy PCI/IDE interrupt mapping */ + int (*pci_get_legacy_ide_irq)(struct pci_dev *dev, int channel); + + /* Get access protection for /dev/mem */ + pgprot_t (*phys_mem_access_prot)(struct file *file, + unsigned long offset, + unsigned long size, + pgprot_t vma_prot); + +}; + +extern struct machdep_calls ppc_md; +extern char cmd_line[COMMAND_LINE_SIZE]; + +#ifdef CONFIG_PPC_PMAC +/* + * Power macintoshes have either a CUDA, PMU or SMU controlling + * system reset, power, NVRAM, RTC. + */ +typedef enum sys_ctrler_kind { + SYS_CTRLER_UNKNOWN = 0, + SYS_CTRLER_CUDA = 1, + SYS_CTRLER_PMU = 2, + SYS_CTRLER_SMU = 3, +} sys_ctrler_t; +extern sys_ctrler_t sys_ctrler; + +#endif /* CONFIG_PPC_PMAC */ + + + +/* Functions to produce codes on the leds. + * The SRC code should be unique for the message category and should + * be limited to the lower 24 bits (the upper 8 are set by these funcs), + * and (for boot & dump) should be sorted numerically in the order + * the events occur. + */ +/* Print a boot progress message. */ +void ppc64_boot_msg(unsigned int src, const char *msg); +/* Print a termination message (print only -- does not stop the kernel) */ +void ppc64_terminate_msg(unsigned int src, const char *msg); +/* Print something that needs attention (device error, etc) */ +void ppc64_attention_msg(unsigned int src, const char *msg); +/* Print a dump progress message. */ +void ppc64_dump_msg(unsigned int src, const char *msg); + +static inline void log_error(char *buf, unsigned int err_type, int fatal) +{ + if (ppc_md.log_error) + ppc_md.log_error(buf, err_type, fatal); +} + +#endif /* _PPC64_MACHDEP_H */ +#endif /* __KERNEL__ */ diff --git a/include/asm-ppc64/macio.h b/include/asm-ppc64/macio.h new file mode 100644 index 000000000000..a3028b364f70 --- /dev/null +++ b/include/asm-ppc64/macio.h @@ -0,0 +1,2 @@ +#include <asm-ppc/macio.h> + diff --git a/include/asm-ppc64/mc146818rtc.h b/include/asm-ppc64/mc146818rtc.h new file mode 100644 index 000000000000..f713e1bbb533 --- /dev/null +++ b/include/asm-ppc64/mc146818rtc.h @@ -0,0 +1,32 @@ +/* + * Machine dependent access functions for RTC registers. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef __ASM_PPC64_MC146818RTC_H +#define __ASM_PPC64_MC146818RTC_H + +#include <asm/io.h> + +#ifndef RTC_PORT +#define RTC_PORT(x) (0x70 + (x)) +#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */ +#endif + +/* + * The yet supported machines all access the RTC index register via + * an ISA port access but the way to access the date register differs ... + */ +#define CMOS_READ(addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +inb_p(RTC_PORT(1)); \ +}) +#define CMOS_WRITE(val, addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +outb_p((val),RTC_PORT(1)); \ +}) + +#endif /* __ASM_PPC64_MC146818RTC_H */ diff --git a/include/asm-ppc64/memory.h b/include/asm-ppc64/memory.h new file mode 100644 index 000000000000..56e09face9a8 --- /dev/null +++ b/include/asm-ppc64/memory.h @@ -0,0 +1,59 @@ +#ifndef _ASM_PPC64_MEMORY_H_ +#define _ASM_PPC64_MEMORY_H_ + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/config.h> + +/* + * Arguably the bitops and *xchg operations don't imply any memory barrier + * or SMP ordering, but in fact a lot of drivers expect them to imply + * both, since they do on x86 cpus. + */ +#ifdef CONFIG_SMP +#define EIEIO_ON_SMP "eieio\n" +#define ISYNC_ON_SMP "\n\tisync" +#else +#define EIEIO_ON_SMP +#define ISYNC_ON_SMP +#endif + +static inline void eieio(void) +{ + __asm__ __volatile__ ("eieio" : : : "memory"); +} + +static inline void isync(void) +{ + __asm__ __volatile__ ("isync" : : : "memory"); +} + +#ifdef CONFIG_SMP +#define eieio_on_smp() eieio() +#define isync_on_smp() isync() +#else +#define eieio_on_smp() __asm__ __volatile__("": : :"memory") +#define isync_on_smp() __asm__ __volatile__("": : :"memory") +#endif + +/* Macros for adjusting thread priority (hardware multi-threading) */ +#define HMT_very_low() asm volatile("or 31,31,31 # very low priority") +#define HMT_low() asm volatile("or 1,1,1 # low priority") +#define HMT_medium_low() asm volatile("or 6,6,6 # medium low priority") +#define HMT_medium() asm volatile("or 2,2,2 # medium priority") +#define HMT_medium_high() asm volatile("or 5,5,5 # medium high priority") +#define HMT_high() asm volatile("or 3,3,3 # high priority") + +#define HMT_VERY_LOW "\tor 31,31,31 # very low priority\n" +#define HMT_LOW "\tor 1,1,1 # low priority\n" +#define HMT_MEDIUM_LOW "\tor 6,6,6 # medium low priority\n" +#define HMT_MEDIUM "\tor 2,2,2 # medium priority\n" +#define HMT_MEDIUM_HIGH "\tor 5,5,5 # medium high priority\n" +#define HMT_HIGH "\tor 3,3,3 # high priority\n" + +#endif diff --git a/include/asm-ppc64/mman.h b/include/asm-ppc64/mman.h new file mode 100644 index 000000000000..d4f93446a52c --- /dev/null +++ b/include/asm-ppc64/mman.h @@ -0,0 +1,52 @@ +#ifndef __PPC64_MMAN_H__ +#define __PPC64_MMAN_H__ + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#define PROT_READ 0x1 /* page can be read */ +#define PROT_WRITE 0x2 /* page can be written */ +#define PROT_EXEC 0x4 /* page can be executed */ +#define PROT_SEM 0x8 /* page may be used for atomic ops */ +#define PROT_NONE 0x0 /* page can not be accessed */ +#define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */ +#define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */ + +#define MAP_SHARED 0x01 /* Share changes */ +#define MAP_PRIVATE 0x02 /* Changes are private */ +#define MAP_TYPE 0x0f /* Mask for type of mapping */ +#define MAP_FIXED 0x10 /* Interpret addr exactly */ +#define MAP_ANONYMOUS 0x20 /* don't use a file */ +#define MAP_RENAME MAP_ANONYMOUS /* In SunOS terminology */ +#define MAP_NORESERVE 0x40 /* don't reserve swap pages */ +#define MAP_LOCKED 0x80 + +#define MAP_GROWSDOWN 0x0100 /* stack-like segment */ +#define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */ + +#define MS_ASYNC 1 /* sync memory asynchronously */ +#define MS_INVALIDATE 2 /* invalidate the caches */ +#define MS_SYNC 4 /* synchronous memory sync */ + +#define MCL_CURRENT 0x2000 /* lock all currently mapped pages */ +#define MCL_FUTURE 0x4000 /* lock all additions to address space */ + +#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ +#define MAP_NONBLOCK 0x10000 /* do not block on IO */ + +#define MADV_NORMAL 0x0 /* default page-in behavior */ +#define MADV_RANDOM 0x1 /* page-in minimum required */ +#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ +#define MADV_WILLNEED 0x3 /* pre-fault pages */ +#define MADV_DONTNEED 0x4 /* discard these pages */ + +/* compatibility flags */ +#define MAP_ANON MAP_ANONYMOUS +#define MAP_FILE 0 + +#endif /* __PPC64_MMAN_H__ */ diff --git a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h new file mode 100644 index 000000000000..188987e9d9d4 --- /dev/null +++ b/include/asm-ppc64/mmu.h @@ -0,0 +1,242 @@ +/* + * PowerPC memory management structures + * + * Dave Engebretsen & Mike Corrigan <{engebret|mikejc}@us.ibm.com> + * PPC64 rework. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _PPC64_MMU_H_ +#define _PPC64_MMU_H_ + +#include <linux/config.h> +#include <asm/page.h> +#include <linux/stringify.h> + +#ifndef __ASSEMBLY__ + +/* Time to allow for more things here */ +typedef unsigned long mm_context_id_t; +typedef struct { + mm_context_id_t id; +#ifdef CONFIG_HUGETLB_PAGE + pgd_t *huge_pgdir; + u16 htlb_segs; /* bitmask */ +#endif +} mm_context_t; + +#define STE_ESID_V 0x80 +#define STE_ESID_KS 0x20 +#define STE_ESID_KP 0x10 +#define STE_ESID_N 0x08 + +#define STE_VSID_SHIFT 12 + +struct stab_entry { + unsigned long esid_data; + unsigned long vsid_data; +}; + +/* Hardware Page Table Entry */ + +#define HPTES_PER_GROUP 8 + +typedef struct { + unsigned long avpn:57; /* vsid | api == avpn */ + unsigned long : 2; /* Software use */ + unsigned long bolted: 1; /* HPTE is "bolted" */ + unsigned long lock: 1; /* lock on pSeries SMP */ + unsigned long l: 1; /* Virtual page is large (L=1) or 4 KB (L=0) */ + unsigned long h: 1; /* Hash function identifier */ + unsigned long v: 1; /* Valid (v=1) or invalid (v=0) */ +} Hpte_dword0; + +typedef struct { + unsigned long pp0: 1; /* Page protection bit 0 */ + unsigned long ts: 1; /* Tag set bit */ + unsigned long rpn: 50; /* Real page number */ + unsigned long : 2; /* Reserved */ + unsigned long ac: 1; /* Address compare */ + unsigned long r: 1; /* Referenced */ + unsigned long c: 1; /* Changed */ + unsigned long w: 1; /* Write-thru cache mode */ + unsigned long i: 1; /* Cache inhibited */ + unsigned long m: 1; /* Memory coherence required */ + unsigned long g: 1; /* Guarded */ + unsigned long n: 1; /* No-execute */ + unsigned long pp: 2; /* Page protection bits 1:2 */ +} Hpte_dword1; + +typedef struct { + char padding[6]; /* padding */ + unsigned long : 6; /* padding */ + unsigned long flags: 10; /* HPTE flags */ +} Hpte_dword1_flags; + +typedef struct { + union { + unsigned long dword0; + Hpte_dword0 dw0; + } dw0; + + union { + unsigned long dword1; + Hpte_dword1 dw1; + Hpte_dword1_flags flags; + } dw1; +} HPTE; + +/* Values for PP (assumes Ks=0, Kp=1) */ +/* pp0 will always be 0 for linux */ +#define PP_RWXX 0 /* Supervisor read/write, User none */ +#define PP_RWRX 1 /* Supervisor read/write, User read */ +#define PP_RWRW 2 /* Supervisor read/write, User read/write */ +#define PP_RXRX 3 /* Supervisor read, User read */ + + +extern HPTE * htab_address; +extern unsigned long htab_hash_mask; + +static inline unsigned long hpt_hash(unsigned long vpn, int large) +{ + unsigned long vsid; + unsigned long page; + + if (large) { + vsid = vpn >> 4; + page = vpn & 0xf; + } else { + vsid = vpn >> 16; + page = vpn & 0xffff; + } + + return (vsid & 0x7fffffffffUL) ^ page; +} + +static inline void __tlbie(unsigned long va, int large) +{ + /* clear top 16 bits, non SLS segment */ + va &= ~(0xffffULL << 48); + + if (large) { + va &= HPAGE_MASK; + asm volatile("tlbie %0,1" : : "r"(va) : "memory"); + } else { + va &= PAGE_MASK; + asm volatile("tlbie %0,0" : : "r"(va) : "memory"); + } +} + +static inline void tlbie(unsigned long va, int large) +{ + asm volatile("ptesync": : :"memory"); + __tlbie(va, large); + asm volatile("eieio; tlbsync; ptesync": : :"memory"); +} + +static inline void __tlbiel(unsigned long va) +{ + /* clear top 16 bits, non SLS segment */ + va &= ~(0xffffULL << 48); + va &= PAGE_MASK; + + /* + * Thanks to Alan Modra we are now able to use machine specific + * assembly instructions (like tlbiel) by using the gas -many flag. + * However we have to support older toolchains so for the moment + * we hardwire it. + */ +#if 0 + asm volatile("tlbiel %0" : : "r"(va) : "memory"); +#else + asm volatile(".long 0x7c000224 | (%0 << 11)" : : "r"(va) : "memory"); +#endif +} + +static inline void tlbiel(unsigned long va) +{ + asm volatile("ptesync": : :"memory"); + __tlbiel(va); + asm volatile("ptesync": : :"memory"); +} + +/* + * Handle a fault by adding an HPTE. If the address can't be determined + * to be valid via Linux page tables, return 1. If handled return 0 + */ +extern int __hash_page(unsigned long ea, unsigned long access, + unsigned long vsid, pte_t *ptep, unsigned long trap, + int local); + +extern void htab_finish_init(void); + +#endif /* __ASSEMBLY__ */ + +/* + * Location of cpu0's segment table + */ +#define STAB0_PAGE 0x9 +#define STAB0_PHYS_ADDR (STAB0_PAGE<<PAGE_SHIFT) +#define STAB0_VIRT_ADDR (KERNELBASE+STAB0_PHYS_ADDR) + +#define SLB_NUM_BOLTED 3 +#define SLB_CACHE_ENTRIES 8 + +/* Bits in the SLB ESID word */ +#define SLB_ESID_V 0x0000000008000000 /* entry is valid */ + +/* Bits in the SLB VSID word */ +#define SLB_VSID_SHIFT 12 +#define SLB_VSID_KS 0x0000000000000800 +#define SLB_VSID_KP 0x0000000000000400 +#define SLB_VSID_N 0x0000000000000200 /* no-execute */ +#define SLB_VSID_L 0x0000000000000100 /* largepage (4M) */ +#define SLB_VSID_C 0x0000000000000080 /* class */ + +#define SLB_VSID_KERNEL (SLB_VSID_KP|SLB_VSID_C) +#define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS) + +#define VSID_MULTIPLIER ASM_CONST(200730139) /* 28-bit prime */ +#define VSID_BITS 36 +#define VSID_MODULUS ((1UL<<VSID_BITS)-1) + +#define CONTEXT_BITS 20 +#define USER_ESID_BITS 15 + +/* + * This macro generates asm code to compute the VSID scramble + * function. Used in slb_allocate() and do_stab_bolted. The function + * computed is: (protovsid*VSID_MULTIPLIER) % VSID_MODULUS + * + * rt = register continaing the proto-VSID and into which the + * VSID will be stored + * rx = scratch register (clobbered) + * + * - rt and rx must be different registers + * - The answer will end up in the low 36 bits of rt. The higher + * bits may contain other garbage, so you may need to mask the + * result. + */ +#define ASM_VSID_SCRAMBLE(rt, rx) \ + lis rx,VSID_MULTIPLIER@h; \ + ori rx,rx,VSID_MULTIPLIER@l; \ + mulld rt,rt,rx; /* rt = rt * MULTIPLIER */ \ + \ + srdi rx,rt,VSID_BITS; \ + clrldi rt,rt,(64-VSID_BITS); \ + add rt,rt,rx; /* add high and low bits */ \ + /* Now, r3 == VSID (mod 2^36-1), and lies between 0 and \ + * 2^36-1+2^28-1. That in particular means that if r3 >= \ + * 2^36-1, then r3+1 has the 2^36 bit set. So, if r3+1 has \ + * the bit clear, r3 already has the answer we want, if it \ + * doesn't, the answer is the low 36 bits of r3+1. So in all \ + * cases the answer is the low 36 bits of (r3 + ((r3+1) >> 36))*/\ + addi rx,rt,1; \ + srdi rx,rx,VSID_BITS; /* extract 2^36 bit */ \ + add rt,rt,rx + +#endif /* _PPC64_MMU_H_ */ diff --git a/include/asm-ppc64/mmu_context.h b/include/asm-ppc64/mmu_context.h new file mode 100644 index 000000000000..c2e8e0466383 --- /dev/null +++ b/include/asm-ppc64/mmu_context.h @@ -0,0 +1,169 @@ +#ifndef __PPC64_MMU_CONTEXT_H +#define __PPC64_MMU_CONTEXT_H + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <asm/mmu.h> +#include <asm/cputable.h> + +/* + * Copyright (C) 2001 PPC 64 Team, IBM Corp + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +/* + * Every architecture must define this function. It's the fastest + * way of searching a 140-bit bitmap where the first 100 bits are + * unlikely to be set. It's guaranteed that at least one of the 140 + * bits is cleared. + */ +static inline int sched_find_first_bit(unsigned long *b) +{ + if (unlikely(b[0])) + return __ffs(b[0]); + if (unlikely(b[1])) + return __ffs(b[1]) + 64; + return __ffs(b[2]) + 128; +} + +static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) +{ +} + +#define NO_CONTEXT 0 +#define MAX_CONTEXT (0x100000-1) + +extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm); +extern void destroy_context(struct mm_struct *mm); + +extern void switch_stab(struct task_struct *tsk, struct mm_struct *mm); +extern void switch_slb(struct task_struct *tsk, struct mm_struct *mm); + +/* + * switch_mm is the entry point called from the architecture independent + * code in kernel/sched.c + */ +static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, + struct task_struct *tsk) +{ + if (!cpu_isset(smp_processor_id(), next->cpu_vm_mask)) + cpu_set(smp_processor_id(), next->cpu_vm_mask); + + /* No need to flush userspace segments if the mm doesnt change */ + if (prev == next) + return; + +#ifdef CONFIG_ALTIVEC + if (cpu_has_feature(CPU_FTR_ALTIVEC)) + asm volatile ("dssall"); +#endif /* CONFIG_ALTIVEC */ + + if (cpu_has_feature(CPU_FTR_SLB)) + switch_slb(tsk, next); + else + switch_stab(tsk, next); +} + +#define deactivate_mm(tsk,mm) do { } while (0) + +/* + * After we have set current->mm to a new value, this activates + * the context for the new mm so we see the new mappings. + */ +static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next) +{ + unsigned long flags; + + local_irq_save(flags); + switch_mm(prev, next, current); + local_irq_restore(flags); +} + +/* VSID allocation + * =============== + * + * We first generate a 36-bit "proto-VSID". For kernel addresses this + * is equal to the ESID, for user addresses it is: + * (context << 15) | (esid & 0x7fff) + * + * The two forms are distinguishable because the top bit is 0 for user + * addresses, whereas the top two bits are 1 for kernel addresses. + * Proto-VSIDs with the top two bits equal to 0b10 are reserved for + * now. + * + * The proto-VSIDs are then scrambled into real VSIDs with the + * multiplicative hash: + * + * VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS + * where VSID_MULTIPLIER = 268435399 = 0xFFFFFC7 + * VSID_MODULUS = 2^36-1 = 0xFFFFFFFFF + * + * This scramble is only well defined for proto-VSIDs below + * 0xFFFFFFFFF, so both proto-VSID and actual VSID 0xFFFFFFFFF are + * reserved. VSID_MULTIPLIER is prime, so in particular it is + * co-prime to VSID_MODULUS, making this a 1:1 scrambling function. + * Because the modulus is 2^n-1 we can compute it efficiently without + * a divide or extra multiply (see below). + * + * This scheme has several advantages over older methods: + * + * - We have VSIDs allocated for every kernel address + * (i.e. everything above 0xC000000000000000), except the very top + * segment, which simplifies several things. + * + * - We allow for 15 significant bits of ESID and 20 bits of + * context for user addresses. i.e. 8T (43 bits) of address space for + * up to 1M contexts (although the page table structure and context + * allocation will need changes to take advantage of this). + * + * - The scramble function gives robust scattering in the hash + * table (at least based on some initial results). The previous + * method was more susceptible to pathological cases giving excessive + * hash collisions. + */ + +/* + * WARNING - If you change these you must make sure the asm + * implementations in slb_allocate(), do_stab_bolted and mmu.h + * (ASM_VSID_SCRAMBLE macro) are changed accordingly. + * + * You'll also need to change the precomputed VSID values in head.S + * which are used by the iSeries firmware. + */ + +static inline unsigned long vsid_scramble(unsigned long protovsid) +{ +#if 0 + /* The code below is equivalent to this function for arguments + * < 2^VSID_BITS, which is all this should ever be called + * with. However gcc is not clever enough to compute the + * modulus (2^n-1) without a second multiply. */ + return ((protovsid * VSID_MULTIPLIER) % VSID_MODULUS); +#else /* 1 */ + unsigned long x; + + x = protovsid * VSID_MULTIPLIER; + x = (x >> VSID_BITS) + (x & VSID_MODULUS); + return (x + ((x+1) >> VSID_BITS)) & VSID_MODULUS; +#endif /* 1 */ +} + +/* This is only valid for addresses >= KERNELBASE */ +static inline unsigned long get_kernel_vsid(unsigned long ea) +{ + return vsid_scramble(ea >> SID_SHIFT); +} + +/* This is only valid for user addresses (which are below 2^41) */ +static inline unsigned long get_vsid(unsigned long context, unsigned long ea) +{ + return vsid_scramble((context << USER_ESID_BITS) + | (ea >> SID_SHIFT)); +} + +#endif /* __PPC64_MMU_CONTEXT_H */ diff --git a/include/asm-ppc64/mmzone.h b/include/asm-ppc64/mmzone.h new file mode 100644 index 000000000000..0619a41a3c9d --- /dev/null +++ b/include/asm-ppc64/mmzone.h @@ -0,0 +1,94 @@ +/* + * Written by Kanoj Sarcar (kanoj@sgi.com) Aug 99 + * + * PowerPC64 port: + * Copyright (C) 2002 Anton Blanchard, IBM Corp. + */ +#ifndef _ASM_MMZONE_H_ +#define _ASM_MMZONE_H_ + +#include <linux/config.h> +#include <asm/smp.h> + +#ifdef CONFIG_DISCONTIGMEM + +extern struct pglist_data *node_data[]; + +/* + * Following are specific to this numa platform. + */ + +extern int numa_cpu_lookup_table[]; +extern char *numa_memory_lookup_table; +extern cpumask_t numa_cpumask_lookup_table[]; +extern int nr_cpus_in_node[]; + +/* 16MB regions */ +#define MEMORY_INCREMENT_SHIFT 24 +#define MEMORY_INCREMENT (1UL << MEMORY_INCREMENT_SHIFT) + +/* NUMA debugging, will not work on a DLPAR machine */ +#undef DEBUG_NUMA + +static inline int pa_to_nid(unsigned long pa) +{ + int nid; + + nid = numa_memory_lookup_table[pa >> MEMORY_INCREMENT_SHIFT]; + +#ifdef DEBUG_NUMA + /* the physical address passed in is not in the map for the system */ + if (nid == -1) { + printk("bad address: %lx\n", pa); + BUG(); + } +#endif + + return nid; +} + +#define pfn_to_nid(pfn) pa_to_nid((pfn) << PAGE_SHIFT) + +/* + * Return a pointer to the node data for node n. + */ +#define NODE_DATA(nid) (node_data[nid]) + +#define node_localnr(pfn, nid) ((pfn) - NODE_DATA(nid)->node_start_pfn) + +/* + * Following are macros that each numa implmentation must define. + */ + +/* + * Given a kernel address, find the home node of the underlying memory. + */ +#define kvaddr_to_nid(kaddr) pa_to_nid(__pa(kaddr)) + +#define node_mem_map(nid) (NODE_DATA(nid)->node_mem_map) +#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) +#define node_end_pfn(nid) (NODE_DATA(nid)->node_end_pfn) + +#define local_mapnr(kvaddr) \ + ( (__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr)) + +/* Written this way to avoid evaluating arguments twice */ +#define discontigmem_pfn_to_page(pfn) \ +({ \ + unsigned long __tmp = pfn; \ + (node_mem_map(pfn_to_nid(__tmp)) + \ + node_localnr(__tmp, pfn_to_nid(__tmp))); \ +}) + +#define discontigmem_page_to_pfn(p) \ +({ \ + struct page *__tmp = p; \ + (((__tmp) - page_zone(__tmp)->zone_mem_map) + \ + page_zone(__tmp)->zone_start_pfn); \ +}) + +/* XXX fix for discontiguous physical memory */ +#define discontigmem_pfn_valid(pfn) ((pfn) < num_physpages) + +#endif /* CONFIG_DISCONTIGMEM */ +#endif /* _ASM_MMZONE_H_ */ diff --git a/include/asm-ppc64/module.h b/include/asm-ppc64/module.h new file mode 100644 index 000000000000..0581607826e8 --- /dev/null +++ b/include/asm-ppc64/module.h @@ -0,0 +1,36 @@ +#ifndef _ASM_PPC64_MODULE_H +#define _ASM_PPC64_MODULE_H + +#include <linux/list.h> +#include <asm/bug.h> + +struct mod_arch_specific +{ + /* Index of stubs section within module. */ + unsigned int stubs_section; + + /* What section is the TOC? */ + unsigned int toc_section; + + /* List of BUG addresses, source line numbers and filenames */ + struct list_head bug_list; + struct bug_entry *bug_table; + unsigned int num_bugs; +}; + +extern struct bug_entry *module_find_bug(unsigned long bugaddr); + +#define Elf_Shdr Elf64_Shdr +#define Elf_Sym Elf64_Sym +#define Elf_Ehdr Elf64_Ehdr + +/* Make empty section for module_frob_arch_sections to expand. */ +#ifdef MODULE +asm(".section .stubs,\"ax\",@nobits; .align 3; .previous"); +#endif + +struct exception_table_entry; +void sort_ex_table(struct exception_table_entry *start, + struct exception_table_entry *finish); + +#endif /* _ASM_PPC64_MODULE_H */ diff --git a/include/asm-ppc64/msgbuf.h b/include/asm-ppc64/msgbuf.h new file mode 100644 index 000000000000..31c1cbf133cc --- /dev/null +++ b/include/asm-ppc64/msgbuf.h @@ -0,0 +1,27 @@ +#ifndef _PPC64_MSGBUF_H +#define _PPC64_MSGBUF_H + +/* + * The msqid64_ds structure for the PPC architecture. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +struct msqid64_ds { + struct ipc64_perm msg_perm; + __kernel_time_t msg_stime; /* last msgsnd time */ + __kernel_time_t msg_rtime; /* last msgrcv time */ + __kernel_time_t msg_ctime; /* last change time */ + unsigned long msg_cbytes; /* current number of bytes on queue */ + unsigned long msg_qnum; /* number of messages in queue */ + unsigned long msg_qbytes; /* max number of bytes on queue */ + __kernel_pid_t msg_lspid; /* pid of last msgsnd */ + __kernel_pid_t msg_lrpid; /* last receive pid */ + unsigned long __unused1; + unsigned long __unused2; +}; + +#endif /* _PPC64_MSGBUF_H */ diff --git a/include/asm-ppc64/naca.h b/include/asm-ppc64/naca.h new file mode 100644 index 000000000000..bfb7caa32eaf --- /dev/null +++ b/include/asm-ppc64/naca.h @@ -0,0 +1,31 @@ +#ifndef _NACA_H +#define _NACA_H + +/* + * c 2001 PPC 64 Team, IBM Corp + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <asm/types.h> + +#ifndef __ASSEMBLY__ + +struct naca_struct { + /* Kernel only data - undefined for user space */ + void *xItVpdAreas; /* VPD Data 0x00 */ + void *xRamDisk; /* iSeries ramdisk 0x08 */ + u64 xRamDiskSize; /* In pages 0x10 */ +}; + +extern struct naca_struct naca; + +#endif /* __ASSEMBLY__ */ + +#define NACA_PAGE 0x4 +#define NACA_PHYS_ADDR (NACA_PAGE<<PAGE_SHIFT) + +#endif /* _NACA_H */ diff --git a/include/asm-ppc64/namei.h b/include/asm-ppc64/namei.h new file mode 100644 index 000000000000..a1412a2d102a --- /dev/null +++ b/include/asm-ppc64/namei.h @@ -0,0 +1,23 @@ +/* + * linux/include/asm-ppc/namei.h + * Adapted from linux/include/asm-alpha/namei.h + * + * Included from linux/fs/namei.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef __PPC64_NAMEI_H +#define __PPC64_NAMEI_H + +/* This dummy routine maybe changed to something useful + * for /usr/gnemul/ emulation stuff. + * Look at asm-sparc/namei.h for details. + */ + +#define __emul_prefix() NULL + +#endif /* __PPC64_NAMEI_H */ diff --git a/include/asm-ppc64/numnodes.h b/include/asm-ppc64/numnodes.h new file mode 100644 index 000000000000..75ae0b906708 --- /dev/null +++ b/include/asm-ppc64/numnodes.h @@ -0,0 +1,7 @@ +#ifndef _ASM_MAX_NUMNODES_H +#define _ASM_MAX_NUMNODES_H + +/* Max 16 Nodes */ +#define NODES_SHIFT 4 + +#endif /* _ASM_MAX_NUMNODES_H */ diff --git a/include/asm-ppc64/nvram.h b/include/asm-ppc64/nvram.h new file mode 100644 index 000000000000..4e6dd370d936 --- /dev/null +++ b/include/asm-ppc64/nvram.h @@ -0,0 +1,115 @@ +/* + * PreP compliant NVRAM access + * This needs to be updated for PPC64 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _PPC64_NVRAM_H +#define _PPC64_NVRAM_H + +#define NVRW_CNT 0x20 +#define NVRAM_HEADER_LEN 16 /* sizeof(struct nvram_header) */ +#define NVRAM_BLOCK_LEN 16 +#define NVRAM_MAX_REQ (2080/NVRAM_BLOCK_LEN) +#define NVRAM_MIN_REQ (1056/NVRAM_BLOCK_LEN) + +#define NVRAM_AS0 0x74 +#define NVRAM_AS1 0x75 +#define NVRAM_DATA 0x77 + + +/* RTC Offsets */ + +#define MOTO_RTC_SECONDS 0x1FF9 +#define MOTO_RTC_MINUTES 0x1FFA +#define MOTO_RTC_HOURS 0x1FFB +#define MOTO_RTC_DAY_OF_WEEK 0x1FFC +#define MOTO_RTC_DAY_OF_MONTH 0x1FFD +#define MOTO_RTC_MONTH 0x1FFE +#define MOTO_RTC_YEAR 0x1FFF +#define MOTO_RTC_CONTROLA 0x1FF8 +#define MOTO_RTC_CONTROLB 0x1FF9 + +#define NVRAM_SIG_SP 0x02 /* support processor */ +#define NVRAM_SIG_OF 0x50 /* open firmware config */ +#define NVRAM_SIG_FW 0x51 /* general firmware */ +#define NVRAM_SIG_HW 0x52 /* hardware (VPD) */ +#define NVRAM_SIG_FLIP 0x5a /* Apple flip/flop header */ +#define NVRAM_SIG_APPL 0x5f /* Apple "system" (???) */ +#define NVRAM_SIG_SYS 0x70 /* system env vars */ +#define NVRAM_SIG_CFG 0x71 /* config data */ +#define NVRAM_SIG_ELOG 0x72 /* error log */ +#define NVRAM_SIG_VEND 0x7e /* vendor defined */ +#define NVRAM_SIG_FREE 0x7f /* Free space */ +#define NVRAM_SIG_OS 0xa0 /* OS defined */ +#define NVRAM_SIG_PANIC 0xa1 /* Apple OSX "panic" */ + +/* If change this size, then change the size of NVNAME_LEN */ +struct nvram_header { + unsigned char signature; + unsigned char checksum; + unsigned short length; + char name[12]; +}; + +struct nvram_partition { + struct list_head partition; + struct nvram_header header; + unsigned int index; +}; + + +extern int nvram_write_error_log(char * buff, int length, unsigned int err_type); +extern int nvram_read_error_log(char * buff, int length, unsigned int * err_type); +extern int nvram_clear_error_log(void); +extern struct nvram_partition *nvram_find_partition(int sig, const char *name); + +extern int pSeries_nvram_init(void); +extern int pmac_nvram_init(void); + +/* PowerMac specific nvram stuffs */ + +enum { + pmac_nvram_OF, /* Open Firmware partition */ + pmac_nvram_XPRAM, /* MacOS XPRAM partition */ + pmac_nvram_NR /* MacOS Name Registry partition */ +}; + +/* Return partition offset in nvram */ +extern int pmac_get_partition(int partition); + +/* Direct access to XPRAM on PowerMacs */ +extern u8 pmac_xpram_read(int xpaddr); +extern void pmac_xpram_write(int xpaddr, u8 data); + +/* Synchronize NVRAM */ +extern int nvram_sync(void); + +/* Some offsets in XPRAM */ +#define PMAC_XPRAM_MACHINE_LOC 0xe4 +#define PMAC_XPRAM_SOUND_VOLUME 0x08 + +/* Machine location structure in PowerMac XPRAM */ +struct pmac_machine_location { + unsigned int latitude; /* 2+30 bit Fractional number */ + unsigned int longitude; /* 2+30 bit Fractional number */ + unsigned int delta; /* mix of GMT delta and DLS */ +}; + +/* + * /dev/nvram ioctls + * + * Note that PMAC_NVRAM_GET_OFFSET is still supported, but is + * definitely obsolete. Do not use it if you can avoid it + */ + +#define OBSOLETE_PMAC_NVRAM_GET_OFFSET \ + _IOWR('p', 0x40, int) + +#define IOC_NVRAM_GET_OFFSET _IOWR('p', 0x42, int) /* Get NVRAM partition offset */ + +#endif /* _PPC64_NVRAM_H */ diff --git a/include/asm-ppc64/of_device.h b/include/asm-ppc64/of_device.h new file mode 100644 index 000000000000..7bc136e22590 --- /dev/null +++ b/include/asm-ppc64/of_device.h @@ -0,0 +1,2 @@ +#include <asm-ppc/of_device.h> + diff --git a/include/asm-ppc64/pSeries_reconfig.h b/include/asm-ppc64/pSeries_reconfig.h new file mode 100644 index 000000000000..c0db1ea7f7d1 --- /dev/null +++ b/include/asm-ppc64/pSeries_reconfig.h @@ -0,0 +1,25 @@ +#ifndef _PPC64_PSERIES_RECONFIG_H +#define _PPC64_PSERIES_RECONFIG_H + +#include <linux/notifier.h> + +/* + * Use this API if your code needs to know about OF device nodes being + * added or removed on pSeries systems. + */ + +#define PSERIES_RECONFIG_ADD 0x0001 +#define PSERIES_RECONFIG_REMOVE 0x0002 + +#ifdef CONFIG_PPC_PSERIES +extern int pSeries_reconfig_notifier_register(struct notifier_block *); +extern void pSeries_reconfig_notifier_unregister(struct notifier_block *); +#else /* !CONFIG_PPC_PSERIES */ +static inline int pSeries_reconfig_notifier_register(struct notifier_block *nb) +{ + return 0; +} +static inline void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) { } +#endif /* CONFIG_PPC_PSERIES */ + +#endif /* _PPC64_PSERIES_RECONFIG_H */ diff --git a/include/asm-ppc64/paca.h b/include/asm-ppc64/paca.h new file mode 100644 index 000000000000..1a0223b5f3b8 --- /dev/null +++ b/include/asm-ppc64/paca.h @@ -0,0 +1,119 @@ +#ifndef _PPC64_PACA_H +#define _PPC64_PACA_H + +/* + * include/asm-ppc64/paca.h + * + * This control block defines the PACA which defines the processor + * specific data for each logical processor on the system. + * There are some pointers defined that are utilized by PLIC. + * + * C 2001 PPC 64 Team, IBM Corp + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/config.h> +#include <asm/types.h> +#include <asm/lppaca.h> +#include <asm/iSeries/ItLpRegSave.h> +#include <asm/mmu.h> + +register struct paca_struct *local_paca asm("r13"); +#define get_paca() local_paca + +struct task_struct; +struct ItLpQueue; + +/* + * Defines the layout of the paca. + * + * This structure is not directly accessed by firmware or the service + * processor except for the first two pointers that point to the + * lppaca area and the ItLpRegSave area for this CPU. Both the + * lppaca and ItLpRegSave objects are currently contained within the + * PACA but they do not need to be. + */ +struct paca_struct { + /* + * Because hw_cpu_id, unlike other paca fields, is accessed + * routinely from other CPUs (from the IRQ code), we stick to + * read-only (after boot) fields in the first cacheline to + * avoid cacheline bouncing. + */ + + /* + * MAGIC: These first two pointers can't be moved - they're + * accessed by the firmware + */ + struct lppaca *lppaca_ptr; /* Pointer to LpPaca for PLIC */ + struct ItLpRegSave *reg_save_ptr; /* Pointer to LpRegSave for PLIC */ + + /* + * MAGIC: the spinlock functions in arch/ppc64/lib/locks.c + * load lock_token and paca_index with a single lwz + * instruction. They must travel together and be properly + * aligned. + */ + u16 lock_token; /* Constant 0x8000, used in locks */ + u16 paca_index; /* Logical processor number */ + + u32 default_decr; /* Default decrementer value */ + struct ItLpQueue *lpqueue_ptr; /* LpQueue handled by this CPU */ + u64 kernel_toc; /* Kernel TOC address */ + u64 stab_real; /* Absolute address of segment table */ + u64 stab_addr; /* Virtual address of segment table */ + void *emergency_sp; /* pointer to emergency stack */ + s16 hw_cpu_id; /* Physical processor number */ + u8 cpu_start; /* At startup, processor spins until */ + /* this becomes non-zero. */ + + /* + * Now, starting in cacheline 2, the exception save areas + */ + u64 exgen[8] __attribute__((aligned(0x80))); /* used for most interrupts/exceptions */ + u64 exmc[8]; /* used for machine checks */ + u64 exslb[8]; /* used for SLB/segment table misses + * on the linear mapping */ + mm_context_t context; + u16 slb_cache[SLB_CACHE_ENTRIES]; + u16 slb_cache_ptr; + + /* + * then miscellaneous read-write fields + */ + struct task_struct *__current; /* Pointer to current */ + u64 kstack; /* Saved Kernel stack addr */ + u64 stab_rr; /* stab/slb round-robin counter */ + u64 next_jiffy_update_tb; /* TB value for next jiffy update */ + u64 saved_r1; /* r1 save for RTAS calls */ + u64 saved_msr; /* MSR saved here by enter_rtas */ + u32 lpevent_count; /* lpevents processed */ + u8 proc_enabled; /* irq soft-enable flag */ + + /* not yet used */ + u64 exdsi[8]; /* used for linear mapping hash table misses */ + + /* + * iSeries structure which the hypervisor knows about - + * this structure should not cross a page boundary. + * The vpa_init/register_vpa call is now known to fail if the + * lppaca structure crosses a page boundary. + * The lppaca is also used on POWER5 pSeries boxes. + * The lppaca is 640 bytes long, and cannot readily change + * since the hypervisor knows its layout, so a 1kB + * alignment will suffice to ensure that it doesn't + * cross a page boundary. + */ + struct lppaca lppaca __attribute__((__aligned__(0x400))); +#ifdef CONFIG_PPC_ISERIES + struct ItLpRegSave reg_save; +#endif +}; + +extern struct paca_struct paca[]; + +#endif /* _PPC64_PACA_H */ diff --git a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h new file mode 100644 index 000000000000..20e0f19324e8 --- /dev/null +++ b/include/asm-ppc64/page.h @@ -0,0 +1,261 @@ +#ifndef _PPC64_PAGE_H +#define _PPC64_PAGE_H + +/* + * Copyright (C) 2001 PPC64 Team, IBM Corp + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/config.h> + +#ifdef __ASSEMBLY__ + #define ASM_CONST(x) x +#else + #define __ASM_CONST(x) x##UL + #define ASM_CONST(x) __ASM_CONST(x) +#endif + +/* PAGE_SHIFT determines the page size */ +#define PAGE_SHIFT 12 +#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) +#define PAGE_OFFSET_MASK (PAGE_SIZE-1) + +#define SID_SHIFT 28 +#define SID_MASK 0xfffffffffUL +#define ESID_MASK 0xfffffffff0000000UL +#define GET_ESID(x) (((x) >> SID_SHIFT) & SID_MASK) + +#define HPAGE_SHIFT 24 +#define HPAGE_SIZE ((1UL) << HPAGE_SHIFT) +#define HPAGE_MASK (~(HPAGE_SIZE - 1)) + +#ifdef CONFIG_HUGETLB_PAGE + +#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) + +/* For 64-bit processes the hugepage range is 1T-1.5T */ +#define TASK_HPAGE_BASE ASM_CONST(0x0000010000000000) +#define TASK_HPAGE_END ASM_CONST(0x0000018000000000) + +#define LOW_ESID_MASK(addr, len) (((1U << (GET_ESID(addr+len-1)+1)) \ + - (1U << GET_ESID(addr))) & 0xffff) + +#define ARCH_HAS_HUGEPAGE_ONLY_RANGE +#define ARCH_HAS_PREPARE_HUGEPAGE_RANGE + +#define touches_hugepage_low_range(mm, addr, len) \ + (LOW_ESID_MASK((addr), (len)) & mm->context.htlb_segs) +#define touches_hugepage_high_range(addr, len) \ + (((addr) > (TASK_HPAGE_BASE-(len))) && ((addr) < TASK_HPAGE_END)) + +#define __within_hugepage_low_range(addr, len, segmask) \ + ((LOW_ESID_MASK((addr), (len)) | (segmask)) == (segmask)) +#define within_hugepage_low_range(addr, len) \ + __within_hugepage_low_range((addr), (len), \ + current->mm->context.htlb_segs) +#define within_hugepage_high_range(addr, len) (((addr) >= TASK_HPAGE_BASE) \ + && ((addr)+(len) <= TASK_HPAGE_END) && ((addr)+(len) >= (addr))) + +#define is_hugepage_only_range(mm, addr, len) \ + (touches_hugepage_high_range((addr), (len)) || \ + touches_hugepage_low_range((mm), (addr), (len))) +#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA + +#define in_hugepage_area(context, addr) \ + (cpu_has_feature(CPU_FTR_16M_PAGE) && \ + ( (((addr) >= TASK_HPAGE_BASE) && ((addr) < TASK_HPAGE_END)) || \ + ( ((addr) < 0x100000000L) && \ + ((1 << GET_ESID(addr)) & (context).htlb_segs) ) ) ) + +#else /* !CONFIG_HUGETLB_PAGE */ + +#define in_hugepage_area(mm, addr) 0 + +#endif /* !CONFIG_HUGETLB_PAGE */ + +/* align addr on a size boundary - adjust address up/down if needed */ +#define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1))) +#define _ALIGN_DOWN(addr,size) ((addr)&(~((size)-1))) + +/* align addr on a size boundary - adjust address up if needed */ +#define _ALIGN(addr,size) _ALIGN_UP(addr,size) + +/* to align the pointer to the (next) double word boundary */ +#define DOUBLEWORD_ALIGN(addr) _ALIGN(addr,sizeof(unsigned long)) + +/* to align the pointer to the (next) page boundary */ +#define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE) + +#ifdef __KERNEL__ +#ifndef __ASSEMBLY__ +#include <asm/cache.h> + +#undef STRICT_MM_TYPECHECKS + +#define REGION_SIZE 4UL +#define REGION_SHIFT 60UL +#define REGION_MASK (((1UL<<REGION_SIZE)-1UL)<<REGION_SHIFT) +#define REGION_STRIDE (1UL << REGION_SHIFT) + +static __inline__ void clear_page(void *addr) +{ + unsigned long lines, line_size; + + line_size = ppc64_caches.dline_size; + lines = ppc64_caches.dlines_per_page; + + __asm__ __volatile__( + "mtctr %1 # clear_page\n\ +1: dcbz 0,%0\n\ + add %0,%0,%3\n\ + bdnz+ 1b" + : "=r" (addr) + : "r" (lines), "0" (addr), "r" (line_size) + : "ctr", "memory"); +} + +extern void copy_page(void *to, void *from); +struct page; +extern void clear_user_page(void *page, unsigned long vaddr, struct page *pg); +extern void copy_user_page(void *to, void *from, unsigned long vaddr, struct page *p); + +#ifdef STRICT_MM_TYPECHECKS +/* + * These are used to make use of C type-checking. + * Entries in the pte table are 64b, while entries in the pgd & pmd are 32b. + */ +typedef struct { unsigned long pte; } pte_t; +typedef struct { unsigned int pmd; } pmd_t; +typedef struct { unsigned int pgd; } pgd_t; +typedef struct { unsigned long pgprot; } pgprot_t; + +#define pte_val(x) ((x).pte) +#define pmd_val(x) ((x).pmd) +#define pgd_val(x) ((x).pgd) +#define pgprot_val(x) ((x).pgprot) + +#define __pte(x) ((pte_t) { (x) } ) +#define __pmd(x) ((pmd_t) { (x) } ) +#define __pgd(x) ((pgd_t) { (x) } ) +#define __pgprot(x) ((pgprot_t) { (x) } ) + +#else +/* + * .. while these make it easier on the compiler + */ +typedef unsigned long pte_t; +typedef unsigned int pmd_t; +typedef unsigned int pgd_t; +typedef unsigned long pgprot_t; + +#define pte_val(x) (x) +#define pmd_val(x) (x) +#define pgd_val(x) (x) +#define pgprot_val(x) (x) + +#define __pte(x) (x) +#define __pmd(x) (x) +#define __pgd(x) (x) +#define __pgprot(x) (x) + +#endif + +/* Pure 2^n version of get_order */ +static inline int get_order(unsigned long size) +{ + int order; + + size = (size-1) >> (PAGE_SHIFT-1); + order = -1; + do { + size >>= 1; + order++; + } while (size); + return order; +} + +#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) + +extern int page_is_ram(unsigned long pfn); + +extern u64 ppc64_pft_size; /* Log 2 of page table size */ + +/* We do define AT_SYSINFO_EHDR but don't use the gate mecanism */ +#define __HAVE_ARCH_GATE_AREA 1 + +#endif /* __ASSEMBLY__ */ + +#ifdef MODULE +#define __page_aligned __attribute__((__aligned__(PAGE_SIZE))) +#else +#define __page_aligned \ + __attribute__((__aligned__(PAGE_SIZE), \ + __section__(".data.page_aligned"))) +#endif + + +/* This must match the -Ttext linker address */ +/* Note: tophys & tovirt make assumptions about how */ +/* KERNELBASE is defined for performance reasons. */ +/* When KERNELBASE moves, those macros may have */ +/* to change! */ +#define PAGE_OFFSET ASM_CONST(0xC000000000000000) +#define KERNELBASE PAGE_OFFSET +#define VMALLOCBASE ASM_CONST(0xD000000000000000) +#define IOREGIONBASE ASM_CONST(0xE000000000000000) + +#define IO_REGION_ID (IOREGIONBASE>>REGION_SHIFT) +#define VMALLOC_REGION_ID (VMALLOCBASE>>REGION_SHIFT) +#define KERNEL_REGION_ID (KERNELBASE>>REGION_SHIFT) +#define USER_REGION_ID (0UL) +#define REGION_ID(X) (((unsigned long)(X))>>REGION_SHIFT) + +#define __bpn_to_ba(x) ((((unsigned long)(x))<<PAGE_SHIFT) + KERNELBASE) +#define __ba_to_bpn(x) ((((unsigned long)(x)) & ~REGION_MASK) >> PAGE_SHIFT) + +#define __va(x) ((void *)((unsigned long)(x) + KERNELBASE)) + +#ifdef CONFIG_DISCONTIGMEM +#define page_to_pfn(page) discontigmem_page_to_pfn(page) +#define pfn_to_page(pfn) discontigmem_pfn_to_page(pfn) +#define pfn_valid(pfn) discontigmem_pfn_valid(pfn) +#else +#define pfn_to_page(pfn) (mem_map + (pfn)) +#define page_to_pfn(page) ((unsigned long)((page) - mem_map)) +#define pfn_valid(pfn) ((pfn) < max_mapnr) +#endif + +#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) +#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) + +#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) + +/* + * Unfortunately the PLT is in the BSS in the PPC32 ELF ABI, + * and needs to be executable. This means the whole heap ends + * up being executable. + */ +#define VM_DATA_DEFAULT_FLAGS32 (VM_READ | VM_WRITE | VM_EXEC | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + +#define VM_DATA_DEFAULT_FLAGS64 (VM_READ | VM_WRITE | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + +#define VM_DATA_DEFAULT_FLAGS \ + (test_thread_flag(TIF_32BIT) ? \ + VM_DATA_DEFAULT_FLAGS32 : VM_DATA_DEFAULT_FLAGS64) + +/* + * This is the default if a program doesn't have a PT_GNU_STACK + * program header entry. + */ +#define VM_STACK_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + +#endif /* __KERNEL__ */ +#endif /* _PPC64_PAGE_H */ diff --git a/include/asm-ppc64/param.h b/include/asm-ppc64/param.h new file mode 100644 index 000000000000..1fad38dcf707 --- /dev/null +++ b/include/asm-ppc64/param.h @@ -0,0 +1,29 @@ +#ifndef _ASM_PPC64_PARAM_H +#define _ASM_PPC64_PARAM_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifdef __KERNEL__ +# define HZ 1000 /* Internal kernel timer frequency */ +# define USER_HZ 100 /* .. some user interfaces are in "ticks" */ +# define CLOCKS_PER_SEC (USER_HZ) /* like times() */ +#endif + +#ifndef HZ +#define HZ 100 +#endif + +#define EXEC_PAGESIZE 4096 + +#ifndef NOGROUP +#define NOGROUP (-1) +#endif + +#define MAXHOSTNAMELEN 64 /* max length of hostname */ + +#endif /* _ASM_PPC64_PARAM_H */ diff --git a/include/asm-ppc64/parport.h b/include/asm-ppc64/parport.h new file mode 100644 index 000000000000..2f8874c581cc --- /dev/null +++ b/include/asm-ppc64/parport.h @@ -0,0 +1,18 @@ +/* + * parport.h: platform-specific PC-style parport initialisation + * + * Copyright (C) 1999, 2000 Tim Waugh <tim@cyberelk.demon.co.uk> + * + * This file should only be included by drivers/parport/parport_pc.c. + */ + +#ifndef _ASM_PPC64_PARPORT_H +#define _ASM_PPC64_PARPORT_H + +static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma); +static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma) +{ + return parport_pc_find_isa_ports (autoirq, autodma); +} + +#endif /* !(_ASM_PPC_PARPORT_H) */ diff --git a/include/asm-ppc64/pci-bridge.h b/include/asm-ppc64/pci-bridge.h new file mode 100644 index 000000000000..c4f9023ea5ed --- /dev/null +++ b/include/asm-ppc64/pci-bridge.h @@ -0,0 +1,90 @@ +#ifdef __KERNEL__ +#ifndef _ASM_PCI_BRIDGE_H +#define _ASM_PCI_BRIDGE_H + +#include <linux/pci.h> + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +/* + * Structure of a PCI controller (host bridge) + */ +struct pci_controller { + struct pci_bus *bus; + char is_dynamic; + void *arch_data; + struct list_head list_node; + + int first_busno; + int last_busno; + + void __iomem *io_base_virt; + unsigned long io_base_phys; + + /* Some machines have a non 1:1 mapping of + * the PCI memory space in the CPU bus space + */ + unsigned long pci_mem_offset; + unsigned long pci_io_size; + + struct pci_ops *ops; + volatile unsigned int __iomem *cfg_addr; + volatile unsigned char __iomem *cfg_data; + + /* Currently, we limit ourselves to 1 IO range and 3 mem + * ranges since the common pci_bus structure can't handle more + */ + struct resource io_resource; + struct resource mem_resources[3]; + int global_number; + int local_number; + unsigned long buid; + unsigned long dma_window_base_cur; + unsigned long dma_window_size; +}; + +struct device_node *fetch_dev_dn(struct pci_dev *dev); + +/* Get a device_node from a pci_dev. This code must be fast except in the case + * where the sysdata is incorrect and needs to be fixed up (hopefully just once) + */ +static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev) +{ + struct device_node *dn = dev->sysdata; + + if (dn->devfn == dev->devfn && dn->busno == dev->bus->number) + return dn; /* fast path. sysdata is good */ + else + return fetch_dev_dn(dev); +} + +static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus) +{ + if (bus->self) + return pci_device_to_OF_node(bus->self); + else + return bus->sysdata; /* Must be root bus (PHB) */ +} + +extern void pci_process_bridge_OF_ranges(struct pci_controller *hose, + struct device_node *dev); + +extern int pcibios_remove_root_bus(struct pci_controller *phb); + +extern void phbs_remap_io(void); + +static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus) +{ + struct device_node *busdn = bus->sysdata; + + BUG_ON(busdn == NULL); + return busdn->phb; +} + +#endif +#endif /* __KERNEL__ */ diff --git a/include/asm-ppc64/pci.h b/include/asm-ppc64/pci.h new file mode 100644 index 000000000000..6cd593f660a0 --- /dev/null +++ b/include/asm-ppc64/pci.h @@ -0,0 +1,142 @@ +#ifndef __PPC64_PCI_H +#define __PPC64_PCI_H +#ifdef __KERNEL__ + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/types.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/dma-mapping.h> + +#include <asm/machdep.h> +#include <asm/scatterlist.h> +#include <asm/io.h> +#include <asm/prom.h> + +#include <asm-generic/pci-dma-compat.h> + +#define PCIBIOS_MIN_IO 0x1000 +#define PCIBIOS_MIN_MEM 0x10000000 + +struct pci_dev; + +#ifdef CONFIG_PPC_ISERIES +#define pcibios_scan_all_fns(a, b) 0 +#else +extern int pcibios_scan_all_fns(struct pci_bus *bus, int devfn); +#endif + +static inline void pcibios_set_master(struct pci_dev *dev) +{ + /* No special bus mastering setup handling */ +} + +static inline void pcibios_penalize_isa_irq(int irq) +{ + /* We don't do dynamic PCI IRQ allocation */ +} + +#define HAVE_ARCH_PCI_GET_LEGACY_IDE_IRQ +static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) +{ + if (ppc_md.pci_get_legacy_ide_irq) + return ppc_md.pci_get_legacy_ide_irq(dev, channel); + return channel ? 15 : 14; +} + +#define HAVE_ARCH_PCI_MWI 1 +static inline int pcibios_prep_mwi(struct pci_dev *dev) +{ + /* + * We would like to avoid touching the cacheline size or MWI bit + * but we cant do that with the current pcibios_prep_mwi + * interface. pSeries firmware sets the cacheline size (which is not + * the cpu cacheline size in all cases) and hardware treats MWI + * the same as memory write. So we dont touch the cacheline size + * here and allow the generic code to set the MWI bit. + */ + return 0; +} + +extern unsigned int pcibios_assign_all_busses(void); + +extern struct dma_mapping_ops pci_dma_ops; + +/* For DAC DMA, we currently don't support it by default, but + * we let the platform override this + */ +static inline int pci_dac_dma_supported(struct pci_dev *hwdev,u64 mask) +{ + if (pci_dma_ops.dac_dma_supported) + return pci_dma_ops.dac_dma_supported(&hwdev->dev, mask); + return 0; +} + +extern int pci_domain_nr(struct pci_bus *bus); + +/* Decide whether to display the domain number in /proc */ +extern int pci_proc_domain(struct pci_bus *bus); + +struct vm_area_struct; +/* Map a range of PCI memory or I/O space for a device into user space */ +int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, + enum pci_mmap_state mmap_state, int write_combine); + +/* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */ +#define HAVE_PCI_MMAP 1 + +/* pci_unmap_{single,page} is not a nop, thus... */ +#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ + dma_addr_t ADDR_NAME; +#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \ + __u32 LEN_NAME; +#define pci_unmap_addr(PTR, ADDR_NAME) \ + ((PTR)->ADDR_NAME) +#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \ + (((PTR)->ADDR_NAME) = (VAL)) +#define pci_unmap_len(PTR, LEN_NAME) \ + ((PTR)->LEN_NAME) +#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ + (((PTR)->LEN_NAME) = (VAL)) + +/* The PCI address space does equal the physical memory + * address space. The networking and block device layers use + * this boolean for bounce buffer decisions. + */ +#define PCI_DMA_BUS_IS_PHYS (0) + +extern void +pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, + struct resource *res); + +extern int +unmap_bus_range(struct pci_bus *bus); + +extern int +remap_bus_range(struct pci_bus *bus); + +extern void +pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus); + +extern struct pci_controller *init_phb_dynamic(struct device_node *dn); + +extern int pci_read_irq_line(struct pci_dev *dev); + +extern void pcibios_add_platform_entries(struct pci_dev *dev); + +struct file; +extern pgprot_t pci_phys_mem_access_prot(struct file *file, + unsigned long offset, + unsigned long size, + pgprot_t prot); + + +#endif /* __KERNEL__ */ + +#endif /* __PPC64_PCI_H */ diff --git a/include/asm-ppc64/percpu.h b/include/asm-ppc64/percpu.h new file mode 100644 index 000000000000..60a659a4ce1f --- /dev/null +++ b/include/asm-ppc64/percpu.h @@ -0,0 +1,6 @@ +#ifndef __ARCH_PPC64_PERCPU__ +#define __ARCH_PPC64_PERCPU__ + +#include <asm-generic/percpu.h> + +#endif /* __ARCH_PPC64_PERCPU__ */ diff --git a/include/asm-ppc64/pgalloc.h b/include/asm-ppc64/pgalloc.h new file mode 100644 index 000000000000..16232d740173 --- /dev/null +++ b/include/asm-ppc64/pgalloc.h @@ -0,0 +1,91 @@ +#ifndef _PPC64_PGALLOC_H +#define _PPC64_PGALLOC_H + +#include <linux/mm.h> +#include <linux/slab.h> +#include <linux/cpumask.h> +#include <linux/percpu.h> + +extern kmem_cache_t *zero_cache; + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +static inline pgd_t * +pgd_alloc(struct mm_struct *mm) +{ + return kmem_cache_alloc(zero_cache, GFP_KERNEL); +} + +static inline void +pgd_free(pgd_t *pgd) +{ + kmem_cache_free(zero_cache, pgd); +} + +#define pgd_populate(MM, PGD, PMD) pgd_set(PGD, PMD) + +static inline pmd_t * +pmd_alloc_one(struct mm_struct *mm, unsigned long addr) +{ + return kmem_cache_alloc(zero_cache, GFP_KERNEL|__GFP_REPEAT); +} + +static inline void +pmd_free(pmd_t *pmd) +{ + kmem_cache_free(zero_cache, pmd); +} + +#define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, pte) +#define pmd_populate(mm, pmd, pte_page) \ + pmd_populate_kernel(mm, pmd, page_address(pte_page)) + +static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) +{ + return kmem_cache_alloc(zero_cache, GFP_KERNEL|__GFP_REPEAT); +} + +static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) +{ + pte_t *pte = kmem_cache_alloc(zero_cache, GFP_KERNEL|__GFP_REPEAT); + if (pte) + return virt_to_page(pte); + return NULL; +} + +static inline void pte_free_kernel(pte_t *pte) +{ + kmem_cache_free(zero_cache, pte); +} + +static inline void pte_free(struct page *ptepage) +{ + kmem_cache_free(zero_cache, page_address(ptepage)); +} + +struct pte_freelist_batch +{ + struct rcu_head rcu; + unsigned int index; + struct page * pages[0]; +}; + +#define PTE_FREELIST_SIZE ((PAGE_SIZE - sizeof(struct pte_freelist_batch)) / \ + sizeof(struct page *)) + +extern void pte_free_now(struct page *ptepage); +extern void pte_free_submit(struct pte_freelist_batch *batch); + +DECLARE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur); + +void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage); +#define __pmd_free_tlb(tlb, pmd) __pte_free_tlb(tlb, virt_to_page(pmd)) + +#define check_pgt_cache() do { } while (0) + +#endif /* _PPC64_PGALLOC_H */ diff --git a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h new file mode 100644 index 000000000000..4c4824653e80 --- /dev/null +++ b/include/asm-ppc64/pgtable.h @@ -0,0 +1,602 @@ +#ifndef _PPC64_PGTABLE_H +#define _PPC64_PGTABLE_H + +#include <asm-generic/4level-fixup.h> + +/* + * This file contains the functions and defines necessary to modify and use + * the ppc64 hashed page table. + */ + +#ifndef __ASSEMBLY__ +#include <linux/config.h> +#include <linux/stddef.h> +#include <asm/processor.h> /* For TASK_SIZE */ +#include <asm/mmu.h> +#include <asm/page.h> +#include <asm/tlbflush.h> +#endif /* __ASSEMBLY__ */ + +/* PMD_SHIFT determines what a second-level page table entry can map */ +#define PMD_SHIFT (PAGE_SHIFT + PAGE_SHIFT - 3) +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE-1)) + +/* PGDIR_SHIFT determines what a third-level page table entry can map */ +#define PGDIR_SHIFT (PAGE_SHIFT + (PAGE_SHIFT - 3) + (PAGE_SHIFT - 2)) +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) + +/* + * Entries per page directory level. The PTE level must use a 64b record + * for each page table entry. The PMD and PGD level use a 32b record for + * each entry by assuming that each entry is page aligned. + */ +#define PTE_INDEX_SIZE 9 +#define PMD_INDEX_SIZE 10 +#define PGD_INDEX_SIZE 10 + +#define PTRS_PER_PTE (1 << PTE_INDEX_SIZE) +#define PTRS_PER_PMD (1 << PMD_INDEX_SIZE) +#define PTRS_PER_PGD (1 << PGD_INDEX_SIZE) + +#define USER_PTRS_PER_PGD (1024) +#define FIRST_USER_PGD_NR 0 + +#define EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \ + PGD_INDEX_SIZE + PAGE_SHIFT) + +/* + * Size of EA range mapped by our pagetables. + */ +#define PGTABLE_EA_BITS 41 +#define PGTABLE_EA_MASK ((1UL<<PGTABLE_EA_BITS)-1) + +/* + * Define the address range of the vmalloc VM area. + */ +#define VMALLOC_START (0xD000000000000000ul) +#define VMALLOC_END (VMALLOC_START + PGTABLE_EA_MASK) + +/* + * Define the address range of the imalloc VM area. + * (used for ioremap) + */ +#define IMALLOC_START (ioremap_bot) +#define IMALLOC_VMADDR(x) ((unsigned long)(x)) +#define PHBS_IO_BASE (0xE000000000000000ul) /* Reserve 2 gigs for PHBs */ +#define IMALLOC_BASE (0xE000000080000000ul) +#define IMALLOC_END (IMALLOC_BASE + PGTABLE_EA_MASK) + +/* + * Define the user address range + */ +#define USER_START (0UL) +#define USER_END (USER_START + PGTABLE_EA_MASK) + + +/* + * Bits in a linux-style PTE. These match the bits in the + * (hardware-defined) PowerPC PTE as closely as possible. + */ +#define _PAGE_PRESENT 0x0001 /* software: pte contains a translation */ +#define _PAGE_USER 0x0002 /* matches one of the PP bits */ +#define _PAGE_FILE 0x0002 /* (!present only) software: pte holds file offset */ +#define _PAGE_EXEC 0x0004 /* No execute on POWER4 and newer (we invert) */ +#define _PAGE_GUARDED 0x0008 +#define _PAGE_COHERENT 0x0010 /* M: enforce memory coherence (SMP systems) */ +#define _PAGE_NO_CACHE 0x0020 /* I: cache inhibit */ +#define _PAGE_WRITETHRU 0x0040 /* W: cache write-through */ +#define _PAGE_DIRTY 0x0080 /* C: page changed */ +#define _PAGE_ACCESSED 0x0100 /* R: page referenced */ +#define _PAGE_RW 0x0200 /* software: user write access allowed */ +#define _PAGE_HASHPTE 0x0400 /* software: pte has an associated HPTE */ +#define _PAGE_BUSY 0x0800 /* software: PTE & hash are busy */ +#define _PAGE_SECONDARY 0x8000 /* software: HPTE is in secondary group */ +#define _PAGE_GROUP_IX 0x7000 /* software: HPTE index within group */ +#define _PAGE_HUGE 0x10000 /* 16MB page */ +/* Bits 0x7000 identify the index within an HPT Group */ +#define _PAGE_HPTEFLAGS (_PAGE_BUSY | _PAGE_HASHPTE | _PAGE_SECONDARY | _PAGE_GROUP_IX) +/* PAGE_MASK gives the right answer below, but only by accident */ +/* It should be preserving the high 48 bits and then specifically */ +/* preserving _PAGE_SECONDARY | _PAGE_GROUP_IX */ +#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HPTEFLAGS) + +#define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_COHERENT) + +#define _PAGE_WRENABLE (_PAGE_RW | _PAGE_DIRTY) + +/* __pgprot defined in asm-ppc64/page.h */ +#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED) + +#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_RW | _PAGE_USER) +#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_RW | _PAGE_USER | _PAGE_EXEC) +#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER) +#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) +#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER) +#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) +#define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_WRENABLE) +#define PAGE_KERNEL_CI __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ + _PAGE_WRENABLE | _PAGE_NO_CACHE | _PAGE_GUARDED) +#define PAGE_KERNEL_EXEC __pgprot(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_EXEC) + +#define PAGE_AGP __pgprot(_PAGE_BASE | _PAGE_WRENABLE | _PAGE_NO_CACHE) +#define HAVE_PAGE_AGP + +/* + * This bit in a hardware PTE indicates that the page is *not* executable. + */ +#define HW_NO_EXEC _PAGE_EXEC + +/* + * POWER4 and newer have per page execute protection, older chips can only + * do this on a segment (256MB) basis. + * + * Also, write permissions imply read permissions. + * This is the closest we can get.. + * + * Note due to the way vm flags are laid out, the bits are XWR + */ +#define __P000 PAGE_NONE +#define __P001 PAGE_READONLY +#define __P010 PAGE_COPY +#define __P011 PAGE_COPY +#define __P100 PAGE_READONLY_X +#define __P101 PAGE_READONLY_X +#define __P110 PAGE_COPY_X +#define __P111 PAGE_COPY_X + +#define __S000 PAGE_NONE +#define __S001 PAGE_READONLY +#define __S010 PAGE_SHARED +#define __S011 PAGE_SHARED +#define __S100 PAGE_READONLY_X +#define __S101 PAGE_READONLY_X +#define __S110 PAGE_SHARED_X +#define __S111 PAGE_SHARED_X + +#ifndef __ASSEMBLY__ + +/* + * ZERO_PAGE is a global shared page that is always zero: used + * for zero-mapped memory areas etc.. + */ +extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)]; +#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) +#endif /* __ASSEMBLY__ */ + +/* shift to put page number into pte */ +#define PTE_SHIFT (17) + +/* We allow 2^41 bytes of real memory, so we need 29 bits in the PMD + * to give the PTE page number. The bottom two bits are for flags. */ +#define PMD_TO_PTEPAGE_SHIFT (2) + +#ifdef CONFIG_HUGETLB_PAGE + +#ifndef __ASSEMBLY__ +int hash_huge_page(struct mm_struct *mm, unsigned long access, + unsigned long ea, unsigned long vsid, int local); + +void hugetlb_mm_free_pgd(struct mm_struct *mm); +#endif /* __ASSEMBLY__ */ + +#define HAVE_ARCH_UNMAPPED_AREA +#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN +#else + +#define hash_huge_page(mm,a,ea,vsid,local) -1 +#define hugetlb_mm_free_pgd(mm) do {} while (0) + +#endif + +#ifndef __ASSEMBLY__ + +/* + * Conversion functions: convert a page and protection to a page entry, + * and a page entry and page directory to the page they refer to. + * + * mk_pte takes a (struct page *) as input + */ +#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) + +#define pfn_pte(pfn,pgprot) \ +({ \ + pte_t pte; \ + pte_val(pte) = ((unsigned long)(pfn) << PTE_SHIFT) | \ + pgprot_val(pgprot); \ + pte; \ +}) + +#define pte_modify(_pte, newprot) \ + (__pte((pte_val(_pte) & _PAGE_CHG_MASK) | pgprot_val(newprot))) + +#define pte_none(pte) ((pte_val(pte) & ~_PAGE_HPTEFLAGS) == 0) +#define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT) + +/* pte_clear moved to later in this file */ + +#define pte_pfn(x) ((unsigned long)((pte_val(x) >> PTE_SHIFT))) +#define pte_page(x) pfn_to_page(pte_pfn(x)) + +#define pmd_set(pmdp, ptep) \ + (pmd_val(*(pmdp)) = (__ba_to_bpn(ptep) << PMD_TO_PTEPAGE_SHIFT)) +#define pmd_none(pmd) (!pmd_val(pmd)) +#define pmd_bad(pmd) (pmd_val(pmd) == 0) +#define pmd_present(pmd) (pmd_val(pmd) != 0) +#define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0) +#define pmd_page_kernel(pmd) \ + (__bpn_to_ba(pmd_val(pmd) >> PMD_TO_PTEPAGE_SHIFT)) +#define pmd_page(pmd) virt_to_page(pmd_page_kernel(pmd)) +#define pgd_set(pgdp, pmdp) (pgd_val(*(pgdp)) = (__ba_to_bpn(pmdp))) +#define pgd_none(pgd) (!pgd_val(pgd)) +#define pgd_bad(pgd) ((pgd_val(pgd)) == 0) +#define pgd_present(pgd) (pgd_val(pgd) != 0UL) +#define pgd_clear(pgdp) (pgd_val(*(pgdp)) = 0UL) +#define pgd_page(pgd) (__bpn_to_ba(pgd_val(pgd))) + +/* + * Find an entry in a page-table-directory. We combine the address region + * (the high order N bits) and the pgd portion of the address. + */ +/* to avoid overflow in free_pgtables we don't use PTRS_PER_PGD here */ +#define pgd_index(address) (((address) >> (PGDIR_SHIFT)) & 0x7ff) + +#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address)) + +/* Find an entry in the second-level page table.. */ +#define pmd_offset(dir,addr) \ + ((pmd_t *) pgd_page(*(dir)) + (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))) + +/* Find an entry in the third-level page table.. */ +#define pte_offset_kernel(dir,addr) \ + ((pte_t *) pmd_page_kernel(*(dir)) + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))) + +#define pte_offset_map(dir,addr) pte_offset_kernel((dir), (addr)) +#define pte_offset_map_nested(dir,addr) pte_offset_kernel((dir), (addr)) +#define pte_unmap(pte) do { } while(0) +#define pte_unmap_nested(pte) do { } while(0) + +/* to find an entry in a kernel page-table-directory */ +/* This now only contains the vmalloc pages */ +#define pgd_offset_k(address) pgd_offset(&init_mm, address) + +/* to find an entry in the ioremap page-table-directory */ +#define pgd_offset_i(address) (ioremap_pgd + pgd_index(address)) + +#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) + +/* + * The following only work if pte_present() is true. + * Undefined behaviour if not.. + */ +static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER;} +static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW;} +static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXEC;} +static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY;} +static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED;} +static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE;} +static inline int pte_huge(pte_t pte) { return pte_val(pte) & _PAGE_HUGE;} + +static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; } +static inline void pte_cache(pte_t pte) { pte_val(pte) &= ~_PAGE_NO_CACHE; } + +static inline pte_t pte_rdprotect(pte_t pte) { + pte_val(pte) &= ~_PAGE_USER; return pte; } +static inline pte_t pte_exprotect(pte_t pte) { + pte_val(pte) &= ~_PAGE_EXEC; return pte; } +static inline pte_t pte_wrprotect(pte_t pte) { + pte_val(pte) &= ~(_PAGE_RW); return pte; } +static inline pte_t pte_mkclean(pte_t pte) { + pte_val(pte) &= ~(_PAGE_DIRTY); return pte; } +static inline pte_t pte_mkold(pte_t pte) { + pte_val(pte) &= ~_PAGE_ACCESSED; return pte; } + +static inline pte_t pte_mkread(pte_t pte) { + pte_val(pte) |= _PAGE_USER; return pte; } +static inline pte_t pte_mkexec(pte_t pte) { + pte_val(pte) |= _PAGE_USER | _PAGE_EXEC; return pte; } +static inline pte_t pte_mkwrite(pte_t pte) { + pte_val(pte) |= _PAGE_RW; return pte; } +static inline pte_t pte_mkdirty(pte_t pte) { + pte_val(pte) |= _PAGE_DIRTY; return pte; } +static inline pte_t pte_mkyoung(pte_t pte) { + pte_val(pte) |= _PAGE_ACCESSED; return pte; } +static inline pte_t pte_mkhuge(pte_t pte) { + pte_val(pte) |= _PAGE_HUGE; return pte; } + +/* Atomic PTE updates */ +static inline unsigned long pte_update(pte_t *p, unsigned long clr) +{ + unsigned long old, tmp; + + __asm__ __volatile__( + "1: ldarx %0,0,%3 # pte_update\n\ + andi. %1,%0,%6\n\ + bne- 1b \n\ + andc %1,%0,%4 \n\ + stdcx. %1,0,%3 \n\ + bne- 1b" + : "=&r" (old), "=&r" (tmp), "=m" (*p) + : "r" (p), "r" (clr), "m" (*p), "i" (_PAGE_BUSY) + : "cc" ); + return old; +} + +/* PTE updating functions, this function puts the PTE in the + * batch, doesn't actually triggers the hash flush immediately, + * you need to call flush_tlb_pending() to do that. + */ +extern void hpte_update(struct mm_struct *mm, unsigned long addr, unsigned long pte, + int wrprot); + +static inline int __ptep_test_and_clear_young(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +{ + unsigned long old; + + if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0) + return 0; + old = pte_update(ptep, _PAGE_ACCESSED); + if (old & _PAGE_HASHPTE) { + hpte_update(mm, addr, old, 0); + flush_tlb_pending(); + } + return (old & _PAGE_ACCESSED) != 0; +} +#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG +#define ptep_test_and_clear_young(__vma, __addr, __ptep) \ +({ \ + int __r; \ + __r = __ptep_test_and_clear_young((__vma)->vm_mm, __addr, __ptep); \ + __r; \ +}) + +/* + * On RW/DIRTY bit transitions we can avoid flushing the hpte. For the + * moment we always flush but we need to fix hpte_update and test if the + * optimisation is worth it. + */ +static inline int __ptep_test_and_clear_dirty(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +{ + unsigned long old; + + if ((pte_val(*ptep) & _PAGE_DIRTY) == 0) + return 0; + old = pte_update(ptep, _PAGE_DIRTY); + if (old & _PAGE_HASHPTE) + hpte_update(mm, addr, old, 0); + return (old & _PAGE_DIRTY) != 0; +} +#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY +#define ptep_test_and_clear_dirty(__vma, __addr, __ptep) \ +({ \ + int __r; \ + __r = __ptep_test_and_clear_dirty((__vma)->vm_mm, __addr, __ptep); \ + __r; \ +}) + +#define __HAVE_ARCH_PTEP_SET_WRPROTECT +static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +{ + unsigned long old; + + if ((pte_val(*ptep) & _PAGE_RW) == 0) + return; + old = pte_update(ptep, _PAGE_RW); + if (old & _PAGE_HASHPTE) + hpte_update(mm, addr, old, 0); +} + +/* + * We currently remove entries from the hashtable regardless of whether + * the entry was young or dirty. The generic routines only flush if the + * entry was young or dirty which is not good enough. + * + * We should be more intelligent about this but for the moment we override + * these functions and force a tlb flush unconditionally + */ +#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH +#define ptep_clear_flush_young(__vma, __address, __ptep) \ +({ \ + int __young = __ptep_test_and_clear_young((__vma)->vm_mm, __address, \ + __ptep); \ + __young; \ +}) + +#define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH +#define ptep_clear_flush_dirty(__vma, __address, __ptep) \ +({ \ + int __dirty = __ptep_test_and_clear_dirty((__vma)->vm_mm, __address, \ + __ptep); \ + flush_tlb_page(__vma, __address); \ + __dirty; \ +}) + +#define __HAVE_ARCH_PTEP_GET_AND_CLEAR +static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +{ + unsigned long old = pte_update(ptep, ~0UL); + + if (old & _PAGE_HASHPTE) + hpte_update(mm, addr, old, 0); + return __pte(old); +} + +static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t * ptep) +{ + unsigned long old = pte_update(ptep, ~0UL); + + if (old & _PAGE_HASHPTE) + hpte_update(mm, addr, old, 0); +} + +/* + * set_pte stores a linux PTE into the linux page table. + */ +static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, pte_t pte) +{ + if (pte_present(*ptep)) { + pte_clear(mm, addr, ptep); + flush_tlb_pending(); + } + *ptep = __pte(pte_val(pte)) & ~_PAGE_HPTEFLAGS; +} + +/* Set the dirty and/or accessed bits atomically in a linux PTE, this + * function doesn't need to flush the hash entry + */ +#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS +static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty) +{ + unsigned long bits = pte_val(entry) & + (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC); + unsigned long old, tmp; + + __asm__ __volatile__( + "1: ldarx %0,0,%4\n\ + andi. %1,%0,%6\n\ + bne- 1b \n\ + or %0,%3,%0\n\ + stdcx. %0,0,%4\n\ + bne- 1b" + :"=&r" (old), "=&r" (tmp), "=m" (*ptep) + :"r" (bits), "r" (ptep), "m" (*ptep), "i" (_PAGE_BUSY) + :"cc"); +} +#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \ + do { \ + __ptep_set_access_flags(__ptep, __entry, __dirty); \ + flush_tlb_page_nohash(__vma, __address); \ + } while(0) + +/* + * Macro to mark a page protection value as "uncacheable". + */ +#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_NO_CACHE | _PAGE_GUARDED)) + +struct file; +extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr, + unsigned long size, pgprot_t vma_prot); +#define __HAVE_PHYS_MEM_ACCESS_PROT + +#define __HAVE_ARCH_PTE_SAME +#define pte_same(A,B) (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HPTEFLAGS) == 0) + +extern unsigned long ioremap_bot, ioremap_base; + +#define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT) +#define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS) + +#define pte_ERROR(e) \ + printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e)) +#define pmd_ERROR(e) \ + printk("%s:%d: bad pmd %08x.\n", __FILE__, __LINE__, pmd_val(e)) +#define pgd_ERROR(e) \ + printk("%s:%d: bad pgd %08x.\n", __FILE__, __LINE__, pgd_val(e)) + +extern pgd_t swapper_pg_dir[1024]; +extern pgd_t ioremap_dir[1024]; + +extern void paging_init(void); + +struct mmu_gather; +void hugetlb_free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *prev, + unsigned long start, unsigned long end); + +/* + * This gets called at the end of handling a page fault, when + * the kernel has put a new PTE into the page table for the process. + * We use it to put a corresponding HPTE into the hash table + * ahead of time, instead of waiting for the inevitable extra + * hash-table miss exception. + */ +struct vm_area_struct; +extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); + +/* Encode and de-code a swap entry */ +#define __swp_type(entry) (((entry).val >> 1) & 0x3f) +#define __swp_offset(entry) ((entry).val >> 8) +#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> PTE_SHIFT }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val << PTE_SHIFT }) +#define pte_to_pgoff(pte) (pte_val(pte) >> PTE_SHIFT) +#define pgoff_to_pte(off) ((pte_t) {((off) << PTE_SHIFT)|_PAGE_FILE}) +#define PTE_FILE_MAX_BITS (BITS_PER_LONG - PTE_SHIFT) + +/* + * kern_addr_valid is intended to indicate whether an address is a valid + * kernel address. Most 32-bit archs define it as always true (like this) + * but most 64-bit archs actually perform a test. What should we do here? + * The only use is in fs/ncpfs/dir.c + */ +#define kern_addr_valid(addr) (1) + +#define io_remap_page_range(vma, vaddr, paddr, size, prot) \ + remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot) + +#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ + remap_pfn_range(vma, vaddr, pfn, size, prot) + +#define MK_IOSPACE_PFN(space, pfn) (pfn) +#define GET_IOSPACE(pfn) 0 +#define GET_PFN(pfn) (pfn) + +void pgtable_cache_init(void); + +extern void hpte_init_native(void); +extern void hpte_init_lpar(void); +extern void hpte_init_iSeries(void); + +/* imalloc region types */ +#define IM_REGION_UNUSED 0x1 +#define IM_REGION_SUBSET 0x2 +#define IM_REGION_EXISTS 0x4 +#define IM_REGION_OVERLAP 0x8 +#define IM_REGION_SUPERSET 0x10 + +extern struct vm_struct * im_get_free_area(unsigned long size); +extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size, + int region_type); +unsigned long im_free(void *addr); + +extern long pSeries_lpar_hpte_insert(unsigned long hpte_group, + unsigned long va, unsigned long prpn, + int secondary, unsigned long hpteflags, + int bolted, int large); + +extern long native_hpte_insert(unsigned long hpte_group, unsigned long va, + unsigned long prpn, int secondary, + unsigned long hpteflags, int bolted, int large); + +/* + * find_linux_pte returns the address of a linux pte for a given + * effective address and directory. If not found, it returns zero. + */ +static inline pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea) +{ + pgd_t *pg; + pmd_t *pm; + pte_t *pt = NULL; + pte_t pte; + + pg = pgdir + pgd_index(ea); + if (!pgd_none(*pg)) { + + pm = pmd_offset(pg, ea); + if (pmd_present(*pm)) { + pt = pte_offset_kernel(pm, ea); + pte = *pt; + if (!pte_present(pte)) + pt = NULL; + } + } + + return pt; +} + +#include <asm-generic/pgtable.h> + +#endif /* __ASSEMBLY__ */ + +#endif /* _PPC64_PGTABLE_H */ diff --git a/include/asm-ppc64/plpar_wrappers.h b/include/asm-ppc64/plpar_wrappers.h new file mode 100644 index 000000000000..f4a5fb7d67c7 --- /dev/null +++ b/include/asm-ppc64/plpar_wrappers.h @@ -0,0 +1,111 @@ +#ifndef _PPC64_PLPAR_WRAPPERS_H +#define _PPC64_PLPAR_WRAPPERS_H + +#include <asm/hvcall.h> + +static inline long poll_pending(void) +{ + unsigned long dummy; + return plpar_hcall(H_POLL_PENDING, 0, 0, 0, 0, + &dummy, &dummy, &dummy); +} + +static inline long prod_processor(void) +{ + plpar_hcall_norets(H_PROD); + return(0); +} + +static inline long cede_processor(void) +{ + plpar_hcall_norets(H_CEDE); + return(0); +} + +static inline long register_vpa(unsigned long flags, unsigned long proc, + unsigned long vpa) +{ + return plpar_hcall_norets(H_REGISTER_VPA, flags, proc, vpa); +} + +void vpa_init(int cpu); + +static inline long plpar_pte_remove(unsigned long flags, + unsigned long ptex, + unsigned long avpn, + unsigned long *old_pteh_ret, + unsigned long *old_ptel_ret) +{ + unsigned long dummy; + return plpar_hcall(H_REMOVE, flags, ptex, avpn, 0, + old_pteh_ret, old_ptel_ret, &dummy); +} + +static inline long plpar_pte_read(unsigned long flags, + unsigned long ptex, + unsigned long *old_pteh_ret, unsigned long *old_ptel_ret) +{ + unsigned long dummy; + return plpar_hcall(H_READ, flags, ptex, 0, 0, + old_pteh_ret, old_ptel_ret, &dummy); +} + +static inline long plpar_pte_protect(unsigned long flags, + unsigned long ptex, + unsigned long avpn) +{ + return plpar_hcall_norets(H_PROTECT, flags, ptex, avpn); +} + +static inline long plpar_tce_get(unsigned long liobn, + unsigned long ioba, + unsigned long *tce_ret) +{ + unsigned long dummy; + return plpar_hcall(H_GET_TCE, liobn, ioba, 0, 0, + tce_ret, &dummy, &dummy); +} + +static inline long plpar_tce_put(unsigned long liobn, + unsigned long ioba, + unsigned long tceval) +{ + return plpar_hcall_norets(H_PUT_TCE, liobn, ioba, tceval); +} + +static inline long plpar_tce_put_indirect(unsigned long liobn, + unsigned long ioba, + unsigned long page, + unsigned long count) +{ + return plpar_hcall_norets(H_PUT_TCE_INDIRECT, liobn, ioba, page, count); +} + +static inline long plpar_tce_stuff(unsigned long liobn, + unsigned long ioba, + unsigned long tceval, + unsigned long count) +{ + return plpar_hcall_norets(H_STUFF_TCE, liobn, ioba, tceval, count); +} + +static inline long plpar_get_term_char(unsigned long termno, + unsigned long *len_ret, + char *buf_ret) +{ + unsigned long *lbuf = (unsigned long *)buf_ret; /* ToDo: alignment? */ + return plpar_hcall(H_GET_TERM_CHAR, termno, 0, 0, 0, + len_ret, lbuf+0, lbuf+1); +} + +static inline long plpar_put_term_char(unsigned long termno, + unsigned long len, + const char *buffer) +{ + unsigned long *lbuf = (unsigned long *)buffer; /* ToDo: alignment? */ + return plpar_hcall_norets(H_PUT_TERM_CHAR, termno, len, lbuf[0], + lbuf[1]); +} + + +#endif /* _PPC64_PLPAR_WRAPPERS_H */ diff --git a/include/asm-ppc64/pmac_feature.h b/include/asm-ppc64/pmac_feature.h new file mode 100644 index 000000000000..e07e36c4cbb2 --- /dev/null +++ b/include/asm-ppc64/pmac_feature.h @@ -0,0 +1,2 @@ +#include <asm-ppc/pmac_feature.h> + diff --git a/include/asm-ppc64/pmac_low_i2c.h b/include/asm-ppc64/pmac_low_i2c.h new file mode 100644 index 000000000000..7bcfc72c5c8a --- /dev/null +++ b/include/asm-ppc64/pmac_low_i2c.h @@ -0,0 +1,2 @@ +#include <asm-ppc/pmac_low_i2c.h> + diff --git a/include/asm-ppc64/pmc.h b/include/asm-ppc64/pmc.h new file mode 100644 index 000000000000..c924748c0bea --- /dev/null +++ b/include/asm-ppc64/pmc.h @@ -0,0 +1,29 @@ +/* + * pmc.h + * Copyright (C) 2004 David Gibson, IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _PPC64_PMC_H +#define _PPC64_PMC_H + +#include <asm/ptrace.h> + +typedef void (*perf_irq_t)(struct pt_regs *); + +int reserve_pmc_hardware(perf_irq_t new_perf_irq); +void release_pmc_hardware(void); + +#endif /* _PPC64_PMC_H */ diff --git a/include/asm-ppc64/poll.h b/include/asm-ppc64/poll.h new file mode 100644 index 000000000000..370fa3ba0db4 --- /dev/null +++ b/include/asm-ppc64/poll.h @@ -0,0 +1,32 @@ +#ifndef __PPC64_POLL_H +#define __PPC64_POLL_H + +/* + * Copyright (C) 2001 PPC64 Team, IBM Corp + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#define POLLIN 0x0001 +#define POLLPRI 0x0002 +#define POLLOUT 0x0004 +#define POLLERR 0x0008 +#define POLLHUP 0x0010 +#define POLLNVAL 0x0020 +#define POLLRDNORM 0x0040 +#define POLLRDBAND 0x0080 +#define POLLWRNORM 0x0100 +#define POLLWRBAND 0x0200 +#define POLLMSG 0x0400 +#define POLLREMOVE 0x1000 + +struct pollfd { + int fd; + short events; + short revents; +}; + +#endif /* __PPC64_POLL_H */ diff --git a/include/asm-ppc64/posix_types.h b/include/asm-ppc64/posix_types.h new file mode 100644 index 000000000000..516de7201b5d --- /dev/null +++ b/include/asm-ppc64/posix_types.h @@ -0,0 +1,119 @@ +#ifndef _PPC64_POSIX_TYPES_H +#define _PPC64_POSIX_TYPES_H + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. Also, we cannot + * assume GCC is being used. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +typedef unsigned long __kernel_ino_t; +typedef unsigned long __kernel_nlink_t; +typedef unsigned int __kernel_mode_t; +typedef long __kernel_off_t; +typedef long long __kernel_loff_t; +typedef int __kernel_pid_t; +typedef int __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef int __kernel_timer_t; +typedef int __kernel_clockid_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; + +typedef unsigned int __kernel_old_uid_t; +typedef unsigned int __kernel_old_gid_t; +typedef unsigned long __kernel_old_dev_t; + +typedef struct { + int val[2]; +} __kernel_fsid_t; + +#ifndef __GNUC__ + +#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d)) +#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d)) +#define __FD_ISSET(d, set) (((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0) +#define __FD_ZERO(set) \ + ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set))) + +#else /* __GNUC__ */ + +#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) \ + || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0) +/* With GNU C, use inline functions instead so args are evaluated only once: */ + +#undef __FD_SET +static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp) +{ + unsigned long _tmp = fd / __NFDBITS; + unsigned long _rem = fd % __NFDBITS; + fdsetp->fds_bits[_tmp] |= (1UL<<_rem); +} + +#undef __FD_CLR +static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp) +{ + unsigned long _tmp = fd / __NFDBITS; + unsigned long _rem = fd % __NFDBITS; + fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem); +} + +#undef __FD_ISSET +static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p) +{ + unsigned long _tmp = fd / __NFDBITS; + unsigned long _rem = fd % __NFDBITS; + return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0; +} + +/* + * This will unroll the loop for the normal constant case (8 ints, + * for a 256-bit fd_set) + */ +#undef __FD_ZERO +static __inline__ void __FD_ZERO(__kernel_fd_set *p) +{ + unsigned long *tmp = (unsigned long *)p->fds_bits; + int i; + + if (__builtin_constant_p(__FDSET_LONGS)) { + switch (__FDSET_LONGS) { + case 16: + tmp[12] = 0; tmp[13] = 0; tmp[14] = 0; tmp[15] = 0; + tmp[ 8] = 0; tmp[ 9] = 0; tmp[10] = 0; tmp[11] = 0; + + case 8: + tmp[ 4] = 0; tmp[ 5] = 0; tmp[ 6] = 0; tmp[ 7] = 0; + + case 4: + tmp[ 0] = 0; tmp[ 1] = 0; tmp[ 2] = 0; tmp[ 3] = 0; + return; + } + } + i = __FDSET_LONGS; + while (i) { + i--; + *tmp = 0; + tmp++; + } +} + +#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ +#endif /* __GNUC__ */ +#endif /* _PPC64_POSIX_TYPES_H */ diff --git a/include/asm-ppc64/ppc32.h b/include/asm-ppc64/ppc32.h new file mode 100644 index 000000000000..1d0404897550 --- /dev/null +++ b/include/asm-ppc64/ppc32.h @@ -0,0 +1,122 @@ +#ifndef _PPC64_PPC32_H +#define _PPC64_PPC32_H + +#include <linux/compat.h> +#include <asm/siginfo.h> +#include <asm/signal.h> + +/* + * Data types and macros for providing 32b PowerPC support. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +/* These are here to support 32-bit syscalls on a 64-bit kernel. */ + +typedef struct compat_siginfo { + int si_signo; + int si_errno; + int si_code; + + union { + int _pad[SI_PAD_SIZE32]; + + /* kill() */ + struct { + compat_pid_t _pid; /* sender's pid */ + compat_uid_t _uid; /* sender's uid */ + } _kill; + + /* POSIX.1b timers */ + struct { + timer_t _tid; /* timer id */ + int _overrun; /* overrun count */ + compat_sigval_t _sigval; /* same as below */ + int _sys_private; /* not to be passed to user */ + } _timer; + + /* POSIX.1b signals */ + struct { + compat_pid_t _pid; /* sender's pid */ + compat_uid_t _uid; /* sender's uid */ + compat_sigval_t _sigval; + } _rt; + + /* SIGCHLD */ + struct { + compat_pid_t _pid; /* which child */ + compat_uid_t _uid; /* sender's uid */ + int _status; /* exit code */ + compat_clock_t _utime; + compat_clock_t _stime; + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */ + struct { + unsigned int _addr; /* faulting insn/memory ref. */ + } _sigfault; + + /* SIGPOLL */ + struct { + int _band; /* POLL_IN, POLL_OUT, POLL_MSG */ + int _fd; + } _sigpoll; + } _sifields; +} compat_siginfo_t; + +#define __old_sigaction32 old_sigaction32 + +struct __old_sigaction32 { + unsigned sa_handler; + compat_old_sigset_t sa_mask; + unsigned int sa_flags; + unsigned sa_restorer; /* not used by Linux/SPARC yet */ +}; + + + +struct sigaction32 { + unsigned int sa_handler; /* Really a pointer, but need to deal with 32 bits */ + unsigned int sa_flags; + unsigned int sa_restorer; /* Another 32 bit pointer */ + compat_sigset_t sa_mask; /* A 32 bit mask */ +}; + +typedef struct sigaltstack_32 { + unsigned int ss_sp; + int ss_flags; + compat_size_t ss_size; +} stack_32_t; + +struct sigcontext32 { + unsigned int _unused[4]; + int signal; + unsigned int handler; + unsigned int oldmask; + u32 regs; /* 4 byte pointer to the pt_regs32 structure. */ +}; + +struct mcontext32 { + elf_gregset_t32 mc_gregs; + elf_fpregset_t mc_fregs; + unsigned int mc_pad[2]; + elf_vrregset_t32 mc_vregs __attribute__((__aligned__(16))); +}; + +struct ucontext32 { + unsigned int uc_flags; + unsigned int uc_link; + stack_32_t uc_stack; + int uc_pad[7]; + u32 uc_regs; /* points to uc_mcontext field */ + compat_sigset_t uc_sigmask; /* mask last for extensibility */ + /* glibc has 1024-bit signal masks, ours are 64-bit */ + int uc_maskext[30]; + int uc_pad2[3]; + struct mcontext32 uc_mcontext; +}; + +#endif /* _PPC64_PPC32_H */ diff --git a/include/asm-ppc64/ppc_asm.h b/include/asm-ppc64/ppc_asm.h new file mode 100644 index 000000000000..9031d8a29aca --- /dev/null +++ b/include/asm-ppc64/ppc_asm.h @@ -0,0 +1,242 @@ +/* + * arch/ppc64/kernel/ppc_asm.h + * + * Definitions used by various bits of low-level assembly code on PowerPC. + * + * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _PPC64_PPC_ASM_H +#define _PPC64_PPC_ASM_H +/* + * Macros for storing registers into and loading registers from + * exception frames. + */ +#define SAVE_GPR(n, base) std n,GPR0+8*(n)(base) +#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base) +#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base) +#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base) +#define SAVE_10GPRS(n, base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base) +#define REST_GPR(n, base) ld n,GPR0+8*(n)(base) +#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base) +#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base) +#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base) +#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base) + +#define SAVE_NVGPRS(base) SAVE_8GPRS(14, base); SAVE_10GPRS(22, base) +#define REST_NVGPRS(base) REST_8GPRS(14, base); REST_10GPRS(22, base) + +#define SAVE_FPR(n, base) stfd n,THREAD_FPR0+8*(n)(base) +#define SAVE_2FPRS(n, base) SAVE_FPR(n, base); SAVE_FPR(n+1, base) +#define SAVE_4FPRS(n, base) SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base) +#define SAVE_8FPRS(n, base) SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, base) +#define SAVE_16FPRS(n, base) SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, base) +#define SAVE_32FPRS(n, base) SAVE_16FPRS(n, base); SAVE_16FPRS(n+16, base) +#define REST_FPR(n, base) lfd n,THREAD_FPR0+8*(n)(base) +#define REST_2FPRS(n, base) REST_FPR(n, base); REST_FPR(n+1, base) +#define REST_4FPRS(n, base) REST_2FPRS(n, base); REST_2FPRS(n+2, base) +#define REST_8FPRS(n, base) REST_4FPRS(n, base); REST_4FPRS(n+4, base) +#define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, base) +#define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n+16, base) + +#define SAVE_VR(n,b,base) li b,THREAD_VR0+(16*(n)); stvx n,b,base +#define SAVE_2VRS(n,b,base) SAVE_VR(n,b,base); SAVE_VR(n+1,b,base) +#define SAVE_4VRS(n,b,base) SAVE_2VRS(n,b,base); SAVE_2VRS(n+2,b,base) +#define SAVE_8VRS(n,b,base) SAVE_4VRS(n,b,base); SAVE_4VRS(n+4,b,base) +#define SAVE_16VRS(n,b,base) SAVE_8VRS(n,b,base); SAVE_8VRS(n+8,b,base) +#define SAVE_32VRS(n,b,base) SAVE_16VRS(n,b,base); SAVE_16VRS(n+16,b,base) +#define REST_VR(n,b,base) li b,THREAD_VR0+(16*(n)); lvx n,b,base +#define REST_2VRS(n,b,base) REST_VR(n,b,base); REST_VR(n+1,b,base) +#define REST_4VRS(n,b,base) REST_2VRS(n,b,base); REST_2VRS(n+2,b,base) +#define REST_8VRS(n,b,base) REST_4VRS(n,b,base); REST_4VRS(n+4,b,base) +#define REST_16VRS(n,b,base) REST_8VRS(n,b,base); REST_8VRS(n+8,b,base) +#define REST_32VRS(n,b,base) REST_16VRS(n,b,base); REST_16VRS(n+16,b,base) + +/* Macros to adjust thread priority for Iseries hardware multithreading */ +#define HMT_LOW or 1,1,1 +#define HMT_MEDIUM or 2,2,2 +#define HMT_HIGH or 3,3,3 + +/* Insert the high 32 bits of the MSR into what will be the new + MSR (via SRR1 and rfid) This preserves the MSR.SF and MSR.ISF + bits. */ + +#define FIX_SRR1(ra, rb) \ + mr rb,ra; \ + mfmsr ra; \ + rldimi ra,rb,0,32 + +#define CLR_TOP32(r) rlwinm (r),(r),0,0,31 /* clear top 32 bits */ + +/* + * LOADADDR( rn, name ) + * loads the address of 'name' into 'rn' + * + * LOADBASE( rn, name ) + * loads the address (less the low 16 bits) of 'name' into 'rn' + * suitable for base+disp addressing + */ +#define LOADADDR(rn,name) \ + lis rn,name##@highest; \ + ori rn,rn,name##@higher; \ + rldicr rn,rn,32,31; \ + oris rn,rn,name##@h; \ + ori rn,rn,name##@l + +#define LOADBASE(rn,name) \ + lis rn,name@highest; \ + ori rn,rn,name@higher; \ + rldicr rn,rn,32,31; \ + oris rn,rn,name@ha + + +#define SET_REG_TO_CONST(reg, value) \ + lis reg,(((value)>>48)&0xFFFF); \ + ori reg,reg,(((value)>>32)&0xFFFF); \ + rldicr reg,reg,32,31; \ + oris reg,reg,(((value)>>16)&0xFFFF); \ + ori reg,reg,((value)&0xFFFF); + +#define SET_REG_TO_LABEL(reg, label) \ + lis reg,(label)@highest; \ + ori reg,reg,(label)@higher; \ + rldicr reg,reg,32,31; \ + oris reg,reg,(label)@h; \ + ori reg,reg,(label)@l; + + +/* PPPBBB - DRENG If KERNELBASE is always 0xC0..., + * Then we can easily do this with one asm insn. -Peter + */ +#define tophys(rd,rs) \ + lis rd,((KERNELBASE>>48)&0xFFFF); \ + rldicr rd,rd,32,31; \ + sub rd,rs,rd + +#define tovirt(rd,rs) \ + lis rd,((KERNELBASE>>48)&0xFFFF); \ + rldicr rd,rd,32,31; \ + add rd,rs,rd + +/* Condition Register Bit Fields */ + +#define cr0 0 +#define cr1 1 +#define cr2 2 +#define cr3 3 +#define cr4 4 +#define cr5 5 +#define cr6 6 +#define cr7 7 + + +/* General Purpose Registers (GPRs) */ + +#define r0 0 +#define r1 1 +#define r2 2 +#define r3 3 +#define r4 4 +#define r5 5 +#define r6 6 +#define r7 7 +#define r8 8 +#define r9 9 +#define r10 10 +#define r11 11 +#define r12 12 +#define r13 13 +#define r14 14 +#define r15 15 +#define r16 16 +#define r17 17 +#define r18 18 +#define r19 19 +#define r20 20 +#define r21 21 +#define r22 22 +#define r23 23 +#define r24 24 +#define r25 25 +#define r26 26 +#define r27 27 +#define r28 28 +#define r29 29 +#define r30 30 +#define r31 31 + + +/* Floating Point Registers (FPRs) */ + +#define fr0 0 +#define fr1 1 +#define fr2 2 +#define fr3 3 +#define fr4 4 +#define fr5 5 +#define fr6 6 +#define fr7 7 +#define fr8 8 +#define fr9 9 +#define fr10 10 +#define fr11 11 +#define fr12 12 +#define fr13 13 +#define fr14 14 +#define fr15 15 +#define fr16 16 +#define fr17 17 +#define fr18 18 +#define fr19 19 +#define fr20 20 +#define fr21 21 +#define fr22 22 +#define fr23 23 +#define fr24 24 +#define fr25 25 +#define fr26 26 +#define fr27 27 +#define fr28 28 +#define fr29 29 +#define fr30 30 +#define fr31 31 + +#define vr0 0 +#define vr1 1 +#define vr2 2 +#define vr3 3 +#define vr4 4 +#define vr5 5 +#define vr6 6 +#define vr7 7 +#define vr8 8 +#define vr9 9 +#define vr10 10 +#define vr11 11 +#define vr12 12 +#define vr13 13 +#define vr14 14 +#define vr15 15 +#define vr16 16 +#define vr17 17 +#define vr18 18 +#define vr19 19 +#define vr20 20 +#define vr21 21 +#define vr22 22 +#define vr23 23 +#define vr24 24 +#define vr25 25 +#define vr26 26 +#define vr27 27 +#define vr28 28 +#define vr29 29 +#define vr30 30 +#define vr31 31 + +#endif /* _PPC64_PPC_ASM_H */ diff --git a/include/asm-ppc64/ppcdebug.h b/include/asm-ppc64/ppcdebug.h new file mode 100644 index 000000000000..fd7f696065c4 --- /dev/null +++ b/include/asm-ppc64/ppcdebug.h @@ -0,0 +1,108 @@ +#ifndef __PPCDEBUG_H +#define __PPCDEBUG_H +/******************************************************************** + * Author: Adam Litke, IBM Corp + * (c) 2001 + * + * This file contains definitions and macros for a runtime debugging + * system for ppc64 (This should also work on 32 bit with a few + * adjustments. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + ********************************************************************/ + +#include <linux/config.h> +#include <linux/types.h> +#include <asm/udbg.h> +#include <stdarg.h> + +#define PPCDBG_BITVAL(X) ((1UL)<<((unsigned long)(X))) + +/* Defined below are the bit positions of various debug flags in the + * ppc64_debug_switch variable. + * -- When adding new values, please enter them into trace names below -- + * + * Values 62 & 63 can be used to stress the hardware page table management + * code. They must be set statically, any attempt to change them dynamically + * would be a very bad idea. + */ +#define PPCDBG_MMINIT PPCDBG_BITVAL(0) +#define PPCDBG_MM PPCDBG_BITVAL(1) +#define PPCDBG_SYS32 PPCDBG_BITVAL(2) +#define PPCDBG_SYS32NI PPCDBG_BITVAL(3) +#define PPCDBG_SYS32X PPCDBG_BITVAL(4) +#define PPCDBG_SYS32M PPCDBG_BITVAL(5) +#define PPCDBG_SYS64 PPCDBG_BITVAL(6) +#define PPCDBG_SYS64NI PPCDBG_BITVAL(7) +#define PPCDBG_SYS64X PPCDBG_BITVAL(8) +#define PPCDBG_SIGNAL PPCDBG_BITVAL(9) +#define PPCDBG_SIGNALXMON PPCDBG_BITVAL(10) +#define PPCDBG_BINFMT32 PPCDBG_BITVAL(11) +#define PPCDBG_BINFMT64 PPCDBG_BITVAL(12) +#define PPCDBG_BINFMTXMON PPCDBG_BITVAL(13) +#define PPCDBG_BINFMT_32ADDR PPCDBG_BITVAL(14) +#define PPCDBG_ALIGNFIXUP PPCDBG_BITVAL(15) +#define PPCDBG_TCEINIT PPCDBG_BITVAL(16) +#define PPCDBG_TCE PPCDBG_BITVAL(17) +#define PPCDBG_PHBINIT PPCDBG_BITVAL(18) +#define PPCDBG_SMP PPCDBG_BITVAL(19) +#define PPCDBG_BOOT PPCDBG_BITVAL(20) +#define PPCDBG_BUSWALK PPCDBG_BITVAL(21) +#define PPCDBG_PROM PPCDBG_BITVAL(22) +#define PPCDBG_RTAS PPCDBG_BITVAL(23) +#define PPCDBG_HTABSTRESS PPCDBG_BITVAL(62) +#define PPCDBG_HTABSIZE PPCDBG_BITVAL(63) +#define PPCDBG_NONE (0UL) +#define PPCDBG_ALL (0xffffffffUL) + +/* The default initial value for the debug switch */ +#define PPC_DEBUG_DEFAULT 0 +/* #define PPC_DEBUG_DEFAULT PPCDBG_ALL */ + +#define PPCDBG_NUM_FLAGS 64 + +extern u64 ppc64_debug_switch; + +#ifdef WANT_PPCDBG_TAB +/* A table of debug switch names to allow name lookup in xmon + * (and whoever else wants it. + */ +char *trace_names[PPCDBG_NUM_FLAGS] = { + /* Known debug names */ + "mminit", "mm", + "syscall32", "syscall32_ni", "syscall32x", "syscall32m", + "syscall64", "syscall64_ni", "syscall64x", + "signal", "signal_xmon", + "binfmt32", "binfmt64", "binfmt_xmon", "binfmt_32addr", + "alignfixup", "tceinit", "tce", "phb_init", + "smp", "boot", "buswalk", "prom", + "rtas" +}; +#else +extern char *trace_names[64]; +#endif /* WANT_PPCDBG_TAB */ + +#ifdef CONFIG_PPCDBG +/* Macro to conditionally print debug based on debug_switch */ +#define PPCDBG(...) udbg_ppcdbg(__VA_ARGS__) + +/* Macro to conditionally call a debug routine based on debug_switch */ +#define PPCDBGCALL(FLAGS,FUNCTION) ifppcdebug(FLAGS) FUNCTION + +/* Macros to test for debug states */ +#define ifppcdebug(FLAGS) if (udbg_ifdebug(FLAGS)) +#define ppcdebugset(FLAGS) (udbg_ifdebug(FLAGS)) +#define PPCDBG_BINFMT (test_thread_flag(TIF_32BIT) ? PPCDBG_BINFMT32 : PPCDBG_BINFMT64) + +#else +#define PPCDBG(...) do {;} while (0) +#define PPCDBGCALL(FLAGS,FUNCTION) do {;} while (0) +#define ifppcdebug(...) if (0) +#define ppcdebugset(FLAGS) (0) +#endif /* CONFIG_PPCDBG */ + +#endif /*__PPCDEBUG_H */ diff --git a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h new file mode 100644 index 000000000000..eb33d33cfd6d --- /dev/null +++ b/include/asm-ppc64/processor.h @@ -0,0 +1,667 @@ +#ifndef __ASM_PPC64_PROCESSOR_H +#define __ASM_PPC64_PROCESSOR_H + +/* + * Copyright (C) 2001 PPC 64 Team, IBM Corp + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/stringify.h> +#ifndef __ASSEMBLY__ +#include <linux/config.h> +#include <asm/atomic.h> +#include <asm/ppcdebug.h> +#include <asm/a.out.h> +#endif +#include <asm/ptrace.h> +#include <asm/types.h> +#include <asm/systemcfg.h> + +/* Machine State Register (MSR) Fields */ +#define MSR_SF_LG 63 /* Enable 64 bit mode */ +#define MSR_ISF_LG 61 /* Interrupt 64b mode valid on 630 */ +#define MSR_HV_LG 60 /* Hypervisor state */ +#define MSR_VEC_LG 25 /* Enable AltiVec */ +#define MSR_POW_LG 18 /* Enable Power Management */ +#define MSR_WE_LG 18 /* Wait State Enable */ +#define MSR_TGPR_LG 17 /* TLB Update registers in use */ +#define MSR_CE_LG 17 /* Critical Interrupt Enable */ +#define MSR_ILE_LG 16 /* Interrupt Little Endian */ +#define MSR_EE_LG 15 /* External Interrupt Enable */ +#define MSR_PR_LG 14 /* Problem State / Privilege Level */ +#define MSR_FP_LG 13 /* Floating Point enable */ +#define MSR_ME_LG 12 /* Machine Check Enable */ +#define MSR_FE0_LG 11 /* Floating Exception mode 0 */ +#define MSR_SE_LG 10 /* Single Step */ +#define MSR_BE_LG 9 /* Branch Trace */ +#define MSR_DE_LG 9 /* Debug Exception Enable */ +#define MSR_FE1_LG 8 /* Floating Exception mode 1 */ +#define MSR_IP_LG 6 /* Exception prefix 0x000/0xFFF */ +#define MSR_IR_LG 5 /* Instruction Relocate */ +#define MSR_DR_LG 4 /* Data Relocate */ +#define MSR_PE_LG 3 /* Protection Enable */ +#define MSR_PX_LG 2 /* Protection Exclusive Mode */ +#define MSR_PMM_LG 2 /* Performance monitor */ +#define MSR_RI_LG 1 /* Recoverable Exception */ +#define MSR_LE_LG 0 /* Little Endian */ + +#ifdef __ASSEMBLY__ +#define __MASK(X) (1<<(X)) +#else +#define __MASK(X) (1UL<<(X)) +#endif + +#define MSR_SF __MASK(MSR_SF_LG) /* Enable 64 bit mode */ +#define MSR_ISF __MASK(MSR_ISF_LG) /* Interrupt 64b mode valid on 630 */ +#define MSR_HV __MASK(MSR_HV_LG) /* Hypervisor state */ +#define MSR_VEC __MASK(MSR_VEC_LG) /* Enable AltiVec */ +#define MSR_POW __MASK(MSR_POW_LG) /* Enable Power Management */ +#define MSR_WE __MASK(MSR_WE_LG) /* Wait State Enable */ +#define MSR_TGPR __MASK(MSR_TGPR_LG) /* TLB Update registers in use */ +#define MSR_CE __MASK(MSR_CE_LG) /* Critical Interrupt Enable */ +#define MSR_ILE __MASK(MSR_ILE_LG) /* Interrupt Little Endian */ +#define MSR_EE __MASK(MSR_EE_LG) /* External Interrupt Enable */ +#define MSR_PR __MASK(MSR_PR_LG) /* Problem State / Privilege Level */ +#define MSR_FP __MASK(MSR_FP_LG) /* Floating Point enable */ +#define MSR_ME __MASK(MSR_ME_LG) /* Machine Check Enable */ +#define MSR_FE0 __MASK(MSR_FE0_LG) /* Floating Exception mode 0 */ +#define MSR_SE __MASK(MSR_SE_LG) /* Single Step */ +#define MSR_BE __MASK(MSR_BE_LG) /* Branch Trace */ +#define MSR_DE __MASK(MSR_DE_LG) /* Debug Exception Enable */ +#define MSR_FE1 __MASK(MSR_FE1_LG) /* Floating Exception mode 1 */ +#define MSR_IP __MASK(MSR_IP_LG) /* Exception prefix 0x000/0xFFF */ +#define MSR_IR __MASK(MSR_IR_LG) /* Instruction Relocate */ +#define MSR_DR __MASK(MSR_DR_LG) /* Data Relocate */ +#define MSR_PE __MASK(MSR_PE_LG) /* Protection Enable */ +#define MSR_PX __MASK(MSR_PX_LG) /* Protection Exclusive Mode */ +#define MSR_PMM __MASK(MSR_PMM_LG) /* Performance monitor */ +#define MSR_RI __MASK(MSR_RI_LG) /* Recoverable Exception */ +#define MSR_LE __MASK(MSR_LE_LG) /* Little Endian */ + +#define MSR_ MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_ISF +#define MSR_KERNEL MSR_ | MSR_SF | MSR_HV + +#define MSR_USER32 MSR_ | MSR_PR | MSR_EE +#define MSR_USER64 MSR_USER32 | MSR_SF + +/* Floating Point Status and Control Register (FPSCR) Fields */ + +#define FPSCR_FX 0x80000000 /* FPU exception summary */ +#define FPSCR_FEX 0x40000000 /* FPU enabled exception summary */ +#define FPSCR_VX 0x20000000 /* Invalid operation summary */ +#define FPSCR_OX 0x10000000 /* Overflow exception summary */ +#define FPSCR_UX 0x08000000 /* Underflow exception summary */ +#define FPSCR_ZX 0x04000000 /* Zero-divide exception summary */ +#define FPSCR_XX 0x02000000 /* Inexact exception summary */ +#define FPSCR_VXSNAN 0x01000000 /* Invalid op for SNaN */ +#define FPSCR_VXISI 0x00800000 /* Invalid op for Inv - Inv */ +#define FPSCR_VXIDI 0x00400000 /* Invalid op for Inv / Inv */ +#define FPSCR_VXZDZ 0x00200000 /* Invalid op for Zero / Zero */ +#define FPSCR_VXIMZ 0x00100000 /* Invalid op for Inv * Zero */ +#define FPSCR_VXVC 0x00080000 /* Invalid op for Compare */ +#define FPSCR_FR 0x00040000 /* Fraction rounded */ +#define FPSCR_FI 0x00020000 /* Fraction inexact */ +#define FPSCR_FPRF 0x0001f000 /* FPU Result Flags */ +#define FPSCR_FPCC 0x0000f000 /* FPU Condition Codes */ +#define FPSCR_VXSOFT 0x00000400 /* Invalid op for software request */ +#define FPSCR_VXSQRT 0x00000200 /* Invalid op for square root */ +#define FPSCR_VXCVI 0x00000100 /* Invalid op for integer convert */ +#define FPSCR_VE 0x00000080 /* Invalid op exception enable */ +#define FPSCR_OE 0x00000040 /* IEEE overflow exception enable */ +#define FPSCR_UE 0x00000020 /* IEEE underflow exception enable */ +#define FPSCR_ZE 0x00000010 /* IEEE zero divide exception enable */ +#define FPSCR_XE 0x00000008 /* FP inexact exception enable */ +#define FPSCR_NI 0x00000004 /* FPU non IEEE-Mode */ +#define FPSCR_RN 0x00000003 /* FPU rounding control */ + +/* Special Purpose Registers (SPRNs)*/ + +#define SPRN_CDBCR 0x3D7 /* Cache Debug Control Register */ +#define SPRN_CTR 0x009 /* Count Register */ +#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */ +#define SPRN_DAC1 0x3F6 /* Data Address Compare 1 */ +#define SPRN_DAC2 0x3F7 /* Data Address Compare 2 */ +#define SPRN_DAR 0x013 /* Data Address Register */ +#define SPRN_DBCR 0x3F2 /* Debug Control Regsiter */ +#define DBCR_EDM 0x80000000 +#define DBCR_IDM 0x40000000 +#define DBCR_RST(x) (((x) & 0x3) << 28) +#define DBCR_RST_NONE 0 +#define DBCR_RST_CORE 1 +#define DBCR_RST_CHIP 2 +#define DBCR_RST_SYSTEM 3 +#define DBCR_IC 0x08000000 /* Instruction Completion Debug Evnt */ +#define DBCR_BT 0x04000000 /* Branch Taken Debug Event */ +#define DBCR_EDE 0x02000000 /* Exception Debug Event */ +#define DBCR_TDE 0x01000000 /* TRAP Debug Event */ +#define DBCR_FER 0x00F80000 /* First Events Remaining Mask */ +#define DBCR_FT 0x00040000 /* Freeze Timers on Debug Event */ +#define DBCR_IA1 0x00020000 /* Instr. Addr. Compare 1 Enable */ +#define DBCR_IA2 0x00010000 /* Instr. Addr. Compare 2 Enable */ +#define DBCR_D1R 0x00008000 /* Data Addr. Compare 1 Read Enable */ +#define DBCR_D1W 0x00004000 /* Data Addr. Compare 1 Write Enable */ +#define DBCR_D1S(x) (((x) & 0x3) << 12) /* Data Adrr. Compare 1 Size */ +#define DAC_BYTE 0 +#define DAC_HALF 1 +#define DAC_WORD 2 +#define DAC_QUAD 3 +#define DBCR_D2R 0x00000800 /* Data Addr. Compare 2 Read Enable */ +#define DBCR_D2W 0x00000400 /* Data Addr. Compare 2 Write Enable */ +#define DBCR_D2S(x) (((x) & 0x3) << 8) /* Data Addr. Compare 2 Size */ +#define DBCR_SBT 0x00000040 /* Second Branch Taken Debug Event */ +#define DBCR_SED 0x00000020 /* Second Exception Debug Event */ +#define DBCR_STD 0x00000010 /* Second Trap Debug Event */ +#define DBCR_SIA 0x00000008 /* Second IAC Enable */ +#define DBCR_SDA 0x00000004 /* Second DAC Enable */ +#define DBCR_JOI 0x00000002 /* JTAG Serial Outbound Int. Enable */ +#define DBCR_JII 0x00000001 /* JTAG Serial Inbound Int. Enable */ +#define SPRN_DBCR0 0x3F2 /* Debug Control Register 0 */ +#define SPRN_DBCR1 0x3BD /* Debug Control Register 1 */ +#define SPRN_DBSR 0x3F0 /* Debug Status Register */ +#define SPRN_DCCR 0x3FA /* Data Cache Cacheability Register */ +#define DCCR_NOCACHE 0 /* Noncacheable */ +#define DCCR_CACHE 1 /* Cacheable */ +#define SPRN_DCMP 0x3D1 /* Data TLB Compare Register */ +#define SPRN_DCWR 0x3BA /* Data Cache Write-thru Register */ +#define DCWR_COPY 0 /* Copy-back */ +#define DCWR_WRITE 1 /* Write-through */ +#define SPRN_DEAR 0x3D5 /* Data Error Address Register */ +#define SPRN_DEC 0x016 /* Decrement Register */ +#define SPRN_DMISS 0x3D0 /* Data TLB Miss Register */ +#define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */ +#define DSISR_NOHPTE 0x40000000 /* no translation found */ +#define DSISR_PROTFAULT 0x08000000 /* protection fault */ +#define DSISR_ISSTORE 0x02000000 /* access was a store */ +#define DSISR_DABRMATCH 0x00400000 /* hit data breakpoint */ +#define DSISR_NOSEGMENT 0x00200000 /* STAB/SLB miss */ +#define SPRN_EAR 0x11A /* External Address Register */ +#define SPRN_ESR 0x3D4 /* Exception Syndrome Register */ +#define ESR_IMCP 0x80000000 /* Instr. Machine Check - Protection */ +#define ESR_IMCN 0x40000000 /* Instr. Machine Check - Non-config */ +#define ESR_IMCB 0x20000000 /* Instr. Machine Check - Bus error */ +#define ESR_IMCT 0x10000000 /* Instr. Machine Check - Timeout */ +#define ESR_PIL 0x08000000 /* Program Exception - Illegal */ +#define ESR_PPR 0x04000000 /* Program Exception - Priveleged */ +#define ESR_PTR 0x02000000 /* Program Exception - Trap */ +#define ESR_DST 0x00800000 /* Storage Exception - Data miss */ +#define ESR_DIZ 0x00400000 /* Storage Exception - Zone fault */ +#define SPRN_EVPR 0x3D6 /* Exception Vector Prefix Register */ +#define SPRN_HASH1 0x3D2 /* Primary Hash Address Register */ +#define SPRN_HASH2 0x3D3 /* Secondary Hash Address Resgister */ +#define SPRN_HID0 0x3F0 /* Hardware Implementation Register 0 */ +#define HID0_EMCP (1<<31) /* Enable Machine Check pin */ +#define HID0_EBA (1<<29) /* Enable Bus Address Parity */ +#define HID0_EBD (1<<28) /* Enable Bus Data Parity */ +#define HID0_SBCLK (1<<27) +#define HID0_EICE (1<<26) +#define HID0_ECLK (1<<25) +#define HID0_PAR (1<<24) +#define HID0_DOZE (1<<23) +#define HID0_NAP (1<<22) +#define HID0_SLEEP (1<<21) +#define HID0_DPM (1<<20) +#define HID0_ICE (1<<15) /* Instruction Cache Enable */ +#define HID0_DCE (1<<14) /* Data Cache Enable */ +#define HID0_ILOCK (1<<13) /* Instruction Cache Lock */ +#define HID0_DLOCK (1<<12) /* Data Cache Lock */ +#define HID0_ICFI (1<<11) /* Instr. Cache Flash Invalidate */ +#define HID0_DCI (1<<10) /* Data Cache Invalidate */ +#define HID0_SPD (1<<9) /* Speculative disable */ +#define HID0_SGE (1<<7) /* Store Gathering Enable */ +#define HID0_SIED (1<<7) /* Serial Instr. Execution [Disable] */ +#define HID0_BTIC (1<<5) /* Branch Target Instruction Cache Enable */ +#define HID0_ABE (1<<3) /* Address Broadcast Enable */ +#define HID0_BHTE (1<<2) /* Branch History Table Enable */ +#define HID0_BTCD (1<<1) /* Branch target cache disable */ +#define SPRN_MSRDORM 0x3F1 /* Hardware Implementation Register 1 */ +#define SPRN_HID1 0x3F1 /* Hardware Implementation Register 1 */ +#define SPRN_IABR 0x3F2 /* Instruction Address Breakpoint Register */ +#define SPRN_NIADORM 0x3F3 /* Hardware Implementation Register 2 */ +#define SPRN_HID4 0x3F4 /* 970 HID4 */ +#define SPRN_HID5 0x3F6 /* 970 HID5 */ +#define SPRN_TSC 0x3FD /* Thread switch control */ +#define SPRN_TST 0x3FC /* Thread switch timeout */ +#define SPRN_IAC1 0x3F4 /* Instruction Address Compare 1 */ +#define SPRN_IAC2 0x3F5 /* Instruction Address Compare 2 */ +#define SPRN_ICCR 0x3FB /* Instruction Cache Cacheability Register */ +#define ICCR_NOCACHE 0 /* Noncacheable */ +#define ICCR_CACHE 1 /* Cacheable */ +#define SPRN_ICDBDR 0x3D3 /* Instruction Cache Debug Data Register */ +#define SPRN_ICMP 0x3D5 /* Instruction TLB Compare Register */ +#define SPRN_ICTC 0x3FB /* Instruction Cache Throttling Control Reg */ +#define SPRN_IMISS 0x3D4 /* Instruction TLB Miss Register */ +#define SPRN_IMMR 0x27E /* Internal Memory Map Register */ +#define SPRN_L2CR 0x3F9 /* Level 2 Cache Control Regsiter */ +#define SPRN_LR 0x008 /* Link Register */ +#define SPRN_PBL1 0x3FC /* Protection Bound Lower 1 */ +#define SPRN_PBL2 0x3FE /* Protection Bound Lower 2 */ +#define SPRN_PBU1 0x3FD /* Protection Bound Upper 1 */ +#define SPRN_PBU2 0x3FF /* Protection Bound Upper 2 */ +#define SPRN_PID 0x3B1 /* Process ID */ +#define SPRN_PIR 0x3FF /* Processor Identification Register */ +#define SPRN_PIT 0x3DB /* Programmable Interval Timer */ +#define SPRN_PURR 0x135 /* Processor Utilization of Resources Register */ +#define SPRN_PVR 0x11F /* Processor Version Register */ +#define SPRN_RPA 0x3D6 /* Required Physical Address Register */ +#define SPRN_SDA 0x3BF /* Sampled Data Address Register */ +#define SPRN_SDR1 0x019 /* MMU Hash Base Register */ +#define SPRN_SGR 0x3B9 /* Storage Guarded Register */ +#define SGR_NORMAL 0 +#define SGR_GUARDED 1 +#define SPRN_SIA 0x3BB /* Sampled Instruction Address Register */ +#define SPRN_SPRG0 0x110 /* Special Purpose Register General 0 */ +#define SPRN_SPRG1 0x111 /* Special Purpose Register General 1 */ +#define SPRN_SPRG2 0x112 /* Special Purpose Register General 2 */ +#define SPRN_SPRG3 0x113 /* Special Purpose Register General 3 */ +#define SPRN_SRR0 0x01A /* Save/Restore Register 0 */ +#define SPRN_SRR1 0x01B /* Save/Restore Register 1 */ +#define SPRN_TBRL 0x10C /* Time Base Read Lower Register (user, R/O) */ +#define SPRN_TBRU 0x10D /* Time Base Read Upper Register (user, R/O) */ +#define SPRN_TBWL 0x11C /* Time Base Lower Register (super, W/O) */ +#define SPRN_TBWU 0x11D /* Time Base Write Upper Register (super, W/O) */ +#define SPRN_HIOR 0x137 /* 970 Hypervisor interrupt offset */ +#define SPRN_TCR 0x3DA /* Timer Control Register */ +#define TCR_WP(x) (((x)&0x3)<<30) /* WDT Period */ +#define WP_2_17 0 /* 2^17 clocks */ +#define WP_2_21 1 /* 2^21 clocks */ +#define WP_2_25 2 /* 2^25 clocks */ +#define WP_2_29 3 /* 2^29 clocks */ +#define TCR_WRC(x) (((x)&0x3)<<28) /* WDT Reset Control */ +#define WRC_NONE 0 /* No reset will occur */ +#define WRC_CORE 1 /* Core reset will occur */ +#define WRC_CHIP 2 /* Chip reset will occur */ +#define WRC_SYSTEM 3 /* System reset will occur */ +#define TCR_WIE 0x08000000 /* WDT Interrupt Enable */ +#define TCR_PIE 0x04000000 /* PIT Interrupt Enable */ +#define TCR_FP(x) (((x)&0x3)<<24) /* FIT Period */ +#define FP_2_9 0 /* 2^9 clocks */ +#define FP_2_13 1 /* 2^13 clocks */ +#define FP_2_17 2 /* 2^17 clocks */ +#define FP_2_21 3 /* 2^21 clocks */ +#define TCR_FIE 0x00800000 /* FIT Interrupt Enable */ +#define TCR_ARE 0x00400000 /* Auto Reload Enable */ +#define SPRN_THRM1 0x3FC /* Thermal Management Register 1 */ +#define THRM1_TIN (1<<0) +#define THRM1_TIV (1<<1) +#define THRM1_THRES (0x7f<<2) +#define THRM1_TID (1<<29) +#define THRM1_TIE (1<<30) +#define THRM1_V (1<<31) +#define SPRN_THRM2 0x3FD /* Thermal Management Register 2 */ +#define SPRN_THRM3 0x3FE /* Thermal Management Register 3 */ +#define THRM3_E (1<<31) +#define SPRN_TSR 0x3D8 /* Timer Status Register */ +#define TSR_ENW 0x80000000 /* Enable Next Watchdog */ +#define TSR_WIS 0x40000000 /* WDT Interrupt Status */ +#define TSR_WRS(x) (((x)&0x3)<<28) /* WDT Reset Status */ +#define WRS_NONE 0 /* No WDT reset occurred */ +#define WRS_CORE 1 /* WDT forced core reset */ +#define WRS_CHIP 2 /* WDT forced chip reset */ +#define WRS_SYSTEM 3 /* WDT forced system reset */ +#define TSR_PIS 0x08000000 /* PIT Interrupt Status */ +#define TSR_FIS 0x04000000 /* FIT Interrupt Status */ +#define SPRN_USIA 0x3AB /* User Sampled Instruction Address Register */ +#define SPRN_XER 0x001 /* Fixed Point Exception Register */ +#define SPRN_ZPR 0x3B0 /* Zone Protection Register */ +#define SPRN_VRSAVE 0x100 /* Vector save */ + +/* Performance monitor SPRs */ +#define SPRN_SIAR 780 +#define SPRN_SDAR 781 +#define SPRN_MMCRA 786 +#define MMCRA_SIHV 0x10000000UL /* state of MSR HV when SIAR set */ +#define MMCRA_SIPR 0x08000000UL /* state of MSR PR when SIAR set */ +#define MMCRA_SAMPLE_ENABLE 0x00000001UL /* enable sampling */ +#define SPRN_PMC1 787 +#define SPRN_PMC2 788 +#define SPRN_PMC3 789 +#define SPRN_PMC4 790 +#define SPRN_PMC5 791 +#define SPRN_PMC6 792 +#define SPRN_PMC7 793 +#define SPRN_PMC8 794 +#define SPRN_MMCR0 795 +#define MMCR0_FC 0x80000000UL /* freeze counters. set to 1 on a perfmon exception */ +#define MMCR0_FCS 0x40000000UL /* freeze in supervisor state */ +#define MMCR0_KERNEL_DISABLE MMCR0_FCS +#define MMCR0_FCP 0x20000000UL /* freeze in problem state */ +#define MMCR0_PROBLEM_DISABLE MMCR0_FCP +#define MMCR0_FCM1 0x10000000UL /* freeze counters while MSR mark = 1 */ +#define MMCR0_FCM0 0x08000000UL /* freeze counters while MSR mark = 0 */ +#define MMCR0_PMXE 0x04000000UL /* performance monitor exception enable */ +#define MMCR0_FCECE 0x02000000UL /* freeze counters on enabled condition or event */ +/* time base exception enable */ +#define MMCR0_TBEE 0x00400000UL /* time base exception enable */ +#define MMCR0_PMC1CE 0x00008000UL /* PMC1 count enable*/ +#define MMCR0_PMCjCE 0x00004000UL /* PMCj count enable*/ +#define MMCR0_TRIGGER 0x00002000UL /* TRIGGER enable */ +#define MMCR0_PMAO 0x00000080UL /* performance monitor alert has occurred, set to 0 after handling exception */ +#define MMCR0_SHRFC 0x00000040UL /* SHRre freeze conditions between threads */ +#define MMCR0_FCTI 0x00000008UL /* freeze counters in tags inactive mode */ +#define MMCR0_FCTA 0x00000004UL /* freeze counters in tags active mode */ +#define MMCR0_FCWAIT 0x00000002UL /* freeze counter in WAIT state */ +#define MMCR0_FCHV 0x00000001UL /* freeze conditions in hypervisor mode */ +#define SPRN_MMCR1 798 + +/* Short-hand versions for a number of the above SPRNs */ + +#define CTR SPRN_CTR /* Counter Register */ +#define DAR SPRN_DAR /* Data Address Register */ +#define DABR SPRN_DABR /* Data Address Breakpoint Register */ +#define DCMP SPRN_DCMP /* Data TLB Compare Register */ +#define DEC SPRN_DEC /* Decrement Register */ +#define DMISS SPRN_DMISS /* Data TLB Miss Register */ +#define DSISR SPRN_DSISR /* Data Storage Interrupt Status Register */ +#define EAR SPRN_EAR /* External Address Register */ +#define HASH1 SPRN_HASH1 /* Primary Hash Address Register */ +#define HASH2 SPRN_HASH2 /* Secondary Hash Address Register */ +#define HID0 SPRN_HID0 /* Hardware Implementation Register 0 */ +#define MSRDORM SPRN_MSRDORM /* MSR Dormant Register */ +#define NIADORM SPRN_NIADORM /* NIA Dormant Register */ +#define TSC SPRN_TSC /* Thread switch control */ +#define TST SPRN_TST /* Thread switch timeout */ +#define IABR SPRN_IABR /* Instruction Address Breakpoint Register */ +#define ICMP SPRN_ICMP /* Instruction TLB Compare Register */ +#define IMISS SPRN_IMISS /* Instruction TLB Miss Register */ +#define IMMR SPRN_IMMR /* PPC 860/821 Internal Memory Map Register */ +#define L2CR SPRN_L2CR /* PPC 750 L2 control register */ +#define __LR SPRN_LR +#define PVR SPRN_PVR /* Processor Version */ +#define PIR SPRN_PIR /* Processor ID */ +#define PURR SPRN_PURR /* Processor Utilization of Resource Register */ +//#define RPA SPRN_RPA /* Required Physical Address Register */ +#define SDR1 SPRN_SDR1 /* MMU hash base register */ +#define SPR0 SPRN_SPRG0 /* Supervisor Private Registers */ +#define SPR1 SPRN_SPRG1 +#define SPR2 SPRN_SPRG2 +#define SPR3 SPRN_SPRG3 +#define SPRG0 SPRN_SPRG0 +#define SPRG1 SPRN_SPRG1 +#define SPRG2 SPRN_SPRG2 +#define SPRG3 SPRN_SPRG3 +#define SRR0 SPRN_SRR0 /* Save and Restore Register 0 */ +#define SRR1 SPRN_SRR1 /* Save and Restore Register 1 */ +#define TBRL SPRN_TBRL /* Time Base Read Lower Register */ +#define TBRU SPRN_TBRU /* Time Base Read Upper Register */ +#define TBWL SPRN_TBWL /* Time Base Write Lower Register */ +#define TBWU SPRN_TBWU /* Time Base Write Upper Register */ +#define ICTC 1019 +#define THRM1 SPRN_THRM1 /* Thermal Management Register 1 */ +#define THRM2 SPRN_THRM2 /* Thermal Management Register 2 */ +#define THRM3 SPRN_THRM3 /* Thermal Management Register 3 */ +#define XER SPRN_XER + +/* Processor Version Register (PVR) field extraction */ + +#define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */ +#define PVR_REV(pvr) (((pvr) >> 0) & 0xFFFF) /* Revison field */ + +/* Processor Version Numbers */ +#define PV_NORTHSTAR 0x0033 +#define PV_PULSAR 0x0034 +#define PV_POWER4 0x0035 +#define PV_ICESTAR 0x0036 +#define PV_SSTAR 0x0037 +#define PV_POWER4p 0x0038 +#define PV_970 0x0039 +#define PV_POWER5 0x003A +#define PV_POWER5p 0x003B +#define PV_970FX 0x003C +#define PV_630 0x0040 +#define PV_630p 0x0041 + +/* Platforms supported by PPC64 */ +#define PLATFORM_PSERIES 0x0100 +#define PLATFORM_PSERIES_LPAR 0x0101 +#define PLATFORM_ISERIES_LPAR 0x0201 +#define PLATFORM_LPAR 0x0001 +#define PLATFORM_POWERMAC 0x0400 +#define PLATFORM_MAPLE 0x0500 + +/* Compatibility with drivers coming from PPC32 world */ +#define _machine (systemcfg->platform) +#define _MACH_Pmac PLATFORM_POWERMAC + +/* + * List of interrupt controllers. + */ +#define IC_INVALID 0 +#define IC_OPEN_PIC 1 +#define IC_PPC_XIC 2 + +#define XGLUE(a,b) a##b +#define GLUE(a,b) XGLUE(a,b) + +/* iSeries CTRL register (for runlatch) */ + +#define CTRLT 0x098 +#define CTRLF 0x088 +#define RUNLATCH 0x0001 + +#ifdef __ASSEMBLY__ + +#define _GLOBAL(name) \ + .section ".text"; \ + .align 2 ; \ + .globl name; \ + .globl GLUE(.,name); \ + .section ".opd","aw"; \ +name: \ + .quad GLUE(.,name); \ + .quad .TOC.@tocbase; \ + .quad 0; \ + .previous; \ + .type GLUE(.,name),@function; \ +GLUE(.,name): + +#define _STATIC(name) \ + .section ".text"; \ + .align 2 ; \ + .section ".opd","aw"; \ +name: \ + .quad GLUE(.,name); \ + .quad .TOC.@tocbase; \ + .quad 0; \ + .previous; \ + .type GLUE(.,name),@function; \ +GLUE(.,name): + +#else /* __ASSEMBLY__ */ + +/* + * Default implementation of macro that returns current + * instruction pointer ("program counter"). + */ +#define current_text_addr() ({ __label__ _l; _l: &&_l;}) + +/* Macros for setting and retrieving special purpose registers */ + +#define mfmsr() ({unsigned long rval; \ + asm volatile("mfmsr %0" : "=r" (rval)); rval;}) + +#define __mtmsrd(v, l) asm volatile("mtmsrd %0," __stringify(l) \ + : : "r" (v)) +#define mtmsrd(v) __mtmsrd((v), 0) + +#define mfspr(rn) ({unsigned long rval; \ + asm volatile("mfspr %0," __stringify(rn) \ + : "=r" (rval)); rval;}) +#define mtspr(rn, v) asm volatile("mtspr " __stringify(rn) ",%0" : : "r" (v)) + +#define mftb() ({unsigned long rval; \ + asm volatile("mftb %0" : "=r" (rval)); rval;}) + +#define mttbl(v) asm volatile("mttbl %0":: "r"(v)) +#define mttbu(v) asm volatile("mttbu %0":: "r"(v)) + +#define mfasr() ({unsigned long rval; \ + asm volatile("mfasr %0" : "=r" (rval)); rval;}) + +static inline void set_tb(unsigned int upper, unsigned int lower) +{ + mttbl(0); + mttbu(upper); + mttbl(lower); +} + +#define __get_SP() ({unsigned long sp; \ + asm volatile("mr %0,1": "=r" (sp)); sp;}) + +#ifdef __KERNEL__ + +extern int have_of; +extern u64 ppc64_interrupt_controller; + +struct task_struct; +void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp); +void release_thread(struct task_struct *); + +/* Prepare to copy thread state - unlazy all lazy status */ +extern void prepare_to_copy(struct task_struct *tsk); + +/* Create a new kernel thread. */ +extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); + +/* Lazy FPU handling on uni-processor */ +extern struct task_struct *last_task_used_math; +extern struct task_struct *last_task_used_altivec; + +/* 64-bit user address space is 41-bits (2TBs user VM) */ +#define TASK_SIZE_USER64 (0x0000020000000000UL) + +/* + * 32-bit user address space is 4GB - 1 page + * (this 1 page is needed so referencing of 0xFFFFFFFF generates EFAULT + */ +#define TASK_SIZE_USER32 (0x0000000100000000UL - (1*PAGE_SIZE)) + +#define TASK_SIZE (test_thread_flag(TIF_32BIT) ? \ + TASK_SIZE_USER32 : TASK_SIZE_USER64) + +/* We can't actually tell the TASK_SIZE given just the mm, but default + * to the 64-bit case to make sure that enough gets cleaned up. */ +#define MM_VM_SIZE(mm) TASK_SIZE_USER64 + +/* This decides where the kernel will search for a free chunk of vm + * space during mmap's. + */ +#define TASK_UNMAPPED_BASE_USER32 (PAGE_ALIGN(TASK_SIZE_USER32 / 4)) +#define TASK_UNMAPPED_BASE_USER64 (PAGE_ALIGN(TASK_SIZE_USER64 / 4)) + +#define TASK_UNMAPPED_BASE ((test_thread_flag(TIF_32BIT)||(ppcdebugset(PPCDBG_BINFMT_32ADDR))) ? \ + TASK_UNMAPPED_BASE_USER32 : TASK_UNMAPPED_BASE_USER64 ) + +typedef struct { + unsigned long seg; +} mm_segment_t; + +struct thread_struct { + unsigned long ksp; /* Kernel stack pointer */ + unsigned long ksp_vsid; + struct pt_regs *regs; /* Pointer to saved register state */ + mm_segment_t fs; /* for get_fs() validation */ + double fpr[32]; /* Complete floating point set */ + unsigned long fpscr; /* Floating point status (plus pad) */ + unsigned long fpexc_mode; /* Floating-point exception mode */ + unsigned long start_tb; /* Start purr when proc switched in */ + unsigned long accum_tb; /* Total accumilated purr for process */ + unsigned long vdso_base; /* base of the vDSO library */ +#ifdef CONFIG_ALTIVEC + /* Complete AltiVec register set */ + vector128 vr[32] __attribute((aligned(16))); + /* AltiVec status */ + vector128 vscr __attribute((aligned(16))); + unsigned long vrsave; + int used_vr; /* set if process has used altivec */ +#endif /* CONFIG_ALTIVEC */ +}; + +#define ARCH_MIN_TASKALIGN 16 + +#define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack) + +#define INIT_THREAD { \ + .ksp = INIT_SP, \ + .regs = (struct pt_regs *)INIT_SP - 1, \ + .fs = KERNEL_DS, \ + .fpr = {0}, \ + .fpscr = 0, \ + .fpexc_mode = MSR_FE0|MSR_FE1, \ +} + +/* + * Note: the vm_start and vm_end fields here should *not* + * be in kernel space. (Could vm_end == vm_start perhaps?) + */ +#define IOREMAP_MMAP { &ioremap_mm, 0, 0x1000, NULL, \ + PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, \ + 1, NULL, NULL } + +extern struct mm_struct ioremap_mm; + +/* + * Return saved PC of a blocked thread. For now, this is the "user" PC + */ +#define thread_saved_pc(tsk) \ + ((tsk)->thread.regs? (tsk)->thread.regs->nip: 0) + +unsigned long get_wchan(struct task_struct *p); + +#define KSTK_EIP(tsk) ((tsk)->thread.regs? (tsk)->thread.regs->nip: 0) +#define KSTK_ESP(tsk) ((tsk)->thread.regs? (tsk)->thread.regs->gpr[1]: 0) + +/* Get/set floating-point exception mode */ +#define GET_FPEXC_CTL(tsk, adr) get_fpexc_mode((tsk), (adr)) +#define SET_FPEXC_CTL(tsk, val) set_fpexc_mode((tsk), (val)) + +extern int get_fpexc_mode(struct task_struct *tsk, unsigned long adr); +extern int set_fpexc_mode(struct task_struct *tsk, unsigned int val); + +static inline unsigned int __unpack_fe01(unsigned long msr_bits) +{ + return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8); +} + +static inline unsigned long __pack_fe01(unsigned int fpmode) +{ + return ((fpmode << 10) & MSR_FE0) | ((fpmode << 8) & MSR_FE1); +} + +#define cpu_relax() do { HMT_low(); HMT_medium(); barrier(); } while (0) + +/* + * Prefetch macros. + */ +#define ARCH_HAS_PREFETCH +#define ARCH_HAS_PREFETCHW +#define ARCH_HAS_SPINLOCK_PREFETCH + +static inline void prefetch(const void *x) +{ + __asm__ __volatile__ ("dcbt 0,%0" : : "r" (x)); +} + +static inline void prefetchw(const void *x) +{ + __asm__ __volatile__ ("dcbtst 0,%0" : : "r" (x)); +} + +#define spin_lock_prefetch(x) prefetchw(x) + +#define HAVE_ARCH_PICK_MMAP_LAYOUT + +#endif /* __KERNEL__ */ + +#endif /* __ASSEMBLY__ */ + +/* + * Number of entries in the SLB. If this ever changes we should handle + * it with a use a cpu feature fixup. + */ +#define SLB_NUM_ENTRIES 64 + +#endif /* __ASM_PPC64_PROCESSOR_H */ diff --git a/include/asm-ppc64/prom.h b/include/asm-ppc64/prom.h new file mode 100644 index 000000000000..2440a2c90ae9 --- /dev/null +++ b/include/asm-ppc64/prom.h @@ -0,0 +1,230 @@ +#ifndef _PPC64_PROM_H +#define _PPC64_PROM_H + +/* + * Definitions for talking to the Open Firmware PROM on + * Power Macintosh computers. + * + * Copyright (C) 1996 Paul Mackerras. + * + * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include <linux/proc_fs.h> +#include <asm/atomic.h> + +#define PTRRELOC(x) ((typeof(x))((unsigned long)(x) - offset)) +#define PTRUNRELOC(x) ((typeof(x))((unsigned long)(x) + offset)) +#define RELOC(x) (*PTRRELOC(&(x))) + +/* Definitions used by the flattened device tree */ +#define OF_DT_HEADER 0xd00dfeed /* 4: version, 4: total size */ +#define OF_DT_BEGIN_NODE 0x1 /* Start node: full name */ +#define OF_DT_END_NODE 0x2 /* End node */ +#define OF_DT_PROP 0x3 /* Property: name off, size, content */ +#define OF_DT_END 0x9 + +#define OF_DT_VERSION 1 + +/* + * This is what gets passed to the kernel by prom_init or kexec + * + * The dt struct contains the device tree structure, full pathes and + * property contents. The dt strings contain a separate block with just + * the strings for the property names, and is fully page aligned and + * self contained in a page, so that it can be kept around by the kernel, + * each property name appears only once in this page (cheap compression) + * + * the mem_rsvmap contains a map of reserved ranges of physical memory, + * passing it here instead of in the device-tree itself greatly simplifies + * the job of everybody. It's just a list of u64 pairs (base/size) that + * ends when size is 0 + */ +struct boot_param_header +{ + u32 magic; /* magic word OF_DT_HEADER */ + u32 totalsize; /* total size of DT block */ + u32 off_dt_struct; /* offset to structure */ + u32 off_dt_strings; /* offset to strings */ + u32 off_mem_rsvmap; /* offset to memory reserve map */ + u32 version; /* format version */ + u32 last_comp_version; /* last compatible version */ + /* version 2 fields below */ + u32 boot_cpuid_phys; /* Which physical CPU id we're booting on */ +}; + + + +typedef u32 phandle; +typedef u32 ihandle; + +struct address_range { + unsigned long space; + unsigned long address; + unsigned long size; +}; + +struct interrupt_info { + int line; + int sense; /* +ve/-ve logic, edge or level, etc. */ +}; + +struct pci_address { + u32 a_hi; + u32 a_mid; + u32 a_lo; +}; + +struct isa_address { + u32 a_hi; + u32 a_lo; +}; + +struct isa_range { + struct isa_address isa_addr; + struct pci_address pci_addr; + unsigned int size; +}; + +struct reg_property { + unsigned long address; + unsigned long size; +}; + +struct reg_property32 { + unsigned int address; + unsigned int size; +}; + +struct reg_property64 { + unsigned long address; + unsigned long size; +}; + +struct property { + char *name; + int length; + unsigned char *value; + struct property *next; +}; + +/* NOTE: the device_node contains PCI specific info for pci devices. + * This perhaps could be hung off the device_node with another struct, + * but for now it is directly in the node. The phb ptr is a good + * indication of a real PCI node. Other nodes leave these fields zeroed. + */ +struct pci_controller; +struct iommu_table; + +struct device_node { + char *name; + char *type; + phandle node; + phandle linux_phandle; + int n_addrs; + struct address_range *addrs; + int n_intrs; + struct interrupt_info *intrs; + char *full_name; + + /* PCI stuff probably doesn't belong here */ + int busno; /* for pci devices */ + int bussubno; /* for pci devices */ + int devfn; /* for pci devices */ + int eeh_mode; /* See eeh.h for possible EEH_MODEs */ + int eeh_config_addr; + int pci_ext_config_space; /* for pci devices */ + struct pci_controller *phb; /* for pci devices */ + struct iommu_table *iommu_table; /* for phb's or bridges */ + + struct property *properties; + struct device_node *parent; + struct device_node *child; + struct device_node *sibling; + struct device_node *next; /* next device of same type */ + struct device_node *allnext; /* next in list of all nodes */ + struct proc_dir_entry *pde; /* this node's proc directory */ + struct proc_dir_entry *name_link; /* name symlink */ + struct proc_dir_entry *addr_link; /* addr symlink */ + struct kref kref; + unsigned long _flags; +}; + +extern struct device_node *of_chosen; + +/* flag descriptions */ +#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ + +#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags) +#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags) + +/* + * Until 32-bit ppc can add proc_dir_entries to its device_node + * definition, we cannot refer to pde, name_link, and addr_link + * in arch-independent code. + */ +#define HAVE_ARCH_DEVTREE_FIXUPS + +static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de) +{ + dn->pde = de; +} + +static void inline set_node_name_link(struct device_node *dn, struct proc_dir_entry *de) +{ + dn->name_link = de; +} + +static void inline set_node_addr_link(struct device_node *dn, struct proc_dir_entry *de) +{ + dn->addr_link = de; +} + +/* OBSOLETE: Old stlye node lookup */ +extern struct device_node *find_devices(const char *name); +extern struct device_node *find_type_devices(const char *type); +extern struct device_node *find_path_device(const char *path); +extern struct device_node *find_compatible_devices(const char *type, + const char *compat); +extern struct device_node *find_all_nodes(void); + +/* New style node lookup */ +extern struct device_node *of_find_node_by_name(struct device_node *from, + const char *name); +extern struct device_node *of_find_node_by_type(struct device_node *from, + const char *type); +extern struct device_node *of_find_compatible_node(struct device_node *from, + const char *type, const char *compat); +extern struct device_node *of_find_node_by_path(const char *path); +extern struct device_node *of_find_node_by_phandle(phandle handle); +extern struct device_node *of_find_all_nodes(struct device_node *prev); +extern struct device_node *of_get_parent(const struct device_node *node); +extern struct device_node *of_get_next_child(const struct device_node *node, + struct device_node *prev); +extern struct device_node *of_node_get(struct device_node *node); +extern void of_node_put(struct device_node *node); + +/* For updating the device tree at runtime */ +extern void of_attach_node(struct device_node *); +extern void of_detach_node(const struct device_node *); + +/* Other Prototypes */ +extern unsigned long prom_init(unsigned long, unsigned long, unsigned long, + unsigned long, unsigned long); +extern void finish_device_tree(void); +extern int device_is_compatible(struct device_node *device, const char *); +extern int machine_is_compatible(const char *compat); +extern unsigned char *get_property(struct device_node *node, const char *name, + int *lenp); +extern void print_properties(struct device_node *node); +extern int prom_n_addr_cells(struct device_node* np); +extern int prom_n_size_cells(struct device_node* np); +extern int prom_n_intr_cells(struct device_node* np); +extern void prom_get_irq_senses(unsigned char *senses, int off, int max); +extern void prom_add_property(struct device_node* np, struct property* prop); + +#endif /* _PPC64_PROM_H */ diff --git a/include/asm-ppc64/ptrace-common.h b/include/asm-ppc64/ptrace-common.h new file mode 100644 index 000000000000..af03547f9c7e --- /dev/null +++ b/include/asm-ppc64/ptrace-common.h @@ -0,0 +1,72 @@ +/* + * linux/arch/ppc64/kernel/ptrace-common.h + * + * Copyright (c) 2002 Stephen Rothwell, IBM Coproration + * Extracted from ptrace.c and ptrace32.c + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file README.legal in the main directory of + * this archive for more details. + */ + +#ifndef _PPC64_PTRACE_COMMON_H +#define _PPC64_PTRACE_COMMON_H +/* + * Set of msr bits that gdb can change on behalf of a process. + */ +#define MSR_DEBUGCHANGE (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1) + +/* + * Get contents of register REGNO in task TASK. + */ +static inline unsigned long get_reg(struct task_struct *task, int regno) +{ + unsigned long tmp = 0; + + /* + * Put the correct FP bits in, they might be wrong as a result + * of our lazy FP restore. + */ + if (regno == PT_MSR) { + tmp = ((unsigned long *)task->thread.regs)[PT_MSR]; + tmp |= task->thread.fpexc_mode; + } else if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) { + tmp = ((unsigned long *)task->thread.regs)[regno]; + } + + return tmp; +} + +/* + * Write contents of register REGNO in task TASK. + */ +static inline int put_reg(struct task_struct *task, int regno, + unsigned long data) +{ + if (regno < PT_SOFTE) { + if (regno == PT_MSR) + data = (data & MSR_DEBUGCHANGE) + | (task->thread.regs->msr & ~MSR_DEBUGCHANGE); + ((unsigned long *)task->thread.regs)[regno] = data; + return 0; + } + return -EIO; +} + +static inline void set_single_step(struct task_struct *task) +{ + struct pt_regs *regs = task->thread.regs; + if (regs != NULL) + regs->msr |= MSR_SE; + set_ti_thread_flag(task->thread_info, TIF_SINGLESTEP); +} + +static inline void clear_single_step(struct task_struct *task) +{ + struct pt_regs *regs = task->thread.regs; + if (regs != NULL) + regs->msr &= ~MSR_SE; + clear_ti_thread_flag(task->thread_info, TIF_SINGLESTEP); +} + +#endif /* _PPC64_PTRACE_COMMON_H */ diff --git a/include/asm-ppc64/ptrace.h b/include/asm-ppc64/ptrace.h new file mode 100644 index 000000000000..c96aad28fc08 --- /dev/null +++ b/include/asm-ppc64/ptrace.h @@ -0,0 +1,189 @@ +#ifndef _PPC64_PTRACE_H +#define _PPC64_PTRACE_H + +/* + * Copyright (C) 2001 PPC64 Team, IBM Corp + * + * This struct defines the way the registers are stored on the + * kernel stack during a system call or other kernel entry. + * + * this should only contain volatile regs + * since we can keep non-volatile in the thread_struct + * should set this up when only volatiles are saved + * by intr code. + * + * Since this is going on the stack, *CARE MUST BE TAKEN* to insure + * that the overall structure is a multiple of 16 bytes in length. + * + * Note that the offsets of the fields in this struct correspond with + * the PT_* values below. This simplifies arch/ppc64/kernel/ptrace.c. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef __ASSEMBLY__ +#define PPC_REG unsigned long +struct pt_regs { + PPC_REG gpr[32]; + PPC_REG nip; + PPC_REG msr; + PPC_REG orig_gpr3; /* Used for restarting system calls */ + PPC_REG ctr; + PPC_REG link; + PPC_REG xer; + PPC_REG ccr; + PPC_REG softe; /* Soft enabled/disabled */ + PPC_REG trap; /* Reason for being here */ + PPC_REG dar; /* Fault registers */ + PPC_REG dsisr; + PPC_REG result; /* Result of a system call */ +}; + +#define PPC_REG_32 unsigned int +struct pt_regs32 { + PPC_REG_32 gpr[32]; + PPC_REG_32 nip; + PPC_REG_32 msr; + PPC_REG_32 orig_gpr3; /* Used for restarting system calls */ + PPC_REG_32 ctr; + PPC_REG_32 link; + PPC_REG_32 xer; + PPC_REG_32 ccr; + PPC_REG_32 mq; /* 601 only (not used at present) */ + /* Used on APUS to hold IPL value. */ + PPC_REG_32 trap; /* Reason for being here */ + PPC_REG_32 dar; /* Fault registers */ + PPC_REG_32 dsisr; + PPC_REG_32 result; /* Result of a system call */ +}; + +#define instruction_pointer(regs) ((regs)->nip) +#ifdef CONFIG_SMP +extern unsigned long profile_pc(struct pt_regs *regs); +#else +#define profile_pc(regs) instruction_pointer(regs) +#endif + +#endif /* __ASSEMBLY__ */ + +#define STACK_FRAME_OVERHEAD 112 /* size of minimum stack frame */ + +/* Size of dummy stack frame allocated when calling signal handler. */ +#define __SIGNAL_FRAMESIZE 128 +#define __SIGNAL_FRAMESIZE32 64 + +#define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1) + +#define force_successful_syscall_return() \ + (current_thread_info()->syscall_noerror = 1) + +/* + * We use the least-significant bit of the trap field to indicate + * whether we have saved the full set of registers, or only a + * partial set. A 1 there means the partial set. + */ +#define FULL_REGS(regs) (((regs)->trap & 1) == 0) +#define TRAP(regs) ((regs)->trap & ~0xF) +#define CHECK_FULL_REGS(regs) BUG_ON(regs->trap & 1) + +/* + * Offsets used by 'ptrace' system call interface. + */ +#define PT_R0 0 +#define PT_R1 1 +#define PT_R2 2 +#define PT_R3 3 +#define PT_R4 4 +#define PT_R5 5 +#define PT_R6 6 +#define PT_R7 7 +#define PT_R8 8 +#define PT_R9 9 +#define PT_R10 10 +#define PT_R11 11 +#define PT_R12 12 +#define PT_R13 13 +#define PT_R14 14 +#define PT_R15 15 +#define PT_R16 16 +#define PT_R17 17 +#define PT_R18 18 +#define PT_R19 19 +#define PT_R20 20 +#define PT_R21 21 +#define PT_R22 22 +#define PT_R23 23 +#define PT_R24 24 +#define PT_R25 25 +#define PT_R26 26 +#define PT_R27 27 +#define PT_R28 28 +#define PT_R29 29 +#define PT_R30 30 +#define PT_R31 31 + +#define PT_NIP 32 +#define PT_MSR 33 +#ifdef __KERNEL__ +#define PT_ORIG_R3 34 +#endif +#define PT_CTR 35 +#define PT_LNK 36 +#define PT_XER 37 +#define PT_CCR 38 +#define PT_SOFTE 39 +#define PT_RESULT 43 + +#define PT_FPR0 48 + +/* Kernel and userspace will both use this PT_FPSCR value. 32-bit apps will have + * visibility to the asm-ppc/ptrace.h header instead of this one. + */ +#define PT_FPSCR (PT_FPR0 + 32) /* each FP reg occupies 1 slot in 64-bit space */ + +#ifdef __KERNEL__ +#define PT_FPSCR32 (PT_FPR0 + 2*32 + 1) /* each FP reg occupies 2 32-bit userspace slots */ +#endif + +#define PT_VR0 82 /* each Vector reg occupies 2 slots in 64-bit */ +#define PT_VSCR (PT_VR0 + 32*2 + 1) +#define PT_VRSAVE (PT_VR0 + 33*2) + +#ifdef __KERNEL__ +#define PT_VR0_32 164 /* each Vector reg occupies 4 slots in 32-bit */ +#define PT_VSCR_32 (PT_VR0 + 32*4 + 3) +#define PT_VRSAVE_32 (PT_VR0 + 33*4) +#endif + +/* + * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go. + * The transfer totals 34 quadword. Quadwords 0-31 contain the + * corresponding vector registers. Quadword 32 contains the vscr as the + * last word (offset 12) within that quadword. Quadword 33 contains the + * vrsave as the first word (offset 0) within the quadword. + * + * This definition of the VMX state is compatible with the current PPC32 + * ptrace interface. This allows signal handling and ptrace to use the same + * structures. This also simplifies the implementation of a bi-arch + * (combined (32- and 64-bit) gdb. + */ +#define PTRACE_GETVRREGS 18 +#define PTRACE_SETVRREGS 19 + +/* Additional PTRACE requests implemented on PowerPC. */ +#define PPC_PTRACE_GETREGS 0x99 /* Get GPRs 0 - 31 */ +#define PPC_PTRACE_SETREGS 0x98 /* Set GPRs 0 - 31 */ +#define PPC_PTRACE_GETFPREGS 0x97 /* Get FPRs 0 - 31 */ +#define PPC_PTRACE_SETFPREGS 0x96 /* Set FPRs 0 - 31 */ +#define PPC_PTRACE_PEEKTEXT_3264 0x95 /* Read word at location ADDR on a 64-bit process from a 32-bit process. */ +#define PPC_PTRACE_PEEKDATA_3264 0x94 /* Read word at location ADDR on a 64-bit process from a 32-bit process. */ +#define PPC_PTRACE_POKETEXT_3264 0x93 /* Write word at location ADDR on a 64-bit process from a 32-bit process. */ +#define PPC_PTRACE_POKEDATA_3264 0x92 /* Write word at location ADDR on a 64-bit process from a 32-bit process. */ +#define PPC_PTRACE_PEEKUSR_3264 0x91 /* Read a register (specified by ADDR) out of the "user area" on a 64-bit process from a 32-bit process. */ +#define PPC_PTRACE_POKEUSR_3264 0x90 /* Write DATA into location ADDR within the "user area" on a 64-bit process from a 32-bit process. */ + + +#endif /* _PPC64_PTRACE_H */ diff --git a/include/asm-ppc64/resource.h b/include/asm-ppc64/resource.h new file mode 100644 index 000000000000..add031b9dfd4 --- /dev/null +++ b/include/asm-ppc64/resource.h @@ -0,0 +1,6 @@ +#ifndef _PPC64_RESOURCE_H +#define _PPC64_RESOURCE_H + +#include <asm-generic/resource.h> + +#endif /* _PPC64_RESOURCE_H */ diff --git a/include/asm-ppc64/rtas.h b/include/asm-ppc64/rtas.h new file mode 100644 index 000000000000..a8ab0e9db84a --- /dev/null +++ b/include/asm-ppc64/rtas.h @@ -0,0 +1,243 @@ +#ifndef _PPC64_RTAS_H +#define _PPC64_RTAS_H + +#include <linux/spinlock.h> +#include <asm/page.h> + +/* + * Definitions for talking to the RTAS on CHRP machines. + * + * Copyright (C) 2001 Peter Bergner + * Copyright (C) 2001 PPC 64 Team, IBM Corp + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#define RTAS_UNKNOWN_SERVICE (-1) +#define RTAS_INSTANTIATE_MAX (1UL<<30) /* Don't instantiate rtas at/above this value */ + +/* Buffer size for ppc_rtas system call. */ +#define RTAS_RMOBUF_MAX (64 * 1024) + +/* RTAS return status codes */ +#define RTAS_BUSY -2 /* RTAS Busy */ +#define RTAS_EXTENDED_DELAY_MIN 9900 +#define RTAS_EXTENDED_DELAY_MAX 9905 + +/* + * In general to call RTAS use rtas_token("string") to lookup + * an RTAS token for the given string (e.g. "event-scan"). + * To actually perform the call use + * ret = rtas_call(token, n_in, n_out, ...) + * Where n_in is the number of input parameters and + * n_out is the number of output parameters + * + * If the "string" is invalid on this system, RTAS_UNKNOWN_SERVICE + * will be returned as a token. rtas_call() does look for this + * token and error out gracefully so rtas_call(rtas_token("str"), ...) + * may be safely used for one-shot calls to RTAS. + * + */ + +typedef u32 rtas_arg_t; + +struct rtas_args { + u32 token; + u32 nargs; + u32 nret; + rtas_arg_t args[16]; + rtas_arg_t *rets; /* Pointer to return values in args[]. */ +}; + +extern struct rtas_args rtas_stop_self_args; + +struct rtas_t { + unsigned long entry; /* physical address pointer */ + unsigned long base; /* physical address pointer */ + unsigned long size; + spinlock_t lock; + struct rtas_args args; + struct device_node *dev; /* virtual address pointer */ +}; + +/* RTAS event classes */ +#define RTAS_INTERNAL_ERROR 0x80000000 /* set bit 0 */ +#define RTAS_EPOW_WARNING 0x40000000 /* set bit 1 */ +#define RTAS_POWERMGM_EVENTS 0x20000000 /* set bit 2 */ +#define RTAS_HOTPLUG_EVENTS 0x10000000 /* set bit 3 */ +#define RTAS_EVENT_SCAN_ALL_EVENTS 0xf0000000 + +/* RTAS event severity */ +#define RTAS_SEVERITY_FATAL 0x5 +#define RTAS_SEVERITY_ERROR 0x4 +#define RTAS_SEVERITY_ERROR_SYNC 0x3 +#define RTAS_SEVERITY_WARNING 0x2 +#define RTAS_SEVERITY_EVENT 0x1 +#define RTAS_SEVERITY_NO_ERROR 0x0 + +/* RTAS event disposition */ +#define RTAS_DISP_FULLY_RECOVERED 0x0 +#define RTAS_DISP_LIMITED_RECOVERY 0x1 +#define RTAS_DISP_NOT_RECOVERED 0x2 + +/* RTAS event initiator */ +#define RTAS_INITIATOR_UNKNOWN 0x0 +#define RTAS_INITIATOR_CPU 0x1 +#define RTAS_INITIATOR_PCI 0x2 +#define RTAS_INITIATOR_ISA 0x3 +#define RTAS_INITIATOR_MEMORY 0x4 +#define RTAS_INITIATOR_POWERMGM 0x5 + +/* RTAS event target */ +#define RTAS_TARGET_UNKNOWN 0x0 +#define RTAS_TARGET_CPU 0x1 +#define RTAS_TARGET_PCI 0x2 +#define RTAS_TARGET_ISA 0x3 +#define RTAS_TARGET_MEMORY 0x4 +#define RTAS_TARGET_POWERMGM 0x5 + +/* RTAS event type */ +#define RTAS_TYPE_RETRY 0x01 +#define RTAS_TYPE_TCE_ERR 0x02 +#define RTAS_TYPE_INTERN_DEV_FAIL 0x03 +#define RTAS_TYPE_TIMEOUT 0x04 +#define RTAS_TYPE_DATA_PARITY 0x05 +#define RTAS_TYPE_ADDR_PARITY 0x06 +#define RTAS_TYPE_CACHE_PARITY 0x07 +#define RTAS_TYPE_ADDR_INVALID 0x08 +#define RTAS_TYPE_ECC_UNCORR 0x09 +#define RTAS_TYPE_ECC_CORR 0x0a +#define RTAS_TYPE_EPOW 0x40 +#define RTAS_TYPE_PLATFORM 0xE0 +#define RTAS_TYPE_IO 0xE1 +#define RTAS_TYPE_INFO 0xE2 +#define RTAS_TYPE_DEALLOC 0xE3 +#define RTAS_TYPE_DUMP 0xE4 +/* I don't add PowerMGM events right now, this is a different topic */ +#define RTAS_TYPE_PMGM_POWER_SW_ON 0x60 +#define RTAS_TYPE_PMGM_POWER_SW_OFF 0x61 +#define RTAS_TYPE_PMGM_LID_OPEN 0x62 +#define RTAS_TYPE_PMGM_LID_CLOSE 0x63 +#define RTAS_TYPE_PMGM_SLEEP_BTN 0x64 +#define RTAS_TYPE_PMGM_WAKE_BTN 0x65 +#define RTAS_TYPE_PMGM_BATTERY_WARN 0x66 +#define RTAS_TYPE_PMGM_BATTERY_CRIT 0x67 +#define RTAS_TYPE_PMGM_SWITCH_TO_BAT 0x68 +#define RTAS_TYPE_PMGM_SWITCH_TO_AC 0x69 +#define RTAS_TYPE_PMGM_KBD_OR_MOUSE 0x6a +#define RTAS_TYPE_PMGM_ENCLOS_OPEN 0x6b +#define RTAS_TYPE_PMGM_ENCLOS_CLOSED 0x6c +#define RTAS_TYPE_PMGM_RING_INDICATE 0x6d +#define RTAS_TYPE_PMGM_LAN_ATTENTION 0x6e +#define RTAS_TYPE_PMGM_TIME_ALARM 0x6f +#define RTAS_TYPE_PMGM_CONFIG_CHANGE 0x70 +#define RTAS_TYPE_PMGM_SERVICE_PROC 0x71 + +struct rtas_error_log { + unsigned long version:8; /* Architectural version */ + unsigned long severity:3; /* Severity level of error */ + unsigned long disposition:2; /* Degree of recovery */ + unsigned long extended:1; /* extended log present? */ + unsigned long /* reserved */ :2; /* Reserved for future use */ + unsigned long initiator:4; /* Initiator of event */ + unsigned long target:4; /* Target of failed operation */ + unsigned long type:8; /* General event or error*/ + unsigned long extended_log_length:32; /* length in bytes */ + unsigned char buffer[1]; +}; + +struct flash_block { + char *data; + unsigned long length; +}; + +/* This struct is very similar but not identical to + * that needed by the rtas flash update. + * All we need to do for rtas is rewrite num_blocks + * into a version/length and translate the pointers + * to absolute. + */ +#define FLASH_BLOCKS_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct flash_block)) +struct flash_block_list { + unsigned long num_blocks; + struct flash_block_list *next; + struct flash_block blocks[FLASH_BLOCKS_PER_NODE]; +}; +struct flash_block_list_header { /* just the header of flash_block_list */ + unsigned long num_blocks; + struct flash_block_list *next; +}; +extern struct flash_block_list_header rtas_firmware_flash_list; + +extern struct rtas_t rtas; + +extern void enter_rtas(unsigned long); +extern int rtas_token(const char *service); +extern int rtas_call(int token, int, int, int *, ...); +extern void call_rtas_display_status(unsigned char); +extern void rtas_restart(char *cmd); +extern void rtas_power_off(void); +extern void rtas_halt(void); +extern void rtas_os_term(char *str); +extern int rtas_get_sensor(int sensor, int index, int *state); +extern int rtas_get_power_level(int powerdomain, int *level); +extern int rtas_set_power_level(int powerdomain, int level, int *setlevel); +extern int rtas_set_indicator(int indicator, int index, int new_value); +extern void rtas_initialize(void); + +/* Given an RTAS status code of 9900..9905 compute the hinted delay */ +unsigned int rtas_extended_busy_delay_time(int status); +static inline int rtas_is_extended_busy(int status) +{ + return status >= 9900 && status <= 9909; +} + +extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal); + +/* Error types logged. */ +#define ERR_FLAG_ALREADY_LOGGED 0x0 +#define ERR_FLAG_BOOT 0x1 /* log was pulled from NVRAM on boot */ +#define ERR_TYPE_RTAS_LOG 0x2 /* from rtas event-scan */ +#define ERR_TYPE_KERNEL_PANIC 0x4 /* from panic() */ + +/* All the types and not flags */ +#define ERR_TYPE_MASK (ERR_TYPE_RTAS_LOG | ERR_TYPE_KERNEL_PANIC) + +#define RTAS_DEBUG KERN_DEBUG "RTAS: " + +#define RTAS_ERROR_LOG_MAX 2048 + +/* + * Return the firmware-specified size of the error log buffer + * for all rtas calls that require an error buffer argument. + * This includes 'check-exception' and 'rtas-last-error'. + */ +extern int rtas_get_error_log_max(void); + +/* Event Scan Parameters */ +#define EVENT_SCAN_ALL_EVENTS 0xf0000000 +#define SURVEILLANCE_TOKEN 9000 +#define LOG_NUMBER 64 /* must be a power of two */ +#define LOG_NUMBER_MASK (LOG_NUMBER-1) + +/* Some RTAS ops require a data buffer and that buffer must be < 4G. + * Rather than having a memory allocator, just use this buffer + * (get the lock first), make the RTAS call. Copy the data instead + * of holding the buffer for long. + */ + +#define RTAS_DATA_BUF_SIZE 4096 +extern spinlock_t rtas_data_buf_lock; +extern char rtas_data_buf[RTAS_DATA_BUF_SIZE]; + +extern void rtas_stop_self(void); + +/* RMO buffer reserved for user-space RTAS use */ +extern unsigned long rtas_rmo_buf; + +#define GLOBAL_INTERRUPT_QUEUE 9005 + +#endif /* _PPC64_RTAS_H */ diff --git a/include/asm-ppc64/rwsem.h b/include/asm-ppc64/rwsem.h new file mode 100644 index 000000000000..bd5c2f093575 --- /dev/null +++ b/include/asm-ppc64/rwsem.h @@ -0,0 +1,167 @@ +/* + * include/asm-ppc64/rwsem.h: R/W semaphores for PPC using the stuff + * in lib/rwsem.c. Adapted largely from include/asm-i386/rwsem.h + * by Paul Mackerras <paulus@samba.org>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _PPC64_RWSEM_H +#define _PPC64_RWSEM_H + +#ifdef __KERNEL__ +#include <linux/list.h> +#include <linux/spinlock.h> +#include <asm/atomic.h> +#include <asm/system.h> + +/* + * the semaphore definition + */ +struct rw_semaphore { + /* XXX this should be able to be an atomic_t -- paulus */ + signed int count; +#define RWSEM_UNLOCKED_VALUE 0x00000000 +#define RWSEM_ACTIVE_BIAS 0x00000001 +#define RWSEM_ACTIVE_MASK 0x0000ffff +#define RWSEM_WAITING_BIAS (-0x00010000) +#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS +#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) + spinlock_t wait_lock; + struct list_head wait_list; +#if RWSEM_DEBUG + int debug; +#endif +}; + +/* + * initialisation + */ +#if RWSEM_DEBUG +#define __RWSEM_DEBUG_INIT , 0 +#else +#define __RWSEM_DEBUG_INIT /* */ +#endif + +#define __RWSEM_INITIALIZER(name) \ + { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \ + LIST_HEAD_INIT((name).wait_list) \ + __RWSEM_DEBUG_INIT } + +#define DECLARE_RWSEM(name) \ + struct rw_semaphore name = __RWSEM_INITIALIZER(name) + +extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem); +extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem); +extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem); +extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem); + +static inline void init_rwsem(struct rw_semaphore *sem) +{ + sem->count = RWSEM_UNLOCKED_VALUE; + spin_lock_init(&sem->wait_lock); + INIT_LIST_HEAD(&sem->wait_list); +#if RWSEM_DEBUG + sem->debug = 0; +#endif +} + +/* + * lock for reading + */ +static inline void __down_read(struct rw_semaphore *sem) +{ + if (unlikely(atomic_inc_return((atomic_t *)(&sem->count)) <= 0)) + rwsem_down_read_failed(sem); +} + +static inline int __down_read_trylock(struct rw_semaphore *sem) +{ + int tmp; + + while ((tmp = sem->count) >= 0) { + if (tmp == cmpxchg(&sem->count, tmp, + tmp + RWSEM_ACTIVE_READ_BIAS)) { + return 1; + } + } + return 0; +} + +/* + * lock for writing + */ +static inline void __down_write(struct rw_semaphore *sem) +{ + int tmp; + + tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS, + (atomic_t *)(&sem->count)); + if (unlikely(tmp != RWSEM_ACTIVE_WRITE_BIAS)) + rwsem_down_write_failed(sem); +} + +static inline int __down_write_trylock(struct rw_semaphore *sem) +{ + int tmp; + + tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE, + RWSEM_ACTIVE_WRITE_BIAS); + return tmp == RWSEM_UNLOCKED_VALUE; +} + +/* + * unlock after reading + */ +static inline void __up_read(struct rw_semaphore *sem) +{ + int tmp; + + tmp = atomic_dec_return((atomic_t *)(&sem->count)); + if (unlikely(tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0)) + rwsem_wake(sem); +} + +/* + * unlock after writing + */ +static inline void __up_write(struct rw_semaphore *sem) +{ + if (unlikely(atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS, + (atomic_t *)(&sem->count)) < 0)) + rwsem_wake(sem); +} + +/* + * implement atomic add functionality + */ +static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem) +{ + atomic_add(delta, (atomic_t *)(&sem->count)); +} + +/* + * downgrade write lock to read lock + */ +static inline void __downgrade_write(struct rw_semaphore *sem) +{ + int tmp; + + tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count)); + if (tmp < 0) + rwsem_downgrade_wake(sem); +} + +/* + * implement exchange and add functionality + */ +static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem) +{ + return atomic_add_return(delta, (atomic_t *)(&sem->count)); +} + +#endif /* __KERNEL__ */ +#endif /* _PPC_RWSEM_XADD_H */ diff --git a/include/asm-ppc64/scatterlist.h b/include/asm-ppc64/scatterlist.h new file mode 100644 index 000000000000..cecce6c6dfbb --- /dev/null +++ b/include/asm-ppc64/scatterlist.h @@ -0,0 +1,31 @@ +#ifndef _PPC64_SCATTERLIST_H +#define _PPC64_SCATTERLIST_H + +/* + * Copyright (C) 2001 PPC64 Team, IBM Corp + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/types.h> +#include <asm/dma.h> + +struct scatterlist { + struct page *page; + unsigned int offset; + unsigned int length; + + /* For TCE support */ + u32 dma_address; + u32 dma_length; +}; + +#define sg_dma_address(sg) ((sg)->dma_address) +#define sg_dma_len(sg) ((sg)->dma_length) + +#define ISA_DMA_THRESHOLD (~0UL) + +#endif /* !(_PPC64_SCATTERLIST_H) */ diff --git a/include/asm-ppc64/seccomp.h b/include/asm-ppc64/seccomp.h new file mode 100644 index 000000000000..c130c334bda1 --- /dev/null +++ b/include/asm-ppc64/seccomp.h @@ -0,0 +1,21 @@ +#ifndef _ASM_SECCOMP_H + +#include <linux/thread_info.h> /* already defines TIF_32BIT */ + +#ifndef TIF_32BIT +#error "unexpected TIF_32BIT on ppc64" +#endif + +#include <linux/unistd.h> + +#define __NR_seccomp_read __NR_read +#define __NR_seccomp_write __NR_write +#define __NR_seccomp_exit __NR_exit +#define __NR_seccomp_sigreturn __NR_rt_sigreturn + +#define __NR_seccomp_read_32 __NR_read +#define __NR_seccomp_write_32 __NR_write +#define __NR_seccomp_exit_32 __NR_exit +#define __NR_seccomp_sigreturn_32 __NR_sigreturn + +#endif /* _ASM_SECCOMP_H */ diff --git a/include/asm-ppc64/sections.h b/include/asm-ppc64/sections.h new file mode 100644 index 000000000000..308ca6f5ced2 --- /dev/null +++ b/include/asm-ppc64/sections.h @@ -0,0 +1,29 @@ +#ifndef _PPC64_SECTIONS_H +#define _PPC64_SECTIONS_H + +extern char _end[]; + +#include <asm-generic/sections.h> + +#define __pmac +#define __pmacdata + +#define __prep +#define __prepdata + +#define __chrp +#define __chrpdata + +#define __openfirmware +#define __openfirmwaredata + + +static inline int in_kernel_text(unsigned long addr) +{ + if (addr >= (unsigned long)_stext && addr < (unsigned long)__init_end) + return 1; + + return 0; +} + +#endif diff --git a/include/asm-ppc64/segment.h b/include/asm-ppc64/segment.h new file mode 100644 index 000000000000..d80fb68cc79e --- /dev/null +++ b/include/asm-ppc64/segment.h @@ -0,0 +1,6 @@ +#ifndef __PPC64_SEGMENT_H +#define __PPC64_SEGMENT_H + +/* Only here because we have some old header files that expect it.. */ + +#endif /* __PPC64_SEGMENT_H */ diff --git a/include/asm-ppc64/semaphore.h b/include/asm-ppc64/semaphore.h new file mode 100644 index 000000000000..aefe7753ea41 --- /dev/null +++ b/include/asm-ppc64/semaphore.h @@ -0,0 +1,98 @@ +#ifndef _PPC64_SEMAPHORE_H +#define _PPC64_SEMAPHORE_H + +/* + * Remove spinlock-based RW semaphores; RW semaphore definitions are + * now in rwsem.h and we use the generic lib/rwsem.c implementation. + * Rework semaphores to use atomic_dec_if_positive. + * -- Paul Mackerras (paulus@samba.org) + */ + +#ifdef __KERNEL__ + +#include <asm/atomic.h> +#include <asm/system.h> +#include <linux/wait.h> +#include <linux/rwsem.h> + +struct semaphore { + /* + * Note that any negative value of count is equivalent to 0, + * but additionally indicates that some process(es) might be + * sleeping on `wait'. + */ + atomic_t count; + wait_queue_head_t wait; +}; + +#define __SEMAPHORE_INITIALIZER(name, n) \ +{ \ + .count = ATOMIC_INIT(n), \ + .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ +} + +#define __MUTEX_INITIALIZER(name) \ + __SEMAPHORE_INITIALIZER(name, 1) + +#define __DECLARE_SEMAPHORE_GENERIC(name, count) \ + struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) + +#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name, 1) +#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name, 0) + +static inline void sema_init (struct semaphore *sem, int val) +{ + atomic_set(&sem->count, val); + init_waitqueue_head(&sem->wait); +} + +static inline void init_MUTEX (struct semaphore *sem) +{ + sema_init(sem, 1); +} + +static inline void init_MUTEX_LOCKED (struct semaphore *sem) +{ + sema_init(sem, 0); +} + +extern void __down(struct semaphore * sem); +extern int __down_interruptible(struct semaphore * sem); +extern void __up(struct semaphore * sem); + +static inline void down(struct semaphore * sem) +{ + might_sleep(); + + /* + * Try to get the semaphore, take the slow path if we fail. + */ + if (unlikely(atomic_dec_return(&sem->count) < 0)) + __down(sem); +} + +static inline int down_interruptible(struct semaphore * sem) +{ + int ret = 0; + + might_sleep(); + + if (unlikely(atomic_dec_return(&sem->count) < 0)) + ret = __down_interruptible(sem); + return ret; +} + +static inline int down_trylock(struct semaphore * sem) +{ + return atomic_dec_if_positive(&sem->count) < 0; +} + +static inline void up(struct semaphore * sem) +{ + if (unlikely(atomic_inc_return(&sem->count) <= 0)) + __up(sem); +} + +#endif /* __KERNEL__ */ + +#endif /* !(_PPC64_SEMAPHORE_H) */ diff --git a/include/asm-ppc64/sembuf.h b/include/asm-ppc64/sembuf.h new file mode 100644 index 000000000000..172e59000767 --- /dev/null +++ b/include/asm-ppc64/sembuf.h @@ -0,0 +1,27 @@ +#ifndef _PPC64_SEMBUF_H +#define _PPC64_SEMBUF_H + +/* + * The semid64_ds structure for PPC architecture. + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Pad space is left for: + * - 2 miscellaneous 64-bit values + */ + +struct semid64_ds { + struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ + __kernel_time_t sem_otime; /* last semop time */ + __kernel_time_t sem_ctime; /* last change time */ + unsigned long sem_nsems; /* no. of semaphores in array */ + + unsigned long __unused1; + unsigned long __unused2; +}; + +#endif /* _PPC64_SEMBUF_H */ diff --git a/include/asm-ppc64/serial.h b/include/asm-ppc64/serial.h new file mode 100644 index 000000000000..d6bcb79b7d7b --- /dev/null +++ b/include/asm-ppc64/serial.h @@ -0,0 +1,23 @@ +/* + * include/asm-ppc64/serial.h + */ +#ifndef _PPC64_SERIAL_H +#define _PPC64_SERIAL_H + +/* + * This assumes you have a 1.8432 MHz clock for your UART. + * + * It'd be nice if someone built a serial card with a 24.576 MHz + * clock, since the 16550A is capable of handling a top speed of 1.5 + * megabits/second; but this requires the faster clock. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +/* Default baud base if not found in device-tree */ +#define BASE_BAUD ( 1843200 / 16 ) + +#endif /* _PPC64_SERIAL_H */ diff --git a/include/asm-ppc64/setup.h b/include/asm-ppc64/setup.h new file mode 100644 index 000000000000..b257b8348c73 --- /dev/null +++ b/include/asm-ppc64/setup.h @@ -0,0 +1,6 @@ +#ifndef _PPC_SETUP_H +#define _PPC_SETUP_H + +#define COMMAND_LINE_SIZE 512 + +#endif /* _PPC_SETUP_H */ diff --git a/include/asm-ppc64/shmbuf.h b/include/asm-ppc64/shmbuf.h new file mode 100644 index 000000000000..02e99d6ec925 --- /dev/null +++ b/include/asm-ppc64/shmbuf.h @@ -0,0 +1,43 @@ +#ifndef _PPC64_SHMBUF_H +#define _PPC64_SHMBUF_H + +/* + * The shmid64_ds structure for PPC64 architecture. + * Note extra padding because this structure is passed back and forth + * between kernel and user space. + * + * Pad space is left for: + * - 2 miscellaneous 64-bit values + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +struct shmid64_ds { + struct ipc64_perm shm_perm; /* operation perms */ + __kernel_time_t shm_atime; /* last attach time */ + __kernel_time_t shm_dtime; /* last detach time */ + __kernel_time_t shm_ctime; /* last change time */ + size_t shm_segsz; /* size of segment (bytes) */ + __kernel_pid_t shm_cpid; /* pid of creator */ + __kernel_pid_t shm_lpid; /* pid of last operator */ + unsigned long shm_nattch; /* no. of current attaches */ + unsigned long __unused1; + unsigned long __unused2; +}; + +struct shminfo64 { + unsigned long shmmax; + unsigned long shmmin; + unsigned long shmmni; + unsigned long shmseg; + unsigned long shmall; + unsigned long __unused1; + unsigned long __unused2; + unsigned long __unused3; + unsigned long __unused4; +}; + +#endif /* _PPC64_SHMBUF_H */ diff --git a/include/asm-ppc64/shmparam.h b/include/asm-ppc64/shmparam.h new file mode 100644 index 000000000000..b2825ceff05e --- /dev/null +++ b/include/asm-ppc64/shmparam.h @@ -0,0 +1,13 @@ +#ifndef _PPC64_SHMPARAM_H +#define _PPC64_SHMPARAM_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */ + +#endif /* _PPC64_SHMPARAM_H */ diff --git a/include/asm-ppc64/sigcontext.h b/include/asm-ppc64/sigcontext.h new file mode 100644 index 000000000000..6f8aee768c5e --- /dev/null +++ b/include/asm-ppc64/sigcontext.h @@ -0,0 +1,47 @@ +#ifndef _ASM_PPC64_SIGCONTEXT_H +#define _ASM_PPC64_SIGCONTEXT_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include <linux/compiler.h> +#include <asm/ptrace.h> +#include <asm/elf.h> + + +struct sigcontext { + unsigned long _unused[4]; + int signal; + int _pad0; + unsigned long handler; + unsigned long oldmask; + struct pt_regs __user *regs; + elf_gregset_t gp_regs; + elf_fpregset_t fp_regs; +/* + * To maintain compatibility with current implementations the sigcontext is + * extended by appending a pointer (v_regs) to a quadword type (elf_vrreg_t) + * followed by an unstructured (vmx_reserve) field of 69 doublewords. This + * allows the array of vector registers to be quadword aligned independent of + * the alignment of the containing sigcontext or ucontext. It is the + * responsibility of the code setting the sigcontext to set this pointer to + * either NULL (if this processor does not support the VMX feature) or the + * address of the first quadword within the allocated (vmx_reserve) area. + * + * The pointer (v_regs) of vector type (elf_vrreg_t) is type compatible with + * an array of 34 quadword entries (elf_vrregset_t). The entries with + * indexes 0-31 contain the corresponding vector registers. The entry with + * index 32 contains the vscr as the last word (offset 12) within the + * quadword. This allows the vscr to be stored as either a quadword (since + * it must be copied via a vector register to/from storage) or as a word. + * The entry with index 33 contains the vrsave as the first word (offset 0) + * within the quadword. + */ + elf_vrreg_t __user *v_regs; + long vmx_reserve[ELF_NVRREG+ELF_NVRREG+1]; +}; + +#endif /* _ASM_PPC64_SIGCONTEXT_H */ diff --git a/include/asm-ppc64/siginfo.h b/include/asm-ppc64/siginfo.h new file mode 100644 index 000000000000..3a7c23dcb5aa --- /dev/null +++ b/include/asm-ppc64/siginfo.h @@ -0,0 +1,16 @@ +#ifndef _PPC64_SIGINFO_H +#define _PPC64_SIGINFO_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) +#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3) + +#include <asm-generic/siginfo.h> + +#endif /* _PPC64_SIGINFO_H */ diff --git a/include/asm-ppc64/signal.h b/include/asm-ppc64/signal.h new file mode 100644 index 000000000000..fe5401adb41b --- /dev/null +++ b/include/asm-ppc64/signal.h @@ -0,0 +1,159 @@ +#ifndef _ASMPPC64_SIGNAL_H +#define _ASMPPC64_SIGNAL_H + +#include <linux/types.h> +#include <linux/compiler.h> +#include <asm/siginfo.h> + +/* Avoid too many header ordering problems. */ +struct siginfo; + +#define _NSIG 64 +#define _NSIG_BPW 64 +#define _NSIG_WORDS (_NSIG / _NSIG_BPW) + +typedef unsigned long old_sigset_t; /* at least 32 bits */ + +typedef struct { + unsigned long sig[_NSIG_WORDS]; +} sigset_t; + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGIOT 6 +#define SIGBUS 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGUSR1 10 +#define SIGSEGV 11 +#define SIGUSR2 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGSTKFLT 16 +#define SIGCHLD 17 +#define SIGCONT 18 +#define SIGSTOP 19 +#define SIGTSTP 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGURG 23 +#define SIGXCPU 24 +#define SIGXFSZ 25 +#define SIGVTALRM 26 +#define SIGPROF 27 +#define SIGWINCH 28 +#define SIGIO 29 +#define SIGPOLL SIGIO +/* +#define SIGLOST 29 +*/ +#define SIGPWR 30 +#define SIGSYS 31 +#define SIGUNUSED 31 + +/* These should not be considered constants from userland. */ +#define SIGRTMIN 32 +#define SIGRTMAX _NSIG + +/* + * SA_FLAGS values: + * + * SA_ONSTACK is not currently supported, but will allow sigaltstack(2). + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the + * SA_RESTART flag to get restarting signals (which were the default long ago) + * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. + * SA_RESETHAND clears the handler when the signal is delivered. + * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. + * SA_NODEFER prevents the current signal from being masked in the handler. + * + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single + * Unix names RESETHAND and NODEFER respectively. + */ +#define SA_NOCLDSTOP 0x00000001u +#define SA_NOCLDWAIT 0x00000002u +#define SA_SIGINFO 0x00000004u +#define SA_ONSTACK 0x08000000u +#define SA_RESTART 0x10000000u +#define SA_NODEFER 0x40000000u +#define SA_RESETHAND 0x80000000u + +#define SA_NOMASK SA_NODEFER +#define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000u /* dummy -- ignored */ + +#define SA_RESTORER 0x04000000u + +/* + * sigaltstack controls + */ +#define SS_ONSTACK 1 +#define SS_DISABLE 2 + +#define MINSIGSTKSZ 2048 +#define SIGSTKSZ 8192 +#ifdef __KERNEL__ + +/* + * These values of sa_flags are used only by the kernel as part of the + * irq handling routines. + * + * SA_INTERRUPT is also used by the irq handling routines. + * SA_SHIRQ is for shared interrupt support on PCI and EISA. + */ +#define SA_PROBE SA_ONESHOT +#define SA_SAMPLE_RANDOM SA_RESTART +#define SA_SHIRQ 0x04000000 +#endif + +#define SIG_BLOCK 0 /* for blocking signals */ +#define SIG_UNBLOCK 1 /* for unblocking signals */ +#define SIG_SETMASK 2 /* for setting the signal mask */ + +/* Type of a signal handler. */ +typedef void __sigfunction(int); +typedef __sigfunction __user * __sighandler_t; + +/* Type of the restorer function */ +typedef void __sigrestorer(void); +typedef __sigrestorer __user * __sigrestorer_t; + +#define SIG_DFL ((__sighandler_t)0) /* default signal handling */ +#define SIG_IGN ((__sighandler_t)1) /* ignore signal */ +#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */ + +struct old_sigaction { + __sighandler_t sa_handler; + old_sigset_t sa_mask; + unsigned long sa_flags; + __sigrestorer_t sa_restorer; +}; + +struct sigaction { + __sighandler_t sa_handler; + unsigned long sa_flags; + __sigrestorer_t sa_restorer; + sigset_t sa_mask; /* mask last for extensibility */ +}; + +struct k_sigaction { + struct sigaction sa; +}; + +typedef struct sigaltstack { + void __user *ss_sp; + int ss_flags; + size_t ss_size; +} stack_t; + +struct pt_regs; +struct timespec; +extern int do_signal(sigset_t *oldset, struct pt_regs *regs); +extern int do_signal32(sigset_t *oldset, struct pt_regs *regs); +#define ptrace_signal_deliver(regs, cookie) do { } while (0) + +#endif /* _ASMPPC64_SIGNAL_H */ diff --git a/include/asm-ppc64/smp.h b/include/asm-ppc64/smp.h new file mode 100644 index 000000000000..c8646fa999c2 --- /dev/null +++ b/include/asm-ppc64/smp.h @@ -0,0 +1,91 @@ +/* + * smp.h: PPC64 specific SMP code. + * + * Original was a copy of sparc smp.h. Now heavily modified + * for PPC. + * + * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1996-2001 Cort Dougan <cort@fsmlabs.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifdef __KERNEL__ +#ifndef _PPC64_SMP_H +#define _PPC64_SMP_H + +#include <linux/config.h> +#include <linux/threads.h> +#include <linux/cpumask.h> +#include <linux/kernel.h> + +#ifndef __ASSEMBLY__ + +#include <asm/paca.h> + +extern int boot_cpuid; +extern int boot_cpuid_phys; + +extern void cpu_die(void); + +#ifdef CONFIG_SMP + +extern void smp_send_debugger_break(int cpu); +struct pt_regs; +extern void smp_message_recv(int, struct pt_regs *); + +#ifdef CONFIG_HOTPLUG_CPU +extern void fixup_irqs(cpumask_t map); +int generic_cpu_disable(void); +int generic_cpu_enable(unsigned int cpu); +void generic_cpu_die(unsigned int cpu); +void generic_mach_cpu_die(void); +#endif + +#define __smp_processor_id() (get_paca()->paca_index) +#define hard_smp_processor_id() (get_paca()->hw_cpu_id) + +extern cpumask_t cpu_sibling_map[NR_CPUS]; + +/* Since OpenPIC has only 4 IPIs, we use slightly different message numbers. + * + * Make sure this matches openpic_request_IPIs in open_pic.c, or what shows up + * in /proc/interrupts will be wrong!!! --Troy */ +#define PPC_MSG_CALL_FUNCTION 0 +#define PPC_MSG_RESCHEDULE 1 +/* This is unused now */ +#if 0 +#define PPC_MSG_MIGRATE_TASK 2 +#endif +#define PPC_MSG_DEBUGGER_BREAK 3 + +void smp_init_iSeries(void); +void smp_init_pSeries(void); + +extern int __cpu_disable(void); +extern void __cpu_die(unsigned int cpu); +#endif /* CONFIG_SMP */ + +#define get_hard_smp_processor_id(CPU) (paca[(CPU)].hw_cpu_id) +#define set_hard_smp_processor_id(CPU, VAL) \ + do { (paca[(CPU)].hw_cpu_id = (VAL)); } while (0) + +extern int smt_enabled_at_boot; + +extern int smp_mpic_probe(void); +extern void smp_mpic_setup_cpu(int cpu); +extern void smp_mpic_message_pass(int target, int msg); +extern void smp_generic_kick_cpu(int nr); + +extern void smp_generic_give_timebase(void); +extern void smp_generic_take_timebase(void); + +extern struct smp_ops_t *smp_ops; + +#endif /* __ASSEMBLY__ */ + +#endif /* !(_PPC64_SMP_H) */ +#endif /* __KERNEL__ */ diff --git a/include/asm-ppc64/smu.h b/include/asm-ppc64/smu.h new file mode 100644 index 000000000000..10b4397af9aa --- /dev/null +++ b/include/asm-ppc64/smu.h @@ -0,0 +1,22 @@ +/* + * Definitions for talking to the SMU chip in newer G5 PowerMacs + */ + +#include <linux/config.h> + +/* + * Basic routines for use by architecture. To be extended as + * we understand more of the chip + */ +extern int smu_init(void); +extern int smu_present(void); +extern void smu_shutdown(void); +extern void smu_restart(void); +extern int smu_get_rtc_time(struct rtc_time *time); +extern int smu_set_rtc_time(struct rtc_time *time); + +/* + * SMU command buffer absolute address, exported by pmac_setup, + * this is allocated very early during boot. + */ +extern unsigned long smu_cmdbuf_abs; diff --git a/include/asm-ppc64/socket.h b/include/asm-ppc64/socket.h new file mode 100644 index 000000000000..59e00dfc8b8e --- /dev/null +++ b/include/asm-ppc64/socket.h @@ -0,0 +1,57 @@ +#ifndef _ASM_SOCKET_H +#define _ASM_SOCKET_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <asm/sockios.h> + +/* For setsockoptions(2) */ +#define SOL_SOCKET 1 + +#define SO_DEBUG 1 +#define SO_REUSEADDR 2 +#define SO_TYPE 3 +#define SO_ERROR 4 +#define SO_DONTROUTE 5 +#define SO_BROADCAST 6 +#define SO_SNDBUF 7 +#define SO_RCVBUF 8 +#define SO_KEEPALIVE 9 +#define SO_OOBINLINE 10 +#define SO_NO_CHECK 11 +#define SO_PRIORITY 12 +#define SO_LINGER 13 +#define SO_BSDCOMPAT 14 +/* To add :#define SO_REUSEPORT 15 */ +#define SO_RCVLOWAT 16 +#define SO_SNDLOWAT 17 +#define SO_RCVTIMEO 18 +#define SO_SNDTIMEO 19 +#define SO_PASSCRED 20 +#define SO_PEERCRED 21 + +/* Security levels - as per NRL IPv6 - don't actually do anything */ +#define SO_SECURITY_AUTHENTICATION 22 +#define SO_SECURITY_ENCRYPTION_TRANSPORT 23 +#define SO_SECURITY_ENCRYPTION_NETWORK 24 + +#define SO_BINDTODEVICE 25 + +/* Socket filtering */ +#define SO_ATTACH_FILTER 26 +#define SO_DETACH_FILTER 27 + +#define SO_PEERNAME 28 +#define SO_TIMESTAMP 29 +#define SCM_TIMESTAMP SO_TIMESTAMP + +#define SO_ACCEPTCONN 30 + +#define SO_PEERSEC 31 + +#endif /* _ASM_SOCKET_H */ diff --git a/include/asm-ppc64/sockios.h b/include/asm-ppc64/sockios.h new file mode 100644 index 000000000000..6bd1a22af4f6 --- /dev/null +++ b/include/asm-ppc64/sockios.h @@ -0,0 +1,19 @@ +#ifndef _ASM_PPC64_SOCKIOS_H +#define _ASM_PPC64_SOCKIOS_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +/* Socket-level I/O control calls. */ +#define FIOSETOWN 0x8901 +#define SIOCSPGRP 0x8902 +#define FIOGETOWN 0x8903 +#define SIOCGPGRP 0x8904 +#define SIOCATMARK 0x8905 +#define SIOCGSTAMP 0x8906 /* Get stamp */ + +#endif /* _ASM_PPC64_SOCKIOS_H */ diff --git a/include/asm-ppc64/spinlock.h b/include/asm-ppc64/spinlock.h new file mode 100644 index 000000000000..a9b2a1162cf7 --- /dev/null +++ b/include/asm-ppc64/spinlock.h @@ -0,0 +1,260 @@ +#ifndef __ASM_SPINLOCK_H +#define __ASM_SPINLOCK_H + +/* + * Simple spin lock operations. + * + * Copyright (C) 2001-2004 Paul Mackerras <paulus@au.ibm.com>, IBM + * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM + * Copyright (C) 2002 Dave Engebretsen <engebret@us.ibm.com>, IBM + * Rework to support virtual processors + * + * Type of int is used as a full 64b word is not necessary. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include <linux/config.h> +#include <asm/paca.h> +#include <asm/hvcall.h> +#include <asm/iSeries/HvCall.h> + +typedef struct { + volatile unsigned int lock; +#ifdef CONFIG_PREEMPT + unsigned int break_lock; +#endif +} spinlock_t; + +typedef struct { + volatile signed int lock; +#ifdef CONFIG_PREEMPT + unsigned int break_lock; +#endif +} rwlock_t; + +#ifdef __KERNEL__ +#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } + +#define spin_is_locked(x) ((x)->lock != 0) +#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0) + +static __inline__ void _raw_spin_unlock(spinlock_t *lock) +{ + __asm__ __volatile__("lwsync # spin_unlock": : :"memory"); + lock->lock = 0; +} + +/* + * On a system with shared processors (that is, where a physical + * processor is multiplexed between several virtual processors), + * there is no point spinning on a lock if the holder of the lock + * isn't currently scheduled on a physical processor. Instead + * we detect this situation and ask the hypervisor to give the + * rest of our timeslice to the lock holder. + * + * So that we can tell which virtual processor is holding a lock, + * we put 0x80000000 | smp_processor_id() in the lock when it is + * held. Conveniently, we have a word in the paca that holds this + * value. + */ + +#if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES) +/* We only yield to the hypervisor if we are in shared processor mode */ +#define SHARED_PROCESSOR (get_paca()->lppaca.shared_proc) +extern void __spin_yield(spinlock_t *lock); +extern void __rw_yield(rwlock_t *lock); +#else /* SPLPAR || ISERIES */ +#define __spin_yield(x) barrier() +#define __rw_yield(x) barrier() +#define SHARED_PROCESSOR 0 +#endif +extern void spin_unlock_wait(spinlock_t *lock); + +/* + * This returns the old value in the lock, so we succeeded + * in getting the lock if the return value is 0. + */ +static __inline__ unsigned long __spin_trylock(spinlock_t *lock) +{ + unsigned long tmp, tmp2; + + __asm__ __volatile__( +" lwz %1,%3(13) # __spin_trylock\n\ +1: lwarx %0,0,%2\n\ + cmpwi 0,%0,0\n\ + bne- 2f\n\ + stwcx. %1,0,%2\n\ + bne- 1b\n\ + isync\n\ +2:" : "=&r" (tmp), "=&r" (tmp2) + : "r" (&lock->lock), "i" (offsetof(struct paca_struct, lock_token)) + : "cr0", "memory"); + + return tmp; +} + +static int __inline__ _raw_spin_trylock(spinlock_t *lock) +{ + return __spin_trylock(lock) == 0; +} + +static void __inline__ _raw_spin_lock(spinlock_t *lock) +{ + while (1) { + if (likely(__spin_trylock(lock) == 0)) + break; + do { + HMT_low(); + if (SHARED_PROCESSOR) + __spin_yield(lock); + } while (likely(lock->lock != 0)); + HMT_medium(); + } +} + +static void __inline__ _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags) +{ + unsigned long flags_dis; + + while (1) { + if (likely(__spin_trylock(lock) == 0)) + break; + local_save_flags(flags_dis); + local_irq_restore(flags); + do { + HMT_low(); + if (SHARED_PROCESSOR) + __spin_yield(lock); + } while (likely(lock->lock != 0)); + HMT_medium(); + local_irq_restore(flags_dis); + } +} + +/* + * Read-write spinlocks, allowing multiple readers + * but only one writer. + * + * NOTE! it is quite common to have readers in interrupts + * but no interrupt writers. For those circumstances we + * can "mix" irq-safe locks - any writer needs to get a + * irq-safe write-lock, but readers can get non-irqsafe + * read-locks. + */ +#define RW_LOCK_UNLOCKED (rwlock_t) { 0 } + +#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0) + +#define read_can_lock(rw) ((rw)->lock >= 0) +#define write_can_lock(rw) (!(rw)->lock) + +static __inline__ void _raw_write_unlock(rwlock_t *rw) +{ + __asm__ __volatile__("lwsync # write_unlock": : :"memory"); + rw->lock = 0; +} + +/* + * This returns the old value in the lock + 1, + * so we got a read lock if the return value is > 0. + */ +static long __inline__ __read_trylock(rwlock_t *rw) +{ + long tmp; + + __asm__ __volatile__( +"1: lwarx %0,0,%1 # read_trylock\n\ + extsw %0,%0\n\ + addic. %0,%0,1\n\ + ble- 2f\n\ + stwcx. %0,0,%1\n\ + bne- 1b\n\ + isync\n\ +2:" : "=&r" (tmp) + : "r" (&rw->lock) + : "cr0", "xer", "memory"); + + return tmp; +} + +static int __inline__ _raw_read_trylock(rwlock_t *rw) +{ + return __read_trylock(rw) > 0; +} + +static void __inline__ _raw_read_lock(rwlock_t *rw) +{ + while (1) { + if (likely(__read_trylock(rw) > 0)) + break; + do { + HMT_low(); + if (SHARED_PROCESSOR) + __rw_yield(rw); + } while (likely(rw->lock < 0)); + HMT_medium(); + } +} + +static void __inline__ _raw_read_unlock(rwlock_t *rw) +{ + long tmp; + + __asm__ __volatile__( + "eieio # read_unlock\n\ +1: lwarx %0,0,%1\n\ + addic %0,%0,-1\n\ + stwcx. %0,0,%1\n\ + bne- 1b" + : "=&r"(tmp) + : "r"(&rw->lock) + : "cr0", "memory"); +} + +/* + * This returns the old value in the lock, + * so we got the write lock if the return value is 0. + */ +static __inline__ long __write_trylock(rwlock_t *rw) +{ + long tmp, tmp2; + + __asm__ __volatile__( +" lwz %1,%3(13) # write_trylock\n\ +1: lwarx %0,0,%2\n\ + cmpwi 0,%0,0\n\ + bne- 2f\n\ + stwcx. %1,0,%2\n\ + bne- 1b\n\ + isync\n\ +2:" : "=&r" (tmp), "=&r" (tmp2) + : "r" (&rw->lock), "i" (offsetof(struct paca_struct, lock_token)) + : "cr0", "memory"); + + return tmp; +} + +static int __inline__ _raw_write_trylock(rwlock_t *rw) +{ + return __write_trylock(rw) == 0; +} + +static void __inline__ _raw_write_lock(rwlock_t *rw) +{ + while (1) { + if (likely(__write_trylock(rw) == 0)) + break; + do { + HMT_low(); + if (SHARED_PROCESSOR) + __rw_yield(rw); + } while (likely(rw->lock != 0)); + HMT_medium(); + } +} + +#endif /* __KERNEL__ */ +#endif /* __ASM_SPINLOCK_H */ diff --git a/include/asm-ppc64/sstep.h b/include/asm-ppc64/sstep.h new file mode 100644 index 000000000000..4a68db50ee6f --- /dev/null +++ b/include/asm-ppc64/sstep.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2004 Paul Mackerras <paulus@au.ibm.com>, IBM + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +struct pt_regs; + +/* + * We don't allow single-stepping an mtmsrd that would clear + * MSR_RI, since that would make the exception unrecoverable. + * Since we need to single-step to proceed from a breakpoint, + * we don't allow putting a breakpoint on an mtmsrd instruction. + * Similarly we don't allow breakpoints on rfid instructions. + * These macros tell us if an instruction is a mtmsrd or rfid. + */ +#define IS_MTMSRD(instr) (((instr) & 0xfc0007fe) == 0x7c000164) +#define IS_RFID(instr) (((instr) & 0xfc0007fe) == 0x4c000024) + +/* Emulate instructions that cause a transfer of control. */ +extern int emulate_step(struct pt_regs *regs, unsigned int instr); diff --git a/include/asm-ppc64/stat.h b/include/asm-ppc64/stat.h new file mode 100644 index 000000000000..973a5f97951d --- /dev/null +++ b/include/asm-ppc64/stat.h @@ -0,0 +1,60 @@ +#ifndef _PPC64_STAT_H +#define _PPC64_STAT_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/types.h> + +struct stat { + unsigned long st_dev; + ino_t st_ino; + nlink_t st_nlink; + mode_t st_mode; + uid_t st_uid; + gid_t st_gid; + unsigned long st_rdev; + off_t st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; + unsigned long st_atime_nsec; + unsigned long st_mtime; + unsigned long st_mtime_nsec; + unsigned long st_ctime; + unsigned long st_ctime_nsec; + unsigned long __unused4; + unsigned long __unused5; + unsigned long __unused6; +}; + +#define STAT_HAVE_NSEC 1 + +/* This matches struct stat64 in glibc2.1. Only used for 32 bit. */ +struct stat64 { + unsigned long st_dev; /* Device. */ + unsigned long st_ino; /* File serial number. */ + unsigned int st_mode; /* File mode. */ + unsigned int st_nlink; /* Link count. */ + unsigned int st_uid; /* User ID of the file's owner. */ + unsigned int st_gid; /* Group ID of the file's group. */ + unsigned long st_rdev; /* Device number, if device. */ + unsigned short __pad2; + long st_size; /* Size of file, in bytes. */ + int st_blksize; /* Optimal block size for I/O. */ + + long st_blocks; /* Number 512-byte blocks allocated. */ + int st_atime; /* Time of last access. */ + int st_atime_nsec; + int st_mtime; /* Time of last modification. */ + int st_mtime_nsec; + int st_ctime; /* Time of last status change. */ + int st_ctime_nsec; + unsigned int __unused4; + unsigned int __unused5; +}; +#endif diff --git a/include/asm-ppc64/statfs.h b/include/asm-ppc64/statfs.h new file mode 100644 index 000000000000..3c985e5246a7 --- /dev/null +++ b/include/asm-ppc64/statfs.h @@ -0,0 +1,61 @@ +#ifndef _PPC64_STATFS_H +#define _PPC64_STATFS_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef __KERNEL_STRICT_NAMES +#include <linux/types.h> +typedef __kernel_fsid_t fsid_t; +#endif + +/* + * We're already 64-bit, so duplicate the definition + */ +struct statfs { + long f_type; + long f_bsize; + long f_blocks; + long f_bfree; + long f_bavail; + long f_files; + long f_ffree; + __kernel_fsid_t f_fsid; + long f_namelen; + long f_frsize; + long f_spare[5]; +}; + +struct statfs64 { + long f_type; + long f_bsize; + long f_blocks; + long f_bfree; + long f_bavail; + long f_files; + long f_ffree; + __kernel_fsid_t f_fsid; + long f_namelen; + long f_frsize; + long f_spare[5]; +}; + +struct compat_statfs64 { + __u32 f_type; + __u32 f_bsize; + __u64 f_blocks; + __u64 f_bfree; + __u64 f_bavail; + __u64 f_files; + __u64 f_ffree; + __kernel_fsid_t f_fsid; + __u32 f_namelen; + __u32 f_frsize; + __u32 f_spare[5]; +}; + +#endif /* _PPC64_STATFS_H */ diff --git a/include/asm-ppc64/string.h b/include/asm-ppc64/string.h new file mode 100644 index 000000000000..eeca68ef1e91 --- /dev/null +++ b/include/asm-ppc64/string.h @@ -0,0 +1,35 @@ +#ifndef _PPC64_STRING_H_ +#define _PPC64_STRING_H_ + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#define __HAVE_ARCH_STRCPY +#define __HAVE_ARCH_STRNCPY +#define __HAVE_ARCH_STRLEN +#define __HAVE_ARCH_STRCMP +#define __HAVE_ARCH_STRCAT +#define __HAVE_ARCH_MEMSET +#define __HAVE_ARCH_MEMCPY +#define __HAVE_ARCH_MEMMOVE +#define __HAVE_ARCH_MEMCMP +#define __HAVE_ARCH_MEMCHR + +extern int strcasecmp(const char *, const char *); +extern int strncasecmp(const char *, const char *, int); +extern char * strcpy(char *,const char *); +extern char * strncpy(char *,const char *, __kernel_size_t); +extern __kernel_size_t strlen(const char *); +extern int strcmp(const char *,const char *); +extern char * strcat(char *, const char *); +extern void * memset(void *,int,__kernel_size_t); +extern void * memcpy(void *,const void *,__kernel_size_t); +extern void * memmove(void *,const void *,__kernel_size_t); +extern int memcmp(const void *,const void *,__kernel_size_t); +extern void * memchr(const void *,int,__kernel_size_t); + +#endif /* _PPC64_STRING_H_ */ diff --git a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h new file mode 100644 index 000000000000..98d120ca8a91 --- /dev/null +++ b/include/asm-ppc64/system.h @@ -0,0 +1,306 @@ +#ifndef __PPC64_SYSTEM_H +#define __PPC64_SYSTEM_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/config.h> +#include <linux/compiler.h> +#include <asm/page.h> +#include <asm/processor.h> +#include <asm/hw_irq.h> +#include <asm/memory.h> + +/* + * Memory barrier. + * The sync instruction guarantees that all memory accesses initiated + * by this processor have been performed (with respect to all other + * mechanisms that access memory). The eieio instruction is a barrier + * providing an ordering (separately) for (a) cacheable stores and (b) + * loads and stores to non-cacheable memory (e.g. I/O devices). + * + * mb() prevents loads and stores being reordered across this point. + * rmb() prevents loads being reordered across this point. + * wmb() prevents stores being reordered across this point. + * read_barrier_depends() prevents data-dependent loads being reordered + * across this point (nop on PPC). + * + * We have to use the sync instructions for mb(), since lwsync doesn't + * order loads with respect to previous stores. Lwsync is fine for + * rmb(), though. + * For wmb(), we use sync since wmb is used in drivers to order + * stores to system memory with respect to writes to the device. + * However, smp_wmb() can be a lighter-weight eieio barrier on + * SMP since it is only used to order updates to system memory. + */ +#define mb() __asm__ __volatile__ ("sync" : : : "memory") +#define rmb() __asm__ __volatile__ ("lwsync" : : : "memory") +#define wmb() __asm__ __volatile__ ("sync" : : : "memory") +#define read_barrier_depends() do { } while(0) + +#define set_mb(var, value) do { var = value; smp_mb(); } while (0) +#define set_wmb(var, value) do { var = value; smp_wmb(); } while (0) + +#ifdef CONFIG_SMP +#define smp_mb() mb() +#define smp_rmb() rmb() +#define smp_wmb() __asm__ __volatile__ ("eieio" : : : "memory") +#define smp_read_barrier_depends() read_barrier_depends() +#else +#define smp_mb() __asm__ __volatile__("": : :"memory") +#define smp_rmb() __asm__ __volatile__("": : :"memory") +#define smp_wmb() __asm__ __volatile__("": : :"memory") +#define smp_read_barrier_depends() do { } while(0) +#endif /* CONFIG_SMP */ + +#ifdef __KERNEL__ +struct task_struct; +struct pt_regs; + +#ifdef CONFIG_DEBUGGER + +extern int (*__debugger)(struct pt_regs *regs); +extern int (*__debugger_ipi)(struct pt_regs *regs); +extern int (*__debugger_bpt)(struct pt_regs *regs); +extern int (*__debugger_sstep)(struct pt_regs *regs); +extern int (*__debugger_iabr_match)(struct pt_regs *regs); +extern int (*__debugger_dabr_match)(struct pt_regs *regs); +extern int (*__debugger_fault_handler)(struct pt_regs *regs); + +#define DEBUGGER_BOILERPLATE(__NAME) \ +static inline int __NAME(struct pt_regs *regs) \ +{ \ + if (unlikely(__ ## __NAME)) \ + return __ ## __NAME(regs); \ + return 0; \ +} + +DEBUGGER_BOILERPLATE(debugger) +DEBUGGER_BOILERPLATE(debugger_ipi) +DEBUGGER_BOILERPLATE(debugger_bpt) +DEBUGGER_BOILERPLATE(debugger_sstep) +DEBUGGER_BOILERPLATE(debugger_iabr_match) +DEBUGGER_BOILERPLATE(debugger_dabr_match) +DEBUGGER_BOILERPLATE(debugger_fault_handler) + +#ifdef CONFIG_XMON +extern void xmon_init(void); +#endif + +#else +static inline int debugger(struct pt_regs *regs) { return 0; } +static inline int debugger_ipi(struct pt_regs *regs) { return 0; } +static inline int debugger_bpt(struct pt_regs *regs) { return 0; } +static inline int debugger_sstep(struct pt_regs *regs) { return 0; } +static inline int debugger_iabr_match(struct pt_regs *regs) { return 0; } +static inline int debugger_dabr_match(struct pt_regs *regs) { return 0; } +static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; } +#endif + +extern int fix_alignment(struct pt_regs *regs); +extern void bad_page_fault(struct pt_regs *regs, unsigned long address, + int sig); +extern void show_regs(struct pt_regs * regs); +extern void low_hash_fault(struct pt_regs *regs, unsigned long address); +extern int die(const char *str, struct pt_regs *regs, long err); + +extern int _get_PVR(void); +extern void giveup_fpu(struct task_struct *); +extern void disable_kernel_fp(void); +extern void flush_fp_to_thread(struct task_struct *); +extern void enable_kernel_fp(void); +extern void giveup_altivec(struct task_struct *); +extern void disable_kernel_altivec(void); +extern void enable_kernel_altivec(void); +extern int emulate_altivec(struct pt_regs *); +extern void cvt_fd(float *from, double *to, unsigned long *fpscr); +extern void cvt_df(double *from, float *to, unsigned long *fpscr); + +#ifdef CONFIG_ALTIVEC +extern void flush_altivec_to_thread(struct task_struct *); +#else +static inline void flush_altivec_to_thread(struct task_struct *t) +{ +} +#endif + +extern int mem_init_done; /* set on boot once kmalloc can be called */ + +/* EBCDIC -> ASCII conversion for [0-9A-Z] on iSeries */ +extern unsigned char e2a(unsigned char); + +extern struct task_struct *__switch_to(struct task_struct *, + struct task_struct *); +#define switch_to(prev, next, last) ((last) = __switch_to((prev), (next))) + +struct thread_struct; +extern struct task_struct * _switch(struct thread_struct *prev, + struct thread_struct *next); + +static inline int __is_processor(unsigned long pv) +{ + unsigned long pvr; + asm("mfspr %0, 0x11F" : "=r" (pvr)); + return(PVR_VER(pvr) == pv); +} + +/* + * Atomic exchange + * + * Changes the memory location '*ptr' to be val and returns + * the previous value stored there. + * + * Inline asm pulled from arch/ppc/kernel/misc.S so ppc64 + * is more like most of the other architectures. + */ +static __inline__ unsigned long +__xchg_u32(volatile int *m, unsigned long val) +{ + unsigned long dummy; + + __asm__ __volatile__( + EIEIO_ON_SMP +"1: lwarx %0,0,%3 # __xchg_u32\n\ + stwcx. %2,0,%3\n\ +2: bne- 1b" + ISYNC_ON_SMP + : "=&r" (dummy), "=m" (*m) + : "r" (val), "r" (m) + : "cc", "memory"); + + return (dummy); +} + +static __inline__ unsigned long +__xchg_u64(volatile long *m, unsigned long val) +{ + unsigned long dummy; + + __asm__ __volatile__( + EIEIO_ON_SMP +"1: ldarx %0,0,%3 # __xchg_u64\n\ + stdcx. %2,0,%3\n\ +2: bne- 1b" + ISYNC_ON_SMP + : "=&r" (dummy), "=m" (*m) + : "r" (val), "r" (m) + : "cc", "memory"); + + return (dummy); +} + +/* + * This function doesn't exist, so you'll get a linker error + * if something tries to do an invalid xchg(). + */ +extern void __xchg_called_with_bad_pointer(void); + +static __inline__ unsigned long +__xchg(volatile void *ptr, unsigned long x, int size) +{ + switch (size) { + case 4: + return __xchg_u32(ptr, x); + case 8: + return __xchg_u64(ptr, x); + } + __xchg_called_with_bad_pointer(); + return x; +} + +#define xchg(ptr,x) \ + ({ \ + __typeof__(*(ptr)) _x_ = (x); \ + (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \ + }) + +#define tas(ptr) (xchg((ptr),1)) + +#define __HAVE_ARCH_CMPXCHG 1 + +static __inline__ unsigned long +__cmpxchg_u32(volatile int *p, int old, int new) +{ + unsigned int prev; + + __asm__ __volatile__ ( + EIEIO_ON_SMP +"1: lwarx %0,0,%2 # __cmpxchg_u32\n\ + cmpw 0,%0,%3\n\ + bne- 2f\n\ + stwcx. %4,0,%2\n\ + bne- 1b" + ISYNC_ON_SMP + "\n\ +2:" + : "=&r" (prev), "=m" (*p) + : "r" (p), "r" (old), "r" (new), "m" (*p) + : "cc", "memory"); + + return prev; +} + +static __inline__ unsigned long +__cmpxchg_u64(volatile long *p, unsigned long old, unsigned long new) +{ + unsigned long prev; + + __asm__ __volatile__ ( + EIEIO_ON_SMP +"1: ldarx %0,0,%2 # __cmpxchg_u64\n\ + cmpd 0,%0,%3\n\ + bne- 2f\n\ + stdcx. %4,0,%2\n\ + bne- 1b" + ISYNC_ON_SMP + "\n\ +2:" + : "=&r" (prev), "=m" (*p) + : "r" (p), "r" (old), "r" (new), "m" (*p) + : "cc", "memory"); + + return prev; +} + +/* This function doesn't exist, so you'll get a linker error + if something tries to do an invalid cmpxchg(). */ +extern void __cmpxchg_called_with_bad_pointer(void); + +static __inline__ unsigned long +__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) +{ + switch (size) { + case 4: + return __cmpxchg_u32(ptr, old, new); + case 8: + return __cmpxchg_u64(ptr, old, new); + } + __cmpxchg_called_with_bad_pointer(); + return old; +} + +#define cmpxchg(ptr,o,n) \ + ({ \ + __typeof__(*(ptr)) _o_ = (o); \ + __typeof__(*(ptr)) _n_ = (n); \ + (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ + (unsigned long)_n_, sizeof(*(ptr))); \ + }) + +/* + * We handle most unaligned accesses in hardware. On the other hand + * unaligned DMA can be very expensive on some ppc64 IO chips (it does + * powers of 2 writes until it reaches sufficient alignment). + * + * Based on this we disable the IP header alignment in network drivers. + */ +#define NET_IP_ALIGN 0 + +#define arch_align_stack(x) (x) + +#endif /* __KERNEL__ */ +#endif diff --git a/include/asm-ppc64/systemcfg.h b/include/asm-ppc64/systemcfg.h new file mode 100644 index 000000000000..9b86b53129aa --- /dev/null +++ b/include/asm-ppc64/systemcfg.h @@ -0,0 +1,64 @@ +#ifndef _SYSTEMCFG_H +#define _SYSTEMCFG_H + +/* + * Copyright (C) 2002 Peter Bergner <bergner@vnet.ibm.com>, IBM + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +/* Change Activity: + * 2002/09/30 : bergner : Created + * End Change Activity + */ + +/* + * If the major version changes we are incompatible. + * Minor version changes are a hint. + */ +#define SYSTEMCFG_MAJOR 1 +#define SYSTEMCFG_MINOR 1 + +#ifndef __ASSEMBLY__ + +#include <linux/unistd.h> + +#define SYSCALL_MAP_SIZE ((__NR_syscalls + 31) / 32) + +struct systemcfg { + __u8 eye_catcher[16]; /* Eyecatcher: SYSTEMCFG:PPC64 0x00 */ + struct { /* Systemcfg version numbers */ + __u32 major; /* Major number 0x10 */ + __u32 minor; /* Minor number 0x14 */ + } version; + + __u32 platform; /* Platform flags 0x18 */ + __u32 processor; /* Processor type 0x1C */ + __u64 processorCount; /* # of physical processors 0x20 */ + __u64 physicalMemorySize; /* Size of real memory(B) 0x28 */ + __u64 tb_orig_stamp; /* Timebase at boot 0x30 */ + __u64 tb_ticks_per_sec; /* Timebase tics / sec 0x38 */ + __u64 tb_to_xs; /* Inverse of TB to 2^20 0x40 */ + __u64 stamp_xsec; /* 0x48 */ + __u64 tb_update_count; /* Timebase atomicity ctr 0x50 */ + __u32 tz_minuteswest; /* Minutes west of Greenwich 0x58 */ + __u32 tz_dsttime; /* Type of dst correction 0x5C */ + /* next four are no longer used except to be exported to /proc */ + __u32 dcache_size; /* L1 d-cache size 0x60 */ + __u32 dcache_line_size; /* L1 d-cache line size 0x64 */ + __u32 icache_size; /* L1 i-cache size 0x68 */ + __u32 icache_line_size; /* L1 i-cache line size 0x6C */ + __u32 syscall_map_64[SYSCALL_MAP_SIZE]; /* map of available syscalls 0x70 */ + __u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of available syscalls */ +}; + +#ifdef __KERNEL__ +extern struct systemcfg *systemcfg; +#endif + +#endif /* __ASSEMBLY__ */ + +#endif /* _SYSTEMCFG_H */ diff --git a/include/asm-ppc64/termbits.h b/include/asm-ppc64/termbits.h new file mode 100644 index 000000000000..d1a2bee10cef --- /dev/null +++ b/include/asm-ppc64/termbits.h @@ -0,0 +1,193 @@ +#ifndef _PPC64_TERMBITS_H +#define _PPC64_TERMBITS_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/posix_types.h> + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +/* + * termios type and macro definitions. Be careful about adding stuff + * to this file since it's used in GNU libc and there are strict rules + * concerning namespace pollution. + */ + +#define NCCS 19 +struct termios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_cc[NCCS]; /* control characters */ + cc_t c_line; /* line discipline (== c_cc[19]) */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + +/* c_cc characters */ +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VMIN 5 +#define VEOL 6 +#define VTIME 7 +#define VEOL2 8 +#define VSWTC 9 +#define VWERASE 10 +#define VREPRINT 11 +#define VSUSP 12 +#define VSTART 13 +#define VSTOP 14 +#define VLNEXT 15 +#define VDISCARD 16 + +/* c_iflag bits */ +#define IGNBRK 0000001 +#define BRKINT 0000002 +#define IGNPAR 0000004 +#define PARMRK 0000010 +#define INPCK 0000020 +#define ISTRIP 0000040 +#define INLCR 0000100 +#define IGNCR 0000200 +#define ICRNL 0000400 +#define IXON 0001000 +#define IXOFF 0002000 +#define IXANY 0004000 +#define IUCLC 0010000 +#define IMAXBEL 0020000 +#define IUTF8 0040000 + +/* c_oflag bits */ +#define OPOST 0000001 +#define ONLCR 0000002 +#define OLCUC 0000004 + +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 + +#define OFILL 00000100 +#define OFDEL 00000200 +#define NLDLY 00001400 +#define NL0 00000000 +#define NL1 00000400 +#define NL2 00001000 +#define NL3 00001400 +#define TABDLY 00006000 +#define TAB0 00000000 +#define TAB1 00002000 +#define TAB2 00004000 +#define TAB3 00006000 +#define XTABS 00006000 /* required by POSIX to == TAB3 */ +#define CRDLY 00030000 +#define CR0 00000000 +#define CR1 00010000 +#define CR2 00020000 +#define CR3 00030000 +#define FFDLY 00040000 +#define FF0 00000000 +#define FF1 00040000 +#define BSDLY 00100000 +#define BS0 00000000 +#define BS1 00100000 +#define VTDLY 00200000 +#define VT0 00000000 +#define VT1 00200000 + +/* c_cflag bit meaning */ +#define CBAUD 0000377 +#define B0 0000000 /* hang up */ +#define B50 0000001 +#define B75 0000002 +#define B110 0000003 +#define B134 0000004 +#define B150 0000005 +#define B200 0000006 +#define B300 0000007 +#define B600 0000010 +#define B1200 0000011 +#define B1800 0000012 +#define B2400 0000013 +#define B4800 0000014 +#define B9600 0000015 +#define B19200 0000016 +#define B38400 0000017 +#define EXTA B19200 +#define EXTB B38400 +#define CBAUDEX 0000000 +#define B57600 00020 +#define B115200 00021 +#define B230400 00022 +#define B460800 00023 +#define B500000 00024 +#define B576000 00025 +#define B921600 00026 +#define B1000000 00027 +#define B1152000 00030 +#define B1500000 00031 +#define B2000000 00032 +#define B2500000 00033 +#define B3000000 00034 +#define B3500000 00035 +#define B4000000 00036 + +#define CSIZE 00001400 +#define CS5 00000000 +#define CS6 00000400 +#define CS7 00001000 +#define CS8 00001400 + +#define CSTOPB 00002000 +#define CREAD 00004000 +#define PARENB 00010000 +#define PARODD 00020000 +#define HUPCL 00040000 + +#define CLOCAL 00100000 +#define CRTSCTS 020000000000 /* flow control */ + +/* c_lflag bits */ +#define ISIG 0x00000080 +#define ICANON 0x00000100 +#define XCASE 0x00004000 +#define ECHO 0x00000008 +#define ECHOE 0x00000002 +#define ECHOK 0x00000004 +#define ECHONL 0x00000010 +#define NOFLSH 0x80000000 +#define TOSTOP 0x00400000 +#define ECHOCTL 0x00000040 +#define ECHOPRT 0x00000020 +#define ECHOKE 0x00000001 +#define FLUSHO 0x00800000 +#define PENDIN 0x20000000 +#define IEXTEN 0x00000400 + +/* Values for the ACTION argument to `tcflow'. */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* Values for the QUEUE_SELECTOR argument to `tcflush'. */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* Values for the OPTIONAL_ACTIONS argument to `tcsetattr'. */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + +#endif /* _PPC64_TERMBITS_H */ diff --git a/include/asm-ppc64/termios.h b/include/asm-ppc64/termios.h new file mode 100644 index 000000000000..02c3d283aa62 --- /dev/null +++ b/include/asm-ppc64/termios.h @@ -0,0 +1,235 @@ +#ifndef _PPC64_TERMIOS_H +#define _PPC64_TERMIOS_H + +/* + * Liberally adapted from alpha/termios.h. In particular, the c_cc[] + * fields have been reordered so that termio & termios share the + * common subset in the same order (for brain dead programs that don't + * know or care about the differences). + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <asm/ioctls.h> +#include <asm/termbits.h> + +struct sgttyb { + char sg_ispeed; + char sg_ospeed; + char sg_erase; + char sg_kill; + short sg_flags; +}; + +struct tchars { + char t_intrc; + char t_quitc; + char t_startc; + char t_stopc; + char t_eofc; + char t_brkc; +}; + +struct ltchars { + char t_suspc; + char t_dsuspc; + char t_rprntc; + char t_flushc; + char t_werasc; + char t_lnextc; +}; + +struct winsize { + unsigned short ws_row; + unsigned short ws_col; + unsigned short ws_xpixel; + unsigned short ws_ypixel; +}; + +#define NCC 10 +struct termio { + unsigned short c_iflag; /* input mode flags */ + unsigned short c_oflag; /* output mode flags */ + unsigned short c_cflag; /* control mode flags */ + unsigned short c_lflag; /* local mode flags */ + unsigned char c_line; /* line discipline */ + unsigned char c_cc[NCC]; /* control characters */ +}; + +/* c_cc characters */ +#define _VINTR 0 +#define _VQUIT 1 +#define _VERASE 2 +#define _VKILL 3 +#define _VEOF 4 +#define _VMIN 5 +#define _VEOL 6 +#define _VTIME 7 +#define _VEOL2 8 +#define _VSWTC 9 + +/* line disciplines */ +#define N_TTY 0 +#define N_SLIP 1 +#define N_MOUSE 2 +#define N_PPP 3 +#define N_STRIP 4 +#define N_AX25 5 +#define N_X25 6 /* X.25 async */ +#define N_6PACK 7 +#define N_MASC 8 /* Reserved for Mobitex module <kaz@cafe.net> */ +#define N_R3964 9 /* Reserved for Simatic R3964 module */ +#define N_PROFIBUS_FDL 10 /* Reserved for Profibus <Dave@mvhi.com> */ +#define N_IRDA 11 /* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */ +#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */ +#define N_HDLC 13 /* synchronous HDLC */ +#define N_SYNC_PPP 14 + +#ifdef __KERNEL__ +/* ^C ^\ del ^U ^D 1 0 0 0 0 ^W ^R ^Z ^Q ^S ^V ^U */ +#define INIT_C_CC "\003\034\177\025\004\001\000\000\000\000\027\022\032\021\023\026\025" +#endif + +#define FIOCLEX _IO('f', 1) +#define FIONCLEX _IO('f', 2) +#define FIOASYNC _IOW('f', 125, int) +#define FIONBIO _IOW('f', 126, int) +#define FIONREAD _IOR('f', 127, int) +#define TIOCINQ FIONREAD + +#define TIOCGETP _IOR('t', 8, struct sgttyb) +#define TIOCSETP _IOW('t', 9, struct sgttyb) +#define TIOCSETN _IOW('t', 10, struct sgttyb) /* TIOCSETP wo flush */ + +#define TIOCSETC _IOW('t', 17, struct tchars) +#define TIOCGETC _IOR('t', 18, struct tchars) +#define TCGETS _IOR('t', 19, struct termios) +#define TCSETS _IOW('t', 20, struct termios) +#define TCSETSW _IOW('t', 21, struct termios) +#define TCSETSF _IOW('t', 22, struct termios) + +#define TCGETA _IOR('t', 23, struct termio) +#define TCSETA _IOW('t', 24, struct termio) +#define TCSETAW _IOW('t', 25, struct termio) +#define TCSETAF _IOW('t', 28, struct termio) + +#define TCSBRK _IO('t', 29) +#define TCXONC _IO('t', 30) +#define TCFLSH _IO('t', 31) + +#define TIOCSWINSZ _IOW('t', 103, struct winsize) +#define TIOCGWINSZ _IOR('t', 104, struct winsize) +#define TIOCSTART _IO('t', 110) /* start output, like ^Q */ +#define TIOCSTOP _IO('t', 111) /* stop output, like ^S */ +#define TIOCOUTQ _IOR('t', 115, int) /* output queue size */ + +#define TIOCGLTC _IOR('t', 116, struct ltchars) +#define TIOCSLTC _IOW('t', 117, struct ltchars) +#define TIOCSPGRP _IOW('t', 118, int) +#define TIOCGPGRP _IOR('t', 119, int) + +#define TIOCEXCL 0x540C +#define TIOCNXCL 0x540D +#define TIOCSCTTY 0x540E + +#define TIOCSTI 0x5412 +#define TIOCMGET 0x5415 +#define TIOCMBIS 0x5416 +#define TIOCMBIC 0x5417 +#define TIOCMSET 0x5418 +#define TIOCGSOFTCAR 0x5419 +#define TIOCSSOFTCAR 0x541A +#define TIOCLINUX 0x541C +#define TIOCCONS 0x541D +#define TIOCGSERIAL 0x541E +#define TIOCSSERIAL 0x541F +#define TIOCPKT 0x5420 + +#define TIOCNOTTY 0x5422 +#define TIOCSETD 0x5423 +#define TIOCGETD 0x5424 +#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ + +#define TIOCSERCONFIG 0x5453 +#define TIOCSERGWILD 0x5454 +#define TIOCSERSWILD 0x5455 +#define TIOCGLCKTRMIOS 0x5456 +#define TIOCSLCKTRMIOS 0x5457 +#define TIOCSERGSTRUCT 0x5458 /* For debugging only */ +#define TIOCSERGETLSR 0x5459 /* Get line status register */ +#define TIOCSERGETMULTI 0x545A /* Get multiport config */ +#define TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ +#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ + +/* Used for packet mode */ +#define TIOCPKT_DATA 0 +#define TIOCPKT_FLUSHREAD 1 +#define TIOCPKT_FLUSHWRITE 2 +#define TIOCPKT_STOP 4 +#define TIOCPKT_START 8 +#define TIOCPKT_NOSTOP 16 +#define TIOCPKT_DOSTOP 32 + +/* modem lines */ +#define TIOCM_LE 0x001 +#define TIOCM_DTR 0x002 +#define TIOCM_RTS 0x004 +#define TIOCM_ST 0x008 +#define TIOCM_SR 0x010 +#define TIOCM_CTS 0x020 +#define TIOCM_CAR 0x040 +#define TIOCM_RNG 0x080 +#define TIOCM_DSR 0x100 +#define TIOCM_CD TIOCM_CAR +#define TIOCM_RI TIOCM_RNG +#define TIOCM_OUT1 0x2000 +#define TIOCM_OUT2 0x4000 +#define TIOCM_LOOP 0x8000 + +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ +#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ + +#ifdef __KERNEL__ + +/* + * Translate a "termio" structure into a "termios". Ugh. + */ +#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \ + unsigned short __tmp; \ + get_user(__tmp,&(termio)->x); \ + (termios)->x = (0xffff0000 & (termios)->x) | __tmp; \ +} + +#define user_termio_to_kernel_termios(termios, termio) \ +({ \ + SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \ + SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \ + SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \ + SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \ + copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \ +}) + +/* + * Translate a "termios" structure into a "termio". Ugh. + */ +#define kernel_termios_to_user_termio(termio, termios) \ +({ \ + put_user((termios)->c_iflag, &(termio)->c_iflag); \ + put_user((termios)->c_oflag, &(termio)->c_oflag); \ + put_user((termios)->c_cflag, &(termio)->c_cflag); \ + put_user((termios)->c_lflag, &(termio)->c_lflag); \ + put_user((termios)->c_line, &(termio)->c_line); \ + copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \ +}) + +#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios)) +#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios)) + +#endif /* __KERNEL__ */ + +#endif /* _PPC64_TERMIOS_H */ diff --git a/include/asm-ppc64/thread_info.h b/include/asm-ppc64/thread_info.h new file mode 100644 index 000000000000..037b5e06083c --- /dev/null +++ b/include/asm-ppc64/thread_info.h @@ -0,0 +1,125 @@ +/* thread_info.h: PPC low-level thread information + * adapted from the i386 version by Paul Mackerras + * + * Copyright (C) 2002 David Howells (dhowells@redhat.com) + * - Incorporating suggestions made by Linus Torvalds and Dave Miller + */ + +#ifndef _ASM_THREAD_INFO_H +#define _ASM_THREAD_INFO_H + +#ifdef __KERNEL__ + +#ifndef __ASSEMBLY__ +#include <linux/config.h> +#include <linux/cache.h> +#include <asm/processor.h> +#include <asm/page.h> +#include <linux/stringify.h> + +/* + * low level task data. + */ +struct thread_info { + struct task_struct *task; /* main task structure */ + struct exec_domain *exec_domain; /* execution domain */ + int cpu; /* cpu we're on */ + int preempt_count; + struct restart_block restart_block; + /* set by force_successful_syscall_return */ + unsigned char syscall_noerror; + /* low level flags - has atomic operations done on it */ + unsigned long flags ____cacheline_aligned_in_smp; +}; + +/* + * macros/functions for gaining access to the thread information structure + * + * preempt_count needs to be 1 initially, until the scheduler is functional. + */ +#define INIT_THREAD_INFO(tsk) \ +{ \ + .task = &tsk, \ + .exec_domain = &default_exec_domain, \ + .cpu = 0, \ + .preempt_count = 1, \ + .restart_block = { \ + .fn = do_no_restart_syscall, \ + }, \ + .flags = 0, \ +} + +#define init_thread_info (init_thread_union.thread_info) +#define init_stack (init_thread_union.stack) + +/* thread information allocation */ + +#define THREAD_ORDER 2 +#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER) +#define THREAD_SHIFT (PAGE_SHIFT + THREAD_ORDER) +#ifdef CONFIG_DEBUG_STACK_USAGE +#define alloc_thread_info(tsk) \ + ({ \ + struct thread_info *ret; \ + \ + ret = kmalloc(THREAD_SIZE, GFP_KERNEL); \ + if (ret) \ + memset(ret, 0, THREAD_SIZE); \ + ret; \ + }) +#else +#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL) +#endif +#define free_thread_info(ti) kfree(ti) +#define get_thread_info(ti) get_task_struct((ti)->task) +#define put_thread_info(ti) put_task_struct((ti)->task) + +/* how to get the thread information struct from C */ +static inline struct thread_info *current_thread_info(void) +{ + struct thread_info *ti; + __asm__("clrrdi %0,1,%1" : "=r"(ti) : "i" (THREAD_SHIFT)); + return ti; +} + +#endif /* __ASSEMBLY__ */ + +#define PREEMPT_ACTIVE 0x10000000 + +/* + * thread information flag bit numbers + */ +#define TIF_SYSCALL_TRACE 0 /* syscall trace active */ +#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */ +#define TIF_SIGPENDING 2 /* signal pending */ +#define TIF_NEED_RESCHED 3 /* rescheduling necessary */ +#define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling + TIF_NEED_RESCHED */ +#define TIF_32BIT 5 /* 32 bit binary */ +#define TIF_RUN_LIGHT 6 /* iSeries run light */ +#define TIF_ABI_PENDING 7 /* 32/64 bit switch needed */ +#define TIF_SYSCALL_AUDIT 8 /* syscall auditing active */ +#define TIF_SINGLESTEP 9 /* singlestepping active */ +#define TIF_MEMDIE 10 +#define TIF_SECCOMP 11 /* secure computing */ + +/* as above, but as bit values */ +#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) +#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) +#define _TIF_SIGPENDING (1<<TIF_SIGPENDING) +#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) +#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) +#define _TIF_32BIT (1<<TIF_32BIT) +#define _TIF_RUN_LIGHT (1<<TIF_RUN_LIGHT) +#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING) +#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) +#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP) +#define _TIF_SECCOMP (1<<TIF_SECCOMP) +#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP) + +#define _TIF_USER_WORK_MASK (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \ + _TIF_NEED_RESCHED) + +#endif /* __KERNEL__ */ + +#endif /* _ASM_THREAD_INFO_H */ diff --git a/include/asm-ppc64/time.h b/include/asm-ppc64/time.h new file mode 100644 index 000000000000..8d6e3760ee10 --- /dev/null +++ b/include/asm-ppc64/time.h @@ -0,0 +1,115 @@ +/* + * Common time prototypes and such for all ppc machines. + * + * Written by Cort Dougan (cort@cs.nmt.edu) to merge + * Paul Mackerras' version and mine for PReP and Pmac. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef __PPC64_TIME_H +#define __PPC64_TIME_H + +#ifdef __KERNEL__ +#include <linux/config.h> +#include <linux/types.h> +#include <linux/mc146818rtc.h> + +#include <asm/processor.h> +#include <asm/paca.h> +#include <asm/iSeries/HvCall.h> + +/* time.c */ +extern unsigned long tb_ticks_per_jiffy; +extern unsigned long tb_ticks_per_usec; +extern unsigned long tb_ticks_per_sec; +extern unsigned long tb_to_xs; +extern unsigned tb_to_us; +extern unsigned long tb_last_stamp; + +struct rtc_time; +extern void to_tm(int tim, struct rtc_time * tm); +extern time_t last_rtc_update; + +/* + * By putting all of this stuff into a single struct we + * reduce the number of cache lines touched by do_gettimeofday. + * Both by collecting all of the data in one cache line and + * by touching only one TOC entry + */ +struct gettimeofday_vars { + unsigned long tb_to_xs; + unsigned long stamp_xsec; + unsigned long tb_orig_stamp; +}; + +struct gettimeofday_struct { + unsigned long tb_ticks_per_sec; + struct gettimeofday_vars vars[2]; + struct gettimeofday_vars * volatile varp; + unsigned var_idx; + unsigned tb_to_us; +}; + +struct div_result { + unsigned long result_high; + unsigned long result_low; +}; + +int via_calibrate_decr(void); + +static __inline__ unsigned long get_tb(void) +{ + return mftb(); +} + +/* Accessor functions for the decrementer register. */ +static __inline__ unsigned int get_dec(void) +{ + return (mfspr(SPRN_DEC)); +} + +static __inline__ void set_dec(int val) +{ +#ifdef CONFIG_PPC_ISERIES + struct paca_struct *lpaca = get_paca(); + int cur_dec; + + if (lpaca->lppaca.shared_proc) { + lpaca->lppaca.virtual_decr = val; + cur_dec = get_dec(); + if (cur_dec > val) + HvCall_setVirtualDecr(); + } else +#endif + mtspr(SPRN_DEC, val); +} + +static inline unsigned long tb_ticks_since(unsigned long tstamp) +{ + return get_tb() - tstamp; +} + +#define mulhwu(x,y) \ +({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;}) +#define mulhdu(x,y) \ +({unsigned long z; asm ("mulhdu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;}) + + +unsigned mulhwu_scale_factor(unsigned, unsigned); +void div128_by_32( unsigned long dividend_high, unsigned long dividend_low, + unsigned divisor, struct div_result *dr ); + +/* Used to store Processor Utilization register (purr) values */ + +struct cpu_usage { + u64 current_tb; /* Holds the current purr register values */ +}; + +DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array); + +#endif /* __KERNEL__ */ +#endif /* __PPC64_TIME_H */ diff --git a/include/asm-ppc64/timex.h b/include/asm-ppc64/timex.h new file mode 100644 index 000000000000..8db4da4064cd --- /dev/null +++ b/include/asm-ppc64/timex.h @@ -0,0 +1,26 @@ +/* + * linux/include/asm-ppc/timex.h + * + * PPC64 architecture timex specifications + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _ASMPPC64_TIMEX_H +#define _ASMPPC64_TIMEX_H + +#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ + +typedef unsigned long cycles_t; + +static inline cycles_t get_cycles(void) +{ + cycles_t ret; + + __asm__ __volatile__("mftb %0" : "=r" (ret) : ); + return ret; +} + +#endif diff --git a/include/asm-ppc64/tlb.h b/include/asm-ppc64/tlb.h new file mode 100644 index 000000000000..97cb696ce68d --- /dev/null +++ b/include/asm-ppc64/tlb.h @@ -0,0 +1,39 @@ +/* + * TLB shootdown specifics for PPC64 + * + * Copyright (C) 2002 Anton Blanchard, IBM Corp. + * Copyright (C) 2002 Paul Mackerras, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _PPC64_TLB_H +#define _PPC64_TLB_H + +#include <asm/tlbflush.h> + +struct mmu_gather; + +extern void pte_free_finish(void); + +static inline void tlb_flush(struct mmu_gather *tlb) +{ + flush_tlb_pending(); + pte_free_finish(); +} + +/* Avoid pulling in another include just for this */ +#define check_pgt_cache() do { } while (0) + +/* Get the generic bits... */ +#include <asm-generic/tlb.h> + +/* Nothing needed here in fact... */ +#define tlb_start_vma(tlb, vma) do { } while (0) +#define tlb_end_vma(tlb, vma) do { } while (0) + +#define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0) + +#endif /* _PPC64_TLB_H */ diff --git a/include/asm-ppc64/tlbflush.h b/include/asm-ppc64/tlbflush.h new file mode 100644 index 000000000000..45411a67e082 --- /dev/null +++ b/include/asm-ppc64/tlbflush.h @@ -0,0 +1,54 @@ +#ifndef _PPC64_TLBFLUSH_H +#define _PPC64_TLBFLUSH_H + +/* + * TLB flushing: + * + * - flush_tlb_mm(mm) flushes the specified mm context TLB's + * - flush_tlb_page(vma, vmaddr) flushes one page + * - flush_tlb_page_nohash(vma, vmaddr) flushes one page if SW loaded TLB + * - flush_tlb_range(vma, start, end) flushes a range of pages + * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages + * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables + */ + +#include <linux/percpu.h> +#include <asm/page.h> + +#define PPC64_TLB_BATCH_NR 192 + +struct mm_struct; +struct ppc64_tlb_batch { + unsigned long index; + unsigned long context; + struct mm_struct *mm; + pte_t pte[PPC64_TLB_BATCH_NR]; + unsigned long addr[PPC64_TLB_BATCH_NR]; + unsigned long vaddr[PPC64_TLB_BATCH_NR]; +}; +DECLARE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); + +extern void __flush_tlb_pending(struct ppc64_tlb_batch *batch); + +static inline void flush_tlb_pending(void) +{ + struct ppc64_tlb_batch *batch = &get_cpu_var(ppc64_tlb_batch); + + if (batch->index) + __flush_tlb_pending(batch); + put_cpu_var(ppc64_tlb_batch); +} + +#define flush_tlb_mm(mm) flush_tlb_pending() +#define flush_tlb_page(vma, addr) flush_tlb_pending() +#define flush_tlb_page_nohash(vma, addr) do { } while (0) +#define flush_tlb_range(vma, start, end) \ + do { (void)(start); flush_tlb_pending(); } while (0) +#define flush_tlb_kernel_range(start, end) flush_tlb_pending() +#define flush_tlb_pgtables(mm, start, end) do { } while (0) + +extern void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte, + int local); +void flush_hash_range(unsigned long context, unsigned long number, int local); + +#endif /* _PPC64_TLBFLUSH_H */ diff --git a/include/asm-ppc64/topology.h b/include/asm-ppc64/topology.h new file mode 100644 index 000000000000..d58d9dd79998 --- /dev/null +++ b/include/asm-ppc64/topology.h @@ -0,0 +1,68 @@ +#ifndef _ASM_PPC64_TOPOLOGY_H +#define _ASM_PPC64_TOPOLOGY_H + +#include <linux/config.h> +#include <asm/mmzone.h> + +#ifdef CONFIG_NUMA + +static inline int cpu_to_node(int cpu) +{ + int node; + + node = numa_cpu_lookup_table[cpu]; + +#ifdef DEBUG_NUMA + BUG_ON(node == -1); +#endif + + return node; +} + +#define parent_node(node) (node) + +static inline cpumask_t node_to_cpumask(int node) +{ + return numa_cpumask_lookup_table[node]; +} + +static inline int node_to_first_cpu(int node) +{ + cpumask_t tmp; + tmp = node_to_cpumask(node); + return first_cpu(tmp); +} + +#define pcibus_to_cpumask(bus) (cpu_online_map) + +#define nr_cpus_node(node) (nr_cpus_in_node[node]) + +/* sched_domains SD_NODE_INIT for PPC64 machines */ +#define SD_NODE_INIT (struct sched_domain) { \ + .span = CPU_MASK_NONE, \ + .parent = NULL, \ + .groups = NULL, \ + .min_interval = 8, \ + .max_interval = 32, \ + .busy_factor = 32, \ + .imbalance_pct = 125, \ + .cache_hot_time = (10*1000000), \ + .cache_nice_tries = 1, \ + .per_cpu_gain = 100, \ + .flags = SD_LOAD_BALANCE \ + | SD_BALANCE_EXEC \ + | SD_BALANCE_NEWIDLE \ + | SD_WAKE_IDLE \ + | SD_WAKE_BALANCE, \ + .last_balance = jiffies, \ + .balance_interval = 1, \ + .nr_balance_failed = 0, \ +} + +#else /* !CONFIG_NUMA */ + +#include <asm-generic/topology.h> + +#endif /* CONFIG_NUMA */ + +#endif /* _ASM_PPC64_TOPOLOGY_H */ diff --git a/include/asm-ppc64/types.h b/include/asm-ppc64/types.h new file mode 100644 index 000000000000..5b8c2cfa1138 --- /dev/null +++ b/include/asm-ppc64/types.h @@ -0,0 +1,80 @@ +#ifndef _PPC64_TYPES_H +#define _PPC64_TYPES_H + +#ifndef __ASSEMBLY__ + +/* + * This file is never included by application software unless + * explicitly requested (e.g., via linux/types.h) in which case the + * application is Linux specific so (user-) name space pollution is + * not a major issue. However, for interoperability, libraries still + * need to be careful to avoid a name clashes. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +typedef unsigned int umode_t; + +/* + * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the + * header files exported to user space + */ + +typedef __signed__ char __s8; +typedef unsigned char __u8; + +typedef __signed__ short __s16; +typedef unsigned short __u16; + +typedef __signed__ int __s32; +typedef unsigned int __u32; + +typedef __signed__ long __s64; +typedef unsigned long __u64; + +typedef struct { + __u32 u[4]; +} __attribute((aligned(16))) __vector128; + +#endif /* __ASSEMBLY__ */ + +#ifdef __KERNEL__ +/* + * These aren't exported outside the kernel to avoid name space clashes + */ +#define BITS_PER_LONG 64 + +#ifndef __ASSEMBLY__ + +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; + +typedef signed long s64; +typedef unsigned long u64; + +typedef __vector128 vector128; + +typedef u32 dma_addr_t; +typedef u64 dma64_addr_t; + +typedef struct { + unsigned long entry; + unsigned long toc; + unsigned long env; +} func_descr_t; + +typedef unsigned int kmem_bufctl_t; +#endif /* __ASSEMBLY__ */ + +#endif /* __KERNEL__ */ + +#endif /* _PPC64_TYPES_H */ diff --git a/include/asm-ppc64/uaccess.h b/include/asm-ppc64/uaccess.h new file mode 100644 index 000000000000..05b5943ab1ee --- /dev/null +++ b/include/asm-ppc64/uaccess.h @@ -0,0 +1,346 @@ +#ifndef _PPC64_UACCESS_H +#define _PPC64_UACCESS_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef __ASSEMBLY__ +#include <linux/sched.h> +#include <linux/errno.h> +#include <asm/processor.h> + +#define VERIFY_READ 0 +#define VERIFY_WRITE 1 + +/* + * The fs value determines whether argument validity checking should be + * performed or not. If get_fs() == USER_DS, checking is performed, with + * get_fs() == KERNEL_DS, checking is bypassed. + * + * For historical reasons, these macros are grossly misnamed. + */ + +#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) + +#define KERNEL_DS MAKE_MM_SEG(0UL) +#define USER_DS MAKE_MM_SEG(0xf000000000000000UL) + +#define get_ds() (KERNEL_DS) +#define get_fs() (current->thread.fs) +#define set_fs(val) (current->thread.fs = (val)) + +#define segment_eq(a,b) ((a).seg == (b).seg) + +/* + * Use the alpha trick for checking ranges: + * + * Is a address valid? This does a straightforward calculation rather + * than tests. + * + * Address valid if: + * - "addr" doesn't have any high-bits set + * - AND "size" doesn't have any high-bits set + * - OR we are in kernel mode. + * + * We dont have to check for high bits in (addr+size) because the first + * two checks force the maximum result to be below the start of the + * kernel region. + */ +#define __access_ok(addr,size,segment) \ + (((segment).seg & (addr | size )) == 0) + +#define access_ok(type,addr,size) \ + __access_ok(((__force unsigned long)(addr)),(size),get_fs()) + +/* this function will go away soon - use access_ok() instead */ +static inline int __deprecated verify_area(int type, const void __user *addr, unsigned long size) +{ + return access_ok(type,addr,size) ? 0 : -EFAULT; +} + + +/* + * The exception table consists of pairs of addresses: the first is the + * address of an instruction that is allowed to fault, and the second is + * the address at which the program should continue. No registers are + * modified, so it is entirely up to the continuation code to figure out + * what to do. + * + * All the routines below use bits of fixup code that are out of line + * with the main instruction path. This means when everything is well, + * we don't even have to jump over them. Further, they do not intrude + * on our cache or tlb entries. + */ + +struct exception_table_entry +{ + unsigned long insn, fixup; +}; + +/* Returns 0 if exception not found and fixup otherwise. */ +extern unsigned long search_exception_table(unsigned long); + +/* + * These are the main single-value transfer routines. They automatically + * use the right size if we just have the right pointer type. + * + * This gets kind of ugly. We want to return _two_ values in "get_user()" + * and yet we don't want to do any pointers, because that is too much + * of a performance impact. Thus we have a few rather ugly macros here, + * and hide all the ugliness from the user. + * + * The "__xxx" versions of the user access functions are versions that + * do not verify the address space, that must have been done previously + * with a separate "access_ok()" call (this is used when we do multiple + * accesses to the same area of user memory). + * + * As we use the same address space for kernel and user data on the + * PowerPC, we can just do these as direct assignments. (Of course, the + * exception handling means that it's no longer "just"...) + */ +#define get_user(x,ptr) \ + __get_user_check((x),(ptr),sizeof(*(ptr))) +#define put_user(x,ptr) \ + __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) + +#define __get_user(x,ptr) \ + __get_user_nocheck((x),(ptr),sizeof(*(ptr))) +#define __put_user(x,ptr) \ + __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) + +#define __get_user_unaligned __get_user +#define __put_user_unaligned __put_user + +extern long __put_user_bad(void); + +#define __put_user_nocheck(x,ptr,size) \ +({ \ + long __pu_err; \ + might_sleep(); \ + __chk_user_ptr(ptr); \ + __put_user_size((x),(ptr),(size),__pu_err,-EFAULT); \ + __pu_err; \ +}) + +#define __put_user_check(x,ptr,size) \ +({ \ + long __pu_err = -EFAULT; \ + void __user *__pu_addr = (ptr); \ + might_sleep(); \ + if (access_ok(VERIFY_WRITE,__pu_addr,size)) \ + __put_user_size((x),__pu_addr,(size),__pu_err,-EFAULT); \ + __pu_err; \ +}) + +#define __put_user_size(x,ptr,size,retval,errret) \ +do { \ + retval = 0; \ + switch (size) { \ + case 1: __put_user_asm(x,ptr,retval,"stb",errret); break; \ + case 2: __put_user_asm(x,ptr,retval,"sth",errret); break; \ + case 4: __put_user_asm(x,ptr,retval,"stw",errret); break; \ + case 8: __put_user_asm(x,ptr,retval,"std",errret); break; \ + default: __put_user_bad(); \ + } \ +} while (0) + +/* + * We don't tell gcc that we are accessing memory, but this is OK + * because we do not write to any memory gcc knows about, so there + * are no aliasing issues. + */ +#define __put_user_asm(x, addr, err, op, errret) \ + __asm__ __volatile__( \ + "1: "op" %1,0(%2) # put_user\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: li %0,%3\n" \ + " b 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 3\n" \ + " .llong 1b,3b\n" \ + ".previous" \ + : "=r"(err) \ + : "r"(x), "b"(addr), "i"(errret), "0"(err)) + + +#define __get_user_nocheck(x,ptr,size) \ +({ \ + long __gu_err, __gu_val; \ + might_sleep(); \ + __get_user_size(__gu_val,(ptr),(size),__gu_err,-EFAULT);\ + (x) = (__typeof__(*(ptr)))__gu_val; \ + __gu_err; \ +}) + +#define __get_user_check(x,ptr,size) \ +({ \ + long __gu_err = -EFAULT, __gu_val = 0; \ + const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ + might_sleep(); \ + if (access_ok(VERIFY_READ,__gu_addr,size)) \ + __get_user_size(__gu_val,__gu_addr,(size),__gu_err,-EFAULT);\ + (x) = (__typeof__(*(ptr)))__gu_val; \ + __gu_err; \ +}) + +extern long __get_user_bad(void); + +#define __get_user_size(x,ptr,size,retval,errret) \ +do { \ + retval = 0; \ + __chk_user_ptr(ptr); \ + switch (size) { \ + case 1: __get_user_asm(x,ptr,retval,"lbz",errret); break; \ + case 2: __get_user_asm(x,ptr,retval,"lhz",errret); break; \ + case 4: __get_user_asm(x,ptr,retval,"lwz",errret); break; \ + case 8: __get_user_asm(x,ptr,retval,"ld",errret); break; \ + default: (x) = __get_user_bad(); \ + } \ +} while (0) + +#define __get_user_asm(x, addr, err, op, errret) \ + __asm__ __volatile__( \ + "1: "op" %1,0(%2) # get_user\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: li %0,%3\n" \ + " li %1,0\n" \ + " b 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 3\n" \ + " .llong 1b,3b\n" \ + ".previous" \ + : "=r"(err), "=r"(x) \ + : "b"(addr), "i"(errret), "0"(err)) + +/* more complex routines */ + +extern unsigned long __copy_tofrom_user(void __user *to, const void __user *from, + unsigned long size); + +static inline unsigned long +__copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) +{ + if (__builtin_constant_p(n)) { + unsigned long ret; + + switch (n) { + case 1: + __get_user_size(*(u8 *)to, from, 1, ret, 1); + return ret; + case 2: + __get_user_size(*(u16 *)to, from, 2, ret, 2); + return ret; + case 4: + __get_user_size(*(u32 *)to, from, 4, ret, 4); + return ret; + case 8: + __get_user_size(*(u64 *)to, from, 8, ret, 8); + return ret; + } + } + return __copy_tofrom_user((__force void __user *) to, from, n); +} + +static inline unsigned long +__copy_from_user(void *to, const void __user *from, unsigned long n) +{ + might_sleep(); + return __copy_from_user_inatomic(to, from, n); +} + +static inline unsigned long +__copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) +{ + if (__builtin_constant_p(n)) { + unsigned long ret; + + switch (n) { + case 1: + __put_user_size(*(u8 *)from, (u8 __user *)to, 1, ret, 1); + return ret; + case 2: + __put_user_size(*(u16 *)from, (u16 __user *)to, 2, ret, 2); + return ret; + case 4: + __put_user_size(*(u32 *)from, (u32 __user *)to, 4, ret, 4); + return ret; + case 8: + __put_user_size(*(u64 *)from, (u64 __user *)to, 8, ret, 8); + return ret; + } + } + return __copy_tofrom_user(to, (__force const void __user *) from, n); +} + +static inline unsigned long +__copy_to_user(void __user *to, const void *from, unsigned long n) +{ + might_sleep(); + return __copy_to_user_inatomic(to, from, n); +} + +#define __copy_in_user(to, from, size) \ + __copy_tofrom_user((to), (from), (size)) + +extern unsigned long copy_from_user(void *to, const void __user *from, + unsigned long n); +extern unsigned long copy_to_user(void __user *to, const void *from, + unsigned long n); +extern unsigned long copy_in_user(void __user *to, const void __user *from, + unsigned long n); + +extern unsigned long __clear_user(void __user *addr, unsigned long size); + +static inline unsigned long +clear_user(void __user *addr, unsigned long size) +{ + might_sleep(); + if (likely(access_ok(VERIFY_WRITE, addr, size))) + size = __clear_user(addr, size); + return size; +} + +extern int __strncpy_from_user(char *dst, const char __user *src, long count); + +static inline long +strncpy_from_user(char *dst, const char __user *src, long count) +{ + might_sleep(); + if (likely(access_ok(VERIFY_READ, src, 1))) + return __strncpy_from_user(dst, src, count); + return -EFAULT; +} + +/* + * Return the size of a string (including the ending 0) + * + * Return 0 for error + */ +extern int __strnlen_user(const char __user *str, long len); + +/* + * Returns the length of the string at str (including the null byte), + * or 0 if we hit a page we can't access, + * or something > len if we didn't find a null byte. + */ +static inline int strnlen_user(const char __user *str, long len) +{ + might_sleep(); + if (likely(access_ok(VERIFY_READ, str, 1))) + return __strnlen_user(str, len); + return 0; +} + +#define strlen_user(str) strnlen_user((str), 0x7ffffffe) + +#endif /* __ASSEMBLY__ */ + +#endif /* _PPC64_UACCESS_H */ diff --git a/include/asm-ppc64/ucontext.h b/include/asm-ppc64/ucontext.h new file mode 100644 index 000000000000..ef8cc5b37542 --- /dev/null +++ b/include/asm-ppc64/ucontext.h @@ -0,0 +1,22 @@ +#ifndef _ASMPPC64_UCONTEXT_H +#define _ASMPPC64_UCONTEXT_H + +#include <asm/sigcontext.h> + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +struct ucontext { + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + sigset_t uc_sigmask; + sigset_t __unsued[15]; /* Allow for uc_sigmask growth */ + struct sigcontext uc_mcontext; /* last for extensibility */ +}; + +#endif /* _ASMPPC64_UCONTEXT_H */ diff --git a/include/asm-ppc64/udbg.h b/include/asm-ppc64/udbg.h new file mode 100644 index 000000000000..a6e04d014b2b --- /dev/null +++ b/include/asm-ppc64/udbg.h @@ -0,0 +1,28 @@ +#ifndef __UDBG_HDR +#define __UDBG_HDR + +#include <linux/compiler.h> + +/* + * c 2001 PPC 64 Team, IBM Corp + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +void udbg_init_uart(void __iomem *comport, unsigned int speed); +void udbg_putc(unsigned char c); +unsigned char udbg_getc(void); +int udbg_getc_poll(void); +void udbg_puts(const char *s); +int udbg_write(const char *s, int n); +int udbg_read(char *buf, int buflen); +struct console; +void udbg_console_write(struct console *con, const char *s, unsigned int n); +void udbg_printf(const char *fmt, ...); +void udbg_ppcdbg(unsigned long flags, const char *fmt, ...); +unsigned long udbg_ifdebug(unsigned long flags); + +#endif diff --git a/include/asm-ppc64/unaligned.h b/include/asm-ppc64/unaligned.h new file mode 100644 index 000000000000..636e93c4f379 --- /dev/null +++ b/include/asm-ppc64/unaligned.h @@ -0,0 +1,21 @@ +#ifndef __PPC64_UNALIGNED_H +#define __PPC64_UNALIGNED_H + +/* + * The PowerPC can do unaligned accesses itself in big endian mode. + * + * The strange macros are there to make sure these can't + * be misused in a way that makes them not work on other + * architectures where unaligned accesses aren't as simple. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#define get_unaligned(ptr) (*(ptr)) + +#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) )) + +#endif /* __PPC64_UNALIGNED_H */ diff --git a/include/asm-ppc64/uninorth.h b/include/asm-ppc64/uninorth.h new file mode 100644 index 000000000000..7ad7059f2c80 --- /dev/null +++ b/include/asm-ppc64/uninorth.h @@ -0,0 +1,2 @@ +#include <asm-ppc/uninorth.h> + diff --git a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h new file mode 100644 index 000000000000..605d91e011ec --- /dev/null +++ b/include/asm-ppc64/unistd.h @@ -0,0 +1,482 @@ +#ifndef _ASM_PPC_UNISTD_H_ +#define _ASM_PPC_UNISTD_H_ + +/* + * This file contains the system call numbers. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#define __NR_restart_syscall 0 +#define __NR_exit 1 +#define __NR_fork 2 +#define __NR_read 3 +#define __NR_write 4 +#define __NR_open 5 +#define __NR_close 6 +#define __NR_waitpid 7 +#define __NR_creat 8 +#define __NR_link 9 +#define __NR_unlink 10 +#define __NR_execve 11 +#define __NR_chdir 12 +#define __NR_time 13 +#define __NR_mknod 14 +#define __NR_chmod 15 +#define __NR_lchown 16 +#define __NR_break 17 +#define __NR_oldstat 18 +#define __NR_lseek 19 +#define __NR_getpid 20 +#define __NR_mount 21 +#define __NR_umount 22 +#define __NR_setuid 23 +#define __NR_getuid 24 +#define __NR_stime 25 +#define __NR_ptrace 26 +#define __NR_alarm 27 +#define __NR_oldfstat 28 +#define __NR_pause 29 +#define __NR_utime 30 +#define __NR_stty 31 +#define __NR_gtty 32 +#define __NR_access 33 +#define __NR_nice 34 +#define __NR_ftime 35 +#define __NR_sync 36 +#define __NR_kill 37 +#define __NR_rename 38 +#define __NR_mkdir 39 +#define __NR_rmdir 40 +#define __NR_dup 41 +#define __NR_pipe 42 +#define __NR_times 43 +#define __NR_prof 44 +#define __NR_brk 45 +#define __NR_setgid 46 +#define __NR_getgid 47 +#define __NR_signal 48 +#define __NR_geteuid 49 +#define __NR_getegid 50 +#define __NR_acct 51 +#define __NR_umount2 52 +#define __NR_lock 53 +#define __NR_ioctl 54 +#define __NR_fcntl 55 +#define __NR_mpx 56 +#define __NR_setpgid 57 +#define __NR_ulimit 58 +#define __NR_oldolduname 59 +#define __NR_umask 60 +#define __NR_chroot 61 +#define __NR_ustat 62 +#define __NR_dup2 63 +#define __NR_getppid 64 +#define __NR_getpgrp 65 +#define __NR_setsid 66 +#define __NR_sigaction 67 +#define __NR_sgetmask 68 +#define __NR_ssetmask 69 +#define __NR_setreuid 70 +#define __NR_setregid 71 +#define __NR_sigsuspend 72 +#define __NR_sigpending 73 +#define __NR_sethostname 74 +#define __NR_setrlimit 75 +#define __NR_getrlimit 76 +#define __NR_getrusage 77 +#define __NR_gettimeofday 78 +#define __NR_settimeofday 79 +#define __NR_getgroups 80 +#define __NR_setgroups 81 +#define __NR_select 82 +#define __NR_symlink 83 +#define __NR_oldlstat 84 +#define __NR_readlink 85 +#define __NR_uselib 86 +#define __NR_swapon 87 +#define __NR_reboot 88 +#define __NR_readdir 89 +#define __NR_mmap 90 +#define __NR_munmap 91 +#define __NR_truncate 92 +#define __NR_ftruncate 93 +#define __NR_fchmod 94 +#define __NR_fchown 95 +#define __NR_getpriority 96 +#define __NR_setpriority 97 +#define __NR_profil 98 +#define __NR_statfs 99 +#define __NR_fstatfs 100 +#define __NR_ioperm 101 +#define __NR_socketcall 102 +#define __NR_syslog 103 +#define __NR_setitimer 104 +#define __NR_getitimer 105 +#define __NR_stat 106 +#define __NR_lstat 107 +#define __NR_fstat 108 +#define __NR_olduname 109 +#define __NR_iopl 110 +#define __NR_vhangup 111 +#define __NR_idle 112 +#define __NR_vm86 113 +#define __NR_wait4 114 +#define __NR_swapoff 115 +#define __NR_sysinfo 116 +#define __NR_ipc 117 +#define __NR_fsync 118 +#define __NR_sigreturn 119 +#define __NR_clone 120 +#define __NR_setdomainname 121 +#define __NR_uname 122 +#define __NR_modify_ldt 123 +#define __NR_adjtimex 124 +#define __NR_mprotect 125 +#define __NR_sigprocmask 126 +#define __NR_create_module 127 +#define __NR_init_module 128 +#define __NR_delete_module 129 +#define __NR_get_kernel_syms 130 +#define __NR_quotactl 131 +#define __NR_getpgid 132 +#define __NR_fchdir 133 +#define __NR_bdflush 134 +#define __NR_sysfs 135 +#define __NR_personality 136 +#define __NR_afs_syscall 137 /* Syscall for Andrew File System */ +#define __NR_setfsuid 138 +#define __NR_setfsgid 139 +#define __NR__llseek 140 +#define __NR_getdents 141 +#define __NR__newselect 142 +#define __NR_flock 143 +#define __NR_msync 144 +#define __NR_readv 145 +#define __NR_writev 146 +#define __NR_getsid 147 +#define __NR_fdatasync 148 +#define __NR__sysctl 149 +#define __NR_mlock 150 +#define __NR_munlock 151 +#define __NR_mlockall 152 +#define __NR_munlockall 153 +#define __NR_sched_setparam 154 +#define __NR_sched_getparam 155 +#define __NR_sched_setscheduler 156 +#define __NR_sched_getscheduler 157 +#define __NR_sched_yield 158 +#define __NR_sched_get_priority_max 159 +#define __NR_sched_get_priority_min 160 +#define __NR_sched_rr_get_interval 161 +#define __NR_nanosleep 162 +#define __NR_mremap 163 +#define __NR_setresuid 164 +#define __NR_getresuid 165 +#define __NR_query_module 166 +#define __NR_poll 167 +#define __NR_nfsservctl 168 +#define __NR_setresgid 169 +#define __NR_getresgid 170 +#define __NR_prctl 171 +#define __NR_rt_sigreturn 172 +#define __NR_rt_sigaction 173 +#define __NR_rt_sigprocmask 174 +#define __NR_rt_sigpending 175 +#define __NR_rt_sigtimedwait 176 +#define __NR_rt_sigqueueinfo 177 +#define __NR_rt_sigsuspend 178 +#define __NR_pread64 179 +#define __NR_pwrite64 180 +#define __NR_chown 181 +#define __NR_getcwd 182 +#define __NR_capget 183 +#define __NR_capset 184 +#define __NR_sigaltstack 185 +#define __NR_sendfile 186 +#define __NR_getpmsg 187 /* some people actually want streams */ +#define __NR_putpmsg 188 /* some people actually want streams */ +#define __NR_vfork 189 +#define __NR_ugetrlimit 190 /* SuS compliant getrlimit */ +#define __NR_readahead 191 +/* #define __NR_mmap2 192 32bit only */ +/* #define __NR_truncate64 193 32bit only */ +/* #define __NR_ftruncate64 194 32bit only */ +/* #define __NR_stat64 195 32bit only */ +/* #define __NR_lstat64 196 32bit only */ +/* #define __NR_fstat64 197 32bit only */ +#define __NR_pciconfig_read 198 +#define __NR_pciconfig_write 199 +#define __NR_pciconfig_iobase 200 +#define __NR_multiplexer 201 +#define __NR_getdents64 202 +#define __NR_pivot_root 203 +/* #define __NR_fcntl64 204 32bit only */ +#define __NR_madvise 205 +#define __NR_mincore 206 +#define __NR_gettid 207 +#define __NR_tkill 208 +#define __NR_setxattr 209 +#define __NR_lsetxattr 210 +#define __NR_fsetxattr 211 +#define __NR_getxattr 212 +#define __NR_lgetxattr 213 +#define __NR_fgetxattr 214 +#define __NR_listxattr 215 +#define __NR_llistxattr 216 +#define __NR_flistxattr 217 +#define __NR_removexattr 218 +#define __NR_lremovexattr 219 +#define __NR_fremovexattr 220 +#define __NR_futex 221 +#define __NR_sched_setaffinity 222 +#define __NR_sched_getaffinity 223 +/* 224 currently unused */ +#define __NR_tuxcall 225 +/* #define __NR_sendfile64 226 32bit only */ +#define __NR_io_setup 227 +#define __NR_io_destroy 228 +#define __NR_io_getevents 229 +#define __NR_io_submit 230 +#define __NR_io_cancel 231 +#define __NR_set_tid_address 232 +#define __NR_fadvise64 233 +#define __NR_exit_group 234 +#define __NR_lookup_dcookie 235 +#define __NR_epoll_create 236 +#define __NR_epoll_ctl 237 +#define __NR_epoll_wait 238 +#define __NR_remap_file_pages 239 +#define __NR_timer_create 240 +#define __NR_timer_settime 241 +#define __NR_timer_gettime 242 +#define __NR_timer_getoverrun 243 +#define __NR_timer_delete 244 +#define __NR_clock_settime 245 +#define __NR_clock_gettime 246 +#define __NR_clock_getres 247 +#define __NR_clock_nanosleep 248 +#define __NR_swapcontext 249 +#define __NR_tgkill 250 +#define __NR_utimes 251 +#define __NR_statfs64 252 +#define __NR_fstatfs64 253 +/* #define __NR_fadvise64_64 254 32bit only */ +#define __NR_rtas 255 +/* Number 256 is reserved for sys_debug_setcontext */ +/* Number 257 is reserved for vserver */ +/* Number 258 is reserved for new sys_remap_file_pages */ +#define __NR_mbind 259 +#define __NR_get_mempolicy 260 +#define __NR_set_mempolicy 261 +#define __NR_mq_open 262 +#define __NR_mq_unlink 263 +#define __NR_mq_timedsend 264 +#define __NR_mq_timedreceive 265 +#define __NR_mq_notify 266 +#define __NR_mq_getsetattr 267 +#define __NR_kexec_load 268 +#define __NR_add_key 269 +#define __NR_request_key 270 +#define __NR_keyctl 271 +#define __NR_waitid 272 + +#define __NR_syscalls 273 +#ifdef __KERNEL__ +#define NR_syscalls __NR_syscalls +#endif + +#ifndef __ASSEMBLY__ + +/* On powerpc a system call basically clobbers the same registers like a + * function call, with the exception of LR (which is needed for the + * "sc; bnslr" sequence) and CR (where only CR0.SO is clobbered to signal + * an error return status). + */ + +#define __syscall_nr(nr, type, name, args...) \ + unsigned long __sc_ret, __sc_err; \ + { \ + register unsigned long __sc_0 __asm__ ("r0"); \ + register unsigned long __sc_3 __asm__ ("r3"); \ + register unsigned long __sc_4 __asm__ ("r4"); \ + register unsigned long __sc_5 __asm__ ("r5"); \ + register unsigned long __sc_6 __asm__ ("r6"); \ + register unsigned long __sc_7 __asm__ ("r7"); \ + register unsigned long __sc_8 __asm__ ("r8"); \ + \ + __sc_loadargs_##nr(name, args); \ + __asm__ __volatile__ \ + ("sc \n\t" \ + "mfcr %0 " \ + : "=&r" (__sc_0), \ + "=&r" (__sc_3), "=&r" (__sc_4), \ + "=&r" (__sc_5), "=&r" (__sc_6), \ + "=&r" (__sc_7), "=&r" (__sc_8) \ + : __sc_asm_input_##nr \ + : "cr0", "ctr", "memory", \ + "r9", "r10","r11", "r12"); \ + __sc_ret = __sc_3; \ + __sc_err = __sc_0; \ + } \ + if (__sc_err & 0x10000000) \ + { \ + errno = __sc_ret; \ + __sc_ret = -1; \ + } \ + return (type) __sc_ret + +#define __sc_loadargs_0(name, dummy...) \ + __sc_0 = __NR_##name +#define __sc_loadargs_1(name, arg1) \ + __sc_loadargs_0(name); \ + __sc_3 = (unsigned long) (arg1) +#define __sc_loadargs_2(name, arg1, arg2) \ + __sc_loadargs_1(name, arg1); \ + __sc_4 = (unsigned long) (arg2) +#define __sc_loadargs_3(name, arg1, arg2, arg3) \ + __sc_loadargs_2(name, arg1, arg2); \ + __sc_5 = (unsigned long) (arg3) +#define __sc_loadargs_4(name, arg1, arg2, arg3, arg4) \ + __sc_loadargs_3(name, arg1, arg2, arg3); \ + __sc_6 = (unsigned long) (arg4) +#define __sc_loadargs_5(name, arg1, arg2, arg3, arg4, arg5) \ + __sc_loadargs_4(name, arg1, arg2, arg3, arg4); \ + __sc_7 = (unsigned long) (arg5) +#define __sc_loadargs_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \ + __sc_loadargs_5(name, arg1, arg2, arg3, arg4, arg5); \ + __sc_8 = (unsigned long) (arg6) + +#define __sc_asm_input_0 "0" (__sc_0) +#define __sc_asm_input_1 __sc_asm_input_0, "1" (__sc_3) +#define __sc_asm_input_2 __sc_asm_input_1, "2" (__sc_4) +#define __sc_asm_input_3 __sc_asm_input_2, "3" (__sc_5) +#define __sc_asm_input_4 __sc_asm_input_3, "4" (__sc_6) +#define __sc_asm_input_5 __sc_asm_input_4, "5" (__sc_7) +#define __sc_asm_input_6 __sc_asm_input_5, "6" (__sc_8) + +#define _syscall0(type,name) \ +type name(void) \ +{ \ + __syscall_nr(0, type, name); \ +} + +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ + __syscall_nr(1, type, name, arg1); \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1, type2 arg2) \ +{ \ + __syscall_nr(2, type, name, arg1, arg2); \ +} + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1, type2 arg2, type3 arg3) \ +{ \ + __syscall_nr(3, type, name, arg1, arg2, arg3); \ +} + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ + __syscall_nr(4, type, name, arg1, arg2, arg3, arg4); \ +} + +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ +{ \ + __syscall_nr(5, type, name, arg1, arg2, arg3, arg4, arg5); \ +} +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \ +{ \ + __syscall_nr(6, type, name, arg1, arg2, arg3, arg4, arg5, arg6); \ +} + +#ifdef __KERNEL_SYSCALLS__ + +/* + * Forking from kernel space will result in the child getting a new, + * empty kernel stack area. Thus the child cannot access automatic + * variables set in the parent unless they are in registers, and the + * procedure where the fork was done cannot return to its caller in + * the child. + */ + +/* + * System call prototypes. + */ +static inline _syscall3(int, execve, __const__ char *, file, char **, argv, + char **,envp) + +#endif /* __KERNEL_SYSCALLS__ */ + +#ifdef __KERNEL__ + +#include <linux/types.h> +#include <linux/compiler.h> +#include <linux/linkage.h> + +#define __ARCH_WANT_IPC_PARSE_VERSION +#define __ARCH_WANT_OLD_READDIR +#define __ARCH_WANT_STAT64 +#define __ARCH_WANT_SYS_ALARM +#define __ARCH_WANT_SYS_GETHOSTNAME +#define __ARCH_WANT_SYS_PAUSE +#define __ARCH_WANT_SYS_SGETMASK +#define __ARCH_WANT_SYS_SIGNAL +#define __ARCH_WANT_SYS_TIME +#define __ARCH_WANT_COMPAT_SYS_TIME +#define __ARCH_WANT_SYS_UTIME +#define __ARCH_WANT_SYS_WAITPID +#define __ARCH_WANT_SYS_SOCKETCALL +#define __ARCH_WANT_SYS_FADVISE64 +#define __ARCH_WANT_SYS_GETPGRP +#define __ARCH_WANT_SYS_LLSEEK +#define __ARCH_WANT_SYS_NICE +#define __ARCH_WANT_SYS_OLD_GETRLIMIT +#define __ARCH_WANT_SYS_OLDUMOUNT +#define __ARCH_WANT_SYS_SIGPENDING +#define __ARCH_WANT_SYS_SIGPROCMASK +#define __ARCH_WANT_SYS_RT_SIGACTION + +unsigned long sys_mmap(unsigned long addr, size_t len, unsigned long prot, + unsigned long flags, unsigned long fd, off_t offset); +struct pt_regs; +int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, + unsigned long a3, unsigned long a4, unsigned long a5, + struct pt_regs *regs); +int sys_clone(unsigned long clone_flags, unsigned long p2, unsigned long p3, + unsigned long p4, unsigned long p5, unsigned long p6, + struct pt_regs *regs); +int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3, + unsigned long p4, unsigned long p5, unsigned long p6, + struct pt_regs *regs); +int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3, + unsigned long p4, unsigned long p5, unsigned long p6, + struct pt_regs *regs); +int sys_pipe(int __user *fildes); +int sys_ptrace(long request, long pid, long addr, long data); +struct sigaction; +long sys_rt_sigaction(int sig, const struct sigaction __user *act, + struct sigaction __user *oact, size_t sigsetsize); + +/* + * "Conditional" syscalls + * + * What we want is __attribute__((weak,alias("sys_ni_syscall"))), + * but it doesn't work on all toolchains, so we just do it by hand + */ +#define cond_syscall(x) asm(".weak\t." #x "\n\t.set\t." #x ",.sys_ni_syscall") + +#endif /* __KERNEL__ */ + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_PPC_UNISTD_H_ */ diff --git a/include/asm-ppc64/user.h b/include/asm-ppc64/user.h new file mode 100644 index 000000000000..d7d6554a421f --- /dev/null +++ b/include/asm-ppc64/user.h @@ -0,0 +1,58 @@ +#ifndef _PPC_USER_H +#define _PPC_USER_H + +/* Adapted from <asm-alpha/user.h> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <asm/ptrace.h> +#include <asm/page.h> + +/* + * Core file format: The core file is written in such a way that gdb + * can understand it and provide useful information to the user (under + * linux we use the `trad-core' bfd, NOT the osf-core). The file contents + * are as follows: + * + * upage: 1 page consisting of a user struct that tells gdb + * what is present in the file. Directly after this is a + * copy of the task_struct, which is currently not used by gdb, + * but it may come in handy at some point. All of the registers + * are stored as part of the upage. The upage should always be + * only one page long. + * data: The data segment follows next. We use current->end_text to + * current->brk to pick up all of the user variables, plus any memory + * that may have been sbrk'ed. No attempt is made to determine if a + * page is demand-zero or if a page is totally unused, we just cover + * the entire range. All of the addresses are rounded in such a way + * that an integral number of pages is written. + * stack: We need the stack information in order to get a meaningful + * backtrace. We need to write the data from usp to + * current->start_stack, so we round each of these in order to be able + * to write an integer number of pages. + */ +struct user { + struct pt_regs regs; /* entire machine state */ + size_t u_tsize; /* text size (pages) */ + size_t u_dsize; /* data size (pages) */ + size_t u_ssize; /* stack size (pages) */ + unsigned long start_code; /* text starting address */ + unsigned long start_data; /* data starting address */ + unsigned long start_stack; /* stack starting address */ + long int signal; /* signal causing core dump */ + struct regs * u_ar0; /* help gdb find registers */ + unsigned long magic; /* identifies a core file */ + char u_comm[32]; /* user command name */ +}; + +#define NBPG PAGE_SIZE +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_DATA_START_ADDR (u.start_data) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) + +#endif /* _PPC_USER_H */ diff --git a/include/asm-ppc64/vdso.h b/include/asm-ppc64/vdso.h new file mode 100644 index 000000000000..b74e16c0cf01 --- /dev/null +++ b/include/asm-ppc64/vdso.h @@ -0,0 +1,83 @@ +#ifndef __PPC64_VDSO_H__ +#define __PPC64_VDSO_H__ + +#ifdef __KERNEL__ + +/* Default link addresses for the vDSOs */ +#define VDSO32_LBASE 0 +#define VDSO64_LBASE 0 + +/* Default map addresses */ +#define VDSO32_MBASE 0x100000 +#define VDSO64_MBASE 0x100000 + +#define VDSO_VERSION_STRING LINUX_2.6.12 + +/* Define if 64 bits VDSO has procedure descriptors */ +#undef VDS64_HAS_DESCRIPTORS + +#ifndef __ASSEMBLY__ + +extern unsigned int vdso64_pages; +extern unsigned int vdso32_pages; + +/* Offsets relative to thread->vdso_base */ +extern unsigned long vdso64_rt_sigtramp; +extern unsigned long vdso32_sigtramp; +extern unsigned long vdso32_rt_sigtramp; + +extern void vdso_init(void); + +#else /* __ASSEMBLY__ */ + +#ifdef __VDSO64__ +#ifdef VDS64_HAS_DESCRIPTORS +#define V_FUNCTION_BEGIN(name) \ + .globl name; \ + .section ".opd","a"; \ + .align 3; \ + name: \ + .quad .name,.TOC.@tocbase,0; \ + .previous; \ + .globl .name; \ + .type .name,@function; \ + .name: \ + +#define V_FUNCTION_END(name) \ + .size .name,.-.name; + +#define V_LOCAL_FUNC(name) (.name) + +#else /* VDS64_HAS_DESCRIPTORS */ + +#define V_FUNCTION_BEGIN(name) \ + .globl name; \ + name: \ + +#define V_FUNCTION_END(name) \ + .size name,.-name; + +#define V_LOCAL_FUNC(name) (name) + +#endif /* VDS64_HAS_DESCRIPTORS */ +#endif /* __VDSO64__ */ + +#ifdef __VDSO32__ + +#define V_FUNCTION_BEGIN(name) \ + .globl name; \ + .type name,@function; \ + name: \ + +#define V_FUNCTION_END(name) \ + .size name,.-name; + +#define V_LOCAL_FUNC(name) (name) + +#endif /* __VDSO32__ */ + +#endif /* __ASSEMBLY__ */ + +#endif /* __KERNEL__ */ + +#endif /* __PPC64_VDSO_H__ */ diff --git a/include/asm-ppc64/vga.h b/include/asm-ppc64/vga.h new file mode 100644 index 000000000000..c09849743f45 --- /dev/null +++ b/include/asm-ppc64/vga.h @@ -0,0 +1,50 @@ +/* + * Access to VGA videoram + * + * (c) 1998 Martin Mares <mj@ucw.cz> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _LINUX_ASM_VGA_H_ +#define _LINUX_ASM_VGA_H_ + +#include <asm/io.h> + +#include <linux/config.h> + +#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_MDA_CONSOLE) + +#define VT_BUF_HAVE_RW +/* + * These are only needed for supporting VGA or MDA text mode, which use little + * endian byte ordering. + * In other cases, we can optimize by using native byte ordering and + * <linux/vt_buffer.h> has already done the right job for us. + */ + +static inline void scr_writew(u16 val, volatile u16 *addr) +{ + st_le16(addr, val); +} + +static inline u16 scr_readw(volatile const u16 *addr) +{ + return ld_le16(addr); +} + +#define VT_BUF_HAVE_MEMCPYW +#define scr_memcpyw memcpy + +#endif /* !CONFIG_VGA_CONSOLE && !CONFIG_MDA_CONSOLE */ + +extern unsigned long vgacon_remap_base; +#define VGA_MAP_MEM(x) ((unsigned long) ioremap((x), 0)) + +#define vga_readb(x) (*(x)) +#define vga_writeb(x,y) (*(y) = (x)) + +#endif diff --git a/include/asm-ppc64/vio.h b/include/asm-ppc64/vio.h new file mode 100644 index 000000000000..20cd98ee6337 --- /dev/null +++ b/include/asm-ppc64/vio.h @@ -0,0 +1,103 @@ +/* + * IBM PowerPC Virtual I/O Infrastructure Support. + * + * Copyright (c) 2003 IBM Corp. + * Dave Engebretsen engebret@us.ibm.com + * Santiago Leon santil@us.ibm.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_VIO_H +#define _ASM_VIO_H + +#include <linux/config.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/device.h> +#include <linux/dma-mapping.h> +#include <asm/hvcall.h> +#include <asm/prom.h> +#include <asm/scatterlist.h> +/* + * Architecture-specific constants for drivers to + * extract attributes of the device using vio_get_attribute() +*/ +#define VETH_MAC_ADDR "local-mac-address" +#define VETH_MCAST_FILTER_SIZE "ibm,mac-address-filters" + +/* End architecture-specific constants */ + +#define h_vio_signal(ua, mode) \ + plpar_hcall_norets(H_VIO_SIGNAL, ua, mode) + +#define VIO_IRQ_DISABLE 0UL +#define VIO_IRQ_ENABLE 1UL + +struct vio_dev; +struct vio_driver; +struct vio_device_id; +struct iommu_table; + +int vio_register_driver(struct vio_driver *drv); +void vio_unregister_driver(struct vio_driver *drv); + +#ifdef CONFIG_PPC_PSERIES +struct vio_dev * __devinit vio_register_device_node( + struct device_node *node_vdev); +#endif +void __devinit vio_unregister_device(struct vio_dev *dev); +struct vio_dev *vio_find_node(struct device_node *vnode); + +const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length); +int vio_get_irq(struct vio_dev *dev); +int vio_enable_interrupts(struct vio_dev *dev); +int vio_disable_interrupts(struct vio_dev *dev); + +extern struct dma_mapping_ops vio_dma_ops; + +extern struct bus_type vio_bus_type; + +struct vio_device_id { + char *type; + char *compat; +}; + +struct vio_driver { + struct list_head node; + char *name; + const struct vio_device_id *id_table; /* NULL if wants all devices */ + int (*probe) (struct vio_dev *dev, const struct vio_device_id *id); /* New device inserted */ + int (*remove) (struct vio_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */ + unsigned long driver_data; + + struct device_driver driver; +}; + +static inline struct vio_driver *to_vio_driver(struct device_driver *drv) +{ + return container_of(drv, struct vio_driver, driver); +} + +/* + * The vio_dev structure is used to describe virtual I/O devices. + */ +struct vio_dev { + struct iommu_table *iommu_table; /* vio_map_* uses this */ + char *name; + char *type; + uint32_t unit_address; + unsigned int irq; + + struct device dev; +}; + +static inline struct vio_dev *to_vio_dev(struct device *dev) +{ + return container_of(dev, struct vio_dev, dev); +} + +#endif /* _ASM_VIO_H */ diff --git a/include/asm-ppc64/xics.h b/include/asm-ppc64/xics.h new file mode 100644 index 000000000000..0027da4364ac --- /dev/null +++ b/include/asm-ppc64/xics.h @@ -0,0 +1,36 @@ +/* + * arch/ppc64/kernel/xics.h + * + * Copyright 2000 IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _PPC64_KERNEL_XICS_H +#define _PPC64_KERNEL_XICS_H + +#include <linux/cache.h> + +void xics_init_IRQ(void); +int xics_get_irq(struct pt_regs *); +void xics_setup_cpu(void); +void xics_cause_IPI(int cpu); +void xics_request_IPIs(void); +void xics_migrate_irqs_away(void); + +/* first argument is ignored for now*/ +void pSeriesLP_cppr_info(int n_cpu, u8 value); + +struct xics_ipi_struct { + volatile unsigned long value; +} ____cacheline_aligned; + +extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; + +extern unsigned int default_distrib_server; +extern unsigned int interrupt_server_size; + +#endif /* _PPC64_KERNEL_XICS_H */ diff --git a/include/asm-ppc64/xor.h b/include/asm-ppc64/xor.h new file mode 100644 index 000000000000..c82eb12a5b18 --- /dev/null +++ b/include/asm-ppc64/xor.h @@ -0,0 +1 @@ +#include <asm-generic/xor.h> |