patch-2.0.21-2.1.0 linux/arch/m68k/kernel/signal.c
Next file: linux/arch/m68k/kernel/sys_m68k.c
Previous file: linux/arch/m68k/kernel/setup.c
Back to the patch index
Back to the overall index
- Lines: 580
- Date:
Wed Sep 25 10:47:39 1996
- Orig file:
lx2.0/v2.0.21/linux/arch/m68k/kernel/signal.c
- Orig date:
Mon May 20 07:54:26 1996
diff -u --recursive --new-file lx2.0/v2.0.21/linux/arch/m68k/kernel/signal.c linux/arch/m68k/kernel/signal.c
@@ -9,7 +9,17 @@
*/
/*
- * 680x0 support by Hamish Macdonald
+ * Linux/m68k support by Hamish Macdonald
+ *
+ * 68060 fixes by Jesper Skov
+ */
+
+/*
+ * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
+ * Atari :-) Current limitation: Only one sigstack can be active at one time.
+ * If a second signal with SA_STACK set arrives while working on a sigstack,
+ * SA_STACK is ignored. This behaviour avoids lots of trouble with nested
+ * signal handlers!
*/
#include <linux/sched.h>
@@ -21,10 +31,10 @@
#include <linux/ptrace.h>
#include <linux/unistd.h>
+#include <asm/setup.h>
#include <asm/segment.h>
#include <asm/pgtable.h>
#include <asm/traps.h>
-#include <asm/bootinfo.h>
#define offsetof(type, member) ((size_t)(&((type *)0)->member))
@@ -74,13 +84,10 @@
static unsigned char fpu_version = 0; /* version number of fpu, set by setup_frame */
-/*
- * This sets regs->usp even though we don't actually use sigstacks yet..
- */
asmlinkage int do_sigreturn(unsigned long __unused)
{
struct sigcontext_struct context;
- struct frame * regs;
+ struct pt_regs *regs;
struct switch_stack *sw;
int fsize = 0;
int formatvec = 0;
@@ -93,7 +100,7 @@
/* get stack frame pointer */
sw = (struct switch_stack *) &__unused;
- regs = (struct frame *) (sw + 1);
+ regs = (struct pt_regs *) (sw + 1);
/* get previous context (including pointer to possible extra junk) */
if (verify_area(VERIFY_READ, (void *)usp, sizeof(context)))
@@ -107,37 +114,21 @@
current->blocked = context.sc_mask & _BLOCKABLE;
/* restore passed registers */
- regs->ptregs.d0 = context.sc_d0;
- regs->ptregs.d1 = context.sc_d1;
- regs->ptregs.a0 = context.sc_a0;
- regs->ptregs.a1 = context.sc_a1;
- regs->ptregs.sr = (regs->ptregs.sr & 0xff00)|(context.sc_sr & 0xff);
- regs->ptregs.pc = context.sc_pc;
-
+ 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;
- regs->ptregs.format = formatvec >> 12;
- regs->ptregs.vector = formatvec & 0xfff;
- if (context.sc_fpstate[0])
- {
+ regs->format = formatvec >> 12;
+ regs->vector = formatvec & 0xfff;
+ if ((!CPU_IS_060 && context.sc_fpstate[0]) || (CPU_IS_060 && context.sc_fpstate[2])){
/* Verify the frame format. */
- if (context.sc_fpstate[0] != fpu_version){
-#if DEBUG
- printk("fpregs=%08x fpcntl=%08x\n", context.sc_fpregs,
- context.sc_fpcntl);
- printk("Wrong fpu: sc_fpstate[0]=%02x fpu_version=%02x\n",
- (unsigned) context.sc_fpstate[0], (unsigned) fpu_version);
- {
- int i;
- printk("Saved fp_state: ");
- for (i = 0; i < 216; i++){
- printk("%02x ", context.sc_fpstate[i]);
- }
- printk("\n");
- }
-#endif
+ if (!CPU_IS_060 && (context.sc_fpstate[0] != fpu_version))
goto badframe;
- }
if (boot_info.cputype & FPU_68881)
{
if (context.sc_fpstate[1] != 0x18
@@ -147,34 +138,22 @@
else if (boot_info.cputype & FPU_68882)
{
if (context.sc_fpstate[1] != 0x38
- && context.sc_fpstate[1] != 0xd4){
-#if 0
- printk("Wrong 68882 fpu-state\n");
-#endif
+ && context.sc_fpstate[1] != 0xd4)
goto badframe;
- }
}
else if (boot_info.cputype & FPU_68040)
{
- if (!((context.sc_fpstate[1] == 0x00)|| \
- (context.sc_fpstate[1] == 0x28)|| \
- (context.sc_fpstate[1] == 0x60))){
-#if 0
- printk("Wrong 68040 fpu-state\n");
-#endif
+ if (!(context.sc_fpstate[1] == 0x00 ||
+ context.sc_fpstate[1] == 0x28 ||
+ context.sc_fpstate[1] == 0x60))
goto badframe;
- }
}
else if (boot_info.cputype & FPU_68060)
{
- if (!((context.sc_fpstate[1] == 0x00)|| \
- (context.sc_fpstate[1] == 0x60)|| \
- (context.sc_fpstate[1] == 0xe0))){
-#if 0
- printk("Wrong 68060 fpu-state\n");
-#endif
+ if (!(context.sc_fpstate[3] == 0x00 ||
+ context.sc_fpstate[3] == 0x60 ||
+ context.sc_fpstate[3] == 0xe0))
goto badframe;
- }
}
__asm__ volatile ("fmovemx %0,%/fp0-%/fp1\n\t"
"fmoveml %1,%/fpcr/%/fpsr/%/fpiar"
@@ -184,17 +163,20 @@
}
__asm__ volatile ("frestore %0" : : "m" (*context.sc_fpstate));
- fsize = extra_sizes[regs->ptregs.format];
+ fsize = extra_sizes[regs->format];
if (fsize < 0) {
/*
* user process trying to return with weird frame format
*/
#if DEBUG
- printk("user process returning with weird frame format\n");
+ printk("user process returning with weird frame format\n");
#endif
goto badframe;
}
+ if (context.sc_usp != fp+fsize)
+ current->flags &= ~PF_ONSIGSTK;
+
/* OK. Make room on the supervisor stack for the extra junk,
* if necessary.
*/
@@ -227,7 +209,7 @@
/* NOTREACHED */
}
- return regs->ptregs.d0;
+ return regs->d0;
badframe:
do_exit(SIGSEGV);
}
@@ -275,25 +257,31 @@
#define UFRAME_SIZE(fs) (sizeof(struct sigcontext_struct)/4 + 6 + fs/4)
-static void setup_frame (struct sigaction * sa, unsigned long **fp,
- unsigned long pc, struct frame *regs, int
- signr, unsigned long oldmask)
+static void setup_frame (struct sigaction * sa, struct pt_regs *regs,
+ int signr, unsigned long oldmask)
{
struct sigcontext_struct context;
unsigned long *frame, *tframe;
- int fsize = extra_sizes[regs->ptregs.format];
+ int fsize = extra_sizes[regs->format];
if (fsize < 0) {
printk ("setup_frame: Unknown frame format %#x\n",
- regs->ptregs.format);
+ regs->format);
do_exit(SIGSEGV);
}
- frame = *fp - UFRAME_SIZE(fsize);
+
+ frame = (unsigned long *)rdusp();
+ if (!(current->flags & PF_ONSIGSTK) && (sa->sa_flags & SA_STACK)) {
+ frame = (unsigned long *)sa->sa_restorer;
+ current->flags |= PF_ONSIGSTK;
+ }
+ frame -= UFRAME_SIZE(fsize);
+
if (verify_area(VERIFY_WRITE,frame,UFRAME_SIZE(fsize)*4))
do_exit(SIGSEGV);
if (fsize) {
- memcpy_tofs (frame + UFRAME_SIZE(0), ®s->un, fsize);
- regs->ptregs.stkadj = fsize;
+ memcpy_tofs (frame + UFRAME_SIZE(0), regs + 1, fsize);
+ regs->stkadj = fsize;
}
/* set up the "normal" stack seen by the signal handler */
@@ -307,7 +295,7 @@
put_user(signr, tframe);
tframe++;
- put_user(regs->ptregs.vector, tframe); tframe++;
+ put_user(regs->vector, tframe); tframe++;
/* "scp" parameter. points to sigcontext */
put_user((ulong)(frame+6), tframe); tframe++;
@@ -320,60 +308,85 @@
/* setup and copy the sigcontext structure */
context.sc_mask = oldmask;
- context.sc_usp = (unsigned long)*fp;
- context.sc_d0 = regs->ptregs.d0;
- context.sc_d1 = regs->ptregs.d1;
- context.sc_a0 = regs->ptregs.a0;
- context.sc_a1 = regs->ptregs.a1;
- context.sc_sr = regs->ptregs.sr;
- context.sc_pc = pc;
- context.sc_formatvec = (regs->ptregs.format << 12 |
- regs->ptregs.vector);
-#if DEBUG
- printk("formatvec: %02x\n", (unsigned) context.sc_formatvec);
-#endif
+ context.sc_usp = rdusp();
+ context.sc_d0 = regs->d0;
+ context.sc_d1 = regs->d1;
+ context.sc_a0 = regs->a0;
+ context.sc_a1 = regs->a1;
+ context.sc_sr = regs->sr;
+ context.sc_pc = regs->pc;
+ context.sc_formatvec = (regs->format << 12 | regs->vector);
__asm__ volatile ("fsave %0" : : "m" (*context.sc_fpstate) : "memory");
- if (context.sc_fpstate[0])
- {
- fpu_version = context.sc_fpstate[0];
-#if DEBUG
- {
- int i;
- printk("Saved fp_state: ");
- for (i = 0; i < 216; i++){
- printk("%02x ", context.sc_fpstate[i]);
- }
- printk("\n");
- }
- printk("fpregs=%08x fpcntl=%08x\n", context.sc_fpregs,
- context.sc_fpcntl);
-#endif
- __asm__ volatile ("fmovemx %/fp0-%/fp1,%0\n\t"
- "fmoveml %/fpcr/%/fpsr/%/fpiar,%1"
- : /* no outputs */
- : "m" (*context.sc_fpregs),
- "m" (*context.sc_fpcntl)
- : "memory");
- }
-#if DEBUG
- {
- int i;
- printk("Saved fp_state: ");
- for (i = 0; i < 216; i++){
- printk("%02x ", context.sc_fpstate[i]);
- }
- printk("\n");
+ if ((!CPU_IS_060 && context.sc_fpstate[0]) || (CPU_IS_060 && context.sc_fpstate[2])){
+ fpu_version = context.sc_fpstate[0];
+ __asm__ volatile ("fmovemx %/fp0-%/fp1,%0\n\t"
+ "fmoveml %/fpcr/%/fpsr/%/fpiar,%1"
+ : /* no outputs */
+ : "m" (*context.sc_fpregs),
+ "m" (*context.sc_fpcntl)
+ : "memory");
}
-#endif
memcpy_tofs (tframe, &context, sizeof(context));
+
/*
* no matter what frame format we were using before, we
* will do the "RTE" using a normal 4 word frame.
*/
- regs->ptregs.format = 0;
+ regs->format = 0;
+
+ /* Set up registers for signal handler */
+ wrusp ((unsigned long) frame);
+ regs->pc = (unsigned long) sa->sa_handler;
+
+ /* Prepare to skip over the extra stuff in the exception frame. */
+ if (regs->stkadj) {
+ struct pt_regs *tregs =
+ (struct pt_regs *)((ulong)regs + regs->stkadj);
+#if DEBUG
+ printk("Performing stackadjust=%04x\n", regs->stkadj);
+#endif
+ /* This must be copied with decreasing addresses to
+ handle overlaps. */
+ tregs->vector = regs->vector;
+ tregs->format = regs->format;
+ tregs->pc = regs->pc;
+ tregs->sr = regs->sr;
+ }
+}
- /* "return" new usp to caller */
- *fp = frame;
+/*
+ * OK, we're invoking a handler
+ */
+static void handle_signal(unsigned long signr, struct sigaction *sa,
+ unsigned long oldmask, struct pt_regs *regs)
+{
+ /* are we from a system call? */
+ if (regs->orig_d0 >= 0) {
+ /* If so, check system call restarting.. */
+ switch (regs->d0) {
+ case -ERESTARTNOHAND:
+ regs->d0 = -EINTR;
+ break;
+
+ case -ERESTARTSYS:
+ if (!(sa->sa_flags & SA_RESTART)) {
+ regs->d0 = -EINTR;
+ break;
+ }
+ /* fallthrough */
+ case -ERESTARTNOINTR:
+ regs->d0 = regs->orig_d0;
+ regs->pc -= 2;
+ }
+ }
+
+ /* set up the stack frame */
+ setup_frame(sa, regs, signr, oldmask);
+
+ if (sa->sa_flags & SA_ONESHOT)
+ sa->sa_handler = NULL;
+ if (!(sa->sa_flags & SA_NOMASK))
+ current->blocked |= (sa->sa_mask | _S(signr)) & _BLOCKABLE;
}
/*
@@ -385,52 +398,59 @@
* that the kernel can handle, and then we build all the user-level signal
* handling stack-frames in one go after that.
*/
-asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs_in)
+asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs)
{
unsigned long mask = ~current->blocked;
- unsigned long handler_signal = 0;
- unsigned long *frame = NULL;
- unsigned long pc = 0;
unsigned long signr;
- struct frame *regs = (struct frame *)regs_in;
struct sigaction * sa;
current->tss.esp0 = (unsigned long) regs;
+ /* If the process is traced, all signals are passed to the debugger. */
+ if (current->flags & PF_PTRACED)
+ mask = ~0UL;
while ((signr = current->signal & mask)) {
__asm__("bfffo %2,#0,#0,%1\n\t"
"bfclr %0,%1,#1\n\t"
"eorw #31,%1"
- :"=m" (current->signal),"=r" (signr)
- :"1" (signr));
+ :"=m" (current->signal),"=d" (signr)
+ :"0" (current->signal), "1" (signr));
sa = current->sig->action + signr;
signr++;
if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
current->exit_code = signr;
current->state = TASK_STOPPED;
+
+ /* Did we come from a system call? */
+ if (regs->orig_d0 >= 0) {
+ /* Restart the system call */
+ if (regs->d0 == -ERESTARTNOHAND ||
+ regs->d0 == -ERESTARTSYS ||
+ regs->d0 == -ERESTARTNOINTR) {
+ regs->d0 = regs->orig_d0;
+ regs->pc -= 2;
+ }
+ }
notify_parent(current);
schedule();
if (!(signr = current->exit_code)) {
discard_frame:
- /* Make sure that a faulted bus cycle
- isn't restarted. */
- switch (regs->ptregs.format) {
- case 7:
- case 9:
- case 10:
- case 11:
- regs->ptregs.stkadj = extra_sizes[regs->ptregs.format];
- regs->ptregs.format = 0;
- break;
- }
- continue;
+ /* Make sure that a faulted bus cycle
+ isn't restarted (only needed on the
+ 68030). */
+ if (regs->format == 10 || regs->format == 11) {
+ regs->stkadj = extra_sizes[regs->format];
+ regs->format = 0;
+ }
+ continue;
}
current->exit_code = 0;
if (signr == SIGSTOP)
goto discard_frame;
if (_S(signr) & current->blocked) {
current->signal |= _S(signr);
+ mask &= ~_S(signr);
continue;
}
sa = current->sig->action + signr - 1;
@@ -447,10 +467,13 @@
if (current->pid == 1)
continue;
switch (signr) {
- case SIGCONT: case SIGCHLD: case SIGWINCH:
+ case SIGCONT: case SIGCHLD: case SIGWINCH:
continue;
- case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
+ case SIGTSTP: case SIGTTIN: case SIGTTOU:
+ if (is_orphaned_pgrp(current->pgrp))
+ continue;
+ case SIGSTOP:
if (current->flags & PF_PTRACED)
continue;
current->state = TASK_STOPPED;
@@ -461,97 +484,46 @@
schedule();
continue;
- case SIGQUIT: case SIGILL: case SIGTRAP:
- case SIGIOT: case SIGFPE: case SIGSEGV:
+ case SIGQUIT: case SIGILL: case SIGTRAP:
+ case SIGIOT: case SIGFPE: case SIGSEGV:
if (current->binfmt && current->binfmt->core_dump) {
- if (current->binfmt->core_dump(signr, (struct pt_regs *)regs))
+ if (current->binfmt->core_dump(signr, regs))
signr |= 0x80;
}
/* fall through */
- default:
+ default:
current->signal |= _S(signr & 0x7f);
+ current->flags |= PF_SIGNALED;
do_exit(signr);
}
}
- /*
- * OK, we're invoking a handler
- */
- if (regs->ptregs.orig_d0 >= 0) {
- if (regs->ptregs.d0 == -ERESTARTNOHAND ||
- (regs->ptregs.d0 == -ERESTARTSYS &&
- !(sa->sa_flags & SA_RESTART)))
- regs->ptregs.d0 = -EINTR;
- }
- handler_signal |= 1 << (signr-1);
- mask &= ~sa->sa_mask;
+ handle_signal(signr, sa, oldmask, regs);
+ return 1;
}
- if (regs->ptregs.orig_d0 >= 0 &&
- (regs->ptregs.d0 == -ERESTARTNOHAND ||
- regs->ptregs.d0 == -ERESTARTSYS ||
- regs->ptregs.d0 == -ERESTARTNOINTR)) {
- regs->ptregs.d0 = regs->ptregs.orig_d0;
- regs->ptregs.pc -= 2;
- }
- if (!handler_signal) /* no handler will be called - return 0 */
- {
- /* If we are about to discard some frame stuff we must
- copy over the remaining frame. */
- if (regs->ptregs.stkadj)
- {
- struct frame *tregs =
- (struct frame *) ((ulong) regs + regs->ptregs.stkadj);
- /* This must be copied with decreasing addresses to
- handle overlaps. */
- tregs->ptregs.vector = regs->ptregs.vector;
- tregs->ptregs.format = regs->ptregs.format;
- tregs->ptregs.pc = regs->ptregs.pc;
- tregs->ptregs.sr = regs->ptregs.sr;
- }
- return 0;
- }
- pc = regs->ptregs.pc;
- frame = (unsigned long *)rdusp();
- signr = 1;
- sa = current->sig->action;
- for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
- if (mask > handler_signal)
- break;
- if (!(mask & handler_signal))
- continue;
- setup_frame(sa,&frame,pc,regs,signr,oldmask);
- pc = (unsigned long) sa->sa_handler;
- if (sa->sa_flags & SA_ONESHOT)
- sa->sa_handler = NULL;
-/* force a supervisor-mode page-in of the signal handler to reduce races */
- __asm__ __volatile__("movesb %0,%/d0": :"m" (*(char *)pc):"d0");
- current->blocked |= sa->sa_mask;
- oldmask |= sa->sa_mask;
+ /* Did we come from a system call? */
+ if (regs->orig_d0 >= 0) {
+ /* Restart the system call - no handlers present */
+ if (regs->d0 == -ERESTARTNOHAND ||
+ regs->d0 == -ERESTARTSYS ||
+ regs->d0 == -ERESTARTNOINTR) {
+ regs->d0 = regs->orig_d0;
+ regs->pc -= 2;
+ }
}
- wrusp((unsigned long)frame);
- regs->ptregs.pc = pc;
- /*
- * if setup_frame saved some extra frame junk, we need to
- * skip over that stuff when doing the RTE. This means we have
- * to move the machine portion of the stack frame to where the
- * "RTE" instruction expects it. The signal that we need to
- * do this is that regs->stkadj is nonzero.
- */
- if (regs->ptregs.stkadj) {
- struct frame *tregs =
- (struct frame *)((ulong)regs + regs->ptregs.stkadj);
-#if DEBUG
- printk("Performing stackadjust=%04x\n", (unsigned)
- regs->ptregs.stkadj);
-#endif
+ /* If we are about to discard some frame stuff we must copy
+ over the remaining frame. */
+ if (regs->stkadj) {
+ struct pt_regs *tregs =
+ (struct pt_regs *) ((ulong) regs + regs->stkadj);
+
/* This must be copied with decreasing addresses to
- handle overlaps. */
- tregs->ptregs.vector = regs->ptregs.vector;
- tregs->ptregs.format = regs->ptregs.format;
- tregs->ptregs.pc = regs->ptregs.pc;
- tregs->ptregs.sr = regs->ptregs.sr;
+ handle overlaps. */
+ tregs->vector = regs->vector;
+ tregs->format = regs->format;
+ tregs->pc = regs->pc;
+ tregs->sr = regs->sr;
}
-
- return 1;
+ return 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov