[PATCH] s390 (13/16): s390/s390x unification - part 4.

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


Merge s390x and s390 to one architecture.

diffstat:
gdb-stub.c | 581 ---------------------------------------------------
head64.S | 664 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
module.c | 92 +++++---
process.c | 98 +++++++-
ptrace.c | 387 ++++++++++++++++++++++++++++------
reipl64.S | 96 ++++++++
s390_ksyms.c | 25 ++
setup.c | 46 +++-
signal.c | 41 ++-
smp.c | 64 ++---
sys_s390.c | 98 +++++++-
11 files changed, 1434 insertions(+), 758 deletions(-)

diff -urN linux-2.5.67/arch/s390/kernel/gdb-stub.c linux-2.5.67-s390/arch/s390/kernel/gdb-stub.c
--- linux-2.5.67/arch/s390/kernel/gdb-stub.c Mon Apr 7 19:32:59 2003
+++ linux-2.5.67-s390/arch/s390/kernel/gdb-stub.c Thu Jan 1 01:00:00 1970
@@ -1,581 +0,0 @@
-/*
- * arch/s390/kernel/gdb-stub.c
- *
- * S390 version
- * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
- *
- * Originally written by Glenn Engel, Lake Stevens Instrument Division
- *
- * Contributed by HP Systems
- *
- * Modified for SPARC by Stu Grossman, Cygnus Support.
- *
- * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
- * Send complaints, suggestions etc. to <andy@waldorf-gmbh.de>
- *
- * Copyright (C) 1995 Andreas Busse
- */
-
-/*
- * To enable debugger support, two things need to happen. One, a
- * call to set_debug_traps() is necessary in order to allow any breakpoints
- * or error conditions to be properly intercepted and reported to gdb.
- * Two, a breakpoint needs to be generated to begin communication. This
- * is most easily accomplished by a call to breakpoint(). Breakpoint()
- * simulates a breakpoint by executing a BREAK instruction.
- *
- *
- * The following gdb commands are supported:
- *
- * command function Return value
- *
- * g return the value of the CPU registers hex data or ENN
- * G set the value of the CPU registers OK or ENN
- *
- * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
- * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
- *
- * c Resume at current address SNN ( signal NN)
- * cAA..AA Continue at address AA..AA SNN
- *
- * s Step one instruction SNN
- * sAA..AA Step one instruction from AA..AA SNN
- *
- * k kill
- *
- * ? What was the last sigval ? SNN (signal NN)
- *
- *
- * All commands and responses are sent with a packet which includes a
- * checksum. A packet consists of
- *
- * $<packet info>#<checksum>.
- *
- * where
- * <packet info> :: <characters representing the command or response>
- * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
- *
- * When a packet is received, it is first acknowledged with either '+' or '-'.
- * '+' indicates a successful transfer. '-' indicates a failed transfer.
- *
- * Example:
- *
- * Host: Reply:
- * $m0,10#2a +$00010203040506070809101112131415#42
- *
- */
-#define TRUE 1
-#define FALSE 0
-#include <asm/gdb-stub.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <linux/stddef.h>
-
-#define S390_REGS_COMMON_SIZE offsetof(struct gdb_pt_regs,orig_gpr2)
-
-/*
- * external low-level support routines
- */
-
-
-extern void fltr_set_mem_err(void);
-extern void trap_low(void);
-
-/*
- * breakpoint and test functions
- */
-extern void breakpoint(void);
-extern void breakinst(void);
-
-/*
- * local prototypes
- */
-
-static void getpacket(char *buffer);
-static void putpacket(char *buffer);
-static int hex(unsigned char ch);
-static int hexToInt(char **ptr, int *intValue);
-static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault);
-
-
-/*
- * BUFMAX defines the maximum number of characters in inbound/outbound buffers
- * at least NUMREGBYTES*2 are needed for register packets
- */
-#define BUFMAX 2048
-
-static char input_buffer[BUFMAX];
-static char output_buffer[BUFMAX];
-int gdb_stub_initialised = FALSE;
-static const char hexchars[]="0123456789abcdef";
-
-
-/*
- * Convert ch from a hex digit to an int
- */
-static int hex(unsigned char ch)
-{
- if (ch >= 'a' && ch <= 'f')
- return ch-'a'+10;
- if (ch >= '0' && ch <= '9')
- return ch-'0';
- if (ch >= 'A' && ch <= 'F')
- return ch-'A'+10;
- return -1;
-}
-
-/*
- * scan for the sequence $<data>#<checksum>
- */
-static void getpacket(char *buffer)
-{
- unsigned char checksum;
- unsigned char xmitcsum;
- int i;
- int count;
- unsigned char ch;
-
- do {
- /*
- * wait around for the start character,
- * ignore all other characters
- */
- while ((ch = (getDebugChar() & 0x7f)) != '$') ;
-
- checksum = 0;
- xmitcsum = -1;
- count = 0;
-
- /*
- * now, read until a # or end of buffer is found
- */
- while (count < BUFMAX) {
- ch = getDebugChar() & 0x7f;
- if (ch == '#')
- break;
- checksum = checksum + ch;
- buffer[count] = ch;
- count = count + 1;
- }
-
- if (count >= BUFMAX)
- continue;
-
- buffer[count] = 0;
-
- if (ch == '#') {
- xmitcsum = hex(getDebugChar() & 0x7f) << 4;
- xmitcsum |= hex(getDebugChar() & 0x7f);
-
- if (checksum != xmitcsum)
- putDebugChar('-'); /* failed checksum */
- else {
- putDebugChar('+'); /* successful transfer */
-
- /*
- * if a sequence char is present,
- * reply the sequence ID
- */
- if (buffer[2] == ':') {
- putDebugChar(buffer[0]);
- putDebugChar(buffer[1]);
-
- /*
- * remove sequence chars from buffer
- */
- count = strlen(buffer);
- for (i=3; i <= count; i++)
- buffer[i-3] = buffer[i];
- }
- }
- }
- }
- while (checksum != xmitcsum);
-}
-
-/*
- * send the packet in buffer.
- */
-static void putpacket(char *buffer)
-{
- unsigned char checksum;
- int count;
- unsigned char ch;
-
- /*
- * $<packet info>#<checksum>.
- */
-
- do {
- putDebugChar('$');
- checksum = 0;
- count = 0;
-
- while ((ch = buffer[count]) != 0) {
- if (!(putDebugChar(ch)))
- return;
- checksum += ch;
- count += 1;
- }
-
- putDebugChar('#');
- putDebugChar(hexchars[checksum >> 4]);
- putDebugChar(hexchars[checksum & 0xf]);
-
- }
- while ((getDebugChar() & 0x7f) != '+');
-}
-
-
-
-/*
- * Convert the memory pointed to by mem into hex, placing result in buf.
- * Return a pointer to the last char put in buf (null), in case of mem fault,
- * return 0.
- * If MAY_FAULT is non-zero, then we will handle memory faults by returning
- * a 0, else treat a fault like any other fault in the stub.
- */
-static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault)
-{
- unsigned char ch;
-
-/* set_mem_fault_trap(may_fault); */
-
- while (count-- > 0) {
- ch = *(mem++);
-#if 0
- if (mem_err)
- return 0;
-#endif
- *buf++ = hexchars[ch >> 4];
- *buf++ = hexchars[ch & 0xf];
- }
-
- *buf = 0;
-
-/* set_mem_fault_trap(0); */
-
- return buf;
-}
-
-/*
- * convert the hex array pointed to by buf into binary to be placed in mem
- * return a pointer to the character AFTER the last byte written
- */
-static char *hex2mem(char *buf, char *mem, int count, int may_fault)
-{
- int i;
- unsigned char ch;
-
-/* set_mem_fault_trap(may_fault); */
-
- for (i=0; i<count; i++)
- {
- ch = hex(*buf++) << 4;
- ch |= hex(*buf++);
- *(mem++) = ch;
-#if 0
- if (mem_err)
- return 0;
-#endif
- }
-
-/* set_mem_fault_trap(0); */
-
- return mem;
-}
-
-
-
-/*
- * Set up exception handlers for tracing and breakpoints
- */
-void set_debug_traps(void)
-{
-// unsigned long flags;
- unsigned char c;
-
-// save_and_cli(flags);
- /*
- * In case GDB is started before us, ack any packets
- * (presumably "$?#xx") sitting there.
- */
- while((c = getDebugChar()) != '$');
- while((c = getDebugChar()) != '#');
- c = getDebugChar(); /* eat first csum byte */
- c = getDebugChar(); /* eat second csum byte */
- putDebugChar('+'); /* ack it */
-
- gdb_stub_initialised = TRUE;
-// restore_flags(flags);
-}
-
-
-/*
- * Trap handler for memory errors. This just sets mem_err to be non-zero. It
- * assumes that %l1 is non-zero. This should be safe, as it is doubtful that
- * 0 would ever contain code that could mem fault. This routine will skip
- * past the faulting instruction after setting mem_err.
- */
-extern void fltr_set_mem_err(void)
-{
- /* FIXME: Needs to be written... */
-}
-
-
-/*
- * While we find nice hex chars, build an int.
- * Return number of chars processed.
- */
-static int hexToInt(char **ptr, int *intValue)
-{
- int numChars = 0;
- int hexValue;
-
- *intValue = 0;
-
- while (**ptr)
- {
- hexValue = hex(**ptr);
- if (hexValue < 0)
- break;
-
- *intValue = (*intValue << 4) | hexValue;
- numChars ++;
-
- (*ptr)++;
- }
-
- return (numChars);
-}
-
-void gdb_stub_get_non_pt_regs(struct gdb_pt_regs *regs)
-{
- s390_fp_regs *fpregs=&regs->fp_regs;
- int has_ieee=save_fp_regs1(fpregs);
-
- if(!has_ieee)
- {
- fpregs->fpc=0;
- fpregs->fprs[1].d=
- fpregs->fprs[3].d=
- fpregs->fprs[5].d=
- fpregs->fprs[7].d=0;
- memset(&fpregs->fprs[8].d,0,sizeof(freg_t)*8);
- }
-}
-
-void gdb_stub_set_non_pt_regs(struct gdb_pt_regs *regs)
-{
- restore_fp_regs1(&regs->fp_regs);
-}
-
-void gdb_stub_send_signal(int sigval)
-{
- char *ptr;
- ptr = output_buffer;
-
- /*
- * Send trap type (converted to signal)
- */
- *ptr++ = 'S';
- *ptr++ = hexchars[sigval >> 4];
- *ptr++ = hexchars[sigval & 0xf];
- *ptr++ = 0;
- putpacket(output_buffer); /* send it off... */
-}
-
-/*
- * This function does all command processing for interfacing to gdb. It
- * returns 1 if you should skip the instruction at the trap address, 0
- * otherwise.
- */
-void gdb_stub_handle_exception(struct gdb_pt_regs *regs,int sigval)
-{
- int trap; /* Trap type */
- int addr;
- int length;
- char *ptr;
- unsigned long *stack;
-
-
- /*
- * reply to host that an exception has occurred
- */
-#if 0
- send_signal(sigval);
-#endif
- /*
- * Wait for input from remote GDB
- */
- while (1)
- {
- output_buffer[0] = 0;
- getpacket(input_buffer);
-
- switch (input_buffer[0])
- {
- case '?':
-#if 0
- send_signal(sigval);
-#endif
- continue;
-
- case 'd':
- /* toggle debug flag */
- break;
-
- /*
- * Return the value of the CPU registers
- */
- case 'g':
- gdb_stub_get_non_pt_regs(regs);
- ptr = output_buffer;
- ptr= mem2hex((char *)regs,ptr,S390_REGS_COMMON_SIZE,FALSE);
- ptr= mem2hex((char *)&regs->crs[0],ptr,NUM_CRS*CR_SIZE,FALSE);
- ptr = mem2hex((char *)&regs->fp_regs, ptr,sizeof(s390_fp_regs),FALSE);
- break;
-
- /*
- * set the value of the CPU registers - return OK
- * FIXME: Needs to be written
- */
- case 'G':
- ptr=input_buffer;
- hex2mem (ptr, (char *)regs,S390_REGS_COMMON_SIZE, FALSE);
- ptr+=S390_REGS_COMMON_SIZE*2;
- hex2mem (ptr, (char *)regs->crs[0],NUM_CRS*CR_SIZE, FALSE);
- ptr+=NUM_CRS*CR_SIZE*2;
- hex2mem (ptr, (char *)&regs->fp_regs,sizeof(s390_fp_regs), FALSE);
- gdb_stub_set_non_pt_regs(regs);
- strcpy(output_buffer,"OK");
- break;
-
- /*
- * mAA..AA,LLLL Read LLLL bytes at address AA..AA
- */
- case 'm':
- ptr = &input_buffer[1];
-
- if (hexToInt(&ptr, &addr)
- && *ptr++ == ','
- && hexToInt(&ptr, &length)) {
- if (mem2hex((char *)addr, output_buffer, length, 1))
- break;
- strcpy (output_buffer, "E03");
- } else
- strcpy(output_buffer,"E01");
- break;
-
- /*
- * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK
- */
- case 'M':
- ptr = &input_buffer[1];
-
- if (hexToInt(&ptr, &addr)
- && *ptr++ == ','
- && hexToInt(&ptr, &length)
- && *ptr++ == ':')
- {
- if (hex2mem(ptr, (char *)addr, length, 1))
- strcpy(output_buffer, "OK");
- else
- strcpy(output_buffer, "E03");
- }
- else
- strcpy(output_buffer, "E02");
- break;
-
- /*
- * cAA..AA Continue at address AA..AA(optional)
- */
- case 'c':
- /* try to read optional parameter, pc unchanged if no parm */
-
- ptr = &input_buffer[1];
- if (hexToInt(&ptr, &addr))
- regs->psw.addr = addr;
- /*
- * Need to flush the instruction cache here, as we may
- * have deposited a breakpoint, and the icache probably
- * has no way of knowing that a data ref to some location
- * may have changed something that is in the instruction
- * cache.
- * NB: We flush both caches, just to be sure...
- */
-
- flush_cache_all();
- return;
- /* NOTREACHED */
- break;
-
-
- /*
- * kill the program
- */
- case 'k' :
- break; /* do nothing */
-
-
- /*
- * Reset the whole machine (FIXME: system dependent)
- */
- case 'r':
- break;
-
-
- /*
- * Step to next instruction
- */
- case 's':
- /*
- * There is no single step insn in the MIPS ISA, so we
- * use breakpoints and continue, instead.
- */
-#if 0
- single_step(regs);
-#endif
- flush_cache_all();
- return;
- /* NOTREACHED */
- break;
-
- } /* switch */
-
- /*
- * reply to the request
- */
-
- putpacket(output_buffer);
-
- } /* while */
-}
-
-/*
- * This function will generate a breakpoint exception. It is used at the
- * beginning of a program to sync up with a debugger and can be used
- * otherwise as a quick means to stop program execution and "break" into
- * the debugger.
- */
-void breakpoint(void)
-{
- if (!gdb_stub_initialised)
- return;
- asm volatile (".globl breakinst\n"
- "breakinst:\t.word %0"
- : : "i" (S390_BREAKPOINT_U16) );
-}
-
-
-
-
-
-
-
diff -urN linux-2.5.67/arch/s390/kernel/head64.S linux-2.5.67-s390/arch/s390/kernel/head64.S
--- linux-2.5.67/arch/s390/kernel/head64.S Thu Jan 1 01:00:00 1970
+++ linux-2.5.67-s390/arch/s390/kernel/head64.S Mon Apr 14 19:11:56 2003
@@ -0,0 +1,664 @@
+/*
+ * arch/s390/kernel/head.S
+ *
+ * S390 version
+ * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Hartmut Penner (hp@de.ibm.com),
+ * Martin Schwidefsky (schwidefsky@de.ibm.com),
+ * Rob van der Heij (rvdhei@iae.nl)
+ *
+ * There are 5 different IPL methods
+ * 1) load the image directly into ram at address 0 and do an PSW restart
+ * 2) linload will load the image from address 0x10000 to memory 0x10000
+ * and start the code thru LPSW 0x0008000080010000 (VM only, deprecated)
+ * 3) generate the tape ipl header, store the generated image on a tape
+ * and ipl from it
+ * In case of SL tape you need to IPL 5 times to get past VOL1 etc
+ * 4) generate the vm reader ipl header, move the generated image to the
+ * VM reader (use option NOH!) and do a ipl from reader (VM only)
+ * 5) direct call of start by the SALIPL loader
+ * We use the cpuid to distinguish between VM and native ipl
+ * params for kernel are pushed to 0x10400 (see setup.h)
+
+ Changes:
+ Okt 25 2000 <rvdheij@iae.nl>
+ added code to skip HDR and EOF to allow SL tape IPL (5 retries)
+ changed first CCW from rewind to backspace block
+
+ */
+
+#include <linux/config.h>
+#include <asm/setup.h>
+#include <asm/lowcore.h>
+
+#ifndef CONFIG_IPL
+ .org 0
+ .long 0x00080000,0x80000000+startup # Just a restart PSW
+#else
+#ifdef CONFIG_IPL_TAPE
+#define IPL_BS 1024
+ .org 0
+ .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded
+ .long 0x27000000,0x60000001 # by ipl to addresses 0-23.
+ .long 0x02000000,0x20000000+IPL_BS # (a PSW and two CCWs).
+ .long 0x00000000,0x00000000 # external old psw
+ .long 0x00000000,0x00000000 # svc old psw
+ .long 0x00000000,0x00000000 # program check old psw
+ .long 0x00000000,0x00000000 # machine check old psw
+ .long 0x00000000,0x00000000 # io old psw
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x000a0000,0x00000058 # external new psw
+ .long 0x000a0000,0x00000060 # svc new psw
+ .long 0x000a0000,0x00000068 # program check new psw
+ .long 0x000a0000,0x00000070 # machine check new psw
+ .long 0x00080000,0x80000000+.Lioint # io new psw
+
+ .org 0x100
+#
+# subroutine for loading from tape
+# Paramters:
+# R1 = device number
+# R2 = load address
+.Lloader:
+ st %r14,.Lldret
+ la %r3,.Lorbread # r3 = address of orb
+ la %r5,.Lirb # r5 = address of irb
+ st %r2,.Lccwread+4 # initialize CCW data addresses
+ lctl %c6,%c6,.Lcr6
+ slr %r2,%r2
+.Lldlp:
+ la %r6,3 # 3 retries
+.Lssch:
+ ssch 0(%r3) # load chunk of IPL_BS bytes
+ bnz .Llderr
+.Lw4end:
+ bas %r14,.Lwait4io
+ tm 8(%r5),0x82 # do we have a problem ?
+ bnz .Lrecov
+ slr %r7,%r7
+ icm %r7,3,10(%r5) # get residual count
+ lcr %r7,%r7
+ la %r7,IPL_BS(%r7) # IPL_BS-residual=#bytes read
+ ar %r2,%r7 # add to total size
+ tm 8(%r5),0x01 # found a tape mark ?
+ bnz .Ldone
+ l %r0,.Lccwread+4 # update CCW data addresses
+ ar %r0,%r7
+ st %r0,.Lccwread+4
+ b .Lldlp
+.Ldone:
+ l %r14,.Lldret
+ br %r14 # r2 contains the total size
+.Lrecov:
+ bas %r14,.Lsense # do the sensing
+ bct %r6,.Lssch # dec. retry count & branch
+ b .Llderr
+#
+# Sense subroutine
+#
+.Lsense:
+ st %r14,.Lsnsret
+ la %r7,.Lorbsense
+ ssch 0(%r7) # start sense command
+ bnz .Llderr
+ bas %r14,.Lwait4io
+ l %r14,.Lsnsret
+ tm 8(%r5),0x82 # do we have a problem ?
+ bnz .Llderr
+ br %r14
+#
+# Wait for interrupt subroutine
+#
+.Lwait4io:
+ lpsw .Lwaitpsw
+.Lioint:
+ c %r1,0xb8 # compare subchannel number
+ bne .Lwait4io
+ tsch 0(%r5)
+ slr %r0,%r0
+ tm 8(%r5),0x82 # do we have a problem ?
+ bnz .Lwtexit
+ tm 8(%r5),0x04 # got device end ?
+ bz .Lwait4io
+.Lwtexit:
+ br %r14
+.Llderr:
+ lpsw .Lcrash
+
+ .align 8
+.Lorbread:
+ .long 0x00000000,0x0080ff00,.Lccwread
+ .align 8
+.Lorbsense:
+ .long 0x00000000,0x0080ff00,.Lccwsense
+ .align 8
+.Lccwread:
+ .long 0x02200000+IPL_BS,0x00000000
+.Lccwsense:
+ .long 0x04200001,0x00000000
+.Lwaitpsw:
+ .long 0x020a0000,0x80000000+.Lioint
+
+.Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.Lcr6: .long 0xff000000
+ .align 8
+.Lcrash:.long 0x000a0000,0x00000000
+.Lldret:.long 0
+.Lsnsret: .long 0
+#endif /* CONFIG_IPL_TAPE */
+
+#ifdef CONFIG_IPL_VM
+#define IPL_BS 0x730
+ .org 0
+ .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded
+ .long 0x02000018,0x60000050 # by ipl to addresses 0-23.
+ .long 0x02000068,0x60000050 # (a PSW and two CCWs).
+ .fill 80-24,1,0x40 # bytes 24-79 are discarded !!
+ .long 0x020000f0,0x60000050 # The next 160 byte are loaded
+ .long 0x02000140,0x60000050 # to addresses 0x18-0xb7
+ .long 0x02000190,0x60000050 # They form the continuation
+ .long 0x020001e0,0x60000050 # of the CCW program started
+ .long 0x02000230,0x60000050 # by ipl and load the range
+ .long 0x02000280,0x60000050 # 0x0f0-0x730 from the image
+ .long 0x020002d0,0x60000050 # to the range 0x0f0-0x730
+ .long 0x02000320,0x60000050 # in memory. At the end of
+ .long 0x02000370,0x60000050 # the channel program the PSW
+ .long 0x020003c0,0x60000050 # at location 0 is loaded.
+ .long 0x02000410,0x60000050 # Initial processing starts
+ .long 0x02000460,0x60000050 # at 0xf0 = iplstart.
+ .long 0x020004b0,0x60000050
+ .long 0x02000500,0x60000050
+ .long 0x02000550,0x60000050
+ .long 0x020005a0,0x60000050
+ .long 0x020005f0,0x60000050
+ .long 0x02000640,0x60000050
+ .long 0x02000690,0x60000050
+ .long 0x020006e0,0x20000050
+
+ .org 0xf0
+#
+# subroutine for loading cards from the reader
+#
+.Lloader:
+ la %r3,.Lorb # r2 = address of orb into r2
+ la %r5,.Lirb # r4 = address of irb
+ la %r6,.Lccws
+ la %r7,20
+.Linit:
+ st %r2,4(%r6) # initialize CCW data addresses
+ la %r2,0x50(%r2)
+ la %r6,8(%r6)
+ bct 7,.Linit
+
+ lctl %c6,%c6,.Lcr6 # set IO subclass mask
+ slr %r2,%r2
+.Lldlp:
+ ssch 0(%r3) # load chunk of 1600 bytes
+ bnz .Llderr
+.Lwait4irq:
+ mvc 0x78(8),.Lnewpsw # set up IO interrupt psw
+ lpsw .Lwaitpsw
+.Lioint:
+ c %r1,0xb8 # compare subchannel number
+ bne .Lwait4irq
+ tsch 0(%r5)
+
+ slr %r0,%r0
+ ic %r0,8(%r5) # get device status
+ chi %r0,8 # channel end ?
+ be .Lcont
+ chi %r0,12 # channel end + device end ?
+ be .Lcont
+
+ l %r0,4(%r5)
+ s %r0,8(%r3) # r0/8 = number of ccws executed
+ mhi %r0,10 # *10 = number of bytes in ccws
+ lh %r3,10(%r5) # get residual count
+ sr %r0,%r3 # #ccws*80-residual=#bytes read
+ ar %r2,%r0
+
+ br %r14 # r2 contains the total size
+
+.Lcont:
+ ahi %r2,0x640 # add 0x640 to total size
+ la %r6,.Lccws
+ la %r7,20
+.Lincr:
+ l %r0,4(%r6) # update CCW data addresses
+ ahi %r0,0x640
+ st %r0,4(%r6)
+ ahi %r6,8
+ bct 7,.Lincr
+
+ b .Lldlp
+.Llderr:
+ lpsw .Lcrash
+
+ .align 8
+.Lorb: .long 0x00000000,0x0080ff00,.Lccws
+.Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.Lcr6: .long 0xff000000
+.Lloadp:.long 0,0
+ .align 8
+.Lcrash:.long 0x000a0000,0x00000000
+.Lnewpsw:
+ .long 0x00080000,0x80000000+.Lioint
+.Lwaitpsw:
+ .long 0x020a0000,0x80000000+.Lioint
+
+ .align 8
+.Lccws: .rept 19
+ .long 0x02600050,0x00000000
+ .endr
+ .long 0x02200050,0x00000000
+#endif /* CONFIG_IPL_VM */
+
+iplstart:
+ lh %r1,0xb8 # test if subchannel number
+ bct %r1,.Lnoload # is valid
+ l %r1,0xb8 # load ipl subchannel number
+ la %r2,IPL_BS # load start address
+ bas %r14,.Lloader # load rest of ipl image
+ larl %r12,_pstart # pointer to parameter area
+ st %r1,IPL_DEVICE+4-PARMAREA(%r12) # store ipl device number
+
+#
+# load parameter file from ipl device
+#
+.Lagain1:
+ l %r2,INITRD_START+4-PARMAREA(%r12)# use ramdisk location as temp
+ bas %r14,.Lloader # load parameter file
+ ltr %r2,%r2 # got anything ?
+ bz .Lnopf
+ chi %r2,895
+ bnh .Lnotrunc
+ la %r2,895
+.Lnotrunc:
+ l %r4,INITRD_START+4-PARMAREA(%r12)
+ clc 0(3,%r4),.L_hdr # if it is HDRx
+ bz .Lagain1 # skip dataset header
+ clc 0(3,%r4),.L_eof # if it is EOFx
+ bz .Lagain1 # skip dateset trailer
+ la %r5,0(%r4,%r2)
+ lr %r3,%r2
+.Lidebc:
+ tm 0(%r5),0x80 # high order bit set ?
+ bo .Ldocv # yes -> convert from EBCDIC
+ ahi %r5,-1
+ bct %r3,.Lidebc
+ b .Lnocv
+.Ldocv:
+ l %r3,.Lcvtab
+ tr 0(256,%r4),0(%r3) # convert parameters to ascii
+ tr 256(256,%r4),0(%r3)
+ tr 512(256,%r4),0(%r3)
+ tr 768(122,%r4),0(%r3)
+.Lnocv: la %r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line
+ mvc 0(256,%r3),0(%r4)
+ mvc 256(256,%r3),256(%r4)
+ mvc 512(256,%r3),512(%r4)
+ mvc 768(122,%r3),768(%r4)
+ slr %r0,%r0
+ b .Lcntlp
+.Ldelspc:
+ ic %r0,0(%r2,%r3)
+ chi %r0,0x20 # is it a space ?
+ be .Lcntlp
+ ahi %r2,1
+ b .Leolp
+.Lcntlp:
+ brct %r2,.Ldelspc
+.Leolp:
+ slr %r0,%r0
+ stc %r0,0(%r2,%r3) # terminate buffer
+.Lnopf:
+
+#
+# load ramdisk from ipl device
+#
+.Lagain2:
+ l %r2,INITRD_START+4-PARMAREA(%r12)# load adr. of ramdisk
+ bas %r14,.Lloader # load ramdisk
+ st %r2,INITRD_SIZE+4-PARMAREA(%r12) # store size of ramdisk
+ ltr %r2,%r2
+ bnz .Lrdcont
+ st %r2,INITRD_START+4-PARMAREA(%r12)# no ramdisk found, null it
+.Lrdcont:
+ l %r2,INITRD_START+4-PARMAREA(%r12)
+ clc 0(3,%r2),.L_hdr # skip HDRx and EOFx
+ bz .Lagain2
+ clc 0(3,%r2),.L_eof
+ bz .Lagain2
+
+#ifdef CONFIG_IPL_VM
+#
+# reset files in VM reader
+#
+ stidp __LC_CPUID # store cpuid
+ tm __LC_CPUID,0xff # running VM ?
+ bno .Lnoreset
+ la %r2,.Lreset
+ lhi %r3,26
+ .long 0x83230008
+.Lnoreset:
+#endif
+
+#
+# everything loaded, go for it
+#
+.Lnoload:
+ l %r1,.Lstartup
+ br %r1
+
+.Lstartup: .long startup
+.Lcvtab:.long _ebcasc # ebcdic to ascii table
+.Lreset:.byte 0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40
+ .byte 0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6
+ .byte 0xc8,0xd6,0xd3,0xc4 # "change rdr all keep nohold"
+.L_eof: .long 0xc5d6c600 /* C'EOF' */
+.L_hdr: .long 0xc8c4d900 /* C'HDR' */
+#endif /* CONFIG_IPL */
+
+#
+# SALIPL loader support. Based on a patch by Rob van der Heij.
+# This entry point is called directly from the SALIPL loader and
+# doesn't need a builtin ipl record.
+#
+ .org 0x800
+ .globl start
+start:
+ stm %r0,%r15,0x07b0 # store registers
+ basr %r12,%r0
+.base:
+ l %r11,.parm
+ l %r8,.cmd # pointer to command buffer
+
+ ltr %r9,%r9 # do we have SALIPL parameters?
+ bp .sk8x8
+
+ mvc 0(64,%r8),0x00b0 # copy saved registers
+ xc 64(240-64,%r8),0(%r8) # remainder of buffer
+ tr 0(64,%r8),.lowcase
+ b .gotr
+.sk8x8:
+ mvc 0(240,%r8),0(%r9) # copy iplparms into buffer
+.gotr:
+ l %r10,.tbl # EBCDIC to ASCII table
+ tr 0(240,%r8),0(%r10)
+ stidp __LC_CPUID # Are we running on VM maybe
+ cli __LC_CPUID,0xff
+ bnz .test
+ .long 0x83300060 # diag 3,0,x'0060' - storage size
+ b .done
+.test:
+ mvc 0x68(8),.pgmnw # set up pgm check handler
+ l %r2,.fourmeg
+ lr %r3,%r2
+ bctr %r3,%r0 # 4M-1
+.loop: iske %r0,%r3
+ ar %r3,%r2
+.pgmx:
+ sr %r3,%r2
+ la %r3,1(%r3)
+.done:
+ l %r1,.memsize
+ st %r3,4(%r1)
+ slr %r0,%r0
+ st %r0,INITRD_SIZE+4-PARMAREA(%r11)
+ st %r0,INITRD_START+4-PARMAREA(%r11)
+ j startup # continue with startup
+.tbl: .long _ebcasc # translate table
+.cmd: .long COMMAND_LINE # address of command line buffer
+.parm: .long PARMAREA
+.fourmeg: .long 0x00400000 # 4M
+.pgmnw: .long 0x00080000,.pgmx
+.memsize: .long memory_size
+.lowcase:
+ .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07
+ .byte 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
+ .byte 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17
+ .byte 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
+ .byte 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27
+ .byte 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f
+ .byte 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37
+ .byte 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f
+ .byte 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47
+ .byte 0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f
+ .byte 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57
+ .byte 0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f
+ .byte 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67
+ .byte 0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f
+ .byte 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77
+ .byte 0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f
+
+ .byte 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87
+ .byte 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f
+ .byte 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97
+ .byte 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f
+ .byte 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7
+ .byte 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf
+ .byte 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7
+ .byte 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf
+ .byte 0xc0,0x81,0x82,0x83,0x84,0x85,0x86,0x87 # .abcdefg
+ .byte 0x88,0x89,0xca,0xcb,0xcc,0xcd,0xce,0xcf # hi
+ .byte 0xd0,0x91,0x92,0x93,0x94,0x95,0x96,0x97 # .jklmnop
+ .byte 0x98,0x99,0xda,0xdb,0xdc,0xdd,0xde,0xdf # qr
+ .byte 0xe0,0xe1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7 # ..stuvwx
+ .byte 0xa8,0xa9,0xea,0xeb,0xec,0xed,0xee,0xef # yz
+ .byte 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7
+ .byte 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
+
+#
+# startup-code at 0x10000, running in real mode
+# this is called either by the ipl loader or directly by PSW restart
+# or linload or SALIPL
+#
+ .org 0x10000
+startup:basr %r13,0 # get base
+.LPG1: sll %r13,1 # remove high order bit
+ srl %r13,1
+ lhi %r1,1 # mode 1 = esame
+ slr %r0,%r0 # set cpuid to zero
+ sigp %r1,%r0,0x12 # switch to esame mode
+ sam64 # switch to 64 bit mode
+ lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
+ larl %r12,_pstart # pointer to parameter area
+ # move IPL device to lowcore
+ mvc __LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12)
+
+#
+# clear bss memory
+#
+ larl %r2,__bss_start # start of bss segment
+ larl %r3,_end # end of bss segment
+ sgr %r3,%r2 # length of bss
+ sgr %r4,%r4 #
+ sgr %r5,%r5 # set src,length and pad to zero
+ mvcle %r2,%r4,0 # clear mem
+ jo .-4 # branch back, if not finish
+
+ # set program check new psw mask
+ mvc __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
+
+#
+# find memory chunks.
+#
+ larl %r1,.Lchkmem # set program check address
+ stg %r1,__LC_PGM_NEW_PSW+8
+ la %r1,1 # test in increments of 128KB
+ sllg %r1,%r1,17
+ larl %r3,memory_chunk
+ slgr %r4,%r4 # set start of chunk to zero
+ slgr %r5,%r5 # set end of chunk to zero
+ slr %r6,%r6 # set access code to zero
+.Lloop:
+ tprot 0(%r5),0 # test protection of first byte
+ ipm %r7
+ srl %r7,28
+ clr %r6,%r7 # compare cc with last access code
+ je .Lsame
+ clgr %r4,%r5 # chunk size > 0?
+ je .Lsize0
+ stg %r4,0(%r3) # store start address of chunk
+ lgr %r0,%r5
+ slgr %r0,%r4
+ stg %r0,8(%r3) # store size of chunk
+ st %r6,20(%r3) # store type of chunk
+ la %r3,24(%r3)
+ lgr %r4,%r5 # set start to end
+ larl %r8,memory_size
+ stg %r5,0(%r8) # store memory size
+.Lsize0:
+ lr %r6,%r7 # set access code to last cc
+.Lsame:
+ algr %r5,%r1 # add 128KB to end of chunk
+ brc 12,.Lloop
+.Lchkmem: # > 16EB or tprot got a program check
+ clgr %r4,%r5 # chunk size > 0?
+ je .Ldonemem
+ stg %r4,0(%r3) # store start address of chunk
+ lgr %r0,%r5
+ slgr %r0,%r4
+ stg %r0,8(%r3) # store size of chunk
+ st %r6,20(%r3) # store type of chunk
+ la %r3,24(%r3)
+ lgr %r4,%r5
+ larl %r8,memory_size
+ stg %r5,0(%r8) # store memory size
+#
+# Running native the HSA is located at 2GB and we will get an
+# addressing exception trying to access it. We have to restart
+# the scan at 2GB to find out if the machine has more than 2GB.
+#
+ lghi %r4,1
+ sllg %r4,%r4,31
+ clgr %r5,%r4
+ jhe .Ldonemem
+ lgr %r5,%r4
+ j .Lloop
+.Ldonemem:
+
+ larl %r12,machine_flags
+#
+# find out if we are running under VM
+#
+ stidp __LC_CPUID # store cpuid
+ tm __LC_CPUID,0xff # running under VM ?
+ bno 0f-.LPG1(%r13)
+ oi 7(%r12),1 # set VM flag
+0: lh %r0,__LC_CPUID+4 # get cpu version
+ chi %r0,0x7490 # running on a P/390 ?
+ bne 1f-.LPG1(%r13)
+ oi 7(%r12),4 # set P/390 flag
+1:
+
+#
+# find out if we have the MVPG instruction
+#
+ la %r1,0f-.LPG1(%r13) # set program check address
+ stg %r1,__LC_PGM_NEW_PSW+8
+ sgr %r0,%r0
+ lghi %r1,0
+ lghi %r2,0
+ mvpg %r1,%r2 # test MVPG instruction
+ oi 7(%r12),16 # set MVPG flag
+0:
+
+#
+# find out if the diag 0x44 works in 64 bit mode
+#
+ la %r1,0f-.LPG1(%r13) # set program check address
+ stg %r1,__LC_PGM_NEW_PSW+8
+ mvc __LC_DIAG44_OPCODE(8),.Lnop-.LPG1(%r13)
+ diag 0,0,0x44 # test diag 0x44
+ oi 7(%r12),32 # set diag44 flag
+ mvc __LC_DIAG44_OPCODE(8),.Ldiag44-.LPG1(%r13)
+0:
+
+ lpswe .Lentry-.LPG1(13) # jump to _stext in primary-space,
+ # virtual and never return ...
+ .align 16
+.Lentry:.quad 0x0000000180000000,_stext
+.Lctl: .quad 0x04b50002 # cr0: various things
+ .quad 0 # cr1: primary space segment table
+ .quad .Lduct # cr2: dispatchable unit control table
+ .quad 0 # cr3: instruction authorization
+ .quad 0 # cr4: instruction authorization
+ .quad 0 # cr5: various things
+ .quad 0 # cr6: I/O interrupts
+ .quad 0 # cr7: secondary space segment table
+ .quad 0 # cr8: access registers translation
+ .quad 0 # cr9: tracing off
+ .quad 0 # cr10: tracing off
+ .quad 0 # cr11: tracing off
+ .quad 0 # cr12: tracing off
+ .quad 0 # cr13: home space segment table
+ .quad 0xc0000000 # cr14: machine check handling off
+ .quad 0 # cr15: linkage stack operations
+.Lpcmsk:.quad 0x0000000180000000
+.L4malign:.quad 0xffffffffffc00000
+.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8
+.Lnop: .long 0x07000700
+.Ldiag44:.long 0x83000044
+
+ .org PARMAREA-64
+.Lduct: .long 0,0,0,0,0,0,0,0
+ .long 0,0,0,0,0,0,0,0
+
+#
+# params at 10400 (setup.h)
+#
+ .org PARMAREA
+ .global _pstart
+_pstart:
+ .quad 0 # IPL_DEVICE
+ .quad RAMDISK_ORIGIN # INITRD_START
+ .quad RAMDISK_SIZE # INITRD_SIZE
+
+ .org COMMAND_LINE
+ .byte "root=/dev/ram0 ro"
+ .byte 0
+ .org 0x11000
+ .global _pend
+_pend:
+
+#ifdef CONFIG_SHARED_KERNEL
+ .org 0x100000
+#endif
+
+#
+# startup-code, running in virtual mode
+#
+ .globl _stext
+_stext: basr %r13,0 # get base
+.LPG2:
+#
+# Setup stack
+#
+ larl %r15,init_thread_union
+ aghi %r15,16384 # init_task_union + 16384
+ stg %r15,__LC_KERNEL_STACK # set end of kernel stack
+ aghi %r15,-160
+ xc 0(8,%r15),0(%r15) # set backchain to zero
+
+# check control registers
+ stctg %c0,%c15,0(%r15)
+ oi 6(%r15),0x20 # enable sigp external interrupts
+ oi 4(%r15),0x10 # switch on low address proctection
+ lctlg %c0,%c15,0(%r15)
+
+#
+ lam 0,15,.Laregs-.LPG2(%r13) # load access regs needed by uaccess
+ brasl %r14,start_kernel # go to C code
+#
+# We returned from start_kernel ?!? PANIK
+#
+ basr %r13,0
+ lpswe .Ldw-.(%r13) # load disabled wait psw
+#
+ .align 8
+.Ldw: .quad 0x0002000180000000,0x0000000000000000
+.Laregs: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
diff -urN linux-2.5.67/arch/s390/kernel/module.c linux-2.5.67-s390/arch/s390/kernel/module.c
--- linux-2.5.67/arch/s390/kernel/module.c Mon Apr 7 19:32:29 2003
+++ linux-2.5.67-s390/arch/s390/kernel/module.c Mon Apr 14 19:11:56 2003
@@ -37,8 +37,11 @@
#define DEBUGP(fmt , ...)
#endif

