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 | 76 | ||||
-rw-r--r-- | arch/mips/kernel/scall32-o32.S | 2 | ||||
-rw-r--r-- | arch/mips/kernel/scall64-n32.S | 6 | ||||
-rw-r--r-- | arch/mips/kernel/scall64-o32.S | 4 | ||||
-rw-r--r-- | arch/mips/kernel/setup.c | 3 | ||||
-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 | 22 | ||||
-rw-r--r-- | arch/mips/kernel/smp_mt.c | 13 | ||||
-rw-r--r-- | arch/mips/kernel/traps.c | 4 |
12 files changed, 125 insertions, 122 deletions
diff --git a/arch/mips/kernel/binfmt_elfn32.c b/arch/mips/kernel/binfmt_elfn32.c index d8e2674a1543..4a9f1ecefaf2 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 cec5f327e360..e31813779895 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 60353f5acc48..e00e5f6e7fdd 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -161,60 +161,6 @@ out: return error; } -struct dirent32 { - unsigned int d_ino; - unsigned int d_off; - unsigned short d_reclen; - char d_name[NAME_MAX + 1]; -}; - -static void -xlate_dirent(void *dirent64, void *dirent32, long n) -{ - long off; - struct dirent *dirp; - struct dirent32 *dirp32; - - off = 0; - while (off < n) { - dirp = (struct dirent *)(dirent64 + off); - dirp32 = (struct dirent32 *)(dirent32 + off); - off += dirp->d_reclen; - dirp32->d_ino = dirp->d_ino; - dirp32->d_off = (unsigned int)dirp->d_off; - dirp32->d_reclen = dirp->d_reclen; - strncpy(dirp32->d_name, dirp->d_name, dirp->d_reclen - ((3 * 4) + 2)); - } - return; -} - -asmlinkage long -sys32_getdents(unsigned int fd, void * dirent32, unsigned int count) -{ - long n; - void *dirent64; - - dirent64 = (void *)((unsigned long)(dirent32 + (sizeof(long) - 1)) & ~(sizeof(long) - 1)); - if ((n = sys_getdents(fd, dirent64, count - (dirent64 - dirent32))) < 0) - return(n); - xlate_dirent(dirent64, dirent32, n); - return(n); -} - -asmlinkage int old_readdir(unsigned int fd, void * dirent, unsigned int count); - -asmlinkage int -sys32_readdir(unsigned int fd, void * dirent32, unsigned int count) -{ - int n; - struct dirent dirent64; - - if ((n = old_readdir(fd, &dirent64, count)) < 0) - return(n); - xlate_dirent(&dirent64, dirent32, dirent64.d_reclen); - return(n); -} - asmlinkage int sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr, int options) { @@ -230,6 +176,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 +1399,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 d83e033dbc87..2f2dc54b2e26 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 bc4980cefc8b..02c8267e45e7 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -195,7 +195,7 @@ EXPORT(sysn32_call_table) PTR sys_fdatasync PTR sys_truncate PTR sys_ftruncate /* 6075 */ - PTR sys32_getdents + PTR compat_sys_getdents PTR sys_getcwd PTR sys_chdir PTR sys_fchdir @@ -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/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 5b0414018c9a..797e0d874889 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -293,7 +293,7 @@ sys_call_table: PTR sys_uselib PTR sys_swapon PTR sys_reboot - PTR sys32_readdir + PTR compat_sys_old_readdir PTR old_mmap /* 4090 */ PTR sys_munmap PTR sys_truncate @@ -345,7 +345,7 @@ sys_call_table: PTR sys_setfsuid PTR sys_setfsgid PTR sys32_llseek /* 4140 */ - PTR sys32_getdents + PTR compat_sys_getdents PTR compat_sys_select PTR sys_flock PTR sys_msync diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index d86affa21278..d9293c558e41 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -540,6 +540,9 @@ void __init setup_arch(char **cmdline_p) sparse_init(); paging_init(); resource_init(); +#ifdef CONFIG_SMP + plat_smp_setup(); +#endif } int __init fpu_disable(char *s) diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 8a8b8dd90417..237cd8a2cd32 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 5a3776096f07..3e168c08a3a8 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 25472fcaf715..06ed90752424 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> @@ -235,7 +236,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) init_new_context(current, &init_mm); current_thread_info()->cpu = 0; smp_tune_scheduling(); - prom_prepare_cpus(max_cpus); + plat_prepare_cpus(max_cpus); } /* preload SMP state for boot cpu */ @@ -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/smp_mt.c b/arch/mips/kernel/smp_mt.c index c930364830d0..993b8bf56aaf 100644 --- a/arch/mips/kernel/smp_mt.c +++ b/arch/mips/kernel/smp_mt.c @@ -143,7 +143,7 @@ static struct irqaction irq_call = { * Make sure all CPU's are in a sensible state before we boot any of the * secondarys */ -void prom_prepare_cpus(unsigned int max_cpus) +void plat_smp_setup(void) { unsigned long val; int i, num; @@ -179,11 +179,9 @@ void prom_prepare_cpus(unsigned int max_cpus) write_vpe_c0_vpeconf0(tmp); /* Record this as available CPU */ - if (i < max_cpus) { - cpu_set(i, phys_cpu_present_map); - __cpu_number_map[i] = ++num; - __cpu_logical_map[num] = i; - } + cpu_set(i, phys_cpu_present_map); + __cpu_number_map[i] = ++num; + __cpu_logical_map[num] = i; } /* disable multi-threading with TC's */ @@ -241,7 +239,10 @@ void prom_prepare_cpus(unsigned int max_cpus) set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch); set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch); } +} +void __init plat_prepare_cpus(unsigned int max_cpus) +{ cpu_ipi_resched_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ; cpu_ipi_call_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ; diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index c9d2b5147ca3..005debbfbe84 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; |