[PATCH] s390 (15/16): s390/s390x unification - part 6.

Martin Schwidefsky (schwidefsky@de.ibm.com)
Mon, 14 Apr 2003 19:54:14 +0200


Merge s390x and s390 to one architecture.

diffstat:
bitops.h | 732 +++++++++++++++++++++++++++++++++++++++++++---------------
byteorder.h | 55 ++++
ccwdev.h | 10
checksum.h | 73 +++++
compat.h | 122 +++++++++
div64.h | 13 -
ebcdic.h | 4
elf.h | 27 ++
fcntl.h | 6
gdb-stub.h | 22 -
idals.h | 14 -
io.h | 9
ipc.h | 1
ipcbuf.h | 2
lowcore.h | 144 ++++++++++-
mmu_context.h | 8
module.h | 5
msgbuf.h | 6
page.h | 69 +++++
pgalloc.h | 53 ++++
pgtable.h | 249 +++++++++++++++++--
21 files changed, 1370 insertions(+), 254 deletions(-)

diff -urN linux-2.5.67/include/asm-s390/bitops.h linux-2.5.67-s390/include/asm-s390/bitops.h
--- linux-2.5.67/include/asm-s390/bitops.h Mon Apr 14 19:11:36 2003
+++ linux-2.5.67-s390/include/asm-s390/bitops.h Mon Apr 14 19:11:58 2003
@@ -15,6 +15,7 @@
#include <linux/config.h>

/*
+ * 32 bit bitops format:
* bit 0 is the LSB of *addr; bit 31 is the MSB of *addr;
* bit 32 is the LSB of *(addr+4). That combined with the
* big endian byte order on S390 give the following bit
@@ -28,6 +29,25 @@
* in the architecture independent code bits operations
* of the form "flags |= (1 << bitnr)" are used INTERMIXED
* with operation of the form "set_bit(bitnr, flags)".
+ *
+ * 64 bit bitops format:
+ * bit 0 is the LSB of *addr; bit 63 is the MSB of *addr;
+ * bit 64 is the LSB of *(addr+8). That combined with the
+ * big endian byte order on S390 give the following bit
+ * order in memory:
+ * 3f 3e 3d 3c 3b 3a 39 38 37 36 35 34 33 32 31 30
+ * 2f 2e 2d 2c 2b 2a 29 28 27 26 25 24 23 22 21 20
+ * 1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10
+ * 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
+ * after that follows the next long with bit numbers
+ * 7f 7e 7d 7c 7b 7a 79 78 77 76 75 74 73 72 71 70
+ * 6f 6e 6d 6c 6b 6a 69 68 67 66 65 64 63 62 61 60
+ * 5f 5e 5d 5c 5b 5a 59 58 57 56 55 54 53 52 51 50
+ * 4f 4e 4d 4c 4b 4a 49 48 47 46 45 44 43 42 41 40
+ * The reason for this bit ordering is the fact that
+ * in the architecture independent code bits operations
+ * of the form "flags |= (1 << bitnr)" are used INTERMIXED
+ * with operation of the form "set_bit(bitnr, flags)".
*/

/* set ALIGN_CS to 1 if the SMP safe bit operations should
@@ -49,106 +69,126 @@
extern const char _zb_findmap[];
extern const char _sb_findmap[];

+#ifndef __s390x__
+
+#define __BITOPS_ALIGN 3
+#define __BITOPS_WORDSIZE 32
+#define __BITOPS_OR "or"
+#define __BITOPS_AND "nr"
+#define __BITOPS_XOR "xr"
+
+#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string) \
+ __asm__ __volatile__(" l %0,0(%4)\n" \
+ "0: lr %1,%0\n" \
+ __op_string " %1,%3\n" \
+ " cs %0,%1,0(%4)\n" \
+ " jl 0b" \
+ : "=&d" (__old), "=&d" (__new), \
+ "=m" (*(unsigned long *) __addr) \
+ : "d" (__val), "a" (__addr), \
+ "m" (*(unsigned long *) __addr) : "cc" );
+
+#else /* __s390x__ */
+
+#define __BITOPS_ALIGN 7
+#define __BITOPS_WORDSIZE 64
+#define __BITOPS_OR "ogr"
+#define __BITOPS_AND "ngr"
+#define __BITOPS_XOR "xgr"
+
+#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string) \
+ __asm__ __volatile__(" lg %0,0(%4)\n" \
+ "0: lgr %1,%0\n" \
+ __op_string " %1,%3\n" \
+ " csg %0,%1,0(%4)\n" \
+ " jl 0b" \
+ : "=&d" (__old), "=&d" (__new), \
+ "=m" (*(unsigned long *) __addr) \
+ : "d" (__val), "a" (__addr), \
+ "m" (*(unsigned long *) __addr) : "cc" );
+
+#endif /* __s390x__ */
+
#ifdef CONFIG_SMP
/*
* SMP safe set_bit routine based on compare and swap (CS)
*/
-static inline void set_bit_cs(int nr, volatile unsigned long *ptr)
+static inline void set_bit_cs(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr, old, new, mask;

addr = (unsigned long) ptr;
#if ALIGN_CS == 1
- nr += (addr & 3) << 3; /* add alignment to bit number */
- addr ^= addr & 3; /* align address to 4 */
+ nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */
+ addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */
#endif
- addr += (nr ^ (nr & 31)) >> 3; /* calculate address for CS */
- mask = 1UL << (nr & 31); /* make OR mask */
- asm volatile(
- " l %0,0(%4)\n"
- "0: lr %1,%0\n"
- " or %1,%3\n"
- " cs %0,%1,0(%4)\n"
- " jl 0b"
- : "=&d" (old), "=&d" (new), "+m" (*(unsigned int *) addr)
- : "d" (mask), "a" (addr)
- : "cc" );
+ /* calculate address for CS */
+ addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+ /* make OR mask */
+ mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1));
+ /* Do the atomic update. */
+ __BITOPS_LOOP(old, new, addr, mask, __BITOPS_OR);
}

/*
* SMP safe clear_bit routine based on compare and swap (CS)
*/
-static inline void clear_bit_cs(int nr, volatile unsigned long *ptr)
+static inline void clear_bit_cs(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr, old, new, mask;

addr = (unsigned long) ptr;
#if ALIGN_CS == 1
- nr += (addr & 3) << 3; /* add alignment to bit number */
- addr ^= addr & 3; /* align address to 4 */
+ nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */
+ addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */
#endif
- addr += (nr ^ (nr & 31)) >> 3; /* calculate address for CS */
- mask = ~(1UL << (nr & 31)); /* make AND mask */
- asm volatile(
- " l %0,0(%4)\n"
- "0: lr %1,%0\n"
- " nr %1,%3\n"
- " cs %0,%1,0(%4)\n"
- " jl 0b"
- : "=&d" (old), "=&d" (new), "+m" (*(unsigned int *) addr)
- : "d" (mask), "a" (addr)
- : "cc" );
+ /* calculate address for CS */
+ addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+ /* make AND mask */
+ mask = ~(1UL << (nr & (__BITOPS_WORDSIZE - 1)));
+ /* Do the atomic update. */
+ __BITOPS_LOOP(old, new, addr, mask, __BITOPS_AND);
}

/*
* SMP safe change_bit routine based on compare and swap (CS)
*/
-static inline void change_bit_cs(int nr, volatile unsigned long *ptr)
+static inline void change_bit_cs(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr, old, new, mask;

addr = (unsigned long) ptr;
#if ALIGN_CS == 1
- nr += (addr & 3) << 3; /* add alignment to bit number */
- addr ^= addr & 3; /* align address to 4 */
+ nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */
+ addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */
#endif
- addr += (nr ^ (nr & 31)) >> 3; /* calculate address for CS */
- mask = 1UL << (nr & 31); /* make XOR mask */
- asm volatile(
- " l %0,0(%4)\n"
- "0: lr %1,%0\n"
- " xr %1,%3\n"
- " cs %0,%1,0(%4)\n"
- " jl 0b"
- : "=&d" (old), "=&d" (new), "+m" (*(unsigned int *) addr)
- : "d" (mask), "a" (addr)
- : "cc" );
+ /* calculate address for CS */
+ addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+ /* make XOR mask */
+ mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1));
+ /* Do the atomic update. */
+ __BITOPS_LOOP(old, new, addr, mask, __BITOPS_XOR);
}

/*
* SMP safe test_and_set_bit routine based on compare and swap (CS)
*/
static inline int
-test_and_set_bit_cs(int nr, volatile unsigned long *ptr)
+test_and_set_bit_cs(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr, old, new, mask;

addr = (unsigned long) ptr;
#if ALIGN_CS == 1
- addr ^= addr & 3; /* align address to 4 */
- nr += (addr & 3) << 3; /* add alignment to bit number */
+ nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */
+ addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */
#endif
- addr += (nr ^ (nr & 31)) >> 3; /* calculate address for CS */
- mask = 1UL << (nr & 31); /* make OR/test mask */
- asm volatile(
- " l %0,0(%4)\n"
- "0: lr %1,%0\n"
- " or %1,%3\n"
- " cs %0,%1,0(%4)\n"
- " jl 0b"
- : "=&d" (old), "=&d" (new), "+m" (*(unsigned int *) addr)
- : "d" (mask), "a" (addr)
- : "cc" );
+ /* calculate address for CS */
+ addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+ /* make OR/test mask */
+ mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1));
+ /* Do the atomic update. */
+ __BITOPS_LOOP(old, new, addr, mask, __BITOPS_OR);
return (old & mask) != 0;
}

@@ -156,26 +196,21 @@
* SMP safe test_and_clear_bit routine based on compare and swap (CS)
*/
static inline int
-test_and_clear_bit_cs(int nr, volatile unsigned long *ptr)
+test_and_clear_bit_cs(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr, old, new, mask;

addr = (unsigned long) ptr;
#if ALIGN_CS == 1
- nr += (addr & 3) << 3; /* add alignment to bit number */
- addr ^= addr & 3; /* align address to 4 */
+ nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */
+ addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */
#endif
- addr += (nr ^ (nr & 31)) >> 3; /* calculate address for CS */
- mask = ~(1UL << (nr & 31)); /* make AND mask */
- asm volatile(
- " l %0,0(%4)\n"
- "0: lr %1,%0\n"
- " nr %1,%3\n"
- " cs %0,%1,0(%4)\n"
- " jl 0b"
- : "=&d" (old), "=&d" (new), "+m" (*(unsigned int *) addr)
- : "d" (mask), "a" (addr)
- : "cc" );
+ /* calculate address for CS */
+ addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+ /* make AND/test mask */
+ mask = ~(1UL << (nr & (__BITOPS_WORDSIZE - 1)));
+ /* Do the atomic update. */
+ __BITOPS_LOOP(old, new, addr, mask, __BITOPS_AND);
return (old ^ new) != 0;
}

@@ -183,26 +218,21 @@
* SMP safe test_and_change_bit routine based on compare and swap (CS)
*/
static inline int
-test_and_change_bit_cs(int nr, volatile unsigned long *ptr)
+test_and_change_bit_cs(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr, old, new, mask;

addr = (unsigned long) ptr;
#if ALIGN_CS == 1
- nr += (addr & 3) << 3; /* add alignment to bit number */
- addr ^= addr & 3; /* align address to 4 */
+ nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */
+ addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */
#endif
- addr += (nr ^ (nr & 31)) >> 3; /* calculate address for CS */
- mask = 1UL << (nr & 31); /* make XOR mask */
- asm volatile(
- " l %0,0(%4)\n"
- "0: lr %1,%0\n"
- " xr %1,%3\n"
- " cs %0,%1,0(%4)\n"
- " jl 0b"
- : "=&d" (old), "=&d" (new), "+m" (*(unsigned int *) addr)
- : "d" (mask), "a" (addr)
- : "cc" );
+ /* calculate address for CS */
+ addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+ /* make XOR/test mask */
+ mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1));
+ /* Do the atomic update. */
+ __BITOPS_LOOP(old, new, addr, mask, __BITOPS_XOR);
return (old & mask) != 0;
}
#endif /* CONFIG_SMP */
@@ -210,55 +240,55 @@
/*
* fast, non-SMP set_bit routine
*/
-static inline void __set_bit(int nr, volatile unsigned long *ptr)
+static inline void __set_bit(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr;

- addr = (unsigned long) ptr + ((nr ^ 24) >> 3);
+ addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
asm volatile("oc 0(1,%1),0(%2)"
- : "+m" (*(char *) addr)
- : "a" (addr), "a" (_oi_bitmap + (nr & 7))
- : "cc" );
+ : "=m" (*(char *) addr)
+ : "a" (addr), "a" (_oi_bitmap + (nr & 7)),
+ "m" (*(char *) addr) : "cc" );
}

static inline void
-__constant_set_bit(const int nr, volatile unsigned long *ptr)
+__constant_set_bit(const unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr;

- addr = ((unsigned long) ptr) + ((nr >> 3) ^ 3);
+ addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
switch (nr&7) {
case 0:
- asm volatile ("oi 0(%1),0x01"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("oi 0(%1),0x01" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
case 1:
- asm volatile ("oi 0(%1),0x02"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("oi 0(%1),0x02" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
case 2:
- asm volatile ("oi 0(%1),0x04"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("oi 0(%1),0x04" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
case 3:
- asm volatile ("oi 0(%1),0x08"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("oi 0(%1),0x08" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
case 4:
- asm volatile ("oi 0(%1),0x10"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("oi 0(%1),0x10" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
case 5:
- asm volatile ("oi 0(%1),0x20"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("oi 0(%1),0x20" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
case 6:
- asm volatile ("oi 0(%1),0x40"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("oi 0(%1),0x40" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
case 7:
- asm volatile ("oi 0(%1),0x80"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("oi 0(%1),0x80" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
}
}
@@ -272,55 +302,55 @@
* fast, non-SMP clear_bit routine
*/
static inline void
-__clear_bit(int nr, volatile unsigned long *ptr)
+__clear_bit(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr;

- addr = (unsigned long) ptr + ((nr ^ 24) >> 3);
+ addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
asm volatile("nc 0(1,%1),0(%2)"
- : "+m" (*(char *) addr)
- : "a" (addr), "a" (_ni_bitmap + (nr & 7))
- : "cc" );
+ : "=m" (*(char *) addr)
+ : "a" (addr), "a" (_ni_bitmap + (nr & 7)),
+ "m" (*(char *) addr) : "cc" );
}

static inline void
-__constant_clear_bit(const int nr, volatile unsigned long *ptr)
+__constant_clear_bit(const unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr;

- addr = ((unsigned long) ptr) + ((nr >> 3) ^ 3);
+ addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
switch (nr&7) {
case 0:
- asm volatile ("ni 0(%1),0xFE"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("ni 0(%1),0xFE" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
case 1:
- asm volatile ("ni 0(%1),0xFD"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("ni 0(%1),0xFD": "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
case 2:
- asm volatile ("ni 0(%1),0xFB"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("ni 0(%1),0xFB" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
case 3:
- asm volatile ("ni 0(%1),0xF7"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("ni 0(%1),0xF7" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
case 4:
- asm volatile ("ni 0(%1),0xEF"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("ni 0(%1),0xEF" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
case 5:
- asm volatile ("ni 0(%1),0xDF"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("ni 0(%1),0xDF" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
case 6:
- asm volatile ("ni 0(%1),0xBF"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("ni 0(%1),0xBF" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
case 7:
- asm volatile ("ni 0(%1),0x7F"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("ni 0(%1),0x7F" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
}
}
@@ -333,55 +363,55 @@
/*
* fast, non-SMP change_bit routine
*/
-static inline void __change_bit(int nr, volatile unsigned long *ptr)
+static inline void __change_bit(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr;

- addr = (unsigned long) ptr + ((nr ^ 24) >> 3);
+ addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
asm volatile("xc 0(1,%1),0(%2)"
- : "+m" (*(char *) addr)
- : "a" (addr), "a" (_oi_bitmap + (nr & 7))
- : "cc" );
+ : "=m" (*(char *) addr)
+ : "a" (addr), "a" (_oi_bitmap + (nr & 7)),
+ "m" (*(char *) addr) : "cc" );
}

static inline void
-__constant_change_bit(const int nr, volatile unsigned long *ptr)
+__constant_change_bit(const unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr;

- addr = ((unsigned long) ptr) + ((nr >> 3) ^ 3);
+ addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
switch (nr&7) {
case 0:
- asm volatile ("xi 0(%1),0x01"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("xi 0(%1),0x01" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
case 1:
- asm volatile ("xi 0(%1),0x02"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("xi 0(%1),0x02" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
case 2:
- asm volatile ("xi 0(%1),0x04"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("xi 0(%1),0x04" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
case 3:
- asm volatile ("xi 0(%1),0x08"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("xi 0(%1),0x08" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
case 4:
- asm volatile ("xi 0(%1),0x10"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("xi 0(%1),0x10" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
case 5:
- asm volatile ("xi 0(%1),0x20"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("xi 0(%1),0x20" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
case 6:
- asm volatile ("xi 0(%1),0x40"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("xi 0(%1),0x40" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
case 7:
- asm volatile ("xi 0(%1),0x80"
- : "+m" (*(char *) addr) : "a" (addr) : "cc" );
+ asm volatile ("xi 0(%1),0x80" : "=m" (*(char *) addr)
+ : "a" (addr), "m" (*(char *) addr) : "cc" );
break;
}
}
@@ -395,17 +425,17 @@
* fast, non-SMP test_and_set_bit routine
*/
static inline int
-test_and_set_bit_simple(int nr, volatile unsigned long *ptr)
+test_and_set_bit_simple(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr;
unsigned char ch;

- addr = (unsigned long) ptr + ((nr ^ 24) >> 3);
+ addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
ch = *(unsigned char *) addr;
asm volatile("oc 0(1,%1),0(%2)"
- : "+m" (*(char *) addr)
- : "a" (addr), "a" (_oi_bitmap + (nr & 7))
- : "cc" );
+ : "=m" (*(char *) addr)
+ : "a" (addr), "a" (_oi_bitmap + (nr & 7)),
+ "m" (*(char *) addr) : "cc" );
return (ch >> (nr & 7)) & 1;
}
#define __test_and_set_bit(X,Y) test_and_set_bit_simple(X,Y)
@@ -414,17 +444,17 @@
* fast, non-SMP test_and_clear_bit routine
*/
static inline int
-test_and_clear_bit_simple(int nr, volatile unsigned long *ptr)
+test_and_clear_bit_simple(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr;
unsigned char ch;

- addr = (unsigned long) ptr + ((nr ^ 24) >> 3);
+ addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
ch = *(unsigned char *) addr;
asm volatile("nc 0(1,%1),0(%2)"
- : "+m" (*(char *) addr)
- : "a" (addr), "a" (_ni_bitmap + (nr & 7))
- : "cc" );
+ : "=m" (*(char *) addr)
+ : "a" (addr), "a" (_ni_bitmap + (nr & 7)),
+ "m" (*(char *) addr) : "cc" );
return (ch >> (nr & 7)) & 1;
}
#define __test_and_clear_bit(X,Y) test_and_clear_bit_simple(X,Y)
@@ -433,17 +463,17 @@
* fast, non-SMP test_and_change_bit routine
*/
static inline int
-test_and_change_bit_simple(int nr, volatile unsigned long *ptr)
+test_and_change_bit_simple(unsigned long nr, volatile unsigned long *ptr)
{
unsigned long addr;
unsigned char ch;

- addr = (unsigned long) ptr + ((nr ^ 24) >> 3);
+ addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
ch = *(unsigned char *) addr;
asm volatile("xc 0(1,%1),0(%2)"
- : "+m" (*(char *) addr)
- : "a" (addr), "a" (_oi_bitmap + (nr & 7))
- : "cc" );
+ : "=m" (*(char *) addr)
+ : "a" (addr), "a" (_oi_bitmap + (nr & 7)),
+ "m" (*(char *) addr) : "cc" );
return (ch >> (nr & 7)) & 1;
}
#define __test_and_change_bit(X,Y) test_and_change_bit_simple(X,Y)
@@ -469,19 +499,20 @@
* This routine doesn't need to be atomic.
*/

-static inline int __test_bit(int nr, const volatile unsigned long *ptr)
+static inline int __test_bit(unsigned long nr, const volatile unsigned long *ptr)
{
unsigned long addr;
unsigned char ch;

- addr = (unsigned long) ptr + ((nr ^ 24) >> 3);
+ addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
ch = *(unsigned char *) addr;
return (ch >> (nr & 7)) & 1;
}

static inline int
-__constant_test_bit(int nr, const volatile unsigned long * addr) {
- return (((volatile char *) addr)[(nr>>3)^3] & (1<<(nr&7))) != 0;
+__constant_test_bit(unsigned long nr, const volatile unsigned long *addr) {
+ return (((volatile char *) addr)
+ [(nr^(__BITOPS_WORDSIZE-8))>>3] & (1<<(nr&7)));
}

#define test_bit(nr,addr) \
@@ -489,6 +520,8 @@
__constant_test_bit((nr),(addr)) : \
__test_bit((nr),(addr)) )

+#ifndef __s390x__
+
/*
* Find-bit routines..
*/
@@ -701,6 +734,245 @@
return result;
}

+#else /* __s390x__ */
+
+/*
+ * Find-bit routines..
+ */
+static inline unsigned long
+find_first_zero_bit(unsigned long * addr, unsigned long size)
+{
+ unsigned long res, cmp, count;
+
+ if (!size)
+ return 0;
+ __asm__(" lghi %1,-1\n"
+ " lgr %2,%3\n"
+ " slgr %0,%0\n"
+ " aghi %2,63\n"
+ " srlg %2,%2,6\n"
+ "0: cg %1,0(%0,%4)\n"
+ " jne 1f\n"
+ " aghi %0,8\n"
+ " brct %2,0b\n"
+ " lgr %0,%3\n"
+ " j 5f\n"
+ "1: lg %2,0(%0,%4)\n"
+ " sllg %0,%0,3\n"
+ " clr %2,%1\n"
+ " jne 2f\n"
+ " aghi %0,32\n"
+ " srlg %2,%2,32\n"
+ "2: lghi %1,0xff\n"
+ " tmll %2,0xffff\n"
+ " jno 3f\n"
+ " aghi %0,16\n"
+ " srl %2,16\n"
+ "3: tmll %2,0x00ff\n"
+ " jno 4f\n"
+ " aghi %0,8\n"
+ " srl %2,8\n"
+ "4: ngr %2,%1\n"
+ " ic %2,0(%2,%5)\n"
+ " algr %0,%2\n"
+ "5:"
+ : "=&a" (res), "=&d" (cmp), "=&a" (count)
+ : "a" (size), "a" (addr), "a" (&_zb_findmap) : "cc" );
+ return (res < size) ? res : size;
+}
+
+static inline unsigned long
+find_first_bit(unsigned long * addr, unsigned long size)
+{
+ unsigned long res, cmp, count;
+
+ if (!size)
+ return 0;
+ __asm__(" slgr %1,%1\n"
+ " lgr %2,%3\n"
+ " slgr %0,%0\n"
+ " aghi %2,63\n"
+ " srlg %2,%2,6\n"
+ "0: cg %1,0(%0,%4)\n"
+ " jne 1f\n"
+ " aghi %0,8\n"
+ " brct %2,0b\n"
+ " lgr %0,%3\n"
+ " j 5f\n"
+ "1: lg %2,0(%0,%4)\n"
+ " sllg %0,%0,3\n"
+ " clr %2,%1\n"
+ " jne 2f\n"
+ " aghi %0,32\n"
+ " srlg %2,%2,32\n"
+ "2: lghi %1,0xff\n"
+ " tmll %2,0xffff\n"
+ " jnz 3f\n"
+ " aghi %0,16\n"
+ " srl %2,16\n"
+ "3: tmll %2,0x00ff\n"
+ " jnz 4f\n"
+ " aghi %0,8\n"
+ " srl %2,8\n"
+ "4: ngr %2,%1\n"
+ " ic %2,0(%2,%5)\n"
+ " algr %0,%2\n"
+ "5:"
+ : "=&a" (res), "=&d" (cmp), "=&a" (count)
+ : "a" (size), "a" (addr), "a" (&_sb_findmap) : "cc" );
+ return (res < size) ? res : size;
+}
+
+static inline unsigned long
+find_next_zero_bit (unsigned long * addr, unsigned long size, unsigned long offset)
+{
+ unsigned long * p = ((unsigned long *) addr) + (offset >> 6);
+ unsigned long bitvec, reg;
+ unsigned long set, bit = offset & 63, res;
+
+ if (bit) {
+ /*
+ * Look for zero in first word
+ */
+ bitvec = (*p) >> bit;
+ __asm__(" lhi %2,-1\n"
+ " slgr %0,%0\n"
+ " clr %1,%2\n"
+ " jne 0f\n"
+ " aghi %0,32\n"
+ " srlg %1,%1,32\n"
+ "0: lghi %2,0xff\n"
+ " tmll %1,0xffff\n"
+ " jno 1f\n"
+ " aghi %0,16\n"
+ " srlg %1,%1,16\n"
+ "1: tmll %1,0x00ff\n"
+ " jno 2f\n"
+ " aghi %0,8\n"
+ " srlg %1,%1,8\n"
+ "2: ngr %1,%2\n"
+ " ic %1,0(%1,%3)\n"
+ " algr %0,%1"
+ : "=&d" (set), "+a" (bitvec), "=&d" (reg)
+ : "a" (&_zb_findmap) : "cc" );
+ if (set < (64 - bit))
+ return set + offset;
+ offset += 64 - bit;
+ p++;
+ }
+ /*
+ * No zero yet, search remaining full words for a zero
+ */
+ res = find_first_zero_bit (p, size - 64 * (p - (unsigned long *) addr));
+ return (offset + res);
+}
+
+static inline unsigned long
+find_next_bit (unsigned long * addr, unsigned long size, unsigned long offset)
+{
+ unsigned long * p = ((unsigned long *) addr) + (offset >> 6);
+ unsigned long bitvec, reg;
+ unsigned long set, bit = offset & 63, res;
+
+ if (bit) {
+ /*
+ * Look for zero in first word
+ */
+ bitvec = (*p) >> bit;
+ __asm__(" slgr %0,%0\n"
+ " ltr %1,%1\n"
+ " jnz 0f\n"
+ " aghi %0,32\n"
+ " srlg %1,%1,32\n"
+ "0: lghi %2,0xff\n"
+ " tmll %1,0xffff\n"
+ " jnz 1f\n"
+ " aghi %0,16\n"
+ " srlg %1,%1,16\n"
+ "1: tmll %1,0x00ff\n"
+ " jnz 2f\n"
+ " aghi %0,8\n"
+ " srlg %1,%1,8\n"
+ "2: ngr %1,%2\n"
+ " ic %1,0(%1,%3)\n"
+ " algr %0,%1"
+ : "=&d" (set), "+a" (bitvec), "=&d" (reg)
+ : "a" (&_sb_findmap) : "cc" );
+ if (set < (64 - bit))
+ return set + offset;
+ offset += 64 - bit;
+ p++;
+ }
+ /*
+ * No set bit yet, search remaining full words for a bit
+ */
+ res = find_first_bit (p, size - 64 * (p - (unsigned long *) addr));
+ return (offset + res);
+}
+
+/*
+ * ffz = Find First Zero in word. Undefined if no zero exists,
+ * so code should check against ~0UL first..
+ */
+static inline unsigned long ffz(unsigned long word)
+{
+ unsigned long reg, result;
+
+ __asm__(" lhi %2,-1\n"
+ " slgr %0,%0\n"
+ " clr %1,%2\n"
+ " jne 0f\n"
+ " aghi %0,32\n"
+ " srlg %1,%1,32\n"
+ "0: lghi %2,0xff\n"
+ " tmll %1,0xffff\n"
+ " jno 1f\n"
+ " aghi %0,16\n"
+ " srlg %1,%1,16\n"
+ "1: tmll %1,0x00ff\n"
+ " jno 2f\n"
+ " aghi %0,8\n"
+ " srlg %1,%1,8\n"
+ "2: ngr %1,%2\n"
+ " ic %1,0(%1,%3)\n"
+ " algr %0,%1"
+ : "=&d" (result), "+a" (word), "=&d" (reg)
+ : "a" (&_zb_findmap) : "cc" );
+ return result;
+}
+
+/*
+ * __ffs = find first bit in word. Undefined if no bit exists,
+ * so code should check against 0UL first..
+ */
+static inline unsigned long __ffs (unsigned long word)
+{
+ unsigned long reg, result;
+
+ __asm__(" slgr %0,%0\n"
+ " ltr %1,%1\n"
+ " jnz 0f\n"
+ " aghi %0,32\n"
+ " srlg %1,%1,32\n"
+ "0: lghi %2,0xff\n"
+ " tmll %1,0xffff\n"
+ " jnz 1f\n"
+ " aghi %0,16\n"
+ " srlg %1,%1,16\n"
+ "1: tmll %1,0x00ff\n"
+ " jnz 2f\n"
+ " aghi %0,8\n"
+ " srlg %1,%1,8\n"
+ "2: ngr %1,%2\n"
+ " ic %1,0(%1,%3)\n"
+ " algr %0,%1"
+ : "=&d" (result), "+a" (word), "=&d" (reg)
+ : "a" (&_sb_findmap) : "cc" );
+ return result;
+}
+
+#endif /* __s390x__ */
+
/*
* Every architecture must define this function. It's the fastest
* way of searching a 140-bit bitmap where the first 100 bits are
@@ -717,7 +989,6 @@
* the libc and compiler builtin ffs routines, therefore
* differs in spirit from the above ffz (man ffs).
*/
-
extern inline int ffs (int x)
{
int r = 1;
@@ -785,7 +1056,14 @@
* hweightN: returns the hamming weight (i.e. the number
* of bits set) of a N-bit word
*/
-
+#define hweight64(x) \
+({ \
+ unsigned long __x = (x); \
+ unsigned int __w; \
+ __w = generic_hweight32((unsigned int) __x); \
+ __w += generic_hweight32((unsigned int) (__x>>32)); \
+ __w; \
+})
#define hweight32(x) generic_hweight32(x)
#define hweight16(x) generic_hweight16(x)
#define hweight8(x) generic_hweight8(x)
@@ -804,15 +1082,17 @@
*/

#define ext2_set_bit(nr, addr) \
- test_and_set_bit((nr)^24, (unsigned long *)addr)
+ test_and_set_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
#define ext2_set_bit_atomic(lock, nr, addr) \
- test_and_set_bit((nr)^24, (unsigned long *)addr)
+ test_and_set_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
#define ext2_clear_bit(nr, addr) \
- test_and_clear_bit((nr)^24, (unsigned long *)addr)
+ test_and_clear_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
#define ext2_clear_bit_atomic(lock, nr, addr) \
- test_and_clear_bit((nr)^24, (unsigned long *)addr)
+ test_and_clear_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
#define ext2_test_bit(nr, addr) \
- test_bit((nr)^24, (unsigned long *)addr)
+ test_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
+
+#ifndef __s390x__

static inline int
ext2_find_first_zero_bit(void *vaddr, unsigned size)
@@ -897,6 +1177,100 @@
return (p - addr) * 32 + res;
}

+#else /* __s390x__ */
+
+static inline unsigned long
+ext2_find_first_zero_bit(void *vaddr, unsigned long size)
+{
+ unsigned long res, cmp, count;
+
+ if (!size)
+ return 0;
+ __asm__(" lghi %1,-1\n"
+ " lgr %2,%3\n"
+ " aghi %2,63\n"
+ " srlg %2,%2,6\n"
+ " slgr %0,%0\n"
+ "0: clg %1,0(%0,%4)\n"
+ " jne 1f\n"
+ " aghi %0,8\n"
+ " brct %2,0b\n"
+ " lgr %0,%3\n"
+ " j 5f\n"
+ "1: cl %1,0(%0,%4)\n"
+ " jne 2f\n"
+ " aghi %0,4\n"
+ "2: l %2,0(%0,%4)\n"
+ " sllg %0,%0,3\n"
+ " aghi %0,24\n"
+ " lghi %1,0xff\n"
+ " tmlh %2,0xffff\n"
+ " jo 3f\n"
+ " aghi %0,-16\n"
+ " srl %2,16\n"
+ "3: tmll %2,0xff00\n"
+ " jo 4f\n"
+ " aghi %0,-8\n"
+ " srl %2,8\n"
+ "4: ngr %2,%1\n"
+ " ic %2,0(%2,%5)\n"
+ " algr %0,%2\n"
+ "5:"
+ : "=&a" (res), "=&d" (cmp), "=&a" (count)
+ : "a" (size), "a" (vaddr), "a" (&_zb_findmap) : "cc" );
+ return (res < size) ? res : size;
+}
+
+static inline unsigned long
+ext2_find_next_zero_bit(void *vaddr, unsigned long size, unsigned long offset)
+{
+ unsigned long *addr = vaddr;
+ unsigned long *p = addr + (offset >> 6);
+ unsigned long word, reg;
+ unsigned long bit = offset & 63UL, res;
+
+ if (offset >= size)
+ return size;
+
+ if (bit) {
+ __asm__(" lrvg %0,%1" /* load reversed, neat instruction */
+ : "=a" (word) : "m" (*p) );
+ word >>= bit;
+ res = bit;
+ /* Look for zero in first 8 byte word */
+ __asm__(" lghi %2,0xff\n"
+ " tmll %1,0xffff\n"
+ " jno 2f\n"
+ " ahi %0,16\n"
+ " srlg %1,%1,16\n"
+ "0: tmll %1,0xffff\n"
+ " jno 2f\n"
+ " ahi %0,16\n"
+ " srlg %1,%1,16\n"
+ "1: tmll %1,0xffff\n"
+ " jno 2f\n"
+ " ahi %0,16\n"
+ " srl %1,16\n"
+ "2: tmll %1,0x00ff\n"
+ " jno 3f\n"
+ " ahi %0,8\n"
+ " srl %1,8\n"
+ "3: ngr %1,%2\n"
+ " ic %1,0(%1,%3)\n"
+ " alr %0,%1"
+ : "+&d" (res), "+a" (word), "=&d" (reg)
+ : "a" (&_zb_findmap) : "cc" );
+ if (res < 64)
+ return (p - addr)*64 + res;
+ p++;
+ }
+ /* No zero yet, search remaining full bytes for a zero */
+ res = ext2_find_first_zero_bit (p, size - 64 * (p - addr));
+ return (p - addr) * 64 + res;
+}
+
+#endif /* __s390x__ */
+
/* Bitmap functions for the minix filesystem. */
/* FIXME !!! */
#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
diff -urN linux-2.5.67/include/asm-s390/byteorder.h linux-2.5.67-s390/include/asm-s390/byteorder.h
--- linux-2.5.67/include/asm-s390/byteorder.h Mon Apr 7 19:33:01 2003
+++ linux-2.5.67-s390/include/asm-s390/byteorder.h Mon Apr 14 19:11:58 2003
@@ -13,22 +13,63 @@

#ifdef __GNUC__

+#ifdef __s390x__
+static __inline__ __const__ __u64 ___arch__swab64p(__u64 *x)
+{
+ __u64 result;
+
+ __asm__ __volatile__ (
+ " lrvg %0,%1"
+ : "=d" (result) : "m" (*x) );
+ return result;
+}
+
+static __inline__ __const__ __u64 ___arch__swab64(__u64 x)
+{
+ __u64 result;
+
+ __asm__ __volatile__ (
+ " lrvgr %0,%1"
+ : "=d" (result) : "d" (x) );
+ return result;
+}
+
+static __inline__ void ___arch__swab64s(__u64 *x)
+{
+ *x = ___arch__swab64p(x);
+}
+#endif /* __s390x__ */
+
static __inline__ __const__ __u32 ___arch__swab32p(__u32 *x)
{
__u32 result;

__asm__ __volatile__ (
+#ifndef __s390x__
" icm %0,8,3(%1)\n"
" icm %0,4,2(%1)\n"
" icm %0,2,1(%1)\n"
" ic %0,0(%1)"
: "=&d" (result) : "a" (x) : "cc" );
+#else /* __s390x__ */
+ " lrv %0,%1"
+ : "=d" (result) : "m" (*x) );
+#endif /* __s390x__ */
return result;
}

static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
{
+#ifndef __s390x__
return ___arch__swab32p(&x);
+#else /* __s390x__ */
+ __u32 result;
+
+ __asm__ __volatile__ (
+ " lrvr %0,%1"
+ : "=d" (result) : "d" (x) );
+ return result;
+#endif /* __s390x__ */
}

static __inline__ void ___arch__swab32s(__u32 *x)
@@ -41,9 +82,14 @@
__u16 result;

__asm__ __volatile__ (
+#ifndef __s390x__
" icm %0,2,1(%1)\n"
" ic %0,0(%1)\n"
: "=&d" (result) : "a" (x) : "cc" );
+#else /* __s390x__ */
+ " lrvh %0,%1"
+ : "=d" (result) : "m" (*x) );
+#endif /* __s390x__ */
return result;
}

@@ -57,6 +103,11 @@
*x = ___arch__swab16p(x);
}

+#ifdef __s390x__
+#define __arch__swab64(x) ___arch__swab64(x)
+#define __arch__swab64p(x) ___arch__swab64p(x)
+#define __arch__swab64s(x) ___arch__swab64s(x)
+#endif /* __s390x__ */
#define __arch__swab32(x) ___arch__swab32(x)
#define __arch__swab16(x) ___arch__swab16(x)
#define __arch__swab32p(x) ___arch__swab32p(x)
@@ -64,10 +115,14 @@
#define __arch__swab32s(x) ___arch__swab32s(x)
#define __arch__swab16s(x) ___arch__swab16s(x)

+#ifndef __s390x__
#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
# define __BYTEORDER_HAS_U64__
# define __SWAB_64_THRU_32__
#endif
+#else /* __s390x__ */
+#define __BYTEORDER_HAS_U64__
+#endif /* __s390x__ */

#endif /* __GNUC__ */

diff -urN linux-2.5.67/include/asm-s390/ccwdev.h linux-2.5.67-s390/include/asm-s390/ccwdev.h
--- linux-2.5.67/include/asm-s390/ccwdev.h Mon Apr 7 19:32:27 2003
+++ linux-2.5.67-s390/include/asm-s390/ccwdev.h Mon Apr 14 19:11:58 2003
@@ -157,6 +157,16 @@
*/
extern int ccw_device_start(struct ccw_device *, struct ccw1 *,
unsigned long, __u8, unsigned long);
+/*
+ * ccw_device_start_timeout()
+ *
+ * This function notifies the device driver if the channel program has not
+ * completed during the specified time. If a timeout occurs, the channel
+ * program is terminated via xsch(), hsch() or csch().
+ */
+extern int ccw_device_start_timeout(struct ccw_device *, struct ccw1 *,
+ unsigned long, __u8, unsigned long, int);
+
extern int ccw_device_resume(struct ccw_device *);
extern int ccw_device_halt(struct ccw_device *, unsigned long);
extern int ccw_device_clear(struct ccw_device *, unsigned long);
diff -urN linux-2.5.67/include/asm-s390/checksum.h linux-2.5.67-s390/include/asm-s390/checksum.h
--- linux-2.5.67/include/asm-s390/checksum.h Mon Apr 7 19:30:34 2003
+++ linux-2.5.67-s390/include/asm-s390/checksum.h Mon Apr 14 19:11:58 2003
@@ -30,17 +30,29 @@
static inline unsigned int
csum_partial(const unsigned char * buff, int len, unsigned int sum)
{
- register_pair rp;
/*
* Experiments with ethernet and slip connections show that buf
* is aligned on either a 2-byte or 4-byte boundary.
*/
+#ifndef __s390x__
+ register_pair rp;
+
rp.subreg.even = (unsigned long) buff;
rp.subreg.odd = (unsigned long) len;
__asm__ __volatile__ (
"0: cksm %0,%1\n" /* do checksum on longs */
" jo 0b\n"
: "+&d" (sum), "+&a" (rp) : : "cc" );
+#else /* __s390x__ */
+ __asm__ __volatile__ (
+ " lgr 2,%1\n" /* address in gpr 2 */
+ " lgfr 3,%2\n" /* length in gpr 3 */
+ "0: cksm %0,2\n" /* do checksum on longs */
+ " jo 0b\n"
+ : "+&d" (sum)
+ : "d" (buff), "d" (len)
+ : "cc", "2", "3" );
+#endif /* __s390x__ */
return sum;
}

@@ -50,6 +62,7 @@
static inline unsigned int
csum_partial_inline(const unsigned char * buff, int len, unsigned int sum)
{
+#ifndef __s390x__
register_pair rp;

rp.subreg.even = (unsigned long) buff;
@@ -58,6 +71,16 @@
"0: cksm %0,%1\n" /* do checksum on longs */
" jo 0b\n"
: "+&d" (sum), "+&a" (rp) : : "cc" );
+#else /* __s390x__ */
+ __asm__ __volatile__ (
+ " lgr 2,%1\n" /* address in gpr 2 */
+ " lgfr 3,%2\n" /* length in gpr 3 */
+ "0: cksm %0,2\n" /* do checksum on longs */
+ " jo 0b\n"
+ : "+&d" (sum)
+ : "d" (buff), "d" (len)
+ : "cc", "2", "3" );
+#endif /* __s390x__ */
return sum;
}

@@ -100,6 +123,7 @@
static inline unsigned short
csum_fold(unsigned int sum)
{
+#ifndef __s390x__
register_pair rp;

__asm__ __volatile__ (
@@ -110,6 +134,16 @@
" alr %0,%1\n" /* %0 = H+L+C L+H */
" srl %0,16\n" /* %0 = H+L+C */
: "+&d" (sum), "=d" (rp) : : "cc" );
+#else /* __s390x__ */
+ __asm__ __volatile__ (
+ " sr 3,3\n" /* %0 = H*65536 + L */
+ " lr 2,%0\n" /* %0 = H L, R2/R3 = H L / 0 0 */
+ " srdl 2,16\n" /* %0 = H L, R2/R3 = 0 H / L 0 */
+ " alr 2,3\n" /* %0 = H L, R2/R3 = L H / L 0 */
+ " alr %0,2\n" /* %0 = H+L+C L+H */
+ " srl %0,16\n" /* %0 = H+L+C */
+ : "+&d" (sum) : : "cc", "2", "3");
+#endif /* __s390x__ */
return ((unsigned short) ~sum);
}

@@ -121,8 +155,9 @@
static inline unsigned short
ip_fast_csum(unsigned char *iph, unsigned int ihl)
{
- register_pair rp;
unsigned long sum;
+#ifndef __s390x__
+ register_pair rp;

rp.subreg.even = (unsigned long) iph;
rp.subreg.odd = (unsigned long) ihl*4;
@@ -131,6 +166,17 @@
"0: cksm %0,%1\n" /* do checksum on longs */
" jo 0b\n"
: "=&d" (sum), "+&a" (rp) : : "cc" );
+#else /* __s390x__ */
+ __asm__ __volatile__ (
+ " slgr %0,%0\n" /* set sum to zero */
+ " lgr 2,%1\n" /* address in gpr 2 */
+ " lgfr 3,%2\n" /* length in gpr 3 */
+ "0: cksm %0,2\n" /* do checksum on ints */
+ " jo 0b\n"
+ : "=&d" (sum)
+ : "d" (iph), "d" (ihl*4)
+ : "cc", "2", "3" );
+#endif /* __s390x__ */
return csum_fold(sum);
}

@@ -143,6 +189,7 @@
unsigned short len, unsigned short proto,
unsigned int sum)
{
+#ifndef __s390x__
__asm__ __volatile__ (
" alr %0,%1\n" /* sum += saddr */
" brc 12,0f\n"
@@ -163,6 +210,28 @@
: "+&d" (sum)
: "d" (((unsigned int) len<<16) + (unsigned int) proto)
: "cc" );
+#else /* __s390x__ */
+ __asm__ __volatile__ (
+ " lgfr %0,%0\n"
+ " algr %0,%1\n" /* sum += saddr */
+ " brc 12,0f\n"
+ " aghi %0,1\n" /* add carry */
+ "0: algr %0,%2\n" /* sum += daddr */
+ " brc 12,1f\n"
+ " aghi %0,1\n" /* add carry */
+ "1: algfr %0,%3\n" /* sum += (len<<16) + proto */
+ " brc 12,2f\n"
+ " aghi %0,1\n" /* add carry */
+ "2: srlg 0,%0,32\n"
+ " alr %0,0\n" /* fold to 32 bits */
+ " brc 12,3f\n"
+ " ahi %0,1\n" /* add carry */
+ "3: llgfr %0,%0"
+ : "+&d" (sum)
+ : "d" (saddr), "d" (daddr),
+ "d" (((unsigned int) len<<16) + (unsigned int) proto)
+ : "cc", "0" );
+#endif /* __s390x__ */
return sum;
}

diff -urN linux-2.5.67/include/asm-s390/compat.h linux-2.5.67-s390/include/asm-s390/compat.h
--- linux-2.5.67/include/asm-s390/compat.h Thu Jan 1 01:00:00 1970
+++ linux-2.5.67-s390/include/asm-s390/compat.h Mon Apr 14 19:11:58 2003
@@ -0,0 +1,122 @@
+#ifndef _ASM_S390X_COMPAT_H
+#define _ASM_S390X_COMPAT_H
+/*
+ * Architecture specific compatibility types
+ */
+#include <linux/types.h>
+
+#define COMPAT_USER_HZ 100
+
+typedef u32 compat_size_t;
+typedef s32 compat_ssize_t;
+typedef s32 compat_time_t;
+typedef s32 compat_clock_t;
+typedef s32 compat_pid_t;
+typedef u16 compat_uid_t;
+typedef u16 compat_gid_t;
+typedef u16 compat_mode_t;
+typedef u32 compat_ino_t;
+typedef u16 compat_dev_t;
+typedef s32 compat_off_t;
+typedef s64 compat_loff_t;
+typedef u16 compat_nlink_t;
+typedef u16 compat_ipc_pid_t;
+typedef s32 compat_daddr_t;
+typedef u32 compat_caddr_t;
+typedef __kernel_fsid_t compat_fsid_t;
+
+typedef s32 compat_int_t;
+typedef s32 compat_long_t;
+typedef u32 compat_uint_t;
+typedef u32 compat_ulong_t;
+
+struct compat_timespec {
+ compat_time_t tv_sec;
+ s32 tv_nsec;
+};
+
+struct compat_timeval {
+ compat_time_t tv_sec;
+ s32 tv_usec;
+};
+
+struct compat_stat {
+ compat_dev_t st_dev;
+ u16 __pad1;
+ compat_ino_t st_ino;
+ compat_mode_t st_mode;
+ compat_nlink_t st_nlink;
+ compat_uid_t st_uid;
+ compat_gid_t st_gid;
+ compat_dev_t st_rdev;
+ u16 __pad2;
+ u32 st_size;
+ u32 st_blksize;
+ u32 st_blocks;
+ u32 st_atime;
+ u32 st_atime_nsec;
+ u32 st_mtime;
+ u32 st_mtime_nsec;
+ u32 st_ctime;
+ u32 st_ctime_nsec;
+ u32 __unused4;
+ u32 __unused5;
+};
+
+struct compat_flock {
+ short l_type;
+ short l_whence;
+ compat_off_t l_start;
+ compat_off_t l_len;
+ compat_pid_t l_pid;
+};
+
+#define F_GETLK64 12
+#define F_SETLK64 13
+#define F_SETLKW64 14
+
+struct compat_flock64 {
+ short l_type;
+ short l_whence;
+ compat_loff_t l_start;
+ compat_loff_t l_len;
+ compat_pid_t l_pid;
+};
+
+struct compat_statfs {
+ s32 f_type;
+ s32 f_bsize;
+ s32 f_blocks;
+ s32 f_bfree;
+ s32 f_bavail;
+ s32 f_files;
+ s32 f_ffree;
+ compat_fsid_t f_fsid;
+ s32 f_namelen;
+ s32 f_spare[6];
+};
+
+typedef u32 compat_old_sigset_t; /* at least 32 bits */
+
+#define _COMPAT_NSIG 64
+#define _COMPAT_NSIG_BPW 32
+
+typedef u32 compat_sigset_word;
+
+#define COMPAT_OFF_T_MAX 0x7fffffff
+#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
+
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef u32 compat_uptr_t;
+
+static inline void *compat_ptr(compat_uptr_t uptr)
+{
+ return (void *)(unsigned long)(uptr & 0x7fffffffUL);
+}
+
+#endif /* _ASM_S390X_COMPAT_H */
diff -urN linux-2.5.67/include/asm-s390/div64.h linux-2.5.67-s390/include/asm-s390/div64.h
--- linux-2.5.67/include/asm-s390/div64.h Mon Apr 7 19:31:55 2003
+++ linux-2.5.67-s390/include/asm-s390/div64.h Mon Apr 14 19:11:58 2003
@@ -1,8 +1,9 @@
#ifndef __S390_DIV64
#define __S390_DIV64

+#ifndef __s390x__
+
/* for do_div "base" needs to be smaller than 2^31-1 */
-
#define do_div(n, base) ({ \
unsigned long long __n = (n); \
unsigned long __r; \
@@ -41,4 +42,14 @@
__r; \
})

+#else /* __s390x__ */
+
+#define do_div(n,base) ({ \
+int __res; \
+__res = ((unsigned long) n) % (unsigned) base; \
+n = ((unsigned long) n) / (unsigned) base; \
+__res; })
+
+#endif /* __s390x__ */
+
#endif
diff -urN linux-2.5.67/include/asm-s390/ebcdic.h linux-2.5.67-s390/include/asm-s390/ebcdic.h
--- linux-2.5.67/include/asm-s390/ebcdic.h Mon Apr 7 19:31:09 2003
+++ linux-2.5.67-s390/include/asm-s390/ebcdic.h Mon Apr 14 19:11:58 2003
@@ -21,8 +21,8 @@
extern __u8 _ebc_tolower[]; /* EBCDIC -> lowercase */
extern __u8 _ebc_toupper[]; /* EBCDIC -> uppercase */

-extern __inline__
-void codepage_convert(const __u8 *codepage, volatile __u8 * addr, int nr)
+extern __inline__ void
+codepage_convert(const __u8 *codepage, volatile __u8 * addr, unsigned long nr)
{
if (nr-- <= 0)
return;
diff -urN linux-2.5.67/include/asm-s390/elf.h linux-2.5.67-s390/include/asm-s390/elf.h
--- linux-2.5.67/include/asm-s390/elf.h Mon Apr 7 19:32:48 2003
+++ linux-2.5.67-s390/include/asm-s390/elf.h Mon Apr 14 19:11:58 2003
@@ -23,7 +23,11 @@
/*
* These are used to set parameters in the core dumps.
*/
+#ifndef __s390x__
#define ELF_CLASS ELFCLASS32
+#else /* __s390x__ */
+#define ELF_CLASS ELFCLASS64
+#endif /* __s390x__ */
#define ELF_DATA ELFDATA2MSB
#define ELF_ARCH EM_S390

@@ -36,8 +40,16 @@

/* For SVR4/S390 the function pointer to be registered with `atexit` is
passed in R14. */
+#ifndef __s390x__
#define ELF_PLAT_INIT(_r, load_addr) \
_r->gprs[14] = 0
+#else /* __s390x__ */
+#define ELF_PLAT_INIT(_r, load_addr) \
+ do { \
+ _r->gprs[14] = 0; \
+ clear_thread_flag(TIF_31BIT); \
+ } while(0)
+#endif /* __s390x__ */

#define USE_ELF_CORE_DUMP
#define ELF_EXEC_PAGESIZE 4096
@@ -47,9 +59,13 @@
the loader. We need to make sure that it is out of the way of the program
that it will "exec", and that there is sufficient room for the brk. */

+#ifndef __s390x__
#define ELF_ET_DYN_BASE ((TASK_SIZE & 0x80000000) \
? TASK_SIZE / 3 * 2 \
: 2 * TASK_SIZE / 3)
+#else /* __s390x__ */
+#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
+#endif /* __s390x__ */

/* Wow, the "main" arch needs arch dependent functions too.. :) */

@@ -76,7 +92,18 @@
#define ELF_PLATFORM (NULL)

#ifdef __KERNEL__
+#ifndef __s390x__
#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
+#else /* __s390x__ */
+#define SET_PERSONALITY(ex, ibcs2) \
+do { \
+ if (ibcs2) \
+ set_personality(PER_SVR4); \
+ else if (current->personality != PER_LINUX32) \
+ set_personality(PER_LINUX); \
+ clear_thread_flag(TIF_31BIT); \
+} while (0)
+#endif /* __s390x__ */
#endif

#endif
diff -urN linux-2.5.67/include/asm-s390/fcntl.h linux-2.5.67-s390/include/asm-s390/fcntl.h
--- linux-2.5.67/include/asm-s390/fcntl.h Mon Apr 7 19:30:33 2003
+++ linux-2.5.67-s390/include/asm-s390/fcntl.h Mon Apr 14 19:11:58 2003
@@ -42,10 +42,11 @@
#define F_SETSIG 10 /* for sockets. */
#define F_GETSIG 11 /* for sockets. */

+#ifndef __s390x__
#define F_GETLK64 12 /* using 'struct flock64' */
#define F_SETLK64 13
#define F_SETLKW64 14
-
+#endif /* ! __s390x__ */

/* for F_[GET|SET]FL */
#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
@@ -82,6 +83,7 @@
pid_t l_pid;
};

+#ifndef __s390x__
struct flock64 {
short l_type;
short l_whence;
@@ -89,6 +91,6 @@
loff_t l_len;
pid_t l_pid;
};
-
+#endif
#define F_LINUX_SPECIFIC_BASE 1024
#endif
diff -urN linux-2.5.67/include/asm-s390/gdb-stub.h linux-2.5.67-s390/include/asm-s390/gdb-stub.h
--- linux-2.5.67/include/asm-s390/gdb-stub.h Mon Apr 7 19:31:56 2003
+++ linux-2.5.67-s390/include/asm-s390/gdb-stub.h Thu Jan 1 01:00:00 1970
@@ -1,22 +0,0 @@
-/*
- * include/asm-s390/gdb-stub.h
- *
- * S390 version
- * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
- */
-
-#ifndef __S390_GDB_STUB__
-#define __S390_GDB_STUB__
-#include <linux/config.h>
-#if CONFIG_REMOTE_DEBUG
-#include <asm/ptrace.h>
-extern int gdb_stub_initialised;
-extern void gdb_stub_handle_exception(struct gdb_pt_regs *regs,int sigval);
-struct net_device;
-extern struct net_device *gdb_dev;
-void gdb_do_timers(void);
-extern int putDebugChar(char c); /* write a single character */
-extern char getDebugChar(void); /* read and return a single char */
-#endif
-#endif
diff -urN linux-2.5.67/include/asm-s390/idals.h linux-2.5.67-s390/include/asm-s390/idals.h
--- linux-2.5.67/include/asm-s390/idals.h Mon Apr 7 19:30:40 2003
+++ linux-2.5.67-s390/include/asm-s390/idals.h Mon Apr 14 19:11:58 2003
@@ -21,7 +21,7 @@
#include <asm/cio.h>
#include <asm/uaccess.h>

-#ifdef CONFIG_ARCH_S390X
+#ifdef __s390x__
#define IDA_SIZE_LOG 12 /* 11 for 2k , 12 for 4k */
#else
#define IDA_SIZE_LOG 11 /* 11 for 2k , 12 for 4k */
@@ -34,7 +34,7 @@
static inline int
idal_is_needed(void *vaddr, unsigned int length)
{
-#if defined(CONFIG_ARCH_S390X)
+#ifdef __s390x__
return ((__pa(vaddr) + length) >> 31) != 0;
#else
return 0;
@@ -48,7 +48,7 @@
static inline unsigned int
idal_nr_words(void *vaddr, unsigned int length)
{
-#if defined(CONFIG_ARCH_S390X)
+#ifdef __s390x__
if (idal_is_needed(vaddr, length))
return ((__pa(vaddr) & (IDA_BLOCK_SIZE-1)) + length +
(IDA_BLOCK_SIZE-1)) >> IDA_SIZE_LOG;
@@ -62,7 +62,7 @@
static inline unsigned long *
idal_create_words(unsigned long *idaws, void *vaddr, unsigned int length)
{
-#if defined(CONFIG_ARCH_S390X)
+#ifdef __s390x__
unsigned long paddr;
unsigned int cidaw;

@@ -86,7 +86,7 @@
static inline int
set_normalized_cda(struct ccw1 * ccw, void *vaddr)
{
-#if defined (CONFIG_ARCH_S390X)
+#ifdef __s390x__
unsigned int nridaws;
unsigned long *idal;

@@ -113,7 +113,7 @@
static inline void
clear_normalized_cda(struct ccw1 * ccw)
{
-#if defined(CONFIG_ARCH_S390X)
+#ifdef __s390x__
if (ccw->flags & CCW_FLAG_IDA) {
kfree((void *)(unsigned long) ccw->cda);
ccw->flags &= ~CCW_FLAG_IDA;
@@ -190,7 +190,7 @@
static inline int
__idal_buffer_is_needed(struct idal_buffer *ib)
{
-#ifdef CONFIG_ARCH_S390X
+#ifdef __s390x__
return ib->size > (4096ul << ib->page_order) ||
idal_is_needed(ib->data[0], ib->size);
#else
diff -urN linux-2.5.67/include/asm-s390/io.h linux-2.5.67-s390/include/asm-s390/io.h
--- linux-2.5.67/include/asm-s390/io.h Mon Apr 7 19:31:56 2003
+++ linux-2.5.67-s390/include/asm-s390/io.h Mon Apr 14 19:11:58 2003
@@ -27,9 +27,16 @@
extern inline unsigned long virt_to_phys(volatile void * address)
{
unsigned long real_address;
- __asm__ (" lra %0,0(%1)\n"
+ __asm__ (
+#ifndef __s390x__
+ " lra %0,0(%1)\n"
" jz 0f\n"
" sr %0,%0\n"
+#else /* __s390x__ */
+ " lrag %0,0(%1)\n"
+ " jz 0f\n"
+ " slgr %0,%0\n"
+#endif /* __s390x__ */
"0:"
: "=a" (real_address) : "a" (address) : "cc" );
return real_address;
diff -urN linux-2.5.67/include/asm-s390/ipc.h linux-2.5.67-s390/include/asm-s390/ipc.h
--- linux-2.5.67/include/asm-s390/ipc.h Mon Apr 7 19:32:54 2003
+++ linux-2.5.67-s390/include/asm-s390/ipc.h Mon Apr 14 19:11:58 2003
@@ -22,6 +22,7 @@
#define SEMOP 1
#define SEMGET 2
#define SEMCTL 3
+#define SEMTIMEDOP 4
#define MSGSND 11
#define MSGRCV 12
#define MSGGET 13
diff -urN linux-2.5.67/include/asm-s390/ipcbuf.h linux-2.5.67-s390/include/asm-s390/ipcbuf.h
--- linux-2.5.67/include/asm-s390/ipcbuf.h Mon Apr 7 19:31:15 2003
+++ linux-2.5.67-s390/include/asm-s390/ipcbuf.h Mon Apr 14 19:11:58 2003
@@ -21,7 +21,9 @@
__kernel_mode_t mode;
unsigned short __pad1;
unsigned short seq;
+#ifndef __s390x__
unsigned short __pad2;
+#endif /* ! __s390x__ */
unsigned long __unused1;
unsigned long __unused2;
};
diff -urN linux-2.5.67/include/asm-s390/lowcore.h linux-2.5.67-s390/include/asm-s390/lowcore.h
--- linux-2.5.67/include/asm-s390/lowcore.h Mon Apr 7 19:31:19 2003
+++ linux-2.5.67-s390/include/asm-s390/lowcore.h Mon Apr 14 19:11:58 2003
@@ -11,6 +11,7 @@
#ifndef _ASM_S390_LOWCORE_H
#define _ASM_S390_LOWCORE_H

+#ifndef __s390x__
#define __LC_EXT_OLD_PSW 0x018
#define __LC_SVC_OLD_PSW 0x020
#define __LC_PGM_OLD_PSW 0x028
@@ -21,43 +22,76 @@
#define __LC_PGM_NEW_PSW 0x068
#define __LC_MCK_NEW_PSW 0x070
#define __LC_IO_NEW_PSW 0x078
+#else /* !__s390x__ */
+#define __LC_EXT_OLD_PSW 0x0130
+#define __LC_SVC_OLD_PSW 0x0140
+#define __LC_PGM_OLD_PSW 0x0150
+#define __LC_MCK_OLD_PSW 0x0160
+#define __LC_IO_OLD_PSW 0x0170
+#define __LC_EXT_NEW_PSW 0x01b0
+#define __LC_SVC_NEW_PSW 0x01c0
+#define __LC_PGM_NEW_PSW 0x01d0
+#define __LC_MCK_NEW_PSW 0x01e0
+#define __LC_IO_NEW_PSW 0x01f0
+#endif /* !__s390x__ */
+
#define __LC_EXT_PARAMS 0x080
#define __LC_CPU_ADDRESS 0x084
#define __LC_EXT_INT_CODE 0x086
-#define __LC_SVC_INT_CODE 0x08B
+
+#define __LC_SVC_ILC 0x088
+#define __LC_SVC_INT_CODE 0x08A
#define __LC_PGM_ILC 0x08C
#define __LC_PGM_INT_CODE 0x08E
-#define __LC_TRANS_EXC_ADDR 0x090
+
#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 0x120
-#define __LC_CREGS_SAVE_AREA 0x1C0

#define __LC_RETURN_PSW 0x200
-#define __LC_IRB 0x208
+
+#define __LC_IRB 0x210
+
+#define __LC_DIAG44_OPCODE 0x250

#define __LC_SAVE_AREA 0xC00
+
+#ifndef __s390x__
#define __LC_KERNEL_STACK 0xC40
#define __LC_ASYNC_STACK 0xC44
#define __LC_CPUID 0xC60
#define __LC_CPUADDR 0xC68
#define __LC_IPLDEV 0xC7C
-
#define __LC_JIFFY_TIMER 0xC80
+#else /* __s390x__ */
+#define __LC_KERNEL_STACK 0xD40
+#define __LC_ASYNC_STACK 0xD48
+#define __LC_CPUID 0xD90
+#define __LC_CPUADDR 0xD98
+#define __LC_IPLDEV 0xDB8
+#define __LC_JIFFY_TIMER 0xDC0
+#endif /* __s390x__ */

#define __LC_PANIC_MAGIC 0xE00

+#ifndef __s390x__
#define __LC_PFAULT_INTPARM 0x080
+#define __LC_AREGS_SAVE_AREA 0x120
+#define __LC_CREGS_SAVE_AREA 0x1C0
+#else /* __s390x__ */
+#define __LC_PFAULT_INTPARM 0x11B8
+#define __LC_AREGS_SAVE_AREA 0x1340
+#define __LC_CREGS_SAVE_AREA 0x1380
+#endif /* __s390x__ */

#ifndef __ASSEMBLY__

#include <linux/config.h>
+#include <asm/processor.h>
#include <linux/types.h>
#include <asm/atomic.h>
-#include <asm/processor.h>
#include <asm/sigp.h>

void restart_int_handler(void);
@@ -69,6 +103,7 @@

struct _lowcore
{
+#ifndef __s390x__
/* prefix area: defined by architecture */
psw_t restart_psw; /* 0x000 */
__u32 ccw2[4]; /* 0x008 */
@@ -142,6 +177,101 @@

/* Align to the top 1k of prefix area */
__u8 pad12[0x1000-0xe04]; /* 0xe04 */
+#else /* !__s390x__ */
+ /* prefix area: defined by architecture */
+ __u32 ccw1[2]; /* 0x000 */
+ __u32 ccw2[4]; /* 0x008 */
+ __u8 pad1[0x80-0x18]; /* 0x018 */
+ __u32 ext_params; /* 0x080 */
+ __u16 cpu_addr; /* 0x084 */
+ __u16 ext_int_code; /* 0x086 */
+ __u16 svc_ilc; /* 0x088 */
+ __u16 svc_code; /* 0x08a */
+ __u16 pgm_ilc; /* 0x08c */
+ __u16 pgm_code; /* 0x08e */
+ __u32 data_exc_code; /* 0x090 */
+ __u16 mon_class_num; /* 0x094 */
+ __u16 per_perc_atmid; /* 0x096 */
+ addr_t per_address; /* 0x098 */
+ __u8 exc_access_id; /* 0x0a0 */
+ __u8 per_access_id; /* 0x0a1 */
+ __u8 op_access_id; /* 0x0a2 */
+ __u8 ar_access_id; /* 0x0a3 */
+ __u8 pad2[0xA8-0xA4]; /* 0x0a4 */
+ addr_t trans_exc_code; /* 0x0A0 */
+ addr_t monitor_code; /* 0x09c */
+ __u16 subchannel_id; /* 0x0b8 */
+ __u16 subchannel_nr; /* 0x0ba */
+ __u32 io_int_parm; /* 0x0bc */
+ __u32 io_int_word; /* 0x0c0 */
+ __u8 pad3[0xc8-0xc4]; /* 0x0c4 */
+ __u32 stfl_fac_list; /* 0x0c8 */
+ __u8 pad4[0xe8-0xcc]; /* 0x0cc */
+ __u32 mcck_interruption_code[2]; /* 0x0e8 */
+ __u8 pad5[0xf4-0xf0]; /* 0x0f0 */
+ __u32 external_damage_code; /* 0x0f4 */
+ addr_t failing_storage_address; /* 0x0f8 */
+ __u8 pad6[0x120-0x100]; /* 0x100 */
+ psw_t restart_old_psw; /* 0x120 */
+ psw_t external_old_psw; /* 0x130 */
+ psw_t svc_old_psw; /* 0x140 */
+ psw_t program_old_psw; /* 0x150 */
+ psw_t mcck_old_psw; /* 0x160 */
+ psw_t io_old_psw; /* 0x170 */
+ __u8 pad7[0x1a0-0x180]; /* 0x180 */
+ psw_t restart_psw; /* 0x1a0 */
+ psw_t external_new_psw; /* 0x1b0 */
+ psw_t svc_new_psw; /* 0x1c0 */
+ psw_t program_new_psw; /* 0x1d0 */
+ psw_t mcck_new_psw; /* 0x1e0 */
+ psw_t io_new_psw; /* 0x1f0 */
+ psw_t return_psw; /* 0x200 */
+ __u8 irb[64]; /* 0x210 */
+ __u32 diag44_opcode; /* 0x250 */
+ __u8 pad8[0xc00-0x254]; /* 0x254 */
+ /* System info area */
+ __u64 save_area[16]; /* 0xc00 */
+ __u8 pad9[0xd40-0xc80]; /* 0xc80 */
+ __u64 kernel_stack; /* 0xd40 */
+ __u64 async_stack; /* 0xd48 */
+ /* entry.S sensitive area start */
+ __u8 pad10[0xd80-0xd50]; /* 0xd64 */
+ struct cpuinfo_S390 cpu_data; /* 0xd80 */
+ __u32 ipl_device; /* 0xdb8 */
+ __u32 pad11; /* 0xdbc */
+ /* entry.S sensitive area end */
+
+ /* SMP info area: defined by DJB */
+ __u64 jiffy_timer; /* 0xdc0 */
+ __u64 ext_call_fast; /* 0xdc8 */
+ __u8 pad12[0xe00-0xdd0]; /* 0xdd0 */
+
+ /* 0xe00 is used as indicator for dump tools */
+ /* whether the kernel died with panic() or not */
+ __u32 panic_magic; /* 0xe00 */
+
+ __u8 pad13[0x1200-0xe04]; /* 0xe04 */
+
+ /* System info area */
+
+ __u64 floating_pt_save_area[16]; /* 0x1200 */
+ __u64 gpregs_save_area[16]; /* 0x1280 */
+ __u32 st_status_fixed_logout[4]; /* 0x1300 */
+ __u8 pad14[0x1318-0x1310]; /* 0x1310 */
+ __u32 prefixreg_save_area; /* 0x1318 */
+ __u32 fpt_creg_save_area; /* 0x131c */
+ __u8 pad15[0x1324-0x1320]; /* 0x1320 */
+ __u32 tod_progreg_save_area; /* 0x1324 */
+ __u32 cpu_timer_save_area[2]; /* 0x1328 */
+ __u32 clock_comp_save_area[2]; /* 0x1330 */
+ __u8 pad16[0x1340-0x1338]; /* 0x1338 */
+ __u32 access_regs_save_area[16]; /* 0x1340 */
+ __u64 cregs_save_area[16]; /* 0x1380 */
+
+ /* align to the top of the prefix area */
+
+ __u8 pad17[0x2000-0x1400]; /* 0x1400 */
+#endif /* !__s390x__ */
} __attribute__((packed)); /* End structure*/

#define S390_lowcore (*((struct _lowcore *) 0))
diff -urN linux-2.5.67/include/asm-s390/mmu_context.h linux-2.5.67-s390/include/asm-s390/mmu_context.h
--- linux-2.5.67/include/asm-s390/mmu_context.h Mon Apr 7 19:31:14 2003
+++ linux-2.5.67-s390/include/asm-s390/mmu_context.h Mon Apr 14 19:11:58 2003
@@ -27,12 +27,20 @@
unsigned long pgd;

if (prev != next) {
+#ifndef __s390x__
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 */
: : "m" (pgd) );
+#else /* __s390x__ */
+ pgd = (__pa(next->pgd)&PAGE_MASK) | (_REGION_TABLE|USER_STD_MASK);
+ /* Load page tables */
+ asm volatile(" lctlg 7,7,%0\n" /* secondary space */
+ " lctlg 13,13,%0\n" /* home space */
+ : : "m" (pgd) );
+#endif /* __s390x__ */
}
set_bit(cpu, &next->cpu_vm_mask);
}
diff -urN linux-2.5.67/include/asm-s390/module.h linux-2.5.67-s390/include/asm-s390/module.h
--- linux-2.5.67/include/asm-s390/module.h Mon Apr 7 19:30:33 2003
+++ linux-2.5.67-s390/include/asm-s390/module.h Mon Apr 14 19:11:58 2003
@@ -28,7 +28,7 @@
struct mod_arch_syminfo *syminfo;
};

-#ifdef CONFIG_ARCH_S390X
+#ifdef __s390x__
#define ElfW(x) Elf64_ ## x
#define ELFW(x) ELF64_ ## x
#else
@@ -36,8 +36,11 @@
#define ELFW(x) ELF32_ ## x
#endif

+#define Elf_Addr ElfW(Addr)
+#define Elf_Rela ElfW(Rela)
#define Elf_Shdr ElfW(Shdr)
#define Elf_Sym ElfW(Sym)
#define Elf_Ehdr ElfW(Ehdr)
+#define ELF_R_SYM ELFW(R_SYM)
#define ELF_R_TYPE ELFW(R_TYPE)
#endif /* _ASM_S390_MODULE_H */
diff -urN linux-2.5.67/include/asm-s390/msgbuf.h linux-2.5.67-s390/include/asm-s390/msgbuf.h
--- linux-2.5.67/include/asm-s390/msgbuf.h Mon Apr 7 19:31:43 2003
+++ linux-2.5.67-s390/include/asm-s390/msgbuf.h Mon Apr 14 19:11:58 2003
@@ -14,11 +14,17 @@
struct msqid64_ds {
struct ipc64_perm msg_perm;
__kernel_time_t msg_stime; /* last msgsnd time */
+#ifndef __s390x__
unsigned long __unused1;
+#endif /* ! __s390x__ */
__kernel_time_t msg_rtime; /* last msgrcv time */
+#ifndef __s390x__
unsigned long __unused2;
+#endif /* ! __s390x__ */
__kernel_time_t msg_ctime; /* last change time */
+#ifndef __s390x__
unsigned long __unused3;
+#endif /* ! __s390x__ */
unsigned long msg_cbytes; /* current number of bytes on queue */
unsigned long msg_qnum; /* number of messages in queue */
unsigned long msg_qbytes; /* max number of bytes on queue */
diff -urN linux-2.5.67/include/asm-s390/page.h linux-2.5.67-s390/include/asm-s390/page.h
--- linux-2.5.67/include/asm-s390/page.h Mon Apr 7 19:30:44 2003
+++ linux-2.5.67-s390/include/asm-s390/page.h Mon Apr 14 19:11:58 2003
@@ -20,6 +20,8 @@
#ifdef __KERNEL__
#ifndef __ASSEMBLY__

+#ifndef __s390x__
+
static inline void clear_page(void *page)
{
register_pair rp;
@@ -59,6 +61,48 @@
: "memory" );
}

+#else /* __s390x__ */
+
+static inline void clear_page(void *page)
+{
+ asm volatile (" lgr 2,%0\n"
+ " lghi 3,4096\n"
+ " slgr 1,1\n"
+ " mvcl 2,0"
+ : : "a" ((void *) (page))
+ : "memory", "cc", "1", "2", "3" );
+}
+
+static inline void copy_page(void *to, void *from)
+{
+ if (MACHINE_HAS_MVPG)
+ asm volatile (" sgr 0,0\n"
+ " mvpg %0,%1"
+ : : "a" ((void *)(to)), "a" ((void *)(from))
+ : "memory", "cc", "0" );
+ else
+ asm volatile (" mvc 0(256,%0),0(%1)\n"
+ " mvc 256(256,%0),256(%1)\n"
+ " mvc 512(256,%0),512(%1)\n"
+ " mvc 768(256,%0),768(%1)\n"
+ " mvc 1024(256,%0),1024(%1)\n"
+ " mvc 1280(256,%0),1280(%1)\n"
+ " mvc 1536(256,%0),1536(%1)\n"
+ " mvc 1792(256,%0),1792(%1)\n"
+ " mvc 2048(256,%0),2048(%1)\n"
+ " mvc 2304(256,%0),2304(%1)\n"
+ " mvc 2560(256,%0),2560(%1)\n"
+ " mvc 2816(256,%0),2816(%1)\n"
+ " mvc 3072(256,%0),3072(%1)\n"
+ " mvc 3328(256,%0),3328(%1)\n"
+ " mvc 3584(256,%0),3584(%1)\n"
+ " mvc 3840(256,%0),3840(%1)\n"
+ : : "a"((void *)(to)),"a"((void *)(from))
+ : "memory" );
+}
+
+#endif /* __s390x__ */
+
#define clear_user_page(page, vaddr, pg) clear_page(page)
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)

@@ -79,7 +123,15 @@
/*
* These are used to make use of C type-checking..
*/
+
+typedef struct { unsigned long pgprot; } pgprot_t;
typedef struct { unsigned long pte; } pte_t;
+
+#define pte_val(x) ((x).pte)
+#define pgprot_val(x) ((x).pgprot)
+
+#ifndef __s390x__
+
typedef struct { unsigned long pmd; } pmd_t;
typedef struct {
unsigned long pgd0;
@@ -87,12 +139,23 @@
unsigned long pgd2;
unsigned long pgd3;
} pgd_t;
-typedef struct { unsigned long pgprot; } pgprot_t;

-#define pte_val(x) ((x).pte)
#define pmd_val(x) ((x).pmd)
#define pgd_val(x) ((x).pgd0)
-#define pgprot_val(x) ((x).pgprot)
+
+#else /* __s390x__ */
+
+typedef struct {
+ unsigned long pmd0;
+ unsigned long pmd1;
+ } pmd_t;
+typedef struct { unsigned long pgd; } pgd_t;
+
+#define pmd_val(x) ((x).pmd0)
+#define pmd_val1(x) ((x).pmd1)
+#define pgd_val(x) ((x).pgd)
+
+#endif /* __s390x__ */

#define __pte(x) ((pte_t) { (x) } )
#define __pmd(x) ((pmd_t) { (x) } )
diff -urN linux-2.5.67/include/asm-s390/pgalloc.h linux-2.5.67-s390/include/asm-s390/pgalloc.h
--- linux-2.5.67/include/asm-s390/pgalloc.h Mon Apr 7 19:31:51 2003
+++ linux-2.5.67-s390/include/asm-s390/pgalloc.h Mon Apr 14 19:11:58 2003
@@ -1,5 +1,5 @@
/*
- * include/asm-s390/bugs.h
+ * include/asm-s390/pgalloc.h
*
* S390 version
* Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
@@ -32,35 +32,79 @@
pgd_t *pgd;
int i;

+#ifndef __s390x__
pgd = (pgd_t *) __get_free_pages(GFP_KERNEL,1);
if (pgd != NULL)
for (i = 0; i < USER_PTRS_PER_PGD; i++)
pmd_clear(pmd_offset(pgd + i, i*PGDIR_SIZE));
+#else /* __s390x__ */
+ pgd = (pgd_t *) __get_free_pages(GFP_KERNEL,2);
+ if (pgd != NULL)
+ for (i = 0; i < PTRS_PER_PGD; i++)
+ pgd_clear(pgd + i);
+#endif /* __s390x__ */
return pgd;
}

static inline void pgd_free(pgd_t *pgd)
{
+#ifndef __s390x__
free_pages((unsigned long) pgd, 1);
+#else /* __s390x__ */
+ free_pages((unsigned long) pgd, 2);
+#endif /* __s390x__ */
}

+#ifndef __s390x__
/*
* page middle directory allocation/free routines.
- * We don't use pmd cache, so these are dummy routines. This
+ * We use pmd cache only on s390x, so these are dummy routines. This
* code never triggers because the pgd will always be present.
*/
#define pmd_alloc_one(mm,address) ({ BUG(); ((pmd_t *)2); })
#define pmd_free(x) do { } while (0)
#define __pmd_free_tlb(tlb,x) do { } while (0)
#define pgd_populate(mm, pmd, pte) BUG()
+#else /* __s390x__ */
+static inline pmd_t * pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
+{
+ pmd_t *pmd;
+ int i;
+
+ pmd = (pmd_t *) __get_free_pages(GFP_KERNEL, 2);
+ if (pmd != NULL) {
+ for (i=0; i < PTRS_PER_PMD; i++)
+ pmd_clear(pmd+i);
+ }
+ return pmd;
+}
+
+static inline void pmd_free (pmd_t *pmd)
+{
+ free_pages((unsigned long) pmd, 2);
+}
+
+#define __pmd_free_tlb(tlb,pmd) pmd_free(pmd)
+
+static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd)
+{
+ pgd_val(*pgd) = _PGD_ENTRY | __pa(pmd);
+}
+
+#endif /* __s390x__ */

static inline void
pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte)
{
+#ifndef __s390x__
pmd_val(pmd[0]) = _PAGE_TABLE + __pa(pte);
pmd_val(pmd[1]) = _PAGE_TABLE + __pa(pte+256);
pmd_val(pmd[2]) = _PAGE_TABLE + __pa(pte+512);
pmd_val(pmd[3]) = _PAGE_TABLE + __pa(pte+768);
+#else /* __s390x__ */
+ pmd_val(*pmd) = _PMD_ENTRY + __pa(pte);
+ pmd_val1(*pmd) = _PMD_ENTRY + __pa(pte+256);
+#endif /* __s390x__ */
}

static inline void
@@ -122,11 +166,16 @@
unsigned long address, pte_t *ptep)
{
pte_t pte = *ptep;
+#ifndef __s390x__
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));
}
+#else /* __s390x__ */
+ if (!(pte_val(pte) & _PAGE_INVALID))
+ __asm__ __volatile__ ("ipte %0,%1" : : "a" (ptep), "a" (address));
+#endif /* __s390x__ */
pte_clear(ptep);
return pte;
}
diff -urN linux-2.5.67/include/asm-s390/pgtable.h linux-2.5.67-s390/include/asm-s390/pgtable.h
--- linux-2.5.67/include/asm-s390/pgtable.h Mon Apr 14 19:11:45 2003
+++ linux-2.5.67-s390/include/asm-s390/pgtable.h Mon Apr 14 19:11:58 2003
@@ -14,10 +14,12 @@
#define _ASM_S390_PGTABLE_H

/*
- * The Linux memory management assumes a three-level page table setup. On
- * the S390, we use that, but "fold" the mid level into the top-level page
- * table, so that we physically have the same two-level page table as the
- * S390 mmu expects.
+ * The Linux memory management assumes a three-level page table setup. For
+ * s390 31 bit we "fold" the mid level into the top-level page table, so
+ * that we physically have the same two-level page table as the s390 mmu
+ * expects in 31 bit mode. For s390 64 bit we use three of the five levels
+ * the hardware provides (region first and region second tables are not
+ * used).
*
* 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
@@ -50,13 +52,18 @@
/*
* PMD_SHIFT determines the size of the area a second-level page
* table can map
+ * PGDIR_SHIFT determines what a third-level page table entry can map
*/
-#define PMD_SHIFT 22
+#ifndef __s390x__
+# define PMD_SHIFT 22
+# define PGDIR_SHIFT 22
+#else /* __s390x__ */
+# define PMD_SHIFT 21
+# define PGDIR_SHIFT 31
+#endif /* __s390x__ */
+
#define PMD_SIZE (1UL << PMD_SHIFT)
#define PMD_MASK (~(PMD_SIZE-1))
-
-/* PGDIR_SHIFT determines what a third-level page table entry can map */
-#define PGDIR_SHIFT 22
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
#define PGDIR_MASK (~(PGDIR_SIZE-1))

@@ -66,24 +73,37 @@
* for S390 segment-table entries are combined to one PGD
* that leads to 1024 pte per pgd
*/
-#define PTRS_PER_PTE 1024
-#define PTRS_PER_PMD 1
-#define PTRS_PER_PGD 512
+#ifndef __s390x__
+# define PTRS_PER_PTE 1024
+# define PTRS_PER_PMD 1
+# define PTRS_PER_PGD 512
+#else /* __s390x__ */
+# define PTRS_PER_PTE 512
+# define PTRS_PER_PMD 1024
+# define PTRS_PER_PGD 2048
+#endif /* __s390x__ */

/*
* pgd entries used up by user/kernel:
*/
-#define USER_PTRS_PER_PGD 512
-#define USER_PGD_PTRS 512
-#define KERNEL_PGD_PTRS 512
-#define FIRST_USER_PGD_NR 0
+#ifndef __s390x__
+# define USER_PTRS_PER_PGD 512
+# define USER_PGD_PTRS 512
+# define KERNEL_PGD_PTRS 512
+# define FIRST_USER_PGD_NR 0
+#else /* __s390x__ */
+# define USER_PTRS_PER_PGD 2048
+# define USER_PGD_PTRS 2048
+# define KERNEL_PGD_PTRS 2048
+# define FIRST_USER_PGD_NR 0
+#endif /* __s390x__ */

#define pte_ERROR(e) \
- printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
+ printk("%s:%d: bad pte %p.\n", __FILE__, __LINE__, (void *) pte_val(e))
#define pmd_ERROR(e) \
- printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
+ printk("%s:%d: bad pmd %p.\n", __FILE__, __LINE__, (void *) pmd_val(e))
#define pgd_ERROR(e) \
- printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+ printk("%s:%d: bad pgd %p.\n", __FILE__, __LINE__, (void *) pgd_val(e))

#ifndef __ASSEMBLY__
/*
@@ -98,11 +118,15 @@
#define VMALLOC_START (((unsigned long) high_memory + VMALLOC_OFFSET) \
& ~(VMALLOC_OFFSET-1))
#define VMALLOC_VMADDR(x) ((unsigned long)(x))
-#define VMALLOC_END (0x7fffffffL)
+#ifndef __s390x__
+# define VMALLOC_END (0x7fffffffL)
+#else /* __s390x__ */
+# define VMALLOC_END (0x40000000000L)
+#endif /* __s390x__ */


/*
- * A pagetable entry of S390 has following format:
+ * A 31 bit pagetable entry of S390 has following format:
* | PFRA | | OS |
* 0 0IP0
* 00000000001111111111222222222233
@@ -111,7 +135,7 @@
* 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 31 bit segmenttable entry of S390 has following format:
* | P-table origin | |PTL
* 0 IC
* 00000000001111111111222222222233
@@ -121,7 +145,7 @@
* C Common-Segment Bit: Segment is not private (PoP 3-30)
* PTL Page-Table-Length: Page-table length (PTL+1*16 entries -> up to 256)
*
- * The segmenttable origin of S390 has following format:
+ * The 31 bit segmenttable origin of S390 has following format:
*
* |S-table origin | | STL |
* X **GPS
@@ -134,6 +158,46 @@
* S Storage-Alteration:
* STL Segment-Table-Length: Segment-table length (STL+1*16 entries -> up to 2048)
*
+ * A 64 bit pagetable entry of S390 has following format:
+ * | PFRA |0IP0| OS |
+ * 0000000000111111111122222222223333333333444444444455555555556666
+ * 0123456789012345678901234567890123456789012345678901234567890123
+ *
+ * I Page-Invalid Bit: Page is not available for address-translation
+ * P Page-Protection Bit: Store access not possible for page
+ *
+ * A 64 bit segmenttable entry of S390 has following format:
+ * | P-table origin | TT
+ * 0000000000111111111122222222223333333333444444444455555555556666
+ * 0123456789012345678901234567890123456789012345678901234567890123
+ *
+ * I Segment-Invalid Bit: Segment is not available for address-translation
+ * C Common-Segment Bit: Segment is not private (PoP 3-30)
+ * P Page-Protection Bit: Store access not possible for page
+ * TT Type 00
+ *
+ * A 64 bit region table entry of S390 has following format:
+ * | S-table origin | TF TTTL
+ * 0000000000111111111122222222223333333333444444444455555555556666
+ * 0123456789012345678901234567890123456789012345678901234567890123
+ *
+ * I Segment-Invalid Bit: Segment is not available for address-translation
+ * TT Type 01
+ * TF
+ * TL Table lenght
+ *
+ * The 64 bit regiontable origin of S390 has following format:
+ * | region table origon | DTTL
+ * 0000000000111111111122222222223333333333444444444455555555556666
+ * 0123456789012345678901234567890123456789012345678901234567890123
+ *
+ * X Space-Switch event:
+ * G Segment-Invalid Bit:
+ * P Private-Space Bit:
+ * S Storage-Alteration:
+ * R Real space
+ * TL Table-Length:
+ *
* A storage key has the following format:
* | ACC |F|R|C|0|
* 0 3 4 5 6 7
@@ -158,6 +222,8 @@
#define _PAGE_INVALID_SWAP 0x200
#define _PAGE_INVALID_FILE 0x201

+#ifndef __s390x__
+
/* Bits in the segment table entry */
#define _PAGE_TABLE_LEN 0xf /* only full page-tables */
#define _PAGE_TABLE_COM 0x10 /* common page-table */
@@ -186,6 +252,32 @@

#define USER_STD_MASK 0x00000080UL

+#else /* __s390x__ */
+
+/* Bits in the segment table entry */
+#define _PMD_ENTRY_INV 0x20 /* invalid segment table entry */
+#define _PMD_ENTRY 0x00
+
+/* Bits in the region third table entry */
+#define _PGD_ENTRY_INV 0x20 /* invalid region table entry */
+#define _PGD_ENTRY 0x07
+
+/*
+ * User and kernel page directory
+ */
+#define _REGION_THIRD 0x4
+#define _REGION_THIRD_LEN 0x3
+#define _REGION_TABLE (_REGION_THIRD|_REGION_THIRD_LEN|0x40|0x100)
+#define _KERN_REGION_TABLE (_REGION_THIRD|_REGION_THIRD_LEN)
+
+#define USER_STD_MASK 0x0000000000000080UL
+
+/* Bits in the storage key */
+#define _PAGE_CHANGED 0x02 /* HW changed bit */
+#define _PAGE_REFERENCED 0x04 /* HW referenced bit */
+
+#endif /* __s390x__ */
+
/*
* No mapping available
*/
@@ -195,7 +287,7 @@
#define PAGE_RO_PRIVATE __pgprot(_PAGE_RO|_PAGE_ISCLEAN)
#define PAGE_COPY __pgprot(_PAGE_RO|_PAGE_ISCLEAN)
#define PAGE_SHARED __pgprot(0)
-#define PAGE_KERNEL __pgprot(0)
+#define PAGE_KERNEL __pgprot(_PAGE_ISCLEAN)

/*
* The S390 can't do page protection for execute, and considers that the
@@ -243,6 +335,8 @@
/*
* pgd/pmd/pte query functions
*/
+#ifndef __s390x__
+
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; }
@@ -254,6 +348,40 @@
return (pmd_val(pmd) & (~PAGE_MASK & ~_PAGE_TABLE_INV)) != _PAGE_TABLE;
}

+#else /* __s390x__ */
+
+extern inline int pgd_present(pgd_t pgd)
+{
+ return (pgd_val(pgd) & ~PAGE_MASK) == _PGD_ENTRY;
+}
+
+extern inline int pgd_none(pgd_t pgd)
+{
+ return pgd_val(pgd) & _PGD_ENTRY_INV;
+}
+
+extern inline int pgd_bad(pgd_t pgd)
+{
+ return (pgd_val(pgd) & (~PAGE_MASK & ~_PGD_ENTRY_INV)) != _PGD_ENTRY;
+}
+
+extern inline int pmd_present(pmd_t pmd)
+{
+ return (pmd_val(pmd) & ~PAGE_MASK) == _PMD_ENTRY;
+}
+
+extern inline int pmd_none(pmd_t pmd)
+{
+ return pmd_val(pmd) & _PMD_ENTRY_INV;
+}
+
+extern inline int pmd_bad(pmd_t pmd)
+{
+ return (pmd_val(pmd) & (~PAGE_MASK & ~_PMD_ENTRY_INV)) != _PMD_ENTRY;
+}
+
+#endif /* __s390x__ */
+
extern inline int pte_none(pte_t pte)
{
return (pte_val(pte) & _PAGE_INVALID_MASK) == _PAGE_INVALID_EMPTY;
@@ -302,6 +430,9 @@
/*
* pgd/pmd/pte modification functions
*/
+
+#ifndef __s390x__
+
extern inline void pgd_clear(pgd_t * pgdp) { }

extern inline void pmd_clear(pmd_t * pmdp)
@@ -312,6 +443,21 @@
pmd_val(pmdp[3]) = _PAGE_TABLE_INV;
}

+#else /* __s390x__ */
+
+extern inline void pgd_clear(pgd_t * pgdp)
+{
+ pgd_val(*pgdp) = _PGD_ENTRY_INV | _PGD_ENTRY;
+}
+
+extern inline void pmd_clear(pmd_t * pmdp)
+{
+ pmd_val(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY;
+ pmd_val1(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY;
+}
+
+#endif /* __s390x__ */
+
extern inline void pte_clear(pte_t *ptep)
{
pte_val(*ptep) = _PAGE_INVALID_EMPTY;
@@ -460,6 +606,18 @@
__pte; \
})

+#ifdef __s390x__
+
+#define pfn_pmd(pfn, pgprot) \
+({ \
+ pgprot_t __pgprot = (pgprot); \
+ unsigned long __physpage = __pa((pfn) << PAGE_SHIFT); \
+ pmd_t __pmd = __pmd(__physpage + pgprot_val(__pgprot)); \
+ __pmd; \
+})
+
+#endif /* __s390x__ */
+
#define pte_pfn(x) (pte_val(x) >> PAGE_SHIFT)
#define pte_page(x) pfn_to_page(pte_pfn(x))

@@ -476,12 +634,23 @@
/* to find an entry in a kernel page-table-directory */
#define pgd_offset_k(address) pgd_offset(&init_mm, address)

+#ifndef __s390x__
+
/* Find an entry in the second-level page table.. */
extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
{
return (pmd_t *) dir;
}

+#else /* __s390x__ */
+
+/* Find an entry in the second-level page table.. */
+#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+#define pmd_offset(dir,addr) \
+ ((pmd_t *) pgd_page_kernel(*(dir)) + pmd_index(addr))
+
+#endif /* __s390x__ */
+
/* Find an entry in the third-level page table.. */
#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
#define pte_offset_kernel(pmd, address) \
@@ -492,6 +661,7 @@
#define pte_unmap_nested(pte) do { } while (0)

/*
+ * 31 bit swap entry format:
* 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
@@ -507,17 +677,38 @@
* 0| offset |0110|type |0
* 00000000001111111111222222222233
* 01234567890123456789012345678901
+ *
+ * 64 bit swap entry format:
+ * A page-table entry has some bits we have to treat in a special way.
+ * Bits 52 and bit 55 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 53 and bit 54 are the page invalid bit and the page protection
+ * bit. We set both to indicate a swapped page.
+ * Bit 63 is used as the software page present bit. If a page is
+ * swapped this obviously has to be zero.
+ * This leaves the bits 0-51 and bits 56-62 to store type and offset.
+ * We use the 7 bits from 56-62 for the type and the 52 bits from 0-51
+ * for the offset.
+ * | offset |0110|type |0
+ * 0000000000111111111122222222223333333333444444444455555555556666
+ * 0123456789012345678901234567890123456789012345678901234567890123
*/
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_SWAP;
+#ifndef __s390x__
pte_val(pte) &= 0x7ffff6fe; /* better to be paranoid */
+#else /* __s390x__ */
+ pte_val(pte) &= 0xfffffffffffff6fe; /* better to be paranoid */
+#endif /* __s390x__ */
return pte;
}

#define __swp_type(entry) (((entry).val >> 1) & 0x3f)
-#define __swp_offset(entry) (((entry).val >> 12) & 0x7FFFF )
+#define __swp_offset(entry) ((entry).val >> 12)
#define __swp_entry(type,offset) ((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) })

#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
@@ -525,7 +716,11 @@

typedef pte_t *pte_addr_t;

-#define PTE_FILE_MAX_BITS 26
+#ifndef __s390x__
+# define PTE_FILE_MAX_BITS 26
+#else /* __s390x__ */
+# define PTE_FILE_MAX_BITS 59
+#endif /* __s390x__ */

#define pte_to_pgoff(__pte) \
((((__pte).pte >> 12) << 7) + (((__pte).pte >> 1) & 0x7f))
@@ -543,5 +738,9 @@
*/
#define pgtable_cache_init() do { } while (0)

+#ifdef __s390x__
+# define HAVE_ARCH_UNMAPPED_AREA
+#endif /* __s390x__ */
+
#endif /* _S390_PAGE_H */

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/