-#define GOT_ENTRY_SIZE 4
+#ifndef CONFIG_ARCH_S390X
#define PLT_ENTRY_SIZE 12
+#else /* CONFIG_ARCH_S390X */
+#define PLT_ENTRY_SIZE 20
+#endif /* CONFIG_ARCH_S390X */

void *module_alloc(unsigned long size)
{
@@ -56,30 +59,34 @@
}

static inline void
-check_rela(Elf32_Rela *rela, struct module *me)
+check_rela(Elf_Rela *rela, struct module *me)
{
struct mod_arch_syminfo *info;

- info = me->arch.syminfo + ELF32_R_SYM (rela->r_info);
- switch (ELF32_R_TYPE (rela->r_info)) {
+ info = me->arch.syminfo + ELF_R_SYM (rela->r_info);
+ switch (ELF_R_TYPE (rela->r_info)) {
case R_390_GOT12: /* 12 bit GOT offset. */
case R_390_GOT16: /* 16 bit GOT offset. */
case R_390_GOT32: /* 32 bit GOT offset. */
+ case R_390_GOT64: /* 64 bit GOT offset. */
case R_390_GOTENT: /* 32 bit PC rel. to GOT entry shifted by 1. */
case R_390_GOTPLT12: /* 12 bit offset to jump slot. */
case R_390_GOTPLT16: /* 16 bit offset to jump slot. */
case R_390_GOTPLT32: /* 32 bit offset to jump slot. */
+ case R_390_GOTPLT64: /* 64 bit offset to jump slot. */
case R_390_GOTPLTENT: /* 32 bit rel. offset to jump slot >> 1. */
if (info->got_offset == -1UL) {
info->got_offset = me->arch.got_size;
- me->arch.got_size += GOT_ENTRY_SIZE;
+ me->arch.got_size += sizeof(void*);
}
break;
case R_390_PLT16DBL: /* 16 bit PC rel. PLT shifted by 1. */
case R_390_PLT32DBL: /* 32 bit PC rel. PLT shifted by 1. */
case R_390_PLT32: /* 32 bit PC relative PLT address. */
+ case R_390_PLT64: /* 64 bit PC relative PLT address. */
case R_390_PLTOFF16: /* 16 bit offset from GOT to PLT. */
case R_390_PLTOFF32: /* 32 bit offset from GOT to PLT. */
+ case R_390_PLTOFF64: /* 16 bit offset from GOT to PLT. */
if (info->plt_offset == -1UL) {
info->plt_offset = me->arch.plt_size;
me->arch.plt_size += PLT_ENTRY_SIZE;
@@ -100,12 +107,12 @@
* got and plt but we can increase the core module size.
*/
int
-module_frob_arch_sections(Elf32_Ehdr *hdr, Elf32_Shdr *sechdrs,
+module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
char *secstrings, struct module *me)
{
- Elf32_Shdr *symtab;
- Elf32_Sym *symbols;
- Elf32_Rela *rela;
+ Elf_Shdr *symtab;
+ Elf_Sym *symbols;
+ Elf_Rela *rela;
char *strings;
int nrela, i, j;

@@ -123,7 +130,7 @@
}

/* Allocate one syminfo structure per symbol. */
- me->arch.nsyms = symtab->sh_size / sizeof(Elf32_Sym);
+ me->arch.nsyms = symtab->sh_size / sizeof(Elf_Sym);
me->arch.syminfo = kmalloc(me->arch.nsyms *
sizeof(struct mod_arch_syminfo),
GFP_KERNEL);
@@ -148,7 +155,7 @@
for (i = 0; i < hdr->e_shnum; i++) {
if (sechdrs[i].sh_type != SHT_RELA)
continue;
- nrela = sechdrs[i].sh_size / sizeof(Elf32_Rela);
+ nrela = sechdrs[i].sh_size / sizeof(Elf_Rela);
rela = (void *) hdr + sechdrs[i].sh_offset;
for (j = 0; j < nrela; j++)
check_rela(rela + j, me);
@@ -174,19 +181,19 @@
}

static inline int
-apply_rela(Elf32_Rela *rela, Elf32_Addr base, Elf32_Sym *symtab,
+apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
struct module *me)
{
struct mod_arch_syminfo *info;
- Elf32_Addr loc, val;
+ Elf_Addr loc, val;
int r_type, r_sym;

/* This is where to make the change */
loc = base + rela->r_offset;
/* This is the symbol it is referring to. Note that all
undefined symbols have been resolved. */
- r_sym = ELF32_R_SYM(rela->r_info);
- r_type = ELF32_R_TYPE(rela->r_info);
+ r_sym = ELF_R_SYM(rela->r_info);
+ r_type = ELF_R_TYPE(rela->r_info);
info = me->arch.syminfo + r_sym;
val = symtab[r_sym].st_value;

@@ -195,6 +202,7 @@
case R_390_12: /* Direct 12 bit. */
case R_390_16: /* Direct 16 bit. */
case R_390_32: /* Direct 32 bit. */
+ case R_390_64: /* Direct 64 bit. */
val += rela->r_addend;
if (r_type == R_390_8)
*(unsigned char *) loc = val;
@@ -205,11 +213,14 @@
*(unsigned short *) loc = val;
else if (r_type == R_390_32)
*(unsigned int *) loc = val;
+ else if (r_type == R_390_64)
+ *(unsigned long *) loc = val;
break;
case R_390_PC16: /* PC relative 16 bit. */
case R_390_PC16DBL: /* PC relative 16 bit shifted by 1. */
case R_390_PC32DBL: /* PC relative 32 bit shifted by 1. */
case R_390_PC32: /* PC relative 32 bit. */
+ case R_390_PC64: /* PC relative 64 bit. */
val += rela->r_addend - loc;
if (r_type == R_390_PC16)
*(unsigned short *) loc = val;
@@ -219,17 +230,22 @@
*(unsigned int *) loc = val >> 1;
else if (r_type == R_390_PC32)
*(unsigned int *) loc = val;
+ else if (r_type == R_390_PC64)
+ *(unsigned long *) loc = val;
break;
case R_390_GOT12: /* 12 bit GOT offset. */
case R_390_GOT16: /* 16 bit GOT offset. */
case R_390_GOT32: /* 32 bit GOT offset. */
+ case R_390_GOT64: /* 64 bit GOT offset. */
case R_390_GOTENT: /* 32 bit PC rel. to GOT entry shifted by 1. */
case R_390_GOTPLT12: /* 12 bit offset to jump slot. */
case R_390_GOTPLT16: /* 16 bit offset to jump slot. */
case R_390_GOTPLT32: /* 32 bit offset to jump slot. */
+ case R_390_GOTPLT64: /* 64 bit offset to jump slot. */
case R_390_GOTPLTENT: /* 32 bit rel. offset to jump slot >> 1. */
if (info->got_initialized == 0) {
- Elf32_Addr *gotent;
+ Elf_Addr *gotent;
+
gotent = me->module_core + me->arch.got_offset +
info->got_offset;
*gotent = val;
@@ -249,27 +265,42 @@
else if (r_type == R_390_GOTENT ||
r_type == R_390_GOTPLTENT)
*(unsigned int *) loc = val >> 1;
+ else if (r_type == R_390_GOT64 ||
+ r_type == R_390_GOTPLT64)
+ *(unsigned long *) loc = val;
break;
case R_390_PLT16DBL: /* 16 bit PC rel. PLT shifted by 1. */
case R_390_PLT32DBL: /* 32 bit PC rel. PLT shifted by 1. */
case R_390_PLT32: /* 32 bit PC relative PLT address. */
+ case R_390_PLT64: /* 64 bit PC relative PLT address. */
case R_390_PLTOFF16: /* 16 bit offset from GOT to PLT. */
case R_390_PLTOFF32: /* 32 bit offset from GOT to PLT. */
+ case R_390_PLTOFF64: /* 16 bit offset from GOT to PLT. */
if (info->plt_initialized == 0) {
unsigned int *ip;
ip = me->module_core + me->arch.plt_offset +
info->plt_offset;
+#ifndef CONFIG_ARCH_S390X
ip[0] = 0x0d105810; /* basr 1,0; l 1,6(1); br 1 */
ip[1] = 0x100607f1;
ip[2] = val;
+#else /* CONFIG_ARCH_S390X */
+ ip[0] = 0x0d10e310; /* basr 1,0; lg 1,10(1); br 1 */
+ ip[1] = 0x100a0004;
+ ip[2] = 0x07f10000;
+ ip[3] = (unsigned int) (val >> 32);
+ ip[4] = (unsigned int) val;
+#endif /* CONFIG_ARCH_S390X */
info->plt_initialized = 1;
}
if (r_type == R_390_PLTOFF16 ||
- r_type == R_390_PLTOFF32)
+ r_type == R_390_PLTOFF32
+ || r_type == R_390_PLTOFF64
+ )
val = me->arch.plt_offset - me->arch.got_offset +
info->plt_offset + rela->r_addend;
else
- val = (Elf32_Addr) me->module_core +
+ val = (Elf_Addr) me->module_core +
me->arch.plt_offset + info->plt_offset +
rela->r_addend - loc;
if (r_type == R_390_PLT16DBL)
@@ -281,19 +312,25 @@
else if (r_type == R_390_PLT32 ||
r_type == R_390_PLTOFF32)
*(unsigned int *) loc = val;
+ else if (r_type == R_390_PLT64 ||
+ r_type == R_390_PLTOFF64)
+ *(unsigned long *) loc = val;
break;
case R_390_GOTOFF16: /* 16 bit offset to GOT. */
case R_390_GOTOFF32: /* 32 bit offset to GOT. */
+ case R_390_GOTOFF64: /* 64 bit offset to GOT. */
val = val + rela->r_addend -
- ((Elf32_Addr) me->module_core + me->arch.got_offset);
+ ((Elf_Addr) me->module_core + me->arch.got_offset);
if (r_type == R_390_GOTOFF16)
*(unsigned short *) loc = val;
else if (r_type == R_390_GOTOFF32)
*(unsigned int *) loc = val;
+ else if (r_type == R_390_GOTOFF64)
+ *(unsigned long *) loc = val;
break;
case R_390_GOTPC: /* 32 bit PC relative offset to GOT. */
case R_390_GOTPCDBL: /* 32 bit PC rel. off. to GOT shifted by 1. */
- val = (Elf32_Addr) me->module_core + me->arch.got_offset +
+ val = (Elf_Addr) me->module_core + me->arch.got_offset +
rela->r_addend - loc;
if (r_type == R_390_GOTPC)
*(unsigned int *) loc = val;
@@ -316,22 +353,23 @@
}

int
-apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
+apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
unsigned int symindex, unsigned int relsec,
struct module *me)
{
- Elf32_Addr base;
- Elf32_Sym *symtab;
- Elf32_Rela *rela;
+ Elf_Addr base;
+ Elf_Sym *symtab;
+ Elf_Rela *rela;
unsigned long i, n;
int rc;

DEBUGP("Applying relocate section %u to %u\n",
relsec, sechdrs[relsec].sh_info);
base = sechdrs[sechdrs[relsec].sh_info].sh_addr;
- symtab = (Elf32_Sym *) sechdrs[symindex].sh_addr;
- rela = (Elf32_Rela *) sechdrs[relsec].sh_addr;
- n = sechdrs[relsec].sh_size / sizeof(Elf32_Rela);
+ symtab = (Elf_Sym *) sechdrs[symindex].sh_addr;
+ rela = (Elf_Rela *) sechdrs[relsec].sh_addr;
+ n = sechdrs[relsec].sh_size / sizeof(Elf_Rela);
+
for (i = 0; i < n; i++, rela++) {
rc = apply_rela(rela, base, symtab, me);
if (rc)
diff -urN linux-2.5.67/arch/s390/kernel/process.c linux-2.5.67-s390/arch/s390/kernel/process.c
--- linux-2.5.67/arch/s390/kernel/process.c Mon Apr 7 19:32:19 2003
+++ linux-2.5.67-s390/arch/s390/kernel/process.c Mon Apr 14 19:11:56 2003
@@ -56,7 +56,11 @@
unsigned long bc;

bc = *((unsigned long *) tsk->thread.ksp);
+#ifndef CONFIG_ARCH_S390X
return *((unsigned long *) (bc+56));
+#else
+ return *((unsigned long *) (bc+112));
+#endif
}

/*
@@ -79,6 +83,7 @@
*/
wait_psw.mask = PSW_KERNEL_BITS | PSW_MASK_MCHECK | PSW_MASK_WAIT |
PSW_MASK_IO | PSW_MASK_EXT;
+#ifndef CONFIG_ARCH_S390X
asm volatile (
" basr %0,0\n"
"0: la %0,1f-0b(%0)\n"
@@ -92,6 +97,18 @@
" lpsw 0(%1)\n"
"2:"
: "=&a" (reg) : "a" (&wait_psw) : "memory", "cc" );
+#else /* CONFIG_ARCH_S390X */
+ asm volatile (
+ " larl %0,0f\n"
+ " stg %0,8(%1)\n"
+ " lpswe 0(%1)\n"
+ "0: larl %0,1f\n"
+ " stg %0,8(%1)\n"
+ " ni 1(%1),0xf9\n"
+ " lpswe 0(%1)\n"
+ "1:"
+ : "=&a" (reg) : "a" (&wait_psw) : "memory", "cc" );
+#endif /* CONFIG_ARCH_S390X */
}

int cpu_idle(void)
@@ -109,9 +126,9 @@
struct task_struct *tsk = current;

printk("CPU: %d %s\n", tsk->thread_info->cpu, print_tainted());
- printk("Process %s (pid: %d, task: %08lx, ksp: %08x)\n",
- current->comm, current->pid, (unsigned long) tsk,
- tsk->thread.ksp);
+ printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
+ current->comm, current->pid, (void *) tsk,
+ (void *) tsk->thread.ksp);

show_registers(regs);
/* Show stack backtrace if pt_regs is from kernel mode */
@@ -120,6 +137,9 @@
}

extern void kernel_thread_starter(void);
+
+#ifndef CONFIG_ARCH_S390X
+
__asm__(".align 4\n"
"kernel_thread_starter:\n"
" l 15,0(8)\n"
@@ -130,6 +150,20 @@
" sr 2,2\n"
" br 11\n");

+#else /* CONFIG_ARCH_S390X */
+
+__asm__(".align 4\n"
+ "kernel_thread_starter:\n"
+ " lg 15,0(8)\n"
+ " sgr 15,7\n"
+ " stosm 48(15),3\n"
+ " lgr 2,10\n"
+ " basr 14,9\n"
+ " sgr 2,2\n"
+ " br 11\n");
+
+#endif /* CONFIG_ARCH_S390X */
+
int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{
struct task_struct *p;
@@ -137,7 +171,7 @@

memset(&regs, 0, sizeof(regs));
regs.psw.mask = PSW_KERNEL_BITS;
- regs.psw.addr = (__u32) kernel_thread_starter | PSW_ADDR_AMODE31;
+ regs.psw.addr = (unsigned long) kernel_thread_starter | PSW_ADDR_AMODE;
regs.gprs[7] = STACK_FRAME_OVERHEAD;
regs.gprs[8] = __LC_KERNEL_STACK;
regs.gprs[9] = (unsigned long) fn;
@@ -180,8 +214,8 @@
unsigned long glue2;
unsigned long scratch[2];
unsigned long gprs[10]; /* gprs 6 -15 */
- unsigned long fprs[4]; /* fpr 4 and 6 */
- unsigned long empty[4];
+ unsigned int fprs[4]; /* fpr 4 and 6 */
+ unsigned int empty[4];
struct pt_regs childregs;
} *frame;

@@ -198,7 +232,8 @@
frame->gprs[8] = (unsigned long) ret_from_fork;

/* fake return stack for resume(), don't go back to schedule */
- frame->gprs[9] = (unsigned long) frame;
+ frame->gprs[9] = (unsigned long) frame;
+#ifndef CONFIG_ARCH_S390X
/*
* save fprs to current->thread.fp_regs to merge them with
* the emulated registers and then copy the result to the child.
@@ -207,14 +242,31 @@
memcpy(&p->thread.fp_regs, &current->thread.fp_regs,
sizeof(s390_fp_regs));
p->thread.user_seg = __pa((unsigned long) p->mm->pgd) | _SEGMENT_TABLE;
- /* start process with ar4 pointing to the correct address space */
+ /* Set a new TLS ? */
+ if (clone_flags & CLONE_SETTLS)
+ frame->childregs.acrs[0] = regs->gprs[6];
+#else /* CONFIG_ARCH_S390X */
+ /* Save the fpu registers to new thread structure. */
+ save_fp_regs(&p->thread.fp_regs);
+ p->thread.user_seg = __pa((unsigned long) p->mm->pgd) | _REGION_TABLE;
+ /* Set a new TLS ? */
+ if (clone_flags & CLONE_SETTLS) {
+ if (test_thread_flag(TIF_31BIT)) {
+ frame->childregs.acrs[0] =
+ (unsigned int) regs->gprs[6];
+ } else {
+ frame->childregs.acrs[0] =
+ (unsigned int)(regs->gprs[6] >> 32);
+ frame->childregs.acrs[1] =
+ (unsigned int) regs->gprs[6];
+ }
+ }
+#endif /* CONFIG_ARCH_S390X */
+ /* start new process with ar4 pointing to the correct address space */
p->thread.ar4 = get_fs().ar4;
/* Don't copy debug registers */
memset(&p->thread.per_info,0,sizeof(p->thread.per_info));

- /* Set a new TLS ? */
- if (clone_flags & CLONE_SETTLS)
- frame->childregs.acrs[0] = regs->gprs[6];
return 0;
}

