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
This commit is contained in:
Linus Torvalds 2011-01-10 15:39:23 -08:00
commit 0caca697a2
10 changed files with 232 additions and 344 deletions

View File

@ -217,9 +217,8 @@ static inline pte_t pgoff_to_pte(unsigned off)
/* Find an entry in the third-level pagetable. */
#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))
/* FIXME: should we bother with kmap() here? */
#define pte_offset_map(pmd, address) ((pte_t *)kmap(pmd_page(*pmd)) + pte_index(address))
#define pte_unmap(pte) kunmap(pte)
#define pte_offset_map(pmd, address) ((pte_t *)page_address(pmd_page(*pmd)) + pte_index(address))
#define pte_unmap(pte) do { } while (0)
/* Macros to (de)construct the fake PTEs representing swap pages. */
#define __swp_type(x) ((x).val & 0x7F)

View File

@ -104,5 +104,6 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_SYSCALL_TRACE 15 /* syscall trace active */
#define TIF_MEMDIE 16 /* is terminating due to OOM killer */
#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 */

View File

@ -373,6 +373,7 @@
#define __ARCH_WANT_SYS_SIGPENDING
#define __ARCH_WANT_SYS_SIGPROCMASK
#define __ARCH_WANT_SYS_RT_SIGACTION
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
/*
* "Conditional" syscalls

View File

@ -99,7 +99,10 @@ do_trace_exit:
jra .Lret_from_exception
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
/* on 68040 complete pending writebacks if any */
#ifdef CONFIG_M68040
@ -174,16 +177,11 @@ do_signal_return:
subql #4,%sp | dummy return address
SAVE_SWITCH_STACK
pea %sp@(SWITCH_STACK_SIZE)
clrl %sp@-
bsrl do_signal
addql #8,%sp
addql #4,%sp
RESTORE_SWITCH_STACK
addql #4,%sp
tstl %d0
jeq resume_userspace
| when single stepping into handler stop at the first insn
btst #6,%curptr@(TASK_INFO+TINFO_FLAGS+2)
jeq resume_userspace
jbra resume_userspace
do_delayed_trace:
bclr #7,%sp@(PT_OFF_SR) | clear trace bit in SR
@ -290,22 +288,6 @@ ENTRY(sys_vfork)
RESTORE_SWITCH_STACK
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)
SAVE_SWITCH_STACK
jbsr do_sigreturn

View File

@ -51,8 +51,6 @@
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
const int frame_extra_sizes[16] = {
[1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */
[2] = sizeof(((struct frame *)0)->un.fmt2),
@ -74,51 +72,21 @@ const int frame_extra_sizes[16] = {
/*
* 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;
saveset = current->blocked;
spin_lock_irq(&current->sighand->siglock);
current->saved_sigmask = current->blocked;
siginitset(&current->blocked, mask);
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;
}
}
current->state = TASK_INTERRUPTIBLE;
schedule();
set_restore_sigmask();
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 -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;
}
return -ERESTARTNOHAND;
}
asmlinkage int
@ -132,10 +100,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
old_sigset_t mask;
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__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;
__get_user(new_ka.sa.sa_flags, &act->sa_flags);
__get_user(mask, &act->sa_mask);
siginitset(&new_ka.sa.sa_mask, mask);
}
@ -144,10 +112,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
if (!ret && 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_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;
__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
}
return ret;
@ -318,36 +286,10 @@ out:
return err;
}
static inline int
restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp,
int *pd0)
static int mangle_kernel_stack(struct pt_regs *regs, int formatvec,
void __user *fp)
{
int fsize, 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->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];
int fsize = frame_extra_sizes[formatvec >> 12];
if (fsize < 0) {
/*
* 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
#ifdef DEBUG
printk("user process returning with weird frame format\n");
#endif
goto badframe;
return 1;
}
/* OK. Make room on the supervisor stack for the extra junk,
* if necessary.
*/
if (fsize) {
if (!fsize) {
regs->format = formatvec >> 12;
regs->vector = formatvec & 0xfff;
} else {
struct switch_stack *sw = (struct switch_stack *)regs - 1;
regs->d0 = context.sc_d0;
unsigned long buf[fsize / 2]; /* yes, twice as much */
/* that'll make sure that expansion won't crap over data */
if (copy_from_user(buf + fsize / 4, fp, fsize))
return 1;
/* point of no return */
regs->format = formatvec >> 12;
regs->vector = formatvec & 0xfff;
#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
__asm__ __volatile__
(" movel %0,%/a0\n\t"
@ -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 */
" lsrl #2,%1\n\t"
" subql #1,%1\n\t"
"2: movesl %4@+,%2\n\t"
"3: movel %2,%/a0@+\n\t"
/* copy to the gap we'd made */
"2: movel %4@+,%/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" (fp)
"n" (frame_offset), "a" (buf + fsize/4)
: "a0");
#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;
return err;
static inline int
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:
return 1;
@ -407,9 +375,9 @@ badframe:
static inline int
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;
unsigned long usp;
int err;
@ -443,65 +411,16 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
regs->orig_d0 = -1; /* disable syscall checks */
err |= __get_user(temp, &uc->uc_formatvec);
regs->format = temp >> 12;
regs->vector = temp & 0xfff;
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;
fsize = frame_extra_sizes[regs->format];
if (fsize < 0) {
/*
* user process trying to return with weird frame format
*/
#ifdef DEBUG
printk("user process returning with weird frame format\n");
#endif
if (mangle_kernel_stack(regs, temp, &uc->uc_extra))
goto badframe;
}
/* OK. Make room on the supervisor stack for the extra junk,
* if necessary.
*/
if (fsize) {
#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;
return 0;
badframe:
return 1;
@ -514,7 +433,6 @@ asmlinkage int do_sigreturn(unsigned long __unused)
unsigned long usp = rdusp();
struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
sigset_t set;
int d0;
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
@ -528,9 +446,9 @@ asmlinkage int do_sigreturn(unsigned long __unused)
current->blocked = set;
recalc_sigpending();
if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0))
if (restore_sigcontext(regs, &frame->sc, frame + 1))
goto badframe;
return d0;
return regs->d0;
badframe:
force_sig(SIGSEGV, current);
@ -544,7 +462,6 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
unsigned long usp = rdusp();
struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4);
sigset_t set;
int d0;
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
@ -555,9 +472,9 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
current->blocked = set;
recalc_sigpending();
if (rt_restore_ucontext(regs, sw, &frame->uc, &d0))
if (rt_restore_ucontext(regs, sw, &frame->uc))
goto badframe;
return d0;
return regs->d0;
badframe:
force_sig(SIGSEGV, current);
@ -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);
}
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)
{
struct sigframe __user *frame;
@ -793,10 +710,8 @@ static void setup_frame (int sig, struct k_sigaction *ka,
frame = get_sigframe(ka, regs, sizeof(*frame) + fsize);
if (fsize) {
if (fsize)
err |= copy_to_user (frame + 1, regs + 1, fsize);
regs->stkadj = fsize;
}
err |= __put_user((current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap
@ -826,11 +741,21 @@ static void setup_frame (int sig, struct k_sigaction *ka,
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);
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. */
if (regs->stkadj) {
struct pt_regs *tregs =
@ -845,14 +770,14 @@ adjust_stack:
tregs->pc = regs->pc;
tregs->sr = regs->sr;
}
return;
return 0;
give_sigsegv:
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)
{
struct rt_sigframe __user *frame;
@ -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));
if (fsize) {
if (fsize)
err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
regs->stkadj = fsize;
}
err |= __put_user((current_thread_info()->exec_domain
&& 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,
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);
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. */
if (regs->stkadj) {
struct pt_regs *tregs =
@ -933,11 +866,11 @@ adjust_stack:
tregs->pc = regs->pc;
tregs->sr = regs->sr;
}
return;
return 0;
give_sigsegv:
force_sigsegv(sig, current);
goto adjust_stack;
return err;
}
static inline void
@ -995,6 +928,7 @@ static void
handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs)
{
int err;
/* are we from a system call? */
if (regs->orig_d0 >= 0)
/* If so, check system call restarting.. */
@ -1002,17 +936,24 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
/* set up the stack frame */
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
setup_frame(sig, ka, oldset, regs);
err = setup_frame(sig, ka, oldset, regs);
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
if (err)
return;
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
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,
* want to handle. Thus you cannot kill init even with a SIGKILL even by
* mistake.
*/
asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
asmlinkage void do_signal(struct pt_regs *regs)
{
siginfo_t info;
struct k_sigaction ka;
int signr;
sigset_t *oldset;
current->thread.esp0 = (unsigned long) regs;
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) {
/* Whee! Actually deliver the signal. */
handle_signal(signr, &ka, &info, oldset, regs);
return 1;
return;
}
/* Did we come from a system call? */
@ -1043,5 +987,9 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
/* Restart the system call - no handlers present */
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);
}
}

