diff options
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r-- | arch/mips/kernel/binfmt_elfn32.c | 5 | ||||
-rw-r--r-- | arch/mips/kernel/binfmt_elfo32.c | 5 | ||||
-rw-r--r-- | arch/mips/kernel/linux32.c | 22 | ||||
-rw-r--r-- | arch/mips/kernel/scall32-o32.S | 2 | ||||
-rw-r--r-- | arch/mips/kernel/scall64-n32.S | 4 | ||||
-rw-r--r-- | arch/mips/kernel/signal32.c | 74 | ||||
-rw-r--r-- | arch/mips/kernel/signal_n32.c | 33 | ||||
-rw-r--r-- | arch/mips/kernel/smp.c | 20 | ||||
-rw-r--r-- | arch/mips/kernel/traps.c | 4 |
9 files changed, 111 insertions, 58 deletions
diff --git a/arch/mips/kernel/binfmt_elfn32.c b/arch/mips/kernel/binfmt_elfn32.c index d8e2674a154..4a9f1ecefaf 100644 --- a/arch/mips/kernel/binfmt_elfn32.c +++ b/arch/mips/kernel/binfmt_elfn32.c @@ -103,8 +103,9 @@ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) * one divide. */ u64 nsec = (u64)jiffies * TICK_NSEC; - value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &value->tv_usec); - value->tv_usec /= NSEC_PER_USEC; + long rem; + value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &rem); + value->tv_usec = rem / NSEC_PER_USEC; } #define ELF_CORE_EFLAGS EF_MIPS_ABI2 diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c index cec5f327e36..e3181377989 100644 --- a/arch/mips/kernel/binfmt_elfo32.c +++ b/arch/mips/kernel/binfmt_elfo32.c @@ -105,8 +105,9 @@ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) * one divide. */ u64 nsec = (u64)jiffies * TICK_NSEC; - value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &value->tv_usec); - value->tv_usec /= NSEC_PER_USEC; + long rem; + value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &rem); + value->tv_usec = rem / NSEC_PER_USEC; } #undef ELF_CORE_COPY_REGS diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 60353f5acc4..5f68b220c26 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -230,6 +230,9 @@ sysn32_waitid(int which, compat_pid_t pid, long ret; mm_segment_t old_fs = get_fs(); + if (!access_ok(VERIFY_WRITE, uinfo, sizeof(*uinfo))) + return -EFAULT; + set_fs (KERNEL_DS); ret = sys_waitid(which, pid, uinfo, options, uru ? (struct rusage __user *) &ru : NULL); @@ -1450,25 +1453,6 @@ sys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *ti return sys_timer_create(clock, p, timer_id); } -asmlinkage long -sysn32_rt_sigtimedwait(const sigset_t __user *uthese, - siginfo_t __user *uinfo, - const struct compat_timespec __user *uts32, - size_t sigsetsize) -{ - struct timespec __user *uts = NULL; - - if (uts32) { - struct timespec ts; - uts = compat_alloc_user_space(sizeof(struct timespec)); - if (get_user(ts.tv_sec, &uts32->tv_sec) || - get_user(ts.tv_nsec, &uts32->tv_nsec) || - copy_to_user (uts, &ts, sizeof (ts))) - return -EFAULT; - } - return sys_rt_sigtimedwait(uthese, uinfo, uts, sigsetsize); -} - save_static_function(sys32_clone); __attribute_used__ noinline static int _sys32_clone(nabi_no_regargs struct pt_regs regs) diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index d83e033dbc8..2f2dc54b2e2 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -626,7 +626,7 @@ einval: li v0, -EINVAL sys sys_fstatat64 4 sys sys_unlinkat 3 sys sys_renameat 4 /* 4295 */ - sys sys_linkat 4 + sys sys_linkat 5 sys sys_symlinkat 3 sys sys_readlinkat 4 sys sys_fchmodat 3 diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index bc4980cefc8..d87b5446fa1 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -245,9 +245,9 @@ EXPORT(sysn32_call_table) PTR sys_capget PTR sys_capset PTR sys32_rt_sigpending /* 6125 */ - PTR sysn32_rt_sigtimedwait + PTR compat_sys_rt_sigtimedwait PTR sys_rt_sigqueueinfo - PTR sys32_rt_sigsuspend + PTR sysn32_rt_sigsuspend PTR sys32_sigaltstack PTR compat_sys_utime /* 6130 */ PTR sys_mknod diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 8a8b8dd9041..237cd8a2cd3 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c @@ -4,7 +4,7 @@ * for more details. * * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright (C) 1994 - 2000 Ralf Baechle + * Copyright (C) 1994 - 2000, 2006 Ralf Baechle * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ #include <linux/cache.h> @@ -106,8 +106,6 @@ typedef struct compat_siginfo { #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -extern int do_signal32(sigset_t *oldset, struct pt_regs *regs); - /* 32-bit compatibility types */ #define _NSIG_BPW32 32 @@ -198,7 +196,7 @@ __attribute_used__ noinline static int _sys32_sigsuspend(nabi_no_regargs struct pt_regs regs) { compat_sigset_t *uset; - sigset_t newset, saveset; + sigset_t newset; uset = (compat_sigset_t *) regs.regs[4]; if (get_sigset(&newset, uset)) @@ -206,19 +204,15 @@ _sys32_sigsuspend(nabi_no_regargs struct pt_regs regs) sigdelsetmask(&newset, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; current->blocked = newset; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - regs.regs[2] = EINTR; - regs.regs[7] = 1; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal32(&saveset, ®s)) - return -EINTR; - } + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; } save_static_function(sys32_rt_sigsuspend); @@ -226,8 +220,8 @@ __attribute_used__ noinline static int _sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) { compat_sigset_t *uset; - sigset_t newset, saveset; - size_t sigsetsize; + sigset_t newset; + size_t sigsetsize; /* XXX Don't preclude handling different sized sigset_t's. */ sigsetsize = regs.regs[5]; @@ -240,19 +234,15 @@ _sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) sigdelsetmask(&newset, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; current->blocked = newset; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - regs.regs[2] = EINTR; - regs.regs[7] = 1; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal32(&saveset, ®s)) - return -EINTR; - } + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; } asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act, @@ -783,7 +773,7 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info, regs->regs[2] = EINTR; break; case ERESTARTSYS: - if(!(ka->sa.sa_flags & SA_RESTART)) { + if (!(ka->sa.sa_flags & SA_RESTART)) { regs->regs[2] = EINTR; break; } @@ -810,9 +800,10 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info, return ret; } -int do_signal32(sigset_t *oldset, struct pt_regs *regs) +void do_signal32(struct pt_regs *regs) { struct k_sigaction ka; + sigset_t *oldset; siginfo_t info; int signr; @@ -822,17 +813,30 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) * if so. */ if (!user_mode(regs)) - return 1; + return; if (try_to_freeze()) goto no_signal; - if (!oldset) + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); - if (signr > 0) - return handle_signal(signr, &info, &ka, oldset, regs); + if (signr > 0) { + /* Whee! Actually deliver the signal. */ + if (handle_signal(signr, &info, &ka, 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); + } + } no_signal: /* @@ -853,7 +857,15 @@ no_signal: regs->cp0_epc -= 4; } } - return 0; + + /* + * 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); + } } asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 *act, diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c index 5a3776096f0..3e168c08a3a 100644 --- a/arch/mips/kernel/signal_n32.c +++ b/arch/mips/kernel/signal_n32.c @@ -81,6 +81,39 @@ struct rt_sigframe_n32 { #endif }; +extern void sigset_from_compat (sigset_t *set, compat_sigset_t *compat); + +save_static_function(sysn32_rt_sigsuspend); +__attribute_used__ noinline static int +_sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) +{ + compat_sigset_t __user *unewset, uset; + size_t sigsetsize; + sigset_t newset; + + /* XXX Don't preclude handling different sized sigset_t's. */ + sigsetsize = regs.regs[5]; + if (sigsetsize != sizeof(sigset_t)) + return -EINVAL; + + unewset = (compat_sigset_t __user *) regs.regs[4]; + if (copy_from_user(&uset, unewset, sizeof(uset))) + return -EFAULT; + sigset_from_compat (&newset, &uset); + sigdelsetmask(&newset, ~_BLOCKABLE); + + spin_lock_irq(¤t->sighand->siglock); + current->saved_sigmask = current->blocked; + current->blocked = newset; + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; +} + save_static_function(sysn32_rt_sigreturn); __attribute_used__ noinline static void _sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 25472fcaf71..5e189862e52 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -29,6 +29,7 @@ #include <linux/timex.h> #include <linux/sched.h> #include <linux/cpumask.h> +#include <linux/cpu.h> #include <asm/atomic.h> #include <asm/cpu.h> @@ -424,6 +425,25 @@ void flush_tlb_one(unsigned long vaddr) local_flush_tlb_one(vaddr); } +static DEFINE_PER_CPU(struct cpu, cpu_devices); + +static int __init topology_init(void) +{ + int cpu; + int ret; + + for_each_cpu(cpu) { + ret = register_cpu(&per_cpu(cpu_devices, cpu), cpu, NULL); + if (ret) + printk(KERN_WARNING "topology_init: register_cpu %d " + "failed (%d)\n", cpu, ret); + } + + return 0; +} + +subsys_initcall(topology_init); + EXPORT_SYMBOL(flush_tlb_page); EXPORT_SYMBOL(flush_tlb_one); EXPORT_SYMBOL(cpu_data); diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index c9d2b5147ca..005debbfbe8 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1994 - 1999, 2000, 01 Ralf Baechle + * Copyright (C) 1994 - 1999, 2000, 01, 06 Ralf Baechle * Copyright (C) 1995, 1996 Paul M. Antoine * Copyright (C) 1998 Ulf Carlsson * Copyright (C) 1999 Silicon Graphics, Inc. @@ -548,6 +548,8 @@ asmlinkage void do_ov(struct pt_regs *regs) { siginfo_t info; + die_if_kernel("Integer overflow", regs); + info.si_code = FPE_INTOVF; info.si_signo = SIGFPE; info.si_errno = 0; |