@@ -292,12 +344,16 @@
*/
int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs)
{
+#ifndef CONFIG_ARCH_S390X
/*
* save fprs to current->thread.fp_regs to merge them with
* the emulated registers and then copy the result to the dump.
*/
save_fp_regs(&current->thread.fp_regs);
memcpy(fpregs, &current->thread.fp_regs, sizeof(s390_fp_regs));
+#else /* CONFIG_ARCH_S390X */
+ save_fp_regs(fpregs);
+#endif /* CONFIG_ARCH_S390X */
return 1;
}

@@ -339,16 +395,22 @@
return 0;
stack_page = (unsigned long) p->thread_info;
r15 = p->thread.ksp;
- if (!stack_page || r15 < stack_page || r15 >= 8188+stack_page)
- return 0;
- bc = (*(unsigned long *) r15) & 0x7fffffff;
+ if (!stack_page || r15 < stack_page ||
+ r15 >= THREAD_SIZE - sizeof(unsigned long) + stack_page)
+ return 0;
+ bc = (*(unsigned long *) r15) & PSW_ADDR_INSN;
do {
- if (bc < stack_page || bc >= 8188+stack_page)
- return 0;
- r14 = (*(unsigned long *) (bc+56)) & 0x7fffffff;
+ if (bc < stack_page ||
+ bc >= THREAD_SIZE - sizeof(unsigned long) + stack_page)
+ return 0;
+#ifndef CONFIG_ARCH_S390X
+ r14 = (*(unsigned long *) (bc+56)) & PSW_ADDR_INSN;
+#else
+ r14 = *(unsigned long *) (bc+112);
+#endif
if (r14 < first_sched || r14 >= last_sched)
return r14;
- bc = (*(unsigned long *) bc) & 0x7fffffff;
+ bc = (*(unsigned long *) bc) & PSW_ADDR_INSN;
} while (count++ < 16);
return 0;
}
diff -urN linux-2.5.67/arch/s390/kernel/ptrace.c linux-2.5.67-s390/arch/s390/kernel/ptrace.c
--- linux-2.5.67/arch/s390/kernel/ptrace.c Mon Apr 14 19:11:45 2003
+++ linux-2.5.67-s390/arch/s390/kernel/ptrace.c Mon Apr 14 19:11:56 2003
@@ -39,8 +39,12 @@
#include <asm/system.h>
#include <asm/uaccess.h>

