summaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/binfmt_elfn32.c5
-rw-r--r--arch/mips/kernel/binfmt_elfo32.c5
-rw-r--r--arch/mips/kernel/linux32.c76
-rw-r--r--arch/mips/kernel/process.c158
-rw-r--r--arch/mips/kernel/scall32-o32.S4
-rw-r--r--arch/mips/kernel/scall64-n32.S6
-rw-r--r--arch/mips/kernel/scall64-o32.S4
-rw-r--r--arch/mips/kernel/setup.c3
-rw-r--r--arch/mips/kernel/signal-common.h2
-rw-r--r--arch/mips/kernel/signal32.c76
-rw-r--r--arch/mips/kernel/signal_n32.c35
-rw-r--r--arch/mips/kernel/smp.c22
-rw-r--r--arch/mips/kernel/smp_mt.c47
-rw-r--r--arch/mips/kernel/traps.c4
14 files changed, 211 insertions, 236 deletions
diff --git a/arch/mips/kernel/binfmt_elfn32.c b/arch/mips/kernel/binfmt_elfn32.c
index d8e2674a1..4a9f1ec 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 cec5f32..e318137 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 60353f5..e00e5f6 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/process.c b/arch/mips/kernel/process.c
index 5232fc7..092679c 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -25,6 +25,7 @@
#include <linux/a.out.h>
#include <linux/init.h>
#include <linux/completion.h>
+#include <linux/kallsyms.h>
#include <asm/abi.h>
#include <asm/bootinfo.h>
@@ -272,46 +273,19 @@ long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
static struct mips_frame_info {
void *func;
- int omit_fp; /* compiled without fno-omit-frame-pointer */
- int frame_offset;
+ unsigned long func_size;
+ int frame_size;
int pc_offset;
-} schedule_frame, mfinfo[] = {
- { schedule, 0 }, /* must be first */
- /* arch/mips/kernel/semaphore.c */
- { __down, 1 },
- { __down_interruptible, 1 },
- /* kernel/sched.c */
-#ifdef CONFIG_PREEMPT
- { preempt_schedule, 0 },
-#endif
- { wait_for_completion, 0 },
- { interruptible_sleep_on, 0 },
- { interruptible_sleep_on_timeout, 0 },
- { sleep_on, 0 },
- { sleep_on_timeout, 0 },
- { yield, 0 },
- { io_schedule, 0 },
- { io_schedule_timeout, 0 },
-#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT)
- { __preempt_spin_lock, 0 },
- { __preempt_write_lock, 0 },
-#endif
- /* kernel/timer.c */
- { schedule_timeout, 1 },
-/* { nanosleep_restart, 1 }, */
- /* lib/rwsem-spinlock.c */
- { __down_read, 1 },
- { __down_write, 1 },
-};
+} *schedule_frame, mfinfo[64];
+static int mfinfo_num;
-static int mips_frame_info_initialized;
static int __init get_frame_info(struct mips_frame_info *info)
{
int i;
void *func = info->func;
union mips_instruction *ip = (union mips_instruction *)func;
info->pc_offset = -1;
- info->frame_offset = info->omit_fp ? 0 : -1;
+ info->frame_size = 0;
for (i = 0; i < 128; i++, ip++) {
/* if jal, jalr, jr, stop. */
if (ip->j_format.opcode == jal_op ||
@@ -320,6 +294,23 @@ static int __init get_frame_info(struct mips_frame_info *info)
ip->r_format.func == jr_op)))
break;
+ if (info->func_size && i >= info->func_size / 4)
+ break;
+ if (
+#ifdef CONFIG_32BIT
+ ip->i_format.opcode == addiu_op &&
+#endif
+#ifdef CONFIG_64BIT
+ ip->i_format.opcode == daddiu_op &&
+#endif
+ ip->i_format.rs == 29 &&
+ ip->i_format.rt == 29) {
+ /* addiu/daddiu sp,sp,-imm */
+ if (info->frame_size)
+ continue;
+ info->frame_size = - ip->i_format.simmediate;
+ }
+
if (
#ifdef CONFIG_32BIT
ip->i_format.opcode == sw_op &&
@@ -327,31 +318,20 @@ static int __init get_frame_info(struct mips_frame_info *info)
#ifdef CONFIG_64BIT
ip->i_format.opcode == sd_op &&
#endif
- ip->i_format.rs == 29)
- {
+ ip->i_format.rs == 29 &&
+ ip->i_format.rt == 31) {
/* sw / sd $ra, offset($sp) */
- if (ip->i_format.rt == 31) {
- if (info->pc_offset != -1)
- continue;
- info->pc_offset =
- ip->i_format.simmediate / sizeof(long);
- }
- /* sw / sd $s8, offset($sp) */
- if (ip->i_format.rt == 30) {
-//#if 0 /* gcc 3.4 does aggressive optimization... */
- if (info->frame_offset != -1)
- continue;
-//#endif
- info->frame_offset =
- ip->i_format.simmediate / sizeof(long);
- }
+ if (info->pc_offset != -1)
+ continue;
+ info->pc_offset =
+ ip->i_format.simmediate / sizeof(long);
}
}
- if (info->pc_offset == -1 || info->frame_offset == -1) {
- printk("Can't analyze prologue code at %p\n", func);
+ if (info->pc_offset == -1 || info->frame_size == 0) {
+ if (func == schedule)
+ printk("Can't analyze prologue code at %p\n", func);
info->pc_offset = -1;
- info->frame_offset = -1;
- return -1;
+ info->frame_size = 0;
}
return 0;
@@ -359,25 +339,36 @@ static int __init get_frame_info(struct mips_frame_info *info)
static int __init frame_info_init(void)
{
- int i, found;
- for (i = 0; i < ARRAY_SIZE(mfinfo); i++)
- if (get_frame_info(&mfinfo[i]))
- return -1;
- schedule_frame = mfinfo[0];
- /* bubble sort */
- do {
- struct mips_frame_info tmp;
- found = 0;
- for (i = 1; i < ARRAY_SIZE(mfinfo); i++) {
- if (mfinfo[i-1].func > mfinfo[i].func) {
- tmp = mfinfo[i];
- mfinfo[i] = mfinfo[i-1];
- mfinfo[i-1] = tmp;
- found = 1;
- }
- }
- } while (found);
- mips_frame_info_initialized = 1;
+ int i;
+#ifdef CONFIG_KALLSYMS
+ char *modname;
+ char namebuf[KSYM_NAME_LEN + 1];
+ unsigned long start, size, ofs;
+ extern char __sched_text_start[], __sched_text_end[];
+ extern char __lock_text_start[], __lock_text_end[];
+
+ start = (unsigned long)__sched_text_start;
+ for (i = 0; i < ARRAY_SIZE(mfinfo); i++) {
+ if (start == (unsigned long)schedule)
+ schedule_frame = &mfinfo[i];
+ if (!kallsyms_lookup(start, &size, &ofs, &modname, namebuf))
+ break;
+ mfinfo[i].func = (void *)(start + ofs);
+ mfinfo[i].func_size = size;
+ start += size - ofs;
+ if (start >= (unsigned long)__lock_text_end)
+ break;
+ if (start == (unsigned long)__sched_text_end)
+ start = (unsigned long)__lock_text_start;
+ }
+#else
+ mfinfo[0].func = schedule;
+ schedule_frame = &mfinfo[0];
+#endif
+ for (i = 0; i < ARRAY_SIZE(mfinfo) && mfinfo[i].func; i++)
+ get_frame_info(&mfinfo[i]);
+
+ mfinfo_num = i;
return 0;
}
@@ -394,47 +385,52 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
if (t->reg31 == (unsigned long) ret_from_fork)
return t->reg31;
- if (schedule_frame.pc_offset < 0)
+ if (!schedule_frame || schedule_frame->pc_offset < 0)
return 0;
- return ((unsigned long *)t->reg29)[schedule_frame.pc_offset];
+ return ((unsigned long *)t->reg29)[schedule_frame->pc_offset];
}
/* get_wchan - a maintenance nightmare^W^Wpain in the ass ... */
unsigned long get_wchan(struct task_struct *p)
{
unsigned long stack_page;
- unsigned long frame, pc;
+ unsigned long pc;
+#ifdef CONFIG_KALLSYMS
+ unsigned long frame;
+#endif
if (!p || p == current || p->state == TASK_RUNNING)
return 0;
stack_page = (unsigned long)task_stack_page(p);
- if (!stack_page || !mips_frame_info_initialized)
+ if (!stack_page || !mfinfo_num)
return 0;
pc = thread_saved_pc(p);
+#ifdef CONFIG_KALLSYMS
if (!in_sched_functions(pc))
return pc;
- frame = ((unsigned long *)p->thread.reg30)[schedule_frame.frame_offset];
+ frame = p->thread.reg29 + schedule_frame->frame_size;
do {
int i;
if (frame < stack_page || frame > stack_page + THREAD_SIZE - 32)
return 0;
- for (i = ARRAY_SIZE(mfinfo) - 1; i >= 0; i--) {
+ for (i = mfinfo_num - 1; i >= 0; i--) {
if (pc >= (unsigned long) mfinfo[i].func)
break;
}
if (i < 0)
break;
- if (mfinfo[i].omit_fp)
- break;
pc = ((unsigned long *)frame)[mfinfo[i].pc_offset];
- frame = ((unsigned long *)frame)[mfinfo[i].frame_offset];
+ if (!mfinfo[i].frame_size)
+ break;
+ frame += mfinfo[i].frame_size;
} while (in_sched_functions(pc));
+#endif
return pc;
}
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index d7c4a38..2f2dc54 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -623,10 +623,10 @@ einval: li v0, -EINVAL
sys sys_mknodat 4 /* 4290 */
sys sys_fchownat 5
sys sys_futimesat 3
- sys sys_newfstatat 4
+ 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 bc4980c..02c8267 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 5b04140..797e0d8 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 d86affa..d9293c5 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/signal-common.h b/arch/mips/kernel/signal-common.h
index 0fbc492..36bfc25 100644
--- a/arch/mips/kernel/signal-common.h
+++ b/arch/mips/kernel/signal-common.h
@@ -176,7 +176,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
sp = current->sas_ss_sp + current->sas_ss_size;
- return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? 32 : ALMASK));
+ return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK));
}
static inline int install_sigtramp(unsigned int __user *tramp,
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index da3271e..237cd8a 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(&current->sighand->siglock);
- saveset = current->blocked;
+ current->saved_sigmask = current->blocked;
current->blocked = newset;
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
- regs.regs[2] = EINTR;
- regs.regs[7] = 1;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal32(&saveset, &regs))
- 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(&current->sighand->siglock);
- saveset = current->blocked;
+ current->saved_sigmask = current->blocked;
current->blocked = newset;
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
- regs.regs[2] = EINTR;
- regs.regs[7] = 1;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal32(&saveset, &regs))
- 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,
@@ -537,7 +527,7 @@ _sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
/* The ucontext contains a stack32_t, so we must convert! */
if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp))
goto badframe;
- st.ss_size = (long) sp;
+ st.ss_sp = (void *)(long) sp;
if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size))
goto badframe;
if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags))
@@ -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 = &current->saved_sigmask;
+ else
oldset = &current->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, &current->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 384fc4a..3e168c0 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(&current->sighand->siglock);
+ current->saved_sigmask = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending();
+ spin_unlock_irq(&current->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)
@@ -108,7 +141,7 @@ _sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
/* The ucontext contains a stack32_t, so we must convert! */
if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp))
goto badframe;
- st.ss_size = (long) sp;
+ st.ss_sp = (void *)(long) sp;
if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size))
goto badframe;
if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags))
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 25472fc..06ed907 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 794a1c3..993b8bf 100644
--- a/arch/mips/kernel/smp_mt.c
+++ b/arch/mips/kernel/smp_mt.c
@@ -68,6 +68,8 @@ void __init sanitize_tlb_entries(void)
set_c0_mvpcontrol(MVPCONTROL_VPC);
+ back_to_back_c0_hazard();
+
/* Disable TLB sharing */
clear_c0_mvpcontrol(MVPCONTROL_STLB);
@@ -102,35 +104,6 @@ void __init sanitize_tlb_entries(void)
clear_c0_mvpcontrol(MVPCONTROL_VPC);
}
-#if 0
-/*
- * Use c0_MVPConf0 to find out how many CPUs are available, setting up
- * phys_cpu_present_map and the logical/physical mappings.
- */
-void __init prom_build_cpu_map(void)
-{
- int i, num, ncpus;
-
- cpus_clear(phys_cpu_present_map);
-
- /* assume we boot on cpu 0.... */
- cpu_set(0, phys_cpu_present_map);
- __cpu_number_map[0] = 0;
- __cpu_logical_map[0] = 0;
-
- if (cpu_has_mipsmt) {
- ncpus = ((read_c0_mvpconf0() & (MVPCONF0_PVPE)) >> MVPCONF0_PVPE_SHIFT) + 1;
- for (i=1, num=0; i< NR_CPUS && i<ncpus; i++) {
- cpu_set(i, phys_cpu_present_map);
- __cpu_number_map[i] = ++num;
- __cpu_logical_map[num] = i;
- }
-
- printk(KERN_INFO "%i available secondary CPU(s)\n", num);
- }
-}
-#endif
-
static void ipi_resched_dispatch (struct pt_regs *regs)
{
do_IRQ(MIPS_CPU_IPI_RESCHED_IRQ, regs);
@@ -170,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;
@@ -206,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 */
@@ -222,6 +193,9 @@ void prom_prepare_cpus(unsigned int max_cpus)
/* set config to be the same as vpe0, particularly kseg0 coherency alg */
write_vpe_c0_config( read_c0_config());
+
+ /* Propagate Config7 */
+ write_vpe_c0_config7(read_c0_config7());
}
}
@@ -265,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 c9d2b51..005debb 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;
OpenPOWER on IntegriCloud