summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel')
-rw-r--r--arch/sparc64/kernel/process.c18
-rw-r--r--arch/sparc64/kernel/signal.c21
-rw-r--r--arch/sparc64/kernel/signal32.c18
-rw-r--r--arch/sparc64/kernel/smp.c27
-rw-r--r--arch/sparc64/kernel/sys_sparc.c4
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c31
-rw-r--r--arch/sparc64/kernel/systbls.S2
7 files changed, 57 insertions, 64 deletions
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 500ac6d483a0..4129c0449856 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -503,6 +503,8 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags,
unsigned long stack_size)
{
int __user *parent_tid_ptr, *child_tid_ptr;
+ unsigned long orig_i1 = regs->u_regs[UREG_I1];
+ long ret;
#ifdef CONFIG_COMPAT
if (test_thread_flag(TIF_32BIT)) {
@@ -515,9 +517,19 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags,
child_tid_ptr = (int __user *) regs->u_regs[UREG_I4];
}
- return do_fork(clone_flags, stack_start,
- regs, stack_size,
- parent_tid_ptr, child_tid_ptr);
+ ret = do_fork(clone_flags, stack_start,
+ regs, stack_size,
+ parent_tid_ptr, child_tid_ptr);
+
+ /* If we get an error and potentially restart the system
+ * call, we're screwed because copy_thread() clobbered
+ * the parent's %o1. So detect that case and restore it
+ * here.
+ */
+ if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK)
+ regs->u_regs[UREG_I1] = orig_i1;
+
+ return ret;
}
/* Copy a Sparc thread. The fork() return value conventions
diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
index 45d6bf632daa..07c0443ea3f5 100644
--- a/arch/sparc64/kernel/signal.c
+++ b/arch/sparc64/kernel/signal.c
@@ -376,16 +376,29 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize)
{
- unsigned long sp;
+ unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS;
- sp = regs->u_regs[UREG_FP] + STACK_BIAS;
+ /*
+ * If we are on the alternate signal stack and would overflow it, don't.
+ * Return an always-bogus address instead so we will die with SIGSEGV.
+ */
+ if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize)))
+ return (void __user *) -1L;
/* This is the X/Open sanctioned signal stack switching. */
if (ka->sa.sa_flags & SA_ONSTACK) {
- if (!on_sig_stack(sp) &&
- !((current->sas_ss_sp + current->sas_ss_size) & 7))
+ if (sas_ss_flags(sp) == 0)
sp = current->sas_ss_sp + current->sas_ss_size;
}
+
+ /* Always align the stack frame. This handles two cases. First,
+ * sigaltstack need not be mindful of platform specific stack
+ * alignment. Second, if we took this signal because the stack
+ * is not aligned properly, we'd like to take the signal cleanly
+ * and report that.
+ */
+ sp &= ~7UL;
+
return (void __user *)(sp - framesize);
}
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
index 9415d2c918c5..0f6b7b156efd 100644
--- a/arch/sparc64/kernel/signal32.c
+++ b/arch/sparc64/kernel/signal32.c
@@ -406,11 +406,27 @@ static void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, uns
regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
sp = regs->u_regs[UREG_FP];
+ /*
+ * If we are on the alternate signal stack and would overflow it, don't.
+ * Return an always-bogus address instead so we will die with SIGSEGV.
+ */
+ if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize)))
+ return (void __user *) -1L;
+
/* This is the X/Open sanctioned signal stack switching. */
if (sa->sa_flags & SA_ONSTACK) {
- if (!on_sig_stack(sp) && !((current->sas_ss_sp + current->sas_ss_size) & 7))
+ if (sas_ss_flags(sp) == 0)
sp = current->sas_ss_sp + current->sas_ss_size;
}
+
+ /* Always align the stack frame. This handles two cases. First,
+ * sigaltstack need not be mindful of platform specific stack
+ * alignment. Second, if we took this signal because the stack
+ * is not aligned properly, we'd like to take the signal cleanly
+ * and report that.
+ */
+ sp &= ~7UL;
+
return (void __user *)(sp - framesize);
}
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 3aba47624df4..0d6403a630ac 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -865,21 +865,14 @@ void smp_call_function_client(int irq, struct pt_regs *regs)
void *info = call_data->info;
clear_softint(1 << irq);
-
- irq_enter();
-
- if (!call_data->wait) {
- /* let initiator proceed after getting data */
- atomic_inc(&call_data->finished);
- }
-
- func(info);
-
- irq_exit();
-
if (call_data->wait) {
/* let initiator proceed only after completion */
+ func(info);
atomic_inc(&call_data->finished);
+ } else {
+ /* let initiator proceed after getting data */
+ atomic_inc(&call_data->finished);
+ func(info);
}
}
@@ -1041,9 +1034,7 @@ void smp_receive_signal(int cpu)
void smp_receive_signal_client(int irq, struct pt_regs *regs)
{
- irq_enter();
clear_softint(1 << irq);
- irq_exit();
}
void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
@@ -1051,8 +1042,6 @@ void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
struct mm_struct *mm;
unsigned long flags;
- irq_enter();
-
clear_softint(1 << irq);
/* See if we need to allocate a new TLB context because
@@ -1072,8 +1061,6 @@ void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
load_secondary_context(mm);
__flush_tlb_mm(CTX_HWBITS(mm->context),
SECONDARY_CONTEXT);
-
- irq_exit();
}
void smp_new_mmu_context_version(void)
@@ -1239,8 +1226,6 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
{
clear_softint(1 << irq);
- irq_enter();
-
preempt_disable();
__asm__ __volatile__("flushw");
@@ -1253,8 +1238,6 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
prom_world(0);
preempt_enable();
-
- irq_exit();
}
/* /proc/profile writes can call this, don't __init it please. */
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
index 8d4761f15fa9..0dbc941f130e 100644
--- a/arch/sparc64/kernel/sys_sparc.c
+++ b/arch/sparc64/kernel/sys_sparc.c
@@ -549,13 +549,13 @@ int sparc64_mmap_check(unsigned long addr, unsigned long len,
if (len >= STACK_TOP32)
return -EINVAL;
- if ((flags & MAP_FIXED) && addr > STACK_TOP32 - len)
+ if (addr > STACK_TOP32 - len)
return -EINVAL;
} else {
if (len >= VA_EXCLUDE_START)
return -EINVAL;
- if ((flags & MAP_FIXED) && invalid_64bit_range(addr, len))
+ if (invalid_64bit_range(addr, len))
return -EINVAL;
}
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 161ce4710fe7..1aa4288125f2 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -236,13 +236,6 @@ asmlinkage long sys32_getegid16(void)
/* 32-bit timeval and related flotsam. */
-static long get_tv32(struct timeval *o, struct compat_timeval __user *i)
-{
- return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
- (__get_user(o->tv_sec, &i->tv_sec) |
- __get_user(o->tv_usec, &i->tv_usec)));
-}
-
static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i)
{
return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
@@ -757,30 +750,6 @@ asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv,
return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
}
-asmlinkage long sys32_utimes(char __user *filename,
- struct compat_timeval __user *tvs)
-{
- struct timespec tv[2];
-
- if (tvs) {
- struct timeval ktvs[2];
- if (get_tv32(&ktvs[0], tvs) ||
- get_tv32(&ktvs[1], 1+tvs))
- return -EFAULT;
-
- if (ktvs[0].tv_usec < 0 || ktvs[0].tv_usec >= 1000000 ||
- ktvs[1].tv_usec < 0 || ktvs[1].tv_usec >= 1000000)
- return -EINVAL;
-
- tv[0].tv_sec = ktvs[0].tv_sec;
- tv[0].tv_nsec = 1000 * ktvs[0].tv_usec;
- tv[1].tv_sec = ktvs[1].tv_sec;
- tv[1].tv_nsec = 1000 * ktvs[1].tv_usec;
- }
-
- return do_utimes(AT_FDCWD, filename, tvs ? tv : NULL, 0);
-}
-
/* These are here just in case some old sparc32 binary calls it. */
asmlinkage long sys32_pause(void)
{
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index a4fef2ba1ae1..8b5282d433c4 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -45,7 +45,7 @@ sys_call_table32:
/*120*/ .word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod
.word sys_nis_syscall, sys32_setreuid16, sys32_setregid16, sys_rename, sys_truncate
/*130*/ .word sys_ftruncate, sys_flock, compat_sys_lstat64, sys_nis_syscall, sys_nis_syscall
- .word sys_nis_syscall, sys32_mkdir, sys_rmdir, sys32_utimes, compat_sys_stat64
+ .word sys_nis_syscall, sys32_mkdir, sys_rmdir, compat_sys_utimes, compat_sys_stat64
/*140*/ .word sys32_sendfile64, sys_nis_syscall, sys32_futex, sys_gettid, compat_sys_getrlimit
.word compat_sys_setrlimit, sys_pivot_root, sys32_prctl, sys_pciconfig_read, sys_pciconfig_write
/*150*/ .word sys_nis_syscall, sys_inotify_init, sys_inotify_add_watch, sys_poll, sys_getdents64