summaryrefslogtreecommitdiffstats
path: root/include/asm-s390
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-s390')
-rw-r--r--include/asm-s390/atomic.h105
-rw-r--r--include/asm-s390/bitops.h147
-rw-r--r--include/asm-s390/ccwcache.h84
-rw-r--r--include/asm-s390/chandev.h188
-rw-r--r--include/asm-s390/checksum.h21
-rw-r--r--include/asm-s390/current.h2
-rw-r--r--include/asm-s390/dasd.h339
-rw-r--r--include/asm-s390/debug.h210
-rw-r--r--include/asm-s390/delay.h5
-rw-r--r--include/asm-s390/dma.h3
-rw-r--r--include/asm-s390/ebcdic.h4
-rw-r--r--include/asm-s390/elf.h13
-rw-r--r--include/asm-s390/fcntl.h13
-rw-r--r--include/asm-s390/hardirq.h8
-rw-r--r--include/asm-s390/idals.h57
-rw-r--r--include/asm-s390/io.h2
-rw-r--r--include/asm-s390/ioctls.h1
-rw-r--r--include/asm-s390/irq.h290
-rw-r--r--include/asm-s390/irqextras390.h2
-rw-r--r--include/asm-s390/lowcore.h36
-rw-r--r--include/asm-s390/mathemu.h15
-rw-r--r--include/asm-s390/misc390.h1
-rw-r--r--include/asm-s390/mmu_context.h3
-rw-r--r--include/asm-s390/namei.h3
-rw-r--r--include/asm-s390/page.h62
-rw-r--r--include/asm-s390/param.h4
-rw-r--r--include/asm-s390/pgalloc.h352
-rw-r--r--include/asm-s390/pgtable.h419
-rw-r--r--include/asm-s390/processor.h36
-rw-r--r--include/asm-s390/ptrace.h35
-rw-r--r--include/asm-s390/queue.h53
-rw-r--r--include/asm-s390/resource.h24
-rw-r--r--include/asm-s390/s390-gdbregs.h7
-rw-r--r--include/asm-s390/s390-regs-common.h14
-rw-r--r--include/asm-s390/s390_ext.h30
-rw-r--r--include/asm-s390/s390dyn.h44
-rw-r--r--include/asm-s390/s390io.h14
-rw-r--r--include/asm-s390/s390mach.h75
-rw-r--r--include/asm-s390/scatterlist.h13
-rw-r--r--include/asm-s390/semaphore.h20
-rw-r--r--include/asm-s390/setup.h1
-rw-r--r--include/asm-s390/sigcontext.h40
-rw-r--r--include/asm-s390/siginfo.h35
-rw-r--r--include/asm-s390/sigp.h104
-rw-r--r--include/asm-s390/smp.h12
-rw-r--r--include/asm-s390/smplock.h4
-rw-r--r--include/asm-s390/socket.h2
-rw-r--r--include/asm-s390/spinlock.h62
-rw-r--r--include/asm-s390/stat.h32
-rw-r--r--include/asm-s390/string.h24
-rw-r--r--include/asm-s390/system.h45
-rw-r--r--include/asm-s390/termios.h21
-rw-r--r--include/asm-s390/todclk.h19
-rw-r--r--include/asm-s390/uaccess.h262
-rw-r--r--include/asm-s390/ucontext.h4
-rw-r--r--include/asm-s390/unistd.h3
56 files changed, 2289 insertions, 1135 deletions
diff --git a/include/asm-s390/atomic.h b/include/asm-s390/atomic.h
index f1c1f3c5d..d7ced05e8 100644
--- a/include/asm-s390/atomic.h
+++ b/include/asm-s390/atomic.h
@@ -38,74 +38,80 @@ static __inline__ void atomic_set(atomic_t *v, int i)
{
__asm__ __volatile__("st %1,%0\n\t"
"bcr 15,0"
- : : "m" (*v), "d" (i) : "memory");
+ : "=m" (*v) : "d" (i) );
}
static __inline__ void atomic_add(int i, atomic_t *v)
{
- __asm__ __volatile__(" l 0,%0\n"
+ __asm__ __volatile__(" la 2,%0\n"
+ " l 0,%0\n"
"0: lr 1,0\n"
" ar 1,%1\n"
- " cs 0,1,%0\n"
+ " cs 0,1,0(2)\n"
" jl 0b"
- : "+m" (*v) : "d" (i) : "0", "1" );
+ : "+m" (*v) : "d" (i) : "0", "1", "2", "cc" );
}
static __inline__ int atomic_add_return (int i, atomic_t *v)
{
int newval;
- __asm__ __volatile__(" l 0,%0\n"
+ __asm__ __volatile__(" la 1,%0\n"
+ " l 0,%0\n"
"0: lr %1,0\n"
" ar %1,%2\n"
- " cs 0,%1,%0\n"
+ " cs 0,%1,0(1)\n"
" jl 0b"
: "+m" (*v), "=&d" (newval)
- : "d" (i) : "0", "cc" );
+ : "d" (i) : "0", "1", "cc" );
return newval;
}
static __inline__ int atomic_add_negative(int i, atomic_t *v)
{
int newval;
- __asm__ __volatile__(" l 0,%0\n"
+ __asm__ __volatile__(" la 1,%0\n"
+ " l 0,%0\n"
"0: lr %1,0\n"
" ar %1,%2\n"
- " cs 0,%1,%0\n"
+ " cs 0,%1,0(1)\n"
" jl 0b\n"
: "+m" (*v), "=&d" (newval)
- : "d" (i) : "0", "cc" );
+ : "d" (i) : "0", "1", "cc" );
return newval < 0;
}
static __inline__ void atomic_sub(int i, atomic_t *v)
{
- __asm__ __volatile__(" l 0,%0\n"
+ __asm__ __volatile__(" la 2,%0\n"
+ " l 0,%0\n"
"0: lr 1,0\n"
" sr 1,%1\n"
- " cs 0,1,%0\n"
+ " cs 0,1,0(2)\n"
" jl 0b"
- : "+m" (*v) : "d" (i) : "0", "1" );
+ : "+m" (*v) : "d" (i) : "0", "1", "2", "cc" );
}
static __inline__ void atomic_inc(volatile atomic_t *v)
{
- __asm__ __volatile__(" l 0,%0\n"
+ __asm__ __volatile__(" la 2,%0\n"
+ " l 0,%0\n"
"0: lr 1,0\n"
" ahi 1,1\n"
- " cs 0,1,%0\n"
+ " cs 0,1,0(2)\n"
" jl 0b"
- : "+m" (*v) : : "0", "1" );
+ : "+m" (*v) : : "0", "1", "2", "cc" );
}
static __inline__ int atomic_inc_return(volatile atomic_t *v)
{
int i;
- __asm__ __volatile__(" l 0,%0\n"
+ __asm__ __volatile__(" la 1,%0\n"
+ " l 0,%0\n"
"0: lr %1,0\n"
" ahi %1,1\n"
- " cs 0,%1,%0\n"
+ " cs 0,%1,0(1)\n"
" jl 0b"
- : "+m" (*v), "=&d" (i) : : "0" );
+ : "+m" (*v), "=&d" (i) : : "0", "1", "cc" );
return i;
}
@@ -113,67 +119,74 @@ static __inline__ int atomic_inc_and_test(volatile atomic_t *v)
{
int i;
- __asm__ __volatile__(" l 0,%0\n"
+ __asm__ __volatile__(" la 1,%0\n"
+ " l 0,%0\n"
"0: lr %1,0\n"
" ahi %1,1\n"
- " cs 0,%1,%0\n"
+ " cs 0,%1,0(1)\n"
" jl 0b"
- : "+m" (*v), "=&d" (i) : : "0" );
+ : "+m" (*v), "=&d" (i) : : "0", "1", "cc" );
return i != 0;
}
static __inline__ void atomic_dec(volatile atomic_t *v)
{
- __asm__ __volatile__(" l 0,%0\n"
+ __asm__ __volatile__(" la 2,%0\n"
+ " l 0,%0\n"
"0: lr 1,0\n"
" ahi 1,-1\n"
- " cs 0,1,%0\n"
+ " cs 0,1,0(2)\n"
" jl 0b"
- : "+m" (*v) : : "0", "1" );
+ : "+m" (*v) : : "0", "1", "2", "cc" );
}
static __inline__ int atomic_dec_return(volatile atomic_t *v)
{
int i;
- __asm__ __volatile__(" l 0,%0\n"
+ __asm__ __volatile__(" la 1,%0\n"
+ " l 0,%0\n"
"0: lr %1,0\n"
" ahi %1,-1\n"
- " cs 0,%1,%0\n"
+ " cs 0,%1,0(1)\n"
" jl 0b"
- : "+m" (*v), "=&d" (i) : : "0" );
+ : "+m" (*v), "=&d" (i) : : "0", "1", "cc" );
return i;
}
static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
{
int i;
- __asm__ __volatile__(" l 0,%0\n"
+ __asm__ __volatile__(" la 1,%0\n"
+ " l 0,%0\n"
"0: lr %1,0\n"
" ahi %1,-1\n"
- " cs 0,%1,%0\n"
+ " cs 0,%1,0(1)\n"
" jl 0b"
- : "+m" (*v), "=&d" (i) : : "0");
+ : "+m" (*v), "=&d" (i) : : "0", "1", "cc" );
return i == 0;
}
static __inline__ void atomic_clear_mask(unsigned long mask, atomic_t *v)
{
- __asm__ __volatile__(" l 0,%0\n"
+ __asm__ __volatile__(" la 2,%0\n"
+ " l 0,%0\n"
"0: lr 1,0\n"
" nr 1,%1\n"
- " cs 0,1,%0\n"
+ " cs 0,1,0(2)\n"
" jl 0b"
- : "+m" (*v) : "d" (~(mask)) : "0", "1" );
+ : "+m" (*v) : "d" (~(mask))
+ : "0", "1", "2", "cc" );
}
static __inline__ void atomic_set_mask(unsigned long mask, atomic_t *v)
{
- __asm__ __volatile__(" l 0,%0\n"
+ __asm__ __volatile__(" la 2,%0\n"
+ " l 0,%0\n"
"0: lr 1,0\n"
" or 1,%1\n"
- " cs 0,1,%0\n"
+ " cs 0,1,0(2)\n"
" jl 0b"
- : "+m" (*v) : "d" (mask) : "0", "1" );
+ : "+m" (*v) : "d" (mask) : "0", "1", "2", "cc" );
}
/*
@@ -186,13 +199,15 @@ atomic_compare_and_swap(int expected_oldval,int new_val,atomic_t *v)
int retval;
__asm__ __volatile__(
- " cs %2,%3,%1\n"
+ " la 1,%1\n"
+ " lr 0,%2\n"
+ " cs 0,%3,0(1)\n"
" ipm %0\n"
" srl %0,28\n"
"0:"
: "=&r" (retval), "+m" (*v)
: "d" (expected_oldval) , "d" (new_val)
- : "memory", "cc");
+ : "0", "1", "cc");
return retval;
}
@@ -203,12 +218,20 @@ static __inline__ void
atomic_compare_and_swap_spin(int expected_oldval,int new_val,atomic_t *v)
{
__asm__ __volatile__(
+ " la 2,%0\n"
"0: lr 1,%1\n"
- " cs 1,%2,%0\n"
+ " cs 1,%2,0(2)\n"
" jl 0b\n"
: "+m" (*v)
: "d" (expected_oldval) , "d" (new_val)
- : "memory", "cc", "1");
+ : "cc", "1", "2");
+}
+
+#define atomic_compare_and_swap_debug(where,from,to) \
+if (atomic_compare_and_swap ((from), (to), (where))) {\
+ printk (KERN_WARNING"%s/%d atomic counter:%s couldn't be changed from %d(%s) to %d(%s), was %d\n",\
+ __FILE__,__LINE__,#where,(from),#from,(to),#to,atomic_read (where));\
+ atomic_set(where,(to));\
}
#endif /* __ARCH_S390_ATOMIC __ */
diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h
index 710cf8829..f441451c8 100644
--- a/include/asm-s390/bitops.h
+++ b/include/asm-s390/bitops.h
@@ -41,32 +41,11 @@ extern const char _oi_bitmap[];
extern const char _ni_bitmap[];
extern const char _zb_findmap[];
-/*
- * Function prototypes to keep gcc -Wall happy
- */
-extern void __set_bit(int nr, volatile void * addr);
-extern void __constant_set_bit(int nr, volatile void * addr);
-extern int __test_bit(int nr, volatile void * addr);
-extern int __constant_test_bit(int nr, volatile void * addr);
-extern void __clear_bit(int nr, volatile void * addr);
-extern void __constant_clear_bit(int nr, volatile void * addr);
-extern void __change_bit(int nr, volatile void * addr);
-extern void __constant_change_bit(int nr, volatile void * addr);
-extern int test_and_set_bit(int nr, volatile void * addr);
-extern int test_and_clear_bit(int nr, volatile void * addr);
-extern int test_and_change_bit(int nr, volatile void * addr);
-extern int test_and_set_bit_simple(int nr, volatile void * addr);
-extern int test_and_clear_bit_simple(int nr, volatile void * addr);
-extern int test_and_change_bit_simple(int nr, volatile void * addr);
-extern int find_first_zero_bit(void * addr, unsigned size);
-extern int find_next_zero_bit (void * addr, int size, int offset);
-extern unsigned long ffz(unsigned long word);
-
#ifdef CONFIG_SMP
/*
* SMP save set_bit routine based on compare and swap (CS)
*/
-extern __inline__ void set_bit_cs(int nr, volatile void * addr)
+static __inline__ void set_bit_cs(int nr, volatile void * addr)
{
__asm__ __volatile__(
#if ALIGN_CS == 1
@@ -80,8 +59,8 @@ extern __inline__ void set_bit_cs(int nr, volatile void * addr)
" nr 1,%0\n" /* make shift value */
" xr %0,1\n"
" srl %0,3\n"
- " la %1,0(%0,%1)\n" /* calc. address for CS */
" lhi 2,1\n"
+ " la %1,0(%0,%1)\n" /* calc. address for CS */
" sll 2,0(1)\n" /* make OR mask */
" l %0,0(%1)\n"
"0: lr 1,%0\n" /* CS loop starts here */
@@ -95,7 +74,7 @@ extern __inline__ void set_bit_cs(int nr, volatile void * addr)
/*
* SMP save clear_bit routine based on compare and swap (CS)
*/
-extern __inline__ void clear_bit_cs(int nr, volatile void * addr)
+static __inline__ void clear_bit_cs(int nr, volatile void * addr)
{
static const int mask = -1;
__asm__ __volatile__(
@@ -110,8 +89,8 @@ extern __inline__ void clear_bit_cs(int nr, volatile void * addr)
" nr 1,%0\n" /* make shift value */
" xr %0,1\n"
" srl %0,3\n"
- " la %1,0(%0,%1)\n" /* calc. address for CS */
" lhi 2,1\n"
+ " la %1,0(%0,%1)\n" /* calc. address for CS */
" sll 2,0(1)\n"
" x 2,%2\n" /* make AND mask */
" l %0,0(%1)\n"
@@ -126,7 +105,7 @@ extern __inline__ void clear_bit_cs(int nr, volatile void * addr)
/*
* SMP save change_bit routine based on compare and swap (CS)
*/
-extern __inline__ void change_bit_cs(int nr, volatile void * addr)
+static __inline__ void change_bit_cs(int nr, volatile void * addr)
{
__asm__ __volatile__(
#if ALIGN_CS == 1
@@ -140,8 +119,8 @@ extern __inline__ void change_bit_cs(int nr, volatile void * addr)
" nr 1,%0\n" /* make shift value */
" xr %0,1\n"
" srl %0,3\n"
- " la %1,0(%0,%1)\n" /* calc. address for CS */
" lhi 2,1\n"
+ " la %1,0(%0,%1)\n" /* calc. address for CS */
" sll 2,0(1)\n" /* make XR mask */
" l %0,0(%1)\n"
"0: lr 1,%0\n" /* CS loop starts here */
@@ -155,7 +134,7 @@ extern __inline__ void change_bit_cs(int nr, volatile void * addr)
/*
* SMP save test_and_set_bit routine based on compare and swap (CS)
*/
-extern __inline__ int test_and_set_bit_cs(int nr, volatile void * addr)
+static __inline__ int test_and_set_bit_cs(int nr, volatile void * addr)
{
__asm__ __volatile__(
#if ALIGN_CS == 1
@@ -186,7 +165,7 @@ extern __inline__ int test_and_set_bit_cs(int nr, volatile void * addr)
/*
* SMP save test_and_clear_bit routine based on compare and swap (CS)
*/
-extern __inline__ int test_and_clear_bit_cs(int nr, volatile void * addr)
+static __inline__ int test_and_clear_bit_cs(int nr, volatile void * addr)
{
static const int mask = -1;
__asm__ __volatile__(
@@ -220,7 +199,7 @@ extern __inline__ int test_and_clear_bit_cs(int nr, volatile void * addr)
/*
* SMP save test_and_change_bit routine based on compare and swap (CS)
*/
-extern __inline__ int test_and_change_bit_cs(int nr, volatile void * addr)
+static __inline__ int test_and_change_bit_cs(int nr, volatile void * addr)
{
__asm__ __volatile__(
#if ALIGN_CS == 1
@@ -252,7 +231,7 @@ extern __inline__ int test_and_change_bit_cs(int nr, volatile void * addr)
/*
* fast, non-SMP set_bit routine
*/
-extern __inline__ void __set_bit(int nr, volatile void * addr)
+static __inline__ void __set_bit(int nr, volatile void * addr)
{
__asm__ __volatile__(
" lhi 2,24\n"
@@ -267,7 +246,7 @@ extern __inline__ void __set_bit(int nr, volatile void * addr)
: "cc", "memory", "1", "2" );
}
-extern __inline__ void
+static __inline__ void
__constant_set_bit(const int nr, volatile void * addr)
{
switch (nr&7) {
@@ -330,7 +309,7 @@ __constant_set_bit(const int nr, volatile void * addr)
/*
* fast, non-SMP clear_bit routine
*/
-extern __inline__ void
+static __inline__ void
__clear_bit(int nr, volatile void * addr)
{
__asm__ __volatile__(
@@ -346,7 +325,7 @@ __clear_bit(int nr, volatile void * addr)
: "cc", "memory", "1", "2" );
}
-extern __inline__ void
+static __inline__ void
__constant_clear_bit(const int nr, volatile void * addr)
{
switch (nr&7) {
@@ -409,7 +388,7 @@ __constant_clear_bit(const int nr, volatile void * addr)
/*
* fast, non-SMP change_bit routine
*/
-extern __inline__ void __change_bit(int nr, volatile void * addr)
+static __inline__ void __change_bit(int nr, volatile void * addr)
{
__asm__ __volatile__(
" lhi 2,24\n"
@@ -424,7 +403,7 @@ extern __inline__ void __change_bit(int nr, volatile void * addr)
: "cc", "memory", "1", "2" );
}
-extern __inline__ void
+static __inline__ void
__constant_change_bit(const int nr, volatile void * addr)
{
switch (nr&7) {
@@ -487,7 +466,7 @@ __constant_change_bit(const int nr, volatile void * addr)
/*
* fast, non-SMP test_and_set_bit routine
*/
-extern __inline__ int test_and_set_bit_simple(int nr, volatile void * addr)
+static __inline__ int test_and_set_bit_simple(int nr, volatile void * addr)
{
static const int mask = 1;
int oldbit;
@@ -512,7 +491,7 @@ extern __inline__ int test_and_set_bit_simple(int nr, volatile void * addr)
/*
* fast, non-SMP test_and_clear_bit routine
*/
-extern __inline__ int test_and_clear_bit_simple(int nr, volatile void * addr)
+static __inline__ int test_and_clear_bit_simple(int nr, volatile void * addr)
{
static const int mask = 1;
int oldbit;
@@ -538,7 +517,7 @@ extern __inline__ int test_and_clear_bit_simple(int nr, volatile void * addr)
/*
* fast, non-SMP test_and_change_bit routine
*/
-extern __inline__ int test_and_change_bit_simple(int nr, volatile void * addr)
+static __inline__ int test_and_change_bit_simple(int nr, volatile void * addr)
{
static const int mask = 1;
int oldbit;
@@ -582,7 +561,7 @@ extern __inline__ int test_and_change_bit_simple(int nr, volatile void * addr)
* This routine doesn't need to be atomic.
*/
-extern __inline__ int __test_bit(int nr, volatile void * addr)
+static __inline__ int __test_bit(int nr, volatile void * addr)
{
static const int mask = 1;
int oldbit;
@@ -602,7 +581,7 @@ extern __inline__ int __test_bit(int nr, volatile void * addr)
return oldbit;
}
-extern __inline__ int __constant_test_bit(int nr, volatile void * addr) {
+static __inline__ int __constant_test_bit(int nr, volatile void * addr) {
return (((volatile char *) addr)[(nr>>3)^3] & (1<<(nr&7))) != 0;
}
@@ -614,7 +593,7 @@ extern __inline__ int __constant_test_bit(int nr, volatile void * addr) {
/*
* Find-bit routines..
*/
-extern __inline__ int find_first_zero_bit(void * addr, unsigned size)
+static __inline__ int find_first_zero_bit(void * addr, unsigned size)
{
static const int mask = 0xffL;
int res;
@@ -633,7 +612,7 @@ extern __inline__ int find_first_zero_bit(void * addr, unsigned size)
" lr 2,%1\n"
" j 4f\n"
"1: l 1,0(2,%2)\n"
- " sll 2,3(0)\n"
+ " sll 2,3\n"
" tml 1,0xFFFF\n"
" jno 2f\n"
" ahi 2,16\n"
@@ -653,7 +632,7 @@ extern __inline__ int find_first_zero_bit(void * addr, unsigned size)
return (res < size) ? res : size;
}
-extern __inline__ int find_next_zero_bit (void * addr, int size, int offset)
+static __inline__ int find_next_zero_bit (void * addr, int size, int offset)
{
static const int mask = 0xffL;
unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
@@ -698,7 +677,7 @@ extern __inline__ int find_next_zero_bit (void * addr, int size, int offset)
* ffz = Find First Zero in word. Undefined if no zero exists,
* so code should check against ~0UL first..
*/
-extern __inline__ unsigned long ffz(unsigned long word)
+static __inline__ unsigned long ffz(unsigned long word)
{
static const int mask = 0xffL;
int result;
@@ -738,24 +717,24 @@ extern int __inline__ ffs (int x)
return 0;
__asm__(" lr %%r1,%1\n"
" sr %0,%0\n"
- " tmh %%r1,0xFFFF\n"
- " jz 0f\n"
+ " tml %%r1,0xFFFF\n"
+ " jnz 0f\n"
" ahi %0,16\n"
" srl %%r1,16\n"
- "0: tml %%r1,0xFF00\n"
- " jz 1f\n"
+ "0: tml %%r1,0x00FF\n"
+ " jnz 1f\n"
" ahi %0,8\n"
" srl %%r1,8\n"
- "1: tml %%r1,0x00F0\n"
- " jz 2f\n"
+ "1: tml %%r1,0x000F\n"
+ " jnz 2f\n"
" ahi %0,4\n"
" srl %%r1,4\n"
- "2: tml %%r1,0x000C\n"
- " jz 3f\n"
+ "2: tml %%r1,0x0003\n"
+ " jnz 3f\n"
" ahi %0,2\n"
" srl %%r1,2\n"
- "3: tml %%r1,0x0002\n"
- " jz 4f\n"
+ "3: tml %%r1,0x0001\n"
+ " jnz 4f\n"
" ahi %0,1\n"
"4:"
: "=&d" (r) : "d" (x) : "cc", "1" );
@@ -787,9 +766,8 @@ extern int __inline__ ffs (int x)
#define ext2_set_bit(nr, addr) test_and_set_bit((nr)^24, addr)
#define ext2_clear_bit(nr, addr) test_and_clear_bit((nr)^24, addr)
#define ext2_test_bit(nr, addr) test_bit((nr)^24, addr)
-extern __inline__ int ext2_find_first_zero_bit(void *vaddr, unsigned size)
+static __inline__ int ext2_find_first_zero_bit(void *vaddr, unsigned size)
{
- static const int mask = 0xffL;
int res;
if (!size)
@@ -806,7 +784,8 @@ extern __inline__ int ext2_find_first_zero_bit(void *vaddr, unsigned size)
" lr 2,%1\n"
" j 4f\n"
"1: l 1,0(2,%2)\n"
- " sll 2,3(0)\n"
+ " sll 2,3\n"
+ " lhi 0,0xff\n"
" ahi 2,24\n"
" tmh 1,0xFFFF\n"
" jo 2f\n"
@@ -816,31 +795,19 @@ extern __inline__ int ext2_find_first_zero_bit(void *vaddr, unsigned size)
" jo 3f\n"
" ahi 2,-8\n"
" srl 1,8\n"
- "3: n 1,%3\n"
- " ic 1,0(1,%4)\n"
- " n 1,%3\n"
+ "3: nr 1,0\n"
+ " ic 1,0(1,%3)\n"
" ar 2,1\n"
"4: lr %0,2"
: "=d" (res) : "a" (size), "a" (vaddr),
- "m" (mask), "a" (&_zb_findmap)
+ "a" (&_zb_findmap)
: "cc", "0", "1", "2" );
return (res < size) ? res : size;
}
-extern __inline__ int
+static __inline__ int
ext2_find_next_zero_bit(void *vaddr, unsigned size, unsigned offset)
{
- static const int mask = 0xffL;
- static unsigned long orword[32] = {
- 0x00000000, 0x01000000, 0x03000000, 0x07000000,
- 0x0f000000, 0x1f000000, 0x3f000000, 0x7f000000,
- 0xff000000, 0xff010000, 0xff030000, 0xff070000,
- 0xff0f0000, 0xff1f0000, 0xff3f0000, 0xff7f0000,
- 0xffff0000, 0xffff0100, 0xffff0300, 0xffff0700,
- 0xffff0f00, 0xffff1f00, 0xffff3f00, 0xffff7f00,
- 0xffffff00, 0xffffff01, 0xffffff03, 0xffffff07,
- 0xffffff0f, 0xffffff1f, 0xffffff3f, 0xffffff7f
- };
unsigned long *addr = vaddr;
unsigned long *p = addr + (offset >> 5);
unsigned long word;
@@ -850,23 +817,29 @@ ext2_find_next_zero_bit(void *vaddr, unsigned size, unsigned offset)
return size;
if (bit) {
- word = *p | orword[bit];
+ __asm__(" ic %0,0(%1)\n"
+ " icm %0,2,1(%1)\n"
+ " icm %0,4,2(%1)\n"
+ " icm %0,8,3(%1)"
+ : "=&a" (word) : "a" (p) );
+ word >>= bit;
+ res = bit;
/* Look for zero in first longword */
- __asm__(" lhi %0,24\n"
- " tmh %1,0xFFFF\n"
- " jo 0f\n"
- " ahi %0,-16\n"
+ __asm__(" lhi 0,0xff\n"
+ " tml %1,0xffff\n"
+ " jno 0f\n"
+ " ahi %0,16\n"
" srl %1,16\n"
- "0: tml %1,0xFF00\n"
- " jo 1f\n"
- " ahi %0,-8\n"
+ "0: tml %1,0x00ff\n"
+ " jno 1f\n"
+ " ahi %0,8\n"
" srl %1,8\n"
- "1: n %1,%2\n"
- " ic %1,0(%1,%3)\n"
+ "1: nr %1,0\n"
+ " ic %1,0(%1,%2)\n"
" alr %0,%1"
- : "=&d" (res), "+&d" (word)
- : "m" (mask), "a" (&_zb_findmap)
- : "cc" );
+ : "+&d" (res), "+&a" (word)
+ : "a" (&_zb_findmap)
+ : "cc", "0" );
if (res < 32)
return (p - addr)*32 + res;
p++;
diff --git a/include/asm-s390/ccwcache.h b/include/asm-s390/ccwcache.h
new file mode 100644
index 000000000..cfbb03bf2
--- /dev/null
+++ b/include/asm-s390/ccwcache.h
@@ -0,0 +1,84 @@
+/*
+ * File...........: linux/include/asm-s390/ccwcache.h
+ * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ * Bugreports.to..: <Linux390@de.ibm.com>
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
+ */
+#ifndef CCWCACHE_H
+#define CCWCACHE_H
+#include <linux/slab.h>
+#include <asm/irq.h>
+
+#ifndef __KERNEL__
+#define kmem_cache_t void
+#endif /* __KERNEL__ */
+
+typedef struct ccw_req_t {
+ /* eye catcher plus queueing information */
+ unsigned int magic;
+ struct ccw_req_t *next; /* pointer to next ccw_req_t in queue */
+ struct ccw_req_t *int_next; /* for internal queueing */
+ struct ccw_req_t *int_prev; /* for internal queueing */
+
+ /* Where to execute what... */
+ void *device; /* index of the device the req is for */
+ void *req; /* pointer to originating request */
+ ccw1_t *cpaddr; /* address of channel program */
+ char status; /* reflecting the status of this request */
+ char flags; /* see below */
+ short retries; /* A retry counter to be set when filling */
+
+ /* ... and how */
+ int options; /* options for execution */
+ char lpm; /* logical path mask */
+ void *data; /* pointer to data area */
+ devstat_t *dstat; /* The device status in case of an error */
+
+ /* these are important for recovering erroneous requests */
+ struct ccw_req_t *refers; /* Does this request refer to another one? */
+ void *function; /* refers to the originating ERP action */ ;
+
+ unsigned long long expires; /* expiratioj period */
+ /* these are for profiling purposes */
+ unsigned long long buildclk; /* TOD-clock of request generation */
+ unsigned long long startclk; /* TOD-clock of request start */
+ unsigned long long stopclk; /* TOD-clock of request interrupt */
+ unsigned long long endclk; /* TOD-clock of request termination */
+
+ /* these are for internal use */
+ int cplength; /* length of the channel program in CCWs */
+ int datasize; /* amount of additional data in bytes */
+ kmem_cache_t *cache; /* the cache this data comes from */
+
+} __attribute__ ((aligned(4))) ccw_req_t;
+
+/*
+ * ccw_req_t -> status can be:
+ */
+#define CQR_STATUS_EMPTY 0x00 /* request is empty */
+#define CQR_STATUS_FILLED 0x01 /* request is ready to be preocessed */
+#define CQR_STATUS_QUEUED 0x02 /* request is queued to be processed */
+#define CQR_STATUS_IN_IO 0x03 /* request is currently in IO */
+#define CQR_STATUS_DONE 0x04 /* request is completed sucessfully */
+#define CQR_STATUS_ERROR 0x05 /* request is completed with error */
+#define CQR_STATUS_FAILED 0x06 /* request is finally failed */
+
+#define CQR_FLAGS_CHAINED 0x01 /* request is chained by another (last CCW is TIC) */
+
+#ifdef __KERNEL__
+#define SMALLEST_SLAB (sizeof(struct ccw_req_t) <= 128 ? 128 :\
+ sizeof(struct ccw_req_t) <= 256 ? 256 : 512 )
+
+/* SMALLEST_SLAB(1),... PAGE_SIZE(CCW_NUMBER_CACHES) */
+#define CCW_NUMBER_CACHES (sizeof(struct ccw_req_t) <= 128 ? 6 :\
+ sizeof(struct ccw_req_t) <= 256 ? 5 : 4 )
+
+int ccwcache_init (void);
+
+ccw_req_t *ccw_alloc_request (char *magic, int cplength, int additional_data);
+void ccw_free_request (ccw_req_t * request);
+#endif /* __KERNEL__ */
+#endif /* CCWCACHE_H */
+
+
+
diff --git a/include/asm-s390/chandev.h b/include/asm-s390/chandev.h
index c9e7d2d54..9efb6fea3 100644
--- a/include/asm-s390/chandev.h
+++ b/include/asm-s390/chandev.h
@@ -1,87 +1,151 @@
/*
* include/asm-s390/chandev.h
*
- * S390 version
* Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
- *
+ *
+ * Generic channel device initialisation support.
*/
-
+#include <linux/version.h>
#include <asm/types.h>
+#include <linux/netdevice.h>
+/* chandev_type is a bitmask for registering & describing device types. */
typedef enum
{
- none=0,
- ctc=1,
- escon=2,
- lcs=4,
- osad=8,
- claw=16,
+ none=0x0,
+ ctc=0x1,
+ escon=0x2,
+ lcs=0x4,
+ osad=0x8,
+ qeth=0x10,
+ claw=0x20,
} chandev_type;
-typedef struct chandev_model_info chandev_model_info;
-
-struct chandev_model_info
-{
- struct chandev_model_info *next;
- chandev_type chan_type;
- u16 cu_type;
- u8 cu_model;
- u8 max_port_no;
-};
-
-typedef struct chandev chandev;
-struct chandev
-{
- struct chandev *next;
- chandev_model_info *model_info;
- u16 devno;
- int irq;
-};
-
-typedef struct chandev_noauto_range chandev_noauto_range;
-struct chandev_noauto_range
-{
- struct chandev_noauto_range *next;
- u16 lo_devno;
- u16 hi_devno;
-};
-
-typedef struct chandev_force chandev_force;
-struct chandev_force
+typedef enum
{
- struct chandev_force *next;
- chandev_type chan_type;
- s32 devif_num; /* -1 don't care e.g. tr0 implies 0 */
- u16 read_devno;
- u16 write_devno;
- s16 port_no; /* where available e.g. lcs,-1 don't care */
- u8 do_ip_checksumming;
- u8 use_hw_stats; /* where available e.g. lcs */
-};
-
-
+ no_category,
+ network_device,
+ serial_device,
+} chandev_category;
+/*
+ * The chandev_probeinfo structure is passed to the device driver with configuration
+ * info for which irq's & ports to use when attempting to probe the device.
+ */
typedef struct
{
- s32 devif_num; /* -1 don't care e.g. tr0 implies 0 */
int read_irq;
int write_irq;
- s16 forced_port_no; /* -1 don't care */
- u8 hint_port_no;
- u8 max_port_no;
- u8 do_ip_checksumming;
+ u16 read_devno;
+ u16 write_devno;
+ s16 port_protocol_no; /* -1 don't care */
+ u8 hint_port_no; /* lcs specific */
+ u8 max_port_no; /* lcs specific */
+ chandev_type chan_type;
+ u8 checksum_received_ip_pkts;
u8 use_hw_stats; /* where available e.g. lcs */
+ u16 cu_type; /* control unit type */
+ u8 cu_model; /* control unit model */
+ u16 dev_type; /* device type */
+ u8 dev_model; /* device model */
+ char *parmstr; /* driver specific parameters added by add_parms keyword */
+ /* newdevice used internally by chandev.c */
+ struct chandev_activelist *newdevice;
+ s32 devif_num;
+/* devif_num=-1 implies don't care,0 implies tr0, info used by chandev_initnetdevice */
} chandev_probeinfo;
+/*
+ * This is a wrapper to the machine check handler & should be used
+ * instead of reqest_irq or s390_request_irq_special for anything
+ * using the channel device layer.
+ */
+int chandev_request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long irqflags,
+ const char *devname,
+ void *dev_id);
+
+typedef enum
+{
+ good=0,
+ not_oper,
+ first_msck=not_oper,
+ no_path,
+ revalidate,
+ gone,
+ last_msck,
+} chandev_msck_status;
typedef int (*chandev_probefunc)(chandev_probeinfo *probeinfo);
+typedef void (*chandev_shutdownfunc)(void *device);
+typedef void (*chandev_unregfunc)(void *device);
+typedef void (*chandev_reoperfunc)(void *device,int msck_for_read_chan,chandev_msck_status prevstatus);
+
+
+
+/* A driver should call chandev_register_and_probe when ready to be probed,
+ * after registeration the drivers probefunction will be called asynchronously
+ * when more devices become available at normal task time.
+ * The shutdownfunc parameter is used so that the channel layer
+ * can request a driver to close unregister itself & release its interrupts.
+ * repoper func is used when a device becomes operational again after being temporarily
+ * not operational the previous status is sent in the prevstatus variable.
+ * This can be used in cases when the default handling isn't quite adequete
+ * e.g. if a ssch is needed to reinitialize long running channel programs.
+ */
+int chandev_register_and_probe(chandev_probefunc probefunc,
+ chandev_shutdownfunc shutdownfunc,
+ chandev_reoperfunc reoperfunc,
+ chandev_type chan_type);
+
+/* The chandev_unregister function is typically called when a module is being removed
+ * from the system. The shutdown parameter if TRUE calls shutdownfunc for each
+ * device instance so the driver writer doesn't have to.
+ */
+void chandev_unregister(chandev_probefunc probefunc,int call_shutdown);
+
+/* chandev_initdevice should be called immeadiately before returning after */
+/* a successful probe. */
+int chandev_initdevice(chandev_probeinfo *probeinfo,void *dev_ptr,u8 port_no,char *devname,
+chandev_category category,chandev_unregfunc unreg_dev);
+
+/* chandev_initnetdevice registers a network device with the channel layer.
+ * It returns the device structure if successful,if dev=NULL it kmallocs it,
+ * On device initialisation failure it will kfree it under ALL curcumstances
+ * i.e. if dev is not NULL on entering this routine it MUST be malloced with kmalloc.
+ * The base name is tr ( e.g. tr0 without the 0 ), for token ring eth for ethernet,
+ * ctc or escon for ctc device drivers.
+ * If valid function pointers are given they will be called to setup,
+ * register & unregister the device.
+ * An example of setup is eth_setup in drivers/net/net_init.c.
+ * An example of init_dev is init_trdev(struct net_device *dev)
+ * & an example of unregister is unregister_trdev,
+ * unregister_netdev should be used for escon & ctc
+ * as there is no network unregister_ctcdev in the kernel.
+*/
+
+#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
+struct net_device *chandev_initnetdevice(chandev_probeinfo *probeinfo,u8 port_no,
+ struct net_device *dev,int sizeof_priv,
+ char *basename,
+ struct net_device *(*init_netdevfunc)
+ (struct net_device *dev, int sizeof_priv),
+ void (*unreg_netdevfunc)(struct net_device *dev));
+#else
+struct device *chandev_initnetdevice(chandev_probeinfo *probeinfo,u8 port_no,
+ struct device *dev,int sizeof_priv,
+ char *basename,
+ struct device *(*init_netdevfunc)
+ (struct device *dev, int sizeof_priv),
+ void (*unreg_netdevfunc)(struct device *dev));
+#endif
+
+
+
+
+
+
-typedef struct chandev_probelist chandev_probelist;
-struct chandev_probelist
-{
- struct chandev_probelist *next;
- chandev_probefunc probefunc;
- chandev_type chan_type;
-};
diff --git a/include/asm-s390/checksum.h b/include/asm-s390/checksum.h
index 487ccc99b..cd0159a5b 100644
--- a/include/asm-s390/checksum.h
+++ b/include/asm-s390/checksum.h
@@ -141,20 +141,19 @@ csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
unsigned int sum)
{
__asm__ __volatile__ (
- " sll %3,16\n"
- " or %3,%4\n" /* newproto=proto<<16 in hiword, len in lowword */
- " alr %1,%2\n" /* saddr+=daddr */
- " brc 12,0f\n"
- " ahi %1,1\n" /* add carry */
- "0: alr %1,%3\n" /* add saddr+=newproto */
- " brc 12,1f\n"
- " ahi %1,1\n" /* add carry again */
- "1: alr %0,%1\n" /* sum+=saddr */
+ " alr %0,%1\n" /* sum += saddr */
+ " brc 12,0f\n"
+ " ahi %0,1\n" /* add carry */
+ "0: alr %0,%2\n" /* sum += daddr */
+ " brc 12,1f\n"
+ " ahi %0,1\n" /* add carry */
+ "1: alr %0,%3\n" /* sum += (len<<16) + (proto<<8) */
" brc 12,2f\n"
- " ahi %0,1\n" /* add carry again */
+ " ahi %0,1\n" /* add carry */
"2:"
: "+&d" (sum)
- : "d" (saddr), "d" (daddr), "d" (proto), "d" (len)
+ : "d" (saddr), "d" (daddr),
+ "d" (((unsigned int) len<<16) + (unsigned int) proto)
: "cc" );
return sum;
}
diff --git a/include/asm-s390/current.h b/include/asm-s390/current.h
index 42567eb94..88e8fc04e 100644
--- a/include/asm-s390/current.h
+++ b/include/asm-s390/current.h
@@ -20,7 +20,7 @@ static inline struct task_struct * get_current(void)
struct task_struct *current;
__asm__("lhi %0,-8192\n\t"
"nr %0,15"
- : "=r" (current) );
+ : "=&r" (current) );
return current;
}
diff --git a/include/asm-s390/dasd.h b/include/asm-s390/dasd.h
new file mode 100644
index 000000000..ea5e43eae
--- /dev/null
+++ b/include/asm-s390/dasd.h
@@ -0,0 +1,339 @@
+/*
+ * File...........: linux/drivers/s390/block/dasd.c
+ * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ * Bugreports.to..: <Linux390@de.ibm.com>
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+ *
+ * History of changes (starts July 2000)
+ */
+
+#ifndef DASD_H
+#define DASD_H
+
+#include <linux/ioctl.h>
+#include <asm/irq.h>
+
+#define IOCTL_LETTER 'D'
+/* Disable the volume (for Linux) */
+#define BIODASDDISABLE _IO(IOCTL_LETTER,0)
+/* Enable the volume (for Linux) */
+#define BIODASDENABLE _IO(IOCTL_LETTER,1)
+/* Issue a reserve/release command, rsp. */
+#define BIODASDRSRV _IO(IOCTL_LETTER,2) /* reserve */
+#define BIODASDRLSE _IO(IOCTL_LETTER,3) /* release */
+#define BIODASDSLCK _IO(IOCTL_LETTER,4) /* steal lock */
+/* Read sense ID infpormation */
+#define BIODASDRSID _IOR(IOCTL_LETTER,0,senseid_t)
+/* Format the volume or an extent */
+#define BIODASDFORMAT _IOW(IOCTL_LETTER,0,format_data_t)
+/* translate blocknumber of partition to absolute */
+#define BIODASDRWTB _IOWR(IOCTL_LETTER,0,int)
+
+#define DASD_NAME "dasd"
+#define DASD_PARTN_BITS 2
+#define DASD_PER_MAJOR ( 1U<<(MINORBITS-DASD_PARTN_BITS))
+
+/*
+ * struct format_data_t
+ * represents all data necessary to format a dasd
+ */
+typedef struct format_data_t {
+ int start_unit; /* from track */
+ int stop_unit; /* to track */
+ int blksize; /* sectorsize */
+ int intensity; /* 0: normal, 1:record zero, 3:home address, 4 invalidate tracks */
+} __attribute__ ((packed)) format_data_t;
+
+#define DASD_FORMAT_DEFAULT_START_UNIT 0
+#define DASD_FORMAT_DEFAULT_STOP_UNIT -1
+#define DASD_FORMAT_DEFAULT_BLOCKSIZE -1
+#define DASD_FORMAT_DEFAULT_INTENSITY -1
+
+#ifdef __KERNEL__
+#include <linux/version.h>
+#include <linux/major.h>
+#include <linux/wait.h>
+#include <asm/ccwcache.h>
+#include <linux/blk.h>
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+#include <linux/blkdev.h>
+#include <linux/devfs_fs_kernel.h>
+#endif
+#include <linux/genhd.h>
+#include <linux/hdreg.h>
+#include <linux/compatmac.h>
+
+#include <asm/s390dyn.h>
+#include <asm/todclk.h>
+#include <asm/debug.h>
+
+/* Kernel Version Compatibility section */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98))
+typedef struct request *request_queue_t;
+#define block_device_operations file_operations
+#define __setup(x,y) struct dasd_device_t
+#define devfs_register_blkdev(major,name,ops) register_blkdev(major,name,ops)
+#define register_disk(dd,dev,partn,ops,size) \
+do { \
+ dd->sizes[MINOR(dev)] = size >> 1; \
+ resetup_one_dev(dd,MINOR(dev)>>DASD_PARTN_BITS); \
+} while(0)
+#define init_waitqueue_head(x) do { *x = NULL; } while(0)
+#define blk_cleanup_queue(x) do {} while(0)
+#define blk_init_queue(x...) do {} while(0)
+#define blk_queue_headactive(x...) do {} while(0)
+#define blk_queue_make_request(x) do {} while(0)
+#define list_empty(x) (0)
+#define INIT_BLK_DEV(d_major,d_request_fn,d_queue_fn,d_current) \
+do { \
+ blk_dev[d_major].request_fn = d_request_fn; \
+ blk_dev[d_major].queue = d_queue_fn; \
+ blk_dev[d_major].current_request = d_current; \
+} while(0)
+#define INIT_GENDISK(D_MAJOR,D_NAME,D_PARTN_BITS,D_PER_MAJOR) \
+ major:D_MAJOR, \
+ major_name:D_NAME, \
+ minor_shift:D_PARTN_BITS, \
+ max_p:1 << D_PARTN_BITS, \
+ max_nr:D_PER_MAJOR, \
+ nr_real:D_PER_MAJOR,
+static inline struct request *
+dasd_next_request( request_queue_t *queue )
+{
+ return *queue;
+}
+static inline void
+dasd_dequeue_request( request_queue_t * q, struct request *req )
+{
+ *q = req->next;
+ req->next = NULL;
+}
+#else
+#define INIT_BLK_DEV(d_major,d_request_fn,d_queue_fn,d_current) \
+do { \
+ blk_dev[d_major].queue = d_queue_fn; \
+} while(0)
+#define INIT_GENDISK(D_MAJOR,D_NAME,D_PARTN_BITS,D_PER_MAJOR) \
+ major:D_MAJOR, \
+ major_name:D_NAME, \
+ minor_shift:D_PARTN_BITS, \
+ max_p:1 << D_PARTN_BITS, \
+ nr_real:D_PER_MAJOR,
+static inline struct request *
+dasd_next_request( request_queue_t *queue )
+{
+ return blkdev_entry_next_request(&queue->queue_head);
+}
+static inline void
+dasd_dequeue_request( request_queue_t * q, struct request *req )
+{
+ blkdev_dequeue_request (req);
+}
+#endif
+
+/* dasd_range_t are used for dynamic device att-/detachment */
+typedef struct dasd_devreg_t {
+ devreg_t devreg; /* the devreg itself */
+ /* build a linked list of devregs, needed for cleanup */
+ struct dasd_devreg_t *next;
+} dasd_devreg_t;
+
+typedef enum {
+ dasd_era_fatal = -1, /* no chance to recover */
+ dasd_era_none = 0, /* don't recover, everything alright */
+ dasd_era_msg = 1, /* don't recover, just report... */
+ dasd_era_recover = 2 /* recovery action recommended */
+} dasd_era_t;
+
+/* BIT DEFINITIONS FOR SENSE DATA */
+#define DASD_SENSE_BIT_0 0x80
+#define DASD_SENSE_BIT_1 0x40
+#define DASD_SENSE_BIT_2 0x20
+#define DASD_SENSE_BIT_3 0x10
+
+#define check_then_set(where,from,to) \
+do { \
+ if ((*(where)) != (from) ) { \
+ printk (KERN_ERR PRINTK_HEADER "was %d\n", *(where)); \
+ BUG(); \
+ } \
+ (*(where)) = (to); \
+} while (0)
+
+#define DASD_MESSAGE(d_loglevel,d_device,d_string,d_args...)\
+do { \
+ int d_devno = d_device->devinfo.devno; \
+ int d_irq = d_device->devinfo.irq; \
+ char *d_name = d_device->name; \
+ int d_major = MAJOR(d_device->kdev); \
+ int d_minor = MINOR(d_device->kdev); \
+ printk(d_loglevel PRINTK_HEADER \
+ "/dev/%s(%d:%d), 0x%04X on SCH 0x%x:" \
+ d_string "\n",d_name,d_major,d_minor,d_devno,d_irq,d_args ); \
+} while(0)
+
+/*
+ * struct dasd_sizes_t
+ * represents all data needed to access dasd with properly set up sectors
+ */
+typedef
+struct dasd_sizes_t {
+ unsigned long blocks; /* size of volume in blocks */
+ unsigned int bp_block; /* bytes per block */
+ unsigned int s2b_shift; /* log2 (bp_block/512) */
+} dasd_sizes_t;
+
+/*
+ * struct dasd_chanq_t
+ * represents a queue of channel programs related to a single device
+ */
+typedef
+struct dasd_chanq_t {
+ ccw_req_t *head;
+ ccw_req_t *tail;
+} dasd_chanq_t;
+
+struct dasd_device_t;
+struct request;
+
+/*
+ * signatures for the functions of dasd_discipline_t
+ * make typecasts much easier
+ */
+typedef ccw_req_t *(*dasd_erp_action_fn_t) (ccw_req_t * cqr);
+typedef ccw_req_t *(*dasd_erp_postaction_fn_t) (ccw_req_t * cqr);
+
+typedef int (*dasd_ck_id_fn_t) (s390_dev_info_t *);
+typedef int (*dasd_ck_characteristics_fn_t) (struct dasd_device_t *);
+typedef int (*dasd_fill_geometry_fn_t) (struct dasd_device_t *, struct hd_geometry *);
+typedef ccw_req_t *(*dasd_format_fn_t) (struct dasd_device_t *, struct format_data_t *);
+typedef ccw_req_t *(*dasd_init_analysis_fn_t) (struct dasd_device_t *);
+typedef int (*dasd_do_analysis_fn_t) (struct dasd_device_t *);
+typedef int (*dasd_io_starter_fn_t) (ccw_req_t *);
+typedef void (*dasd_int_handler_fn_t)(int irq, void *, struct pt_regs *);
+typedef dasd_era_t (*dasd_error_examine_fn_t) (ccw_req_t *, devstat_t * stat);
+typedef dasd_erp_action_fn_t (*dasd_error_analyse_fn_t) (ccw_req_t *);
+typedef dasd_erp_postaction_fn_t (*dasd_erp_analyse_fn_t) (ccw_req_t *);
+typedef ccw_req_t *(*dasd_cp_builder_fn_t)(struct dasd_device_t *,struct request *);
+typedef char *(*dasd_dump_sense_fn_t)(struct dasd_device_t *,ccw_req_t *);
+typedef ccw_req_t *(*dasd_reserve_fn_t)(struct dasd_device_t *);
+typedef ccw_req_t *(*dasd_release_fn_t)(struct dasd_device_t *);
+typedef ccw_req_t *(*dasd_merge_cp_fn_t)(struct dasd_device_t *);
+
+
+/*
+ * the dasd_discipline_t is
+ * sth like a table of virtual functions, if you think of dasd_eckd
+ * inheriting dasd...
+ * no, currently we are not planning to reimplement the driver in C++
+ */
+typedef struct dasd_discipline_t {
+ char ebcname[8]; /* a name used for tagging and printks */
+ char name[8]; /* a name used for tagging and printks */
+
+ dasd_ck_id_fn_t id_check; /* to check sense data */
+ dasd_ck_characteristics_fn_t check_characteristics; /* to check the characteristics */
+ dasd_init_analysis_fn_t init_analysis; /* to start the analysis of the volume */
+ dasd_do_analysis_fn_t do_analysis; /* to complete the analysis of the volume */
+ dasd_fill_geometry_fn_t fill_geometry; /* to set up hd_geometry */
+ dasd_io_starter_fn_t start_IO;
+ dasd_format_fn_t format_device; /* to format the device */
+ dasd_error_examine_fn_t examine_error;
+ dasd_error_analyse_fn_t erp_action;
+ dasd_erp_analyse_fn_t erp_postaction;
+ dasd_cp_builder_fn_t build_cp_from_req;
+ dasd_dump_sense_fn_t dump_sense;
+ dasd_int_handler_fn_t int_handler;
+ dasd_reserve_fn_t reserve;
+ dasd_release_fn_t release;
+ dasd_merge_cp_fn_t merge_cp;
+
+ struct dasd_discipline_t *next; /* used for list of disciplines */
+} dasd_discipline_t;
+
+typedef struct major_info_t {
+ struct major_info_t *next;
+ struct dasd_device_t **dasd_device;
+ struct gendisk gendisk; /* actually contains the major number */
+} __attribute__ ((packed)) major_info_t;
+
+typedef struct dasd_profile_info_t {
+ unsigned long dasd_io_reqs; /* number of requests processed at all */
+ unsigned long dasd_io_secs[32]; /* histogram of request's sizes */
+ unsigned long dasd_io_times[32]; /* histogram of requests's times */
+ unsigned long dasd_io_timps[32]; /* histogram of requests's times per sector */
+ unsigned long dasd_io_time1[32]; /* histogram of time from build to start */
+ unsigned long dasd_io_time2[32]; /* histogram of time from start to irq */
+ unsigned long dasd_io_time2ps[32]; /* histogram of time from start to irq */
+ unsigned long dasd_io_time3[32]; /* histogram of time from irq to end */
+} dasd_profile_info_t;
+
+typedef struct dasd_device_t {
+ s390_dev_info_t devinfo;
+ dasd_discipline_t *discipline;
+ int level;
+ int open_count;
+ kdev_t kdev;
+ major_info_t *major_info;
+ struct dasd_chanq_t queue;
+ wait_queue_head_t wait_q;
+ request_queue_t request_queue;
+ devstat_t dev_status; /* needed ONLY!! for request_irq */
+ dasd_sizes_t sizes;
+ char name[16]; /* The name of the device in /dev */
+ char *private; /* to be used by the discipline internally */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+ devfs_handle_t devfs_entry;
+#endif /* LINUX_IS_24 */
+ struct tq_struct bh_tq;
+ atomic_t bh_scheduled;
+ debug_info_t *debug_area;
+ dasd_profile_info_t profile;
+ struct proc_dir_entry *proc_dir; /* directory node */
+ struct proc_dir_entry *proc_info; /* information from dasd_device_t */
+ struct proc_dir_entry *proc_stats; /* statictics information */
+} dasd_device_t;
+
+/* dasd_device_t.level can be: */
+#define DASD_DEVICE_LEVEL_UNKNOWN 0x00
+#define DASD_DEVICE_LEVEL_RECOGNIZED 0x01
+#define DASD_DEVICE_LEVEL_ANALYSIS_PENDING 0x02
+#define DASD_DEVICE_LEVEL_ANALYSIS_PREPARED 0x04
+#define DASD_DEVICE_LEVEL_ANALYSED 0x08
+#define DASD_DEVICE_LEVEL_PARTITIONED 0x10
+
+int dasd_init (void);
+void dasd_discipline_enq (dasd_discipline_t *);
+int dasd_discipline_deq(dasd_discipline_t *);
+int dasd_start_IO (ccw_req_t *);
+void dasd_int_handler (int , void *, struct pt_regs *);
+ccw_req_t *default_erp_action (ccw_req_t *);
+ccw_req_t *default_erp_postaction (ccw_req_t *);
+int dasd_chanq_deq (dasd_chanq_t *, ccw_req_t *);
+ccw_req_t *dasd_alloc_request (char *, int, int);
+void dasd_free_request (ccw_req_t *);
+int (*genhd_dasd_name) (char *, int, int, struct gendisk *);
+int dasd_oper_handler (int irq, devreg_t * devreg);
+
+#endif /* __KERNEL__ */
+
+#endif /* DASD_H */
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff --git a/include/asm-s390/debug.h b/include/asm-s390/debug.h
new file mode 100644
index 000000000..fdcc56008
--- /dev/null
+++ b/include/asm-s390/debug.h
@@ -0,0 +1,210 @@
+/*
+ * include/asm-s390/debug.h
+ * S/390 debug facility
+ *
+ * Copyright (C) 1999, 2000 IBM Deutschland Entwicklung GmbH,
+ * IBM Corporation
+ */
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+/* Note:
+ * struct __debug_entry must be defined outside of #ifdef __KERNEL__
+ * in order to allow a user program to analyze the 'raw'-view.
+ */
+
+struct __debug_entry{
+ union {
+ struct {
+ unsigned long long clock:52;
+ unsigned long long exception:1;
+ unsigned long long used:1;
+ unsigned long long unused:1;
+ unsigned long long cpuid:9;
+ } fields;
+
+ unsigned long long stck;
+ } id;
+ void* caller;
+} __attribute__((packed));
+
+#ifdef __KERNEL__
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+ #include <asm/spinlock.h>
+#else
+ #include <linux/spinlock.h>
+#endif /* LINUX_VERSION_CODE */
+#include <linux/kernel.h>
+#include <linux/time.h>
+#include <linux/proc_fs.h>
+
+#define DEBUG_MAX_LEVEL 6 /* debug levels range from 0 to 6 */
+#define DEBUG_OFF_LEVEL -1 /* level where debug is switched off */
+#define DEBUG_MAX_VIEWS 10 /* max number of views in proc fs */
+#define DEBUG_MAX_PROCF_LEN 16 /* max length for a proc file name */
+#define DEBUG_DEFAULT_LEVEL 3 /* initial debug level */
+#define DEBUG_FEATURE_VERSION 1 /* version of debug feature */
+
+#define DEBUG_DIR_ROOT "s390dbf" /* name of debug root directory in proc fs */
+
+#define DEBUG_DATA(entry) (char*)(entry + 1) /* data is stored behind */
+ /* the entry information */
+
+#define STCK(x) asm volatile ("STCK %0":"=m" (x))
+
+typedef struct __debug_entry debug_entry_t;
+
+struct debug_view;
+
+typedef struct debug_info {
+ struct debug_info* next;
+ struct debug_info* prev;
+ atomic_t ref_count;
+ spinlock_t lock;
+ int level;
+ int nr_areas;
+ int page_order;
+ int buf_size;
+ int entry_size;
+ debug_entry_t** areas;
+ int active_area;
+ int *active_entry;
+ struct proc_dir_entry* proc_root_entry;
+ struct proc_dir_entry* proc_entries[DEBUG_MAX_VIEWS];
+ struct debug_view* views[DEBUG_MAX_VIEWS];
+ char name[DEBUG_MAX_PROCF_LEN];
+} debug_info_t;
+
+typedef int (debug_header_proc_t) (debug_info_t* id,
+ struct debug_view* view,
+ int area,
+ debug_entry_t* entry,
+ char* out_buf);
+
+typedef int (debug_format_proc_t) (debug_info_t* id,
+ struct debug_view* view, char* out_buf,
+ const char* in_buf);
+typedef int (debug_prolog_proc_t) (debug_info_t* id,
+ struct debug_view* view,
+ char* out_buf);
+typedef int (debug_input_proc_t) (debug_info_t* id,
+ struct debug_view* view,
+ struct file* file, const char* user_buf,
+ size_t in_buf_size, loff_t* offset);
+
+int debug_dflt_header_fn(debug_info_t* id, struct debug_view* view,
+ int area, debug_entry_t* entry, char* out_buf);
+
+struct debug_view {
+ char name[DEBUG_MAX_PROCF_LEN];
+ debug_prolog_proc_t* prolog_proc;
+ debug_header_proc_t* header_proc;
+ debug_format_proc_t* format_proc;
+ debug_input_proc_t* input_proc;
+};
+
+extern struct debug_view debug_hex_ascii_view;
+extern struct debug_view debug_raw_view;
+
+debug_info_t* debug_register(char* name, int pages_index, int nr_areas,
+ int buf_size);
+void debug_unregister(debug_info_t* id);
+
+void debug_set_level(debug_info_t* id, int new_level);
+
+debug_entry_t* debug_event(debug_info_t* id, int level, void* data,
+ int length);
+debug_entry_t* debug_int_event(debug_info_t* id, int level,
+ unsigned int tag);
+debug_entry_t* debug_text_event(debug_info_t* id, int level,
+ const char* txt);
+
+debug_entry_t* debug_exception(debug_info_t* id, int level, void* data,
+ int length);
+debug_entry_t* debug_int_exception(debug_info_t* id, int level,
+ unsigned int tag);
+debug_entry_t* debug_text_exception(debug_info_t* id, int level,
+ const char* txt);
+
+static inline debug_entry_t *
+debug_long_event (debug_info_t* id, int level, unsigned long tag)
+{
+ unsigned long t=tag;
+ return debug_event(id,level,&t,sizeof(unsigned long));
+}
+static inline debug_entry_t *
+debug_long_exception (debug_info_t* id, int level, unsigned long tag)
+{
+ unsigned long t=tag;
+ return debug_exception(id,level,&t,sizeof(unsigned long));
+}
+int debug_register_view(debug_info_t* id, struct debug_view* view);
+int debug_unregister_view(debug_info_t* id, struct debug_view* view);
+
+/*
+ define the debug levels:
+ - 0 No debugging output to console or syslog
+ - 1 Log internal errors to syslog, ignore check conditions
+ - 2 Log internal errors and check conditions to syslog
+ - 3 Log internal errors to console, log check conditions to syslog
+ - 4 Log internal errors and check conditions to console
+ - 5 panic on internal errors, log check conditions to console
+ - 6 panic on both, internal errors and check conditions
+ */
+
+#ifndef DEBUG_LEVEL
+#define DEBUG_LEVEL 4
+#endif
+
+#define INTERNAL_ERRMSG(x,y...) "E" __FILE__ "%d: " x, __LINE__, y
+#define INTERNAL_WRNMSG(x,y...) "W" __FILE__ "%d: " x, __LINE__, y
+#define INTERNAL_INFMSG(x,y...) "I" __FILE__ "%d: " x, __LINE__, y
+#define INTERNAL_DEBMSG(x,y...) "D" __FILE__ "%d: " x, __LINE__, y
+
+#if DEBUG_LEVEL > 0
+#define PRINT_DEBUG(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
+#define PRINT_INFO(x...) printk ( KERN_INFO PRINTK_HEADER x )
+#define PRINT_WARN(x...) printk ( KERN_WARNING PRINTK_HEADER x )
+#define PRINT_ERR(x...) printk ( KERN_ERR PRINTK_HEADER x )
+#define PRINT_FATAL(x...) panic ( PRINTK_HEADER x )
+#else
+#define PRINT_DEBUG(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
+#define PRINT_INFO(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
+#define PRINT_WARN(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
+#define PRINT_ERR(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
+#define PRINT_FATAL(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
+#endif /* DASD_DEBUG */
+
+#if DASD_DEBUG > 4
+#define INTERNAL_ERROR(x...) PRINT_FATAL ( INTERNAL_ERRMSG ( x ) )
+#elif DASD_DEBUG > 2
+#define INTERNAL_ERROR(x...) PRINT_ERR ( INTERNAL_ERRMSG ( x ) )
+#elif DASD_DEBUG > 0
+#define INTERNAL_ERROR(x...) PRINT_WARN ( INTERNAL_ERRMSG ( x ) )
+#else
+#define INTERNAL_ERROR(x...)
+#endif /* DASD_DEBUG */
+
+#if DASD_DEBUG > 5
+#define INTERNAL_CHECK(x...) PRINT_FATAL ( INTERNAL_CHKMSG ( x ) )
+#elif DASD_DEBUG > 3
+#define INTERNAL_CHECK(x...) PRINT_ERR ( INTERNAL_CHKMSG ( x ) )
+#elif DASD_DEBUG > 1
+#define INTERNAL_CHECK(x...) PRINT_WARN ( INTERNAL_CHKMSG ( x ) )
+#else
+#define INTERNAL_CHECK(x...)
+#endif /* DASD_DEBUG */
+
+#undef DEBUG_MALLOC
+#ifdef DEBUG_MALLOC
+void *b;
+#define kmalloc(x...) (PRINT_INFO(" kmalloc %p\n",b=kmalloc(x)),b)
+#define kfree(x) PRINT_INFO(" kfree %p\n",x);kfree(x)
+#define get_free_page(x...) (PRINT_INFO(" gfp %p\n",b=get_free_page(x)),b)
+#define __get_free_pages(x...) (PRINT_INFO(" gfps %p\n",b=__get_free_pages(x)),b)
+#endif /* DEBUG_MALLOC */
+
+#endif /* __KERNEL__ */
+#endif /* DEBUG_H */
diff --git a/include/asm-s390/delay.h b/include/asm-s390/delay.h
index 87ac55391..357fdb835 100644
--- a/include/asm-s390/delay.h
+++ b/include/asm-s390/delay.h
@@ -15,11 +15,8 @@
#define _S390_DELAY_H
extern void __udelay(unsigned long usecs);
-extern void __const_udelay(unsigned long usecs);
extern void __delay(unsigned long loops);
-#define udelay(n) (__builtin_constant_p(n) ? \
- __const_udelay((n) * 0x10c6ul) : \
- __udelay(n))
+#define udelay(n) __udelay(n)
#endif /* defined(_S390_DELAY_H) */
diff --git a/include/asm-s390/dma.h b/include/asm-s390/dma.h
index e7ae126e6..e7e157330 100644
--- a/include/asm-s390/dma.h
+++ b/include/asm-s390/dma.h
@@ -1,5 +1,5 @@
/*
- * include/asm-s390/delay.h
+ * include/asm-s390/dma.h
*
* S390 version
*
@@ -11,7 +11,6 @@
#include <asm/io.h> /* need byte IO */
-#define MAX_DMA_CHANNELS 0
#define MAX_DMA_ADDRESS 0x80000000
#endif /* _ASM_DMA_H */
diff --git a/include/asm-s390/ebcdic.h b/include/asm-s390/ebcdic.h
index 7d6aeb2a7..be17f99d4 100644
--- a/include/asm-s390/ebcdic.h
+++ b/include/asm-s390/ebcdic.h
@@ -14,6 +14,8 @@
#include <types.h>
#endif
+extern __u8 _ascebc_500[]; /* ASCII -> EBCDIC 500 conversion table */
+extern __u8 _ebcasc_500[]; /* EBCDIC 500 -> ASCII conversion table */
extern __u8 _ascebc[]; /* ASCII -> EBCDIC conversion table */
extern __u8 _ebcasc[]; /* EBCDIC -> ASCII conversion table */
extern __u8 _ebc_tolower[]; /* EBCDIC -> lowercase */
@@ -44,6 +46,8 @@ void codepage_convert(const __u8 *codepage, volatile __u8 * addr, int nr)
#define ASCEBC(addr,nr) codepage_convert(_ascebc, addr, nr)
#define EBCASC(addr,nr) codepage_convert(_ebcasc, addr, nr)
+#define ASCEBC_500(addr,nr) codepage_convert(_ascebc_500, addr, nr)
+#define EBCASC_500(addr,nr) codepage_convert(_ebcasc_500, addr, nr)
#define EBC_TOLOWER(addr,nr) codepage_convert(_ebc_tolower, addr, nr)
#define EBC_TOUPPER(addr,nr) codepage_convert(_ebc_toupper, addr, nr)
diff --git a/include/asm-s390/elf.h b/include/asm-s390/elf.h
index 28c5e47db..1f4de7c51 100644
--- a/include/asm-s390/elf.h
+++ b/include/asm-s390/elf.h
@@ -19,10 +19,6 @@
typedef s390_fp_regs elf_fpregset_t;
typedef s390_regs elf_gregset_t;
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x) ((x)->e_machine == EM_S390)
/*
* These are used to set parameters in the core dumps.
@@ -31,6 +27,12 @@ typedef s390_regs elf_gregset_t;
#define ELF_DATA ELFDATA2MSB
#define ELF_ARCH EM_S390
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) \
+ ((x)->e_machine == ELF_ARCH && (x)->e_ident[EI_CLASS] == ELF_CLASS)
+
/* For SVR4/S390 the function pointer to be registered with `atexit` is
passed in R14. */
#define ELF_PLAT_INIT(_r) \
@@ -73,8 +75,7 @@ typedef s390_regs elf_gregset_t;
#define ELF_PLATFORM (NULL)
#ifdef __KERNEL__
-#define SET_PERSONALITY(ex, ibcs2) \
- current->personality = (ibcs2 ? PER_SVR4 : PER_LINUX)
+#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
#endif
#endif
diff --git a/include/asm-s390/fcntl.h b/include/asm-s390/fcntl.h
index c1987889a..80fdd6c2e 100644
--- a/include/asm-s390/fcntl.h
+++ b/include/asm-s390/fcntl.h
@@ -42,6 +42,11 @@
#define F_SETSIG 10 /* for sockets. */
#define F_GETSIG 11 /* for sockets. */
+#define F_GETLK64 12 /* using 'struct flock64' */
+#define F_SETLK64 13
+#define F_SETLKW64 14
+
+
/* for F_[GET|SET]FL */
#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
@@ -77,5 +82,13 @@ struct flock {
pid_t l_pid;
};
+struct flock64 {
+ short l_type;
+ short l_whence;
+ loff_t l_start;
+ loff_t l_len;
+ pid_t l_pid;
+};
+
#define F_LINUX_SPECIFIC_BASE 1024
#endif
diff --git a/include/asm-s390/hardirq.h b/include/asm-s390/hardirq.h
index b32a0684a..05a95993c 100644
--- a/include/asm-s390/hardirq.h
+++ b/include/asm-s390/hardirq.h
@@ -50,14 +50,14 @@
* Special definitions for s390, always access current PSA.
*/
#define in_interrupt() ((S390_lowcore.__local_irq_count + S390_lowcore.__local_bh_count) != 0)
-
+
#define in_irq() (S390_lowcore.__local_irq_count != 0)
-
+
#ifndef CONFIG_SMP
-
+
#define hardirq_trylock(cpu) (local_irq_count(cpu) == 0)
#define hardirq_endlock(cpu) do { } while (0)
-
+
#define hardirq_enter(cpu) (local_irq_count(cpu)++)
#define hardirq_exit(cpu) (local_irq_count(cpu)--)
diff --git a/include/asm-s390/idals.h b/include/asm-s390/idals.h
new file mode 100644
index 000000000..7d5232b65
--- /dev/null
+++ b/include/asm-s390/idals.h
@@ -0,0 +1,57 @@
+/*
+ * File...........: linux/include/asm-s390x/idals.h
+ * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ * Bugreports.to..: <Linux390@de.ibm.com>
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000a
+
+ * History of changes
+ * 07/24/00 new file
+ */
+#include <linux/config.h>
+#include <asm/irq.h>
+
+typedef unsigned long idaw_t;
+
+static inline idaw_t *
+idal_alloc ( int nridaws )
+{
+ if ( nridaws > 33 )
+ BUG();
+ return kmalloc(nridaws * sizeof(idaw_t), GFP_ATOMIC | GFP_DMA );
+}
+
+static inline void
+idal_free ( idaw_t *idal )
+{
+ kfree (idal);
+}
+
+/*
+ * Function: set_normalized_cda
+ * sets the address of the data in CCW
+ * if necessary it allocates an IDAL and sets sthe appropriate flags
+ */
+#if defined (CONFIG_ARCH_S390X)
+extern void set_normalized_cda(ccw1_t * ccw, unsigned long address);
+#else
+static inline void
+set_normalized_cda(ccw1_t * ccw, unsigned long address)
+{
+ ccw->cda = address;
+}
+#endif
+
+/*
+ * Function: clear_normalized_cda
+ * releases any allocated IDAL related to the CCW
+ */
+static inline void
+clear_normalized_cda ( ccw1_t * ccw )
+{
+ if ( ccw -> flags & CCW_FLAG_IDA ) {
+ idal_free ( (idaw_t *) (ccw -> cda ));
+ ccw -> flags &= ~CCW_FLAG_IDA;
+ }
+ ccw -> cda = 0;
+}
+
diff --git a/include/asm-s390/io.h b/include/asm-s390/io.h
index 87c4edb72..11bd4217a 100644
--- a/include/asm-s390/io.h
+++ b/include/asm-s390/io.h
@@ -27,7 +27,7 @@
extern inline unsigned long virt_to_phys(volatile void * address)
{
unsigned long real_address;
- __asm__ (" lra %0,0(0,%1)\n"
+ __asm__ (" lra %0,0(%1)\n"
" jz 0f\n"
" sr %0,%0\n"
"0:"
diff --git a/include/asm-s390/ioctls.h b/include/asm-s390/ioctls.h
index 41748666a..db7b0a0c3 100644
--- a/include/asm-s390/ioctls.h
+++ b/include/asm-s390/ioctls.h
@@ -73,6 +73,7 @@
#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
+#define FIOQSIZE 0x545E
/* Used for packet mode */
#define TIOCPKT_DATA 0
diff --git a/include/asm-s390/irq.h b/include/asm-s390/irq.h
index 5efcdd40b..9849d6fdc 100644
--- a/include/asm-s390/irq.h
+++ b/include/asm-s390/irq.h
@@ -1,15 +1,8 @@
-/*
- * arch/s390/kernel/s390io.h
- *
- * S390 version
- * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Ingo Adlung (adlung@de.ibm.com)
- */
-
#ifndef __irq_h
#define __irq_h
#include <linux/config.h>
+#ifdef __KERNEL__
#include <asm/hardirq.h>
/*
@@ -18,6 +11,8 @@
#define __MAX_SUBCHANNELS 65536
#define NR_IRQS __MAX_SUBCHANNELS
+#define LPM_ANYPATH 0xff /* doesn't really belong here, Ingo? */
+
#define INVALID_STORAGE_AREA ((void *)(-1 - 0x3FFF ))
extern int disable_irq(unsigned int);
@@ -50,7 +45,8 @@ struct hw_interrupt_type {
*/
typedef struct {
__u32 intparm; /* interruption parameter */
- __u32 res0 : 2; /* reserved zeros */
+ __u32 qf : 1; /* qdio facility */
+ __u32 res0 : 1; /* reserved zeros */
__u32 isc : 3; /* interruption sublass */
__u32 res5 : 3; /* reserved zeros */
__u32 ena : 1; /* enabled */
@@ -77,6 +73,7 @@ typedef struct {
/* ... in an operand exception. */
} __attribute__ ((packed)) pmcw_t;
+#endif /* __KERNEL__ */
/*
* subchannel status word
*/
@@ -89,7 +86,7 @@ typedef struct {
__u32 pfch : 1; /* prefetch */
__u32 isic : 1; /* initial-status interruption control */
__u32 alcc : 1; /* address-limit checking control */
- __u32 ssi : 1; /* supress-suspended interruption */
+ __u32 ssi : 1; /* suppress-suspended interruption */
__u32 zcc : 1; /* zero condition code */
__u32 ectl : 1; /* extended control */
__u32 pno : 1; /* path not operational */
@@ -140,6 +137,44 @@ typedef struct {
#define SCHN_STAT_CHAIN_CHECK 0x01
/*
+ * architectured values for first sense byte
+ */
+#define SNS0_CMD_REJECT 0x80
+#define SNS_CMD_REJECT SNS0_CMD_REJECT
+#define SNS0_INTERVENTION_REQ 0x40
+#define SNS0_BUS_OUT_CHECK 0x20
+#define SNS0_EQUIPMENT_CHECK 0x10
+#define SNS0_DATA_CHECK 0x08
+#define SNS0_OVERRUN 0x04
+/* 0x02 reserved */
+#define SNS0_INCOMPL_DOMAIN 0x01
+
+/*
+ * architectured values for second sense byte
+ */
+#define SNS1_PERM_ERR 0x80
+#define SNS1_INV_TRACK_FORMAT 0x40
+#define SNS1_EOC 0x20
+#define SNS1_MESSAGE_TO_OPER 0x10
+#define SNS1_NO_REC_FOUND 0x08
+#define SNS1_FILE_PROTECTED 0x04
+#define SNS1_WRITE_INHIBITED 0x02
+#define SNS1_INPRECISE_END 0x01
+
+/*
+ * architectured values for third sense byte
+ */
+#define SNS2_REQ_INH_WRITE 0x80
+#define SNS2_CORRECTABLE 0x40
+#define SNS2_FIRST_LOG_ERR 0x20
+#define SNS2_ENV_DATA_PRESENT 0x10
+/* 0x08 reserved */
+#define SNS2_INPRECISE_END 0x04
+/* 0x02 reserved */
+/* 0x01 reserved */
+
+#ifdef __KERNEL__
+/*
* subchannel information block
*/
typedef struct {
@@ -147,13 +182,14 @@ typedef struct {
scsw_t scsw; /* subchannel status word */
__u8 mda[12]; /* model dependent area */
} __attribute__ ((packed,aligned(4))) schib_t;
+#endif /* __KERNEL__ */
typedef struct {
__u8 cmd_code;/* command code */
- __u8 flags; /* flags, like IDA adressing, etc. */
+ __u8 flags; /* flags, like IDA addressing, etc. */
__u16 count; /* byte count */
__u32 cda; /* data address */
- } ccw1_t __attribute__ ((packed,aligned(8)));
+ } __attribute__ ((packed,aligned(8))) ccw1_t;
#define CCW_FLAG_DC 0x80
#define CCW_FLAG_CC 0x40
@@ -168,10 +204,13 @@ typedef struct {
#define CCW_CMD_BASIC_SENSE 0x04
#define CCW_CMD_TIC 0x08
#define CCW_CMD_SENSE_PGID 0x34
+#define CCW_CMD_SUSPEND_RECONN 0x5B
#define CCW_CMD_RDC 0x64
#define CCW_CMD_SET_PGID 0xAF
#define CCW_CMD_SENSE_ID 0xE4
+#define CCW_CMD_DCTL 0xF3
+#ifdef __KERNEL__
#define SENSE_MAX_COUNT 0x20
/*
@@ -192,19 +231,25 @@ typedef struct {
__u32 intparm; /* interruption parameter */
__u32 key : 4; /* flags, like key, suspend control, etc. */
__u32 spnd : 1; /* suspend control */
- __u32 res1 : 3; /* reserved */
+ __u32 res1 : 1; /* reserved */
+ __u32 mod : 1; /* modification control */
+ __u32 sync : 1; /* synchronize control */
__u32 fmt : 1; /* format control */
__u32 pfch : 1; /* prefetch control */
__u32 isic : 1; /* initial-status-interruption control */
__u32 alcc : 1; /* address-limit-checking control */
__u32 ssic : 1; /* suppress-suspended-interr. control */
- __u32 res2 : 3; /* reserved */
+ __u32 res2 : 1; /* reserved */
+ __u32 c64 : 1; /* IDAW/QDIO 64 bit control */
+ __u32 i2k : 1; /* IDAW 2/4kB block size control */
__u32 lpm : 8; /* logical path mask */
__u32 ils : 1; /* incorrect length */
- __u32 zero : 7; /* reserved zeros */
+ __u32 zero : 6; /* reserved zeros */
+ __u32 orbx : 1; /* ORB extension control */
__u32 cpa; /* channel program address */
} __attribute__ ((packed,aligned(4))) orb_t;
+#endif /* __KERNEL__ */
typedef struct {
__u32 res0 : 4; /* reserved */
__u32 pvrf : 1; /* path-verification-required flag */
@@ -249,7 +294,7 @@ typedef struct {
typedef struct {
__u8 zero0; /* reserved zeros */
__u8 lpum; /* last path used mask */
- __u8 zero16; /* reserved zeros */
+ __u16 zero16; /* reserved zeros */
erw_t erw; /* extended report word */
__u32 zeros[3]; /* 2 fullwords of zeros */
} __attribute__ ((packed)) esw1_t;
@@ -291,30 +336,24 @@ typedef struct {
esw_t esw; /* extended status word */
__u8 ecw[32]; /* extended control word */
} irb_t __attribute__ ((packed,aligned(4)));
+#ifdef __KERNEL__
/*
* TPI info structure
*/
typedef struct {
- __u32 res : 16; /* reserved 0x00000001 */
- __u32 irq : 16; /* aka. subchannel number */
- __u32 intparm; /* interruption parameter */
+ __u32 reserved1 : 16; /* reserved 0x00000001 */
+ __u32 irq : 16; /* aka. subchannel number */
+ __u32 intparm; /* interruption parameter */
+ __u32 adapter_IO : 1;
+ __u32 reserved2 : 1;
+ __u32 isc : 3;
+ __u32 reserved3 : 12;
+ __u32 int_type : 3;
+ __u32 reserved4 : 12;
} __attribute__ ((packed)) tpi_info_t;
-/*
- * This is the "IRQ descriptor", which contains various information
- * about the irq, including what kind of hardware handling it has,
- * whether it is disabled etc etc.
- *
- * Pad this out to 32 bytes for cache and indexing reasons.
- */
-typedef struct {
- __u32 status; /* IRQ status - IRQ_INPROGRESS, IRQ_DISABLED */
- struct hw_interrupt_type *handler; /* handle/enable/disable functions */
- struct irqaction *action; /* IRQ action list */
- } irq_desc_t;
-
//
// command information word (CIW) layout
//
@@ -330,6 +369,7 @@ typedef struct _ciw {
#define CIW_TYPE_SII 0x1 // set interface identifier
#define CIW_TYPE_RNI 0x2 // read node identifier
+#define MAX_CIWS 8
//
// sense-id response buffer layout
//
@@ -342,9 +382,10 @@ typedef struct {
__u8 dev_model; /* device model */
__u8 unused; /* padding byte */
/* extended part */
- ciw_t ciw[62]; /* variable # of CIWs */
+ ciw_t ciw[MAX_CIWS]; /* variable # of CIWs */
} __attribute__ ((packed,aligned(4))) senseid_t;
+#endif /* __KERNEL__ */
/*
* sense data
*/
@@ -363,7 +404,7 @@ typedef struct {
*/
typedef struct {
__u16 devno; /* device number, aka. "cuu" from irb */
- unsigned int intparm; /* interrupt parameter */
+ unsigned long intparm; /* interrupt parameter */
__u8 cstat; /* channel status - accumulated */
__u8 dstat; /* device status - accumulated */
__u8 lpum; /* last path used mask from irb */
@@ -387,9 +428,53 @@ typedef struct {
#define DEVSTAT_DEVICE_GONE 0x00000040
#define DEVSTAT_DEVICE_OWNED 0x00000080
#define DEVSTAT_CLEAR_FUNCTION 0x00000100
+#define DEVSTAT_PCI 0x00000200
+#define DEVSTAT_SUSPENDED 0x00000400
+#define DEVSTAT_UNKNOWN_DEV 0x00000800
#define DEVSTAT_FINAL_STATUS 0x80000000
+#define DEVINFO_NOT_OPER DEVSTAT_NOT_OPER
+#define DEVINFO_UNKNOWN_DEV DEVSTAT_UNKNOWN_DEV
+#define DEVINFO_DEVICE_OWNED DEVSTAT_DEVICE_OWNED
+#define DEVINFO_QDIO_CAPABLE 0x40000000
+
#define INTPARM_STATUS_PENDING 0xFFFFFFFF
+#ifdef __KERNEL__
+
+#define IO_INTERRUPT_TYPE 0 /* I/O interrupt type */
+
+typedef void (* io_handler_func1_t) ( int irq,
+ devstat_t *devstat,
+ struct pt_regs *rgs);
+
+typedef void (* io_handler_func_t) ( int irq,
+ void *devstat,
+ struct pt_regs *rgs);
+
+typedef void ( * not_oper_handler_func_t)( int irq,
+ int status );
+
+typedef int (* adapter_int_handler_t)( __u32 intparm );
+
+struct s390_irqaction {
+ io_handler_func_t handler;
+ unsigned long flags;
+ const char *name;
+ devstat_t *dev_id;
+};
+
+/*
+ * This is the "IRQ descriptor", which contains various information
+ * about the irq, including what kind of hardware handling it has,
+ * whether it is disabled etc etc.
+ *
+ * Pad this out to 32 bytes for cache and indexing reasons.
+ */
+typedef struct {
+ unsigned int status; /* IRQ status - IRQ_INPROGRESS, IRQ_DISABLED */
+ struct hw_interrupt_type *handler; /* handle/enable/disable functions */
+ struct s390_irqaction *action; /* IRQ action list */
+ } irq_desc_t;
typedef struct {
__u8 state1 : 2; /* path state value 1 */
@@ -409,36 +494,39 @@ typedef struct {
__u32 tod_high; /* high word TOD clock */
} __attribute__ ((packed)) pgid_t;
+#define SPID_FUNC_SINGLE_PATH 0x00
#define SPID_FUNC_MULTI_PATH 0x80
#define SPID_FUNC_ESTABLISH 0x00
#define SPID_FUNC_RESIGN 0x40
#define SPID_FUNC_DISBAND 0x20
-#define SNID_STATE1_RESET 0x0
-#define SNID_STATE1_UNGROUPED 0x8
-#define SNID_STATE1_GROUPED 0xC
+#define SNID_STATE1_RESET 0
+#define SNID_STATE1_UNGROUPED 2
+#define SNID_STATE1_GROUPED 3
-#define SNID_STATE2_NOT_RESVD 0x0
-#define SNID_STATE2_RESVD_ELSE 0x8
-#define SNID_STATE2_RESVD_SELF 0xC
+#define SNID_STATE2_NOT_RESVD 0
+#define SNID_STATE2_RESVD_ELSE 2
+#define SNID_STATE2_RESVD_SELF 3
#define SNID_STATE3_MULTI_PATH 1
+#define SNID_STATE3_SINGLE_PATH 0
/*
* Flags used as input parameters for do_IO()
*/
-#define DOIO_EARLY_NOTIFICATION 0x01 /* allow for I/O completion ... */
+#define DOIO_EARLY_NOTIFICATION 0x0001 /* allow for I/O completion ... */
/* ... notification after ... */
/* ... primary interrupt status */
-#define DOIO_RETURN_CHAN_END DOIO_EARLY_NOTIFICATION
-#define DOIO_VALID_LPM 0x02 /* LPM input parameter is valid */
-#define DOIO_WAIT_FOR_INTERRUPT 0x04 /* wait synchronously for interrupt */
-#define DOIO_REPORT_ALL 0x08 /* report all interrupt conditions */
-#define DOIO_ALLOW_SUSPEND 0x10 /* allow for channel prog. suspend */
-#define DOIO_DENY_PREFETCH 0x20 /* don't allow for CCW prefetch */
-#define DOIO_SUPPRESS_INTER 0x40 /* suppress intermediate inter. */
+#define DOIO_RETURN_CHAN_END DOIO_EARLY_NOTIFICATION
+#define DOIO_VALID_LPM 0x0002 /* LPM input parameter is valid */
+#define DOIO_WAIT_FOR_INTERRUPT 0x0004 /* wait synchronously for interrupt */
+#define DOIO_REPORT_ALL 0x0008 /* report all interrupt conditions */
+#define DOIO_ALLOW_SUSPEND 0x0010 /* allow for channel prog. suspend */
+#define DOIO_DENY_PREFETCH 0x0020 /* don't allow for CCW prefetch */
+#define DOIO_SUPPRESS_INTER 0x0040 /* suppress intermediate inter. */
/* ... for suspended CCWs */
-#define DOIO_TIMEOUT 0x80 /* 3 secs. timeout for sync. I/O */
+#define DOIO_TIMEOUT 0x0080 /* 3 secs. timeout for sync. I/O */
+#define DOIO_DONT_CALL_INTHDLR 0x0100 /* don't call interrupt handler */
/*
* do_IO()
@@ -464,7 +552,7 @@ int do_IO( int irq, /* IRQ aka. subchannel number */
int start_IO( int irq, /* IRQ aka. subchannel number */
ccw1_t *cpa, /* logical channel program address */
- unsigned int intparm, /* interruption parameter */
+ unsigned long intparm, /* interruption parameter */
__u8 lpm, /* logical path mask */
unsigned int flag); /* flags : see above */
@@ -493,12 +581,12 @@ typedef struct {
__u16 devno; /* device number */
unsigned int status; /* device status */
senseid_t sid_data; /* senseID data */
- } dev_info_t;
+ } s390_dev_info_t;
-int get_dev_info( int irq, dev_info_t *); /* to be eliminated - don't use */
+int get_dev_info( int irq, s390_dev_info_t *); /* to be eliminated - don't use */
-int get_dev_info_by_irq ( int irq, dev_info_t *pdi);
-int get_dev_info_by_devno( __u16 devno, dev_info_t *pdi);
+int get_dev_info_by_irq ( int irq, s390_dev_info_t *pdi);
+int get_dev_info_by_devno( __u16 devno, s390_dev_info_t *pdi);
int get_irq_by_devno( __u16 devno );
unsigned int get_devno_by_irq( int irq );
@@ -507,7 +595,16 @@ int get_irq_first( void );
int get_irq_next ( int irq );
int read_dev_chars( int irq, void **buffer, int length );
-int read_conf_data( int irq, void **buffer, int *length );
+int read_conf_data( int irq, void **buffer, int *length, __u8 lpm );
+
+int s390_DevicePathVerification( int irq, __u8 domask );
+
+int s390_request_irq_special( int irq,
+ io_handler_func_t io_handler,
+ not_oper_handler_func_t not_oper_handler,
+ unsigned long irqflags,
+ const char *devname,
+ void *dev_id);
extern int handle_IRQ_event( unsigned int irq, int cpu, struct pt_regs *);
@@ -524,7 +621,11 @@ extern __inline__ int stsch(int irq, volatile schib_t *addr)
int ccode;
__asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+ "LGR 1,%1\n\t"
+#else
"LR 1,%1\n\t"
+#endif
"STSCH 0(%2)\n\t"
"IPM %0\n\t"
"SRL %0,28\n\t"
@@ -538,7 +639,11 @@ extern __inline__ int msch(int irq, volatile schib_t *addr)
int ccode;
__asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+ "LGR 1,%1\n\t"
+#else
"LR 1,%1\n\t"
+#endif
"MSCH 0(%2)\n\t"
"IPM %0\n\t"
"SRL %0,28\n\t"
@@ -552,6 +657,21 @@ extern __inline__ int msch_err(int irq, volatile schib_t *addr)
int ccode;
__asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+ " lgr 1,%1\n"
+ " msch 0(%2)\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
+ "1:\n"
+ ".section .fixup,\"ax\"\n"
+ "2: l %0,%3\n"
+ " jg 1b\n"
+ ".previous\n"
+ ".section __ex_table,\"a\"\n"
+ " .align 8\n"
+ " .quad 0b,2b\n"
+ ".previous"
+#else
" lr 1,%1\n"
" msch 0(%2)\n"
"0: ipm %0\n"
@@ -568,6 +688,7 @@ extern __inline__ int msch_err(int irq, volatile schib_t *addr)
" .align 4\n"
" .long 0b,2b\n"
".previous"
+#endif
: "=d" (ccode)
: "r" (irq | 0x10000L), "a" (addr), "i" (__LC_PGM_ILC)
: "cc", "1" );
@@ -579,7 +700,11 @@ extern __inline__ int tsch(int irq, volatile irb_t *addr)
int ccode;
__asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+ "LGR 1,%1\n\t"
+#else
"LR 1,%1\n\t"
+#endif
"TSCH 0(%2)\n\t"
"IPM %0\n\t"
"SRL %0,28\n\t"
@@ -606,7 +731,11 @@ extern __inline__ int ssch(int irq, volatile orb_t *addr)
int ccode;
__asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+ "LGR 1,%1\n\t"
+#else
"LR 1,%1\n\t"
+#endif
"SSCH 0(%2)\n\t"
"IPM %0\n\t"
"SRL %0,28\n\t"
@@ -620,7 +749,11 @@ extern __inline__ int rsch(int irq)
int ccode;
__asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+ "LGR 1,%1\n\t"
+#else
"LR 1,%1\n\t"
+#endif
"RSCH\n\t"
"IPM %0\n\t"
"SRL %0,28\n\t"
@@ -634,7 +767,11 @@ extern __inline__ int csch(int irq)
int ccode;
__asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+ "LGR 1,%1\n\t"
+#else
"LR 1,%1\n\t"
+#endif
"CSCH\n\t"
"IPM %0\n\t"
"SRL %0,28\n\t"
@@ -648,7 +785,11 @@ extern __inline__ int hsch(int irq)
int ccode;
__asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+ "LGR 1,%1\n\t"
+#else
"LR 1,%1\n\t"
+#endif
"HSCH\n\t"
"IPM %0\n\t"
"SRL %0,28\n\t"
@@ -669,6 +810,24 @@ extern __inline__ int iac( void)
return ccode;
}
+extern __inline__ int rchp(int chpid)
+{
+ int ccode;
+
+ __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+ "LGR 1,%1\n\t"
+#else
+ "LR 1,%1\n\t"
+#endif
+ "RCHP\n\t"
+ "IPM %0\n\t"
+ "SRL %0,28\n\t"
+ : "=d" (ccode) : "r" (chpid)
+ : "cc", "1" );
+ return ccode;
+}
+
typedef struct {
__u16 vrdcdvno : 16; /* device number (input) */
__u16 vrdclen : 16; /* data block length (input) */
@@ -690,12 +849,18 @@ extern __inline__ int diag210( diag210_t * addr)
int ccode;
__asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+ "SAM31\n\t"
+ "DIAG %1,0,0x210\n\t"
+ "SAM64\n\t"
+#else
"LR 1,%1\n\t"
".long 0x83110210\n\t"
+#endif
"IPM %0\n\t"
"SRL %0,28\n\t"
: "=d" (ccode) : "a" (addr)
- : "cc", "1" );
+ : "cc" );
return ccode;
}
@@ -720,9 +885,15 @@ extern spinlock_t irq_controller_lock;
static inline void irq_enter(int cpu, unsigned int irq)
{
hardirq_enter(cpu);
+#ifdef CONFIG_ARCH_S390X
+ while (atomic_read(&global_irq_lock) != 0) {
+ eieio();
+ }
+#else
while (test_bit(0,&global_irq_lock)) {
eieio();
}
+#endif
}
static inline void irq_exit(int cpu, unsigned int irq)
@@ -754,10 +925,13 @@ static inline void irq_exit(int cpu, unsigned int irq)
* x86 profiling function, SMP safe. We might want to do this in
* assembly totally?
*/
+extern char _stext;
static inline void s390_do_profile (unsigned long addr)
{
-#if 0
if (prof_buffer && current->pid) {
+#ifndef CONFIG_ARCH_S390X
+ addr &= 0x7fffffff;
+#endif
addr -= (unsigned long) &_stext;
addr >>= prof_shift;
/*
@@ -769,7 +943,6 @@ static inline void s390_do_profile (unsigned long addr)
addr = prof_len-1;
atomic_inc((atomic_t *)&prof_buffer[addr]);
}
-#endif
}
#include <asm/s390io.h>
@@ -784,5 +957,6 @@ static inline void s390_do_profile (unsigned long addr)
spin_lock_irqsave(&(ioinfo[irq]->irq_lock), flags)
#define s390irq_spin_unlock_irqrestore(irq,flags) \
spin_unlock_irqrestore(&(ioinfo[irq]->irq_lock), flags)
+#endif /* __KERNEL__ */
#endif
diff --git a/include/asm-s390/irqextras390.h b/include/asm-s390/irqextras390.h
index 0ca2f718a..70bac7f44 100644
--- a/include/asm-s390/irqextras390.h
+++ b/include/asm-s390/irqextras390.h
@@ -100,7 +100,7 @@ typedef struct
__u16 count;
- void *ccw_data_address;
+ __u32 ccw_data_address;
} ccw1_bits_t __attribute__((packed,aligned(8)));
typedef struct
diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h
index 3430056da..cdfa00fa2 100644
--- a/include/asm-s390/lowcore.h
+++ b/include/asm-s390/lowcore.h
@@ -31,10 +31,11 @@
#define __LC_SUBCHANNEL_ID 0x0B8
#define __LC_SUBCHANNEL_NR 0x0BA
#define __LC_IO_INT_PARM 0x0BC
+#define __LC_IO_INT_WORD 0x0C0
#define __LC_MCCK_CODE 0x0E8
-#define __LC_AREGS_SAVE_AREA 0x200
-#define __LC_CREGS_SAVE_AREA 0x240
-#define __LC_RETURN_PSW 0x280
+#define __LC_AREGS_SAVE_AREA 0x120
+#define __LC_CREGS_SAVE_AREA 0x1C0
+#define __LC_RETURN_PSW 0x200
#define __LC_SYNC_IO_WORD 0x400
@@ -45,7 +46,7 @@
#define __LC_CPUID 0xC60
#define __LC_CPUADDR 0xC68
#define __LC_IPLDEV 0xC7C
-
+#define __LC_PANIC_MAGIC 0xE00
/* interrupt handler start with all io, external and mcck interrupt disabled */
@@ -53,7 +54,7 @@
#define _EXT_PSW_MASK 0x04080000
#define _PGM_PSW_MASK 0x04080000
#define _SVC_PSW_MASK 0x04080000
-#define _MCCK_PSW_MASK 0x040A0000
+#define _MCCK_PSW_MASK 0x04080000
#define _IO_PSW_MASK 0x04080000
#define _USER_PSW_MASK 0x070DC000/* DAT, IO, EXT, Home-space */
#define _WAIT_PSW_MASK 0x070E0000/* DAT, IO, EXT, Wait, Home-space */
@@ -119,7 +120,8 @@ struct _lowcore
__u16 subchannel_id; /* 0x0b8 */
__u16 subchannel_nr; /* 0x0ba */
__u32 io_int_parm; /* 0x0bc */
- __u8 pad3[0xD8-0xC0]; /* 0x0c0 */
+ __u32 io_int_word; /* 0x0c0 */
+ __u8 pad3[0xD8-0xC4]; /* 0x0c4 */
__u32 cpu_timer_save_area[2]; /* 0x0d8 */
__u32 clock_comp_save_area[2]; /* 0x0e0 */
__u32 mcck_interuption_code[2]; /* 0x0e8 */
@@ -128,15 +130,14 @@ struct _lowcore
__u32 failing_storage_address; /* 0x0f8 */
__u8 pad5[0x100-0xfc]; /* 0x0fc */
__u32 st_status_fixed_logout[4];/* 0x100 */
- __u8 pad6[0x160-0x110]; /* 0x110 */
+ __u8 pad6[0x120-0x110]; /* 0x110 */
+ __u32 access_regs_save_area[16];/* 0x120 */
__u32 floating_pt_save_area[8]; /* 0x160 */
__u32 gpregs_save_area[16]; /* 0x180 */
- __u8 pad7[0x200-0x1c0]; /* 0x1c0 */
-
- __u32 access_regs_save_area[16];/* 0x200 */
__u32 cregs_save_area[16]; /* 0x240 */
- psw_t return_psw; /* 0x280 */
- __u8 pad8[0x400-0x288]; /* 0x288 */
+
+ psw_t return_psw; /* 0x200 */
+ __u8 pad8[0x400-0x208]; /* 0x208 */
__u32 sync_io_word; /* 0x400 */
@@ -163,9 +164,14 @@ struct _lowcore
atomic_t ext_call_fast; /* 0xc88 */
atomic_t ext_call_queue; /* 0xc8c */
atomic_t ext_call_count; /* 0xc90 */
+ __u8 pad11[0xe00-0xc94]; /* 0xc94 */
- /* Align SMP info to the top 1k of prefix area */
- __u8 pad11[0x1000-0xc94]; /* 0xc94 */
+ /* 0xe00 is used as indicator for dump tools */
+ /* whether the kernel died with panic() or not */
+ __u32 panic_magic; /* 0xe00 */
+
+ /* Align to the top 1k of prefix area */
+ __u8 pad12[0x1000-0xe04]; /* 0xe04 */
} __attribute__((packed)); /* End structure*/
extern __inline__ void set_prefix(__u32 address)
@@ -186,5 +192,7 @@ extern struct _lowcore *lowcore_ptr[];
#endif
#endif /* __ASSEMBLY__ */
+#define __PANIC_MAGIC 0xDEADC0DE
+
#endif
diff --git a/include/asm-s390/mathemu.h b/include/asm-s390/mathemu.h
index c78d97b43..429b3a4f4 100644
--- a/include/asm-s390/mathemu.h
+++ b/include/asm-s390/mathemu.h
@@ -12,12 +12,12 @@
extern int math_emu_b3(__u8 *, struct pt_regs *);
extern int math_emu_ed(__u8 *, struct pt_regs *);
-extern void math_emu_ldr(__u8 *);
-extern void math_emu_ler(__u8 *);
-extern void math_emu_std(__u8 *, struct pt_regs *);
-extern void math_emu_ld(__u8 *, struct pt_regs *);
-extern void math_emu_ste(__u8 *, struct pt_regs *);
-extern void math_emu_le(__u8 *, struct pt_regs *);
+extern int math_emu_ldr(__u8 *);
+extern int math_emu_ler(__u8 *);
+extern int math_emu_std(__u8 *, struct pt_regs *);
+extern int math_emu_ld(__u8 *, struct pt_regs *);
+extern int math_emu_ste(__u8 *, struct pt_regs *);
+extern int math_emu_le(__u8 *, struct pt_regs *);
extern int math_emu_lfpc(__u8 *, struct pt_regs *);
extern int math_emu_stfpc(__u8 *, struct pt_regs *);
extern int math_emu_srnm(__u8 *, struct pt_regs *);
@@ -46,3 +46,6 @@ extern __u64 __extendsfdf2(__u32);
#endif /* __MATHEMU__ */
+
+
+
diff --git a/include/asm-s390/misc390.h b/include/asm-s390/misc390.h
index 43d89ccfb..3a48a7385 100644
--- a/include/asm-s390/misc390.h
+++ b/include/asm-s390/misc390.h
@@ -12,3 +12,4 @@
#define allocaligned(type,name,number) allocaligned2(type,name,number,__alignof__(type))
+extern void s390_daemonize(char *name,unsigned long mask,int use_init_fs);
diff --git a/include/asm-s390/mmu_context.h b/include/asm-s390/mmu_context.h
index 71f0f66df..d58b14cbb 100644
--- a/include/asm-s390/mmu_context.h
+++ b/include/asm-s390/mmu_context.h
@@ -27,7 +27,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
unsigned long pgd;
if (prev != next) {
- pgd = (__pa(next->pgd) & PAGE_MASK) | _SEGMENT_TABLE;
+ pgd = (__pa(next->pgd)&PAGE_MASK) |
+ (_SEGMENT_TABLE|USER_STD_MASK);
/* Load page tables */
asm volatile(" lctl 7,7,%0\n" /* secondary space */
" lctl 13,13,%0\n" /* home space */
diff --git a/include/asm-s390/namei.h b/include/asm-s390/namei.h
index 524b93937..3e286bdde 100644
--- a/include/asm-s390/namei.h
+++ b/include/asm-s390/namei.h
@@ -16,7 +16,6 @@
* Look at asm-sparc/namei.h for details.
*/
-#define __prefix_lookup_dentry(name, lookup_flags) \
- do {} while (0)
+#define __emul_prefix() NULL
#endif /* __S390_NAMEI_H */
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h
index e259b2bff..745db14f6 100644
--- a/include/asm-s390/page.h
+++ b/include/asm-s390/page.h
@@ -17,7 +17,15 @@
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
-#define STRICT_MM_TYPECHECKS
+/*
+ * gcc uses builtin, i.e. MVCLE for both operations
+ */
+
+#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
+#define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE)
+
+#define clear_user_page(page, vaddr) clear_page(page)
+#define copy_user_page(to, from, vaddr) copy_page(to, from)
#define BUG() do { \
printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
@@ -43,14 +51,6 @@ extern __inline__ int get_order(unsigned long size)
}
/*
- * gcc uses builtin, i.e. MVCLE for both operations
- */
-
-#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
-#define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE)
-
-#ifdef STRICT_MM_TYPECHECKS
-/*
* These are used to make use of C type-checking..
*/
typedef struct { unsigned long pte; } pte_t;
@@ -73,48 +73,18 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#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 long pmd_t;
-typedef struct {
- unsigned long pgd0;
- unsigned long pgd1;
- unsigned long pgd2;
- unsigned long pgd3;
- } 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
-#endif /* !__ASSEMBLY__ */
+#endif /* !__ASSEMBLY__ */
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-/*
- *
- *
- */
-
-#define __PAGE_OFFSET (0x0)
-#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
-#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
-#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
+#define __PAGE_OFFSET 0x0UL
+#define PAGE_OFFSET 0x0UL
+#define __pa(x) (unsigned long)(x)
+#define __va(x) (void *)(x)
#define virt_to_page(kaddr) (mem_map + (__pa(kaddr) >> PAGE_SHIFT))
#define VALID_PAGE(page) ((page - mem_map) < max_mapnr)
-#endif /* __KERNEL__ */
+#endif /* __KERNEL__ */
-#endif /* _S390_PAGE_H */
+#endif /* _S390_PAGE_H */
diff --git a/include/asm-s390/param.h b/include/asm-s390/param.h
index bd04cebde..c6d7f934f 100644
--- a/include/asm-s390/param.h
+++ b/include/asm-s390/param.h
@@ -28,4 +28,8 @@
#define MAXHOSTNAMELEN 64 /* max length of hostname */
+#ifdef __KERNEL__
+# define CLOCKS_PER_SEC HZ /* frequency at which times() counts */
+#endif
+
#endif
diff --git a/include/asm-s390/pgalloc.h b/include/asm-s390/pgalloc.h
index c1fed9346..72c67617e 100644
--- a/include/asm-s390/pgalloc.h
+++ b/include/asm-s390/pgalloc.h
@@ -31,7 +31,7 @@
extern __inline__ pgd_t* get_pgd_slow(void)
{
int i;
- pgd_t *pgd,*ret = (pgd_t *)__get_free_pages(GFP_KERNEL,2);
+ pgd_t *pgd,*ret = (pgd_t *)__get_free_pages(GFP_KERNEL,1);
if (ret)
for (i=0,pgd=ret;i<USER_PTRS_PER_PGD;i++,pgd++)
pmd_clear(pmd_offset(pgd,i*PGDIR_SIZE));
@@ -40,47 +40,80 @@ extern __inline__ pgd_t* get_pgd_slow(void)
extern __inline__ pgd_t* get_pgd_fast(void)
{
- unsigned long *ret;
+ unsigned long *ret = pgd_quicklist;
- if((ret = pgd_quicklist) != NULL) {
+ if (ret != NULL) {
pgd_quicklist = (unsigned long *)(*ret);
ret[0] = ret[1];
- pgtable_cache_size--;
- /*
- * Need to flush tlb, since private page tables
- * are unique thru address of pgd and virtual address.
- * If we reuse pgd we need to be sure no tlb entry
- * with that pdg is left -> global flush
- *
- * Fixme: To avoid this global flush we should
- * use pdg_quicklist as fix lenght fifo list
- * and not as stack
- */
- } else
- ret = (unsigned long *)get_pgd_slow();
+ pgtable_cache_size -= 2;
+ }
return (pgd_t *)ret;
}
+extern __inline__ pgd_t *pgd_alloc(void)
+{
+ pgd_t *pgd;
+
+ pgd = get_pgd_fast();
+ if (!pgd)
+ pgd = get_pgd_slow();
+ return pgd;
+}
+
extern __inline__ void free_pgd_fast(pgd_t *pgd)
{
*(unsigned long *)pgd = (unsigned long) pgd_quicklist;
pgd_quicklist = (unsigned long *) pgd;
- pgtable_cache_size++;
+ pgtable_cache_size += 2;
}
extern __inline__ void free_pgd_slow(pgd_t *pgd)
{
- free_pages((unsigned long)pgd,2);
+ free_pages((unsigned long) pgd, 1);
+}
+
+#define pgd_free(pgd) free_pgd_fast(pgd)
+
+/*
+ * page middle directory allocation/free routines.
+ * We don't use pmd cache, so these are dummy routines.
+ */
+extern __inline__ pmd_t *get_pmd_fast(void)
+{
+ return (pmd_t *)0;
+}
+
+extern __inline__ void free_pmd_fast(pmd_t *pmd)
+{
+}
+
+extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
+{
+ return (pmd_t *) pgd;
+}
+
+extern __inline__ void free_pmd_slow(pmd_t *pmd)
+{
+}
+
+extern inline void pmd_free(pmd_t * pmd)
+{
}
+#define pmd_free_kernel pmd_free
+#define pmd_alloc_kernel pmd_alloc
+
+/*
+ * page table entry allocation/free routines.
+ */
+extern pte_t empty_bad_pte_table[];
extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
-extern pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long address_preadjusted);
extern __inline__ pte_t* get_pte_fast(void)
{
- unsigned long *ret;
+ unsigned long *ret = (unsigned long *) pte_quicklist;
- if((ret = (unsigned long *)pte_quicklist) != NULL) {
+ if (ret != NULL) {
pte_quicklist = (unsigned long *)(*ret);
ret[0] = ret[1];
pgtable_cache_size--;
@@ -90,6 +123,8 @@ extern __inline__ pte_t* get_pte_fast(void)
extern __inline__ void free_pte_fast(pte_t *pte)
{
+ if (pte == empty_bad_pte_table)
+ return;
*(unsigned long *)pte = (unsigned long) pte_quicklist;
pte_quicklist = (unsigned long *) pte;
pgtable_cache_size++;
@@ -97,79 +132,41 @@ extern __inline__ void free_pte_fast(pte_t *pte)
extern __inline__ void free_pte_slow(pte_t *pte)
{
- free_page((unsigned long)pte);
-}
-
-#define pte_free_kernel(pte) free_pte_fast(pte)
-#define pte_free(pte) free_pte_fast(pte)
-#define pgd_free(pgd) free_pgd_fast(pgd)
-#define pgd_alloc() get_pgd_fast()
-
-extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
-{
- address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
- if (pmd_none(*pmd)) {
- pte_t * page = (pte_t *) get_pte_fast();
-
- if (!page)
- return get_pte_kernel_slow(pmd, address);
- pmd_val(pmd[0]) = _KERNPG_TABLE + __pa(page);
- pmd_val(pmd[1]) = _KERNPG_TABLE + __pa(page+1024);
- pmd_val(pmd[2]) = _KERNPG_TABLE + __pa(page+2048);
- pmd_val(pmd[3]) = _KERNPG_TABLE + __pa(page+3072);
- return page + address;
- }
- if (pmd_bad(*pmd)) {
- __handle_bad_pmd_kernel(pmd);
- return NULL;
- }
- return (pte_t *) pmd_page(*pmd) + address;
+ free_page((unsigned long) pte);
}
-extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
+extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long vmaddr)
{
- address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+ unsigned long offset;
- if (pmd_none(*pmd))
- goto getnew;
+ offset = (vmaddr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+ if (pmd_none(*pmd)) {
+ unsigned long page = (unsigned long) get_pte_fast();
+
+ if (!page)
+ return get_pte_slow(pmd, offset);
+ pmd_val(pmd[0]) = _PAGE_TABLE + __pa(page);
+ pmd_val(pmd[1]) = _PAGE_TABLE + __pa(page+1024);
+ pmd_val(pmd[2]) = _PAGE_TABLE + __pa(page+2048);
+ pmd_val(pmd[3]) = _PAGE_TABLE + __pa(page+3072);
+ return (pte_t *) page + offset;
+ }
if (pmd_bad(*pmd))
- goto fix;
- return (pte_t *) pmd_page(*pmd) + address;
-getnew:
-{
- unsigned long page = (unsigned long) get_pte_fast();
-
- if (!page)
- return get_pte_slow(pmd, address);
- pmd_val(pmd[0]) = _PAGE_TABLE + __pa(page);
- pmd_val(pmd[1]) = _PAGE_TABLE + __pa(page+1024);
- pmd_val(pmd[2]) = _PAGE_TABLE + __pa(page+2048);
- pmd_val(pmd[3]) = _PAGE_TABLE + __pa(page+3072);
- return (pte_t *) page + address;
-}
-fix:
- __handle_bad_pmd(pmd);
- return NULL;
-}
-
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */
-extern inline void pmd_free(pmd_t * pmd)
-{
+ BUG();
+ return (pte_t *) pmd_page(*pmd) + offset;
}
-extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
-{
- return (pmd_t *) pgd;
-}
-
-#define pmd_free_kernel pmd_free
-#define pmd_alloc_kernel pmd_alloc
+#define pte_alloc_kernel(pmd, addr) pte_alloc(pmd, addr)
+#define pte_free_kernel(pte) free_pte_fast(pte)
+#define pte_free(pte) free_pte_fast(pte)
extern int do_check_pgt_cache(int, int);
+/*
+ * This establishes kernel virtual mappings (e.g., as a result of a
+ * vmalloc call). Since s390-esame uses a separate kernel page table,
+ * there is nothing to do here... :)
+ */
#define set_pgdir(addr,entry) do { } while(0)
/*
@@ -185,161 +182,122 @@ extern int do_check_pgt_cache(int, int);
*/
/*
- * s390 has two ways of flushing TLBs
+ * S/390 has three ways of flushing TLBs
* 'ptlb' does a flush of the local processor
- * 'ipte' invalidates a pte in a page table and flushes that out of
- * the TLBs of all PUs of a SMP
+ * 'csp' flushes the TLBs on all PUs of a SMP
+ * 'ipte' invalidates a pte in a page table and flushes that out of
+ * the TLBs of all PUs of a SMP
*/
-#define __flush_tlb() \
+#define local_flush_tlb() \
do { __asm__ __volatile__("ptlb": : :"memory"); } while (0)
-static inline void __flush_global_tlb(void)
-{
- int cs1=0,dum=0;
- int *adr;
- long long dummy=0;
- adr = (int*) (((int)(((int*) &dummy)+1) & 0xfffffffc)|1);
- __asm__ __volatile__("lr 2,%0\n\t"
- "lr 3,%1\n\t"
- "lr 4,%2\n\t"
- ".long 0xb2500024" :
- : "d" (cs1), "d" (dum), "d" (adr)
- : "2", "3", "4");
-}
-
-#if 0
-#define flush_tlb_one(a,b) __flush_tlb()
-#define __flush_tlb_one(a,b) __flush_tlb()
-#else
-static inline void __flush_tlb_one(struct mm_struct *mm,
- unsigned long addr)
-{
- pgd_t * pgdir;
- pmd_t * pmd;
- pte_t * pte, *pto;
-
- pgdir = pgd_offset(mm, addr);
- if (pgd_none(*pgdir) || pgd_bad(*pgdir))
- return;
- pmd = pmd_offset(pgdir, addr);
- if (pmd_none(*pmd) || pmd_bad(*pmd))
- return;
- pte = pte_offset(pmd,addr);
-
- /*
- * S390 has 1mb segments, we are emulating 4MB segments
- */
-
- pto = (pte_t*) (((unsigned long) pte) & 0x7ffffc00);
-
- __asm__ __volatile(" ic 0,2(%0)\n"
- " ipte %1,%2\n"
- " stc 0,2(%0)"
- : : "a" (pte), "a" (pto), "a" (addr): "0");
-}
-#endif
-
-
#ifndef CONFIG_SMP
-#define flush_tlb() __flush_tlb()
-#define flush_tlb_all() __flush_tlb()
-#define local_flush_tlb() __flush_tlb()
-
/*
* We always need to flush, since s390 does not flush tlb
* on each context switch
*/
+#define flush_tlb() local_flush_tlb()
+#define flush_tlb_all() local_flush_tlb()
+#define flush_tlb_mm(mm) local_flush_tlb()
+#define flush_tlb_page(vma, va) local_flush_tlb()
+#define flush_tlb_range(mm, start, end) local_flush_tlb()
-static inline void flush_tlb_mm(struct mm_struct *mm)
-{
- __flush_tlb();
-}
+#else
+
+#include <asm/smp.h>
-static inline void flush_tlb_page(struct vm_area_struct *vma,
- unsigned long addr)
+extern void smp_ptlb_all(void);
+static inline void global_flush_tlb_csp(void)
{
- __flush_tlb_one(vma->vm_mm,addr);
+ int cs1=0,dum=0;
+ int *adr;
+ long long dummy=0;
+ adr = (int*) (((int)(((int*) &dummy)+1) & 0xfffffffc)|1);
+ __asm__ __volatile__("lr 2,%0\n\t"
+ "lr 3,%1\n\t"
+ "lr 4,%2\n\t"
+ "csp 2,4" :
+ : "d" (cs1), "d" (dum), "d" (adr)
+ : "2", "3", "4");
}
-
-static inline void flush_tlb_range(struct mm_struct *mm,
- unsigned long start, unsigned long end)
+static inline void global_flush_tlb(void)
{
- __flush_tlb();
+ if (MACHINE_HAS_CSP)
+ global_flush_tlb_csp();
+ else
+ smp_ptlb_all();
}
-#else
-
-/*
- * We aren't very clever about this yet - SMP could certainly
- * avoid some global flushes..
- */
-
-#include <asm/smp.h>
-
-#define local_flush_tlb() \
- __flush_tlb()
-
/*
- * We only have to do global flush of tlb if process run since last
- * flush on any other pu than current.
- * If we have threads (mm->count > 1) we always do a global flush,
- * since the process runs on more than one processor at the same time.
+ * We only have to do global flush of tlb if process run since last
+ * flush on any other pu than current.
+ * If we have threads (mm->count > 1) we always do a global flush,
+ * since the process runs on more than one processor at the same time.
*/
-static inline void flush_tlb_current_task(void)
+static inline void __flush_tlb_mm(struct mm_struct * mm)
{
- if ((atomic_read(&current->mm->mm_count) != 1) ||
- (current->mm->cpu_vm_mask != (1UL << smp_processor_id()))) {
- current->mm->cpu_vm_mask = (1UL << smp_processor_id());
- __flush_global_tlb();
+ if ((smp_num_cpus > 1) &&
+ ((atomic_read(&mm->mm_count) != 1) ||
+ (mm->cpu_vm_mask != (1UL << smp_processor_id())))) {
+ mm->cpu_vm_mask = (1UL << smp_processor_id());
+ global_flush_tlb();
} else {
local_flush_tlb();
}
}
-#define flush_tlb() flush_tlb_current_task()
+#define flush_tlb() __flush_tlb_mm(current->mm)
+#define flush_tlb_all() global_flush_tlb()
+#define flush_tlb_mm(mm) __flush_tlb_mm(mm)
+#define flush_tlb_page(vma, va) __flush_tlb_mm((vma)->vm_mm)
+#define flush_tlb_range(mm, start, end) __flush_tlb_mm(mm)
-#define flush_tlb_all() __flush_global_tlb()
+#endif
-static inline void flush_tlb_mm(struct mm_struct * mm)
+extern inline void flush_tlb_pgtables(struct mm_struct *mm,
+ unsigned long start, unsigned long end)
{
- if ((atomic_read(&mm->mm_count) != 1) ||
- (mm->cpu_vm_mask != (1UL << smp_processor_id()))) {
- mm->cpu_vm_mask = (1UL << smp_processor_id());
- __flush_global_tlb();
- } else {
- local_flush_tlb();
- }
+ /* S/390 does not keep any page table caches in TLB */
}
-static inline void flush_tlb_page(struct vm_area_struct * vma,
- unsigned long va)
+
+static inline int ptep_test_and_clear_and_flush_young(struct vm_area_struct *vma,
+ unsigned long address, pte_t *ptep)
{
- __flush_tlb_one(vma->vm_mm,va);
+ /* No need to flush TLB; bits are in storage key */
+ return ptep_test_and_clear_young(ptep);
}
-static inline void flush_tlb_range(struct mm_struct * mm,
- unsigned long start, unsigned long end)
+static inline int ptep_test_and_clear_and_flush_dirty(struct vm_area_struct *vma,
+ unsigned long address, pte_t *ptep)
{
- if ((atomic_read(&mm->mm_count) != 1) ||
- (mm->cpu_vm_mask != (1UL << smp_processor_id()))) {
- mm->cpu_vm_mask = (1UL << smp_processor_id());
- __flush_global_tlb();
- } else {
- local_flush_tlb();
- }
+ /* No need to flush TLB; bits are in storage key */
+ return ptep_test_and_clear_dirty(ptep);
}
-#endif
+static inline pte_t ptep_invalidate(struct vm_area_struct *vma,
+ unsigned long address, pte_t *ptep)
+{
+ pte_t pte = *ptep;
+ if (!(pte_val(pte) & _PAGE_INVALID)) {
+ /* S390 has 1mb segments, we are emulating 4MB segments */
+ pte_t *pto = (pte_t *) (((unsigned long) ptep) & 0x7ffffc00);
+ __asm__ __volatile__ ("ipte %0,%1" : : "a" (pto), "a" (address));
+ }
+ pte_clear(ptep);
+ return pte;
+}
-extern inline void flush_tlb_pgtables(struct mm_struct *mm,
- unsigned long start, unsigned long end)
+static inline void ptep_establish(struct vm_area_struct *vma,
+ unsigned long address, pte_t *ptep, pte_t entry)
{
- /* S/390 does not keep any page table caches in TLB */
+ ptep_invalidate(vma, address, ptep);
+ set_pte(ptep, entry);
}
#endif /* _S390_PGALLOC_H */
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index 6906a875a..3c83ec404 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -3,7 +3,9 @@
*
* S390 version
* Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Hartmut Penner
+ * Author(s): Hartmut Penner (hp@de.ibm.com)
+ * Ulrich Weigand (weigand@de.ibm.com)
+ * Martin Schwidefsky (schwidefsky@de.ibm.com)
*
* Derived from "include/asm-i386/pgtable.h"
*/
@@ -17,14 +19,19 @@
* table, so that we physically have the same two-level page table as the
* S390 mmu expects.
*
+ * The "pgd_xxx()" functions are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ *
* This file contains the functions and defines necessary to modify and use
* the S390 page table tree.
*/
#ifndef __ASSEMBLY__
#include <asm/processor.h>
-#include <linux/tasks.h>
+#include <linux/threads.h>
extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096)));
+extern void paging_init(void);
/* Caches aren't brain-dead on S390. */
#define flush_cache_all() do { } while (0)
@@ -37,20 +44,30 @@ extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096)));
#define flush_icache_page(vma,pg) do { } while (0)
/*
+ * The S390 doesn't have any external MMU info: the kernel page
+ * tables contain all the necessary information.
+ */
+#define update_mmu_cache(vma, address, pte) do { } while (0)
+
+/*
* ZERO_PAGE is a global shared page that is always zero: used
* for zero-mapped memory areas etc..
*/
-extern unsigned long empty_zero_page[1024];
+extern char empty_zero_page[PAGE_SIZE];
#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
#endif /* !__ASSEMBLY__ */
-/* Certain architectures need to do special things when PTEs
+/*
+ * Certain architectures need to do special things when PTEs
* within a page table are directly modified. Thus, the following
* hook is made available.
*/
#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
-/* PMD_SHIFT determines the size of the area a second-level page table can map */
+/*
+ * PMD_SHIFT determines the size of the area a second-level page
+ * table can map
+ */
#define PMD_SHIFT 22
#define PMD_SIZE (1UL << PMD_SHIFT)
#define PMD_MASK (~(PMD_SIZE-1))
@@ -70,7 +87,6 @@ extern unsigned long empty_zero_page[1024];
#define PTRS_PER_PMD 1
#define PTRS_PER_PGD 512
-
/*
* pgd entries used up by user/kernel:
*/
@@ -87,7 +103,8 @@ extern unsigned long empty_zero_page[1024];
printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
#ifndef __ASSEMBLY__
-/* Just any arbitrary offset to the start of the vmalloc VM area: the
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
* current 8MB value just means that there will be a 8MB "hole" after the
* physical memory until the kernel virtual memory starts. That means that
* any out-of-bounds memory accesses will hopefully be caught.
@@ -95,14 +112,14 @@ extern unsigned long empty_zero_page[1024];
* area for the same reason. ;)
*/
#define VMALLOC_OFFSET (8*1024*1024)
-#define VMALLOC_START (((unsigned long) high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_START (((unsigned long) high_memory + VMALLOC_OFFSET) \
+ & ~(VMALLOC_OFFSET-1))
#define VMALLOC_VMADDR(x) ((unsigned long)(x))
#define VMALLOC_END (0x7fffffffL)
/*
* A pagetable entry of S390 has following format:
- *
* | PFRA | | OS |
* 0 0IP0
* 00000000001111111111222222222233
@@ -110,11 +127,8 @@ extern unsigned long empty_zero_page[1024];
*
* I Page-Invalid Bit: Page is not available for address-translation
* P Page-Protection Bit: Store access not possible for page
- */
-
-/*
- * A segmenttable entry of S390 has following format:
*
+ * A segmenttable entry of S390 has following format:
* | P-table origin | |PTL
* 0 IC
* 00000000001111111111222222222233
@@ -122,10 +136,8 @@ extern unsigned long empty_zero_page[1024];
*
* I Segment-Invalid Bit: Segment is not available for address-translation
* C Common-Segment Bit: Segment is not private (PoP 3-30)
- * PTL Page-Table-Length: Length of Page-table (PTL+1*16 entries -> up to 256 entries)
- */
-
-/*
+ * PTL Page-Table-Length: Page-table length (PTL+1*16 entries -> up to 256)
+ *
* The segmenttable origin of S390 has following format:
*
* |S-table origin | | STL |
@@ -137,27 +149,38 @@ extern unsigned long empty_zero_page[1024];
* G Segment-Invalid Bit: *
* P Private-Space Bit: Segment is not private (PoP 3-30)
* S Storage-Alteration:
- * STL Segment-Table-Length: Length of Page-table (STL+1*16 entries -> up to 2048 entries)
+ * STL Segment-Table-Length: Segment-table length (STL+1*16 entries -> up to 2048)
+ *
+ * A storage key has the following format:
+ * | ACC |F|R|C|0|
+ * 0 3 4 5 6 7
+ * ACC: access key
+ * F : fetch protection bit
+ * R : referenced bit
+ * C : changed bit
*/
+/* Bits in the page table entry */
#define _PAGE_PRESENT 0x001 /* Software */
-#define _PAGE_ACCESSED 0x002 /* Software accessed */
-#define _PAGE_DIRTY 0x004 /* Software dirty */
#define _PAGE_RO 0x200 /* HW read-only */
#define _PAGE_INVALID 0x400 /* HW invalid */
+/* Bits in the segment table entry */
#define _PAGE_TABLE_LEN 0xf /* only full page-tables */
#define _PAGE_TABLE_COM 0x10 /* common page-table */
#define _PAGE_TABLE_INV 0x20 /* invalid page-table */
#define _SEG_PRESENT 0x001 /* Software (overlap with PTL) */
+/* Bits int the storage key */
+#define _PAGE_CHANGED 0x02 /* HW changed bit */
+#define _PAGE_REFERENCED 0x04 /* HW referenced bit */
+
#define _USER_SEG_TABLE_LEN 0x7f /* user-segment-table up to 2 GB */
#define _KERNEL_SEG_TABLE_LEN 0x7f /* kernel-segment-table up to 2 GB */
/*
* User and Kernel pagetables are identical
*/
-
#define _PAGE_TABLE (_PAGE_TABLE_LEN )
#define _KERNPG_TABLE (_PAGE_TABLE_LEN )
@@ -165,22 +188,25 @@ extern unsigned long empty_zero_page[1024];
* The Kernel segment-tables includes the User segment-table
*/
-#define _SEGMENT_TABLE (_USER_SEG_TABLE_LEN|0x80000000)
+#define _SEGMENT_TABLE (_USER_SEG_TABLE_LEN|0x80000000|0x100)
#define _KERNSEG_TABLE (_KERNEL_SEG_TABLE_LEN)
+
/*
* No mapping available
*/
-#define PAGE_NONE __pgprot(_PAGE_INVALID )
-
-#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
-#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_RO)
-#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_RO)
-#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define PAGE_INVALID __pgprot(_PAGE_INVALID)
+#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_INVALID)
+#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_RO)
+#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_RO)
+#define PAGE_SHARED __pgprot(_PAGE_PRESENT)
+#define PAGE_KERNEL __pgprot(_PAGE_PRESENT)
/*
- * The S390 can't do page protection for execute, and considers that the same are read.
- * Also, write permissions imply read permissions. This is the closest we can get..
+ * The S390 can't do page protection for execute, and considers that the
+ * same are read. Also, write permissions imply read permissions. This is
+ * the closest we can get..
*/
+ /*xwr*/
#define __P000 PAGE_NONE
#define __P001 PAGE_READONLY
#define __P010 PAGE_COPY
@@ -200,152 +226,199 @@ extern unsigned long empty_zero_page[1024];
#define __S111 PAGE_SHARED
/*
- * Define this if things work differently on an i386 and an i486:
- * it will (on an i486) warn about kernel memory accesses that are
- * done without a 'verify_area(VERIFY_WRITE,..)'
- *
- * Kernel and User memory-access are done equal, so we don't need verify
+ * Permanent address of a page.
*/
-#undef TEST_VERIFY_AREA
+#define page_address(page) ((page)->virtual)
+#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
-/* page table for 0-4MB for everybody */
-extern unsigned long pg0[1024];
+/*
+ * pgd/pmd/pte query functions
+ */
+extern inline int pgd_present(pgd_t pgd) { return 1; }
+extern inline int pgd_none(pgd_t pgd) { return 0; }
+extern inline int pgd_bad(pgd_t pgd) { return 0; }
-/* number of bits that fit into a memory pointer */
-#define BITS_PER_PTR (8*sizeof(unsigned long))
+extern inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) & _SEG_PRESENT; }
+extern inline int pmd_none(pmd_t pmd) { return pmd_val(pmd) & _PAGE_TABLE_INV; }
+extern inline int pmd_bad(pmd_t pmd)
+{
+ return (pmd_val(pmd) & (~PAGE_MASK & ~_PAGE_TABLE_INV)) != _PAGE_TABLE;
+}
-/* to align the pointer to a pointer address */
-#define PTR_MASK (~(sizeof(void*)-1))
+extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; }
+extern inline int pte_none(pte_t pte)
+{
+ return ((pte_val(pte) &
+ (_PAGE_INVALID | _PAGE_RO | _PAGE_PRESENT)) == _PAGE_INVALID);
+}
-/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
-/* 64-bit machines, beware! SRB. */
-#define SIZEOF_PTR_LOG2 2
+#define pte_same(a,b) (pte_val(a) == pte_val(b))
-/* to find an entry in a page-table */
-#define PAGE_PTR(address) \
-((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
+/*
+ * query functions pte_write/pte_dirty/pte_young only work if
+ * pte_present() is true. Undefined behaviour if not..
+ */
+extern inline int pte_write(pte_t pte)
+{
+ return (pte_val(pte) & _PAGE_RO) == 0;
+}
+extern inline int pte_dirty(pte_t pte)
+{
+ int skey;
+ asm volatile ("iske %0,%1" : "=d" (skey) : "a" (pte_val(pte)));
+ return skey & _PAGE_CHANGED;
+}
-/*
- * CR 7 (SPST) and cr 13 (HPST) are set to the user pgdir.
- * Kernel is running in its own, disjunct address space,
- * running in primary address space.
- * Copy to/from user is done via access register mode with
- * access registers set to 0 or 1. For that purpose we need
- * set up CR 7 with the user pgd.
- *
- */
+extern inline int pte_young(pte_t pte)
+{
+ int skey;
-#define SET_PAGE_DIR(tsk,pgdir) \
-do { \
- unsigned long __pgdir = (__pa(pgdir) & PAGE_MASK ) | _SEGMENT_TABLE; \
- (tsk)->thread.user_seg = __pgdir; \
- if ((tsk) == current) { \
- __asm__ __volatile__("lctl 7,7,%0": :"m" (__pgdir)); \
- __asm__ __volatile__("lctl 13,13,%0": :"m" (__pgdir)); \
- } \
-} while (0)
-
-/*
- * CR 7 (SPST) and cr 13 (HPST) are set to the user pgdir.
- * Kernel is running in its own, disjunct address space,
- * running in primary address space.
- * Copy to/from user is done via access register mode with
- * access registers set to 0 or 1. For that purpose we need
- * set up CR 7 with the user pgd.
- *
+ asm volatile ("iske %0,%1" : "=d" (skey) : "a" (pte_val(pte)));
+ return skey & _PAGE_REFERENCED;
+}
+
+/*
+ * pgd/pmd/pte modification functions
*/
+extern inline void pgd_clear(pgd_t * pgdp) { }
-#define SET_PAGE_DIR(tsk,pgdir) \
-do { \
- unsigned long __pgdir = (__pa(pgdir) & PAGE_MASK ) | _SEGMENT_TABLE; \
- (tsk)->thread.user_seg = __pgdir; \
- if ((tsk) == current) { \
- __asm__ __volatile__("lctl 7,7,%0": :"m" (__pgdir)); \
- __asm__ __volatile__("lctl 13,13,%0": :"m" (__pgdir)); \
- } \
-} while (0)
+extern inline void pmd_clear(pmd_t * pmdp)
+{
+ pmd_val(pmdp[0]) = _PAGE_TABLE_INV;
+ pmd_val(pmdp[1]) = _PAGE_TABLE_INV;
+ pmd_val(pmdp[2]) = _PAGE_TABLE_INV;
+ pmd_val(pmdp[3]) = _PAGE_TABLE_INV;
+}
+extern inline void pte_clear(pte_t *ptep)
+{
+ pte_val(*ptep) = _PAGE_INVALID;
+}
-extern inline int pte_none(pte_t pte) { return ((pte_val(pte) & (_PAGE_INVALID | _PAGE_RO)) == _PAGE_INVALID); }
-extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; }
-extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = _PAGE_INVALID; }
#define PTE_INIT(x) pte_clear(x)
-extern inline int pmd_none(pmd_t pmd) { return pmd_val(pmd) & _PAGE_TABLE_INV; }
-extern inline int pmd_bad(pmd_t pmd) { return (pmd_val(pmd) == 0); }
-extern inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) & _SEG_PRESENT; }
-extern inline void pmd_clear(pmd_t * pmdp) {
- pmd_val(pmdp[0]) = _PAGE_TABLE_INV;
- pmd_val(pmdp[1]) = _PAGE_TABLE_INV;
- pmd_val(pmdp[2]) = _PAGE_TABLE_INV;
- pmd_val(pmdp[3]) = _PAGE_TABLE_INV;
- }
-
/*
- * The "pgd_xxx()" functions here are trivial for a folded two-level
- * setup: the pgd is never bad, and a pmd always exists (as it's folded
- * into the pgd entry)
+ * The following pte modification functions only work if
+ * pte_present() is true. Undefined behaviour if not..
*/
-extern inline int pgd_none(pgd_t pgd) { return 0; }
-extern inline int pgd_bad(pgd_t pgd) { return 0; }
-extern inline int pgd_present(pgd_t pgd) { return 1; }
-extern inline void pgd_clear(pgd_t * pgdp) { }
+extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+ pte_val(pte) = (pte_val(pte) & PAGE_MASK) | pgprot_val(newprot);
+ return pte;
+}
+extern inline pte_t pte_wrprotect(pte_t pte)
+{
+ pte_val(pte) |= _PAGE_RO;
+ return pte;
+}
-/*
- * The following only work if pte_present() is true.
- * Undefined behaviour if not..
- */
-extern inline int pte_write(pte_t pte) { return !(pte_val(pte) & _PAGE_RO); }
-extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
-extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
+extern inline pte_t pte_mkwrite(pte_t pte)
+{
+ pte_val(pte) &= ~_PAGE_RO;
+ return pte;
+}
+
+extern inline pte_t pte_mkclean(pte_t pte)
+{
+ /* We can't clear the changed bit atomically. The iske/and/sske
+ * sequence has a race condition with the page referenced bit.
+ * At the moment pte_mkclean is always followed by a pte_mkold.
+ * So its safe to ignore the problem for now. Hope this will
+ * never change ... */
+ asm volatile ("sske %0,%1"
+ : : "d" (0), "a" (pte_val(pte)));
+ return pte;
+}
+
+extern inline pte_t pte_mkdirty(pte_t pte)
+{
+ /* We can't set the changed bit atomically either. For now we
+ * set (!) the page referenced bit. */
+ asm volatile ("sske %0,%1"
+ : : "d" (_PAGE_CHANGED|_PAGE_REFERENCED),
+ "a" (pte_val(pte)));
+ return pte;
+}
+
+extern inline pte_t pte_mkold(pte_t pte)
+{
+ asm volatile ("rrbe 0,%0" : : "a" (pte_val(pte)));
+ return pte;
+}
+
+extern inline pte_t pte_mkyoung(pte_t pte)
+{
+ /* To set the referenced bit we read the first word from the real
+ * page with a special instruction: load using real address (lura).
+ * Isn't S/390 a nice architecture ?! */
+ asm volatile ("lura 0,%0" : : "a" (pte_val(pte) & PAGE_MASK) : "0" );
+ return pte;
+}
+
+static inline int ptep_test_and_clear_young(pte_t *ptep)
+{
+ int ccode;
-/* who needs that
-extern inline int pte_read(pte_t pte) { return !(pte_val(pte) & _PAGE_INVALID); }
-extern inline int pte_exec(pte_t pte) { return !(pte_val(pte) & _PAGE_INVALID); }
-extern inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) |= _PAGE_INVALID; return pte; }
-extern inline pte_t pte_exprotect(pte_t pte) { pte_val(pte) |= _PAGE_INVALID; return pte; }
-extern inline pte_t pte_mkread(pte_t pte) { pte_val(pte) &= _PAGE_INVALID; return pte; }
-extern inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) &= _PAGE_INVALID; return pte; }
-*/
+ asm volatile ("rrbe 0,%1\n\t"
+ "ipm %0\n\t"
+ "srl %0,28\n\t" : "=d" (ccode) : "a" (pte_val(*ptep)));
+ return ccode & 2;
+}
-extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) |= _PAGE_RO; return pte; }
-extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) &= ~_PAGE_RO ; return pte; }
+static inline int ptep_test_and_clear_dirty(pte_t *ptep)
+{
+ int skey;
+
+ asm volatile ("iske %0,%1" : "=d" (skey) : "a" (*ptep));
+ if ((skey & _PAGE_CHANGED) == 0)
+ return 0;
+ /* We can't clear the changed bit atomically. For now we
+ * clear (!) the page referenced bit. */
+ asm volatile ("sske %0,%1"
+ : : "d" (0), "a" (*ptep));
+ return 1;
+}
-extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
-extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; }
+static inline pte_t ptep_get_and_clear(pte_t *ptep)
+{
+ pte_t pte = *ptep;
+ pte_clear(ptep);
+ return pte;
+}
-extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+static inline void ptep_set_wrprotect(pte_t *ptep)
+{
+ pte_t old_pte = *ptep;
+ set_pte(ptep, pte_wrprotect(old_pte));
+}
+static inline void ptep_mkdirty(pte_t *ptep)
+{
+ pte_mkdirty(*ptep);
+}
/*
* Conversion functions: convert a page and protection to a page entry,
* and a page entry and page directory to the page they refer to.
*/
-#define mk_pte(page, pgprot) \
-({ pte_t __pte; pte_val(__pte) = __pa(((page)-mem_map)<<PAGE_SHIFT) + pgprot_val(pgprot); __pte; })
-
-/* This takes a physical page address that is used by the remapping functions */
-#define mk_pte_phys(physpage, pgprot) \
-({ pte_t __pte; pte_val(__pte) = physpage + pgprot_val(pgprot); __pte; })
-
-extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
-{ pte_val(pte) = (pte_val(pte) & PAGE_MASK) | pgprot_val(newprot); return pte; }
+extern inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
+{
+ pte_t __pte;
+ pte_val(__pte) = physpage + pgprot_val(pgprot);
+ return __pte;
+}
+#define mk_pte(page,pgprot) mk_pte_phys(__pa(((page)-mem_map)<<PAGE_SHIFT),pgprot)
-#define page_address(page) ((page)->virtual)
-#define pte_page(x) (mem_map+(unsigned long)((pte_val(pte) >> PAGE_SHIFT)))
+#define pte_page(x) (mem_map+(unsigned long)((pte_val(x) >> PAGE_SHIFT)))
#define pmd_page(pmd) \
-((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+ ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
/* to find an entry in a page-table-directory */
#define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
-
-#define __pgd_offset(address) pgd_index(address)
-
#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
/* to find an entry in a kernel page-table-directory */
@@ -359,53 +432,39 @@ extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
/* Find an entry in the third-level page table.. */
#define pte_offset(pmd, address) \
-((pte_t *) (pmd_page(*pmd) + ((address>>10) & ((PTRS_PER_PTE-1)<<2))))
-
-
-/* We don't use pmd cache, so these are dummy routines */
-extern __inline__ pmd_t *get_pmd_fast(void)
-{
- return (pmd_t *)0;
-}
-
-extern __inline__ void free_pmd_fast(pmd_t *pmd)
-{
-}
-
-extern __inline__ void free_pmd_slow(pmd_t *pmd)
-{
-}
-
-extern void __handle_bad_pmd(pmd_t *pmd);
-extern void __handle_bad_pmd_kernel(pmd_t *pmd);
+ ((pte_t *) (pmd_page(*pmd) + ((address>>10) & ((PTRS_PER_PTE-1)<<2))))
/*
- * The S390 doesn't have any external MMU info: the kernel page
- * tables contain all the necessary information.
+ * A page-table entry has some bits we have to treat in a special way.
+ * Bits 0, 20 and bit 23 have to be zero, otherwise an specification
+ * exception will occur instead of a page translation exception. The
+ * specifiation exception has the bad habit not to store necessary
+ * information in the lowcore.
+ * Bit 21 and bit 22 are the page invalid bit and the page protection
+ * bit. We set both to indicate a swapped page.
+ * Bit 31 is used as the software page present bit. If a page is
+ * swapped this obviously has to be zero.
+ * This leaves the bits 1-19 and bits 24-30 to store type and offset.
+ * We use the 7 bits from 24-30 for the type and the 19 bits from 1-19
+ * for the offset.
+ * 0| offset |0110|type |0
+ * 00000000001111111111222222222233
+ * 01234567890123456789012345678901
*/
-extern inline void update_mmu_cache(struct vm_area_struct * vma,
- unsigned long address, pte_t pte)
+extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
{
+ pte_t pte;
+ pte_val(pte) = (type << 1) | (offset << 12) | _PAGE_INVALID | _PAGE_RO;
+ pte_val(pte) &= 0x7ffff6fe; /* better to be paranoid */
+ return pte;
}
-/*
- * a page-table entry has only 19 bit for offset and 7 bit for type
- * if bits 0, 20 or 23 are set, a translation specification exceptions occures, and it's
- * hard to find out the failing address
- * therefor, we zero out this bits
- */
-
-#define SWP_TYPE(entry) (((entry).val >> 1) & 0x3f)
-#define SWP_OFFSET(entry) (((entry).val >> 12) & 0x7FFFF )
-#define SWP_ENTRY(type,offset) ((swp_entry_t) { (((type) << 1) | \
- ((offset) << 12) | \
- _PAGE_INVALID | _PAGE_RO) \
- & 0x7ffff6fe })
-
-#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
-#define swp_entry_to_pte(x) ((pte_t) { (x).val })
+#define SWP_TYPE(entry) (((entry).val >> 1) & 0x3f)
+#define SWP_OFFSET(entry) (((entry).val >> 12) & 0x7FFFF )
+#define SWP_ENTRY(type,offset) ((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) })
-#include <asm-generic/pgtable.h>
+#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
+#define swp_entry_to_pte(x) ((pte_t) { (x).val })
#endif /* !__ASSEMBLY__ */
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
index 4629c822b..63f7a2a72 100644
--- a/include/asm-s390/processor.h
+++ b/include/asm-s390/processor.h
@@ -41,7 +41,7 @@ struct cpuinfo_S390
cpuid_t cpu_id;
__u16 cpu_addr;
__u16 cpu_nr;
- unsigned long loops_per_sec;
+ unsigned long loops_per_jiffy;
unsigned long *pgd_quick;
unsigned long *pte_quick;
unsigned long pgtable_cache_sz;
@@ -87,13 +87,15 @@ struct thread_struct
/* perform syscall argument validation (get/set_fs) */
mm_segment_t fs;
per_struct per_info;/* Must be aligned on an 4 byte boundary*/
+ addr_t ieee_instruction_pointer;
+ /* Used to give failing instruction back to user for ieee exceptions */
};
typedef struct thread_struct thread_struct;
#define INIT_MMAP \
{ &init_mm, 0, 0, NULL, PAGE_SHARED, \
-VM_READ | VM_WRITE | VM_EXEC, 1, NULL, &init_mm.mmap }
+VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
#define INIT_THREAD { (struct pt_regs *) 0, \
{ 0,{{0},{0},{0},{0},{0},{0},{0},{0},{0},{0}, \
@@ -108,12 +110,8 @@ VM_READ | VM_WRITE | VM_EXEC, 1, NULL, &init_mm.mmap }
/* need to define ... */
#define start_thread(regs, new_psw, new_stackp) do { \
- unsigned long *u_stack = new_stackp; \
regs->psw.mask = _USER_PSW_MASK; \
- regs->psw.addr = new_psw | 0x80000000 ; \
- get_user(regs->gprs[2],u_stack); \
- get_user(regs->gprs[3],u_stack+1); \
- get_user(regs->gprs[4],u_stack+2); \
+ regs->psw.addr = new_psw | 0x80000000; \
regs->gprs[15] = new_stackp ; \
} while (0)
@@ -172,13 +170,33 @@ unsigned long get_wchan(struct task_struct *p);
static inline void disabled_wait(unsigned long code)
{
char psw_buffer[2*sizeof(psw_t)];
+ char ctl_buf[4];
psw_t *dw_psw = (psw_t *)(((unsigned long) &psw_buffer+sizeof(psw_t)-1)
& -sizeof(psw_t));
dw_psw->mask = 0x000a0000;
dw_psw->addr = code;
- /* load disabled wait psw, the processor is dead afterwards */
- asm volatile ("lpsw 0(%0)" : : "a" (dw_psw));
+ /*
+ * Store status and then load disabled wait psw,
+ * the processor is dead afterwards
+ */
+
+ asm volatile (" stctl 0,0,0(%1)\n"
+ " ni 0(%1),0xef\n" /* switch off protection */
+ " lctl 0,0,0(%1)\n"
+ " stpt 0xd8\n" /* store timer */
+ " stckc 0xe0\n" /* store clock comparator */
+ " stpx 0x108\n" /* store prefix register */
+ " stam 0,15,0x120\n" /* store access registers */
+ " std 0,0x160\n" /* store f0 */
+ " std 2,0x168\n" /* store f2 */
+ " std 4,0x170\n" /* store f4 */
+ " std 6,0x178\n" /* store f6 */
+ " stm 0,15,0x180\n" /* store general registers */
+ " stctl 0,15,0x1c0\n" /* store control registers */
+ " oi 0(%1),0x10\n" /* fake protection bit */
+ " lpsw 0(%0)"
+ : : "a" (dw_psw), "a" (&ctl_buf));
}
#endif /* __ASM_S390_PROCESSOR_H */
diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h
index 60a698662..bf076e9b8 100644
--- a/include/asm-s390/ptrace.h
+++ b/include/asm-s390/ptrace.h
@@ -63,8 +63,8 @@ typedef struct
unsigned storage_alt_space_ctl:1;
unsigned :5;
unsigned :16;
- __u32 starting_addr;
- __u32 ending_addr;
+ addr_t starting_addr;
+ addr_t ending_addr;
} per_cr_bits __attribute__((packed));
typedef struct
@@ -83,13 +83,25 @@ typedef struct
unsigned perc_store_real_address:1;
unsigned :3;
unsigned :1;
- unsigned atmid:5;
+ unsigned atmid_validity_bit:1;
+ unsigned atmid_psw_bit_32:1;
+ unsigned atmid_psw_bit_5:1;
+ unsigned atmid_psw_bit_16:1;
+ unsigned atmid_psw_bit_17:1;
unsigned si:2;
- __u32 address; /* 0x098 */
+ addr_t address; /* 0x098 */
unsigned :4; /* 0x0a1 */
unsigned access_id:4;
} per_lowcore_bits __attribute__((packed));
+typedef enum
+{
+ primary_asce,
+ ar_asce,
+ secondary_asce,
+ home_space_asce
+} per_ai_codes;
+
typedef struct
{
union
@@ -134,6 +146,8 @@ struct user_regs_struct
* this is the way intel does it
*/
per_struct per_info;
+ addr_t ieee_instruction_pointer;
+ /* Used to give failing instruction back to user for ieee exceptions */
};
typedef struct user_regs_struct user_regs_struct;
@@ -143,12 +157,8 @@ typedef struct pt_regs pt_regs;
#ifdef __KERNEL__
#define user_mode(regs) (((regs)->psw.mask & PSW_PROBLEM_STATE) != 0)
#define instruction_pointer(regs) ((regs)->psw.addr)
-
-struct thread_struct;
-extern int sprintf_regs(int line,char *buff,struct task_struct * task,
- struct thread_struct *tss,struct pt_regs * regs);
-extern void show_regs(struct task_struct * task,struct thread_struct *tss,
- struct pt_regs * regs);
+extern void show_regs(struct pt_regs * regs);
+extern char *task_show_regs(struct task_struct *task, char *buffer);
#endif
@@ -270,8 +280,9 @@ enum
PT_CR_9=pt_off(per_info.control_regs.words.cr[0]),
PT_CR_10=pt_off(per_info.control_regs.words.cr[1]),
PT_CR_11=pt_off(per_info.control_regs.words.cr[2]),
- PT_LASTOFF=PT_CR_11,
- PT_ENDREGS=offsetof(user_regs_struct,per_info.lowcore.words.perc_atmid)
+ PT_IEEE_IP=pt_off(ieee_instruction_pointer),
+ PT_LASTOFF=PT_IEEE_IP,
+ PT_ENDREGS=sizeof(user_regs_struct)-1
};
#define PTRACE_AREA \
diff --git a/include/asm-s390/queue.h b/include/asm-s390/queue.h
index 9771d3048..c817d23b3 100644
--- a/include/asm-s390/queue.h
+++ b/include/asm-s390/queue.h
@@ -70,6 +70,35 @@ static __inline__ void add_to_list(list **lhead,list *member)
*lhead=member;
}
+static __inline__ list *remove_listhead(list **lhead)
+{
+ list *oldhead=*lhead;
+
+ if(oldhead)
+ *lhead=(*lhead)->next;
+ return(oldhead);
+}
+
+static __inline__ void add_to_list_tail(list **lhead,list *member)
+{
+ list *curr,*prev;
+ if(*lhead==NULL)
+ *lhead=member;
+ else
+ {
+ prev=*lhead;
+ for(curr=(*lhead)->next;curr!=NULL;curr=curr->next)
+ prev=curr;
+ prev->next=member;
+ }
+}
+static __inline__ void add_to_list_tail_null(list **lhead,list *member)
+{
+ member->next=NULL;
+ add_to_list_tail_null(lhead,member);
+}
+
+
static __inline__ int is_in_list(list *lhead,list *member)
{
list *curr;
@@ -96,6 +125,7 @@ static __inline__ int get_prev(list *lhead,list *member,list **prev)
}
+
static __inline__ int remove_from_list(list **lhead,list *member)
{
list *prev;
@@ -112,6 +142,29 @@ static __inline__ int remove_from_list(list **lhead,list *member)
return(FALSE);
}
+static __inline__ int remove_from_queue(qheader *qhead,queue *member)
+{
+ queue *prev;
+
+ if(get_prev(qhead->head,(list *)member,(list **)&prev))
+ {
+
+ if(prev)
+ {
+ prev->next=member->next;
+ if(prev->next==NULL)
+ qhead->tail=prev;
+ }
+ else
+ {
+ if(qhead->head==qhead->tail)
+ qhead->tail=NULL;
+ qhead->head=member->next;
+ }
+ return(TRUE);
+ }
+ return(FALSE);
+}
diff --git a/include/asm-s390/resource.h b/include/asm-s390/resource.h
index 4e5d91143..bc2520e1d 100644
--- a/include/asm-s390/resource.h
+++ b/include/asm-s390/resource.h
@@ -23,8 +23,8 @@
#define RLIMIT_NOFILE 7 /* max number of open files */
#define RLIMIT_MEMLOCK 8 /* max locked-in-memory address space */
#define RLIMIT_AS 9 /* address space limit */
-#define RLIMIT_AS 10 /* maximum file locks held */
-
+#define RLIMIT_LOCKS 10 /* maximum file locks held */
+
#define RLIM_NLIMITS 11
/*
@@ -37,17 +37,17 @@
#define INIT_RLIMITS \
{ \
- { LONG_MAX, LONG_MAX }, \
- { LONG_MAX, LONG_MAX }, \
- { LONG_MAX, LONG_MAX }, \
- { _STK_LIM, LONG_MAX }, \
- { 0, LONG_MAX }, \
- { LONG_MAX, LONG_MAX }, \
- { MAX_TASKS_PER_USER, MAX_TASKS_PER_USER }, \
+ { RLIM_INFINITY, RLIM_INFINITY }, \
+ { RLIM_INFINITY, RLIM_INFINITY }, \
+ { RLIM_INFINITY, RLIM_INFINITY }, \
+ { _STK_LIM, RLIM_INFINITY }, \
+ { 0, RLIM_INFINITY }, \
+ { RLIM_INFINITY, RLIM_INFINITY }, \
+ { 0, 0 }, \
{ INR_OPEN, INR_OPEN }, \
- { LONG_MAX, LONG_MAX }, \
- { LONG_MAX, LONG_MAX }, \
- { LONG_MAX, LONG_MAX }, \
+ { RLIM_INFINITY, RLIM_INFINITY }, \
+ { RLIM_INFINITY, RLIM_INFINITY }, \
+ { RLIM_INFINITY, RLIM_INFINITY }, \
}
#endif /* __KERNEL__ */
diff --git a/include/asm-s390/s390-gdbregs.h b/include/asm-s390/s390-gdbregs.h
index af708d51d..9527f575e 100644
--- a/include/asm-s390/s390-gdbregs.h
+++ b/include/asm-s390/s390-gdbregs.h
@@ -8,13 +8,14 @@
* used both by the linux kernel for remote debugging & gdb
*/
-/* Say how long (ordinary) registers are. This is a piece of bogosity
- used in push_word and a few other places; REGISTER_RAW_SIZE is the
- real way to know how big a register is. */
#ifndef _S390_GDBREGS_H
#define _S390_GDBREGS_H
+#ifdef __KERNEL__
#include <asm/s390-regs-common.h>
+#else
+#include <s390/s390-regs-common.h>
+#endif
#define S390_MAX_INSTR_SIZE 6
#define NUM_REGS (2+NUM_GPRS+NUM_ACRS+NUM_CRS+1+NUM_FPRS)
#define FIRST_ACR (2+NUM_GPRS)
diff --git a/include/asm-s390/s390-regs-common.h b/include/asm-s390/s390-regs-common.h
index aa349a69d..7934b3dab 100644
--- a/include/asm-s390/s390-regs-common.h
+++ b/include/asm-s390/s390-regs-common.h
@@ -16,8 +16,9 @@
#ifndef __ASSEMBLY__
#include <asm/types.h>
#endif
-
+#if defined(WANT_S390_TGT_DEFS) || defined(__KERNEL__)
#define REGISTER_SIZE 4
+#endif
#define NUM_GPRS 16
#define GPR_SIZE 4
#define PSW_MASK_SIZE 4
@@ -41,8 +42,6 @@ typedef struct
__u32 addr;
} psw_t __attribute__ ((aligned(8)));
-typedef __u32 gpr_t;
-
/* 2 __u32's are used for floats instead to compile with a __STRICT_ANSI__ defined */
typedef union
{
@@ -71,6 +70,13 @@ typedef struct
freg_t fprs[NUM_FPRS];
} s390_fp_regs;
+#define FPC_EXCEPTION_MASK 0xF8000000
+#define FPC_FLAGS_MASK 0x00F80000
+#define FPC_DXC_MASK 0x0000FF00
+#define FPC_RM_MASK 0x00000003
+#define FPC_VALID_MASK ((FPC_EXCEPTION_MASK|FPC_FLAGS_MASK| \
+ FPC_DXC_MASK|FPC_RM_MASK))
+
/*
gdb structures & the kernel have this much always in common
*/
@@ -90,9 +96,11 @@ typedef struct
#define S390_BREAKPOINT_U16 ((__u16)0x0001)
#define S390_SYSCALL_OPCODE ((__u16)0x0a00)
#define S390_SYSCALL_SIZE 2
+#if defined(WANT_S390_TGT_DEFS) || defined(__KERNEL__)
#define ADDR_BITS_REMOVE(addr) ((addr)&0x7fffffff)
#endif
#endif
+#endif
diff --git a/include/asm-s390/s390_ext.h b/include/asm-s390/s390_ext.h
new file mode 100644
index 000000000..08a080441
--- /dev/null
+++ b/include/asm-s390/s390_ext.h
@@ -0,0 +1,30 @@
+#ifndef _S390_EXTINT_H
+#define _S390_EXTINT_H
+
+/*
+ * include/asm-s390/s390_ext.h
+ *
+ * S390 version
+ * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com),
+ * Martin Schwidefsky (schwidefsky@de.ibm.com)
+ */
+
+typedef void (*ext_int_handler_t)(struct pt_regs *regs, __u16 code);
+
+/*
+ * Warning: if you change ext_int_info_t you have to change the
+ * external interrupt handler in entry.S too.
+ */
+typedef struct ext_int_info_t {
+ struct ext_int_info_t *next;
+ ext_int_handler_t handler;
+ __u16 code;
+} __attribute__ ((packed)) ext_int_info_t;
+
+extern ext_int_info_t *ext_int_hash[];
+
+int register_external_interrupt(__u16 code, ext_int_handler_t handler);
+int unregister_external_interrupt(__u16 code, ext_int_handler_t handler);
+
+#endif
diff --git a/include/asm-s390/s390dyn.h b/include/asm-s390/s390dyn.h
index 960a81b43..a728ddf33 100644
--- a/include/asm-s390/s390dyn.h
+++ b/include/asm-s390/s390dyn.h
@@ -12,28 +12,20 @@
struct _devreg;
-typedef int (* oper_handler_func_t)( int irq,
- struct _devreg *dreg);
-typedef void (* io_handler_func_t) ( int irq,
- __u32 intparm );
-typedef void ( * not_oper_handler_func_t)( int irq,
- int status );
+typedef int (* oper_handler_func_t)( int irq,
+ struct _devreg *dreg);
+
+typedef struct _devreg_hc_t {
+ __u16 ctype;
+ __u8 cmode;
+ __u16 dtype;
+ __u8 dmode;
+ } __attribute__ ((packed)) devreg_hc_t;
typedef struct _devreg {
union {
- struct _hc {
- __u16 ctype;
- __u8 cmode;
- __u16 dtype;
- __u8 dmode;
- } hc; /* has controller info */
-
- struct _hnc {
- __u16 dtype;
- __u8 dmode;
- __u16 res1;
- __u8 res2;
- } hnc; /* has no controller info */
+ int devno;
+ devreg_hc_t hc; /* has controller info */
} ci;
int flag;
@@ -46,15 +38,13 @@ typedef struct _devreg {
#define DEVREG_MATCH_DEV_TYPE 0x00000002
#define DEVREG_MATCH_CU_TYPE 0x00000004
#define DEVREG_NO_CU_INFO 0x00000008
+#define DEVREG_NO_DEV_INFO 0x00000010
+#define DEVREG_TYPE_DEVNO 0x80000000
+#define DEVREG_TYPE_DEVCHARS 0x40000000
-int s390_device_register ( devreg_t *drinfo );
-int s390_device_deregister ( devreg_t *dreg );
-int s390_request_irq_special( int irq,
- io_handler_func_t io_handler,
- not_oper_handler_func_t not_oper_handler,
- unsigned long irqflags,
- const char *devname,
- void *dev_id);
+int s390_device_register ( devreg_t *drinfo );
+int s390_device_unregister( devreg_t *dreg );
+devreg_t * s390_search_devreg ( ioinfo_t *ioinfo );
#endif /* __s390dyn */
diff --git a/include/asm-s390/s390io.h b/include/asm-s390/s390io.h
index 8ba9c11db..1a5a0f094 100644
--- a/include/asm-s390/s390io.h
+++ b/include/asm-s390/s390io.h
@@ -47,25 +47,35 @@ typedef struct _ioinfo {
unsigned int s_pend : 1; /* status pending condition */
unsigned int pgid : 1; /* "path group ID" is valid */
unsigned int pgid_supp : 1; /* "path group ID" command is supported */
- unsigned int unused : (sizeof(unsigned int)*8 - 18); /* unused */
+ unsigned int esid : 1; /* Ext. SenseID supported by HW */
+ unsigned int rcd : 1; /* RCD supported by HW */
+ unsigned int repnone : 1; /* don't call IRQ handler on interrupt */
+ unsigned int newreq : 1; /* new register interface */
+ unsigned int dval : 1; /* device number valid */
+ unsigned int unknown : 1; /* unknown device - if SenseID failed */
+ unsigned int unused : (sizeof(unsigned int)*8 - 24); /* unused */
} __attribute__ ((packed)) flags;
} ui;
unsigned long u_intparm; /* user interruption parameter */
senseid_t senseid; /* SenseID info */
irq_desc_t irq_desc; /* irq descriptor */
+ not_oper_handler_func_t nopfunc; /* not oper handler */
__u8 ulpm; /* logical path mask used for I/O */
__u8 opm; /* path mask of operational paths */
+ __u16 devno; /* device number */
pgid_t pgid; /* path group ID */
schib_t schib; /* subchannel information block */
orb_t orb; /* operation request block */
devstat_t devstat; /* device status */
ccw1_t *qcpa; /* queued channel program */
ccw1_t senseccw; /* ccw for sense command */
+ __u8 sense_data[32];/* buffer for basic sense */
unsigned int stctl; /* accumulated status control from irb */
unsigned long qintparm; /* queued interruption parameter */
unsigned long qflag; /* queued flags */
- unsigned char qlpm; /* queued logical path mask */
+ __u8 qlpm; /* queued logical path mask */
+ __u32 syncnt; /* sync I/O recursive usage count */
} __attribute__ ((aligned(8))) ioinfo_t;
diff --git a/include/asm-s390/s390mach.h b/include/asm-s390/s390mach.h
index 56349777a..961e17ecf 100644
--- a/include/asm-s390/s390mach.h
+++ b/include/asm-s390/s390mach.h
@@ -12,14 +12,21 @@
#include <asm/types.h>
-//
-// machine-check-interruption code
-//
-typedef struct _mcic {
+typedef struct _mci {
__u32 to_be_defined_1 : 9;
__u32 cp : 1; /* channel-report pending */
__u32 to_be_defined_2 : 22;
__u32 to_be_defined_3;
+ } mci_t;
+
+//
+// machine-check-interruption code
+//
+typedef struct _mcic {
+ union _mcc {
+ __u64 mcl; /* machine check int. code - long info */
+ mci_t mcd; /* machine check int. code - details */
+ } mcc;
} __attribute__ ((packed)) mcic_t;
//
@@ -37,29 +44,63 @@ typedef struct _crw {
__u32 rsid : 16; /* reporting-source ID */
} __attribute__ ((packed)) crw_t;
+#define CRW_RSC_MONITOR 0x2 /* monitoring facility */
+#define CRW_RSC_SCH 0x3 /* subchannel */
+#define CRW_RSC_CPATH 0x4 /* channel path */
+#define CRW_RSC_CONFIG 0x9 /* configuration-alert facility */
+#define CRW_RSC_CSS 0xB /* channel subsystem */
+
+#define CRW_ERC_EVENT 0x00 /* event information pending */
+#define CRW_ERC_AVAIL 0x01 /* available */
+#define CRW_ERC_INIT 0x02 /* initialized */
+#define CRW_ERC_TERROR 0x03 /* temporary error */
+#define CRW_ERC_IPARM 0x04 /* installed parm initialized */
+#define CRW_ERC_TERM 0x05 /* terminal */
+#define CRW_ERC_PERRN 0x06 /* perm. error, fac. not init */
+#define CRW_ERC_PERRI 0x07 /* perm. error, facility init */
+#define CRW_ERC_PMOD 0x08 /* installed parameters modified */
+
+#define MAX_CRW_PENDING 1024
+#define MAX_MACH_PENDING 1024
+
//
// CRW Entry
//
typedef struct _crwe {
- crw_t crw;
- crw_t *crw_next;
+ crw_t crw;
+ struct _crwe *crwe_next;
} __attribute__ ((packed)) crwe_t;
-typedef struct _mchchk_queue_element {
- spinlock_t lock;
- unsigned int status;
- mcic_t mcic;
- crwe_t *crwe; /* CRW if applicable */
- struct mchchk_queue_element *next;
- struct mchchk_queue_element *prev;
-} mchchk_queue_element_t;
+typedef struct _mache {
+ spinlock_t lock;
+ unsigned int status;
+ mcic_t mcic;
+ union _mc {
+ crwe_t *crwe; /* CRW if applicable */
+ } mc;
+ struct _mache *next;
+ struct _mache *prev;
+} mache_t;
#define MCHCHK_STATUS_TO_PROCESS 0x00000001
#define MCHCHK_STATUS_IN_PROGRESS 0x00000002
#define MCHCHK_STATUS_WAITING 0x00000004
-void s390_init_machine_check ( void );
-void __init s390_do_machine_check ( void );
-void __init s390_machine_check_handler( struct semaphore * );
+void s390_init_machine_check( void );
+void s390_do_machine_check ( void );
+void s390_do_crw_pending ( crwe_t *pcrwe );
+
+extern __inline__ int stcrw( __u32 *pcrw )
+{
+ int ccode;
+
+ __asm__ __volatile__(
+ "STCRW 0(%1)\n\t"
+ "IPM %0\n\t"
+ "SRL %0,28\n\t"
+ : "=d" (ccode) : "a" (pcrw)
+ : "cc", "1" );
+ return ccode;
+}
#endif /* __s390mach */
diff --git a/include/asm-s390/scatterlist.h b/include/asm-s390/scatterlist.h
new file mode 100644
index 000000000..e9cfe86f6
--- /dev/null
+++ b/include/asm-s390/scatterlist.h
@@ -0,0 +1,13 @@
+#ifndef _ASMS390X_SCATTERLIST_H
+#define _ASMS390X_SCATTERLIST_H
+
+struct scatterlist {
+ char * address; /* Location data is to be transferred to */
+ char * alt_address; /* Location of actual if address is a
+ * dma indirect buffer. NULL otherwise */
+ unsigned int length;
+};
+
+#define ISA_DMA_THRESHOLD (0xffffffffffffffff)
+
+#endif /* _ASMS390X_SCATTERLIST_H */
diff --git a/include/asm-s390/semaphore.h b/include/asm-s390/semaphore.h
index fc903d772..dfd49e1d7 100644
--- a/include/asm-s390/semaphore.h
+++ b/include/asm-s390/semaphore.h
@@ -36,7 +36,7 @@ struct semaphore {
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
-extern inline void sema_init (struct semaphore *sem, int val)
+static inline void sema_init (struct semaphore *sem, int val)
{
*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
}
@@ -61,13 +61,13 @@ asmlinkage int __down_interruptible(struct semaphore * sem);
asmlinkage int __down_trylock(struct semaphore * sem);
asmlinkage void __up(struct semaphore * sem);
-extern inline void down(struct semaphore * sem)
+static inline void down(struct semaphore * sem)
{
if (atomic_dec_return(&sem->count) < 0)
__down(sem);
}
-extern inline int down_interruptible(struct semaphore * sem)
+static inline int down_interruptible(struct semaphore * sem)
{
int ret = 0;
@@ -76,7 +76,7 @@ extern inline int down_interruptible(struct semaphore * sem)
return ret;
}
-extern inline int down_trylock(struct semaphore * sem)
+static inline int down_trylock(struct semaphore * sem)
{
int ret = 0;
@@ -85,7 +85,7 @@ extern inline int down_trylock(struct semaphore * sem)
return ret;
}
-extern inline void up(struct semaphore * sem)
+static inline void up(struct semaphore * sem)
{
if (atomic_inc_return(&sem->count) <= 0)
__up(sem);
@@ -136,7 +136,7 @@ struct rw_semaphore {
#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
-extern inline void init_rwsem(struct rw_semaphore *sem)
+static inline void init_rwsem(struct rw_semaphore *sem)
{
atomic_set(&sem->count, RW_LOCK_BIAS);
sem->read_bias_granted = 0;
@@ -149,7 +149,7 @@ extern void __down_read_failed(int, struct rw_semaphore *);
extern void __down_write_failed(int, struct rw_semaphore *);
extern void __rwsem_wake(int, struct rw_semaphore *);
-extern inline void down_read(struct rw_semaphore *sem)
+static inline void down_read(struct rw_semaphore *sem)
{
int count;
count = atomic_dec_return(&sem->count);
@@ -157,7 +157,7 @@ extern inline void down_read(struct rw_semaphore *sem)
__down_read_failed(count, sem);
}
-extern inline void down_write(struct rw_semaphore *sem)
+static inline void down_write(struct rw_semaphore *sem)
{
int count;
count = atomic_add_return (-RW_LOCK_BIAS, &sem->count);
@@ -169,7 +169,7 @@ extern inline void down_write(struct rw_semaphore *sem)
* case is when there was a writer waiting, and we've
* bumped the count to 0: we must wake the writer up.
*/
-extern inline void up_read(struct rw_semaphore *sem)
+static inline void up_read(struct rw_semaphore *sem)
{
int count;
count = atomic_inc_return(&sem->count);
@@ -180,7 +180,7 @@ extern inline void up_read(struct rw_semaphore *sem)
/* releasing the writer is easy -- just release it and
* wake up any sleepers.
*/
-extern inline void up_write(struct rw_semaphore *sem)
+static inline void up_write(struct rw_semaphore *sem)
{
int count;
count = atomic_add_return(RW_LOCK_BIAS, &sem->count);
diff --git a/include/asm-s390/setup.h b/include/asm-s390/setup.h
index 6a9449a52..9e97f2dc0 100644
--- a/include/asm-s390/setup.h
+++ b/include/asm-s390/setup.h
@@ -41,6 +41,7 @@
#define MACHINE_IS_VM (MACHINE_FLAGS & 1)
#define MACHINE_HAS_IEEE (MACHINE_FLAGS & 2)
#define MACHINE_IS_P390 (MACHINE_FLAGS & 4)
+#define MACHINE_HAS_CSP (MACHINE_FLAGS & 8)
#define RAMDISK_ORIGIN 0x800000
#define RAMDISK_BLKSIZE 0x1000
diff --git a/include/asm-s390/sigcontext.h b/include/asm-s390/sigcontext.h
index 610f20e26..25c65e26a 100644
--- a/include/asm-s390/sigcontext.h
+++ b/include/asm-s390/sigcontext.h
@@ -2,12 +2,15 @@
* include/asm-s390/sigcontext.h
*
* S390 version
- * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
*/
#ifndef _ASM_S390_SIGCONTEXT_H
#define _ASM_S390_SIGCONTEXT_H
-#include <asm/s390-regs-common.h>
+
+#define __NUM_GPRS 16
+#define __NUM_FPRS 16
+#define __NUM_ACRS 16
/*
Has to be at least _NSIG_WORDS from asm/signal.h
@@ -15,20 +18,39 @@
#define _SIGCONTEXT_NSIG 64
#define _SIGCONTEXT_NSIG_BPW 32
/* Size of stack frame allocated when calling signal handler. */
-#define __SIGNAL_FRAMESIZE STACK_FRAME_OVERHEAD
-#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
-#define SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
+#define __SIGNAL_FRAMESIZE 96
+#define _SIGCONTEXT_NSIG_WORDS (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
+#define _SIGMASK_COPY_SIZE (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
+
+typedef struct
+{
+ unsigned long mask;
+ unsigned long addr;
+} _psw_t __attribute__ ((aligned(8)));
+
+typedef struct
+{
+ _psw_t psw;
+ unsigned long gprs[__NUM_GPRS];
+ unsigned int acrs[__NUM_ACRS];
+} _s390_regs_common __attribute__ ((packed));
+
+typedef struct
+{
+ unsigned int fpc;
+ double fprs[__NUM_FPRS];
+} _s390_fp_regs;
typedef struct
{
- s390_regs_common regs;
- s390_fp_regs fpregs;
-} sigregs;
+ _s390_regs_common regs;
+ _s390_fp_regs fpregs;
+} _sigregs;
struct sigcontext
{
unsigned long oldmask[_SIGCONTEXT_NSIG_WORDS];
- sigregs *sregs;
+ _sigregs *sregs;
};
diff --git a/include/asm-s390/siginfo.h b/include/asm-s390/siginfo.h
index 1efd4e1c3..876e8baae 100644
--- a/include/asm-s390/siginfo.h
+++ b/include/asm-s390/siginfo.h
@@ -85,6 +85,25 @@ typedef struct siginfo {
#define si_band _sifields._sigpoll._band
#define si_fd _sifields._sigpoll._fd
+#ifdef __KERNEL__
+#define __SI_MASK 0xffff0000
+#define __SI_KILL (0 << 16)
+#define __SI_TIMER (1 << 16)
+#define __SI_POLL (2 << 16)
+#define __SI_FAULT (3 << 16)
+#define __SI_CHLD (4 << 16)
+#define __SI_RT (5 << 16)
+#define __SI_CODE(T,N) ((T) << 16 | ((N) & 0xffff))
+#else
+#define __SI_KILL 0
+#define __SI_TIMER 0
+#define __SI_POLL 0
+#define __SI_FAULT 0
+#define __SI_CHLD 0
+#define __SI_RT 0
+#define __SI_CODE(T,N) (N)
+#endif
+
/*
* si_code values
* Digital reserves positive values for kernel-generated signals.
@@ -202,4 +221,20 @@ typedef struct sigevent {
#define sigev_notify_function _sigev_un._sigev_thread._function
#define sigev_notify_attributes _sigev_un._sigev_thread._attribute
+#ifdef __KERNEL__
+#include <linux/string.h>
+
+extern inline void copy_siginfo(siginfo_t *to, siginfo_t *from)
+{
+ if (from->si_code < 0)
+ memcpy(to, from, sizeof(siginfo_t));
+ else
+ /* _sigchld is currently the largest know union member */
+ memcpy(to, from, 3*sizeof(int) + sizeof(from->_sifields._sigchld));
+}
+
+extern int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from);
+
+#endif /* __KERNEL__ */
+
#endif
diff --git a/include/asm-s390/sigp.h b/include/asm-s390/sigp.h
index 5154a34a5..bbf97d5c9 100644
--- a/include/asm-s390/sigp.h
+++ b/include/asm-s390/sigp.h
@@ -41,83 +41,6 @@ typedef enum
sigp_store_extended_status_at_address
} sigp_order_code;
-#if 0
-/*
- * these definitions are not used at the moment, but we might need
- * them in future.
- */
-typedef struct
-{
- __u64 cpu_timer;
- psw_t current_psw;
- __u32 prefix;
- __u32 access_regs[16];
- __u64 float_regs[4];
- __u32 gpr_regs[16];
- __u32 control_regs[16];
-} sigp_status __attribute__((packed));
-
-typedef struct
-{
- __u8 unused1[216];
- __u64 cpu_timer;
- psw_t current_psw;
- __u32 prefix;
- __u32 access_regs[16];
- __u64 float_regs[4];
- __u32 gpr_regs[16];
- __u32 control_regs[16];
-} sigp_status_512 __attribute__((packed));
-
-typedef struct
-{
- __u32 extended_save_area_address;
- __u64 cpu_timer;
- psw_t current_psw;
- __u32 prefix;
- __u32 access_regs[16];
- __u64 float_regs[4];
- __u32 gpr_regs[16];
- __u32 control_regs[16];
-} sigp_extended_status __attribute__((packed));
-
-typedef struct
-{
- __u8 unused1[212];
- __u32 extended_save_area_address;
- __u64 cpu_timer;
- psw_t current_psw;
- __u32 prefix;
- __u32 access_regs[16];
- __u64 float_regs[4];
- __u32 gpr_regs[16];
- __u32 control_regs[16];
-} sigp_extended_status_512 __attribute__((packed));
-
-typedef struct
-{
- __u64 bfp_float_regs[16];
- __u32 bfp_float_control_reg;
- __u8 reserved[12];
-} sigp_extended_save_area __attribute__ ((packed));
-
-typedef struct
-{
- unsigned equipment_check:1;
- unsigned unassigned1:20;
- unsigned incorrect_state:1;
- unsigned invalid_parameter:1;
- unsigned external_call_pending:1;
- unsigned stopped:1;
- unsigned operator_intervening:1;
- unsigned check_stop:1;
- unsigned unassigned2:1;
- unsigned inoperative:1;
- unsigned invalid_order:1;
- unsigned receiver_check:1;
-} sigp_status_bits __attribute__((packed));
-#endif
-
typedef __u32 sigp_status_word;
typedef enum
@@ -140,16 +63,15 @@ typedef enum
ec_restart,
ec_halt,
ec_power_off,
+ ec_ptlb,
ec_bit_last
} ec_bit_sig;
/* Signals which come with a parameter area, synchronous */
typedef enum
{
- ec_set_ctl,
- ec_get_ctl,
- ec_set_ctl_masked,
- ec_cmd_last
+ ec_callback_async,
+ ec_callback_sync
} ec_cmd_sig;
/* state information for synchronous signals */
@@ -166,26 +88,10 @@ typedef struct ec_ext_call
ec_cmd_sig cmd;
atomic_t status;
struct ec_ext_call *next;
- void *parms;
+ void (*func)(void *info);
+ void *info;
} ec_ext_call;
-/* parameter area for the ec_set_ctl and ec_get_ctl signal */
-typedef struct
-{
- __u16 start_ctl;
- __u16 end_ctl;
- __u32 cregs[16];
-} ec_creg_parms;
-
-/* parameter area for the ec_set_ctl_masked signal */
-typedef struct
-{
- __u16 start_ctl;
- __u16 end_ctl;
- __u32 orvals[16];
- __u32 andvals[16];
-} ec_creg_mask_parms;
-
/*
* Signal processor
*/
diff --git a/include/asm-s390/smp.h b/include/asm-s390/smp.h
index d7f246bb7..2922f398a 100644
--- a/include/asm-s390/smp.h
+++ b/include/asm-s390/smp.h
@@ -13,7 +13,7 @@
#ifndef __ASSEMBLY__
#include <asm/lowcore.h>
-#include <linux/tasks.h> // FOR NR_CPUS definition only.
+#include <linux/threads.h> // FOR NR_CPUS definition only.
#include <linux/kernel.h> // FOR FASTCALL definition
#define smp_processor_id() (current->processor)
@@ -31,7 +31,6 @@
#define PROC_CHANGE_PENALTY 20 /* Schedule penalty */
-extern unsigned long ipi_count;
extern void count_cpus(void);
extern __inline__ int cpu_logical_map(int cpu)
@@ -67,10 +66,11 @@ typedef struct
__u16 cpu;
} sigp_info;
-sigp_ccode smp_ext_call_sync(int cpu, ec_cmd_sig cmd,void *parms);
-sigp_ccode smp_ext_call_async(int cpu, ec_bit_sig sig);
-void smp_ext_call_sync_others(ec_cmd_sig cmd, void *parms);
-void smp_ext_call_async_others(ec_bit_sig sig);
+sigp_ccode
+smp_ext_call(int cpu, void (*callback)(void *info), void *info, int wait);
+void smp_ext_call_others(void (*callback)(void *info), void *info, int wait);
+sigp_ccode smp_ext_bitcall(int cpu, ec_bit_sig sig);
+void smp_ext_bitcall_others(ec_bit_sig sig);
int smp_signal_others(sigp_order_code order_code,__u32 parameter,
int spin,sigp_info *info);
diff --git a/include/asm-s390/smplock.h b/include/asm-s390/smplock.h
index 4ebd38025..1f6485fb0 100644
--- a/include/asm-s390/smplock.h
+++ b/include/asm-s390/smplock.h
@@ -7,10 +7,12 @@
*/
#include <linux/interrupt.h>
-#include <asm/spinlock.h>
+#include <linux/spinlock.h>
extern spinlock_t kernel_flag;
+#define kernel_locked() spin_is_locked(&kernel_flag)
+
/*
* Release global kernel lock and global interrupt lock
*/
diff --git a/include/asm-s390/socket.h b/include/asm-s390/socket.h
index 0d00c3b54..7b52cdb8f 100644
--- a/include/asm-s390/socket.h
+++ b/include/asm-s390/socket.h
@@ -51,6 +51,8 @@
#define SO_TIMESTAMP 29
#define SCM_TIMESTAMP SO_TIMESTAMP
+#define SO_ACCEPTCONN 30
+
/* Nast libc5 fixup - bletch */
#if defined(__KERNEL__)
/* Socket types. */
diff --git a/include/asm-s390/spinlock.h b/include/asm-s390/spinlock.h
index 9c7725b55..52bcfc739 100644
--- a/include/asm-s390/spinlock.h
+++ b/include/asm-s390/spinlock.h
@@ -24,37 +24,36 @@ typedef struct {
#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
#define spin_lock_init(lp) do { (lp)->lock = 0; } while(0)
-#define spin_unlock_wait(lp) do { barrier(); } while((volatile spinlock_t *)(lp)->lock)
+#define spin_unlock_wait(lp) do { barrier(); } while(((volatile spinlock_t *)(lp))->lock)
#define spin_is_locked(x) ((x)->lock != 0)
extern inline void spin_lock(spinlock_t *lp)
{
- __asm__ __volatile(" lhi 1,-1\n"
- "0: slr 0,0\n"
- " cs 0,1,%1\n"
- " jl 0b"
- : "=m" (lp->lock)
- : "0" (lp->lock) : "0", "1");
+ __asm__ __volatile(" bras 1,1f\n"
+ "0: diag 0,0,68\n"
+ "1: slr 0,0\n"
+ " cs 0,1,%1\n"
+ " jl 0b\n"
+ : "=m" (lp->lock)
+ : "0" (lp->lock) : "0", "1", "cc" );
}
extern inline int spin_trylock(spinlock_t *lp)
{
unsigned long result;
__asm__ __volatile(" slr %1,%1\n"
- " lhi 0,-1\n"
- "0: cs %1,0,%0"
+ " basr 1,0\n"
+ "0: cs %1,1,%0"
: "=m" (lp->lock), "=&d" (result)
- : "0" (lp->lock) : "0");
+ : "0" (lp->lock) : "1", "cc" );
return !result;
}
-
-
extern inline void spin_unlock(spinlock_t *lp)
{
__asm__ __volatile(" xc 0(4,%0),0(%0)\n"
" bcr 15,0"
- : /* no output */ : "a" (lp) );
+ : /* no output */ : "a" (lp) : "memory", "cc" );
}
/*
@@ -76,45 +75,42 @@ typedef struct {
#define read_lock(rw) \
asm volatile(" l 2,%0\n" \
- "0: sll 2,1\n" \
- " srl 2,1\n" /* clear high (=write) bit */ \
- " lr 3,2\n" \
- " ahi 3,1\n" /* one more reader */ \
+ " j 1f\n" \
+ "0: diag 0,0,68\n" \
+ "1: la 2,0(2)\n" /* clear high (=write) bit */ \
+ " la 3,1(2)\n" /* one more reader */ \
" cs 2,3,%0\n" /* try to write new value */ \
" jl 0b" \
- : "+m" ((rw)->lock) : : "2", "3" );
+ : "+m" ((rw)->lock) : : "2", "3", "cc" );
#define read_unlock(rw) \
asm volatile(" l 2,%0\n" \
- "0: lr 3,2\n" \
+ " j 1f\n" \
+ "0: diag 0,0,68\n" \
+ "1: lr 3,2\n" \
" ahi 3,-1\n" /* one less reader */ \
" cs 2,3,%0\n" \
" jl 0b" \
- : "+m" ((rw)->lock) : : "2", "3" );
+ : "+m" ((rw)->lock) : : "2", "3", "cc" );
#define write_lock(rw) \
asm volatile(" lhi 3,1\n" \
" sll 3,31\n" /* new lock value = 0x80000000 */ \
- "0: slr 2,2\n" /* old lock value must be 0 */ \
+ " j 1f\n" \
+ "0: diag 0,0,68\n" \
+ "1: slr 2,2\n" /* old lock value must be 0 */ \
" cs 2,3,%0\n" \
" jl 0b" \
- : "+m" ((rw)->lock) : : "2", "3" );
+ : "+m" ((rw)->lock) : : "2", "3", "cc" );
#define write_unlock(rw) \
asm volatile(" slr 3,3\n" /* new lock value = 0 */ \
- "0: lhi 2,1\n" \
+ " j 1f\n" \
+ "0: diag 0,0,68\n" \
+ "1: lhi 2,1\n" \
" sll 2,31\n" /* old lock value must be 0x80000000 */ \
" cs 2,3,%0\n" \
" jl 0b" \
- : "+m" ((rw)->lock) : : "2", "3" );
+ : "+m" ((rw)->lock) : : "2", "3", "cc" );
#endif /* __ASM_SPINLOCK_H */
-
-
-
-
-
-
-
-
-
diff --git a/include/asm-s390/stat.h b/include/asm-s390/stat.h
index be52ef679..a0edcab80 100644
--- a/include/asm-s390/stat.h
+++ b/include/asm-s390/stat.h
@@ -50,36 +50,30 @@ struct stat {
* insane amounts of padding around dev_t's.
*/
struct stat64 {
- unsigned short st_dev;
unsigned char __pad0[6];
-
- unsigned long long st_ino;
+ unsigned short st_dev;
+ unsigned int __pad1;
+#define STAT64_HAS_BROKEN_ST_INO 1
+ unsigned long __st_ino;
unsigned int st_mode;
unsigned int st_nlink;
-
unsigned long st_uid;
unsigned long st_gid;
-
+ unsigned char __pad2[6];
unsigned short st_rdev;
- unsigned char __pad3[10];
-
+ unsigned int __pad3;
long long st_size;
unsigned long st_blksize;
-
- unsigned long st_blocks; /* Number 512-byte blocks allocated. */
- unsigned long __pad4; /* future possible st_blocks high bits */
-
+ unsigned char __pad4[4];
+ unsigned long __pad5; /* future possible st_blocks high bits */
+ unsigned long st_blocks; /* Number 512-byte blocks allocated. */
unsigned long st_atime;
- unsigned long __pad5;
-
- unsigned long st_mtime;
unsigned long __pad6;
-
+ unsigned long st_mtime;
+ unsigned long __pad7;
unsigned long st_ctime;
- unsigned long __pad7; /* will be high 32 bits of ctime someday */
-
- unsigned long __unused1;
- unsigned long __unused2;
+ unsigned long __pad8; /* will be high 32 bits of ctime someday */
+ unsigned long long st_ino;
};
#endif
diff --git a/include/asm-s390/string.h b/include/asm-s390/string.h
index 2e8081912..304979b83 100644
--- a/include/asm-s390/string.h
+++ b/include/asm-s390/string.h
@@ -40,24 +40,29 @@
#undef __HAVE_ARCH_STRSTR
extern void *memset(void *, int, size_t);
+extern void *memcpy(void *, const void *, size_t);
+extern void *memmove(void *, const void *, size_t);
+extern char *strncpy(char *, const char *, size_t);
+extern int strcmp(const char *,const char *);
-extern inline void * memchr(const void * cs,int c,size_t count)
+static inline void * memchr(const void * cs,int c,size_t count)
{
void *ptr;
__asm__ __volatile__ (" lr 0,%2\n"
+ " lr 1,%1\n"
" la %0,0(%3,%1)\n"
- "0: srst %0,%1\n"
+ "0: srst %0,1\n"
" jo 0b\n"
" brc 13,1f\n"
" slr %0,%0\n"
"1:"
- : "=a" (ptr) : "a" (cs), "d" (c), "d" (count)
- : "cc", "0" );
+ : "=&a" (ptr) : "a" (cs), "d" (c), "d" (count)
+ : "cc", "0", "1" );
return ptr;
}
-extern __inline__ char *strcpy(char *dest, const char *src)
+static __inline__ char *strcpy(char *dest, const char *src)
{
char *tmp = dest;
@@ -69,7 +74,7 @@ extern __inline__ char *strcpy(char *dest, const char *src)
return tmp;
}
-extern __inline__ size_t strlen(const char *s)
+static __inline__ size_t strlen(const char *s)
{
size_t len;
@@ -84,7 +89,7 @@ extern __inline__ size_t strlen(const char *s)
return len;
}
-extern __inline__ char *strcat(char *dest, const char *src)
+static __inline__ char *strcat(char *dest, const char *src)
{
char *tmp = dest;
@@ -100,8 +105,13 @@ extern __inline__ char *strcat(char *dest, const char *src)
return tmp;
}
+extern void *alloca(size_t);
#endif /* __KERNEL__ */
#endif /* __S390_STRING_H_ */
+
+
+
+
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h
index afced6af1..49ccb1a74 100644
--- a/include/asm-s390/system.h
+++ b/include/asm-s390/system.h
@@ -12,6 +12,7 @@
#define __ASM_SYSTEM_H
#include <linux/config.h>
+#include <asm/types.h>
#ifdef __KERNEL__
#include <asm/lowcore.h>
#endif
@@ -40,7 +41,7 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
asm volatile (
" lhi 1,3\n"
" nr 1,%0\n" /* isolate last 2 bits */
- " xr 1,%0\n" /* align ptr */
+ " xr %0,1\n" /* align ptr */
" bras 2,0f\n"
" icm 1,8,%1\n" /* for ptr&3 == 0 */
" stcm 0,8,%1\n"
@@ -52,13 +53,13 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
" stcm 0,1,%1\n"
"0: sll 1,3\n"
" la 2,0(1,2)\n" /* r2 points to an icm */
- " l 0,%1\n" /* get fullword */
+ " l 0,0(%0)\n" /* get fullword */
"1: lr 1,0\n" /* cs loop */
" ex 0,0(2)\n" /* insert x */
- " cs 0,1,%1\n"
+ " cs 0,1,0(%0)\n"
" jl 1b\n"
" ex 0,4(2)" /* store *ptr to x */
- : "+a&" (ptr) : "m" (x)
+ : "+a&" (ptr), "+m" (x) :
: "memory", "0", "1", "2");
case 2:
if(((__u32)ptr)&1)
@@ -66,7 +67,7 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
asm volatile (
" lhi 1,2\n"
" nr 1,%0\n" /* isolate bit 2^1 */
- " xr 1,%0\n" /* align ptr */
+ " xr %0,1\n" /* align ptr */
" bras 2,0f\n"
" icm 1,12,%1\n" /* for ptr&2 == 0 */
" stcm 0,12,%1\n"
@@ -74,13 +75,13 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
" stcm 0,3,%1\n"
"0: sll 1,2\n"
" la 2,0(1,2)\n" /* r2 points to an icm */
- " l 0,%1\n" /* get fullword */
+ " l 0,0(%0)\n" /* get fullword */
"1: lr 1,0\n" /* cs loop */
" ex 0,0(2)\n" /* insert x */
- " cs 0,1,%1\n"
+ " cs 0,1,0(%0)\n"
" jl 1b\n"
" ex 0,4(2)" /* store *ptr to x */
- : "+a&" (ptr) : "m" (x)
+ : "+a&" (ptr), "+m" (x) :
: "memory", "0", "1", "2");
break;
case 4:
@@ -115,6 +116,12 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
#define mb() eieio()
#define rmb() eieio()
#define wmb() eieio()
+#define smp_mb() mb()
+#define smp_rmb() rmb()
+#define smp_wmb() wmb()
+#define smp_mb__before_clear_bit() smp_mb()
+#define smp_mb__after_clear_bit() smp_mb()
+
#define set_mb(var, value) do { var = value; mb(); } while (0)
#define set_wmb(var, value) do { var = value; wmb(); } while (0)
@@ -139,6 +146,27 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
#define __restore_flags(x) \
__asm__ __volatile__("ssm %0" : : "m" (x) : "memory")
+#define __load_psw(psw) \
+ __asm__ __volatile__("lpsw %0" : : "m" (psw));
+
+#define __ctl_load(array, low, high) ({ \
+ __asm__ __volatile__ ( \
+ " la 1,%0\n" \
+ " bras 2,0f\n" \
+ " lctl 0,0,0(1)\n" \
+ "0: ex %1,0(2)" \
+ : : "m" (array), "a" (((low)<<4)+(high)) : "1", "2" ); \
+ })
+
+#define __ctl_store(array, low, high) ({ \
+ __asm__ __volatile__ ( \
+ " la 1,%0\n" \
+ " bras 2,0f\n" \
+ " stctl 0,0,0(1)\n" \
+ "0: ex %1,0(2)" \
+ : "=m" (array) : "a" (((low)<<4)+(high)): "1", "2" ); \
+ })
+
#define __ctl_set_bit(cr, bit) ({ \
__u8 dummy[16]; \
__asm__ __volatile__ ( \
@@ -220,7 +248,6 @@ extern int save_fp_regs1(s390_fp_regs *fpregs);
extern void save_fp_regs(s390_fp_regs *fpregs);
extern int restore_fp_regs1(s390_fp_regs *fpregs);
extern void restore_fp_regs(s390_fp_regs *fpregs);
-extern void show_crashed_task_info(void);
#endif
#endif
diff --git a/include/asm-s390/termios.h b/include/asm-s390/termios.h
index 86415c0a2..30defbf1d 100644
--- a/include/asm-s390/termios.h
+++ b/include/asm-s390/termios.h
@@ -60,7 +60,7 @@ struct termio {
#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 IR - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA 11 /* Linux IR - http://irda.sourceforge.net/ */
#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */
#define N_HDLC 13 /* synchronous HDLC */
@@ -77,18 +77,19 @@ struct termio {
/*
* Translate a "termio" structure into a "termios". Ugh.
*/
-#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
- unsigned short __tmp; \
- get_user(__tmp,&(termio)->x); \
- *(unsigned short *) &(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); \
+ unsigned short tmp; \
+ get_user(tmp, &(termio)->c_iflag); \
+ (termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \
+ get_user(tmp, &(termio)->c_oflag); \
+ (termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \
+ get_user(tmp, &(termio)->c_cflag); \
+ (termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \
+ get_user(tmp, &(termio)->c_lflag); \
+ (termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \
+ get_user((termios)->c_line, &(termio)->c_line); \
copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
})
diff --git a/include/asm-s390/todclk.h b/include/asm-s390/todclk.h
new file mode 100644
index 000000000..92a27a9d4
--- /dev/null
+++ b/include/asm-s390/todclk.h
@@ -0,0 +1,19 @@
+/*
+ * File...........: linux/include/asm/todclk.h
+ * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ * Bugreports.to..: <Linux390@de.ibm.com>
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+ *
+ * History of changes (starts July 2000)
+ */
+
+#ifndef __ASM_TODCLK_H
+#define __ASM_TODCLK_H
+
+#define TOD_uSEC (0x1000ULL)
+#define TOD_mSEC (1000 * TOD_uSEC)
+#define TOD_SEC (1000 * TOD_mSEC)
+#define TOD_MIN (60 * TOD_SEC)
+#define TOD_HOUR (60 * TOD_MIN)
+
+#endif
diff --git a/include/asm-s390/uaccess.h b/include/asm-s390/uaccess.h
index a19cfa29f..3bcf7bbed 100644
--- a/include/asm-s390/uaccess.h
+++ b/include/asm-s390/uaccess.h
@@ -84,15 +84,14 @@ extern inline int __put_user_asm_4(__u32 x, void *ptr)
{
int err;
- __asm__ __volatile__ ( " iac 1\n"
- " sr %1,%1\n"
+ __asm__ __volatile__ ( " sr %1,%1\n"
" la 4,%0\n"
" sacf 512\n"
"0: st %2,0(4)\n"
- " sacf 0(1)\n"
+ " sacf 0\n"
"1:\n"
".section .fixup,\"ax\"\n"
- "2: sacf 0(1)\n"
+ "2: sacf 0\n"
" lhi %1,%h3\n"
" bras 4,3f\n"
" .long 1b\n"
@@ -105,7 +104,7 @@ extern inline int __put_user_asm_4(__u32 x, void *ptr)
".previous"
: "=m" (*((__u32*) ptr)) , "=&d" (err)
: "d" (x), "K" (-EFAULT)
- : "1", "4" );
+ : "4" );
return err;
}
@@ -113,15 +112,14 @@ extern inline int __put_user_asm_2(__u16 x, void *ptr)
{
int err;
- __asm__ __volatile__ ( " iac 1\n"
- " sr %1,%1\n"
+ __asm__ __volatile__ ( " sr %1,%1\n"
" la 4,%0\n"
" sacf 512\n"
"0: sth %2,0(4)\n"
- " sacf 0(1)\n"
+ " sacf 0\n"
"1:\n"
".section .fixup,\"ax\"\n"
- "2: sacf 0(1)\n"
+ "2: sacf 0\n"
" lhi %1,%h3\n"
" bras 4,3f\n"
" .long 1b\n"
@@ -134,7 +132,7 @@ extern inline int __put_user_asm_2(__u16 x, void *ptr)
".previous"
: "=m" (*((__u16*) ptr)) , "=&d" (err)
: "d" (x), "K" (-EFAULT)
- : "1", "4" );
+ : "4" );
return err;
}
@@ -142,15 +140,14 @@ extern inline int __put_user_asm_1(__u8 x, void *ptr)
{
int err;
- __asm__ __volatile__ ( " iac 1\n"
- " sr %1,%1\n"
+ __asm__ __volatile__ ( " sr %1,%1\n"
" la 4,%0\n"
" sacf 512\n"
"0: stc %2,0(4)\n"
- " sacf 0(1)\n"
+ " sacf 0\n"
"1:\n"
".section .fixup,\"ax\"\n"
- "2: sacf 0(1)\n"
+ "2: sacf 0\n"
" lhi %1,%h3\n"
" bras 4,3f\n"
" .long 1b\n"
@@ -163,7 +160,7 @@ extern inline int __put_user_asm_1(__u8 x, void *ptr)
".previous"
: "=m" (*((__u8*) ptr)) , "=&d" (err)
: "d" (x), "K" (-EFAULT)
- : "1", "4" );
+ : "4" );
return err;
}
@@ -176,13 +173,13 @@ extern inline int __put_user_asm_1(__u8 x, void *ptr)
int __pu_err; \
switch (sizeof (*(ptr))) { \
case 1: \
- __pu_err = __put_user_asm_1((__u8)(__u32)x,ptr);\
+ __pu_err = __put_user_asm_1((__u8)(__u32)x,(ptr));\
break; \
case 2: \
- __pu_err = __put_user_asm_2((__u16)(__u32)x,ptr);\
+ __pu_err = __put_user_asm_2((__u16)(__u32)x,(ptr));\
break; \
case 4: \
- __pu_err = __put_user_asm_4((__u32) x,ptr);\
+ __pu_err = __put_user_asm_4((__u32) x,(ptr));\
break; \
default: \
__pu_err = __put_user_bad(); \
@@ -195,7 +192,7 @@ extern inline int __put_user_asm_1(__u8 x, void *ptr)
({ \
long __pu_err = -EFAULT; \
__typeof__(*(ptr)) *__pu_addr = (ptr); \
- __typeof__(x) __x = (x); \
+ __typeof__(*(ptr)) __x = (x); \
if (__access_ok((long)__pu_addr,sizeof(*(ptr)))) { \
__pu_err = 0; \
__put_user((__x), (__pu_addr)); \
@@ -206,83 +203,80 @@ extern inline int __put_user_asm_1(__u8 x, void *ptr)
extern int __put_user_bad(void);
-#define __get_user_asm_4(x, ptr, err) \
-({ \
- __asm__ __volatile__ ( " iac 1\n" \
- " sr %1,%1\n" \
- " la 4,%2\n" \
- " sacf 512\n" \
- "0: l %0,0(4)\n" \
- " sacf 0(1)\n" \
- "1:\n" \
- ".section .fixup,\"ax\"\n" \
- "2: sacf 0(1)\n" \
- " lhi %1,%h3\n" \
- " bras 4,3f\n" \
- " .long 1b\n" \
- "3: l 4,0(4)\n" \
- " br 4\n" \
- ".previous\n" \
- ".section __ex_table,\"a\"\n" \
- " .align 4\n" \
- " .long 0b,2b\n" \
- ".previous" \
- : "=d" (x) , "=&d" (err) \
- : "m" (*(__u32*) ptr), "K" (-EFAULT) \
- : "1", "4" ); \
+#define __get_user_asm_4(x, ptr, err) \
+({ \
+ __asm__ __volatile__ ( " sr %1,%1\n" \
+ " la 4,%2\n" \
+ " sacf 512\n" \
+ "0: l %0,0(4)\n" \
+ " sacf 0\n" \
+ "1:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "2: sacf 0\n" \
+ " lhi %1,%h3\n" \
+ " bras 4,3f\n" \
+ " .long 1b\n" \
+ "3: l 4,0(4)\n" \
+ " br 4\n" \
+ ".previous\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 4\n" \
+ " .long 0b,2b\n" \
+ ".previous" \
+ : "=d" (x) , "=&d" (err) \
+ : "m" (*(const __u32*)(ptr)),"K" (-EFAULT) \
+ : "4" ); \
})
-#define __get_user_asm_2(x, ptr, err) \
-({ \
- __asm__ __volatile__ ( " iac 1\n" \
- " sr %1,%1\n" \
- " la 4,%2\n" \
- " sacf 512\n" \
- "0: lh %0,0(4)\n" \
- " sacf 0(1)\n" \
- "1:\n" \
- ".section .fixup,\"ax\"\n" \
- "2: sacf 0(1)\n" \
- " lhi %1,%h3\n" \
- " bras 4,3f\n" \
- " .long 1b\n" \
- "3: l 4,0(4)\n" \
- " br 4\n" \
- ".previous\n" \
- ".section __ex_table,\"a\"\n" \
- " .align 4\n" \
- " .long 0b,2b\n" \
- ".previous" \
- : "=d" (x) , "=&d" (err) \
- : "m" (*(__u16*) ptr), "K" (-EFAULT) \
- : "1", "4" ); \
+#define __get_user_asm_2(x, ptr, err) \
+({ \
+ __asm__ __volatile__ ( " sr %1,%1\n" \
+ " la 4,%2\n" \
+ " sacf 512\n" \
+ "0: lh %0,0(4)\n" \
+ " sacf 0\n" \
+ "1:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "2: sacf 0\n" \
+ " lhi %1,%h3\n" \
+ " bras 4,3f\n" \
+ " .long 1b\n" \
+ "3: l 4,0(4)\n" \
+ " br 4\n" \
+ ".previous\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 4\n" \
+ " .long 0b,2b\n" \
+ ".previous" \
+ : "=d" (x) , "=&d" (err) \
+ : "m" (*(const __u16*)(ptr)),"K" (-EFAULT) \
+ : "4" ); \
})
-#define __get_user_asm_1(x, ptr, err) \
-({ \
- __asm__ __volatile__ ( " iac 1\n" \
- " sr %1,%1\n" \
- " la 4,%2\n" \
- " sr %0,%0\n" \
- " sacf 512\n" \
- "0: ic %0,0(4)\n" \
- " sacf 0(1)\n" \
- "1:\n" \
- ".section .fixup,\"ax\"\n" \
- "2: sacf 0(1)\n" \
- " lhi %1,%h3\n" \
- " bras 4,3f\n" \
- " .long 1b\n" \
- "3: l 4,0(4)\n" \
- " br 4\n" \
- ".previous\n" \
- ".section __ex_table,\"a\"\n" \
- " .align 4\n" \
- " .long 0b,2b\n" \
- ".previous" \
- : "=d" (x) , "=&d" (err) \
- : "m" (*(__u8*) ptr), "K" (-EFAULT) \
- : "1", "4" ); \
+#define __get_user_asm_1(x, ptr, err) \
+({ \
+ __asm__ __volatile__ ( " sr %1,%1\n" \
+ " la 4,%2\n" \
+ " sr %0,%0\n" \
+ " sacf 512\n" \
+ "0: ic %0,0(4)\n" \
+ " sacf 0\n" \
+ "1:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "2: sacf 0\n" \
+ " lhi %1,%h3\n" \
+ " bras 4,3f\n" \
+ " .long 1b\n" \
+ "3: l 4,0(4)\n" \
+ " br 4\n" \
+ ".previous\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 4\n" \
+ " .long 0b,2b\n" \
+ ".previous" \
+ : "=d" (x) , "=&d" (err) \
+ : "m" (*(const __u8*)(ptr)),"K" (-EFAULT) \
+ : "4" ); \
})
#define __get_user(x, ptr) \
@@ -310,7 +304,7 @@ extern int __put_user_bad(void);
({ \
long __gu_err = -EFAULT; \
__typeof__(ptr) __gu_addr = (ptr); \
- __typeof__(x) __x; \
+ __typeof__(*(ptr)) __x; \
if (__access_ok((long)__gu_addr,sizeof(*(ptr)))) { \
__gu_err = 0; \
__get_user((__x), (__gu_addr)); \
@@ -327,26 +321,28 @@ extern int __get_user_bad(void);
* access register are set up, that 4 points to secondary (user) , 2 to primary (kernel)
*/
+asmlinkage void __copy_from_user_fixup(void /* special calling convention */);
+asmlinkage void __copy_to_user_fixup(void /* special calling convention */);
+
extern inline unsigned long
__copy_to_user_asm(void* to, const void* from, long n)
{
- __asm__ __volatile__ ( " iac 1\n"
- " lr 2,%2\n"
+ __asm__ __volatile__ ( " lr 2,%2\n"
" lr 4,%1\n"
" lr 3,%0\n"
" lr 5,3\n"
" sacf 512\n"
"0: mvcle 4,2,0\n"
" jo 0b\n"
- "1: sacf 0(1)\n"
+ " sacf 0\n"
" lr %0,3\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
- " .long 0b,1b\n"
+ " .long 0b,__copy_to_user_fixup\n"
".previous"
: "+&d" (n) : "d" (to), "d" (from)
- : "1", "2", "3", "4", "5" );
+ : "2", "3", "4", "5" );
return n;
}
@@ -370,22 +366,21 @@ __copy_to_user_asm(void* to, const void* from, long n)
extern inline unsigned long
__copy_from_user_asm(void* to, const void* from, long n)
{
- __asm__ __volatile__ ( " iac 1\n"
- " lr 2,%1\n"
+ __asm__ __volatile__ ( " lr 2,%1\n"
" lr 4,%2\n"
" lr 3,%0\n"
" lr 5,3\n"
" sacf 512\n"
"0: mvcle 2,4,0\n"
" jo 0b\n"
- "1: sacf 0(1)\n"
+ " sacf 0\n"
" lr %0,3\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
- " .long 0b,1b\n"
+ " .long 0b,__copy_from_user_fixup\n"
".previous"
: "+&d" (n) : "d" (to), "d" (from)
- : "1", "2", "3", "4", "5" );
+ : "2", "3", "4", "5" );
return n;
}
@@ -412,11 +407,10 @@ __copy_from_user_asm(void* to, const void* from, long n)
*/
static inline long
-strncpy_from_user(char *dst, const char *src, long count)
+__strncpy_from_user(char *dst, const char *src, long count)
{
int len;
- __asm__ __volatile__ ( " iac 1\n"
- " slr %0,%0\n"
+ __asm__ __volatile__ ( " slr %0,%0\n"
" lr 2,%1\n"
" lr 4,%2\n"
" slr 3,3\n"
@@ -428,7 +422,7 @@ strncpy_from_user(char *dst, const char *src, long count)
" ahi %0,1\n"
" clr %0,%3\n"
" jl 0b\n"
- "2: sacf 0(1)\n"
+ "2: sacf 0\n"
".section .fixup,\"ax\"\n"
"3: lhi %0,%h4\n"
" basr 3,0\n"
@@ -444,10 +438,20 @@ strncpy_from_user(char *dst, const char *src, long count)
: "=&a" (len)
: "a" (dst), "d" (src), "d" (count),
"K" (-EFAULT)
- : "1", "2", "3", "4", "memory" );
+ : "2", "3", "4", "memory" );
return len;
}
+static inline long
+strncpy_from_user(char *dst, const char *src, long count)
+{
+ long res = -EFAULT;
+ if (access_ok(VERIFY_READ, src, 1))
+ res = __strncpy_from_user(dst, src, count);
+ return res;
+}
+
+
/*
* Return the size of a string (including the ending 0)
*
@@ -456,8 +460,7 @@ strncpy_from_user(char *dst, const char *src, long count)
static inline unsigned long
strnlen_user(const char * src, unsigned long n)
{
- __asm__ __volatile__ (" iac 1\n"
- " alr %0,%1\n"
+ __asm__ __volatile__ (" alr %0,%1\n"
" slr 0,0\n"
" lr 4,%1\n"
" sacf 512\n"
@@ -465,10 +468,10 @@ strnlen_user(const char * src, unsigned long n)
" jo 0b\n"
" slr %0,%1\n"
" ahi %0,1\n"
- " sacf 0(1)\n"
+ " sacf 0\n"
"1:\n"
".section .fixup,\"ax\"\n"
- "2: sacf 0(1)\n"
+ "2: sacf 0\n"
" slr %0,%0\n"
" bras 4,3f\n"
" .long 1b\n"
@@ -480,7 +483,7 @@ strnlen_user(const char * src, unsigned long n)
" .long 0b,2b\n"
".previous"
: "+&a" (n) : "d" (src)
- : "cc", "0", "1", "4" );
+ : "cc", "0", "4" );
return n;
}
#define strlen_user(str) strnlen_user(str, ~0UL)
@@ -490,26 +493,45 @@ strnlen_user(const char * src, unsigned long n)
*/
static inline unsigned long
-clear_user(void *to, unsigned long n)
+__clear_user(void *to, unsigned long n)
{
- __asm__ __volatile__ ( " iac 1\n"
- " sacf 512\n"
+ __asm__ __volatile__ ( " sacf 512\n"
" lr 4,%1\n"
" lr 5,%0\n"
" sr 2,2\n"
" sr 3,3\n"
"0: mvcle 4,2,0\n"
" jo 0b\n"
- "1: sacf 0(1)\n"
- " lr %0,3\n"
+ " sacf 0\n"
+ "1: lr %0,3\n"
+ ".section .fixup,\"ax\"\n"
+ "2: lhi 5,-4096\n"
+ " n 5,0x90\n"
+ " sr 5,4\n"
+ " mvcle 4,2,0\n"
+ " sacf 0\n"
+ " basr 4,0\n"
+ " l 4,3f-.(4)\n"
+ " br 4\n"
+ "3: .long 1b\n"
+ ".previous\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
- " .long 0b,1b\n"
+ " .long 0b,2b\n"
".previous"
: "+&a" (n)
: "a" (to)
- : "cc", "1", "2", "3", "4", "5" );
+ : "cc", "2", "3", "4", "5" );
+ return n;
+}
+
+static inline unsigned long
+clear_user(void *to, unsigned long n)
+{
+ if (access_ok(VERIFY_WRITE, to, n))
+ n = __clear_user(to, n);
return n;
}
+
#endif /* _S390_UACCESS_H */
diff --git a/include/asm-s390/ucontext.h b/include/asm-s390/ucontext.h
index cf7c431f1..d4e39ae77 100644
--- a/include/asm-s390/ucontext.h
+++ b/include/asm-s390/ucontext.h
@@ -13,8 +13,10 @@ struct ucontext {
unsigned long uc_flags;
struct ucontext *uc_link;
stack_t uc_stack;
- struct sigcontext uc_mcontext;
sigset_t uc_sigmask; /* mask last for extensibility */
+ struct sigcontext *sc; /* Added for pthread support */
};
+
+
#endif /* !_ASM_S390_UCONTEXT_H */
diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
index e7da084b0..b223e0490 100644
--- a/include/asm-s390/unistd.h
+++ b/include/asm-s390/unistd.h
@@ -222,7 +222,7 @@ do { \
return (type) (res); \
} while (0)
-#define _svc_clobber "cc", "memory"
+#define _svc_clobber "2", "cc", "memory"
#define _syscall0(type,name) \
type name(void) { \
@@ -359,7 +359,6 @@ static inline _syscall1(int,_exit,int,exitcode)
static inline _syscall1(int,delete_module,const char *,name)
static inline _syscall2(long,stat,char *,filename,struct stat *,statbuf)
-extern int sys_wait4(int, int *, int, struct rusage *);
static inline pid_t waitpid(int pid, int * wait_stat, int flags)
{
return sys_wait4(pid, wait_stat, flags, NULL);