mirror of https://gitee.com/openkylin/linux.git
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:
commit
0caca697a2
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(¤t->sighand->siglock);
|
||||
current->saved_sigmask = current->blocked;
|
||||
siginitset(¤t->blocked, mask);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->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 @@ static inline int rt_restore_fpu_state(struct ucontext __user *uc)
|
|||
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 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u
|
|||
|
||||
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 @@ static void setup_frame (int sig, struct k_sigaction *ka,
|
|||
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 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||
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(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->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 = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->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, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(¤t->sighand->siglock);
|
||||
saveset = current->blocked;
|
||||
current->saved_sigmask = current->blocked;
|
||||
siginitset(¤t->blocked, mask);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->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(¤t->sighand->siglock);
|
||||
saveset = current->blocked;
|
||||
current->blocked = newset;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->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 @@ static inline int restore_fpu_state(struct sigcontext *sc)
|
|||
#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 @@ static inline int rt_restore_fpu_state(struct ucontext *uc)
|
|||
#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 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp,
|
|||
|
||||
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 @@ static void setup_frame (int sig, struct k_sigaction *ka,
|
|||
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 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||
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(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
|
@ -748,6 +714,8 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||
sigaddset(¤t->blocked,sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->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 = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->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, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue