summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-10 15:39:23 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-10 15:39:23 -0800
commit0caca697a2d173c6beff3c24e7d9481b732bd131 (patch)
tree5a39998978a385b9d0efd0692fe9db34c3aa839d /arch
parentecacc6c70cf77a52a22af66c879873202522d6ce (diff)
parent751c88a2c362a4a8985f9a2cb5daf7cd9ce1c4d0 (diff)
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
Diffstat (limited to 'arch')
-rw-r--r--arch/m68k/include/asm/sun3_pgtable.h5
-rw-r--r--arch/m68k/include/asm/thread_info.h1
-rw-r--r--arch/m68k/include/asm/unistd.h1
-rw-r--r--arch/m68k/kernel/entry.S30
-rw-r--r--arch/m68k/kernel/signal.c314
-rw-r--r--arch/m68knommu/kernel/entry.S16
-rw-r--r--arch/m68knommu/kernel/signal.c188
-rw-r--r--arch/m68knommu/platform/68328/entry.S7
-rw-r--r--arch/m68knommu/platform/68360/entry.S7
-rw-r--r--arch/m68knommu/platform/coldfire/entry.S5
10 files changed, 231 insertions, 343 deletions
diff --git a/arch/m68k/include/asm/sun3_pgtable.h b/arch/m68k/include/asm/sun3_pgtable.h
index cf5fad9b5250..f55aa04161e8 100644
--- a/arch/m68k/include/asm/sun3_pgtable.h
+++ b/arch/m68k/include/asm/sun3_pgtable.h
@@ -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)
diff --git a/arch/m68k/include/asm/thread_info.h b/arch/m68k/include/asm/thread_info.h
index 1da5d53a00eb..790988967ba7 100644
--- a/arch/m68k/include/asm/thread_info.h
+++ b/arch/m68k/include/asm/thread_info.h
@@ -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 */
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h
index b43b36beafe3..26d851d385bb 100644
--- a/arch/m68k/include/asm/unistd.h
+++ b/arch/m68k/include/asm/unistd.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
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 6360c437dcf5..1559dea36e55 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -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
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index 4b387538706f..d12c3b0d9e4f 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -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;
- }
-}
-
-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;
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ set_restore_sigmask();
- 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;
}
+ 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,
- * if necessary.
- */
+ /* that'll make sure that expansion won't crap over data */
+ if (copy_from_user(buf + fsize / 4, fp, fsize))
+ return 1;
- if (fsize) {
- struct switch_stack *sw = (struct switch_stack *)regs - 1;
- regs->d0 = context.sc_d0;
+ /* 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);
+ }
}
diff --git a/arch/m68knommu/kernel/entry.S b/arch/m68knommu/kernel/entry.S
index aff6f57ef8b5..2783f25e38bd 100644
--- a/arch/m68knommu/kernel/entry.S
+++ b/arch/m68knommu/kernel/entry.S
@@ -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
diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c
index 5ab6a04af14e..36a81bb6835a 100644
--- a/arch/m68knommu/kernel/signal.c
+++ b/arch/m68knommu/kernel/signal.c
@@ -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;
- }
-}
-
-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;
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ set_restore_sigmask();
- 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;
- }
+ return -ERESTARTNOHAND;
}
-asmlinkage int
-sys_sigaction(int sig, const struct old_sigaction *act,
- struct old_sigaction *oact)
+asmlinkage int
+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);
+ }
}
diff --git a/arch/m68knommu/platform/68328/entry.S b/arch/m68knommu/platform/68328/entry.S
index 27241e16a526..240a7a6e25c8 100644
--- a/arch/m68knommu/platform/68328/entry.S
+++ b/arch/m68knommu/platform/68328/entry.S
@@ -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()
diff --git a/arch/m68knommu/platform/68360/entry.S b/arch/m68knommu/platform/68360/entry.S
index c131c6e1d92d..8a28788c0eea 100644
--- a/arch/m68knommu/platform/68360/entry.S
+++ b/arch/m68knommu/platform/68360/entry.S
@@ -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()
diff --git a/arch/m68knommu/platform/coldfire/entry.S b/arch/m68knommu/platform/coldfire/entry.S
index 5e92bed94b7e..e1debc8285ef 100644
--- a/arch/m68knommu/platform/coldfire/entry.S
+++ b/arch/m68knommu/platform/coldfire/entry.S
@@ -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