Commit 0caca697 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k:
  m68knommu: Need to check __get_user()/__put_user() result
  m68knommu: signal.c __user annotations
  m68knommu: Equivalent of "m68k: handle new gcc's"
  m68knommu: f_pcr has been gone since headers' merge
  m68knommu: Don't lose state if sigframe setup fails
  m68knommu: Handle multiple pending signals
  m68knommu: Switch to saner sigsuspend
  m68knommu: Don't bother with SA_ONESHOT
  m68k: Check __get_user()/__put_user() return value
  m68k: Missing syscall_trace() on sigreturn
  m68k: Fix stack mangling logics in sigreturn
  m68k: If we fail to set sigframe up, just leave regs alone...
  m68k: Don't lose state if sigframe setup fails
  m68k: Simplify the singlestepping handling in signals
  m68k: Switch to saner sigsuspend()
  m68k: Resetting sa_handler in local copy of k_sigaction is pointless
  m68k/sun3: Kill pte_unmap() warnings
parents ecacc6c7 751c88a2
...@@ -217,9 +217,8 @@ static inline pte_t pgoff_to_pte(unsigned off) ...@@ -217,9 +217,8 @@ static inline pte_t pgoff_to_pte(unsigned off)
/* Find an entry in the third-level pagetable. */ /* Find an entry in the third-level pagetable. */
#define pte_index(address) ((address >> PAGE_SHIFT) & (PTRS_PER_PTE-1)) #define pte_index(address) ((address >> PAGE_SHIFT) & (PTRS_PER_PTE-1))
#define pte_offset_kernel(pmd, address) ((pte_t *) __pmd_page(*pmd) + pte_index(address)) #define pte_offset_kernel(pmd, address) ((pte_t *) __pmd_page(*pmd) + pte_index(address))
/* FIXME: should we bother with kmap() here? */ #define pte_offset_map(pmd, address) ((pte_t *)page_address(pmd_page(*pmd)) + pte_index(address))
#define pte_offset_map(pmd, address) ((pte_t *)kmap(pmd_page(*pmd)) + pte_index(address)) #define pte_unmap(pte) do { } while (0)
#define pte_unmap(pte) kunmap(pte)
/* Macros to (de)construct the fake PTEs representing swap pages. */ /* Macros to (de)construct the fake PTEs representing swap pages. */
#define __swp_type(x) ((x).val & 0x7F) #define __swp_type(x) ((x).val & 0x7F)
......
...@@ -104,5 +104,6 @@ static inline struct thread_info *current_thread_info(void) ...@@ -104,5 +104,6 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_SYSCALL_TRACE 15 /* syscall trace active */ #define TIF_SYSCALL_TRACE 15 /* syscall trace active */
#define TIF_MEMDIE 16 /* is terminating due to OOM killer */ #define TIF_MEMDIE 16 /* is terminating due to OOM killer */
#define TIF_FREEZE 17 /* thread is freezing for suspend */ #define TIF_FREEZE 17 /* thread is freezing for suspend */
#define TIF_RESTORE_SIGMASK 18 /* restore signal mask in do_signal */
#endif /* _ASM_M68K_THREAD_INFO_H */ #endif /* _ASM_M68K_THREAD_INFO_H */
...@@ -373,6 +373,7 @@ ...@@ -373,6 +373,7 @@
#define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPENDING
#define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_SIGPROCMASK
#define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGACTION
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
/* /*
* "Conditional" syscalls * "Conditional" syscalls
......
...@@ -99,7 +99,10 @@ do_trace_exit: ...@@ -99,7 +99,10 @@ do_trace_exit:
jra .Lret_from_exception jra .Lret_from_exception
ENTRY(ret_from_signal) ENTRY(ret_from_signal)
RESTORE_SWITCH_STACK tstb %curptr@(TASK_INFO+TINFO_FLAGS+2)
jge 1f
jbsr syscall_trace
1: RESTORE_SWITCH_STACK
addql #4,%sp addql #4,%sp
/* on 68040 complete pending writebacks if any */ /* on 68040 complete pending writebacks if any */
#ifdef CONFIG_M68040 #ifdef CONFIG_M68040
...@@ -174,16 +177,11 @@ do_signal_return: ...@@ -174,16 +177,11 @@ do_signal_return:
subql #4,%sp | dummy return address subql #4,%sp | dummy return address
SAVE_SWITCH_STACK SAVE_SWITCH_STACK
pea %sp@(SWITCH_STACK_SIZE) pea %sp@(SWITCH_STACK_SIZE)
clrl %sp@-
bsrl do_signal bsrl do_signal
addql #8,%sp addql #4,%sp
RESTORE_SWITCH_STACK RESTORE_SWITCH_STACK
addql #4,%sp addql #4,%sp
tstl %d0 jbra resume_userspace
jeq resume_userspace
| when single stepping into handler stop at the first insn
btst #6,%curptr@(TASK_INFO+TINFO_FLAGS+2)
jeq resume_userspace
do_delayed_trace: do_delayed_trace:
bclr #7,%sp@(PT_OFF_SR) | clear trace bit in SR bclr #7,%sp@(PT_OFF_SR) | clear trace bit in SR
...@@ -290,22 +288,6 @@ ENTRY(sys_vfork) ...@@ -290,22 +288,6 @@ ENTRY(sys_vfork)
RESTORE_SWITCH_STACK RESTORE_SWITCH_STACK
rts rts
ENTRY(sys_sigsuspend)
SAVE_SWITCH_STACK
pea %sp@(SWITCH_STACK_SIZE)
jbsr do_sigsuspend
addql #4,%sp
RESTORE_SWITCH_STACK
rts
ENTRY(sys_rt_sigsuspend)
SAVE_SWITCH_STACK
pea %sp@(SWITCH_STACK_SIZE)
jbsr do_rt_sigsuspend
addql #4,%sp
RESTORE_SWITCH_STACK
rts
ENTRY(sys_sigreturn) ENTRY(sys_sigreturn)
SAVE_SWITCH_STACK SAVE_SWITCH_STACK
jbsr do_sigreturn jbsr do_sigreturn
......
...@@ -51,8 +51,6 @@ ...@@ -51,8 +51,6 @@
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
const int frame_extra_sizes[16] = { const int frame_extra_sizes[16] = {
[1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */ [1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */
[2] = sizeof(((struct frame *)0)->un.fmt2), [2] = sizeof(((struct frame *)0)->un.fmt2),
...@@ -74,51 +72,21 @@ const int frame_extra_sizes[16] = { ...@@ -74,51 +72,21 @@ const int frame_extra_sizes[16] = {
/* /*
* Atomically swap in the new signal mask, and wait for a signal. * Atomically swap in the new signal mask, and wait for a signal.
*/ */
asmlinkage int do_sigsuspend(struct pt_regs *regs) asmlinkage int
sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
{ {
old_sigset_t mask = regs->d3;
sigset_t saveset;
mask &= _BLOCKABLE; mask &= _BLOCKABLE;
saveset = current->blocked; spin_lock_irq(&current->sighand->siglock);
current->saved_sigmask = current->blocked;
siginitset(&current->blocked, mask); siginitset(&current->blocked, mask);
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
regs->d0 = -EINTR; current->state = TASK_INTERRUPTIBLE;
while (1) { schedule();
current->state = TASK_INTERRUPTIBLE; set_restore_sigmask();
schedule();
if (do_signal(&saveset, regs))
return -EINTR;
}
}
asmlinkage int
do_rt_sigsuspend(struct pt_regs *regs)
{
sigset_t __user *unewset = (sigset_t __user *)regs->d1;
size_t sigsetsize = (size_t)regs->d2;
sigset_t saveset, newset;
/* XXX: Don't preclude handling different sized sigset_t's. */
if (sigsetsize != sizeof(sigset_t))
return -EINVAL;
if (copy_from_user(&newset, unewset, sizeof(newset))) return -ERESTARTNOHAND;
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);
saveset = current->blocked;
current->blocked = newset;
recalc_sigpending();
regs->d0 = -EINTR;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
if (do_signal(&saveset, regs))
return -EINTR;
}
} }
asmlinkage int asmlinkage int
...@@ -132,10 +100,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, ...@@ -132,10 +100,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
old_sigset_t mask; old_sigset_t mask;
if (!access_ok(VERIFY_READ, act, sizeof(*act)) || if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) || __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
__get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
__get_user(mask, &act->sa_mask))
return -EFAULT; return -EFAULT;
__get_user(new_ka.sa.sa_flags, &act->sa_flags);
__get_user(mask, &act->sa_mask);
siginitset(&new_ka.sa.sa_mask, mask); siginitset(&new_ka.sa.sa_mask, mask);
} }
...@@ -144,10 +112,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, ...@@ -144,10 +112,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
if (!ret && oact) { if (!ret && oact) {
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) || __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
return -EFAULT; return -EFAULT;
__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
} }
return ret; return ret;
...@@ -318,36 +286,10 @@ static inline int rt_restore_fpu_state(struct ucontext __user *uc) ...@@ -318,36 +286,10 @@ static inline int rt_restore_fpu_state(struct ucontext __user *uc)
return err; return err;
} }
static inline int static int mangle_kernel_stack(struct pt_regs *regs, int formatvec,
restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp, void __user *fp)
int *pd0)
{ {
int fsize, formatvec; int fsize = frame_extra_sizes[formatvec >> 12];
struct sigcontext context;
int err;
/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
/* get previous context */
if (copy_from_user(&context, usc, sizeof(context)))
goto badframe;
/* restore passed registers */
regs->d1 = context.sc_d1;
regs->a0 = context.sc_a0;
regs->a1 = context.sc_a1;
regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
regs->pc = context.sc_pc;
regs->orig_d0 = -1; /* disable syscall checks */
wrusp(context.sc_usp);
formatvec = context.sc_formatvec;
regs->format = formatvec >> 12;
regs->vector = formatvec & 0xfff;
err = restore_fpu_state(&context);
fsize = frame_extra_sizes[regs->format];
if (fsize < 0) { if (fsize < 0) {
/* /*
* user process trying to return with weird frame format * user process trying to return with weird frame format
...@@ -355,16 +297,22 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u ...@@ -355,16 +297,22 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u
#ifdef DEBUG #ifdef DEBUG
printk("user process returning with weird frame format\n"); printk("user process returning with weird frame format\n");
#endif #endif
goto badframe; return 1;
} }
if (!fsize) {
regs->format = formatvec >> 12;
regs->vector = formatvec & 0xfff;
} else {
struct switch_stack *sw = (struct switch_stack *)regs - 1;
unsigned long buf[fsize / 2]; /* yes, twice as much */
/* OK. Make room on the supervisor stack for the extra junk, /* that'll make sure that expansion won't crap over data */
* if necessary. if (copy_from_user(buf + fsize / 4, fp, fsize))
*/ return 1;
if (fsize) { /* point of no return */
struct switch_stack *sw = (struct switch_stack *)regs - 1; regs->format = formatvec >> 12;
regs->d0 = context.sc_d0; regs->vector = formatvec & 0xfff;
#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack)) #define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
__asm__ __volatile__ __asm__ __volatile__
(" movel %0,%/a0\n\t" (" movel %0,%/a0\n\t"
...@@ -376,30 +324,50 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u ...@@ -376,30 +324,50 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u
" lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */ " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
" lsrl #2,%1\n\t" " lsrl #2,%1\n\t"
" subql #1,%1\n\t" " subql #1,%1\n\t"
"2: movesl %4@+,%2\n\t" /* copy to the gap we'd made */
"3: movel %2,%/a0@+\n\t" "2: movel %4@+,%/a0@+\n\t"
" dbra %1,2b\n\t" " dbra %1,2b\n\t"
" bral ret_from_signal\n" " bral ret_from_signal\n"
"4:\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 2b,4b\n"
" .long 3b,4b\n"
".previous"
: /* no outputs, it doesn't ever return */ : /* no outputs, it doesn't ever return */
: "a" (sw), "d" (fsize), "d" (frame_offset/4-1), : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
"n" (frame_offset), "a" (fp) "n" (frame_offset), "a" (buf + fsize/4)
: "a0"); : "a0");
#undef frame_offset #undef frame_offset
/*
* If we ever get here an exception occurred while
* building the above stack-frame.
*/
goto badframe;
} }
return 0;
}
*pd0 = context.sc_d0; static inline int
return err; restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp)
{
int formatvec;
struct sigcontext context;
int err;
/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
/* get previous context */
if (copy_from_user(&context, usc, sizeof(context)))
goto badframe;
/* restore passed registers */
regs->d0 = context.sc_d0;
regs->d1 = context.sc_d1;
regs->a0 = context.sc_a0;
regs->a1 = context.sc_a1;
regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
regs->pc = context.sc_pc;
regs->orig_d0 = -1; /* disable syscall checks */
wrusp(context.sc_usp);
formatvec = context.sc_formatvec;
err = restore_fpu_state(&context);
if (err || mangle_kernel_stack(regs, formatvec, fp))
goto badframe;
return 0;
badframe: badframe:
return 1; return 1;
...@@ -407,9 +375,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u ...@@ -407,9 +375,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u
static inline int static inline int
rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
struct ucontext __user *uc, int *pd0) struct ucontext __user *uc)
{ {
int fsize, temp; int temp;
greg_t __user *gregs = uc->uc_mcontext.gregs; greg_t __user *gregs = uc->uc_mcontext.gregs;
unsigned long usp; unsigned long usp;
int err; int err;
...@@ -443,65 +411,16 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, ...@@ -443,65 +411,16 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
regs->sr = (regs->sr & 0xff00) | (temp & 0xff); regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
regs->orig_d0 = -1; /* disable syscall checks */ regs->orig_d0 = -1; /* disable syscall checks */
err |= __get_user(temp, &uc->uc_formatvec); err |= __get_user(temp, &uc->uc_formatvec);
regs->format = temp >> 12;
regs->vector = temp & 0xfff;
err |= rt_restore_fpu_state(uc); err |= rt_restore_fpu_state(uc);
if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT) if (err || do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
goto badframe; goto badframe;
fsize = frame_extra_sizes[regs->format]; if (mangle_kernel_stack(regs, temp, &uc->uc_extra))
if (fsize < 0) {
/*
* user process trying to return with weird frame format
*/
#ifdef DEBUG
printk("user process returning with weird frame format\n");
#endif
goto badframe; goto badframe;
}
/* OK. Make room on the supervisor stack for the extra junk,
* if necessary.
*/
if (fsize) { return 0;
#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
__asm__ __volatile__
(" movel %0,%/a0\n\t"
" subl %1,%/a0\n\t" /* make room on stack */
" movel %/a0,%/sp\n\t" /* set stack pointer */
/* move switch_stack and pt_regs */
"1: movel %0@+,%/a0@+\n\t"
" dbra %2,1b\n\t"
" lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
" lsrl #2,%1\n\t"
" subql #1,%1\n\t"
"2: movesl %4@+,%2\n\t"
"3: movel %2,%/a0@+\n\t"
" dbra %1,2b\n\t"
" bral ret_from_signal\n"
"4:\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 2b,4b\n"
" .long 3b,4b\n"
".previous"
: /* no outputs, it doesn't ever return */
: "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
"n" (frame_offset), "a" (&uc->uc_extra)
: "a0");
#undef frame_offset
/*
* If we ever get here an exception occurred while
* building the above stack-frame.
*/
goto badframe;
}
*pd0 = regs->d0;
return err;
badframe: badframe:
return 1; return 1;
...@@ -514,7 +433,6 @@ asmlinkage int do_sigreturn(unsigned long __unused) ...@@ -514,7 +433,6 @@ asmlinkage int do_sigreturn(unsigned long __unused)
unsigned long usp = rdusp(); unsigned long usp = rdusp();
struct sigframe __user *frame = (struct sigframe __user *)(usp - 4); struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
sigset_t set; sigset_t set;
int d0;
if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe; goto badframe;
...@@ -528,9 +446,9 @@ asmlinkage int do_sigreturn(unsigned long __unused) ...@@ -528,9 +446,9 @@ asmlinkage int do_sigreturn(unsigned long __unused)
current->blocked = set; current->blocked = set;
recalc_sigpending(); recalc_sigpending();
if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0)) if (restore_sigcontext(regs, &frame->sc, frame + 1))
goto badframe; goto badframe;
return d0; return regs->d0;
badframe: badframe:
force_sig(SIGSEGV, current); force_sig(SIGSEGV, current);
...@@ -544,7 +462,6 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused) ...@@ -544,7 +462,6 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
unsigned long usp = rdusp(); unsigned long usp = rdusp();
struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4); struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4);
sigset_t set; sigset_t set;
int d0;
if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe; goto badframe;
...@@ -555,9 +472,9 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused) ...@@ -555,9 +472,9 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
current->blocked = set; current->blocked = set;
recalc_sigpending(); recalc_sigpending();
if (rt_restore_ucontext(regs, sw, &frame->uc, &d0)) if (rt_restore_ucontext(regs, sw, &frame->uc))
goto badframe; goto badframe;
return d0; return regs->d0;
badframe: badframe:
force_sig(SIGSEGV, current); force_sig(SIGSEGV, current);
...@@ -775,7 +692,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) ...@@ -775,7 +692,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
return (void __user *)((usp - frame_size) & -8UL); return (void __user *)((usp - frame_size) & -8UL);
} }
static void setup_frame (int sig, struct k_sigaction *ka, static int setup_frame (int sig, struct k_sigaction *ka,
sigset_t *set, struct pt_regs *regs) sigset_t *set, struct pt_regs *regs)
{ {
struct sigframe __user *frame; struct sigframe __user *frame;
...@@ -793,10 +710,8 @@ static void setup_frame (int sig, struct k_sigaction *ka, ...@@ -793,10 +710,8 @@ static void setup_frame (int sig, struct k_sigaction *ka,
frame = get_sigframe(ka, regs, sizeof(*frame) + fsize); frame = get_sigframe(ka, regs, sizeof(*frame) + fsize);
if (fsize) { if (fsize)
err |= copy_to_user (frame + 1, regs + 1, fsize); err |= copy_to_user (frame + 1, regs + 1, fsize);
regs->stkadj = fsize;
}
err |= __put_user((current_thread_info()->exec_domain err |= __put_user((current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap && current_thread_info()->exec_domain->signal_invmap
...@@ -826,11 +741,21 @@ static void setup_frame (int sig, struct k_sigaction *ka, ...@@ -826,11 +741,21 @@ static void setup_frame (int sig, struct k_sigaction *ka,
push_cache ((unsigned long) &frame->retcode); push_cache ((unsigned long) &frame->retcode);
/* Set up registers for signal handler */ /*
* Set up registers for signal handler. All the state we are about
* to destroy is successfully copied to sigframe.
*/
wrusp ((unsigned long) frame); wrusp ((unsigned long) frame);
regs->pc = (unsigned long) ka->sa.sa_handler; regs->pc = (unsigned long) ka->sa.sa_handler;
adjust_stack: /*
* This is subtle; if we build more than one sigframe, all but the
* first one will see frame format 0 and have fsize == 0, so we won't
* screw stkadj.
*/
if (fsize)
regs->stkadj = fsize;
/* Prepare to skip over the extra stuff in the exception frame. */ /* Prepare to skip over the extra stuff in the exception frame. */
if (regs->stkadj) { if (regs->stkadj) {
struct pt_regs *tregs = struct pt_regs *tregs =
...@@ -845,14 +770,14 @@ static void setup_frame (int sig, struct k_sigaction *ka, ...@@ -845,14 +770,14 @@ static void setup_frame (int sig, struct k_sigaction *ka,
tregs->pc = regs->pc; tregs->pc = regs->pc;
tregs->sr = regs->sr; tregs->sr = regs->sr;
} }
return; return 0;
give_sigsegv: give_sigsegv:
force_sigsegv(sig, current); force_sigsegv(sig, current);
goto adjust_stack; return err;
} }
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) sigset_t *set, struct pt_regs *regs)
{ {
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
...@@ -869,10 +794,8 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -869,10 +794,8 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ka, regs, sizeof(*frame));
if (fsize) { if (fsize)
err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize); err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
regs->stkadj = fsize;
}
err |= __put_user((current_thread_info()->exec_domain err |= __put_user((current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap && current_thread_info()->exec_domain->signal_invmap
...@@ -914,11 +837,21 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -914,11 +837,21 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
push_cache ((unsigned long) &frame->retcode); push_cache ((unsigned long) &frame->retcode);
/* Set up registers for signal handler */ /*
* Set up registers for signal handler. All the state we are about
* to destroy is successfully copied to sigframe.
*/
wrusp ((unsigned long) frame); wrusp ((unsigned long) frame);
regs->pc = (unsigned long) ka->sa.sa_handler; regs->pc = (unsigned long) ka->sa.sa_handler;
adjust_stack: /*
* This is subtle; if we build more than one sigframe, all but the
* first one will see frame format 0 and have fsize == 0, so we won't
* screw stkadj.
*/
if (fsize)
regs->stkadj = fsize;
/* Prepare to skip over the extra stuff in the exception frame. */ /* Prepare to skip over the extra stuff in the exception frame. */
if (regs->stkadj) { if (regs->stkadj) {
struct pt_regs *tregs = struct pt_regs *tregs =
...@@ -933,11 +866,11 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -933,11 +866,11 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
tregs->pc = regs->pc; tregs->pc = regs->pc;
tregs->sr = regs->sr; tregs->sr = regs->sr;
} }
return; return 0;
give_sigsegv: give_sigsegv:
force_sigsegv(sig, current); force_sigsegv(sig, current);
goto adjust_stack; return err;
} }
static inline void static inline void
...@@ -995,6 +928,7 @@ static void ...@@ -995,6 +928,7 @@ static void
handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs) sigset_t *oldset, struct pt_regs *regs)
{ {
int err;
/* are we from a system call? */ /* are we from a system call? */
if (regs->orig_d0 >= 0) if (regs->orig_d0 >= 0)
/* If so, check system call restarting.. */ /* If so, check system call restarting.. */
...@@ -1002,17 +936,24 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -1002,17 +936,24 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
/* set up the stack frame */ /* set up the stack frame */
if (ka->sa.sa_flags & SA_SIGINFO) if (ka->sa.sa_flags & SA_SIGINFO)
setup_rt_frame(sig, ka, info, oldset, regs); err = setup_rt_frame(sig, ka, info, oldset, regs);
else else
setup_frame(sig, ka, oldset, regs); err = setup_frame(sig, ka, oldset, regs);
if (ka->sa.sa_flags & SA_ONESHOT) if (err)
ka->sa.sa_handler = SIG_DFL; return;
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER)) if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig); sigaddset(&current->blocked,sig);
recalc_sigpending(); recalc_sigpending();
if (test_thread_flag(TIF_DELAYED_TRACE)) {
regs->sr &= ~0x8000;
send_sig(SIGTRAP, current, 1);
}
clear_thread_flag(TIF_RESTORE_SIGMASK);
} }
/* /*
...@@ -1020,22 +961,25 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -1020,22 +961,25 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
* want to handle. Thus you cannot kill init even with a SIGKILL even by * want to handle. Thus you cannot kill init even with a SIGKILL even by
* mistake. * mistake.
*/ */
asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) asmlinkage void do_signal(struct pt_regs *regs)
{ {
siginfo_t info; siginfo_t info;
struct k_sigaction ka; struct k_sigaction ka;
int signr; int signr;
sigset_t *oldset;
current->thread.esp0 = (unsigned long) regs; current->thread.esp0 = (unsigned long) regs;
if (!oldset) if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked; oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, &ka, &info, oldset, regs); handle_signal(signr, &ka, &info, oldset, regs);
return 1; return;
} }
/* Did we come from a system call? */ /* Did we come from a system call? */
...@@ -1043,5 +987,9 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -1043,5 +987,9 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
/* Restart the system call - no handlers present */ /* Restart the system call - no handlers present */
handle_restart(regs, NULL, 0); handle_restart(regs, NULL, 0);
return 0; /* If there's no signal to deliver, we just restore the saved mask. */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
...@@ -112,22 +112,6 @@ ENTRY(sys_clone) ...@@ -112,22 +112,6 @@ ENTRY(sys_clone)
RESTORE_SWITCH_STACK RESTORE_SWITCH_STACK
rts rts
ENTRY(sys_sigsuspend)
SAVE_SWITCH_STACK
pea %sp@(SWITCH_STACK_SIZE)
jbsr do_sigsuspend
addql #4,%sp
RESTORE_SWITCH_STACK
rts
ENTRY(sys_rt_sigsuspend)
SAVE_SWITCH_STACK
pea %sp@(SWITCH_STACK_SIZE)
jbsr do_rt_sigsuspend
addql #4,%sp
RESTORE_SWITCH_STACK
rts
ENTRY(sys_sigreturn) ENTRY(sys_sigreturn)
SAVE_SWITCH_STACK SAVE_SWITCH_STACK
jbsr do_sigreturn jbsr do_sigreturn
......
...@@ -53,65 +53,30 @@ ...@@ -53,65 +53,30 @@
void ret_from_user_signal(void); void ret_from_user_signal(void);
void ret_from_user_rt_signal(void); void ret_from_user_rt_signal(void);
asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
/* /*
* Atomically swap in the new signal mask, and wait for a signal. * Atomically swap in the new signal mask, and wait for a signal.
*/ */
asmlinkage int do_sigsuspend(struct pt_regs *regs) asmlinkage int
sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
{ {
old_sigset_t mask = regs->d3;
sigset_t saveset;
mask &= _BLOCKABLE; mask &= _BLOCKABLE;
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
saveset = current->blocked; current->saved_sigmask = current->blocked;
siginitset(&current->blocked, mask); siginitset(&current->blocked, mask);
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
regs->d0 = -EINTR; current->state = TASK_INTERRUPTIBLE;
while (1) { schedule();
current->state = TASK_INTERRUPTIBLE; set_restore_sigmask();
schedule();
if (do_signal(&saveset, regs))
return -EINTR;
}
}
asmlinkage int
do_rt_sigsuspend(struct pt_regs *regs)
{
sigset_t *unewset = (sigset_t *)regs->d1;
size_t sigsetsize = (size_t)regs->d2;
sigset_t saveset, newset;
/* XXX: Don't preclude handling different sized sigset_t's. */
if (sigsetsize != sizeof(sigset_t))
return -EINVAL;
if (copy_from_user(&newset, unewset, sizeof(newset))) return -ERESTARTNOHAND;
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock);
saveset = current->blocked;
current->blocked = newset;
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
regs->d0 = -EINTR;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
if (do_signal(&saveset, regs))
return -EINTR;
}
} }
asmlinkage int asmlinkage int
sys_sigaction(int sig, const struct old_sigaction *act, sys_sigaction(int sig, const struct old_sigaction __user *act,
struct old_sigaction *oact) struct old_sigaction __user *oact)
{ {
struct k_sigaction new_ka, old_ka; struct k_sigaction new_ka, old_ka;
int ret; int ret;
...@@ -120,10 +85,10 @@ sys_sigaction(int sig, const struct old_sigaction *act, ...@@ -120,10 +85,10 @@ sys_sigaction(int sig, const struct old_sigaction *act,
old_sigset_t mask; old_sigset_t mask;
if (!access_ok(VERIFY_READ, act, sizeof(*act)) || if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) || __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
__get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
__get_user(mask, &act->sa_mask))
return -EFAULT; return -EFAULT;
__get_user(new_ka.sa.sa_flags, &act->sa_flags);
__get_user(mask, &act->sa_mask);
siginitset(&new_ka.sa.sa_mask, mask); siginitset(&new_ka.sa.sa_mask, mask);
} }
...@@ -132,17 +97,17 @@ sys_sigaction(int sig, const struct old_sigaction *act, ...@@ -132,17 +97,17 @@ sys_sigaction(int sig, const struct old_sigaction *act,
if (!ret && oact) { if (!ret && oact) {
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) || __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
return -EFAULT; return -EFAULT;
__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
} }
return ret; return ret;
} }
asmlinkage int asmlinkage int
sys_sigaltstack(const stack_t *uss, stack_t *uoss) sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
{ {
return do_sigaltstack(uss, uoss, rdusp()); return do_sigaltstack(uss, uoss, rdusp());
} }
...@@ -157,10 +122,10 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss) ...@@ -157,10 +122,10 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss)
struct sigframe struct sigframe
{ {
char *pretcode; char __user *pretcode;
int sig; int sig;
int code; int code;
struct sigcontext *psc; struct sigcontext __user *psc;
char retcode[8]; char retcode[8];
unsigned long extramask[_NSIG_WORDS-1]; unsigned long extramask[_NSIG_WORDS-1];
struct sigcontext sc; struct sigcontext sc;
...@@ -168,10 +133,10 @@ struct sigframe ...@@ -168,10 +133,10 @@ struct sigframe
struct rt_sigframe struct rt_sigframe
{ {
char *pretcode; char __user *pretcode;
int sig; int sig;
struct siginfo *pinfo; struct siginfo __user *pinfo;
void *puc; void __user *puc;
char retcode[8]; char retcode[8];
struct siginfo info; struct siginfo info;
struct ucontext uc; struct ucontext uc;
...@@ -198,8 +163,8 @@ static inline int restore_fpu_state(struct sigcontext *sc) ...@@ -198,8 +163,8 @@ static inline int restore_fpu_state(struct sigcontext *sc)
goto out; goto out;
__asm__ volatile (".chip 68k/68881\n\t" __asm__ volatile (".chip 68k/68881\n\t"
"fmovemx %0,%/fp0-%/fp1\n\t" "fmovemx %0,%%fp0-%%fp1\n\t"
"fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t" "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
".chip 68k" ".chip 68k"
: /* no outputs */ : /* no outputs */
: "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl)); : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl));
...@@ -218,7 +183,7 @@ static inline int restore_fpu_state(struct sigcontext *sc) ...@@ -218,7 +183,7 @@ static inline int restore_fpu_state(struct sigcontext *sc)
#define uc_formatvec uc_filler[FPCONTEXT_SIZE/4] #define uc_formatvec uc_filler[FPCONTEXT_SIZE/4]
#define uc_extra uc_filler[FPCONTEXT_SIZE/4+1] #define uc_extra uc_filler[FPCONTEXT_SIZE/4+1]
static inline int rt_restore_fpu_state(struct ucontext *uc) static inline int rt_restore_fpu_state(struct ucontext __user *uc)
{ {
unsigned char fpstate[FPCONTEXT_SIZE]; unsigned char fpstate[FPCONTEXT_SIZE];
int context_size = 0; int context_size = 0;
...@@ -228,7 +193,7 @@ static inline int rt_restore_fpu_state(struct ucontext *uc) ...@@ -228,7 +193,7 @@ static inline int rt_restore_fpu_state(struct ucontext *uc)
if (FPU_IS_EMU) { if (FPU_IS_EMU) {
/* restore fpu control register */ /* restore fpu control register */
if (__copy_from_user(current->thread.fpcntl, if (__copy_from_user(current->thread.fpcntl,
&uc->uc_mcontext.fpregs.f_pcr, 12)) uc->uc_mcontext.fpregs.f_fpcntl, 12))
goto out; goto out;
/* restore all other fpu register */ /* restore all other fpu register */
if (__copy_from_user(current->thread.fp, if (__copy_from_user(current->thread.fp,
...@@ -237,7 +202,7 @@ static inline int rt_restore_fpu_state(struct ucontext *uc) ...@@ -237,7 +202,7 @@ static inline int rt_restore_fpu_state(struct ucontext *uc)
return 0; return 0;
} }
if (__get_user(*(long *)fpstate, (long *)&uc->uc_fpstate)) if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate))
goto out; goto out;
if (fpstate[0]) { if (fpstate[0]) {
context_size = fpstate[1]; context_size = fpstate[1];
...@@ -249,15 +214,15 @@ static inline int rt_restore_fpu_state(struct ucontext *uc) ...@@ -249,15 +214,15 @@ static inline int rt_restore_fpu_state(struct ucontext *uc)
sizeof(fpregs))) sizeof(fpregs)))
goto out; goto out;
__asm__ volatile (".chip 68k/68881\n\t" __asm__ volatile (".chip 68k/68881\n\t"
"fmovemx %0,%/fp0-%/fp7\n\t" "fmovemx %0,%%fp0-%%fp7\n\t"
"fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t" "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
".chip 68k" ".chip 68k"
: /* no outputs */ : /* no outputs */
: "m" (*fpregs.f_fpregs), : "m" (*fpregs.f_fpregs),
"m" (fpregs.f_pcr)); "m" (*fpregs.f_fpcntl));
} }
if (context_size && if (context_size &&
__copy_from_user(fpstate + 4, (long *)&uc->uc_fpstate + 1, __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1,
context_size)) context_size))
goto out; goto out;
__asm__ volatile (".chip 68k/68881\n\t" __asm__ volatile (".chip 68k/68881\n\t"
...@@ -272,7 +237,7 @@ static inline int rt_restore_fpu_state(struct ucontext *uc) ...@@ -272,7 +237,7 @@ static inline int rt_restore_fpu_state(struct ucontext *uc)
#endif #endif
static inline int static inline int
restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp, restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp,
int *pd0) int *pd0)
{ {
int formatvec; int formatvec;
...@@ -312,10 +277,10 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp, ...@@ -312,10 +277,10 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp,
static inline int static inline int
rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
struct ucontext *uc, int *pd0) struct ucontext __user *uc, int *pd0)
{ {
int temp; int temp;
greg_t *gregs = uc->uc_mcontext.gregs; greg_t __user *gregs = uc->uc_mcontext.gregs;
unsigned long usp; unsigned long usp;
int err; int err;
...@@ -365,7 +330,7 @@ asmlinkage int do_sigreturn(unsigned long __unused) ...@@ -365,7 +330,7 @@ asmlinkage int do_sigreturn(unsigned long __unused)
struct switch_stack *sw = (struct switch_stack *) &__unused; struct switch_stack *sw = (struct switch_stack *) &__unused;
struct pt_regs *regs = (struct pt_regs *) (sw + 1); struct pt_regs *regs = (struct pt_regs *) (sw + 1);
unsigned long usp = rdusp(); unsigned long usp = rdusp();
struct sigframe *frame = (struct sigframe *)(usp - 4); struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
sigset_t set; sigset_t set;
int d0; int d0;
...@@ -397,7 +362,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused) ...@@ -397,7 +362,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
struct switch_stack *sw = (struct switch_stack *) &__unused; struct switch_stack *sw = (struct switch_stack *) &__unused;
struct pt_regs *regs = (struct pt_regs *) (sw + 1); struct pt_regs *regs = (struct pt_regs *) (sw + 1);
unsigned long usp = rdusp(); unsigned long usp = rdusp();
struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4); struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4);
sigset_t set; sigset_t set;
int d0; int d0;
...@@ -443,17 +408,17 @@ static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs) ...@@ -443,17 +408,17 @@ static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
if (sc->sc_fpstate[0]) { if (sc->sc_fpstate[0]) {
fpu_version = sc->sc_fpstate[0]; fpu_version = sc->sc_fpstate[0];
__asm__ volatile (".chip 68k/68881\n\t" __asm__ volatile (".chip 68k/68881\n\t"
"fmovemx %/fp0-%/fp1,%0\n\t" "fmovemx %%fp0-%%fp1,%0\n\t"
"fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t" "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
".chip 68k" ".chip 68k"
: /* no outputs */ : "=m" (*sc->sc_fpregs),
: "m" (*sc->sc_fpregs), "=m" (*sc->sc_fpcntl)
"m" (*sc->sc_fpcntl) : /* no inputs */
: "memory"); : "memory");
} }
} }
static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs) static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs)
{ {
unsigned char fpstate[FPCONTEXT_SIZE]; unsigned char fpstate[FPCONTEXT_SIZE];
int context_size = 0; int context_size = 0;
...@@ -461,7 +426,7 @@ static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs) ...@@ -461,7 +426,7 @@ static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs)
if (FPU_IS_EMU) { if (FPU_IS_EMU) {
/* save fpu control register */ /* save fpu control register */
err |= copy_to_user(&uc->uc_mcontext.fpregs.f_pcr, err |= copy_to_user(uc->uc_mcontext.fpregs.f_pcntl,
current->thread.fpcntl, 12); current->thread.fpcntl, 12);
/* save all other fpu register */ /* save all other fpu register */
err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs, err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
...@@ -474,24 +439,24 @@ static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs) ...@@ -474,24 +439,24 @@ static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs)
".chip 68k" ".chip 68k"
: : "m" (*fpstate) : "memory"); : : "m" (*fpstate) : "memory");
err |= __put_user(*(long *)fpstate, (long *)&uc->uc_fpstate); err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate);
if (fpstate[0]) { if (fpstate[0]) {
fpregset_t fpregs; fpregset_t fpregs;
context_size = fpstate[1]; context_size = fpstate[1];
fpu_version = fpstate[0]; fpu_version = fpstate[0];
__asm__ volatile (".chip 68k/68881\n\t" __asm__ volatile (".chip 68k/68881\n\t"
"fmovemx %/fp0-%/fp7,%0\n\t" "fmovemx %%fp0-%%fp7,%0\n\t"
"fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t" "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
".chip 68k" ".chip 68k"
: /* no outputs */ : "=m" (*fpregs.f_fpregs),
: "m" (*fpregs.f_fpregs), "=m" (*fpregs.f_fpcntl)
"m" (fpregs.f_pcr) : /* no inputs */
: "memory"); : "memory");
err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs, err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
sizeof(fpregs)); sizeof(fpregs));
} }
if (context_size) if (context_size)
err |= copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4, err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4,
context_size); context_size);
return err; return err;
} }
...@@ -516,10 +481,10 @@ static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, ...@@ -516,10 +481,10 @@ static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
#endif #endif
} }
static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs) static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs)
{ {
struct switch_stack *sw = (struct switch_stack *)regs - 1; struct switch_stack *sw = (struct switch_stack *)regs - 1;
greg_t *gregs = uc->uc_mcontext.gregs; greg_t __user *gregs = uc->uc_mcontext.gregs;
int err = 0; int err = 0;
err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version); err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
...@@ -547,7 +512,7 @@ static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs) ...@@ -547,7 +512,7 @@ static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs)
return err; return err;
} }
static inline void * static inline void __user *
get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
{ {
unsigned long usp; unsigned long usp;
...@@ -560,13 +525,13 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) ...@@ -560,13 +525,13 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
if (!sas_ss_flags(usp)) if (!sas_ss_flags(usp))
usp = current->sas_ss_sp + current->sas_ss_size; usp = current->sas_ss_sp + current->sas_ss_size;
} }
return (void *)((usp - frame_size) & -8UL); return (void __user *)((usp - frame_size) & -8UL);
} }
static void setup_frame (int sig, struct k_sigaction *ka, static int setup_frame (int sig, struct k_sigaction *ka,
sigset_t *set, struct pt_regs *regs) sigset_t *set, struct pt_regs *regs)
{ {
struct sigframe *frame; struct sigframe __user *frame;
struct sigcontext context; struct sigcontext context;
int err = 0; int err = 0;
...@@ -617,17 +582,17 @@ static void setup_frame (int sig, struct k_sigaction *ka, ...@@ -617,17 +582,17 @@ static void setup_frame (int sig, struct k_sigaction *ka,
tregs->pc = regs->pc; tregs->pc = regs->pc;
tregs->sr = regs->sr; tregs->sr = regs->sr;
} }
return; return err;
give_sigsegv: give_sigsegv:
force_sigsegv(sig, current); force_sigsegv(sig, current);
goto adjust_stack; goto adjust_stack;
} }
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) sigset_t *set, struct pt_regs *regs)
{ {
struct rt_sigframe *frame; struct rt_sigframe __user *frame;
int err = 0; int err = 0;
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ka, regs, sizeof(*frame));
...@@ -644,8 +609,8 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -644,8 +609,8 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
/* Create the ucontext. */ /* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_flags);
err |= __put_user(0, &frame->uc.uc_link); err |= __put_user(NULL, &frame->uc.uc_link);
err |= __put_user((void *)current->sas_ss_sp, err |= __put_user((void __user *)current->sas_ss_sp,
&frame->uc.uc_stack.ss_sp); &frame->uc.uc_stack.ss_sp);
err |= __put_user(sas_ss_flags(rdusp()), err |= __put_user(sas_ss_flags(rdusp()),
&frame->uc.uc_stack.ss_flags); &frame->uc.uc_stack.ss_flags);
...@@ -681,7 +646,7 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -681,7 +646,7 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
tregs->pc = regs->pc; tregs->pc = regs->pc;
tregs->sr = regs->sr; tregs->sr = regs->sr;
} }
return; return err;
give_sigsegv: give_sigsegv:
force_sigsegv(sig, current); force_sigsegv(sig, current);
...@@ -728,6 +693,7 @@ static void ...@@ -728,6 +693,7 @@ static void
handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs) sigset_t *oldset, struct pt_regs *regs)
{ {
int err;
/* are we from a system call? */ /* are we from a system call? */
if (regs->orig_d0 >= 0) if (regs->orig_d0 >= 0)
/* If so, check system call restarting.. */ /* If so, check system call restarting.. */
...@@ -735,12 +701,12 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -735,12 +701,12 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
/* set up the stack frame */ /* set up the stack frame */
if (ka->sa.sa_flags & SA_SIGINFO) if (ka->sa.sa_flags & SA_SIGINFO)
setup_rt_frame(sig, ka, info, oldset, regs); err = setup_rt_frame(sig, ka, info, oldset, regs);
else else
setup_frame(sig, ka, oldset, regs); err = setup_frame(sig, ka, oldset, regs);
if (ka->sa.sa_flags & SA_ONESHOT) if (err)
ka->sa.sa_handler = SIG_DFL; return;
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
...@@ -748,6 +714,8 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -748,6 +714,8 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
sigaddset(&current->blocked,sig); sigaddset(&current->blocked,sig);
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
clear_thread_flag(TIF_RESTORE_SIGMASK);
} }
/* /*
...@@ -755,11 +723,12 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -755,11 +723,12 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
* want to handle. Thus you cannot kill init even with a SIGKILL even by * want to handle. Thus you cannot kill init even with a SIGKILL even by
* mistake. * mistake.
*/ */
asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) asmlinkage void do_signal(struct pt_regs *regs)
{ {
struct k_sigaction ka; struct k_sigaction ka;
siginfo_t info; siginfo_t info;
int signr; int signr;
sigset_t *oldset;
/* /*
* We want the common case to go fast, which * We want the common case to go fast, which
...@@ -768,16 +737,18 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -768,16 +737,18 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
* if so. * if so.
*/ */
if (!user_mode(regs)) if (!user_mode(regs))
return 1; return;
if (!oldset) if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked; oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, &ka, &info, oldset, regs); handle_signal(signr, &ka, &info, oldset, regs);
return 1; return;
} }
/* Did we come from a system call? */ /* Did we come from a system call? */
...@@ -785,5 +756,10 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -785,5 +756,10 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
/* Restart the system call - no handlers present */ /* Restart the system call - no handlers present */
handle_restart(regs, NULL, 0); handle_restart(regs, NULL, 0);
} }
return 0;
/* If there's no signal to deliver, we just restore the saved mask. */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
...@@ -106,6 +106,7 @@ Luser_return: ...@@ -106,6 +106,7 @@ Luser_return:
movel %sp,%d1 /* get thread_info pointer */ movel %sp,%d1 /* get thread_info pointer */
andl #-THREAD_SIZE,%d1 andl #-THREAD_SIZE,%d1
movel %d1,%a2 movel %d1,%a2
1:
move %a2@(TI_FLAGS),%d1 /* thread_info->flags */ move %a2@(TI_FLAGS),%d1 /* thread_info->flags */
andl #_TIF_WORK_MASK,%d1 andl #_TIF_WORK_MASK,%d1
jne Lwork_to_do jne Lwork_to_do
...@@ -120,13 +121,11 @@ Lsignal_return: ...@@ -120,13 +121,11 @@ Lsignal_return:
subql #4,%sp /* dummy return address*/ subql #4,%sp /* dummy return address*/
SAVE_SWITCH_STACK SAVE_SWITCH_STACK
pea %sp@(SWITCH_STACK_SIZE) pea %sp@(SWITCH_STACK_SIZE)
clrl %sp@-
bsrw do_signal bsrw do_signal
addql #8,%sp addql #4,%sp
RESTORE_SWITCH_STACK RESTORE_SWITCH_STACK
addql #4,%sp addql #4,%sp
Lreturn: jra 1b
RESTORE_ALL
/* /*
* This is the main interrupt handler, responsible for calling process_int() * This is the main interrupt handler, responsible for calling process_int()
......
...@@ -102,6 +102,7 @@ Luser_return: ...@@ -102,6 +102,7 @@ Luser_return:
movel %sp,%d1 /* get thread_info pointer */ movel %sp,%d1 /* get thread_info pointer */
andl #-THREAD_SIZE,%d1 andl #-THREAD_SIZE,%d1
movel %d1,%a2 movel %d1,%a2
1:
move %a2@(TI_FLAGS),%d1 /* thread_info->flags */ move %a2@(TI_FLAGS),%d1 /* thread_info->flags */
andl #_TIF_WORK_MASK,%d1 andl #_TIF_WORK_MASK,%d1
jne Lwork_to_do jne Lwork_to_do
...@@ -116,13 +117,11 @@ Lsignal_return: ...@@ -116,13 +117,11 @@ Lsignal_return:
subql #4,%sp /* dummy return address*/ subql #4,%sp /* dummy return address*/
SAVE_SWITCH_STACK SAVE_SWITCH_STACK
pea %sp@(SWITCH_STACK_SIZE) pea %sp@(SWITCH_STACK_SIZE)
clrl %sp@-
bsrw do_signal bsrw do_signal
addql #8,%sp addql #4,%sp
RESTORE_SWITCH_STACK RESTORE_SWITCH_STACK
addql #4,%sp addql #4,%sp
Lreturn: jra 1b
RESTORE_ALL
/* /*
* This is the main interrupt handler, responsible for calling do_IRQ() * This is the main interrupt handler, responsible for calling do_IRQ()
......
...@@ -167,12 +167,11 @@ Lsignal_return: ...@@ -167,12 +167,11 @@ Lsignal_return:
subql #4,%sp /* dummy return address */ subql #4,%sp /* dummy return address */
SAVE_SWITCH_STACK SAVE_SWITCH_STACK
pea %sp@(SWITCH_STACK_SIZE) pea %sp@(SWITCH_STACK_SIZE)
clrl %sp@-
jsr do_signal jsr do_signal
addql #8,%sp addql #4,%sp
RESTORE_SWITCH_STACK RESTORE_SWITCH_STACK
addql #4,%sp addql #4,%sp
jmp Lreturn jmp Luser_return
/* /*
* This is the generic interrupt handler (for all hardware interrupt * This is the generic interrupt handler (for all hardware interrupt
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment