diff options
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r-- | arch/s390/kernel/compat_linux.c | 103 | ||||
-rw-r--r-- | arch/s390/kernel/compat_signal.c | 105 | ||||
-rw-r--r-- | arch/s390/kernel/compat_wrapper.S | 143 | ||||
-rw-r--r-- | arch/s390/kernel/entry.S | 51 | ||||
-rw-r--r-- | arch/s390/kernel/entry64.S | 75 | ||||
-rw-r--r-- | arch/s390/kernel/machine_kexec.c | 5 | ||||
-rw-r--r-- | arch/s390/kernel/process.c | 4 | ||||
-rw-r--r-- | arch/s390/kernel/setup.c | 2 | ||||
-rw-r--r-- | arch/s390/kernel/signal.c | 146 | ||||
-rw-r--r-- | arch/s390/kernel/smp.c | 73 | ||||
-rw-r--r-- | arch/s390/kernel/sys_s390.c | 4 | ||||
-rw-r--r-- | arch/s390/kernel/syscalls.S | 23 | ||||
-rw-r--r-- | arch/s390/kernel/time.c | 11 | ||||
-rw-r--r-- | arch/s390/kernel/traps.c | 2 |
14 files changed, 414 insertions, 333 deletions
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, ®s, 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(¤t->sighand->siglock); - saveset = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->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(¤t->sighand->siglock); - saveset = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->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(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked,sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + ret = setup_frame32(sig, ka, oldset, regs); + + if (ret == 0) { + spin_lock_irq(¤t->sighand->siglock); + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + if (!(ka->sa.sa_flags & SA_NODEFER)) + sigaddset(¤t->blocked,sig); + recalc_sigpending(); + spin_unlock_irq(¤t->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(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; siginitset(¤t->blocked, mask); recalc_sigpending(); spin_unlock_irq(¤t->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(¤t->sighand->siglock); - saveset = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->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(¤t->sighand->siglock); + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + if (!(ka->sa.sa_flags & SA_NODEFER)) + sigaddset(¤t->blocked,sig); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + } - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked,sig); - recalc_sigpending(); - spin_unlock_irq(¤t->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 = ¤t->saved_sigmask; + else oldset = ¤t->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, ¤t->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); } |