+#ifdef CONFIG_S390_SUPPORT
+#include "compat_ptrace.h"
+#endif

-static void FixPerRegisters(struct task_struct *task)
+static void
+FixPerRegisters(struct task_struct *task)
{
struct pt_regs *regs;
per_struct *per_info;
@@ -52,7 +56,12 @@

if (per_info->single_step) {
per_info->control_regs.bits.starting_addr = 0;
- per_info->control_regs.bits.ending_addr = 0x7fffffffUL;
+#ifdef CONFIG_S390_SUPPORT
+ if (test_thread_flag(TIF_31BIT))
+ per_info->control_regs.bits.ending_addr = 0x7fffffffUL;
+ else
+#endif
+ per_info->control_regs.bits.ending_addr = PSW_ADDR_INSN;
} else {
per_info->control_regs.bits.starting_addr =
per_info->starting_addr;
@@ -74,13 +83,15 @@
per_info->control_regs.bits.storage_alt_space_ctl = 0;
}

-void set_single_step(struct task_struct *task)
+void
+set_single_step(struct task_struct *task)
{
task->thread.per_info.single_step = 1;
FixPerRegisters(task);
}

-void clear_single_step(struct task_struct *task)
+void
+clear_single_step(struct task_struct *task)
{
task->thread.per_info.single_step = 0;
FixPerRegisters(task);
@@ -91,12 +102,19 @@
*
* Make sure single step bits etc are not set.
*/
-void ptrace_disable(struct task_struct *child)
+void
+ptrace_disable(struct task_struct *child)
{
/* make sure the single step bit is not set. */
clear_single_step(child);
}

+#ifndef CONFIG_ARCH_S390X
+# define __ADDR_MASK 3
+#else
+# define __ADDR_MASK 7
+#endif
+
/*
* Read the word at offset addr from the user area of a process. The
* trouble here is that the information is littered over different
@@ -106,20 +124,20 @@
* struct user contain pad bytes that should be read as zeroes.
* Lovely...
*/
-static int peek_user(struct task_struct *child, addr_t addr, addr_t data)
+static int
+peek_user(struct task_struct *child, addr_t addr, addr_t data)
{
struct user *dummy = NULL;
- addr_t offset;
- __u32 tmp;
+ addr_t offset, tmp;

- if ((addr & 3) || addr > sizeof(struct user) - 3)
+ if ((addr & __ADDR_MASK) || addr > sizeof(struct user) - __ADDR_MASK)
return -EIO;

if (addr <= (addr_t) &dummy->regs.orig_gpr2) {
/*
* psw, gprs, acrs and orig_gpr2 are stored on the stack
*/
- tmp = *(__u32 *)((addr_t) __KSTK_PTREGS(child) + addr);
+ tmp = *(addr_t *)((addr_t) __KSTK_PTREGS(child) + addr);

} else if (addr >= (addr_t) &dummy->regs.fp_regs &&
addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
@@ -127,7 +145,7 @@
* floating point regs. are stored in the thread structure
*/
offset = addr - (addr_t) &dummy->regs.fp_regs;
- tmp = *(__u32 *)((addr_t) &child->thread.fp_regs + offset);
+ tmp = *(addr_t *)((addr_t) &child->thread.fp_regs + offset);

} else if (addr >= (addr_t) &dummy->regs.per_info &&
addr < (addr_t) (&dummy->regs.per_info + 1)) {
@@ -135,12 +153,12 @@
* per_info is found in the thread structure
*/
offset = addr - (addr_t) &dummy->regs.per_info;
- tmp = *(__u32 *)((addr_t) &child->thread.per_info + offset);
+ tmp = *(addr_t *)((addr_t) &child->thread.per_info + offset);

} else
tmp = 0;

- return put_user(tmp, (__u32 *) data);
+ return put_user(tmp, (addr_t *) data);
}

/*
@@ -149,12 +167,13 @@
* Stores to the program status word and on the floating point
* control register needs to get checked for validity.
*/
-static int poke_user(struct task_struct *child, addr_t addr, addr_t data)
+static int
+poke_user(struct task_struct *child, addr_t addr, addr_t data)
{
struct user *dummy = NULL;
addr_t offset;

- if ((addr & 3) || addr > sizeof(struct user) - 3)
+ if ((addr & __ADDR_MASK) || addr > sizeof(struct user) - __ADDR_MASK)
return -EIO;

if (addr <= (addr_t) &dummy->regs.orig_gpr2) {
@@ -162,14 +181,19 @@
* psw, gprs, acrs and orig_gpr2 are stored on the stack
*/
if (addr == (addr_t) &dummy->regs.psw.mask &&
+#ifdef CONFIG_S390_SUPPORT
+ (data & ~PSW_MASK_CC) != PSW_USER32_BITS &&
+#endif
(data & ~PSW_MASK_CC) != PSW_USER_BITS)
/* Invalid psw mask. */
return -EINVAL;
+#ifndef CONFIG_ARCH_S390X
if (addr == (addr_t) &dummy->regs.psw.addr)
/* I'd like to reject addresses without the
high order bit but older gdb's rely on it */
- data |= PSW_ADDR_AMODE31;
- *(__u32 *)((addr_t) __KSTK_PTREGS(child) + addr) = data;
+ data |= PSW_ADDR_AMODE;
+#endif
+ *(addr_t *)((addr_t) __KSTK_PTREGS(child) + addr) = data;

} else if (addr >= (addr_t) &dummy->regs.fp_regs &&
addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
@@ -180,7 +204,7 @@
(data & ~FPC_VALID_MASK) != 0)
return -EINVAL;
offset = addr - (addr_t) &dummy->regs.fp_regs;
- *(__u32 *)((addr_t) &child->thread.fp_regs + offset) = data;
+ *(addr_t *)((addr_t) &child->thread.fp_regs + offset) = data;

} else if (addr >= (addr_t) &dummy->regs.per_info &&
addr < (addr_t) (&dummy->regs.per_info + 1)) {
@@ -188,7 +212,7 @@
* per_info is found in the thread structure
*/
offset = addr - (addr_t) &dummy->regs.per_info;
- *(__u32 *)((addr_t) &child->thread.per_info + offset) = data;
+ *(addr_t *)((addr_t) &child->thread.per_info + offset) = data;

}

@@ -197,33 +221,16 @@
}

static int
-do_ptrace(struct task_struct *child, long request, long addr, long data)
+do_ptrace_normal(struct task_struct *child, long request, long addr, long data)
{
unsigned long tmp;
ptrace_area parea;
int copied, ret;

- if (request == PTRACE_ATTACH)
- return ptrace_attach(child);
-
- /*
- * Special cases to get/store the ieee instructions pointer.
- */
- if (child == current) {
- if (request == PTRACE_PEEKUSR && addr == PT_IEEE_IP)
- return peek_user(child, addr, data);
- if (request == PTRACE_POKEUSR && addr == PT_IEEE_IP)
- return poke_user(child, addr, data);
- }
-
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret < 0)
- return ret;
-
switch (request) {
case PTRACE_PEEKTEXT:
case PTRACE_PEEKDATA:
- /* Remove high order bit from address. */
+ /* Remove high order bit from address (only for 31 bit). */
addr &= PSW_ADDR_INSN;
/* read word at location addr. */
copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
@@ -237,7 +244,7 @@

case PTRACE_POKETEXT:
case PTRACE_POKEDATA:
- /* Remove high order bit from address. */
+ /* Remove high order bit from address (only for 31 bit). */
addr &= PSW_ADDR_INSN;
/* write the word at location addr. */
copied = access_process_vm(child, addr, &data, sizeof(data),1);
@@ -249,6 +256,272 @@
/* write the word at location addr in the USER area */
return poke_user(child, addr, data);

+ case PTRACE_PEEKUSR_AREA:
+ case PTRACE_POKEUSR_AREA:
+ if (!copy_from_user(&parea, (void *) addr, sizeof(parea)))
+ return -EFAULT;
+ addr = parea.kernel_addr;
+ data = parea.process_addr;
+ copied = 0;
+ while (copied < parea.len) {
+ if (request == PTRACE_PEEKUSR_AREA)
+ ret = peek_user(child, addr, data);
+ else
+ ret = poke_user(child, addr, data);
+ if (ret)
+ return ret;
+ addr += sizeof(unsigned long);
+ data += sizeof(unsigned long);
+ copied += sizeof(unsigned long);
+ }
+ return 0;
+ }
+ return ptrace_request(child, request, addr, data);
+}
+
+#ifdef CONFIG_S390_SUPPORT
+/*
+ * Now the fun part starts... a 31 bit program running in the
+ * 31 bit emulation tracing another program. PTRACE_PEEKTEXT,
+ * PTRACE_PEEKDATA, PTRACE_POKETEXT and PTRACE_POKEDATA are easy
+ * to handle, the difference to the 64 bit versions of the requests
+ * is that the access is done in multiples of 4 byte instead of
+ * 8 bytes (sizeof(unsigned long) on 31/64 bit).
+ * The ugly part are PTRACE_PEEKUSR, PTRACE_PEEKUSR_AREA,
+ * PTRACE_POKEUSR and PTRACE_POKEUSR_AREA. If the traced program
+ * is a 31 bit program too, the content of struct user can be
+ * emulated. A 31 bit program peeking into the struct user of
+ * a 64 bit program is a no-no.
+ */
+
+/*
+ * Same as peek_user but for a 31 bit program.
+ */
+static int
+peek_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
+{
+ struct user32 *dummy32 = NULL;
+ per_struct32 *dummy_per32 = NULL;
+ addr_t offset;
+ __u32 tmp;
+
+ if (!test_thread_flag(TIF_31BIT) ||
+ (addr & 3) || addr > sizeof(struct user) - 3)
+ return -EIO;
+
+ if (addr <= (addr_t) &dummy32->regs.orig_gpr2) {
+ /*
+ * psw, gprs, acrs and orig_gpr2 are stored on the stack
+ */
+ if (addr == (addr_t) &dummy32->regs.psw.mask) {
+ /* Fake a 31 bit psw mask. */
+ tmp = (__u32)(__KSTK_PTREGS(child)->psw.mask >> 32);
+ tmp = (tmp & PSW32_MASK_CC) | PSW32_USER_BITS;
+ } else if (addr == (addr_t) &dummy32->regs.psw.addr) {
+ /* Fake a 31 bit psw address. */
+ tmp = (__u32) __KSTK_PTREGS(child)->psw.addr |
+ PSW32_ADDR_AMODE31;
+ } else
+ tmp = *(__u32 *)((addr_t) __KSTK_PTREGS(child) +
+ addr*2 + 4);
+ } else if (addr >= (addr_t) &dummy32->regs.fp_regs &&
+ addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
+ /*
+ * floating point regs. are stored in the thread structure
+ */
+ offset = addr - (addr_t) &dummy32->regs.fp_regs;
+ tmp = *(__u32 *)((addr_t) &child->thread.fp_regs + offset);
+
+ } else if (addr >= (addr_t) &dummy32->regs.per_info &&
+ addr < (addr_t) (&dummy32->regs.per_info + 1)) {
+ /*
+ * per_info is found in the thread structure
+ */
+ offset = addr - (addr_t) &dummy32->regs.per_info;
+ /* This is magic. See per_struct and per_struct32. */
+ if ((offset >= (addr_t) &dummy_per32->control_regs &&
+ offset < (addr_t) (&dummy_per32->control_regs + 1)) ||
+ (offset >= (addr_t) &dummy_per32->starting_addr &&
+ offset <= (addr_t) &dummy_per32->ending_addr) ||
+ offset == (addr_t) &dummy_per32->lowcore.words.address)
+ offset = offset*2 + 4;
+ else
+ offset = offset*2;
+ tmp = *(__u32 *)((addr_t) &child->thread.per_info + offset);
+
+ } else
+ tmp = 0;
+
+ return put_user(tmp, (__u32 *) data);
+}
+
+/*
+ * Same as poke_user but for a 31 bit program.
+ */
+static int
+poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
+{
+ struct user32 *dummy32 = NULL;
+ per_struct32 *dummy_per32 = NULL;
+ addr_t offset;
+ __u32 tmp;
+
+ if (!test_thread_flag(TIF_31BIT) ||
+ (addr & 3) || addr > sizeof(struct user32) - 3)
+ return -EIO;
+
+ tmp = (__u32) data;
+
+ if (addr <= (addr_t) &dummy32->regs.orig_gpr2) {
+ /*
+ * psw, gprs, acrs and orig_gpr2 are stored on the stack
+ */
+ if (addr == (addr_t) &dummy32->regs.psw.mask) {
+ /* Build a 64 bit psw mask from 31 bit mask. */
+ if ((tmp & ~PSW32_MASK_CC) != PSW32_USER_BITS)
+ /* Invalid psw mask. */
+ return -EINVAL;
+ __KSTK_PTREGS(child)->psw.mask = PSW_USER_BITS |
+ ((tmp & PSW32_MASK_CC) << 32);
+ } else if (addr == (addr_t) &dummy32->regs.psw.addr) {
+ /* Build a 64 bit psw address from 31 bit address. */
+ __KSTK_PTREGS(child)->psw.addr =
+ (__u64) tmp & PSW32_ADDR_INSN;
+ } else
+ *(__u32*)((addr_t) __KSTK_PTREGS(child) + addr*2 + 4) =
+ tmp;
+ } else if (addr >= (addr_t) &dummy32->regs.fp_regs &&
+ addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
+ /*
+ * floating point regs. are stored in the thread structure
+ */
+ if (addr == (addr_t) &dummy32->regs.fp_regs.fpc &&
+ (tmp & ~FPC_VALID_MASK) != 0)
+ /* Invalid floating point control. */
+ return -EINVAL;
+ offset = addr - (addr_t) &dummy32->regs.fp_regs;
+ *(__u32 *)((addr_t) &child->thread.fp_regs + offset) = tmp;
+
+ } else if (addr >= (addr_t) &dummy32->regs.per_info &&
+ addr < (addr_t) (&dummy32->regs.per_info + 1)) {
+ /*
+ * per_info is found in the thread structure.
+ */
+ offset = addr - (addr_t) &dummy32->regs.per_info;
+ /*
+ * This is magic. See per_struct and per_struct32.
+ * By incident the offsets in per_struct are exactly
+ * twice the offsets in per_struct32 for all fields.
+ * The 8 byte fields need special handling though,
+ * because the second half (bytes 4-7) is needed and
+ * not the first half.
+ */
+ if ((offset >= (addr_t) &dummy_per32->control_regs &&
+ offset < (addr_t) (&dummy_per32->control_regs + 1)) ||
+ (offset >= (addr_t) &dummy_per32->starting_addr &&
+ offset <= (addr_t) &dummy_per32->ending_addr) ||
+ offset == (addr_t) &dummy_per32->lowcore.words.address)
+ offset = offset*2 + 4;
+ else
+ offset = offset*2;
+ *(__u32 *)((addr_t) &child->thread.per_info + offset) = tmp;
+
+ }
+
+ FixPerRegisters(child);
+ return 0;
+}
+
+static int
+do_ptrace_emu31(struct task_struct *child, long request, long addr, long data)
+{
+ unsigned int tmp; /* 4 bytes !! */
+ ptrace_area_emu31 parea;
+ int copied, ret;
+
+ switch (request) {
+ case PTRACE_PEEKTEXT:
+ case PTRACE_PEEKDATA:
+ /* read word at location addr. */
+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ if (copied != sizeof(tmp))
+ return -EIO;
+ return put_user(tmp, (unsigned int *) data);
+
+ case PTRACE_PEEKUSR:
+ /* read the word at location addr in the USER area. */
+ return peek_user_emu31(child, addr, data);
+
+ case PTRACE_POKETEXT:
+ case PTRACE_POKEDATA:
+ /* write the word at location addr. */
+ tmp = data;
+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 1);
+ if (copied != sizeof(tmp))
+ return -EIO;
+ return 0;
+
+ case PTRACE_POKEUSR:
+ /* write the word at location addr in the USER area */
+ return poke_user_emu31(child, addr, data);
+
+ case PTRACE_PEEKUSR_AREA:
+ case PTRACE_POKEUSR_AREA:
+ if (!copy_from_user(&parea, (void *) addr, sizeof(parea)))
+ return -EFAULT;
+ addr = parea.kernel_addr;
+ data = parea.process_addr;
+ copied = 0;
+ while (copied < parea.len) {
+ if (request == PTRACE_PEEKUSR_AREA)
+ ret = peek_user_emu31(child, addr, data);
+ else
+ ret = poke_user_emu31(child, addr, data);
+ if (ret)
+ return ret;
+ addr += sizeof(unsigned int);
+ data += sizeof(unsigned int);
+ copied += sizeof(unsigned int);
+ }
+ return 0;
+ }
+ return ptrace_request(child, request, addr, data);
+}
+#endif
+
+#define PT32_IEEE_IP 0x13c
+
+static int
+do_ptrace(struct task_struct *child, long request, long addr, long data)
+{
+ int ret;
+
+ if (request == PTRACE_ATTACH)
+ return ptrace_attach(child);
+
+ /*
+ * Special cases to get/store the ieee instructions pointer.
+ */
+ if (child == current) {
+ if (request == PTRACE_PEEKUSR && addr == PT_IEEE_IP)
+ return peek_user(child, addr, data);
+ if (request == PTRACE_POKEUSR && addr == PT_IEEE_IP)
+ return poke_user(child, addr, data);
+#ifdef CONFIG_S390_SUPPORT
+ if (request == PTRACE_PEEKUSR &&
+ addr == PT32_IEEE_IP && test_thread_flag(TIF_31BIT))
+ return peek_user_emu31(child, addr, data);
+ if (request == PTRACE_POKEUSR &&
+ addr == PT32_IEEE_IP && test_thread_flag(TIF_31BIT))
+ return poke_user_emu31(child, addr, data);
+#endif
+ }
+
+ ret = ptrace_check_attach(child, request == PTRACE_KILL);
+ if (ret < 0)
+ return ret;
+
+ switch (request) {
case PTRACE_SYSCALL:
/* continue and stop at next (return from) syscall */
case PTRACE_CONT:
@@ -294,30 +567,21 @@
/* detach a process that was attached. */
return ptrace_detach(child, data);

- case PTRACE_PEEKUSR_AREA:
- case PTRACE_POKEUSR_AREA:
- if (!copy_from_user(&parea, (void *) addr, sizeof(parea)))
- return -EFAULT;
- addr = parea.kernel_addr;
- data = parea.process_addr;
- copied = 0;
- while (copied < parea.len) {
- if (request == PTRACE_PEEKUSR_AREA)
- ret = peek_user(child, addr, data);
- else
- ret = poke_user(child, addr, data);
- if (ret)
- return ret;
- addr += sizeof(unsigned long);
- data += sizeof(unsigned long);
- copied += sizeof(unsigned long);
- }
- return 0;
+
+ /* Do requests that differ for 31/64 bit */
+ default:
+#ifdef CONFIG_S390_SUPPORT
+ if (test_thread_flag(TIF_31BIT))
+ return do_ptrace_emu31(child, request, addr, data);
+#endif
+ return do_ptrace_normal(child, request, addr, data);
}
- return ptrace_request(child, request, addr, data);
+ /* Not reached. */
+ return -EIO;
}

-asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+asmlinkage int
+sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
int ret;
@@ -358,7 +622,8 @@
return ret;
}

-asmlinkage void syscall_trace(void)
+asmlinkage void
+syscall_trace(void)
{
if (!test_thread_flag(TIF_SYSCALL_TRACE))
return;
diff -urN linux-2.5.67/arch/s390/kernel/reipl64.S linux-2.5.67-s390/arch/s390/kernel/reipl64.S
--- linux-2.5.67/arch/s390/kernel/reipl64.S Thu Jan 1 01:00:00 1970
+++ linux-2.5.67-s390/arch/s390/kernel/reipl64.S Mon Apr 14 19:11:56 2003
@@ -0,0 +1,96 @@
+/*
+ * arch/s390/kernel/reipl.S
+ *
+ * S390 version
+ * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com)
+ Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ */
+
+#include <asm/lowcore.h>
+ .globl do_reipl
+do_reipl: basr %r13,0
+.Lpg0: lpswe .Lnewpsw-.Lpg0(%r13)
+.Lpg1: lctlg %c6,%c6,.Lall-.Lpg0(%r13)
+ stctg %c0,%c0,.Lctlsave-.Lpg0(%r13)
+ ni .Lctlsave+4-.Lpg0(%r13),0xef
+ lctlg %c0,%c0,.Lctlsave-.Lpg0(%r13)
+ lgr %r1,%r2
+ mvc __LC_PGM_NEW_PSW(16),.Lpcnew-.Lpg0(%r13)
+ stsch .Lschib-.Lpg0(%r13)
+ oi .Lschib+5-.Lpg0(%r13),0x84
+.Lecs: xi .Lschib+27-.Lpg0(%r13),0x01
+ msch .Lschib-.Lpg0(%r13)
+ lghi %r0,5
+.Lssch: ssch .Liplorb-.Lpg0(%r13)
+ jz .L001
+ brct %r0,.Lssch
+ bas %r14,.Ldisab-.Lpg0(%r13)
+.L001: mvc __LC_IO_NEW_PSW(16),.Lionew-.Lpg0(%r13)
+.Ltpi: lpswe .Lwaitpsw-.Lpg0(%r13)
+.Lcont: c %r1,__LC_SUBCHANNEL_ID
+ jnz .Ltpi
+ clc __LC_IO_INT_PARM(4),.Liplorb-.Lpg0(%r13)
+ jnz .Ltpi
+ tsch .Liplirb-.Lpg0(%r13)
+ tm .Liplirb+9-.Lpg0(%r13),0xbf
+ jz .L002
+ bas %r14,.Ldisab-.Lpg0(%r13)
+.L002: tm .Liplirb+8-.Lpg0(%r13),0xf3
+ jz .L003
+ bas %r14,.Ldisab-.Lpg0(%r13)
+.L003: spx .Lnull-.Lpg0(%r13)
+ st %r1,__LC_SUBCHANNEL_ID
+ lhi %r1,0 # mode 0 = esa
+ slr %r0,%r0 # set cpuid to zero
+ sigp %r1,%r0,0x12 # switch to esa mode
+ lpsw 0
+.Ldisab: sll %r14,1
+ srl %r14,1 # need to kill hi bit to avoid specification exceptions.
+ st %r14,.Ldispsw+12-.Lpg0(%r13)
+ lpswe .Ldispsw-.Lpg0(%r13)
+ .align 8
+.Lall: .quad 0x00000000ff000000
+.Lctlsave: .quad 0x0000000000000000
+.Lnull: .long 0x0000000000000000
+ .align 16
+/*
+ * These addresses have to be 31 bit otherwise
+ * the sigp will throw a specifcation exception
+ * when switching to ESA mode as bit 31 be set
+ * in the ESA psw.
+ * Bit 31 of the addresses has to be 0 for the
+ * 31bit lpswe instruction a fact they appear to have
+ * ommited from the pop.
+ */
+.Lnewpsw: .quad 0x0000000080000000
+ .quad .Lpg1
+.Lpcnew: .quad 0x0000000080000000
+ .quad .Lecs
+.Lionew: .quad 0x0000000080000000
+ .quad .Lcont
+.Lwaitpsw: .quad 0x0202000080000000
+ .quad .Ltpi
+.Ldispsw: .quad 0x0002000080000000
+ .quad 0x0000000000000000
+.Liplccws: .long 0x02000000,0x60000018
+ .long 0x08000008,0x20000001
+.Liplorb: .long 0x0049504c,0x0040ff80
+ .long 0x00000000+.Liplccws
+.Lschib: .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+.Liplirb: .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+ .long 0x00000000,0x00000000
+
+
+
diff -urN linux-2.5.67/arch/s390/kernel/s390_ksyms.c linux-2.5.67-s390/arch/s390/kernel/s390_ksyms.c
--- linux-2.5.67/arch/s390/kernel/s390_ksyms.c Mon Apr 7 19:31:51 2003
+++ linux-2.5.67-s390/arch/s390/kernel/s390_ksyms.c Mon Apr 14 19:11:56 2003
@@ -4,11 +4,14 @@
* S390 version
*/
#include <linux/config.h>
+#include <linux/highuid.h>
#include <linux/module.h>
+#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/interrupt.h>
#include <asm/checksum.h>
#include <asm/delay.h>
+#include <asm/pgalloc.h>
#include <asm/setup.h>
#if CONFIG_IP_MULTICAST
#include <net/arp.h>
@@ -50,6 +53,28 @@
EXPORT_SYMBOL_NOVERS(strpbrk);

/*
+ * binfmt_elf loader
+ */
+extern int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs);
+EXPORT_SYMBOL(dump_fpu);
+EXPORT_SYMBOL(overflowuid);
+EXPORT_SYMBOL(overflowgid);
+
+#ifdef CONFIG_S390_SUPPORT
+/*
+ * Dynamically add/remove 31 bit ioctl conversion functions.
+ */
+extern int register_ioctl32_conversion(unsigned int cmd,
+ int (*handler)(unsigned int,
+ unsigned int,
+ unsigned long,
+ struct file *));
+int unregister_ioctl32_conversion(unsigned int cmd);
+EXPORT_SYMBOL(register_ioctl32_conversion);
+EXPORT_SYMBOL(unregister_ioctl32_conversion);
+#endif
+
+/*
* misc.
*/
EXPORT_SYMBOL(machine_flags);
diff -urN linux-2.5.67/arch/s390/kernel/setup.c linux-2.5.67-s390/arch/s390/kernel/setup.c
--- linux-2.5.67/arch/s390/kernel/setup.c Mon Apr 14 19:11:52 2003
+++ linux-2.5.67-s390/arch/s390/kernel/setup.c Mon Apr 14 19:11:56 2003
@@ -324,15 +324,22 @@
/*
* print what head.S has found out about the machine
*/
+#ifndef CONFIG_ARCH_S390X
printk((MACHINE_IS_VM) ?
"We are running under VM (31 bit mode)\n" :
"We are running native (31 bit mode)\n");
printk((MACHINE_HAS_IEEE) ?
"This machine has an IEEE fpu\n" :
"This machine has no IEEE fpu\n");
+#else /* CONFIG_ARCH_S390X */
+ printk((MACHINE_IS_VM) ?
+ "We are running under VM (64 bit mode)\n" :
+ "We are running native (64 bit mode)\n");
+#endif /* CONFIG_ARCH_S390X */

