# This patch adds s390 (31-bit) to UML. # # SKAS0 and SKAS3 are tested a bit at least system boots and # shuts down correctly, network (tun/tap) works and we even could # start YaST on it. # # Note:s # We use a host running SuSE SLES8 with a "private" kernel named # 2.4.21-fsc.11, that contains special adaptions and drivers for # Fujitsu-Siemens mainframes. This means, our current SKAS3-patch # doesn't fit to vanilla kernels. We will create a reworked patch for # vanilla later (2.4 and 2.6). # Our 2.4 kernel also contains two fixes and one enhancement, that all # are essential to make UML run, even in SKAS0. The enhancement is to # support PT_TRACESYSGOOD, that generally is available in 2.6 kernels # but not in 2.4 for s390. So I would suggest to use 2.6 host for the # moment. # The fixes meanwhile are included into mainline. I don't know precisely # the first version containing them, in 2.6.13-rc5 they are present. # As those two patches are very small, they are inserted here as as # comment (AFAICS, its easy to do the changes by hand on older kernel # versions): # # First patch to fix signal stack handling: # --- a/arch/s390/kernel/signal.c 2005-03-22 11:07:39.000000000 +0100 # +++ b/arch/s390/kernel/signal.c 2005-03-22 11:08:44.000000000 +0100 # @@ -285,7 +285,7 @@ # # /* This is the X/Open sanctioned signal stack switching. */ # if (ka->sa.sa_flags & SA_ONSTACK) { # - if (! on_sig_stack(sp)) # + if (! sas_ss_flags(sp)) # sp = current->sas_ss_sp + current->sas_ss_size; # } # # Second patch to allow skipping of syscall restart: # --- a/arch/s390/kernel/ptrace.c 2005-05-07 07:20:31.000000000 +0200 # +++ b/arch/s390/kernel/ptrace.c 2005-08-02 06:45:48.000000000 +0200 # @@ -723,6 +761,13 @@ # ? 0x80 : 0)); # # /* # + * If the debugger has set an invalid system call number, # + * we prepare to skip the system call restart handling. # + */ # + if (!entryexit && regs->gprs[2] >= NR_syscalls) # + regs->trap = -1; # + # + /* # * this isn't the same as continuing with a signal, but it will do # * for normal use. strace only continues with a signal if the # * stopping signal is not SIGTRAP. -brl # Index: linux-2.6.16/arch/um/Kconfig_s390 =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/Kconfig_s390 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,39 @@ +config 64_BIT + bool + default n + +config TOP_ADDR + hex + default 0x80000000 + +config 3_LEVEL_PGTABLES + bool "Three-level pagetables" + default n + help + Three-level pagetables will let UML have more than 4G of physical + memory. All the memory that can't be mapped directly will be treated + as high memory. + +config STUB_CODE + hex + default 0x7fffe000 + +config STUB_DATA + hex + default 0x7ffff000 + +config STUB_START + hex + default STUB_CODE + +config ARCH_HAS_SC_SIGNALS + bool + default y + +config ARCH_REUSE_HOST_VSYSCALL_AREA + bool + default n + +config ARCH_S390_31 + bool + default y Index: linux-2.6.16/arch/um/Makefile-s390 =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/Makefile-s390 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,57 @@ +core-y += arch/um/sys-s390/ + +TOP_ADDR := $(CONFIG_TOP_ADDR) + +ifeq ($(CONFIG_MODE_SKAS),y) + ifneq ($(CONFIG_MODE_TT),y) + START := 0x8048000 + endif +endif + +LDFLAGS += -m elf_s390 +ELF_ARCH := $(SUBARCH) +ELF_FORMAT := elf32-$(SUBARCH) +JIFFIES_OFS := 4 +OBJCOPYFLAGS := -O binary -R .note -R .comment -S + +ifeq ("$(origin SUBARCH)", "command line") +ifneq ("$(shell uname -m)", "$(SUBARCH)") +CFLAGS += $(call cc-option,-m31) +USER_CFLAGS += $(call cc-option,-m31) +HOSTCFLAGS += $(call cc-option,-m31) +HOSTLDFLAGS += $(call cc-option,-m31) +AFLAGS += $(call cc-option,-m31) +LINK-y += $(call cc-option,-m31) +UML_OBJCOPYFLAGS += -F $(ELF_FORMAT) + +export LDFLAGS HOSTCFLAGS HOSTLDFLAGS UML_OBJCOPYFLAGS +endif +endif + +CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH) $(STUB_CFLAGS) + +ifneq ($(CONFIG_GPROF),y) +ARCH_CFLAGS += -DUM_FASTCALL +endif + +SYS_UTIL_DIR := $(ARCH_DIR)/sys-s390/util +SYS_HEADERS := $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h + +prepare: $(SYS_HEADERS) + +$(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc + $(call filechk,gen_header) + +$(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread + $(call filechk,gen_header) + +$(SYS_UTIL_DIR)/mk_sc: scripts_basic $(ARCH_DIR)/user-offsets.h FORCE + $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@ + +$(SYS_UTIL_DIR)/mk_thread: scripts_basic $(ARCH_DIR)/kernel-offsets.h FORCE + $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@ + +$(SYS_UTIL_DIR): scripts_basic include/asm FORCE + $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) + +CLEAN_FILES += $(SYS_HEADERS) Index: linux-2.6.16/arch/um/include/sysdep-s390/breakpoint.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/include/sysdep-s390/breakpoint.h 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2005 Fujitsu Siemens Computers GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * + * Licensed under the GPL + */ + +#ifndef __SYSDEP_BREAKPOINT_H +#define __SYSDEP_BREAKPOINT_H + +#include "skas_ptregs.h" + +static inline long trap_myself(void) +{ + __asm__ __volatile__ ( + " .word %0, 0" + : : "i" (HOST_S390_BREAKPOINT) ); +} + +#endif Index: linux-2.6.16/arch/um/include/sysdep-s390/checksum.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/include/sysdep-s390/checksum.h 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,238 @@ +#ifndef UM_S390_CHECKSUM_H +#define UM_S390_CHECKSUM_H + +/* This is modified for UML by Bodo Stroesser (bstroesser@fujitsu-siemens.com) + */ + +/* + * include/asm-s390/checksum.h + * S390 fast network checksum routines + * see also arch/S390/lib/checksum.c + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Ulrich Hild (first version) + * Martin Schwidefsky (heavily optimized CKSM version) + * D.J. Barrow (third attempt) + */ + +#include + +/* + * computes the checksum of a memory block at buff, length len, + * and adds in "sum" (32-bit) + * + * returns a 32-bit number suitable for feeding into itself + * or csum_tcpudp_magic + * + * this function must be called with even lengths, except + * for the last fragment, which may be odd + * + * it's best to have buff aligned on a 32-bit boundary + */ + +static inline unsigned int +csum_partial(const unsigned char * buff, int len, unsigned int sum) +{ + /* + * 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", "memory" ); +#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", "memory", "2", "3" ); +#endif /* __s390x__ */ + return sum; +} + +/* + * the same as csum_partial_copy, but copies from user space. + * + * here even more important to align src and dst on a 32-bit (or even + * better 64-bit) boundary + * + * Copy from userspace and compute checksum. If we catch an exception + * then zero the rest of the buffer. + */ +static inline unsigned int +csum_partial_copy_from_user(const char __user *src, char *dst, + int len, unsigned int sum, + int *err_ptr) +{ + int missing; + + missing = copy_from_user(dst, src, len); + if (missing) { + memset(dst + len - missing, 0, missing); + *err_ptr = -EFAULT; + } + + return csum_partial(dst, len, sum); +} + + +static inline unsigned int +csum_partial_copy_nocheck (const char *src, char *dst, int len, unsigned int sum) +{ + memcpy(dst,src,len); + return csum_partial(dst, len, sum); +} + +/* + * Fold a partial checksum without adding pseudo headers + */ +static inline unsigned short +csum_fold(unsigned int sum) +{ +#ifndef __s390x__ + register_pair rp; + + __asm__ __volatile__ ( + " slr %N1,%N1\n" /* %0 = H L */ + " lr %1,%0\n" /* %0 = H L, %1 = H L 0 0 */ + " srdl %1,16\n" /* %0 = H L, %1 = 0 H L 0 */ + " alr %1,%N1\n" /* %0 = H L, %1 = L H L 0 */ + " 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); +} + +/* + * This is a version of ip_compute_csum() optimized for IP headers, + * which always checksum on 4 octet boundaries. + * + */ +static inline unsigned short +ip_fast_csum(unsigned char *iph, unsigned int ihl) +{ + unsigned long sum; +#ifndef __s390x__ + register_pair rp; + + rp.subreg.even = (unsigned long) iph; + rp.subreg.odd = (unsigned long) ihl*4; + __asm__ __volatile__ ( + " sr %0,%0\n" /* set sum to zero */ + "0: cksm %0,%1\n" /* do checksum on longs */ + " jo 0b\n" + : "=&d" (sum), "+&a" (rp) : : "cc", "memory" ); +#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", "memory", "2", "3" ); +#endif /* __s390x__ */ + return csum_fold(sum); +} + +/* + * computes the checksum of the TCP/UDP pseudo-header + * returns a 32-bit checksum + */ +static inline unsigned int +csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, + unsigned short len, unsigned short proto, + unsigned int sum) +{ +#ifndef __s390x__ + __asm__ __volatile__ ( + " alr %0,%1\n" /* sum += saddr */ + " brc 12,0f\n" + " ahi %0,1\n" /* add carry */ + "0:" + : "+&d" (sum) : "d" (saddr) : "cc" ); + __asm__ __volatile__ ( + " alr %0,%1\n" /* sum += daddr */ + " brc 12,1f\n" + " ahi %0,1\n" /* add carry */ + "1:" + : "+&d" (sum) : "d" (daddr) : "cc" ); + __asm__ __volatile__ ( + " alr %0,%1\n" /* sum += (len<<16) + (proto<<8) */ + " brc 12,2f\n" + " ahi %0,1\n" /* add carry */ + "2:" + : "+&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; +} + +/* + * computes the checksum of the TCP/UDP pseudo-header + * returns a 16-bit checksum, already complemented + */ + +static inline unsigned short int +csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, + unsigned short len, unsigned short proto, + unsigned int sum) +{ + return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); +} + +/* + * this routine is used for miscellaneous IP-like checksums, mainly + * in icmp.c + */ + +static inline unsigned short +ip_compute_csum(unsigned char * buff, int len) +{ + return csum_fold(csum_partial(buff, len, 0)); +} + +#endif /* _S390_CHECKSUM_H */ Index: linux-2.6.16/arch/um/include/sysdep-s390/faultinfo.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/include/sysdep-s390/faultinfo.h 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computers GmbH + * Author: Bodo Stroesser + * Licensed under the GPL + */ + +#ifndef __FAULTINFO_S390_H +#define __FAULTINFO_S390_H + +/* On s390, this is just the same as struct ptrace_faultinfo */ +struct faultinfo { + unsigned long address; + int trap_no; +}; + +#define FAULT_WRITE(fi) ((fi).trap_no == 4) +#define FAULT_ADDRESS(fi) ((fi).address) + +#define PTRACE_FULL_FAULTINFO 1 + +#define ARCH_STUB_SEGV_MASK_SIGNAL -1 + +#endif Index: linux-2.6.16/arch/um/include/sysdep-s390/ptrace.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/include/sysdep-s390/ptrace.h 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * + * This is derived from arch/um/include/sysdep-i386/ptrace.h + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * + * Licensed under the GPL + */ + +#ifndef __SYSDEP_S390_PTRACE_H +#define __SYSDEP_S390_PTRACE_H + +#include "uml-config.h" + +#ifdef UML_CONFIG_MODE_TT +#include "sysdep/sc.h" +#endif + +#ifdef UML_CONFIG_MODE_SKAS + +/* syscall emulation path in ptrace */ + +#ifndef PTRACE_SYSEMU +#define PTRACE_SYSEMU 31 +#endif +#ifndef PTRACE_SYSEMU_SINGLESTEP +#define PTRACE_SYSEMU_SINGLESTEP 32 +#endif + +void set_using_sysemu(int value); +int get_using_sysemu(void); +extern int sysemu_supported; + +extern void update_debugregs(int seq); + +#include "skas_ptregs.h" +#include "sysdep/faultinfo.h" + +#define REGS_MASK(r) ((r)[HOST_MASK]) +#define REGS_ADDR(r) ((r)[HOST_ADDR]) +#define REGS_IP(r) \ + (((struct { unsigned long amode: 1; \ + unsigned long addr31: 31; \ + } *)®S_ADDR(r))->addr31) +#define REGS_GPRS(r) ((r)+HOST_GPRS) +#define REGS_GPR(r,n) (REGS_GPRS(r)[n]) +#define REGS_ACRS(r) ((r)+HOST_ACRS) +#define REGS_ACR(r,n) (REGS_ACRS(r)[n]) +#define REGS_ORIGGPR2(r) ((r)[HOST_ORIGGPR2]) +#define REGS_SP(r) (REGS_GPR(r,15)) + +#define REGS_SET_SYSCALL_RETURN(r, res) REGS_GPR(r,2) = (res) + +#endif + +#include "choose-mode.h" + +union uml_pt_regs { +#ifdef UML_CONFIG_MODE_TT + struct tt_regs { + long syscall; + unsigned long origgpr2; + void *sc; + struct faultinfo faultinfo; + } tt; +#endif +#ifdef UML_CONFIG_MODE_SKAS + struct skas_regs { + unsigned long regs[HOST_FRAME_SIZE]; + unsigned long fpregs[HOST_FP_SIZE]; + struct faultinfo faultinfo; + long syscall; + int is_user; + } skas; +#endif +}; + +#define EMPTY_UML_PT_REGS { } + +extern int mode_tt; + +#define SC_GPR(r,n) ((SC_GPRS(r))[n]) +#define SC_ACR(r,n) ((SC_ACRS(r))[n]) + +#define UPT_SC(r) ((r)->tt.sc) +#define UPT_MASK(r) \ + CHOOSE_MODE(SC_PSWMASK(UPT_SC(r)), REGS_MASK((r)->skas.regs)) +#define UPT_ADDR(r) \ + CHOOSE_MODE(SC_PSWADDR(UPT_SC(r)), REGS_ADDR((r)->skas.regs)) +#define UPT_IP(r) \ + CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs)) +#define UPT_SP(r) \ + CHOOSE_MODE(SC_GPR(UPT_SC(r),15), REGS_SP((r)->skas.regs)) +#define UPT_GPRS(r) \ + CHOOSE_MODE(SC_GPRS(UPT_SC(r)), REGS_GPRS((r)->skas.regs)) +#define UPT_GPR(r,n) \ + CHOOSE_MODE(SC_GPR(UPT_SC(r),n), REGS_GPR((r)->skas.regs,n)) +#define UPT_ACRS(r) \ + CHOOSE_MODE(SC_ACRS(UPT_SC(r)), REGS_ACRS((r)->skas.regs)) +#define UPT_ACR(r,n) \ + CHOOSE_MODE(SC_ACR(UPT_SC(r),n), REGS_ACR((r)->skas.regs,n)) +#define UPT_ORIGGPR2(r) \ + CHOOSE_MODE((r)->tt.origgpr2, REGS_ORIGGPR2((r)->skas.regs)) +#define UPT_FPRS(r) \ + CHOOSE_MODE(SC_FPREGS(UPT_SC(r)), ((r)->skas.fpregs)) +#define UPT_FPR(r,n) \ + ((UPT_FPRS(r))[n]) + +#define UPT_SYSCALL_ARG1(r) UPT_ORIGGPR2(r) +#define UPT_SYSCALL_ARG2(r) UPT_GPR(r,3) +#define UPT_SYSCALL_ARG3(r) UPT_GPR(r,4) +#define UPT_SYSCALL_ARG4(r) UPT_GPR(r,5) +#define UPT_SYSCALL_ARG5(r) UPT_GPR(r,6) +#define UPT_SYSCALL_ARG6(r) UPT_GPR(r,7) + +extern int user_context(unsigned long sp); + +#define UPT_IS_USER(r) \ + CHOOSE_MODE(user_context(UPT_SP(r)), (r)->skas.is_user) + +#define SYSCALL_ARGS(r) UPT_SYSCALL_ARG1(r), \ + UPT_SYSCALL_ARG2(r), \ + UPT_SYSCALL_ARG3(r), \ + UPT_SYSCALL_ARG4(r), \ + UPT_SYSCALL_ARG5(r), \ + UPT_SYSCALL_ARG6(r) + +#define UPT_SET_SYSCALL_RETURN(r, res) \ + CHOOSE_MODE(SC_SET_SYSCALL_RETURN(UPT_SC(r), (res)), \ + REGS_SET_SYSCALL_RETURN((r)->skas.regs, (res))) + +#define UPT_RESTART_SYSCALL(r) \ + set_tsk_thread_flag(current, TIF_RESTART_SVC) + +#define UPT_ORIG_SYSCALL(r) UPT_GPR(r,2) +#define UPT_SYSCALL_NR(r) \ + CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall) +#define UPT_SYSCALL_RET(r) UPT_GPR(r,2) + +#define UPT_FAULTINFO(r) \ + CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo)) + +#define SUBARCH_SET_SINGLESTEPPING(task, onoff) \ + { \ + extern void FixPerRegisters(struct task_struct *tsk); \ + task->thread.arch.per_info.single_step = onoff; \ + FixPerRegisters(task); \ + } + +#define SUBARCH_PTRACE_SPECIAL(task, request, addr, data) \ + { \ + struct user *dummy = NULL; \ + if (task == current && \ + addr == (long )&dummy->regs->ieee_instruction_pointer) { \ + if (request == PEEKUSER) { \ + ret = peek_user(task,addr,data); \ + goto out_tsk; \ + } \ + else if (request == POKEUSER) { \ + ret = poke_user(task,addr,data); \ + goto out_tsk; \ + } \ + } \ + } + +#define SUBARCH_EXECVE1(uptregs) \ + { /* reset FPC register */ \ + UPT_FPR((uptregs),0) = 0; } + +#endif Index: linux-2.6.16/arch/um/include/sysdep-s390/ptrace_user.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/include/sysdep-s390/ptrace_user.h 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * + * This is derived from arch/um/include/sysdep-i386/ptrace_user.h + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * + * Licensed under the GPL + */ + +#ifndef __SYSDEP_S390_PTRACE_USER_H__ +#define __SYSDEP_S390_PTRACE_USER_H__ + +#include +#include +#include + +#define PT_SYSCALL_NR(regs) ((regs)[PT_GPR2/sizeof(long)]) +#define PT_SYSCALL_NR_OFFSET PT_GPR2 + +#define PT_SYSCALL_NR_SKIP_RESTART -1 + +#define PT_SYSCALL_ARG1_OFFSET PT_ORIGGPR2 +#define PT_SYSCALL_ARG2_OFFSET PT_GPR3 +#define PT_SYSCALL_ARG3_OFFSET PT_GPR4 +#define PT_SYSCALL_ARG4_OFFSET PT_GPR5 +#define PT_SYSCALL_ARG5_OFFSET PT_GPR6 +#define PT_SYSCALL_ARG6_OFFSET PT_GPR7 + +#define PT_SYSCALL_RET_OFFSET PT_GPR2 + +#define PT_IP_OFFSET PT_PSWADDR +#define PT_IP(regs) ((regs)[PT_PSWADDR/sizeof(long)]&0x7fffffff) +#define PT_SP(regs) ((regs)[PT_GPR15]) + +#define REGS_IP_INDEX (PT_PSWADDR/sizeof(long)) +#define REGS_SP_INDEX (PT_GPR15/sizeof(long)) + +#ifndef FRAME_SIZE +#define FRAME_SIZE (PT_FPC/sizeof(long)) +#endif +#define FRAME_SIZE_OFFSET (FRAME_SIZE * sizeof(unsigned long)) + +#define FP_FRAME_SIZE ((PT_CR9-PTFPC)/sizeof(long)) + +#define MAX_REG_OFFSET (FRAME_SIZE_OFFSET) +#define MAX_REG_NR (FRAME_SIZE) + +/* These are for the old s390 2.4 kernels, that + * dont have PTRACE_SETOPTIONS normally + */ +#ifndef PTRACE_SETOPTIONS +#define PTRACE_SETOPTIONS 0x4200 +#endif + +#ifndef PTRACE_O_TRACESYSGOOD +#define PTRACE_O_TRACESYSGOOD 0x00000001 +#endif + +#ifndef PTRACE_GETREGS +#define PTRACE_GETREGS 12 +#endif +#ifndef PTRACE_SETREGS +#define PTRACE_SETREGS 13 +#endif + +#ifndef PTRACE_GETFPREGS +#define PTRACE_GETFPREGS 14 +#endif +#ifndef PTRACE_SETFPREGS +#define PTRACE_SETFPREGS 15 +#endif + +#endif Index: linux-2.6.16/arch/um/include/sysdep-s390/sigcontext.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/include/sysdep-s390/sigcontext.h 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * + * This is derived from arch/um/include/sysdep-i386/sigcontext.h + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * + * Licensed under the GPL + */ + +#ifndef __SYS_SIGCONTEXT_S390_H +#define __SYS_SIGCONTEXT_S390_H + +#include "sc.h" + +#define SC_SIGMASK(sc) (*SC_SIGMASK_P(sc)) + +#define IP_RESTART_SYSCALL(ip) ((ip) -= 2) + +#define SC_RESTART_SYSCALL(sc) IP_RESTART_SYSCALL(SC_IP(sc)) +#define SC_SET_SYSCALL_RETURN(sc, result) SC_GPR(sc,2) = (result) + +#define SC_SP(sc) SC_GPR(sc,15) + +#define GET_FAULTINFO_FROM_SC(fi,sc) \ + (fi = *(struct faultinfo *)*SC_ERRINFO_P(sc)) + +#define SC_START_SYSCALL(sc) do SC_GPR(sc,2) = -ENOSYS; while(0) + +/* This is Page Fault */ +#define SEGV_IS_FIXABLE(fi) \ + ((fi)->trap_no == 0x04 || (fi)->trap_no == 0x10 || (fi)->trap_no == 0x11) + +#endif Index: linux-2.6.16/arch/um/include/sysdep-s390/signal.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/include/sysdep-s390/signal.h 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * Licensed under the GPL + */ + +#ifndef __S390_SIGNAL_H_ +#define __S390_SIGNAL_H_ + +#include + +#define ARCH_SIGHDLR_PARAM \ + struct sigcontext * contxt, int trap, unsigned long addr + +#define ARCH_GET_SIGCONTEXT(sc, sig) \ + struct faultinfo fi; \ + fi.trap_no = trap; \ + fi.address = addr; \ + sc = contxt; \ + *SC_ERRINFO_P(sc) = (long )&fi; + +#endif Index: linux-2.6.16/arch/um/include/sysdep-s390/skas_ptrace.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/include/sysdep-s390/skas_ptrace.h 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __SYSDEP_S390_SKAS_PTRACE_H +#define __SYSDEP_S390_SKAS_PTRACE_H + +/* Just the same as struct faultinfo */ +struct ptrace_faultinfo { + unsigned long address; + int trap_no; +}; + +#endif Index: linux-2.6.16/arch/um/include/sysdep-s390/stub.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/include/sysdep-s390/stub.h 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * + * This is derived from arch/um/include/sysdep-i386/stub.h + * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) + * + * Licensed under the GPL + */ + +#ifndef __SYSDEP_STUB_H +#define __SYSDEP_STUB_H + +#include "uml-config.h" +#include +#include "sysdep/breakpoint.h" + +/* on 2.4 s390, CLONE_PARENT isn't defined in bits/sched.h */ +#ifndef CLONE_PARENT +#define CLONE_PARENT 0x00008000 +#endif + +extern void stub_segv_handler(int sig); +extern void stub_clone_handler(void); + +#define ARCH_STUB_NO_SIGRETURN 1 + +#define STUB_SYSCALL_RET GPR2 +#define STUB_MMAP_NR __NR_mmap2 +#define MMAP_OFFSET(o) ((o) >> PAGE_SHIFT) + +/* + * All stub_syscallX routines use the syscall-array via + * calling stub_syscall_entry. + * Entry and array are defined in stub.S + */ + +static inline long stub_syscall1(long syscall, long arg1) +{ + extern int __syscall_stub_start; + extern int stub_syscall_entry; + + register long __syscall asm("1") = syscall; + register long __arg1 asm("2") = arg1; + register long __svcres asm("2"); + register long __entry asm("8") = UML_CONFIG_STUB_CODE + + (long )&stub_syscall_entry - (long )&__syscall_stub_start; + + __asm__ __volatile__ ( + " basr %%r14,%%r8" + : "=d" (__svcres) + : "d" (__syscall), + "0" (__arg1), + "d" (__entry) + : "9", "14", "cc"); + return __svcres; +} + +static inline long stub_syscall2(long syscall, long arg1, long arg2) +{ + extern int __syscall_stub_start; + extern int stub_syscall_entry; + + register long __syscall asm("1") = syscall; + register long __arg1 asm("2"); + register long __arg2 asm("3"); + register long __svcres asm("2"); + register long __entry asm("8") = UML_CONFIG_STUB_CODE + + (long )&stub_syscall_entry - (long )&__syscall_stub_start; + + if(syscall == __NR_clone) { + /* Switch params before calling sys_clone, as s390 + * uses changed sequence of params compared to i386 + */ + __arg1 = arg2; + __arg2 = arg1; + } + else{ + __arg1 = arg1; + __arg2 = arg2; + } + __asm__ __volatile__ ( + " basr %%r14,%%r8" + : "=d" (__svcres) + : "d" (__syscall), + "0" (__arg1), + "d" (__arg2), + "d" (__entry) + : "9", "14", "cc"); + return __svcres; +} + +static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3) +{ + extern int __syscall_stub_start; + extern int stub_syscall_entry; + + register long __syscall asm("1") = syscall; + register long __arg1 asm("2") = arg1; + register long __arg2 asm("3") = arg2; + register long __arg3 asm("4") = arg3; + register long __svcres asm("2"); + register long __entry asm("8") = UML_CONFIG_STUB_CODE + + (long )&stub_syscall_entry - (long )&__syscall_stub_start; + + __asm__ __volatile__ ( + " basr %%r14,%%r8" + : "=d" (__svcres) + : "d" (__syscall), + "0" (__arg1), + "d" (__arg2), + "d" (__arg3), + "d" (__entry) + : "9", "14", "cc"); + return __svcres; +} + +static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3, + long arg4) +{ + extern int __syscall_stub_start; + extern int stub_syscall_entry; + + register long __syscall asm("1") = syscall; + register long __arg1 asm("2") = arg1; + register long __arg2 asm("3") = arg2; + register long __arg3 asm("4") = arg3; + register long __arg4 asm("5") = arg4; + register long __svcres asm("2"); + register long __entry asm("8") = UML_CONFIG_STUB_CODE + + (long )&stub_syscall_entry - (long )&__syscall_stub_start; + + __asm__ __volatile__ ( + " basr %%r14,%%r8" + : "=d" (__svcres) + : "d" (__syscall), + "0" (__arg1), + "d" (__arg2), + "d" (__arg3), + "d" (__arg4), + "d" (__entry) + : "9", "14", "cc"); + return __svcres; +} + +static inline long _stub_syscall6(long syscall, long arg1, long arg2, long arg3, + long arg4, long arg5, long arg6) +{ + extern int __syscall_stub_start; + extern int stub_syscall_entry; + + register long __syscall asm("1") = syscall; + register long __arg1 asm("2") = arg1; + register long __arg2 asm("3") = arg2; + register long __arg3 asm("4") = arg3; + register long __arg4 asm("5") = arg4; + register long __arg5 asm("6") = arg5; + register long __arg6 asm("7") = arg6; + register long __svcres asm("2"); + register long __entry asm("8") = UML_CONFIG_STUB_CODE + + (long )&stub_syscall_entry - (long )&__syscall_stub_start; + + __asm__ __volatile__ ( + " basr %%r14,%%r8" + : "=d" (__svcres) + : "d" (__syscall), + "0" (__arg1), + "d" (__arg2), + "d" (__arg3), + "d" (__arg4), + "d" (__arg5), + "d" (__arg6), + "d" (__entry) + : "9", "14", "cc"); + return __svcres; +} + +static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3, + long arg4, long arg5, long arg6) +{ + long args[6]; + + if(syscall != __NR_mmap && syscall != __NR_mmap2) + return _stub_syscall6(syscall, arg1, arg2, arg3, + arg4, arg5, arg6); + + args[0] = arg1; + args[1] = arg2; + args[2] = arg3; + args[3] = arg4; + args[4] = arg5; + args[5] = arg6; + + return stub_syscall1(syscall, (long )args); +} + +#endif Index: linux-2.6.16/arch/um/include/sysdep-s390/syscalls.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/include/sysdep-s390/syscalls.h 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * Licensed under the GPL + */ + +#include "sysdep/ptrace.h" + +typedef long syscall_handler_t(struct pt_regs); + +extern syscall_handler_t *sys_call_table[]; + +#define EXECUTE_SYSCALL(syscall, regs) \ + ((long (*)(unsigned long, unsigned long, unsigned long, \ + unsigned long, unsigned long, unsigned long)) \ + (*sys_call_table[syscall]))(SYSCALL_ARGS(®s->regs)) Index: linux-2.6.16/arch/um/os-Linux/skas/util/mk_ptregs_s390.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/os-Linux/skas/util/mk_ptregs_s390.c 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,29 @@ +#include +#include "../../../user-offsets.h" + +#define SHOW(name) printf("#define %s %d\n", #name, name) + +int main(int argc, char **argv) +{ + printf("/* Automatically generated by " + "arch/um/kernel/skas/util/mk_ptregs */\n"); + printf("\n"); + printf("#ifndef __SKAS_PT_REGS_\n"); + printf("#define __SKAS_PT_REGS_\n"); + printf("\n"); + SHOW(HOST_FRAME_SIZE); + SHOW(HOST_FP_SIZE); + SHOW(HOST_XFP_SIZE); + + SHOW(HOST_MASK); + SHOW(HOST_ADDR); + SHOW(HOST_GPRS); + SHOW(HOST_ACRS); + SHOW(HOST_ORIGGPR2); + + SHOW(HOST_S390_BREAKPOINT); + + printf("\n"); + printf("#endif\n"); + return(0); +} Index: linux-2.6.16/arch/um/os-Linux/sys-s390/Makefile =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/os-Linux/sys-s390/Makefile 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,10 @@ +# +# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) +# Licensed under the GPL +# + +obj-$(CONFIG_MODE_SKAS) = registers.o + +USER_OBJS := $(obj-y) + +include arch/um/scripts/Makefile.rules Index: linux-2.6.16/arch/um/os-Linux/sys-s390/registers.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/os-Linux/sys-s390/registers.c 2006-04-27 18:43:44.000000000 -0400 @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * + * This is derived from arch/um/os-Linux/sys-i386/registers.c + * Copyright (C) 2004 PathScale, Inc + * + * Licensed under the GPL + */ + +#include +#include +#include "sysdep/ptrace_user.h" +#include "sysdep/ptrace.h" +#include "uml-config.h" +#include "skas_ptregs.h" +#include "registers.h" +#include "user.h" + +/* These are set once at boot time and not changed thereafter */ +/* Do not change sequence and do not split, as this is used + * as a consecutive buffer in init_registers */ +static unsigned long exec_regs[HOST_FRAME_SIZE]; +static unsigned long exec_fp_regs[HOST_FP_SIZE]; + +void init_thread_registers(union uml_pt_regs *to) +{ + memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs)); + memcpy(to->skas.fpregs, exec_fp_regs, sizeof(to->skas.fpregs)); +} + +int ptrace_getregs(long pid, unsigned long * regs) +{ + int err; + + ptrace_area parea = { + .process_addr = (unsigned long)regs, + .kernel_addr = PT_PSWMASK, + .len = HOST_FRAME_SIZE * sizeof(long) + }; + err = ptrace(PTRACE_PEEKUSR_AREA, pid, &parea, 0); + if(err) + return -errno; + return 0; +} + +int ptrace_setregs(long pid, unsigned long * regs) +{ + int err; + + ptrace_area parea = { + .process_addr = (unsigned long)regs, + .kernel_addr = PT_PSWMASK, + .len = HOST_FRAME_SIZE * sizeof(long) + }; + err = ptrace(PTRACE_POKEUSR_AREA, pid, &parea, 0); + if(err) + return -errno; + return 0; +} + +void save_registers(int pid, union uml_pt_regs *regs) +{ + int err; + + ptrace_area parea = { + .process_addr = (unsigned long)regs->skas.regs, + .kernel_addr = PT_PSWMASK, + .len = (HOST_FRAME_SIZE + HOST_FP_SIZE) * sizeof(long) + }; + err = ptrace(PTRACE_PEEKUSR_AREA, pid, &parea, 0); + if(err) + panic("save_registers - saving registers failed, errno = %d\n", + -errno); +} + +void restore_registers(int pid, union uml_pt_regs *regs) +{ + int err; + + ptrace_area parea = { + .process_addr = (unsigned long)regs->skas.regs, + .kernel_addr = PT_PSWMASK, + .len = (HOST_FRAME_SIZE + HOST_FP_SIZE) * sizeof(long) + }; + err = ptrace(PTRACE_POKEUSR_AREA, pid, &parea, 0); + if(err) + panic("restore_registers - restoring registers failed, " + "errno = %d\n", -errno); +} + +void init_registers(int pid) +{ + int err; + + ptrace_area parea = { + .process_addr = (unsigned long)exec_regs, + .kernel_addr = PT_PSWMASK, + .len = (HOST_FRAME_SIZE + HOST_FP_SIZE) * sizeof(long) + }; + err = ptrace(PTRACE_PEEKUSR_AREA, pid, &parea, 0); + if(err) + panic("check_ptrace : PTRACE_PEEKUSR_AREA failed, errno = %d", + errno); +} + +void get_safe_registers(unsigned long *regs) +{ + memcpy(regs, exec_regs, HOST_FRAME_SIZE * sizeof(unsigned long)); +} Index: linux-2.6.16/arch/um/sys-s390/Makefile =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/Makefile 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,30 @@ +obj-y = bugs.o delay.o fault.o ksyms.o ptrace.o bitmap.o string.o \ + ptrace_user.o semaphore.o signal.o sigcontext.o stub.o stub_segv.o \ + syscalls.o sysrq.o sys_call_table.o gate_vma.o glibc-bug.o + +obj-$(CONFIG_HIGHMEM) += highmem.o +obj-$(CONFIG_MODULES) += module.o + +USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o glibc-bug.o + +SYMLINKS = semaphore.c highmem.c module.c bitmap.S string.c + +include arch/um/scripts/Makefile.rules + +semaphore.c-dir = kernel +highmem.c-dir = mm +module.c-dir = kernel +bitmap.S-dir = kernel +string.c-dir = lib + +STUB_CFLAGS = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS)) + +# _cflags works with kernel files, not with userspace ones, but c_flags does, +# why ask why? +$(obj)/stub_segv.o : c_flags = $(STUB_CFLAGS) + +$(obj)/stub.o : a_flags = $(STUB_CFLAGS) + +subdir- := util + +include arch/um/scripts/Makefile.unmap Index: linux-2.6.16/arch/um/sys-s390/bugs.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/bugs.c 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * + * This is derived from arch/um/sys-i386/bugs.c + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * + * Licensed under the GPL + */ + +#include "kern_util.h" +#include "user.h" +#include "sysdep/ptrace.h" + +int cpu_feature(char *what, char *buf, int len) +{ + return 0; +} + + +void arch_init_thread(void) +{ +} + +void arch_check_bugs(void) +{ +} + +int arch_handle_signal(int sig, union uml_pt_regs *regs) +{ + return 0; +} Index: linux-2.6.16/arch/um/sys-s390/delay.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/delay.c 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,45 @@ +/* + * arch/um/sys-s390/delay.c + * Precise Delay Loops for S390 + * + * Derived from arch/s390/lib/delay.c + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + * + * Derived from "arch/i386/lib/delay.c" + * Copyright (C) 1993 Linus Torvalds + * Copyright (C) 1997 Martin Mares + */ + +#include + +void __delay(unsigned long loops) +{ + /* + * To end the bloody studid and useless discussion about the + * BogoMips number I took the liberty to define the __delay + * function in a way that that resulting BogoMips number will + * yield the megahertz number of the cpu. The important function + * is udelay and that is done using the tod clock. -- martin. + */ + __asm__ __volatile__( + "0: brct %0,0b" + : /* no outputs */ : "r" (loops/2) ); +} + +/* + * Waits for 'usecs' microseconds using the tod clock + */ +void __udelay(unsigned long usecs) +{ + unsigned long long start_cc, end_cc; + + if (usecs == 0) + return; + asm volatile ("STCK %0" : "=m" (start_cc)); + do { + asm volatile ("STCK %0" : "=m" (end_cc)); + } while (((end_cc - start_cc)/4096) < usecs); +} Index: linux-2.6.16/arch/um/sys-s390/fault.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/fault.c 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,6 @@ +#include "user.h" + +int arch_fixup(unsigned long address, void *sc_ptr) +{ + return(0); +} Index: linux-2.6.16/arch/um/sys-s390/gate_vma.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/gate_vma.c 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,266 @@ +#include "linux/mm.h" +#include "linux/sched.h" +#include "linux/seq_file.h" +#include "skas.h" + +static struct vm_area_struct gate_vmas[3]; + +static int vma_count; + +/* Dummy to make fs/proc/task_mmu.c happy */ +struct vm_area_struct *get_gate_vma(struct task_struct *tsk) +{ + if(vma_count) return gate_vmas; + + return NULL; +} + +int in_gate_area(struct task_struct *task, unsigned long addr) +{ + int i; + + for(i = 0; i < vma_count; i++) + if(gate_vmas[i].vm_start <= addr && gate_vmas[i].vm_end > addr) + return 1; + + return 0; +} + +struct vm_area_struct *uml_get_gate_vma(struct task_struct *task, + unsigned long addr) +{ + int i; + + for(i = 0; i < vma_count; i++) + if(gate_vmas[i].vm_start <= addr && gate_vmas[i].vm_end > addr) + return gate_vmas + i; + + return NULL; +} + +struct vm_area_struct * get_next_gate_vma(struct task_struct *task, + struct vm_area_struct *vma) +{ + int i; + + if(vma == NULL) + return vma_count ? gate_vmas : NULL; + + for(i = 0; i < vma_count-1; i++) + if(gate_vmas + i == vma) + return gate_vmas + i + 1; + + return NULL; +} + +int is_gate_vma(struct task_struct *task, struct vm_area_struct *vma) +{ + int i; + + for(i = 0; i < vma_count; i++) + if(gate_vmas + i == vma) return 1; + + return 0; +} + +/* sysbols in vsyscall only, not in stub-pages */ +int in_gate_area_no_task(unsigned long addr) +{ + return 0; +} + +extern struct seq_operations proc_pid_maps_op; +static int uml_map_show(struct seq_file *m, void *v); +static void *uml_map_start(struct seq_file *m, loff_t *pos); +static void uml_map_stop(struct seq_file *m, void *v); +static void *uml_map_next(struct seq_file *m, void *v, loff_t *pos); + +static int __init gate_vma_init(void) +{ + struct vm_area_struct * vma = gate_vmas; + + if(skas_needs_stub){ + vma->vm_mm = NULL; + vma->vm_start = CONFIG_STUB_CODE; + vma->vm_end = CONFIG_STUB_CODE + PAGE_SIZE; + vma->vm_page_prot = PAGE_READONLY; + vma->vm_flags = VM_READ | VM_EXEC; + vma->vm_private_data = "[stub-code]"; + vma_count++; + vma++; + + vma->vm_mm = NULL; + vma->vm_start = CONFIG_STUB_DATA; + vma->vm_end = CONFIG_STUB_DATA + PAGE_SIZE; + vma->vm_page_prot = PAGE_SHARED; + vma->vm_flags = VM_READ | VM_WRITE; + vma->vm_private_data = "[stub-stack]"; + vma_count++; + vma++; + } + + proc_pid_maps_op.start = uml_map_start; + proc_pid_maps_op.next = uml_map_next; + proc_pid_maps_op.stop = uml_map_stop; + proc_pid_maps_op.show = uml_map_show; + + return 0; +} +__initcall(gate_vma_init); + +/* + * The following routines are stolen from fs/proc/task_mmu.c + */ +static void pad_len_spaces(struct seq_file *m, int len) +{ + len = 25 + sizeof(void*) * 6 - len; + if (len < 1) + len = 1; + seq_printf(m, "%*c", len, ' '); +} + +static int uml_map_show(struct seq_file *m, void *v) +{ + struct task_struct *task = m->private; + struct vm_area_struct *map = v; + struct mm_struct *mm = map->vm_mm; + struct file *file = map->vm_file; + int flags = map->vm_flags; + unsigned long ino = 0; + dev_t dev = 0; + int len; + + if (file) { + struct inode *inode = map->vm_file->f_dentry->d_inode; + dev = inode->i_sb->s_dev; + ino = inode->i_ino; + } + + seq_printf(m, "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n", + map->vm_start, + map->vm_end, + flags & VM_READ ? 'r' : '-', + flags & VM_WRITE ? 'w' : '-', + flags & VM_EXEC ? 'x' : '-', + flags & VM_MAYSHARE ? 's' : 'p', + map->vm_pgoff << PAGE_SHIFT, + MAJOR(dev), MINOR(dev), ino, &len); + + /* + * Print the dentry name for named mappings, and a + * special [heap] marker for the heap: + */ + if (map->vm_file) { + pad_len_spaces(m, len); + seq_path(m, file->f_vfsmnt, file->f_dentry, ""); + } else { + if (mm) { + if (map->vm_start <= mm->start_brk && + map->vm_end >= mm->brk) { + pad_len_spaces(m, len); + seq_puts(m, "[heap]"); + } else { + if (map->vm_start <= mm->start_stack && + map->vm_end >= mm->start_stack) { + + pad_len_spaces(m, len); + seq_puts(m, "[stack]"); + } + } + } else { + pad_len_spaces(m, len); + if(map->vm_private_data) + seq_puts(m, map->vm_private_data); + else seq_puts(m, "[vdso]"); + } + } + seq_putc(m, '\n'); + if (m->count < m->size) /* map is copied successfully */ + m->version = is_gate_vma(task, map)? 0: map->vm_start; + return 0; +} + +static void *uml_map_start(struct seq_file *m, loff_t *pos) +{ + struct task_struct *task = m->private; + unsigned long last_addr = m->version; + struct mm_struct *mm; + struct vm_area_struct *map; + loff_t l = *pos; + + /* + * We remember last_addr rather than next_addr to hit with + * mmap_cache most of the time. We have zero last_addr at + * the begining and also after lseek. We will have -1 last_addr + * after the end of the maps. + */ + + if (last_addr == -1UL) + return NULL; + + mm = get_task_mm(task); + if (!mm) + return NULL; + + down_read(&mm->mmap_sem); + + m->version = 0; + + /* Start with last addr hint */ + if (last_addr && (map = find_vma(mm, last_addr))) { + map = map->vm_next; + goto out; + } + + /* + * Check the map index is within the range and do + * sequential scan until m_index. + */ + map = NULL; + if ((unsigned long)l < mm->map_count) { + map = mm->mmap; + while (l-- && map) + map = map->vm_next; + goto out; + } + + /* End of maps has reached */ + up_read(&mm->mmap_sem); + mmput(mm); + + l -= mm->map_count; + do { + map = get_next_gate_vma(task, map); + } while(l-- && map); + + m->version = (map != NULL)? 0: -1UL; + +out: + return map; +} + +static void uml_map_stop(struct seq_file *m, void *v) +{ + struct task_struct *task = m->private; + struct vm_area_struct *map = v; + if (map && !is_gate_vma(task, map)) { + struct mm_struct *mm = map->vm_mm; + up_read(&mm->mmap_sem); + mmput(mm); + } +} + +static void *uml_map_next(struct seq_file *m, void *v, loff_t *pos) +{ + struct task_struct *task = m->private; + struct vm_area_struct *map = v; + int is_gate = is_gate_vma(task, map); + + (*pos)++; + if (map && !is_gate && map->vm_next) + return map->vm_next; + uml_map_stop(m, v); + if (map && !is_gate) + map = NULL; + return get_next_gate_vma(task, map); +} Index: linux-2.6.16/arch/um/sys-s390/glibc-bug.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/glibc-bug.c 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,16 @@ +/* glibc 2.2.5 in SuSE-SLES 8 doesn't have a clone(), but a __clone() + * only. This is a bug in glibc, because there should be a weak_alias + * for clone(). We want to work with this old glibc correctly, so we + * declare a "weak" wrapper here. + */ +#include +#include + +extern int __clone(int (*fn)(void *arg), void *child_stack, + int flags, void *arg); + +int __attribute__((weak)) clone(int (*fn)(void *arg), void *child_stack, + int flags, void *arg) +{ + return __clone( fn, child_stack, flags, arg); +} Index: linux-2.6.16/arch/um/sys-s390/kernel-offsets.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/kernel-offsets.c 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,25 @@ +#include +#include +#include +#include +#include + +#define DEFINE(sym, val) \ + asm volatile("\n->" #sym " %0 " #val : : "i" (val)) + +#define STR(x) #x +#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : ) + +#define BLANK() asm volatile("\n->" : : ) + +#define OFFSET(sym, str, mem) \ + DEFINE(sym, offsetof(struct str, mem)); + +void foo(void) +{ + OFFSET(TASK_PER_STRUCT, task_struct, thread.arch.per_info); +#ifdef CONFIG_MODE_TT + OFFSET(TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid); +#endif +#include +} Index: linux-2.6.16/arch/um/sys-s390/ksyms.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/ksyms.c 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,23 @@ +#include "linux/module.h" +#include "linux/in6.h" +#include "linux/rwsem.h" +#include "asm/byteorder.h" +#include "asm/delay.h" +#include "asm/semaphore.h" +#include "asm/uaccess.h" +#include "asm/checksum.h" +#include "asm/errno.h" + +/* delay core functions */ +EXPORT_SYMBOL(__udelay); + +/* semaphore ops */ +EXPORT_SYMBOL(__up); +EXPORT_SYMBOL(__down); +EXPORT_SYMBOL(__down_interruptible); + +/* used by bitops.h */ +EXPORT_SYMBOL(_oi_bitmap); +EXPORT_SYMBOL(_ni_bitmap); +EXPORT_SYMBOL(_zb_findmap); +EXPORT_SYMBOL(_sb_findmap); Index: linux-2.6.16/arch/um/sys-s390/ptrace.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/ptrace.c 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * + * This is derived from arch/um/sys-s390/ptrace.c + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * + * and arch/s390/kernel/ptrace.c + * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), + * Martin Schwidefsky (schwidefsky@de.ibm.com) + * + * Licensed under the GPL + */ + +#include "linux/sched.h" +#include "asm/elf.h" +#include "asm/ptrace.h" +#include "asm/uaccess.h" +#include "asm/unistd.h" +#include "sysdep/ptrace.h" +#include "sysdep/sigcontext.h" +#include "sysdep/sc.h" + +void arch_switch(void) +{ + update_debugregs(current->thread.arch.per_struct_seq); +} + +int is_syscall(unsigned long addr) +{ + union uml_pt_regs * regs; + unsigned char instr[4]; + int reg; + + if (copy_from_user(instr, (void *) addr, 2)) { + printk("is_syscall : failed to read instruction from 0x%lx\n", + addr); + return 0; + } + if (instr[0] == 0x0a ) /* SVC */ + return 1; + + if (instr[0] != 0x44 ) /* EXECUTE */ + return 0; + + /* Now, we have handled the simple cases. + * EXECUTE instruction needs more care! + */ + + /* Read the rest of EXECUTE instruction */ + if (copy_from_user(instr+2, (void *)(addr+2), 2)) { + printk("is_syscall : failed to read instruction from 0x%lx\n", + addr); + return 0; + } + + /* Compute 2nd operand address */ + regs = ¤t->thread.regs.regs; + addr = *(unsigned short *)(instr+2) & 0xfff; /* Displacement */ + reg = instr[1] & 0x0f; /* X2 */ + if (reg) + addr += UPT_GPR(regs,reg); + reg = instr[2] >> 4; /* B2 */ + if (reg) + addr += UPT_GPR(regs,reg); + + /* Read the EXECUTEd instruction from 2nd operand address */ + if (copy_from_user(instr, (void *) addr, 2)) { + printk("is_syscall : failed to read EXECed instruction from 0x%lx\n", + addr); + return 0; + } + if (instr[0] == 0x0a ) /* SVC */ + return 1; + + return 0; +} + +#define PSW_MASK_USERBITS 0x00003f00UL +#define PSW_MASK_PER 0x40000000UL +#define PSW_ADDR_AMODE 0x80000000UL + +#define FPC_INVALID_MASK 0x070700fcUL + +#define PER_MAX_ADDR 0x7fffffffUL + +void FixPerRegisters(struct task_struct *task) +{ + per_struct *per_info = &task->thread.arch.per_info; + + per_info->control_regs.bits.em_instruction_fetch = + per_info->single_step | per_info->instruction_fetch; + + if (per_info->single_step) { + per_info->control_regs.bits.starting_addr = 0; + per_info->control_regs.bits.ending_addr = PER_MAX_ADDR; + } + + /* + * if any of the control reg tracing bits are on + * we switch on per in the psw + */ + if (per_info->control_regs.bits.em_branching || + per_info->control_regs.bits.em_instruction_fetch || + per_info->control_regs.bits.em_storage_alteration || + per_info->control_regs.bits.em_store_real_address ) + UPT_MASK(&task->thread.regs.regs) |= PSW_MASK_PER; + else + UPT_MASK(&task->thread.regs.regs) &= ~PSW_MASK_PER; + + if (per_info->control_regs.bits.em_storage_alteration) + per_info->control_regs.bits.storage_alt_space_ctl = 1; + else + per_info->control_regs.bits.storage_alt_space_ctl = 0; +} + +int poke_user(struct task_struct *child, long addr, long data) +{ + struct user *dummy = NULL; + union uml_pt_regs *regs = &child->thread.regs.regs; + + if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) + return -EIO; + + if (addr == (long )&dummy->regs.psw.mask) { + if ( (data|PSW_MASK_USERBITS) != + (UPT_MASK(regs)|PSW_MASK_USERBITS) ) + return -EINVAL; + UPT_MASK(regs) = data; + FixPerRegisters(child); + } + else if (addr == (long )&dummy->regs.psw.addr) { + UPT_ADDR(regs) = data|PSW_ADDR_AMODE; + } + else if (addr <= (long )(dummy->regs.gprs+NUM_GPRS-1)) { + UPT_GPR(regs, (addr-(long )dummy->regs.gprs)/sizeof(long)) = data; + } + else if (addr <= (long )(dummy->regs.acrs+NUM_ACRS-1)) { + UPT_ACR(regs, (addr-(long )dummy->regs.acrs)/sizeof(int)) = data; + } + else if (addr == (long )&dummy->regs.orig_gpr2) { + UPT_ORIGGPR2(regs) = data; + } + else if (addr == (long )&dummy->regs.fp_regs.fpc) { + if (data&FPC_INVALID_MASK) + return -EINVAL; + UPT_FPR(regs,0) = data; + } + else if (addr < (long )(&dummy->regs.fp_regs + 1)) { + UPT_FPR(regs, (addr-(long )&dummy->regs.fp_regs)/sizeof(long)) = data; + } + else if (addr < (long )(&dummy->regs.per_info + 1)) { + ((long *)&child->thread.arch.per_info) + [(addr-(long )&dummy->regs.per_info)/sizeof(long)] = data; + FixPerRegisters(child); + } + return 0; +} + +int peek_user(struct task_struct *child, long addr, long data) +{ + struct user *dummy = NULL; + union uml_pt_regs *regs = &child->thread.regs.regs; + long tmp = 0; + + if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) + return -EIO; + + if (addr == (long )&dummy->regs.psw.mask) { + tmp = UPT_MASK(regs) & ~PSW_MASK_PER; + } + else if (addr == (long )&dummy->regs.psw.addr) { + tmp = UPT_ADDR(regs); + } + else if (addr <= (long )(dummy->regs.gprs+NUM_GPRS-1)) { + tmp = UPT_GPR(regs, (addr-(long )dummy->regs.gprs)/sizeof(long)); + } + else if (addr <= (long )(dummy->regs.acrs+NUM_ACRS-1)) { + tmp = UPT_ACR(regs, (addr-(long )dummy->regs.acrs)/sizeof(int)); + } + else if (addr == (long )&dummy->regs.orig_gpr2) { + tmp = UPT_ORIGGPR2(regs); + } + else if (addr == (long )&dummy->regs.fp_regs.fpc) { + if (data&FPC_INVALID_MASK) + return -EINVAL; + tmp = UPT_FPR(regs,0); + } + else if (addr < (long )(&dummy->regs.fp_regs + 1)) { + tmp = UPT_FPR(regs, (addr-(long )&dummy->regs.fp_regs)/sizeof(long)); + } + else if (addr < (long )(&dummy->regs.per_info + 1)) { + tmp = ((long *)&child->thread.arch.per_info) + [(addr-(long )&dummy->regs.per_info)/sizeof(long)]; + } + return put_user(tmp, (addr_t __user *)data); +} + + +int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu ) +{ + s390_fp_regs * from = (s390_fp_regs *)UPT_FPRS(®s->regs); + memcpy(fpu, from, sizeof(s390_fp_regs)); + return(1); +} Index: linux-2.6.16/arch/um/sys-s390/ptrace_user.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/ptrace_user.c 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * + * This is derived from arch/um/sys-i386/ptrace_user.c + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * + * Licensed under the GPL + */ + +#include +#include +#include +#include +#include +#include +#include +#include "kern_util.h" +#include "sysdep/thread.h" +#include "user.h" +#include "os.h" + +static void write_debugregs(int pid, per_struct *per) +{ + struct user *dummy = NULL;; + ptrace_area parea; + + parea.len = sizeof(per_struct); + parea.kernel_addr = (unsigned long)&dummy->regs.per_info; + parea.process_addr = (unsigned long)per; + if (ptrace(PTRACE_POKEUSR_AREA, pid, &parea, 0)) { + printk("write_debugregs - ptrace(PTRACE_POKEUSR_AREA failed " + ", errno = %d\n", errno); + } +} + +static void read_debugregs(int pid, per_struct *per) +{ + struct user *dummy = NULL; + ptrace_area parea; + + parea.len = sizeof(per_struct); + parea.kernel_addr = (unsigned long)&dummy->regs.per_info; + parea.process_addr = (unsigned long)per; + if (ptrace(PTRACE_PEEKUSR_AREA, pid, &parea, 0)) { + printk("read_debugregs - ptrace(PTRACE_PEEKUSR_AREA failed " + ", errno = %d\n", errno); + *per = (per_struct){{{{0,}}},0,0,0,0,{{0,}}}; + } +} + +/* Accessed only by the tracing thread */ +static per_struct kernel_per_struct = (per_struct){{{{0,}}},0,0,0,0,{{0,}}}; +static int per_struct_seq = 0; + +void arch_enter_kernel(void *task, int pid) +{ + read_debugregs(pid, (per_struct *)TASK_PER_STRUCT(task)); + write_debugregs(pid, &kernel_per_struct); +} + +void arch_leave_kernel(void *task, int pid) +{ + read_debugregs(pid, &kernel_per_struct); + write_debugregs(pid, (per_struct *)TASK_PER_STRUCT(task)); +} + +void ptrace_pokeuser(unsigned long addr, unsigned long data) +{ + struct user *dummy = NULL; + + addr -= (unsigned long)&dummy->regs.per_info; + if (addr >= sizeof(per_struct)) + return; + + addr /= sizeof(unsigned long); + if(((unsigned long *)&kernel_per_struct)[addr] == data) return; + + ((unsigned long *)&kernel_per_struct)[addr] = data; + per_struct_seq++; +} + +static void update_debugregs_cb(void *arg) +{ + int pid = *((int *) arg); + + write_debugregs(pid, &kernel_per_struct); +} + +void update_debugregs(int seq) +{ + int me; + + if(seq == per_struct_seq) return; + + me = os_getpid(); + initial_thread_cb(update_debugregs_cb, &me); +} Index: linux-2.6.16/arch/um/sys-s390/sigcontext.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/sigcontext.c 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * Licensed under the GPL + */ + +#include +#include + +void sc_to_sc(void *to, void *from) +{ + memcpy(((struct sigcontext *)to)->oldmask, + ((struct sigcontext *)from)->oldmask, + sizeof(((struct sigcontext *)to)->oldmask)); + memcpy(((struct sigcontext *)to)->sregs, + ((struct sigcontext *)from)->sregs, sizeof(_sigregs)); +} Index: linux-2.6.16/arch/um/sys-s390/signal.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/signal.c 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * + * This is derived from arch/um/sys-i386/signal.c + * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) + * + * and arch/s390/kernel/signal.c + * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) + * + * Licensed under the GPL + */ + +#include "linux/signal.h" +#include "linux/ptrace.h" +#include "asm/current.h" +#include "asm/ucontext.h" +#include "asm/uaccess.h" +#include "asm/unistd.h" +#include "frame_kern.h" +#include "signal_user.h" +#include "sigcontext.h" +#include "registers.h" +#include "mode.h" + +#ifdef CONFIG_MODE_SKAS + +#include "skas.h" + +static int restore_sigregs_skas(struct pt_regs *regs, _sigregs *from) +{ + return copy_from_user(regs->regs.skas.regs, &from->regs, + sizeof(from->regs)) || + copy_from_user(regs->regs.skas.fpregs, &from->fpregs, + sizeof(from->fpregs)); +} + +int save_sigregs_skas(struct pt_regs *regs, _sigregs *to) +{ + return copy_to_user(&to->regs, regs->regs.skas.regs, + sizeof(to->regs)) || + copy_to_user(&to->fpregs, regs->regs.skas.fpregs, + sizeof(to->fpregs)); +} + +#endif + +#ifdef CONFIG_MODE_TT + +/* These copy a sigcontext to/from userspace. They copy the fpstate pointer, + * blowing away the old, good one. So, that value is saved, and then restored + * after the sigcontext copy. In copy_from, the variable holding the saved + * fpstate pointer, and the sigcontext that it should be restored to are both + * in the kernel, so we can just restore using an assignment. In copy_to, the + * saved pointer is in the kernel, but the sigcontext is in userspace, so we + * copy_to_user it. + */ +static inline int restore_sigregs_tt(_sigregs *to, _sigregs *from) +{ + return copy_from_user(to, from, sizeof(*to)); +} + +static inline int save_sigregs_tt(_sigregs *from, _sigregs *to) +{ + return copy_to_user(to, from, sizeof(*to)); +} +#endif + +static int restore_sigregs(struct pt_regs *to, _sigregs __user *from) +{ + unsigned long old_mask = PT_REGS_MASK(to); + int ret; + + ret = CHOOSE_MODE(restore_sigregs_tt(((struct sigcontext *) + UPT_SC(&to->regs))->sregs, from), + restore_sigregs_skas(to, from)); + + PT_REGS_MASK(to) = PSW_MASK_MERGE(old_mask, PT_REGS_MASK(to)); + PT_REGS_ADDR(to) |= PSW_ADDR_AMODE; + PT_REGS_FPC(to) &= FPC_VALID_MASK; + + /* Avoid ERESTART handling */ + PT_REGS_SYSCALL_NR(to) = -1; + + return(ret); +} + +static int save_sigregs(struct pt_regs *from, _sigregs *to) +{ + int ret; + unsigned long orig_mask = PT_REGS_MASK(from); + + PT_REGS_MASK(from) = PSW_MASK_MERGE(PSW_USER_BITS, PT_REGS_MASK(from)); + + ret = CHOOSE_MODE(save_sigregs_tt(((struct sigcontext *) + UPT_SC(&from->regs))->sregs, to), + save_sigregs_skas(from, to)); + + PT_REGS_MASK(from) = orig_mask; + + return ret; +} + +typedef struct +{ + __u8 callee_used_stack[__SIGNAL_FRAMESIZE]; + struct sigcontext sc; + _sigregs sregs; + int signo; + __u8 retcode[S390_SYSCALL_SIZE]; +} sigframe; + +typedef struct +{ + __u8 callee_used_stack[__SIGNAL_FRAMESIZE]; + __u8 retcode[S390_SYSCALL_SIZE]; + struct siginfo info; + struct ucontext uc; +} rt_sigframe; + +int setup_signal_stack_sc(unsigned long stack_top, int sig, + struct k_sigaction *ka, struct pt_regs *regs, + sigset_t *set) +{ + sigframe __user *frame; + + frame = (sigframe __user *) ((stack_top - sizeof(sigframe)) & -8L); + if(!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + return 1; + + if (__copy_to_user(&frame->sc.oldmask, &set->sig, + sizeof(frame->sc.oldmask)) || + save_sigregs(regs, &frame->sregs) || + __put_user(&frame->sregs, &frame->sc.sregs)) + return 1; + + if(ka->sa.sa_flags & SA_RESTORER) { + PT_REGS_GPR(regs,14) = (unsigned long) + ka->sa.sa_restorer | PSW_ADDR_AMODE; + } else { + PT_REGS_GPR(regs,14) = (unsigned long) + frame->retcode | PSW_ADDR_AMODE; + if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, + (u16 __user *)(frame->retcode))) + return 1; + } + + /* Set up backchain. */ + if (__put_user(PT_REGS_GPR(regs,15), (addr_t __user *) frame)) + return 1; + + /* Set up registers for signal handler */ + PT_REGS_GPR(regs,15) = (unsigned long) frame; + PT_REGS_ADDR(regs) = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; + + PT_REGS_GPR(regs,2) = sig; + PT_REGS_GPR(regs,3) = (unsigned long) &frame->sc; + + /* We forgot to include these in the sigcontext. + To avoid breaking binary compatibility, they are passed as args. */ + PT_REGS_GPR(regs,4) = current->thread.arch.faultinfo.trap_no; + PT_REGS_GPR(regs,5) = current->thread.arch.faultinfo.address; + + /* Place signal number on stack to allow backtrace from handler. */ + if (__put_user(PT_REGS_GPR(regs,2), (int __user *) &frame->signo)) + return 1; + + return(0); +} + +int setup_signal_stack_si(unsigned long stack_top, int sig, + struct k_sigaction *ka, struct pt_regs *regs, + siginfo_t *info, sigset_t *set) +{ + rt_sigframe __user *frame; + + frame = (rt_sigframe __user *)((stack_top - sizeof(rt_sigframe)) & -8L); + if(!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + return 1; + + if (copy_siginfo_to_user(&frame->info, info)) + return 1; + + if (__put_user(0, &frame->uc.uc_flags) || + __put_user(0, &frame->uc.uc_link) || + __put_user((void *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) || + __put_user(sas_ss_flags(PT_REGS_GPR(regs,15)), + &frame->uc.uc_stack.ss_flags) || + __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size) || + save_sigregs(regs, &frame->uc.uc_mcontext) || + __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set))) + return 1; + + if(ka->sa.sa_flags & SA_RESTORER) { + PT_REGS_GPR(regs,14) = (unsigned long) + ka->sa.sa_restorer | PSW_ADDR_AMODE; + } else { + PT_REGS_GPR(regs,14) = (unsigned long) + frame->retcode | PSW_ADDR_AMODE; + if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, + (u16 __user *)(frame->retcode))) + return 1; + } + + /* Set up backchain. */ + if (__put_user(PT_REGS_GPR(regs,15), (addr_t __user *) frame)) + return 1; + + /* Set up registers for signal handler */ + PT_REGS_GPR(regs,15) = (unsigned long) frame; + PT_REGS_ADDR(regs) = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; + + PT_REGS_GPR(regs,2) = sig; + PT_REGS_GPR(regs,3) = (unsigned long) &frame->info; + PT_REGS_GPR(regs,4) = (unsigned long) &frame->uc; + + return(0); +} + +long sys_sigreturn(struct pt_regs dummy) +{ + struct pt_regs * regs = ¤t->thread.regs; + sigframe __user *frame = (sigframe __user *)PT_REGS_GPR(regs,15); + sigset_t set; + + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) + goto segfault; + if(__copy_from_user(&set.sig, &frame->sc.oldmask, + sizeof(frame->sc.oldmask))) + goto segfault; + + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sighand->siglock); + current->blocked = set; + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + if(restore_sigregs(regs, &frame->sregs)) + goto segfault; + + return PT_REGS_GPR(regs,2); + + segfault: + force_sig(SIGSEGV, current); + return 0; +} + +long sys_rt_sigreturn(struct pt_regs dummy) +{ + struct pt_regs * regs = ¤t->thread.regs; + rt_sigframe __user *frame = (rt_sigframe __user *)PT_REGS_GPR(regs,15); + sigset_t set; + + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) + goto segfault; + if(copy_from_user(&set.sig, &frame->uc.uc_sigmask, sizeof(set))) + goto segfault; + + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sighand->siglock); + current->blocked = set; + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + if(restore_sigregs(regs, &frame->uc.uc_mcontext)) + goto segfault; + + /* It is more difficult to avoid calling this function than to + call it and ignore errors. */ + do_sigaltstack(&frame->uc.uc_stack, NULL, PT_REGS_GPR(regs,15)); + + return PT_REGS_GPR(regs,2); + + segfault: + force_sig(SIGSEGV, current); + return 0; +} Index: linux-2.6.16/arch/um/sys-s390/stub.S =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/stub.S 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,346 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * Licensed under the GPL + */ + +#include +#include "uml-config.h" +#include "skas_ptregs.h" + + .globl syscall_stub +.section .__syscall_stub, "x" + + .globl batch_syscall_stub +batch_syscall_stub: + /* load base register */ + basr %r12, 0 +base: + /* load pointer to UML_CONFIG_STUB_DATA */ + l %r13, stub_data_p-base(%r12) + + /* load pointer to first operation */ + la %r15, 8(%r13) + +again: + /* load length of additional data */ + /* and test if == 0 */ + icm %r1, 15, 0(%r15) + + /* write possible 0 to header */ + st %r1, 4(%r13) + + /* if(length == 0) : end of list */ + jz done + + /* save current pointer */ + st %r15, 4(%r13) + + /* skip additional data */ + ar %r15, %r1 + + /* load syscall-# */ + l %r1, 0(%r15) + + /* load pointer to mmap2-struct */ + la %r2, 4(%r15) + /* if syscall is mmap2, do the call */ + chi %r1, __NR_mmap2 + je do_syscall + + /* load syscall params */ + lm %r2, %r7, 4(%r15) + +do_syscall: + /* execute syscall */ + bas %r14, stub_syscall_entry-base(%r12) + + /* check return value */ +check_retcode: + c %r2, 28(%r15) + la %r15, 32(%r15) + je again + +done: + /* save return value */ + st %r2, 0(%r13) + + /* stop */ + .short HOST_S390_BREAKPOINT + +stub_data_p: + .long UML_CONFIG_STUB_DATA + + .macro SYSCALL nr + svc \nr + br 14 + .endm + + .globl stub_syscall_entry + +stub_syscall_entry: + basr %r9, 0 +base2: + sll %r1, 2 + chi %r1, 4*256 + bl syscall_array-base2(%r9,%r1) + srl %r1, 2 + /* fall through */ + +syscall_array: + SYSCALL 0 + SYSCALL 1 + SYSCALL 2 + SYSCALL 3 + SYSCALL 4 + SYSCALL 5 + SYSCALL 6 + SYSCALL 7 + SYSCALL 8 + SYSCALL 9 + SYSCALL 10 + SYSCALL 11 + SYSCALL 12 + SYSCALL 13 + SYSCALL 14 + SYSCALL 15 + SYSCALL 16 + SYSCALL 17 + SYSCALL 18 + SYSCALL 19 + SYSCALL 20 + SYSCALL 21 + SYSCALL 22 + SYSCALL 23 + SYSCALL 24 + SYSCALL 25 + SYSCALL 26 + SYSCALL 27 + SYSCALL 28 + SYSCALL 29 + SYSCALL 30 + SYSCALL 31 + SYSCALL 32 + SYSCALL 33 + SYSCALL 34 + SYSCALL 35 + SYSCALL 36 + SYSCALL 37 + SYSCALL 38 + SYSCALL 39 + SYSCALL 40 + SYSCALL 41 + SYSCALL 42 + SYSCALL 43 + SYSCALL 44 + SYSCALL 45 + SYSCALL 46 + SYSCALL 47 + SYSCALL 48 + SYSCALL 49 + SYSCALL 50 + SYSCALL 51 + SYSCALL 52 + SYSCALL 53 + SYSCALL 54 + SYSCALL 55 + SYSCALL 56 + SYSCALL 57 + SYSCALL 58 + SYSCALL 59 + SYSCALL 60 + SYSCALL 61 + SYSCALL 62 + SYSCALL 63 + SYSCALL 64 + SYSCALL 65 + SYSCALL 66 + SYSCALL 67 + SYSCALL 68 + SYSCALL 69 + SYSCALL 70 + SYSCALL 71 + SYSCALL 72 + SYSCALL 73 + SYSCALL 74 + SYSCALL 75 + SYSCALL 76 + SYSCALL 77 + SYSCALL 78 + SYSCALL 79 + SYSCALL 80 + SYSCALL 81 + SYSCALL 82 + SYSCALL 83 + SYSCALL 84 + SYSCALL 85 + SYSCALL 86 + SYSCALL 87 + SYSCALL 88 + SYSCALL 89 + SYSCALL 90 + SYSCALL 91 + SYSCALL 92 + SYSCALL 93 + SYSCALL 94 + SYSCALL 95 + SYSCALL 96 + SYSCALL 97 + SYSCALL 98 + SYSCALL 99 + SYSCALL 100 + SYSCALL 101 + SYSCALL 102 + SYSCALL 103 + SYSCALL 104 + SYSCALL 105 + SYSCALL 106 + SYSCALL 107 + SYSCALL 108 + SYSCALL 109 + SYSCALL 110 + SYSCALL 111 + SYSCALL 112 + SYSCALL 113 + SYSCALL 114 + SYSCALL 115 + SYSCALL 116 + SYSCALL 117 + SYSCALL 118 + SYSCALL 119 + SYSCALL 120 + SYSCALL 121 + SYSCALL 122 + SYSCALL 123 + SYSCALL 124 + SYSCALL 125 + SYSCALL 126 + SYSCALL 127 + SYSCALL 128 + SYSCALL 129 + SYSCALL 130 + SYSCALL 131 + SYSCALL 132 + SYSCALL 133 + SYSCALL 134 + SYSCALL 135 + SYSCALL 136 + SYSCALL 137 + SYSCALL 138 + SYSCALL 139 + SYSCALL 140 + SYSCALL 141 + SYSCALL 142 + SYSCALL 143 + SYSCALL 144 + SYSCALL 145 + SYSCALL 146 + SYSCALL 147 + SYSCALL 148 + SYSCALL 149 + SYSCALL 150 + SYSCALL 151 + SYSCALL 152 + SYSCALL 153 + SYSCALL 154 + SYSCALL 155 + SYSCALL 156 + SYSCALL 157 + SYSCALL 158 + SYSCALL 159 + SYSCALL 160 + SYSCALL 161 + SYSCALL 162 + SYSCALL 163 + SYSCALL 164 + SYSCALL 165 + SYSCALL 166 + SYSCALL 167 + SYSCALL 168 + SYSCALL 169 + SYSCALL 170 + SYSCALL 171 + SYSCALL 172 + SYSCALL 173 + SYSCALL 174 + SYSCALL 175 + SYSCALL 176 + SYSCALL 177 + SYSCALL 178 + SYSCALL 179 + SYSCALL 180 + SYSCALL 181 + SYSCALL 182 + SYSCALL 183 + SYSCALL 184 + SYSCALL 185 + SYSCALL 186 + SYSCALL 187 + SYSCALL 188 + SYSCALL 189 + SYSCALL 190 + SYSCALL 191 + SYSCALL 192 + SYSCALL 193 + SYSCALL 194 + SYSCALL 195 + SYSCALL 196 + SYSCALL 197 + SYSCALL 198 + SYSCALL 199 + SYSCALL 200 + SYSCALL 201 + SYSCALL 202 + SYSCALL 203 + SYSCALL 204 + SYSCALL 205 + SYSCALL 206 + SYSCALL 207 + SYSCALL 208 + SYSCALL 209 + SYSCALL 210 + SYSCALL 211 + SYSCALL 212 + SYSCALL 213 + SYSCALL 214 + SYSCALL 215 + SYSCALL 216 + SYSCALL 217 + SYSCALL 218 + SYSCALL 219 + SYSCALL 220 + SYSCALL 221 + SYSCALL 222 + SYSCALL 223 + SYSCALL 224 + SYSCALL 225 + SYSCALL 226 + SYSCALL 227 + SYSCALL 228 + SYSCALL 229 + SYSCALL 230 + SYSCALL 231 + SYSCALL 232 + SYSCALL 233 + SYSCALL 234 + SYSCALL 235 + SYSCALL 236 + SYSCALL 237 + SYSCALL 238 + SYSCALL 239 + SYSCALL 240 + SYSCALL 241 + SYSCALL 242 + SYSCALL 243 + SYSCALL 244 + SYSCALL 245 + SYSCALL 246 + SYSCALL 247 + SYSCALL 248 + SYSCALL 249 + SYSCALL 250 + SYSCALL 251 + SYSCALL 252 + SYSCALL 253 + SYSCALL 254 + SYSCALL 255 Index: linux-2.6.16/arch/um/sys-s390/stub_segv.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/stub_segv.c 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * Licensed under the GPL + */ + +#include +// #include +#include "uml-config.h" +#include "sysdep/faultinfo.h" +#include "sysdep/breakpoint.h" + +void __attribute__ ((__section__ (".__syscall_stub"))) +stub_segv_handler(int sig, struct sigcontext * sc, int trap, void * addr) +{ + *((struct faultinfo *) UML_CONFIG_STUB_DATA) = + (struct faultinfo) { + .trap_no = trap, + .address = (unsigned long)addr + }; + + trap_myself(); + +/* __asm__("svc %b0\n" + "la %%r3,%b1\n" + "svc %b2\n" + "lr %%r15,%3\n" + "svc %b4\n" + : : "i" (__NR_getpid), + "i" (SIGUSR1), + "i" (__NR_kill), + "d" ((unsigned long)sc - __SIGNAL_FRAMESIZE), + "i" (__NR_sigreturn) + : "2", "3"); */ +} Index: linux-2.6.16/arch/um/sys-s390/sys_call_table.S =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/sys_call_table.S 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,26 @@ +/* Steal s390 syscall table for our purposes, but with some slight changes.*/ +/* The code,to do this, again is stolen from arch/s390/kernel/entry.S */ + +#define SYSCALL(esa,esame,emu) .long esa + +#define sys_time um_time +#define sys_stime um_stime + +#define sys_fork_glue sys_fork +#define sys_execve_glue sys_execve +#define sys_sigsuspend_glue sys_sigsuspend +#define sys_sigreturn_glue sys_sigreturn +#define sys_clone_glue sys_clone +#define sys_rt_sigreturn_glue sys_rt_sigreturn +#define sys_rt_sigsuspend_glue sys_rt_sigsuspend +#define sys_sigaltstack_glue sys_sigaltstack +#define sys_vfork_glue sys_vfork + +#define old_mmap s390_old_mmap +#define sys_mmap2 s390_mmap2 + + + .globl sys_call_table +sys_call_table: + +#include "../../s390/kernel/syscalls.S" Index: linux-2.6.16/arch/um/sys-s390/syscalls.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/syscalls.c 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * + * This is derived from arch/um/sys-i386/syscalls.c + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) + * + * and arch/s390/kernel/sys_s390.c + * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + * Thomas Spatzier (tspat@de.ibm.com) + * + * Licensed under the GPL + */ + +#include "linux/sched.h" +#include "linux/shm.h" +#include "asm/ipc.h" +#include "asm/mman.h" +#include "asm/uaccess.h" +#include "asm/unistd.h" + +/* + * Perform the mmap() and mmap2() system calls. + * Linux/s390 didn't use to be able to handle more than + * 5 system call parameters, so these system calls use a + * memory block for parameter passing.. + */ + +struct mmap_arg_struct { + unsigned long addr; + unsigned long len; + unsigned long prot; + unsigned long flags; + unsigned long fd; + unsigned long offset; +}; + +extern long old_mmap(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long offset); + +long s390_old_mmap(struct mmap_arg_struct __user *arg) +{ + struct mmap_arg_struct a; + int err = -EFAULT; + + if (copy_from_user(&a, arg, sizeof(a))) + goto out; + + err = old_mmap(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); + out: + return err; +} + +extern long sys_mmap2(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff); + +long s390_mmap2(struct mmap_arg_struct __user *arg) +{ + struct mmap_arg_struct a; + int err = -EFAULT; + + if (copy_from_user(&a, arg, sizeof(a))) + goto out; + err = sys_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); +out: + return err; +} + + +long sys_clone(unsigned long newsp, unsigned long clone_flags, int *parent_tid, + int *child_tid, unsigned long newtls) +{ + long ret; + + if (!newsp) + newsp = UPT_SP(¤t->thread.regs.regs); + current->thread.forking = 1; + + { + /* + * Special processing for TLS support in s390: + * If CLONE_SETTLS is set, newtls will hold a new TLS pointer for the + * new thread to be created. Normally, this should be loaded into ACR0 + * in copy_thread. Therefore, we would have to add some aubarch stuff + * to copy_thread. We avoid this by saving current ACR0, loading newtls + * into ACR0, from where it will be copied to the new thread's ACR0. + * When do_fork returns, we reload current ACR0 with the original value. + */ + union uml_pt_regs * regs = ¤t->thread.regs.regs; + unsigned long origtls = UPT_ACR(regs,0); + if (clone_flags & CLONE_SETTLS) + UPT_ACR(regs,0) = newtls; + ret = do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid, + child_tid); + UPT_ACR(regs,0) = origtls; + } + + current->thread.forking = 0; + return(ret); +} + +/* + * sys_ipc() is the de-multiplexer for the SysV IPC calls.. + * + * This is really horribly ugly. + */ +long sys_ipc (uint call, int first, int second, + int third, void __user *ptr) +{ + struct ipc_kludge tmp; + int ret; + + switch (call) { + case SEMOP: + return sys_semtimedop(first, (struct sembuf __user *) ptr, + (unsigned)second, NULL); + case SEMTIMEDOP: + return sys_semtimedop(first, (struct sembuf __user *) ptr, + (unsigned)second, + (const struct timespec __user *) third); + case SEMGET: + return sys_semget (first, (int)second, third); + case SEMCTL: { + union semun fourth; + if (!ptr) + return -EINVAL; + if (get_user(fourth.__pad, (void __user * __user *) ptr)) + return -EFAULT; + return sys_semctl (first, (int)second, third, fourth); + } + case MSGSND: + return sys_msgsnd (first, (struct msgbuf __user *) ptr, + (size_t)second, third); + case MSGRCV: + if (!ptr) + return -EINVAL; + if (copy_from_user(&tmp, (struct ipc_kludge __user *) ptr, + sizeof (struct ipc_kludge))) + return -EFAULT; + return sys_msgrcv (first, tmp.msgp, + (size_t)second, tmp.msgtyp, third); + case MSGGET: + return sys_msgget ((key_t) first, (int)second); + case MSGCTL: + return sys_msgctl (first, (int)second, + (struct msqid_ds __user *) ptr); + + case SHMAT: { + ulong raddr; + ret = do_shmat (first, (char __user *) ptr, + (int)second, &raddr); + if (ret) + return ret; + return put_user (raddr, (ulong __user *) third); + } + case SHMDT: + return sys_shmdt ((char __user *)ptr); + case SHMGET: + return sys_shmget (first, (size_t)second, third); + case SHMCTL: + return sys_shmctl (first, (int)second, + (struct shmid_ds __user *) ptr); + default: + return -ENOSYS; + } +} + +long sys_sigaction(int sig, const struct old_sigaction __user *act, + struct old_sigaction __user *oact) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + if (act) { + old_sigset_t mask; + if (!access_ok(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) + return -EFAULT; + __get_user(new_ka.sa.sa_flags, &act->sa_flags); + __get_user(mask, &act->sa_mask); + siginitset(&new_ka.sa.sa_mask, mask); + } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) + return -EFAULT; + __put_user(old_ka.sa.sa_flags, &oact->sa_flags); + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); + } + + return ret; +} + +long s390_fadvise64(int fd, u32 offset_high, u32 offset_low, size_t len, int advice) +{ + return sys_fadvise64(fd, (u64) offset_high << 32 | offset_low, len, advice); +} + +struct fadvise64_64_args { + int fd; + long long offset; + long long len; + int advice; +}; + +long s390_fadvise64_64(struct fadvise64_64_args __user *args) +{ + struct fadvise64_64_args a; + + if (copy_from_user(&a, args, sizeof(a))) + return -EFAULT; + return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice); +} Index: linux-2.6.16/arch/um/sys-s390/sysrq.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/sysrq.c 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * Licensed under the GPL + */ + +#include "linux/kernel.h" +#include "linux/smp.h" +#include "linux/sched.h" +#include "linux/kallsyms.h" +#include "asm/ptrace.h" +#include "asm/uaccess.h" +#include "sysrq.h" + +void show_regs(struct pt_regs *regs) +{ + register unsigned long * __r15 asm ("15"); + mm_segment_t old_fs; + char * mode = user_mode(regs) ? "User" : "Krnl"; + int i; + + printk("\n"); + printk("CPU: %d %s\n", smp_processor_id(), print_tainted()); + printk("%s PSW : %p %p\n", mode, + (void *)PT_REGS_MASK(regs), (void *)PT_REGS_ADDR(regs)); + print_symbol(" (%s)\n", PT_REGS_ADDR(regs) & PSW_ADDR_INSN); + printk("%s GPRS: %08lx %08lx %08lx %08lx\n", mode, + PT_REGS_GPR(regs,0), PT_REGS_GPR(regs,1), + PT_REGS_GPR(regs,2), PT_REGS_GPR(regs,3)); + printk(" %08lx %08lx %08lx %08lx\n", + PT_REGS_GPR(regs,4), PT_REGS_GPR(regs,5), + PT_REGS_GPR(regs,6), PT_REGS_GPR(regs,7)); + printk(" %08lx %08lx %08lx %08lx\n", + PT_REGS_GPR(regs,8), PT_REGS_GPR(regs,9), + PT_REGS_GPR(regs,10), PT_REGS_GPR(regs,11)); + printk(" %08lx %08lx %08lx %08lx\n", + PT_REGS_GPR(regs,12), PT_REGS_GPR(regs,13), + PT_REGS_GPR(regs,14), PT_REGS_GPR(regs,15)); + + if(user_mode(regs)){ + old_fs = get_fs(); + set_fs(USER_DS); + printk("\nUser Code: "); + for (i = 0; i < 20; i++) { + unsigned char c; + if (__get_user(c, (char __user *)(PT_REGS_ADDR(regs) + i - 8))) { + printk(" Bad PSW."); + break; + } + printk("%02x ", c); + } + set_fs(old_fs); + printk("\n"); + } + + show_trace(current, __r15); +} Index: linux-2.6.16/arch/um/sys-s390/unmap.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/unmap.c 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * + * This is derived from arch/um/sys-i386/unmap.c + * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * + * Licensed under the GPL + */ + +#include +#include + +struct mmap_arg_struct { + unsigned long addr; + unsigned long len; + unsigned long prot; + unsigned long flags; + unsigned long fd; + unsigned long offset; +}; + +static int errno; + +static inline _syscall2(int, munmap, void *, start, size_t, len) +static inline _syscall1(void *, mmap2, struct mmap_arg_struct *, argp) +int switcheroo(int fd, int prot, void *from, void *to, int size) +{ + struct mmap_arg_struct mmap_args = { + (unsigned long)to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0 }; + + if(munmap(to, size) < 0){ + return(-1); + } + if(mmap2(&mmap_args) == (void*) -1 ){ + return(-1); + } + if(munmap(from, size) < 0){ + return(-1); + } + return(0); +} Index: linux-2.6.16/arch/um/sys-s390/user-offsets.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/user-offsets.c 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include + +#define DEFINE(sym, val) \ + asm volatile("\n->" #sym " %0 " #val : : "i" (val)) + +#define OFFSET(sym, str, mem) \ + DEFINE(sym, offsetof(str, mem)); + +void foo(void) +{ + OFFSET(SC_SIGMASK_P, struct sigcontext, oldmask); + OFFSET(SC_SIGREGS_P, struct sigcontext, sregs); + /* S390 supplies trapno and error_addr in registers, when sighdlr + * is called. We have to insert this into sigcontext. So we write + * trapno and error_addr into a struct errinfo (sysdep/sigcontext.h) + * located on sighdlr's stack. The address of this struct is written + * immediately after the struct sigcontext, where fortunately is + * space for an additional pointer. + * The following "DEFINE" inserts just this additional pointer. + */ + DEFINE(SC_ERRINFO_P, offsetof(struct sigcontext, sregs)+sizeof(void *)); + + OFFSET(SC_PSWMASK, _sigregs, regs.psw.mask); + OFFSET(SC_PSWADDR, _sigregs, regs.psw.addr); + OFFSET(SC_GPRS, _sigregs, regs.gprs); + OFFSET(SC_ACRS, _sigregs, regs.acrs); + OFFSET(SC_FPREGS, _sigregs, fpregs); + + DEFINE(HOST_FRAME_SIZE, PT_FPC/sizeof( unsigned long)); + DEFINE(HOST_FP_SIZE, sizeof(s390_fp_regs) / sizeof(unsigned long)); + DEFINE(HOST_XFP_SIZE, 0); + DEFINE(__UM_FRAME_SIZE, 0); /* This is a dummy only */ + + DEFINE(HOST_MASK, PT_PSWMASK / sizeof(unsigned long)); + DEFINE(HOST_ADDR, PT_PSWADDR / sizeof(unsigned long)); + DEFINE(HOST_GPRS, PT_GPR0 / sizeof(unsigned long)); + DEFINE(HOST_ACRS, PT_ACR0 / sizeof(unsigned long)); + DEFINE(HOST_ORIGGPR2, PT_ORIGGPR2 / sizeof(unsigned long)); + + /* This is for stub.S only. + * S390_BREAKPOINT is defined in asm/ptrace.h inside of a + * #ifndef __ASSEMBLY__. So we can't use this definition + * directly. + */ + DEFINE(HOST_S390_BREAKPOINT, S390_BREAKPOINT_U16); +} Index: linux-2.6.16/arch/um/sys-s390/util/Makefile =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/util/Makefile 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,5 @@ +hostprogs-y := mk_sc mk_thread +always := $(hostprogs-y) + +HOSTCFLAGS_mk_sc.o := -I$(objtree)/arch/um +HOSTCFLAGS_mk_thread.o := -I$(objtree)/arch/um Index: linux-2.6.16/arch/um/sys-s390/util/mk_sc.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/util/mk_sc.c 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,39 @@ +#include +#include "../../user-offsets.h" + +#define SC_PTR_OFFSET(name) \ + printf("#define " #name "(sc) ((unsigned long *) (((char *) (sc)) + %d))\n",\ + name) + +#define SC_SIGREGS_OFFSET(name) \ + printf("#define " #name \ + "(sc) (*(unsigned long *) (((char *)*SC_SIGREGS_P(sc)) + %d))\n",\ + name) + +#define SC_SIGREGS_PTR_OFFSET(name) \ + printf("#define " #name \ + "(sc) ((unsigned long *) (((char *)*SC_SIGREGS_P(sc)) + %d))\n",\ + name) + +int main(int argc, char **argv) +{ + SC_PTR_OFFSET(SC_SIGMASK_P); + SC_PTR_OFFSET(SC_SIGREGS_P); + SC_PTR_OFFSET(SC_ERRINFO_P); + + printf( "#define SC_IP(sc) \\\n"); + printf( " ((unsigned long)\\\n"); + printf( " (((struct { unsigned long amode: 1; \\\n"); + printf( " unsigned long addr31: 31; \\\n"); + printf( " } *)&SC_PSWADDR(sc))->addr31))\n"); + + SC_SIGREGS_OFFSET(SC_PSWMASK); + SC_SIGREGS_OFFSET(SC_PSWADDR); + + SC_SIGREGS_PTR_OFFSET(SC_GPRS); + SC_SIGREGS_PTR_OFFSET(SC_ACRS); + + SC_SIGREGS_PTR_OFFSET(SC_FPREGS); + + return(0); +} Index: linux-2.6.16/arch/um/sys-s390/util/mk_thread.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/arch/um/sys-s390/util/mk_thread.c 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,22 @@ +#include +#include "../../kernel-offsets.h" + +int main(int argc, char **argv) +{ + printf("/*\n"); + printf(" * Generated by mk_thread\n"); + printf(" */\n"); + printf("\n"); + printf("#ifndef __UM_THREAD_H\n"); + printf("#define __UM_THREAD_H\n"); + printf("\n"); + printf("#define TASK_PER_STRUCT(task) ((unsigned long *) " + "&(((char *) (task))[%d]))\n", TASK_PER_STRUCT); +#ifdef TASK_EXTERN_PID + printf("#define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[%d]))\n", + TASK_EXTERN_PID); +#endif + printf("\n"); + printf("#endif\n"); + return(0); +} Index: linux-2.6.16/include/asm-um/archparam-s390.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/include/asm-um/archparam-s390.h 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * Licensed under the GPL + */ + +#ifndef __UM_ARCHPARAM_S390_H +#define __UM_ARCHPARAM_S390_H + +/* s390 doesn't support vsyscall-page */ +#define VSYSCALL_BASE 0 +#define VSYSCALL_END 0 + +extern void __const_udelay(unsigned long usecs); + +#endif Index: linux-2.6.16/include/asm-um/elf-s390.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/include/asm-um/elf-s390.h 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * + * This is derived from include/asm-s390/elf.h + */ + +#ifndef __UM_ELF_S390_H +#define __UM_ELF_S390_H + +/* s390 relocations defined by the ABIs */ +#define R_390_NONE 0 /* No reloc. */ +#define R_390_8 1 /* Direct 8 bit. */ +#define R_390_12 2 /* Direct 12 bit. */ +#define R_390_16 3 /* Direct 16 bit. */ +#define R_390_32 4 /* Direct 32 bit. */ +#define R_390_PC32 5 /* PC relative 32 bit. */ +#define R_390_GOT12 6 /* 12 bit GOT offset. */ +#define R_390_GOT32 7 /* 32 bit GOT offset. */ +#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */ +#define R_390_COPY 9 /* Copy symbol at runtime. */ +#define R_390_GLOB_DAT 10 /* Create GOT entry. */ +#define R_390_JMP_SLOT 11 /* Create PLT entry. */ +#define R_390_RELATIVE 12 /* Adjust by program base. */ +#define R_390_GOTOFF32 13 /* 32 bit offset to GOT. */ +#define R_390_GOTPC 14 /* 32 bit PC rel. offset to GOT. */ +#define R_390_GOT16 15 /* 16 bit GOT offset. */ +#define R_390_PC16 16 /* PC relative 16 bit. */ +#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */ +#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */ +#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */ +#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */ +#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */ +#define R_390_64 22 /* Direct 64 bit. */ +#define R_390_PC64 23 /* PC relative 64 bit. */ +#define R_390_GOT64 24 /* 64 bit GOT offset. */ +#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */ +#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */ +#define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */ +#define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */ +#define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */ +#define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */ +#define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */ +#define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */ +#define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */ +#define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */ +#define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */ +#define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */ +#define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */ +#define R_390_TLS_GDCALL 38 /* Tag for function call in general + dynamic TLS code. */ +#define R_390_TLS_LDCALL 39 /* Tag for function call in local + dynamic TLS code. */ +#define R_390_TLS_GD32 40 /* Direct 32 bit for general dynamic + thread local data. */ +#define R_390_TLS_GD64 41 /* Direct 64 bit for general dynamic + thread local data. */ +#define R_390_TLS_GOTIE12 42 /* 12 bit GOT offset for static TLS + block offset. */ +#define R_390_TLS_GOTIE32 43 /* 32 bit GOT offset for static TLS + block offset. */ +#define R_390_TLS_GOTIE64 44 /* 64 bit GOT offset for static TLS + block offset. */ +#define R_390_TLS_LDM32 45 /* Direct 32 bit for local dynamic + thread local data in LD code. */ +#define R_390_TLS_LDM64 46 /* Direct 64 bit for local dynamic + thread local data in LD code. */ +#define R_390_TLS_IE32 47 /* 32 bit address of GOT entry for + negated static TLS block offset. */ +#define R_390_TLS_IE64 48 /* 64 bit address of GOT entry for + negated static TLS block offset. */ +#define R_390_TLS_IEENT 49 /* 32 bit rel. offset to GOT entry for + negated static TLS block offset. */ +#define R_390_TLS_LE32 50 /* 32 bit negated offset relative to + static TLS block. */ +#define R_390_TLS_LE64 51 /* 64 bit negated offset relative to + static TLS block. */ +#define R_390_TLS_LDO32 52 /* 32 bit offset relative to TLS + block. */ +#define R_390_TLS_LDO64 53 /* 64 bit offset relative to TLS + block. */ +#define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */ +#define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */ +#define R_390_TLS_TPOFF 56 /* Negate offset in static TLS + block. */ +#define R_390_20 57 /* Direct 20 bit. */ +#define R_390_GOT20 58 /* 20 bit GOT offset. */ +#define R_390_GOTPLT20 59 /* 20 bit offset to jump slot. */ +#define R_390_TLS_GOTIE20 60 /* 20 bit GOT offset for static TLS + block offset. */ +/* Keep this the last entry. */ +#define R_390_NUM 61 + +#include "asm/ptrace.h" +#include "asm/user.h" + +typedef s390_fp_regs elf_fpregset_t; +typedef s390_regs elf_gregset_t; + +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2MSB +#define ELF_ARCH EM_S390 + +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(x) \ + (((x)->e_machine == EM_S390 || (x)->e_machine == EM_S390_OLD) \ + && (x)->e_ident[EI_CLASS] == ELF_CLASS) + +#define ELF_PLAT_INIT(regs, load_addr) \ + do { \ + PT_REGS_GPR(regs,14) = 0; \ + } while(0) + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE 4096 + +#define ELF_ET_DYN_BASE ((TASK_SIZE & 0x80000000) \ + ? TASK_SIZE / 3 * 2 \ + : 2 * TASK_SIZE / 3) + +#define ELF_CORE_COPY_REGS(pr_reg, regs) do { \ + pr_reg.psw.mask = PT_REGS_MASK(regs); \ + pr_reg.psw.addr = PT_REGS_ADDR(regs); \ + memcpy(pr_reg.gprs, PT_REGS_GPRS(regs), sizeof(pr_reg.gprs)); \ + memcpy(pr_reg.acrs, PT_REGS_ACRS(regs), sizeof(pr_reg.acrs)); \ + pr_reg.orig_gpr2 = PT_REGS_ORIGGPR2(regs); \ +} while(0); + +#define ELF_HWCAP (0) + +#define ELF_PLATFORM (NULL) + +#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX) + +#endif Index: linux-2.6.16/include/asm-um/ldt-s390.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/include/asm-um/ldt-s390.h 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2004 Fujitsu Siemens Computers GmbH + * Licensed under the GPL + * + * Author: Bodo Stroesser + */ + +#ifndef __ASM_LDT_S390_H +#define __ASM_LDT_S390_H + +struct mmu_context_skas; + +static inline void ldt_host_info(void) +{ +} + +static inline long init_new_ldt(struct mmu_context_skas * to_mm, + struct mmu_context_skas * from_mm) +{ + return 0; +} + +static inline void free_ldt(struct mmu_context_skas * mm) { } + +typedef char uml_ldt_t[0]; + +#endif Index: linux-2.6.16/include/asm-um/lowcore.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/include/asm-um/lowcore.h 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,6 @@ +#ifndef __UM_LOWCORE_H +#define __UM_LOWCORE_H + +/* Fake s390 only */ + +#endif Index: linux-2.6.16/include/asm-um/module-s390.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/include/asm-um/module-s390.h 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,6 @@ +#ifndef __UM_MODULE_S390_H +#define __UM_MODULE_S390_H + +#include "asm/arch/module.h" + +#endif Index: linux-2.6.16/include/asm-um/processor-s390.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/include/asm-um/processor-s390.h 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * + * This is derived from include/asm-um/processor-i386.h + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * + * Licensed under the GPL + */ + +#ifndef __UM_PROCESSOR_S390_H +#define __UM_PROCESSOR_S390_H + +#include "asm/arch/user.h" +#include "sysdep/faultinfo.h" + +struct arch_thread { + per_struct per_info; + int per_struct_seq; + struct faultinfo faultinfo; +}; + +#define INIT_ARCH_THREAD { \ + .per_info = (per_struct) {{{{0,}}},0,0,0,0,{{0,}}}, \ + .per_struct_seq = 0, \ + .faultinfo = { 0, 0 } } + +/* + * Default implementation of macro that returns current + * instruction pointer ("program counter"). Stolen + * from asm-s390/processor.h + */ +#define current_text_addr() ({ void *pc; __asm__("basr %0,0":"=a"(pc)); pc; }) + +#define cpu_relax() barrier() + +#define ARCH_IS_STACKGROW(address) (1==1) + +#define TIF_RESTART_SVC 7 /* restart svc with new svc number */ +#define _TIF_RESTART_SVC (1 << TIF_RESTART_SVC) + +#include "asm/processor-generic.h" + +#endif Index: linux-2.6.16/include/asm-um/ptrace-s390.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/include/asm-um/ptrace-s390.h 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * + * This is derived from include/asm-um/ptrace-i386.h + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * + * Licensed under the GPL + */ + +#ifndef __UM_PTRACE_S390_H +#define __UM_PTRACE_S390_H + +#define HOST_AUDIT_ARCH AUDIT_ARCH_S390 + +/* Normally defined in include/asm-s390/page.h, + * but used in macros imported via include/asm-um/arch/ptrace.h + * So, we need to have our own definition here. + */ +#define PAGE_DEFAULT_ACC 0 + +#include "sysdep/ptrace.h" +#include "asm/ptrace-generic.h" + +#define PT_REGS_ADDR(r) UPT_ADDR(&(r)->regs) +#define PT_REGS_MASK(r) UPT_MASK(&(r)->regs) +#define PT_REGS_GPR(r,inx) UPT_GPR(&(r)->regs,inx) +#define PT_REGS_GPRS(r) UPT_GPRS(&(r)->regs) +#define PT_REGS_ACRS(r) UPT_ACRS(&(r)->regs) +#define PT_REGS_ORIGGPR2(r) UPT_ORIGGPR2(&(r)->regs) +#define PT_REGS_FPC(r) UPT_FPR(&(r)->regs,0) + +#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_SYSCALL_NR(r) +#define PT_REGS_SYSCALL_RET(r) PT_REGS_GPR(r,2) +#define PT_FIX_EXEC_STACK(sp) do ; while(0) + +#define user_mode(r) UPT_IS_USER(&(r)->regs) + +#undef profile_pc +#define profile_pc(regs) PT_REGS_IP(regs) + +#endif Index: linux-2.6.16/include/asm-um/sigcontext-s390.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/include/asm-um/sigcontext-s390.h 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,6 @@ +#ifndef __UM_SIGCONTEXT_S390_H +#define __UM_SIGCONTEXT_S390_H + +#include "asm/sigcontext-generic.h" + +#endif Index: linux-2.6.16/include/asm-um/system-s390.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/include/asm-um/system-s390.h 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,14 @@ +#ifndef __UM_SYSTEM_S390_H +#define __UM_SYSTEM_S390_H + +/* Fake this to make asm-s390/system.h compile */ +#define MACHINE_HAS_IEEE 1 +extern void __load_psw_mask(unsigned long mask); + +#include "asm/system-generic.h" + +#undef prepare_arch_switch +#undef finish_arch_switch +#undef task_running + +#endif Index: linux-2.6.16/include/asm-um/vm-flags-s390.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.16/include/asm-um/vm-flags-s390.h 2006-04-27 18:43:31.000000000 -0400 @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2004, 2005 Fujitsu Siemens Computer GmbH + * Author: Bodo Stroesser (bstroesser@fujitsu-siemens.com) + * + * This is derived from include/asm-um/vm-flags-i386.h + * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) + * + * Licensed under the GPL + */ + +#ifndef __VM_FLAGS_S390_H +#define __VM_FLAGS_S390_H + +#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + +#endif