
From: Martin Schwidefsky <schwidefsky@de.ibm.com>

s390 core changes:
 - Fix a race condition between kernel thread creation and preemption.
 - Fix idal_is_needed for the border case 0x7ffff000.
 - Get rid of compiler warnings in compat_signal.c and profile.c.
 - Regenerate default configuration.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/s390/defconfig              |   11 ++++++++---
 25-akpm/arch/s390/kernel/compat_signal.c |   24 +++++++++++++++++-------
 25-akpm/arch/s390/kernel/entry.S         |    5 ++++-
 25-akpm/arch/s390/kernel/entry64.S       |    5 ++++-
 25-akpm/arch/s390/kernel/process.c       |   27 +++------------------------
 25-akpm/arch/s390/kernel/profile.c       |    1 +
 25-akpm/include/asm-s390/idals.h         |    2 +-
 7 files changed, 38 insertions(+), 37 deletions(-)

diff -puN arch/s390/defconfig~s390-core-changes arch/s390/defconfig
--- 25/arch/s390/defconfig~s390-core-changes	Mon Aug 30 14:45:56 2004
+++ 25-akpm/arch/s390/defconfig	Mon Aug 30 14:45:56 2004
@@ -1,5 +1,7 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc1
+# Mon Aug 30 19:03:48 2004
 #
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -130,9 +132,7 @@ CONFIG_SCSI_FC_ATTRS=y
 #
 # SCSI low-level drivers
 #
-# CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_DEBUG is not set
 CONFIG_ZFCP=y
 CONFIG_CCW=y
@@ -168,6 +168,7 @@ CONFIG_BLK_DEV_MD=y
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
 CONFIG_MD_RAID1=m
+# CONFIG_MD_RAID10 is not set
 CONFIG_MD_RAID5=m
 # CONFIG_MD_RAID6 is not set
 CONFIG_MD_MULTIPATH=m
@@ -236,11 +237,13 @@ CONFIG_IP_MULTICAST=y
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_IPV6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 CONFIG_XFRM=y
@@ -442,6 +445,7 @@ CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
@@ -485,8 +489,8 @@ CONFIG_MSDOS_PARTITION=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_INFO is not set
 
 #
 # Security options
@@ -505,6 +509,7 @@ CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_SHA1_Z990 is not set
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WHIRLPOOL is not set
 # CONFIG_CRYPTO_DES is not set
 # CONFIG_CRYPTO_DES_Z990 is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
diff -puN arch/s390/kernel/compat_signal.c~s390-core-changes arch/s390/kernel/compat_signal.c
--- 25/arch/s390/kernel/compat_signal.c~s390-core-changes	Mon Aug 30 14:45:56 2004
+++ 25-akpm/arch/s390/kernel/compat_signal.c	Mon Aug 30 14:45:56 2004
@@ -218,14 +218,17 @@ sys32_sigaction(int sig, const struct ol
 		 struct old_sigaction32 __user *oact)
 {
         struct k_sigaction new_ka, old_ka;
+	unsigned long sa_handler, sa_restorer;
         int ret;
 
         if (act) {
 		compat_old_sigset_t mask;
 		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
-		    __get_user((unsigned long)new_ka.sa.sa_handler, &act->sa_handler) ||
-		    __get_user((unsigned long)new_ka.sa.sa_restorer, &act->sa_restorer))
+		    __get_user(sa_handler, &act->sa_handler) ||
+		    __get_user(sa_restorer, &act->sa_restorer))
 			return -EFAULT;
+		new_ka.sa.sa_handler = (__sighandler_t) sa_handler;
+		new_ka.sa.sa_restorer = (void (*)(void)) sa_restorer;
 		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
 		__get_user(mask, &act->sa_mask);
 		siginitset(&new_ka.sa.sa_mask, mask);