ROOT_DEV = Root_RAM0;
memory_start = (unsigned long) &_end; /* fixit if use $CODELO etc*/
+#ifndef CONFIG_ARCH_S390X
memory_end = memory_size & ~0x400000UL; /* align memory end to 4MB */
/*
* We need some free virtual space to be able to do vmalloc.
@@ -341,6 +348,9 @@
*/
if (memory_end > 1920*1024*1024)
memory_end = 1920*1024*1024;
+#else /* CONFIG_ARCH_S390X */
+ memory_end = memory_size & ~0x200000UL; /* detected in head.s */
+#endif /* CONFIG_ARCH_S390X */
init_mm.start_code = PAGE_OFFSET;
init_mm.end_code = (unsigned long) &_etext;
init_mm.end_data = (unsigned long) &_edata;
@@ -461,26 +471,46 @@
/*
* Setup lowcore for boot cpu
*/
+#ifndef CONFIG_ARCH_S390X
lc = (struct _lowcore *) __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0);
memset(lc, 0, PAGE_SIZE);
+#else /* CONFIG_ARCH_S390X */
+ lc = (struct _lowcore *) __alloc_bootmem(2*PAGE_SIZE, 2*PAGE_SIZE, 0);
+ memset(lc, 0, 2*PAGE_SIZE);
+#endif /* CONFIG_ARCH_S390X */
lc->restart_psw.mask = PSW_BASE_BITS;
- lc->restart_psw.addr = PSW_ADDR_AMODE31 + (__u32) restart_int_handler;
+ lc->restart_psw.addr =
+ PSW_ADDR_AMODE + (unsigned long) restart_int_handler;
lc->external_new_psw.mask = PSW_KERNEL_BITS;
- lc->external_new_psw.addr = PSW_ADDR_AMODE31 + (__u32) ext_int_handler;
+ lc->external_new_psw.addr =
+ PSW_ADDR_AMODE + (unsigned long) ext_int_handler;
lc->svc_new_psw.mask = PSW_KERNEL_BITS;
- lc->svc_new_psw.addr = PSW_ADDR_AMODE31 + (__u32) system_call;
+ lc->svc_new_psw.addr = PSW_ADDR_AMODE + (unsigned long) system_call;
lc->program_new_psw.mask = PSW_KERNEL_BITS;
- lc->program_new_psw.addr = PSW_ADDR_AMODE31 + (__u32)pgm_check_handler;
- lc->mcck_new_psw.mask = PSW_KERNEL_BITS;
- lc->mcck_new_psw.addr = PSW_ADDR_AMODE31 + (__u32) mcck_int_handler;
+ lc->program_new_psw.addr =
+ PSW_ADDR_AMODE + (unsigned long)pgm_check_handler;
+ lc->mcck_new_psw.mask = PSW_KERNEL_BITS;
+ lc->mcck_new_psw.addr =
+ PSW_ADDR_AMODE + (unsigned long) mcck_int_handler;
lc->io_new_psw.mask = PSW_KERNEL_BITS;
- lc->io_new_psw.addr = PSW_ADDR_AMODE31 + (__u32) io_int_handler;
+ lc->io_new_psw.addr = PSW_ADDR_AMODE + (unsigned long) io_int_handler;
lc->ipl_device = S390_lowcore.ipl_device;
+ lc->jiffy_timer = -1LL;
+#ifndef CONFIG_ARCH_S390X
lc->kernel_stack = ((__u32) &init_thread_union) + 8192;
lc->async_stack = (__u32)
__alloc_bootmem(2*PAGE_SIZE, 2*PAGE_SIZE, 0) + 8192;
- lc->jiffy_timer = -1LL;
set_prefix((__u32) lc);
+#else /* CONFIG_ARCH_S390X */
+ lc->kernel_stack = ((__u64) &init_thread_union) + 16384;
+ lc->async_stack = (__u64)
+ __alloc_bootmem(4*PAGE_SIZE, 4*PAGE_SIZE, 0) + 16384;
+ if (MACHINE_HAS_DIAG44)
+ lc->diag44_opcode = 0x83000044;
+ else
+ lc->diag44_opcode = 0x07000700;
+ set_prefix((__u32)(__u64) lc);
+#endif /* CONFIG_ARCH_S390X */
cpu_init();
__cpu_logical_map[0] = S390_lowcore.cpu_data.cpu_addr;