View File

@ -112,22 +112,6 @@ ENTRY(sys_clone)
RESTORE_SWITCH_STACK
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)
SAVE_SWITCH_STACK
jbsr do_sigreturn

View File

@ -53,65 +53,30 @@
void ret_from_user_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.
*/
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;
spin_lock_irq(&current->sighand->siglock);
saveset = current->blocked;
current->saved_sigmask = current->blocked;
siginitset(&current->blocked, mask);
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;
}
current->state = TASK_INTERRUPTIBLE;
schedule();
set_restore_sigmask();
return -ERESTARTNOHAND;
}
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 -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
sys_sigaction(int sig, const struct old_sigaction *act,
struct old_sigaction *oact)
sys_sigaction(int sig, const struct old_sigaction __user *act,
struct old_sigaction __user *oact)
{
struct k_sigaction new_ka, old_ka;
int ret;
@ -120,10 +85,10 @@ sys_sigaction(int sig, const struct old_sigaction *act,
old_sigset_t mask;
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__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;
__get_user(new_ka.sa.sa_flags, &act->sa_flags);
__get_user(mask, &act->sa_mask);
siginitset(&new_ka.sa.sa_mask, mask);
}
@ -132,17 +97,17 @@ sys_sigaction(int sig, const struct old_sigaction *act,
if (!ret && 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_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;
__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
}
return ret;
}
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());
}
@ -157,10 +122,10 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss)
struct sigframe
{
char *pretcode;
char __user *pretcode;
int sig;
int code;
struct sigcontext *psc;
struct sigcontext __user *psc;
char retcode[8];
unsigned long extramask[_NSIG_WORDS-1];
struct sigcontext sc;
@ -168,10 +133,10 @@ struct sigframe
struct rt_sigframe
{
char *pretcode;
char __user *pretcode;
int sig;
struct siginfo *pinfo;
void *puc;
struct siginfo __user *pinfo;
void __user *puc;
char retcode[8];
struct siginfo info;
struct ucontext uc;
@ -198,8 +163,8 @@ static inline int restore_fpu_state(struct sigcontext *sc)
goto out;
__asm__ volatile (".chip 68k/68881\n\t"
"fmovemx %0,%/fp0-%/fp1\n\t"
"fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t"
"fmovemx %0,%%fp0-%%fp1\n\t"
"fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
".chip 68k"
: /* no outputs */
: "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl));
@ -218,7 +183,7 @@ out:
#define uc_formatvec uc_filler[FPCONTEXT_SIZE/4]
#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];
int context_size = 0;
@ -228,7 +193,7 @@ static inline int rt_restore_fpu_state(struct ucontext *uc)
if (FPU_IS_EMU) {
/* restore fpu control register */
if (__copy_from_user(current->thread.fpcntl,
&uc->uc_mcontext.fpregs.f_pcr, 12))
uc->uc_mcontext.fpregs.f_fpcntl, 12))
goto out;
/* restore all other fpu register */
if (__copy_from_user(current->thread.fp,
@ -237,7 +202,7 @@ static inline int rt_restore_fpu_state(struct ucontext *uc)
return 0;
}
if (__get_user(*(long *)fpstate, (long *)&uc->uc_fpstate))
if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate))
goto out;
if (fpstate[0]) {
context_size = fpstate[1];
@ -249,15 +214,15 @@ static inline int rt_restore_fpu_state(struct ucontext *uc)
sizeof(fpregs)))
goto out;
__asm__ volatile (".chip 68k/68881\n\t"
"fmovemx %0,%/fp0-%/fp7\n\t"
"fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t"
"fmovemx %0,%%fp0-%%fp7\n\t"
"fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
".chip 68k"
: /* no outputs */
: "m" (*fpregs.f_fpregs),
"m" (fpregs.f_pcr));
"m" (*fpregs.f_fpcntl));
}
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))
goto out;
__asm__ volatile (".chip 68k/68881\n\t"
@ -272,7 +237,7 @@ out:
#endif
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 formatvec;
@ -312,10 +277,10 @@ badframe:
static inline int
rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
struct ucontext *uc, int *pd0)
struct ucontext __user *uc, int *pd0)
{
int temp;
greg_t *gregs = uc->uc_mcontext.gregs;
greg_t __user *gregs = uc->uc_mcontext.gregs;
unsigned long usp;
int err;
@ -365,7 +330,7 @@ asmlinkage int do_sigreturn(unsigned long __unused)
struct switch_stack *sw = (struct switch_stack *) &__unused;
struct pt_regs *regs = (struct pt_regs *) (sw + 1);
unsigned long usp = rdusp();
struct sigframe *frame = (struct sigframe *)(usp - 4);
struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
sigset_t set;
int d0;
@ -397,7 +362,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
struct switch_stack *sw = (struct switch_stack *) &__unused;
struct pt_regs *regs = (struct pt_regs *) (sw + 1);
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;
int d0;
@ -443,17 +408,17 @@ static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
if (sc->sc_fpstate[0]) {
fpu_version = sc->sc_fpstate[0];
__asm__ volatile (".chip 68k/68881\n\t"
"fmovemx %/fp0-%/fp1,%0\n\t"
"fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t"
"fmovemx %%fp0-%%fp1,%0\n\t"
"fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
".chip 68k"
: /* no outputs */
: "m" (*sc->sc_fpregs),
"m" (*sc->sc_fpcntl)
: "=m" (*sc->sc_fpregs),
"=m" (*sc->sc_fpcntl)
: /* no inputs */
: "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];
int context_size = 0;
@ -461,7 +426,7 @@ static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs)
if (FPU_IS_EMU) {
/* 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);
/* save all other fpu register */
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)
".chip 68k"
: : "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]) {
fpregset_t fpregs;
context_size = fpstate[1];
fpu_version = fpstate[0];
__asm__ volatile (".chip 68k/68881\n\t"
"fmovemx %/fp0-%/fp7,%0\n\t"
"fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t"
"fmovemx %%fp0-%%fp7,%0\n\t"
"fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
".chip 68k"
: /* no outputs */
: "m" (*fpregs.f_fpregs),
"m" (fpregs.f_pcr)
: "=m" (*fpregs.f_fpregs),
"=m" (*fpregs.f_fpcntl)
: /* no inputs */
: "memory");
err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
sizeof(fpregs));
}
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);
return err;
}
@ -516,10 +481,10 @@ static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
#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;
greg_t *gregs = uc->uc_mcontext.gregs;
greg_t __user *gregs = uc->uc_mcontext.gregs;
int err = 0;
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)
return err;
}
static inline void *
static inline void __user *
get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
{
unsigned long usp;
@ -560,13 +525,13 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
if (!sas_ss_flags(usp))
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)
{
struct sigframe *frame;
struct sigframe __user *frame;
struct sigcontext context;
int err = 0;
@ -617,17 +582,17 @@ adjust_stack:
tregs->pc = regs->pc;
tregs->sr = regs->sr;
}
return;
return err;
give_sigsegv:
force_sigsegv(sig, current);
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)
{
struct rt_sigframe *frame;
struct rt_sigframe __user *frame;
int err = 0;
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,
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
err |= __put_user(0, &frame->uc.uc_link);
err |= __put_user((void *)current->sas_ss_sp,
err |= __put_user(NULL, &frame->uc.uc_link);
err |= __put_user((void __user *)current->sas_ss_sp,
&frame->uc.uc_stack.ss_sp);
err |= __put_user(sas_ss_flags(rdusp()),
&frame->uc.uc_stack.ss_flags);
@ -681,7 +646,7 @@ adjust_stack:
tregs->pc = regs->pc;
tregs->sr = regs->sr;
}
return;
return err;
give_sigsegv:
force_sigsegv(sig, current);
@ -728,6 +693,7 @@ static void
handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs)
{
int err;
/* are we from a system call? */
if (regs->orig_d0 >= 0)
/* If so, check system call restarting.. */
@ -735,12 +701,12 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
/* set up the stack frame */
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
setup_frame(sig, ka, oldset, regs);
err = setup_frame(sig, ka, oldset, regs);
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
if (err)
return;
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@ -748,6 +714,8 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
sigaddset(&current->blocked,sig);
recalc_sigpending();
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,
* want to handle. Thus you cannot kill init even with a SIGKILL even by
* mistake.
*/
asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
asmlinkage void do_signal(struct pt_regs *regs)
{
struct k_sigaction ka;
siginfo_t info;
int signr;
sigset_t *oldset;
/*
* We want the common case to go fast, which
@ -768,16 +737,18 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
* if so.
*/
if (!user_mode(regs))
return 1;
return;
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) {
/* Whee! Actually deliver the signal. */
handle_signal(signr, &ka, &info, oldset, regs);
return 1;
return;
}
/* Did we come from a system call? */
@ -785,5 +756,10 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
/* Restart the system call - no handlers present */
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);
}
}

