summaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/Kconfig4
-rw-r--r--arch/s390/defconfig41
-rw-r--r--arch/s390/kernel/compat_linux.c103
-rw-r--r--arch/s390/kernel/compat_signal.c105
-rw-r--r--arch/s390/kernel/compat_wrapper.S143
-rw-r--r--arch/s390/kernel/entry.S51
-rw-r--r--arch/s390/kernel/entry64.S75
-rw-r--r--arch/s390/kernel/machine_kexec.c5
-rw-r--r--arch/s390/kernel/process.c4
-rw-r--r--arch/s390/kernel/setup.c2
-rw-r--r--arch/s390/kernel/signal.c146
-rw-r--r--arch/s390/kernel/smp.c73
-rw-r--r--arch/s390/kernel/sys_s390.c4
-rw-r--r--arch/s390/kernel/syscalls.S23
-rw-r--r--arch/s390/kernel/time.c11
-rw-r--r--arch/s390/kernel/traps.c2
-rw-r--r--arch/s390/lib/Makefile2
-rw-r--r--arch/s390/lib/delay.c2
-rw-r--r--arch/s390/lib/spinlock.c15
-rw-r--r--arch/s390/lib/uaccess.S6
-rw-r--r--arch/s390/lib/uaccess64.S6
-rw-r--r--arch/s390/mm/cmm.c10
22 files changed, 472 insertions, 361 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index b66602ad7b3..b7ca5bf9acf 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -80,6 +80,10 @@ config HOTPLUG_CPU
can be controlled through /sys/devices/system/cpu/cpu#.
Say N if you want to disable CPU hotplug.
+config DEFAULT_MIGRATION_COST
+ int
+ default "1000000"
+
config MATHEMU
bool "IEEE FPU emulation"
depends on MARCH_G5
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 7d23edc6fac..f8d0cd540a0 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,19 +1,17 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.15-rc2
-# Mon Nov 21 13:51:30 2005
+# Linux kernel version: 2.6.16-rc2
+# Wed Feb 8 10:44:39 2006
#
CONFIG_MMU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_S390=y
-CONFIG_UID16=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -29,18 +27,20 @@ CONFIG_POSIX_MQUEUE=y
CONFIG_SYSCTL=y
CONFIG_AUDIT=y
# CONFIG_AUDITSYSCALL is not set
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
+CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -49,8 +49,10 @@ CONFIG_CC_ALIGN_FUNCTIONS=0
CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
#
# Loadable module support
@@ -76,11 +78,11 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_DEFAULT_IOSCHED="deadline"
#
# Base setup
@@ -151,6 +153,7 @@ CONFIG_NET=y
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -193,6 +196,11 @@ CONFIG_IPV6=y
# SCTP Configuration (EXPERIMENTAL)
#
# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
@@ -362,6 +370,7 @@ CONFIG_DM_MULTIPATH=y
#
CONFIG_UNIX98_PTYS=y
CONFIG_UNIX98_PTY_COUNT=2048
+# CONFIG_HANGCHECK_TIMER is not set
#
# Watchdog Cards
@@ -488,6 +497,7 @@ CONFIG_FS_MBCACHE=y
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_INOTIFY=y
@@ -520,6 +530,7 @@ CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
#
# Miscellaneous filesystems
@@ -584,6 +595,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
#
@@ -592,27 +604,30 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
#
-# Profiling support
+# Instrumentation Support
#
# CONFIG_PROFILING is not set
+# CONFIG_STATISTICS is not set
#
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=17
-CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_DETECT_SOFTLOCKUP is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_VM is not set
+CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
#
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index bf9a7a361b3..cc058dc3bc8 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -100,12 +100,12 @@
#define SET_STAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid)
#define SET_STAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid)
-asmlinkage long sys32_chown16(const char * filename, u16 user, u16 group)
+asmlinkage long sys32_chown16(const char __user * filename, u16 user, u16 group)
{
return sys_chown(filename, low2highuid(user), low2highgid(group));
}
-asmlinkage long sys32_lchown16(const char * filename, u16 user, u16 group)
+asmlinkage long sys32_lchown16(const char __user * filename, u16 user, u16 group)
{
return sys_lchown(filename, low2highuid(user), low2highgid(group));
}
@@ -141,7 +141,7 @@ asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid)
low2highuid(suid));
}
-asmlinkage long sys32_getresuid16(u16 *ruid, u16 *euid, u16 *suid)
+asmlinkage long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid)
{
int retval;
@@ -158,7 +158,7 @@ asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid)
low2highgid(sgid));
}
-asmlinkage long sys32_getresgid16(u16 *rgid, u16 *egid, u16 *sgid)
+asmlinkage long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid)
{
int retval;
@@ -179,7 +179,7 @@ asmlinkage long sys32_setfsgid16(u16 gid)
return sys_setfsgid((gid_t)gid);
}
-static int groups16_to_user(u16 *grouplist, struct group_info *group_info)
+static int groups16_to_user(u16 __user *grouplist, struct group_info *group_info)
{
int i;
u16 group;
@@ -193,7 +193,7 @@ static int groups16_to_user(u16 *grouplist, struct group_info *group_info)
return 0;
}
-static int groups16_from_user(struct group_info *group_info, u16 *grouplist)
+static int groups16_from_user(struct group_info *group_info, u16 __user *grouplist)
{
int i;
u16 group;
@@ -207,7 +207,7 @@ static int groups16_from_user(struct group_info *group_info, u16 *grouplist)
return 0;
}
-asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist)
+asmlinkage long sys32_getgroups16(int gidsetsize, u16 __user *grouplist)
{
int i;
@@ -231,7 +231,7 @@ out:
return i;
}
-asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist)
+asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist)
{
struct group_info *group_info;
int retval;
@@ -278,14 +278,14 @@ asmlinkage long sys32_getegid16(void)
/* 32-bit timeval and related flotsam. */
-static inline long get_tv32(struct timeval *o, struct compat_timeval *i)
+static inline long get_tv32(struct timeval *o, struct compat_timeval __user *i)
{
return (!access_ok(VERIFY_READ, o, sizeof(*o)) ||
(__get_user(o->tv_sec, &i->tv_sec) ||
__get_user(o->tv_usec, &i->tv_usec)));
}
-static inline long put_tv32(struct compat_timeval *o, struct timeval *i)
+static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
{
return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
(__put_user(i->tv_sec, &o->tv_sec) ||
@@ -341,7 +341,7 @@ asmlinkage long sys32_ipc(u32 call, int first, int second, int third, u32 ptr)
return -ENOSYS;
}
-asmlinkage long sys32_truncate64(const char * path, unsigned long high, unsigned long low)
+asmlinkage long sys32_truncate64(const char __user * path, unsigned long high, unsigned long low)
{
if ((int)high < 0)
return -EINVAL;
@@ -357,7 +357,7 @@ asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned
return sys_ftruncate(fd, (high << 32) | low);
}
-int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf)
+int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
{
int err;
@@ -591,7 +591,7 @@ sys32_delete_module(const char __user *name_user, unsigned int flags)
extern struct timezone sys_tz;
-asmlinkage long sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz)
+asmlinkage long sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
{
if (tv) {
struct timeval ktv;
@@ -606,7 +606,7 @@ asmlinkage long sys32_gettimeofday(struct compat_timeval *tv, struct timezone *t
return 0;
}
-static inline long get_ts32(struct timespec *o, struct compat_timeval *i)
+static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
{
long usec;
@@ -620,7 +620,7 @@ static inline long get_ts32(struct timespec *o, struct compat_timeval *i)
return 0;
}
-asmlinkage long sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz)
+asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
{
struct timespec kts;
struct timezone ktz;
@@ -645,7 +645,7 @@ asmlinkage long sys32_pause(void)
return -ERESTARTNOHAND;
}
-asmlinkage long sys32_pread64(unsigned int fd, char *ubuf,
+asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf,
size_t count, u32 poshi, u32 poslo)
{
if ((compat_ssize_t) count < 0)
@@ -653,7 +653,7 @@ asmlinkage long sys32_pread64(unsigned int fd, char *ubuf,
return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
}
-asmlinkage long sys32_pwrite64(unsigned int fd, const char *ubuf,
+asmlinkage long sys32_pwrite64(unsigned int fd, const char __user *ubuf,
size_t count, u32 poshi, u32 poslo)
{
if ((compat_ssize_t) count < 0)
@@ -666,7 +666,7 @@ asmlinkage compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 coun
return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count);
}
-asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, size_t count)
+asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, size_t count)
{
mm_segment_t old_fs = get_fs();
int ret;
@@ -686,7 +686,7 @@ asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, size
}
asmlinkage long sys32_sendfile64(int out_fd, int in_fd,
- compat_loff_t *offset, s32 count)
+ compat_loff_t __user *offset, s32 count)
{
mm_segment_t old_fs = get_fs();
int ret;
@@ -722,7 +722,7 @@ struct timex32 {
extern int do_adjtimex(struct timex *);
-asmlinkage long sys32_adjtimex(struct timex32 *utp)
+asmlinkage long sys32_adjtimex(struct timex32 __user *utp)
{
struct timex txc;
int ret;
@@ -789,12 +789,13 @@ struct __sysctl_args32 {
u32 __unused[4];
};
-asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
+asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
{
struct __sysctl_args32 tmp;
int error;
- size_t oldlen, *oldlenp = NULL;
- unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7;
+ size_t oldlen;
+ size_t __user *oldlenp = NULL;
+ unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7;
if (copy_from_user(&tmp, args, sizeof(tmp)))
return -EFAULT;
@@ -806,20 +807,20 @@ asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
basically copy the whole sysctl.c here, and
glibc's __sysctl uses rw memory for the structure
anyway. */
- if (get_user(oldlen, (u32 *)A(tmp.oldlenp)) ||
- put_user(oldlen, (size_t *)addr))
+ if (get_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp)) ||
+ put_user(oldlen, (size_t __user *)addr))
return -EFAULT;
- oldlenp = (size_t *)addr;
+ oldlenp = (size_t __user *)addr;
}
lock_kernel();
- error = do_sysctl((int *)A(tmp.name), tmp.nlen, (void *)A(tmp.oldval),
- oldlenp, (void *)A(tmp.newval), tmp.newlen);
+ error = do_sysctl(compat_ptr(tmp.name), tmp.nlen, compat_ptr(tmp.oldval),
+ oldlenp, compat_ptr(tmp.newval), tmp.newlen);
unlock_kernel();
if (oldlenp) {
if (!error) {
- if (get_user(oldlen, (size_t *)addr) ||
- put_user(oldlen, (u32 *)A(tmp.oldlenp)))
+ if (get_user(oldlen, (size_t __user *)addr) ||
+ put_user(oldlen, (u32 __user *)compat_ptr(tmp.oldlenp)))
error = -EFAULT;
}
copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
@@ -853,7 +854,7 @@ struct stat64_emu31 {
unsigned long st_ino;
};
-static int cp_stat64(struct stat64_emu31 *ubuf, struct kstat *stat)
+static int cp_stat64(struct stat64_emu31 __user *ubuf, struct kstat *stat)
{
struct stat64_emu31 tmp;
@@ -877,7 +878,7 @@ static int cp_stat64(struct stat64_emu31 *ubuf, struct kstat *stat)
return copy_to_user(ubuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
}
-asmlinkage long sys32_stat64(char * filename, struct stat64_emu31 * statbuf)
+asmlinkage long sys32_stat64(char __user * filename, struct stat64_emu31 __user * statbuf)
{
struct kstat stat;
int ret = vfs_stat(filename, &stat);
@@ -886,7 +887,7 @@ asmlinkage long sys32_stat64(char * filename, struct stat64_emu31 * statbuf)
return ret;
}
-asmlinkage long sys32_lstat64(char * filename, struct stat64_emu31 * statbuf)
+asmlinkage long sys32_lstat64(char __user * filename, struct stat64_emu31 __user * statbuf)
{
struct kstat stat;
int ret = vfs_lstat(filename, &stat);
@@ -895,7 +896,7 @@ asmlinkage long sys32_lstat64(char * filename, struct stat64_emu31 * statbuf)
return ret;
}
-asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 * statbuf)
+asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 __user * statbuf)
{
struct kstat stat;
int ret = vfs_fstat(fd, &stat);
@@ -904,6 +905,26 @@ asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 * statbuf)
return ret;
}
+asmlinkage long sys32_fstatat64(unsigned int dfd, char __user *filename,
+ struct stat64_emu31 __user* statbuf, int flag)
+{
+ struct kstat stat;
+ int error = -EINVAL;
+
+ if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+ goto out;
+
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ error = vfs_lstat_fd(dfd, filename, &stat);
+ else
+ error = vfs_stat_fd(dfd, filename, &stat);
+
+ if (!error)
+ error = cp_stat64(statbuf, &stat);
+out:
+ return error;
+}
+
/*
* Linux/i386 didn't use to be able to handle more than
* 4 system call parameters, so these system calls used a memory
@@ -952,7 +973,7 @@ out:
asmlinkage unsigned long
-old32_mmap(struct mmap_arg_struct_emu31 *arg)
+old32_mmap(struct mmap_arg_struct_emu31 __user *arg)
{
struct mmap_arg_struct_emu31 a;
int error = -EFAULT;
@@ -970,7 +991,7 @@ out:
}
asmlinkage long
-sys32_mmap2(struct mmap_arg_struct_emu31 *arg)
+sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg)
{
struct mmap_arg_struct_emu31 a;
int error = -EFAULT;
@@ -982,7 +1003,7 @@ out:
return error;
}
-asmlinkage long sys32_read(unsigned int fd, char * buf, size_t count)
+asmlinkage long sys32_read(unsigned int fd, char __user * buf, size_t count)
{
if ((compat_ssize_t) count < 0)
return -EINVAL;
@@ -990,7 +1011,7 @@ asmlinkage long sys32_read(unsigned int fd, char * buf, size_t count)
return sys_read(fd, buf, count);
}
-asmlinkage long sys32_write(unsigned int fd, char * buf, size_t count)
+asmlinkage long sys32_write(unsigned int fd, char __user * buf, size_t count)
{
if ((compat_ssize_t) count < 0)
return -EINVAL;
@@ -1002,12 +1023,12 @@ asmlinkage long sys32_clone(struct pt_regs regs)
{
unsigned long clone_flags;
unsigned long newsp;
- int *parent_tidptr, *child_tidptr;
+ int __user *parent_tidptr, *child_tidptr;
clone_flags = regs.gprs[3] & 0xffffffffUL;
newsp = regs.orig_gpr2 & 0x7fffffffUL;
- parent_tidptr = (int *) (regs.gprs[4] & 0x7fffffffUL);
- child_tidptr = (int *) (regs.gprs[5] & 0x7fffffffUL);
+ parent_tidptr = compat_ptr(regs.gprs[4]);
+ child_tidptr = compat_ptr(regs.gprs[5]);
if (!newsp)
newsp = regs.gprs[15];
return do_fork(clone_flags, newsp, &regs, 0,
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index fa2b3bc22f2..5291b5f8788 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -1,8 +1,7 @@
/*
- * arch/s390/kernel/signal32.c
+ * arch/s390/kernel/compat_signal.c
*
- * S390 version
- * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright (C) IBM Corp. 2000,2006
* Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
* Gerhard Tonn (ton@de.ibm.com)
*
@@ -52,8 +51,6 @@ typedef struct
struct ucontext32 uc;
} rt_sigframe32;
-asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
-
int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
{
int err;
@@ -161,66 +158,6 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
return err;
}
-/*
- * Atomically swap in the new signal mask, and wait for a signal.
- */
-asmlinkage int
-sys32_sigsuspend(struct pt_regs * regs,int history0, int history1, old_sigset_t mask)
-{
- sigset_t saveset;
-
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- regs->gprs[2] = -EINTR;
-
- while (1) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule();
- if (do_signal(regs, &saveset))
- return -EINTR;
- }
-}
-
-asmlinkage int
-sys32_rt_sigsuspend(struct pt_regs * regs, compat_sigset_t __user *unewset,
- size_t sigsetsize)
-{
- sigset_t saveset, newset;
- compat_sigset_t set32;
-
- /* XXX: Don't preclude handling different sized sigset_t's. */
- if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
-
- if (copy_from_user(&set32, unewset, sizeof(set32)))
- return -EFAULT;
- switch (_NSIG_WORDS) {
- case 4: newset.sig[3] = set32.sig[6] + (((long)set32.sig[7]) << 32);
- case 3: newset.sig[2] = set32.sig[4] + (((long)set32.sig[5]) << 32);
- case 2: newset.sig[1] = set32.sig[2] + (((long)set32.sig[3]) << 32);
- case 1: newset.sig[0] = set32.sig[0] + (((long)set32.sig[1]) << 32);
- }
- sigdelsetmask(&newset, ~_BLOCKABLE);
-
- spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- regs->gprs[2] = -EINTR;
-
- while (1) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule();
- if (do_signal(regs, &saveset))
- return -EINTR;
- }
-}
-
asmlinkage long
sys32_sigaction(int sig, const struct old_sigaction32 __user *act,
struct old_sigaction32 __user *oact)
@@ -258,9 +195,6 @@ sys32_sigaction(int sig, const struct old_sigaction32 __user *act,
return ret;
}
-int
-do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact);
-
asmlinkage long
sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
struct sigaction32 __user *oact, size_t sigsetsize)
@@ -520,7 +454,7 @@ static inline int map_signal(int sig)
return sig;
}
-static void setup_frame32(int sig, struct k_sigaction *ka,
+static int setup_frame32(int sig, struct k_sigaction *ka,
sigset_t *set, struct pt_regs * regs)
{
sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32));
@@ -565,13 +499,14 @@ static void setup_frame32(int sig, struct k_sigaction *ka,
/* Place signal number on stack to allow backtrace from handler. */
if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
goto give_sigsegv;
- return;
+ return 0;
give_sigsegv:
force_sigsegv(sig, current);
+ return -EFAULT;
}
-static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs * regs)
{
int err = 0;
@@ -615,31 +550,37 @@ static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->gprs[2] = map_signal(sig);
regs->gprs[3] = (__u64) &frame->info;
regs->gprs[4] = (__u64) &frame->uc;
- return;
+ return 0;
give_sigsegv:
force_sigsegv(sig, current);
+ return -EFAULT;
}
/*
* OK, we're invoking a handler
*/
-void
+int
handle_signal32(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
{
+ int ret;
+
/* Set up the stack frame */
if (ka->sa.sa_flags & SA_SIGINFO)
- setup_rt_frame32(sig, ka, info, oldset, regs);
+ ret = setup_rt_frame32(sig, ka, info, oldset, regs);
else
- setup_frame32(sig, ka, oldset, regs);
-
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ ret = setup_frame32(sig, ka, oldset, regs);
+
+ if (ret == 0) {
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
+ sigaddset(&current->blocked,sig);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+ }
+ return ret;
}
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index cfde1905d07..50e80138e7a 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1,9 +1,8 @@
/*
-* arch/s390/kernel/sys_wrapper31.S
+* arch/s390/kernel/compat_wrapper.S
* wrapper for 31 bit compatible system calls.
*
-* S390 version
-* Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+* Copyright (C) IBM Corp. 2000,2006
* Author(s): Gerhard Tonn (ton@de.ibm.com),
* Thomas Spatzier (tspat@de.ibm.com)
*/
@@ -288,7 +287,12 @@ sys32_setregid16_wrapper:
llgfr %r3,%r3 # __kernel_old_gid_emu31_t
jg sys32_setregid16 # branch to system call
-#sys32_sigsuspend_wrapper # done in sigsuspend_glue
+ .globl sys_sigsuspend_wrapper
+sys_sigsuspend_wrapper:
+ lgfr %r2,%r2 # int
+ lgfr %r3,%r3 # int
+ llgfr %r4,%r4 # old_sigset_t
+ jg sys_sigsuspend
.globl compat_sys_sigpending_wrapper
compat_sys_sigpending_wrapper:
@@ -855,7 +859,11 @@ sys32_rt_sigqueueinfo_wrapper:
llgtr %r4,%r4 # siginfo_emu31_t *
jg sys32_rt_sigqueueinfo # branch to system call
-#sys32_rt_sigsuspend_wrapper # done in rt_sigsuspend_glue
+ .globl compat_sys_rt_sigsuspend_wrapper
+compat_sys_rt_sigsuspend_wrapper:
+ llgtr %r2,%r2 # compat_sigset_t *
+ llgfr %r3,%r3 # compat_size_t
+ jg compat_sys_rt_sigsuspend
.globl sys32_pread64_wrapper
sys32_pread64_wrapper:
@@ -1475,3 +1483,128 @@ sys_inotify_rm_watch_wrapper:
lgfr %r2,%r2 # int
llgfr %r3,%r3 # u32
jg sys_inotify_rm_watch
+
+ .globl compat_sys_openat_wrapper
+compat_sys_openat_wrapper:
+ llgfr %r2,%r2 # unsigned int
+ llgtr %r3,%r3 # const char *
+ lgfr %r4,%r4 # int
+ lgfr %r5,%r5 # int
+ jg compat_sys_openat
+
+ .globl sys_mkdirat_wrapper
+sys_mkdirat_wrapper:
+ lgfr %r2,%r2 # int
+ llgtr %r3,%r3 # const char *
+ lgfr %r4,%r4 # int
+ jg sys_mkdirat
+
+ .globl sys_mknodat_wrapper
+sys_mknodat_wrapper:
+ lgfr %r2,%r2 # int
+ llgtr %r3,%r3 # const char *
+ lgfr %r4,%r4 # int
+ llgfr %r5,%r5 # unsigned int
+ jg sys_mknodat
+
+ .globl sys_fchownat_wrapper
+sys_fchownat_wrapper:
+ lgfr %r2,%r2 # int
+ llgtr %r3,%r3 # const char *
+ llgfr %r4,%r4 # uid_t
+ llgfr %r5,%r5 # gid_t
+ lgfr %r6,%r6 # int
+ jg sys_fchownat
+
+ .globl compat_sys_futimesat_wrapper
+compat_sys_futimesat_wrapper:
+ llgfr %r2,%r2 # unsigned int
+ llgtr %r3,%r3 # char *
+ llgtr %r4,%r4 # struct timeval *
+ jg compat_sys_futimesat
+
+ .globl sys32_fstatat64_wrapper
+sys32_fstatat64_wrapper:
+ llgfr %r2,%r2 # unsigned int
+ llgtr %r3,%r3 # char *
+ llgtr %r4,%r4 # struct stat64 *
+ lgfr %r5,%r5 # int
+ jg sys32_fstatat64
+
+ .globl sys_unlinkat_wrapper
+sys_unlinkat_wrapper:
+ lgfr %r2,%r2 # int
+ llgtr %r3,%r3 # const char *
+ lgfr %r4,%r4 # int
+ jg sys_unlinkat
+
+ .globl sys_renameat_wrapper
+sys_renameat_wrapper:
+ lgfr %r2,%r2 # int
+ llgtr %r3,%r3 # const char *
+ lgfr %r4,%r4 # int
+ llgtr %r5,%r5 # const char *
+ jg sys_renameat
+
+ .globl sys_linkat_wrapper
+sys_linkat_wrapper:
+ lgfr %r2,%r2 # int
+ llgtr %r3,%r3 # const char *
+ lgfr %r4,%r4 # int
+ llgtr %r5,%r5 # const char *
+ lgfr %r6,%r6 # int
+ jg sys_linkat
+
+ .globl sys_symlinkat_wrapper
+sys_symlinkat_wrapper:
+ llgtr %r2,%r2 # const char *
+ lgfr %r3,%r3 # int
+ llgtr %r4,%r4 # const char *
+ jg sys_symlinkat
+
+ .globl sys_readlinkat_wrapper
+sys_readlinkat_wrapper:
+ lgfr %r2,%r2 # int
+ llgtr %r3,%r3 # const char *
+ llgtr %r4,%r4 # char *
+ lgfr %r5,%r5 # int
+ jg sys_readlinkat
+
+ .globl sys_fchmodat_wrapper
+sys_fchmodat_wrapper:
+ lgfr %r2,%r2 # int
+ llgtr %r3,%r3 # const char *
+ llgfr %r4,%r4 # mode_t
+ jg sys_fchmodat
+
+ .globl sys_faccessat_wrapper
+sys_faccessat_wrapper:
+ lgfr %r2,%r2 # int
+ llgtr %r3,%r3 # const char *
+ lgfr %r4,%r4 # int
+ jg sys_faccessat
+
+ .globl compat_sys_pselect6_wrapper
+compat_sys_pselect6_wrapper:
+ lgfr %r2,%r2 # int
+ llgtr %r3,%r3 # fd_set *
+ llgtr %r4,%r4 # fd_set *
+ llgtr %r5,%r5 # fd_set *
+ llgtr %r6,%r6 # struct timespec *
+ llgt %r0,164(%r15) # void *
+ stg %r0,160(%r15)
+ jg compat_sys_pselect6
+
+ .globl compat_sys_ppoll_wrapper
+compat_sys_ppoll_wrapper:
+ llgtr %r2,%r2 # struct pollfd *
+ llgfr %r3,%r3 # unsigned int
+ llgtr %r4,%r4 # struct timespec *
+ llgtr %r5,%r5 # const sigset_t *
+ llgfr %r6,%r6 # size_t
+ jg compat_sys_ppoll
+
+ .globl sys_unshare_wrapper
+sys_unshare_wrapper:
+ llgfr %r2,%r2 # unsigned long
+ jg sys_unshare
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 27b07730b7b..b2448487854 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -2,8 +2,7 @@
* arch/s390/kernel/entry.S
* S390 low-level entry points.
*
- * S390 version
- * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright (C) IBM Corp. 1999,2006
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
* Hartmut Penner (hp@de.ibm.com),
* Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
@@ -50,9 +49,10 @@ SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC
SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP
SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
-_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING | \
- _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
-_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
+_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
+ _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
+_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
+ _TIF_MCCK_PENDING)
STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
STACK_SIZE = 1 << STACK_SHIFT
@@ -251,8 +251,8 @@ sysc_work:
bo BASED(sysc_mcck_pending)
tm __TI_flags+3(%r9),_TIF_NEED_RESCHED
bo BASED(sysc_reschedule)
- tm __TI_flags+3(%r9),_TIF_SIGPENDING
- bo BASED(sysc_sigpending)
+ tm __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
+ bnz BASED(sysc_sigpending)
tm __TI_flags+3(%r9),_TIF_RESTART_SVC
bo BASED(sysc_restart)
tm __TI_flags+3(%r9),_TIF_SINGLE_STEP
@@ -276,12 +276,11 @@ sysc_mcck_pending:
br %r1 # TIF bit will be cleared by handler
#
-# _TIF_SIGPENDING is set, call do_signal
+# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
#
sysc_sigpending:
ni __TI_flags+3(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
la %r2,SP_PTREGS(%r15) # load pt_regs
- sr %r3,%r3 # clear *oldset
l %r1,BASED(.Ldo_signal)
basr %r14,%r1 # call do_signal
tm __TI_flags+3(%r9),_TIF_RESTART_SVC
@@ -397,30 +396,6 @@ sys_rt_sigreturn_glue:
l %r1,BASED(.Lrt_sigreturn)
br %r1 # branch to sys_sigreturn
-#
-# sigsuspend and rt_sigsuspend need pt_regs as an additional
-# parameter and they have to skip the store of %r2 into the
-# user register %r2 because the return value was set in
-# sigsuspend and rt_sigsuspend already and must not be overwritten!
-#
-
-sys_sigsuspend_glue:
- lr %r5,%r4 # move mask back
- lr %r4,%r3 # move history1 parameter
- lr %r3,%r2 # move history0 parameter
- la %r2,SP_PTREGS(%r15) # load pt_regs as first parameter
- l %r1,BASED(.Lsigsuspend)
- la %r14,4(%r14) # skip store of return value
- br %r1 # branch to sys_sigsuspend
-
-sys_rt_sigsuspend_glue:
- lr %r4,%r3 # move sigsetsize parameter
- lr %r3,%r2 # move unewset parameter
- la %r2,SP_PTREGS(%r15) # load pt_regs as first parameter
- l %r1,BASED(.Lrt_sigsuspend)
- la %r14,4(%r14) # skip store of return value
- br %r1 # branch to sys_rt_sigsuspend
-
sys_sigaltstack_glue:
la %r4,SP_PTREGS(%r15) # load pt_regs as parameter
l %r1,BASED(.Lsigaltstack)
@@ -604,15 +579,16 @@ io_work:
lr %r15,%r1
#
# One of the work bits is on. Find out which one.
-# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED and _TIF_MCCK_PENDING
+# Checked are: _TIF_SIGPENDING, _TIF_RESTORE_SIGMASK, _TIF_NEED_RESCHED
+# and _TIF_MCCK_PENDING
#
io_work_loop:
tm __TI_flags+3(%r9),_TIF_MCCK_PENDING
bo BASED(io_mcck_pending)
tm __TI_flags+3(%r9),_TIF_NEED_RESCHED
bo BASED(io_reschedule)
- tm __TI_flags+3(%r9),_TIF_SIGPENDING
- bo BASED(io_sigpending)
+ tm __TI_flags+3(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
+ bnz BASED(io_sigpending)
b BASED(io_leave)
#
@@ -636,12 +612,11 @@ io_reschedule:
b BASED(io_work_loop)
#
-# _TIF_SIGPENDING is set, call do_signal
+# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
#
io_sigpending:
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
la %r2,SP_PTREGS(%r15) # load pt_regs
- sr %r3,%r3 # clear *oldset
l %r1,BASED(.Ldo_signal)
basr %r14,%r1 # call do_signal
stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 369ab4413ec..2ac095bc0e2 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -1,9 +1,8 @@
/*
- * arch/s390/kernel/entry.S
+ * arch/s390/kernel/entry64.S
* S390 low-level entry points.
*
- * S390 version
- * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright (C) IBM Corp. 1999,2006
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
* Hartmut Penner (hp@de.ibm.com),
* Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
@@ -53,9 +52,10 @@ SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
STACK_SIZE = 1 << STACK_SHIFT
-_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING | \
- _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
-_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
+_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
+ _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
+_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
+ _TIF_MCCK_PENDING)
#define BASED(name) name-system_call(%r13)
@@ -249,8 +249,8 @@ sysc_work:
jo sysc_mcck_pending
tm __TI_flags+7(%r9),_TIF_NEED_RESCHED
jo sysc_reschedule
- tm __TI_flags+7(%r9),_TIF_SIGPENDING
- jo sysc_sigpending
+ tm __TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
+ jnz sysc_sigpending
tm __TI_flags+7(%r9),_TIF_RESTART_SVC
jo sysc_restart
tm __TI_flags+7(%r9),_TIF_SINGLE_STEP
@@ -272,12 +272,11 @@ sysc_mcck_pending:
jg s390_handle_mcck # TIF bit will be cleared by handler
#
-# _TIF_SIGPENDING is set, call do_signal
+# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
#
sysc_sigpending:
ni __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP
la %r2,SP_PTREGS(%r15) # load pt_regs
- sgr %r3,%r3 # clear *oldset
brasl %r14,do_signal # call do_signal
tm __TI_flags+7(%r9),_TIF_RESTART_SVC
jo sysc_restart
@@ -414,52 +413,6 @@ sys32_rt_sigreturn_glue:
jg sys32_rt_sigreturn # branch to sys32_sigreturn
#endif
-#
-# sigsuspend and rt_sigsuspend need pt_regs as an additional
-# parameter and they have to skip the store of %r2 into the
-# user register %r2 because the return value was set in
-# sigsuspend and rt_sigsuspend already and must not be overwritten!
-#
-
-sys_sigsuspend_glue:
- lgr %r5,%r4 # move mask back
- lgr %r4,%r3 # move history1 parameter
- lgr %r3,%r2 # move history0 parameter
- la %r2,SP_PTREGS(%r15) # load pt_regs as first parameter
- la %r14,6(%r14) # skip store of return value
- jg sys_sigsuspend # branch to sys_sigsuspend
-
-#ifdef CONFIG_COMPAT
-sys32_sigsuspend_glue:
- llgfr %r4,%r4 # unsigned long
- lgr %r5,%r4 # move mask back
- lgfr %r3,%r3 # int
- lgr %r4,%r3 # move history1 parameter
- lgfr %r2,%r2 # int
- lgr %r3,%r2 # move history0 parameter
- la %r2,SP_PTREGS(%r15) # load pt_regs as first parameter
- la %r14,6(%r14) # skip store of return value
- jg sys32_sigsuspend # branch to sys32_sigsuspend
-#endif
-
-sys_rt_sigsuspend_glue:
- lgr %r4,%r3 # move sigsetsize parameter
- lgr %r3,%r2 # move unewset parameter
- la %r2,SP_PTREGS(%r15) # load pt_regs as first parameter
- la %r14,6(%r14) # skip store of return value
- jg sys_rt_sigsuspend # branch to sys_rt_sigsuspend
-
-#ifdef CONFIG_COMPAT
-sys32_rt_sigsuspend_glue:
- llgfr %r3,%r3 # size_t
- lgr %r4,%r3 # move sigsetsize parameter
- llgtr %r2,%r2 # sigset_emu31_t *
- lgr %r3,%r2 # move unewset parameter
- la %r2,SP_PTREGS(%r15) # load pt_regs as first parameter
- la %r14,6(%r14) # skip store of return value
- jg sys32_rt_sigsuspend # branch to sys32_rt_sigsuspend
-#endif
-
sys_sigaltstack_glue:
la %r4,SP_PTREGS(%r15) # load pt_regs as parameter
jg sys_sigaltstack # branch to sys_sigreturn
@@ -646,15 +599,16 @@ io_work:
lgr %r15,%r1
#
# One of the work bits is on. Find out which one.
-# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED and _TIF_MCCK_PENDING
+# Checked are: _TIF_SIGPENDING, _TIF_RESTORE_SIGPENDING, _TIF_NEED_RESCHED
+# and _TIF_MCCK_PENDING
#
io_work_loop:
tm __TI_flags+7(%r9),_TIF_MCCK_PENDING
jo io_mcck_pending
tm __TI_flags+7(%r9),_TIF_NEED_RESCHED
jo io_reschedule
- tm __TI_flags+7(%r9),_TIF_SIGPENDING
- jo io_sigpending
+ tm __TI_flags+7(%r9),(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)
+ jnz io_sigpending
j io_leave
#
@@ -676,12 +630,11 @@ io_reschedule:
j io_work_loop
#
-# _TIF_SIGPENDING is set, call do_signal
+# _TIF_SIGPENDING or _TIF_RESTORE_SIGMASK is set, call do_signal
#
io_sigpending:
stosm __SF_EMPTY(%r15),0x03 # reenable interrupts
la %r2,SP_PTREGS(%r15) # load pt_regs
- slgr %r3,%r3 # clear *oldset
brasl %r14,do_signal # call do_signal
stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
j io_work_loop
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c
index f0ed5c642c7..bad81b5832d 100644
--- a/arch/s390/kernel/machine_kexec.c
+++ b/arch/s390/kernel/machine_kexec.c
@@ -12,15 +12,16 @@
* on the S390 architecture.
*/
-#include <asm/cio.h>
-#include <asm/setup.h>
#include <linux/device.h>
#include <linux/mm.h>
#include <linux/kexec.h>
#include <linux/delay.h>
+#include <asm/cio.h>
+#include <asm/setup.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/system.h>
+#include <asm/smp.h>
static void kexec_halt_all_cpus(void *);
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 008c74526fd..da6fbae8df9 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -128,8 +128,10 @@ void default_idle(void)
__ctl_set_bit(8, 15);
#ifdef CONFIG_HOTPLUG_CPU
- if (cpu_is_offline(cpu))
+ if (cpu_is_offline(cpu)) {
+ preempt_enable_no_resched();
cpu_die();
+ }
#endif
local_mcck_disable();
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index de878426747..24f62f16c0e 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -600,6 +600,7 @@ setup_arch(char **cmdline_p)
init_mm.brk = (unsigned long) &_end;
parse_cmdline_early(cmdline_p);
+ parse_early_param();
setup_memory();
setup_resources();
@@ -607,6 +608,7 @@ setup_arch(char **cmdline_p)
cpu_init();
__cpu_logical_map[0] = S390_lowcore.cpu_data.cpu_addr;
+ smp_setup_cpu_possible_map();
/*
* Create kernel page tables and switch to virtual addressing.
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 6ae4a77270b..ae1927e48cf 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -1,8 +1,7 @@
/*
* arch/s390/kernel/signal.c
*
- * S390 version
- * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright (C) IBM Corp. 1999,2006
* Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
*
* Based on Intel version
@@ -51,60 +50,24 @@ typedef struct
struct ucontext uc;
} rt_sigframe;
-int do_signal(struct pt_regs *regs, sigset_t *oldset);
-
/*
* Atomically swap in the new signal mask, and wait for a signal.
*/
asmlinkage int
-sys_sigsuspend(struct pt_regs * regs, int history0, int history1,
- old_sigset_t mask)
+sys_sigsuspend(int history0, int history1, old_sigset_t mask)
{
- sigset_t saveset;
-
mask &= _BLOCKABLE;
spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
+ current->saved_sigmask = current->blocked;
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
- regs->gprs[2] = -EINTR;
-
- while (1) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule();
- if (do_signal(regs, &saveset))
- return -EINTR;
- }
-}
-
-asmlinkage long
-sys_rt_sigsuspend(struct pt_regs *regs, sigset_t __user *unewset,
- size_t sigsetsize)
-{
- sigset_t saveset, newset;
- /* XXX: Don't preclude handling different sized sigset_t's. */
- if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ set_thread_flag(TIF_RESTORE_SIGMASK);
- if (copy_from_user(&newset, unewset, sizeof(newset)))
- return -EFAULT;
- sigdelsetmask(&newset, ~_BLOCKABLE);
-
- spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- regs->gprs[2] = -EINTR;
-
- while (1) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule();
- if (do_signal(regs, &saveset))
- return -EINTR;
- }
+ return -ERESTARTNOHAND;
}
asmlinkage long
@@ -306,8 +269,8 @@ static inline int map_signal(int sig)
return sig;
}
-static void setup_frame(int sig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs * regs)
+static int setup_frame(int sig, struct k_sigaction *ka,
+ sigset_t *set, struct pt_regs * regs)
{
sigframe __user *frame;
@@ -355,13 +318,14 @@ static void setup_frame(int sig, struct k_sigaction *ka,
/* Place signal number on stack to allow backtrace from handler. */
if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
goto give_sigsegv;
- return;
+ return 0;
give_sigsegv:
force_sigsegv(sig, current);
+ return -EFAULT;
}
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs * regs)
{
int err = 0;
@@ -409,32 +373,39 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->gprs[2] = map_signal(sig);
regs->gprs[3] = (unsigned long) &frame->info;
regs->gprs[4] = (unsigned long) &frame->uc;
- return;
+ return 0;
give_sigsegv:
force_sigsegv(sig, current);
+ return -EFAULT;
}
/*
* OK, we're invoking a handler
*/
-static void
+static int
handle_signal(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
{
+ int ret;
+
/* Set up the stack frame */
if (ka->sa.sa_flags & SA_SIGINFO)
- setup_rt_frame(sig, ka, info, oldset, regs);
+ ret = setup_rt_frame(sig, ka, info, oldset, regs);
else
- setup_frame(sig, ka, oldset, regs);
+ ret = setup_frame(sig, ka, oldset, regs);
+
+ if (ret == 0) {
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
+ sigaddset(&current->blocked,sig);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+ }
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ return ret;
}
/*
@@ -446,12 +417,13 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
* the kernel can handle, and then we build all the user-level signal handling
* stack-frames in one go after that.
*/
-int do_signal(struct pt_regs *regs, sigset_t *oldset)
+void do_signal(struct pt_regs *regs)
{
unsigned long retval = 0, continue_addr = 0, restart_addr = 0;
siginfo_t info;
int signr;
struct k_sigaction ka;
+ sigset_t *oldset;
/*
* We want the common case to go fast, which
@@ -460,9 +432,11 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
* if so.
*/
if (!user_mode(regs))
- return 1;
+ return;
- if (!oldset)
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = &current->saved_sigmask;
+ else
oldset = &current->blocked;
/* Are we from a system call? */
@@ -473,12 +447,14 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
/* Prepare for system call restart. We do this here so that a
debugger will see the already changed PSW. */
- if (retval == -ERESTARTNOHAND ||
- retval == -ERESTARTSYS ||
- retval == -ERESTARTNOINTR) {
+ switch (retval) {
+ case -ERESTARTNOHAND:
+ case -ERESTARTSYS:
+ case -ERESTARTNOINTR:
regs->gprs[2] = regs->orig_gpr2;
regs->psw.addr = restart_addr;
- } else if (retval == -ERESTART_RESTARTBLOCK) {
+ break;
+ case -ERESTART_RESTARTBLOCK:
regs->gprs[2] = -EINTR;
}
}
@@ -503,17 +479,38 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
/* Whee! Actually deliver the signal. */
#ifdef CONFIG_COMPAT
if (test_thread_flag(TIF_31BIT)) {
- extern void handle_signal32(unsigned long sig,
- struct k_sigaction *ka,
- siginfo_t *info,
- sigset_t *oldset,
- struct pt_regs *regs);
- handle_signal32(signr, &ka, &info, oldset, regs);
- return 1;
+ extern int handle_signal32(unsigned long sig,
+ struct k_sigaction *ka,
+ siginfo_t *info,
+ sigset_t *oldset,
+ struct pt_regs *regs);
+ if (handle_signal32(
+ signr, &ka, &info, oldset, regs) == 0) {
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ }
+ return;
}
#endif
- handle_signal(signr, &ka, &info, oldset, regs);
- return 1;
+ if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
+ /*
+ * A signal was successfully delivered; the saved
+ * sigmask will have been stored in the signal frame,
+ * and will be restored by sigreturn, so we can simply
+ * clear the TIF_RESTORE_SIGMASK flag.
+ */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ }
+ return;
+ }
+
+ /*
+ * If there's no signal to deliver, we just put the saved sigmask back.
+ */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
/* Restart a different system call. */
@@ -522,5 +519,4 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
regs->gprs[2] = __NR_restart_syscall;
set_thread_flag(TIF_RESTART_SVC);
}
- return 0;
}
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index cbfcfd02a43..7dbe00c76c6 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -1,8 +1,7 @@
/*
* arch/s390/kernel/smp.c
*
- * S390 version
- * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright (C) IBM Corp. 1999,2006
* Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
* Martin Schwidefsky (schwidefsky@de.ibm.com)
* Heiko Carstens (heiko.carstens@de.ibm.com)
@@ -41,8 +40,6 @@
#include <asm/cpcmd.h>
#include <asm/tlbflush.h>
-/* prototypes */
-
extern volatile int __cpu_logical_map[];
/*
@@ -51,13 +48,11 @@ extern volatile int __cpu_logical_map[];
struct _lowcore *lowcore_ptr[NR_CPUS];
-cpumask_t cpu_online_map;
-cpumask_t cpu_possible_map;
+cpumask_t cpu_online_map = CPU_MASK_NONE;
+cpumask_t cpu_possible_map = CPU_MASK_NONE;
static struct task_struct *current_set[NR_CPUS];
-EXPORT_SYMBOL(cpu_online_map);
-
/*
* Reboot, halt and power_off routines for SMP.
*/
@@ -490,10 +485,10 @@ void smp_ctl_clear_bit(int cr, int bit) {
* Lets check how many CPUs we have.
*/
-void
-__init smp_check_cpus(unsigned int max_cpus)
+static unsigned int
+__init smp_count_cpus(void)
{
- int cpu, num_cpus;
+ unsigned int cpu, num_cpus;
__u16 boot_cpu_addr;
/*
@@ -503,22 +498,20 @@ __init smp_check_cpus(unsigned int max_cpus)
boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
current_thread_info()->cpu = 0;
num_cpus = 1;
- for (cpu = 0; cpu <= 65535 && num_cpus < max_cpus; cpu++) {
+ for (cpu = 0; cpu <= 65535; cpu++) {
if ((__u16) cpu == boot_cpu_addr)
continue;
- __cpu_logical_map[num_cpus] = (__u16) cpu;
- if (signal_processor(num_cpus, sigp_sense) ==
+ __cpu_logical_map[1] = (__u16) cpu;
+ if (signal_processor(1, sigp_sense) ==
sigp_not_operational)
continue;
- cpu_set(num_cpus, cpu_present_map);
num_cpus++;
}
- for (cpu = 1; cpu < max_cpus; cpu++)
- cpu_set(cpu, cpu_possible_map);
-
printk("Detected %d CPU's\n",(int) num_cpus);
printk("Boot cpu address %2X\n", boot_cpu_addr);
+
+ return num_cpus;
}
/*
@@ -679,6 +672,44 @@ __cpu_up(unsigned int cpu)
return 0;
}
+static unsigned int __initdata additional_cpus;
+static unsigned int __initdata possible_cpus;
+
+void __init smp_setup_cpu_possible_map(void)
+{
+ unsigned int phy_cpus, pos_cpus, cpu;
+
+ phy_cpus = smp_count_cpus();
+ pos_cpus = min(phy_cpus + additional_cpus, (unsigned int) NR_CPUS);
+
+ if (possible_cpus)
+ pos_cpus = min(possible_cpus, (unsigned int) NR_CPUS);
+
+ for (cpu = 0; cpu < pos_cpus; cpu++)
+ cpu_set(cpu, cpu_possible_map);
+
+ phy_cpus = min(phy_cpus, pos_cpus);
+
+ for (cpu = 0; cpu < phy_cpus; cpu++)
+ cpu_set(cpu, cpu_present_map);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+static int __init setup_additional_cpus(char *s)
+{
+ additional_cpus = simple_strtoul(s, NULL, 0);
+ return 0;
+}
+early_param("additional_cpus", setup_additional_cpus);
+
+static int __init setup_possible_cpus(char *s)
+{
+ possible_cpus = simple_strtoul(s, NULL, 0);
+ return 0;
+}
+early_param("possible_cpus", setup_possible_cpus);
+
int
__cpu_disable(void)
{
@@ -747,6 +778,8 @@ cpu_die(void)
for(;;);
}
+#endif /* CONFIG_HOTPLUG_CPU */
+
/*
* Cycle through the processors and setup structures.
*/
@@ -760,7 +793,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
/* request the 0x1201 emergency signal external interrupt */
if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0)
panic("Couldn't request external interrupt 0x1201");
- smp_check_cpus(max_cpus);
memset(lowcore_ptr,0,sizeof(lowcore_ptr));
/*
* Initialize prefix pages and stacks for all possible cpus
@@ -809,8 +841,6 @@ void __devinit smp_prepare_boot_cpu(void)
BUG_ON(smp_processor_id() != 0);
cpu_set(0, cpu_online_map);
- cpu_set(0, cpu_present_map);
- cpu_set(0, cpu_possible_map);
S390_lowcore.percpu_offset = __per_cpu_offset[0];
current_set[0] = current;
}
@@ -849,6 +879,7 @@ static int __init topology_init(void)
subsys_initcall(topology_init);
+EXPORT_SYMBOL(cpu_online_map);
EXPORT_SYMBOL(cpu_possible_map);
EXPORT_SYMBOL(lowcore_ptr);
EXPORT_SYMBOL(smp_ctl_set_bit);
diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c
index 6a63553493c..e351780bb66 100644
--- a/arch/s390/kernel/sys_s390.c
+++ b/arch/s390/kernel/sys_s390.c
@@ -122,8 +122,8 @@ out:
#ifndef CONFIG_64BIT
struct sel_arg_struct {
unsigned long n;
- fd_set *inp, *outp, *exp;
- struct timeval *tvp;
+ fd_set __user *inp, *outp, *exp;
+ struct timeval __user *tvp;
};
asmlinkage long old_select(struct sel_arg_struct __user *arg)
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 426d7cafdab..7c88d85c359 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -80,7 +80,7 @@ NI_SYSCALL /* old sgetmask syscall*/
NI_SYSCALL /* old ssetmask syscall*/
SYSCALL(sys_setreuid16,sys_ni_syscall,sys32_setreuid16_wrapper) /* old setreuid16 syscall */
SYSCALL(sys_setregid16,sys_ni_syscall,sys32_setregid16_wrapper) /* old setregid16 syscall */
-SYSCALL(sys_sigsuspend_glue,sys_sigsuspend_glue,sys32_sigsuspend_glue)
+SYSCALL(sys_sigsuspend,sys_sigsuspend,sys_sigsuspend_wrapper)
SYSCALL(sys_sigpending,sys_sigpending,compat_sys_sigpending_wrapper)
SYSCALL(sys_sethostname,sys_sethostname,sys32_sethostname_wrapper)
SYSCALL(sys_setrlimit,sys_setrlimit,compat_sys_setrlimit_wrapper) /* 75 */
@@ -187,7 +187,7 @@ SYSCALL(sys_rt_sigprocmask,sys_rt_sigprocmask,sys32_rt_sigprocmask_wrapper) /* 1
SYSCALL(sys_rt_sigpending,sys_rt_sigpending,sys32_rt_sigpending_wrapper)
SYSCALL(sys_rt_sigtimedwait,sys_rt_sigtimedwait,compat_sys_rt_sigtimedwait_wrapper)
SYSCALL(sys_rt_sigqueueinfo,sys_rt_sigqueueinfo,sys32_rt_sigqueueinfo_wrapper)
-SYSCALL(sys_rt_sigsuspend_glue,sys_rt_sigsuspend_glue,sys32_rt_sigsuspend_glue)
+SYSCALL(sys_rt_sigsuspend,sys_rt_sigsuspend,compat_sys_rt_sigsuspend_wrapper)
SYSCALL(sys_pread64,sys_pread64,sys32_pread64_wrapper) /* 180 */
SYSCALL(sys_pwrite64,sys_pwrite64,sys32_pwrite64_wrapper)
SYSCALL(sys_chown16,sys_ni_syscall,sys32_chown16_wrapper) /* old chown16 syscall */
@@ -293,5 +293,22 @@ SYSCALL(sys_waitid,sys_waitid,compat_sys_waitid_wrapper)
SYSCALL(sys_ioprio_set,sys_ioprio_set,sys_ioprio_set_wrapper)
SYSCALL(sys_ioprio_get,sys_ioprio_get,sys_ioprio_get_wrapper)
SYSCALL(sys_inotify_init,sys_inotify_init,sys_inotify_init)
-SYSCALL(sys_inotify_add_watch,sys_inotify_add_watch,sys_inotify_add_watch_wrapper)
+SYSCALL(sys_inotify_add_watch,sys_inotify_add_watch,sys_inotify_add_watch_wrapper) /* 285 */
SYSCALL(sys_inotify_rm_watch,sys_inotify_rm_watch,sys_inotify_rm_watch_wrapper)
+NI_SYSCALL /* 287 sys_migrate_pages */
+SYSCALL(sys_openat,sys_openat,compat_sys_openat_wrapper)
+SYSCALL(sys_mkdirat,sys_mkdirat,sys_mkdirat_wrapper)
+SYSCALL(sys_mknodat,sys_mknodat,sys_mknodat_wrapper) /* 290 */
+SYSCALL(sys_fchownat,sys_fchownat,sys_fchownat_wrapper)
+SYSCALL(sys_futimesat,sys_futimesat,compat_sys_futimesat_wrapper)
+SYSCALL(sys_fstatat64,sys_newfstatat,sys32_fstatat64_wrapper)
+SYSCALL(sys_unlinkat,sys_unlinkat,sys_unlinkat_wrapper)
+SYSCALL(sys_renameat,sys_renameat,sys_renameat_wrapper) /* 295 */
+SYSCALL(sys_linkat,sys_linkat,sys_linkat_wrapper)
+SYSCALL(sys_symlinkat,sys_symlinkat,sys_symlinkat_wrapper)
+SYSCALL(sys_readlinkat,sys_readlinkat,sys_readlinkat_wrapper)
+SYSCALL(sys_fchmodat,sys_fchmodat,sys_fchmodat_wrapper)
+SYSCALL(sys_faccessat,sys_faccessat,sys_faccessat_wrapper) /* 300 */
+SYSCALL(sys_pselect6,sys_pselect6,compat_sys_pselect6_wrapper)
+SYSCALL(sys_ppoll,sys_ppoll,compat_sys_ppoll_wrapper)
+SYSCALL(sys_unshare,sys_unshare,sys_unshare_wrapper)
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 7c0fe152a11..fea043b69b9 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -61,9 +61,18 @@ extern unsigned long wall_jiffies;
*/
unsigned long long sched_clock(void)
{
- return ((get_clock() - jiffies_timer_cc) * 1000) >> 12;
+ return ((get_clock() - jiffies_timer_cc) * 125) >> 9;
}
+/*
+ * Monotonic_clock - returns # of nanoseconds passed since time_init()
+ */
+unsigned long long monotonic_clock(void)
+{
+ return sched_clock();
+}
+EXPORT_SYMBOL(monotonic_clock);
+
void tod_to_timeval(__u64 todval, struct timespec *xtime)
{
unsigned long long sec;
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 5d21e9e6e7b..a46793beedd 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -486,7 +486,7 @@ asmlinkage void illegal_op(struct pt_regs * regs, long interruption_code)
info.si_signo = signal;
info.si_errno = 0;
info.si_code = ILL_ILLOPC;
- info.si_addr = (void *) location;
+ info.si_addr = (void __user *) location;
do_trap(interruption_code, signal,
"illegal operation", regs, &info);
}
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
index f20b51ff1d8..e05d087a6ea 100644
--- a/arch/s390/lib/Makefile
+++ b/arch/s390/lib/Makefile
@@ -6,4 +6,4 @@ EXTRA_AFLAGS := -traditional
lib-y += delay.o string.o
lib-y += $(if $(CONFIG_64BIT),uaccess64.o,uaccess.o)
-lib-$(CONFIG_SMP) += spinlock.o \ No newline at end of file
+lib-$(CONFIG_SMP) += spinlock.o
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c
index e96c35bddac..71f0a2fb307 100644
--- a/arch/s390/lib/delay.c
+++ b/arch/s390/lib/delay.c
@@ -30,7 +30,7 @@ void __delay(unsigned long loops)
*/
__asm__ __volatile__(
"0: brct %0,0b"
- : /* no outputs */ : "r" (loops/2) );
+ : /* no outputs */ : "r" ((loops/2) + 1));
}
/*
diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c
index 60f80a4eed4..b9b7958a226 100644
--- a/arch/s390/lib/spinlock.c
+++ b/arch/s390/lib/spinlock.c
@@ -2,8 +2,7 @@
* arch/s390/lib/spinlock.c
* Out of line spinlock code.
*
- * S390 version
- * Copyright (C) 2004 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright (C) IBM Corp. 2004, 2006
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
*/
@@ -44,6 +43,8 @@ _raw_spin_lock_wait(raw_spinlock_t *lp, unsigned int pc)
_diag44();
count = spin_retry;
}
+ if (__raw_spin_is_locked(lp))
+ continue;
if (_raw_compare_and_swap(&lp->lock, 0, pc) == 0)
return;
}
@@ -56,6 +57,8 @@ _raw_spin_trylock_retry(raw_spinlock_t *lp, unsigned int pc)
int count = spin_retry;
while (count-- > 0) {
+ if (__raw_spin_is_locked(lp))
+ continue;
if (_raw_compare_and_swap(&lp->lock, 0, pc) == 0)
return 1;
}
@@ -74,6 +77,8 @@ _raw_read_lock_wait(raw_rwlock_t *rw)
_diag44();
count = spin_retry;
}
+ if (!__raw_read_can_lock(rw))
+ continue;
old = rw->lock & 0x7fffffffU;
if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old)
return;
@@ -88,6 +93,8 @@ _raw_read_trylock_retry(raw_rwlock_t *rw)
int count = spin_retry;
while (count-- > 0) {
+ if (!__raw_read_can_lock(rw))
+ continue;
old = rw->lock & 0x7fffffffU;
if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old)
return 1;
@@ -106,6 +113,8 @@ _raw_write_lock_wait(raw_rwlock_t *rw)
_diag44();
count = spin_retry;
}
+ if (!__raw_write_can_lock(rw))
+ continue;
if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
return;
}
@@ -118,6 +127,8 @@ _raw_write_trylock_retry(raw_rwlock_t *rw)
int count = spin_retry;
while (count-- > 0) {
+ if (!__raw_write_can_lock(rw))
+ continue;
if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)
return 1;
}
diff --git a/arch/s390/lib/uaccess.S b/arch/s390/lib/uaccess.S
index 88fc94fe648..5d59e262504 100644
--- a/arch/s390/lib/uaccess.S
+++ b/arch/s390/lib/uaccess.S
@@ -198,12 +198,12 @@ __strnlen_user_asm:
0: srst %r2,%r1
jo 0b
sacf 0
- jh 1f # \0 found in string ?
ahi %r2,1 # strnlen_user result includes the \0
-1: slr %r2,%r3
+ # or return count+1 if \0 not found
+ slr %r2,%r3
br %r14
2: sacf 0
- lhi %r2,-EFAULT
+ slr %r2,%r2 # return 0 on exception
br %r14
.section __ex_table,"a"
.long 0b,2b
diff --git a/arch/s390/lib/uaccess64.S b/arch/s390/lib/uaccess64.S
index 50219786fc7..19b41a33c23 100644
--- a/arch/s390/lib/uaccess64.S
+++ b/arch/s390/lib/uaccess64.S
@@ -194,12 +194,12 @@ __strnlen_user_asm:
0: srst %r2,%r1
jo 0b
sacf 0
- jh 1f # \0 found in string ?
aghi %r2,1 # strnlen_user result includes the \0
-1: slgr %r2,%r3
+ # or return count+1 if \0 not found
+ slgr %r2,%r3
br %r14
2: sacf 0
- lghi %r2,-EFAULT
+ slgr %r2,%r2 # return 0 on exception
br %r14
.section __ex_table,"a"
.quad 0b,2b
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index 2d5cb138575..b075ab499d0 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -42,8 +42,8 @@ static volatile long cmm_timed_pages_target = 0;
static long cmm_timeout_pages = 0;
static long cmm_timeout_seconds = 0;
-static struct cmm_page_array *cmm_page_list = 0;
-static struct cmm_page_array *cmm_timed_page_list = 0;
+static struct cmm_page_array *cmm_page_list = NULL;
+static struct cmm_page_array *cmm_timed_page_list = NULL;
static unsigned long cmm_thread_active = 0;
static struct work_struct cmm_thread_starter;
@@ -259,7 +259,7 @@ static struct ctl_table cmm_table[];
static int
cmm_pages_handler(ctl_table *ctl, int write, struct file *filp,
- void *buffer, size_t *lenp, loff_t *ppos)
+ void __user *buffer, size_t *lenp, loff_t *ppos)
{
char buf[16], *p;
long pages;
@@ -300,7 +300,7 @@ cmm_pages_handler(ctl_table *ctl, int write, struct file *filp,
static int
cmm_timeout_handler(ctl_table *ctl, int write, struct file *filp,
- void *buffer, size_t *lenp, loff_t *ppos)
+ void __user *buffer, size_t *lenp, loff_t *ppos)
{
char buf[64], *p;
long pages, seconds;
@@ -419,7 +419,7 @@ cmm_init (void)
#ifdef CONFIG_CMM_IUCV
smsg_register_callback(SMSG_PREFIX, cmm_smsg_target);
#endif
- INIT_WORK(&cmm_thread_starter, (void *) cmm_start_thread, 0);
+ INIT_WORK(&cmm_thread_starter, (void *) cmm_start_thread, NULL);
init_waitqueue_head(&cmm_thread_wait);
init_timer(&cmm_timer);
return 0;