@@ -234,9 +237,11 @@ sys32_sigaction(int sig, const struct ol
         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 
 	if (!ret && oact) {
+		sa_handler = (unsigned long) old_ka.sa.sa_handler;
+		sa_restorer = (unsigned long) old_ka.sa.sa_restorer;
 		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
-		    __put_user((unsigned long)old_ka.sa.sa_handler, &oact->sa_handler) ||
-		    __put_user((unsigned long)old_ka.sa.sa_restorer, &oact->sa_restorer))
+		    __put_user(sa_handler, &oact->sa_handler) ||
+		    __put_user(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);
@@ -253,6 +258,7 @@ sys32_rt_sigaction(int sig, const struct
 	   struct sigaction32 __user *oact,  size_t sigsetsize)
 {
 	struct k_sigaction new_ka, old_ka;
+	unsigned long sa_handler;
 	int ret;
 	compat_sigset_t set32;
 
@@ -261,7 +267,7 @@ sys32_rt_sigaction(int sig, const struct
 		return -EINVAL;
 
 	if (act) {
-		ret = get_user((unsigned long)new_ka.sa.sa_handler, &act->sa_handler);
+		ret = get_user(sa_handler, &act->sa_handler);
 		ret |= __copy_from_user(&set32, &act->sa_mask,
 					sizeof(compat_sigset_t));
 		switch (_NSIG_WORDS) {
@@ -278,6 +284,7 @@ sys32_rt_sigaction(int sig, const struct
 		
 		if (ret)
 			return -EFAULT;
+		new_ka.sa.sa_handler = (__sighandler_t) sa_handler;
 	}
 
 	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
@@ -311,17 +318,19 @@ sys32_sigaltstack(const stack_t32 __user
 							struct pt_regs *regs)
 {
 	stack_t kss, koss;
+	unsigned long ss_sp;
 	int ret, err = 0;
 	mm_segment_t old_fs = get_fs();
 
 	if (uss) {
 		if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
 			return -EFAULT;
-		err |= __get_user((unsigned long) kss.ss_sp, &uss->ss_sp);
+		err |= __get_user(ss_sp, &uss->ss_sp);
 		err |= __get_user(kss.ss_size, &uss->ss_size);
 		err |= __get_user(kss.ss_flags, &uss->ss_flags);
 		if (err)
 			return -EFAULT;
+		kss.ss_sp = (void *) ss_sp;
 	}
 
 	set_fs (KERNEL_DS);
@@ -333,7 +342,8 @@ sys32_sigaltstack(const stack_t32 __user
 	if (!ret && uoss) {
 		if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
 			return -EFAULT;
-		err |= __put_user((unsigned long) koss.ss_sp, &uoss->ss_sp);
+		ss_sp = (unsigned long) koss.ss_sp;
+		err |= __put_user(ss_sp, &uoss->ss_sp);
 		err |= __put_user(koss.ss_size, &uoss->ss_size);
 		err |= __put_user(koss.ss_flags, &uoss->ss_flags);
 		if (err)
diff -puN arch/s390/kernel/entry64.S~s390-core-changes arch/s390/kernel/entry64.S
--- 25/arch/s390/kernel/entry64.S~s390-core-changes	Mon Aug 30 14:45:56 2004
+++ 25-akpm/arch/s390/kernel/entry64.S	Mon Aug 30 14:45:56 2004
@@ -304,7 +304,10 @@ sysc_tracenogo:
 ret_from_fork:
 	lg	%r13,__LC_SVC_NEW_PSW+8
 	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
-        brasl   %r14,schedule_tail
+	tm	SP_PSW+1(%r15),0x01	# forking a kernel thread ?
+	jo	0f
+	stg	%r15,SP_R15(%r15)	# store stack pointer for new kthread
+0:	brasl   %r14,schedule_tail
         stosm   24(%r15),0x03     # reenable interrupts
 	j	sysc_return
 
diff -puN arch/s390/kernel/entry.S~s390-core-changes arch/s390/kernel/entry.S
--- 25/arch/s390/kernel/entry.S~s390-core-changes	Mon Aug 30 14:45:56 2004
+++ 25-akpm/arch/s390/kernel/entry.S	Mon Aug 30 14:45:56 2004
@@ -304,7 +304,10 @@ sysc_tracenogo:
 ret_from_fork:
 	l	%r13,__LC_SVC_NEW_PSW+4
 	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
-        l       %r1,BASED(.Lschedtail)
+	tm	SP_PSW+1(%r15),0x01	# forking a kernel thread ?
+	bo	BASED(0f)
+	st	%r15,SP_R15(%r15)	# store stack pointer for new kthread
+0:	l       %r1,BASED(.Lschedtail)
 	basr    %r14,%r1
         stosm   24(%r15),0x03     # reenable interrupts
 	b	BASED(sysc_return)
diff -puN arch/s390/kernel/process.c~s390-core-changes arch/s390/kernel/process.c
--- 25/arch/s390/kernel/process.c~s390-core-changes	Mon Aug 30 14:45:56 2004
+++ 25-akpm/arch/s390/kernel/process.c	Mon Aug 30 14:45:56 2004
@@ -186,41 +186,20 @@ void show_regs(struct pt_regs *regs)
 
 extern void kernel_thread_starter(void);
 
-#ifndef CONFIG_ARCH_S390X
-
-__asm__(".align 4\n"
-	"kernel_thread_starter:\n"
-	"    l     15,0(8)\n"
-	"    sr    15,7\n"
-	"    stosm 24(15),3\n"
-	"    lr    2,10\n"
-	"    basr  14,9\n"
-	"    sr    2,2\n"
-	"    br    11\n");
-
-#else /* CONFIG_ARCH_S390X */
-
 __asm__(".align 4\n"
 	"kernel_thread_starter:\n"
-	"    lg    15,0(8)\n"
-	"    sgr   15,7\n"
-	"    stosm 48(15),3\n"
-	"    lgr   2,10\n"
+	"    la    2,0(10)\n"
 	"    basr  14,9\n"
-	"    sgr   2,2\n"
+	"    la    2,0\n"
 	"    br    11\n");
 
-#endif /* CONFIG_ARCH_S390X */
-
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
 	struct pt_regs regs;
 
 	memset(&regs, 0, sizeof(regs));
-	regs.psw.mask = PSW_KERNEL_BITS;
+	regs.psw.mask = PSW_KERNEL_BITS | PSW_MASK_IO | PSW_MASK_EXT;
 	regs.psw.addr = (unsigned long) kernel_thread_starter | PSW_ADDR_AMODE;
-	regs.gprs[7] = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
-	regs.gprs[8] = __LC_KERNEL_STACK;
 	regs.gprs[9] = (unsigned long) fn;
 	regs.gprs[10] = (unsigned long) arg;
 	regs.gprs[11] = (unsigned long) do_exit;
diff -puN arch/s390/kernel/profile.c~s390-core-changes arch/s390/kernel/profile.c
--- 25/arch/s390/kernel/profile.c~s390-core-changes	Mon Aug 30 14:45:56 2004
+++ 25-akpm/arch/s390/kernel/profile.c	Mon Aug 30 14:45:56 2004
@@ -6,6 +6,7 @@
  *
  */
 #include <linux/proc_fs.h>
+#include <linux/profile.h>
 
 static struct proc_dir_entry * root_irq_dir;
 
diff -puN include/asm-s390/idals.h~s390-core-changes include/asm-s390/idals.h
--- 25/include/asm-s390/idals.h~s390-core-changes	Mon Aug 30 14:45:56 2004
+++ 25-akpm/include/asm-s390/idals.h	Mon Aug 30 14:45:56 2004
@@ -35,7 +35,7 @@ static inline int
 idal_is_needed(void *vaddr, unsigned int length)
 {
 #ifdef __s390x__
-	return ((__pa(vaddr) + length) >> 31) != 0;
+	return ((__pa(vaddr) + length - 1) >> 31) != 0;
 #else
 	return 0;
 #endif
_