View File

@ -106,6 +106,7 @@ Luser_return:
movel %sp,%d1 /* get thread_info pointer */
andl #-THREAD_SIZE,%d1
movel %d1,%a2
1:
move %a2@(TI_FLAGS),%d1 /* thread_info->flags */
andl #_TIF_WORK_MASK,%d1
jne Lwork_to_do
@ -120,13 +121,11 @@ Lsignal_return:
subql #4,%sp /* dummy return address*/
SAVE_SWITCH_STACK
pea %sp@(SWITCH_STACK_SIZE)
clrl %sp@-
bsrw do_signal
addql #8,%sp
addql #4,%sp
RESTORE_SWITCH_STACK
addql #4,%sp
Lreturn:
RESTORE_ALL
jra 1b
/*
* This is the main interrupt handler, responsible for calling process_int()

View File

@ -102,6 +102,7 @@ Luser_return:
movel %sp,%d1 /* get thread_info pointer */
andl #-THREAD_SIZE,%d1
movel %d1,%a2
1:
move %a2@(TI_FLAGS),%d1 /* thread_info->flags */
andl #_TIF_WORK_MASK,%d1
jne Lwork_to_do
@ -116,13 +117,11 @@ Lsignal_return:
subql #4,%sp /* dummy return address*/
SAVE_SWITCH_STACK
pea %sp@(SWITCH_STACK_SIZE)
clrl %sp@-
bsrw do_signal
addql #8,%sp
addql #4,%sp
RESTORE_SWITCH_STACK
addql #4,%sp
Lreturn:
RESTORE_ALL
jra 1b
/*
* This is the main interrupt handler, responsible for calling do_IRQ()

View File

@ -167,12 +167,11 @@ Lsignal_return:
subql #4,%sp /* dummy return address */
SAVE_SWITCH_STACK
pea %sp@(SWITCH_STACK_SIZE)
clrl %sp@-
jsr do_signal
addql #8,%sp
addql #4,%sp
RESTORE_SWITCH_STACK
addql #4,%sp
jmp Lreturn
jmp Luser_return
/*
* This is the generic interrupt handler (for all hardware interrupt