diff -urN linux-2.5.67/arch/s390/kernel/signal.c linux-2.5.67-s390/arch/s390/kernel/signal.c
--- linux-2.5.67/arch/s390/kernel/signal.c Mon Apr 14 19:11:52 2003
+++ linux-2.5.67-s390/arch/s390/kernel/signal.c Mon Apr 14 19:11:56 2003
@@ -146,7 +146,7 @@


/* Returns non-zero on fault. */
-static int save_sigregs(struct pt_regs *regs,_sigregs *sregs)
+static int save_sigregs(struct pt_regs *regs, _sigregs *sregs)
{
int err;

@@ -158,18 +158,18 @@
* to merge them with the emulated registers.
*/
save_fp_regs(&current->thread.fp_regs);
- return __copy_to_user(&sregs->fpregs, &current->thread.fp_regs,
+ return __copy_to_user(&sregs->fpregs, &current->thread.fp_regs,
sizeof(s390_fp_regs));
}

/* Returns positive number on error */
-static int restore_sigregs(struct pt_regs *regs,_sigregs *sregs)
+static int restore_sigregs(struct pt_regs *regs, _sigregs *sregs)
{
int err;

err = __copy_from_user(regs, &sregs->regs, sizeof(_s390_regs_common));
regs->psw.mask = PSW_USER_BITS | (regs->psw.mask & PSW_MASK_CC);
- regs->psw.addr |= PSW_ADDR_AMODE31;
+ regs->psw.addr |= PSW_ADDR_AMODE;
if (err)
return err;

@@ -299,9 +299,11 @@
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
- regs->gprs[14] = (__u32) ka->sa.sa_restorer | PSW_ADDR_AMODE31;
+ regs->gprs[14] = (unsigned long)
+ ka->sa.sa_restorer | PSW_ADDR_AMODE;
} else {
- regs->gprs[14] = (__u32) frame->retcode | PSW_ADDR_AMODE31;
+ regs->gprs[14] = (unsigned long)
+ frame->retcode | PSW_ADDR_AMODE;
if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
(u16 *)(frame->retcode)))
goto give_sigsegv;
@@ -312,12 +314,12 @@
goto give_sigsegv;

/* Set up registers for signal handler */
- regs->gprs[15] = (__u32) frame;
- regs->psw.addr = (__u32) ka->sa.sa_handler | PSW_ADDR_AMODE31;
+ regs->gprs[15] = (unsigned long) frame;
+ regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
regs->psw.mask = PSW_USER_BITS;

regs->gprs[2] = map_signal(sig);
- regs->gprs[3] = (__u32) &frame->sc;
+ regs->gprs[3] = (unsigned long) &frame->sc;

/* We forgot to include these in the sigcontext.
To avoid breaking binary compatibility, they are passed as args. */
@@ -357,9 +359,11 @@
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
- regs->gprs[14] = (__u32) ka->sa.sa_restorer | PSW_ADDR_AMODE31;
+ regs->gprs[14] = (unsigned long)
+ ka->sa.sa_restorer | PSW_ADDR_AMODE;
} else {
- regs->gprs[14] = (__u32) frame->retcode | PSW_ADDR_AMODE31;
+ regs->gprs[14] = (unsigned long)
+ frame->retcode | PSW_ADDR_AMODE;
err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
(u16 *)(frame->retcode));
}
@@ -369,13 +373,13 @@
goto give_sigsegv;

/* Set up registers for signal handler */
- regs->gprs[15] = (__u32) frame;
- regs->psw.addr = (__u32) ka->sa.sa_handler | PSW_ADDR_AMODE31;
+ regs->gprs[15] = (unsigned long) frame;
+ regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
regs->psw.mask = PSW_USER_BITS;

regs->gprs[2] = map_signal(sig);
- regs->gprs[3] = (__u32) &frame->info;
- regs->gprs[4] = (__u32) &frame->uc;
+ regs->gprs[3] = (unsigned long) &frame->info;
+ regs->gprs[4] = (unsigned long) &frame->uc;
return;

give_sigsegv:
@@ -461,6 +465,13 @@

if (!oldset)
oldset = &current->blocked;
+#ifdef CONFIG_S390_SUPPORT
+ if (test_thread_flag(TIF_31BIT)) {
+ extern asmlinkage int do_signal32(struct pt_regs *regs,
+ sigset_t *oldset);
+ return do_signal32(regs, oldset);
+ }
+#endif

signr = get_signal_to_deliver(&info, regs, NULL);
if (signr > 0) {
diff -urN linux-2.5.67/arch/s390/kernel/smp.c linux-2.5.67-s390/arch/s390/kernel/smp.c
--- linux-2.5.67/arch/s390/kernel/smp.c Mon Apr 7 19:30:34 2003
+++ linux-2.5.67-s390/arch/s390/kernel/smp.c Mon Apr 14 19:11:56 2003
@@ -171,7 +171,7 @@

/* store status of all processors in their lowcores (real 0) */
for (i = 0; i < NR_CPUS; i++) {
- if (!cpu_online(i) || smp_processor_id() == i)
+ if (!cpu_online(i) || smp_processor_id() == i)
continue;
low_core_addr = (unsigned long) lowcore_ptr[i];
do {
@@ -310,13 +310,11 @@
*/
static void smp_ext_bitcall_others(ec_bit_sig sig)
{
- struct _lowcore *lowcore;
int i;

for (i = 0; i < NR_CPUS; i++) {
if (!cpu_online(i) || smp_processor_id() == i)
continue;
- lowcore = lowcore_ptr[i];
/*
* Set signaling bit in lowcore of target cpu and kick it
*/
@@ -326,6 +324,7 @@
}
}

+#ifndef CONFIG_ARCH_S390X
/*
* this function sends a 'purge tlb' signal to another CPU.
*/
@@ -338,6 +337,7 @@
{
on_each_cpu(smp_ptlb_callback, NULL, 0, 1);
}
+#endif /* ! CONFIG_ARCH_S390X */

/*
* this function sends a 'reschedule' IPI to another CPU.
@@ -356,8 +356,8 @@
{
__u16 start_ctl;
__u16 end_ctl;
- __u32 orvals[16];
- __u32 andvals[16];
+ unsigned long orvals[16];
+ unsigned long andvals[16];
} ec_creg_mask_parms;

/*
@@ -365,25 +365,14 @@
*/
void smp_ctl_bit_callback(void *info) {
ec_creg_mask_parms *pp;
- u32 cregs[16];
+ unsigned long cregs[16];
int i;

pp = (ec_creg_mask_parms *) info;
- asm volatile (" bras 1,0f\n"
- " stctl 0,0,0(%0)\n"
- "0: ex %1,0(1)\n"
- : : "a" (cregs+pp->start_ctl),
- "a" ((pp->start_ctl<<4) + pp->end_ctl)
- : "memory", "1" );
+ __ctl_store(cregs[pp->start_ctl], pp->start_ctl, pp->end_ctl);
for (i = pp->start_ctl; i <= pp->end_ctl; i++)
cregs[i] = (cregs[i] & pp->andvals[i]) | pp->orvals[i];
- asm volatile (" bras 1,0f\n"
- " lctl 0,0,0(%0)\n"
- "0: ex %1,0(1)\n"
- : : "a" (cregs+pp->start_ctl),
- "a" ((pp->start_ctl<<4) + pp->end_ctl)
- : "memory", "1" );
- return;
+ __ctl_load(cregs[pp->start_ctl], pp->start_ctl, pp->end_ctl);
}

/*
@@ -395,7 +384,7 @@
parms.start_ctl = cr;
parms.end_ctl = cr;
parms.orvals[cr] = 1 << bit;
- parms.andvals[cr] = 0xFFFFFFFF;
+ parms.andvals[cr] = -1L;
preempt_disable();
smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
__ctl_set_bit(cr, bit);
@@ -410,8 +399,8 @@

parms.start_ctl = cr;
parms.end_ctl = cr;
- parms.orvals[cr] = 0x00000000;
- parms.andvals[cr] = ~(1 << bit);
+ parms.orvals[cr] = 0;
+ parms.andvals[cr] = ~(1L << bit);
preempt_disable();
smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
__ctl_clear_bit(cr, bit);
@@ -493,7 +482,7 @@
* Set prefix page for new cpu
*/

- ccode = signal_processor_p((u32)(lowcore_ptr[cpu]),
+ ccode = signal_processor_p((unsigned long)(lowcore_ptr[cpu]),
cpu, sigp_set_prefix);
if (ccode){
printk("sigp_set_prefix failed for cpu %d "
@@ -502,7 +491,6 @@
return -EIO;
}

-
/* We can't use kernel_thread since we must _avoid_ to reschedule
the child. */
idle = fork_by_hand();
@@ -521,15 +509,13 @@

cpu_lowcore = lowcore_ptr[cpu];
cpu_lowcore->save_area[15] = idle->thread.ksp;
- cpu_lowcore->kernel_stack = (__u32) idle->thread_info + (2*PAGE_SIZE);
- __asm__ __volatile__("la 1,%0\n\t"
- "stctl 0,15,0(1)\n\t"
- "la 1,%1\n\t"
- "stam 0,15,0(1)"
- : "=m" (cpu_lowcore->cregs_save_area[0]),
- "=m" (cpu_lowcore->access_regs_save_area[0])
- : : "1", "memory");
-
+ cpu_lowcore->kernel_stack = (unsigned long)
+ idle->thread_info + (THREAD_SIZE);
+ __ctl_store(cpu_lowcore->cregs_save_area[0], 0, 15);
+ __asm__ __volatile__("la 1,%0\n\t"
+ "stam 0,15,0(1)"
+ : "=m" (cpu_lowcore->access_regs_save_area[0])
+ : : "1", "memory");
eieio();
signal_processor(cpu,sigp_restart);

@@ -551,7 +537,6 @@
panic("Couldn't request external interrupt 0x1202");
smp_check_cpus(max_cpus);
memset(lowcore_ptr,0,sizeof(lowcore_ptr));
-
/*
* Initialize prefix pages and stacks for all possible cpus
*/
@@ -561,15 +546,16 @@
if (!cpu_possible(i))
continue;
lowcore_ptr[i] = (struct _lowcore *)
- __get_free_page(GFP_KERNEL|GFP_DMA);
- async_stack = __get_free_pages(GFP_KERNEL,1);
- if (lowcore_ptr[i] == NULL || async_stack == 0UL)
+ __get_free_pages(GFP_KERNEL|GFP_DMA,
+ sizeof(void*) == 8 ? 1 : 0);
+ async_stack = __get_free_pages(GFP_KERNEL,ASYNC_ORDER);
+ if (lowcore_ptr[i] == NULL || async_stack == 0ULL)
panic("smp_boot_cpus failed to allocate memory\n");

memcpy(lowcore_ptr[i], &S390_lowcore, sizeof(struct _lowcore));
- lowcore_ptr[i]->async_stack = async_stack + (2 * PAGE_SIZE);
+ lowcore_ptr[i]->async_stack = async_stack + (ASYNC_SIZE);
}
- set_prefix((u32) lowcore_ptr[smp_processor_id()]);
+ set_prefix((u32)(unsigned long) lowcore_ptr[smp_processor_id()]);
}

void __devinit smp_prepare_boot_cpu(void)
diff -urN linux-2.5.67/arch/s390/kernel/sys_s390.c linux-2.5.67-s390/arch/s390/kernel/sys_s390.c
--- linux-2.5.67/arch/s390/kernel/sys_s390.c Mon Apr 7 19:31:05 2003
+++ linux-2.5.67-s390/arch/s390/kernel/sys_s390.c Mon Apr 14 19:11:56 2003
@@ -24,15 +24,24 @@
#include <linux/mman.h>
#include <linux/file.h>
#include <linux/utsname.h>
+#ifdef CONFIG_ARCH_S390X
+#include <linux/personality.h>
+#endif /* CONFIG_ARCH_S390X */

#include <asm/uaccess.h>
#include <asm/ipc.h>

+#ifndef CONFIG_ARCH_S390X
+#define __SYS_RETTYPE int
+#else
+#define __SYS_RETTYPE long
+#endif /* CONFIG_ARCH_S390X */
+
/*
* sys_pipe() is the normal C calling standard for creating
* a pipe. It's not the way Unix traditionally does this, though.
*/
-asmlinkage int sys_pipe(unsigned long * fildes)
+asmlinkage __SYS_RETTYPE sys_pipe(unsigned long * fildes)
{
int fd[2];
int error;
@@ -51,7 +60,7 @@
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff)
{
- int error = -EBADF;
+ __SYS_RETTYPE error = -EBADF;
struct file * file = NULL;

flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
@@ -99,10 +108,10 @@
return error;
}

-asmlinkage int old_mmap(struct mmap_arg_struct *arg)
+asmlinkage __SYS_RETTYPE old_mmap(struct mmap_arg_struct *arg)
{
struct mmap_arg_struct a;
- int error = -EFAULT;
+ __SYS_RETTYPE error = -EFAULT;

if (copy_from_user(&a, arg, sizeof(a)))
goto out;
@@ -118,6 +127,7 @@

extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);

+#ifndef CONFIG_ARCH_S390X
struct sel_arg_struct {
unsigned long n;
fd_set *inp, *outp, *exp;
@@ -132,22 +142,61 @@
return -EFAULT;
/* sys_select() does the appropriate kernel locking */
return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
+
}
+#else /* CONFIG_ARCH_S390X */
+unsigned long
+arch_get_unmapped_area(struct file *filp, unsigned long addr,
+ unsigned long len, unsigned long pgoff,
+ unsigned long flags)
+{
+ struct vm_area_struct *vma;
+ unsigned long end;
+
+ if (test_thread_flag(TIF_31BIT)) {
+ if (!addr)
+ addr = 0x40000000;
+ end = 0x80000000;
+ } else {
+ if (!addr)
+ addr = TASK_SIZE / 2;
+ end = TASK_SIZE;
+ }
+
+ if (len > end)
+ return -ENOMEM;
+ addr = PAGE_ALIGN(addr);
+
+ for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
+ /* At this point: (!vma || addr < vma->vm_end). */
+ if (end - len < addr)
+ return -ENOMEM;
+ if (!vma || addr + len <= vma->vm_start)
+ return addr;
+ addr = vma->vm_end;
+ }
+}
+#endif /* CONFIG_ARCH_S390X */

/*
* sys_ipc() is the de-multiplexer for the SysV IPC calls..
*
* This is really horribly ugly.
*/
-asmlinkage int sys_ipc (uint call, int first, int second,
- int third, void *ptr)
+asmlinkage __SYS_RETTYPE sys_ipc (uint call, int first, int second,
+ unsigned long third, void *ptr,
+ unsigned long fifth)
{
struct ipc_kludge tmp;
int ret;

switch (call) {
case SEMOP:
- return sys_semop (first, (struct sembuf *)ptr, second);
+ return sys_semtimedop (first, (struct sembuf *) ptr, second,
+ NULL);
+ case SEMTIMEDOP:
+ return sys_semtimedop(first, (struct sembuf *) ptr, second,
+ (const struct timespec *) fifth);
case SEMGET:
return sys_semget (first, second, third);
case SEMCTL: {
@@ -191,7 +240,7 @@
return sys_shmctl (first, second,
(struct shmid_ds *) ptr);
default:
- return -EINVAL;
+ return -ENOSYS;

}

@@ -212,6 +261,7 @@
return err?-EFAULT:0;
}

+#ifndef CONFIG_ARCH_S390X
asmlinkage int sys_olduname(struct oldold_utsname * name)
{
int error;
@@ -243,6 +293,36 @@

asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
{
- return -ENOSYS;
+ return -ENOSYS;
+}
+
+#else /* CONFIG_ARCH_S390X */
+
+extern asmlinkage int sys_newuname(struct new_utsname * name);
+
+asmlinkage int s390x_newuname(struct new_utsname * name)
+{
+ int ret = sys_newuname(name);
+
+ if (current->personality == PER_LINUX32 && !ret) {
+ ret = copy_to_user(name->machine, "s390\0\0\0\0", 8);
+ if (ret) ret = -EFAULT;
+ }
+ return ret;
}

+extern asmlinkage long sys_personality(unsigned long);
+
+asmlinkage int s390x_personality(unsigned long personality)
+{
+ int ret;
+
+ if (current->personality == PER_LINUX32 && personality == PER_LINUX)
+ personality = PER_LINUX32;
+ ret = sys_personality(personality);
+ if (ret == PER_LINUX32)
+ ret = PER_LINUX;
+
+ return ret;
+}
+#endif /* CONFIG_ARCH_S390X */

-
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/