patch-2.3.99-pre4 linux/arch/sh/kernel/signal.c
Next file: linux/arch/sh/lib/Makefile
Previous file: linux/arch/sh/kernel/ptrace.c
Back to the patch index
Back to the overall index
- Lines: 194
- Date:
Mon Mar 27 10:26:15 2000
- Orig file:
v2.3.99-pre3/linux/arch/sh/kernel/signal.c
- Orig date:
Tue Mar 7 14:32:25 2000
diff -u --recursive --new-file v2.3.99-pre3/linux/arch/sh/kernel/signal.c linux/arch/sh/kernel/signal.c
@@ -1,4 +1,4 @@
-/* $Id: signal.c,v 1.16 2000/01/29 11:31:31 gniibe Exp gniibe $
+/* $Id: signal.c,v 1.21 2000/03/11 14:06:21 gniibe Exp $
*
* linux/arch/sh/kernel/signal.c
*
@@ -6,7 +6,7 @@
*
* 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
*
- * SuperH version: Copyright (C) 1999 Niibe Yutaka
+ * SuperH version: Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima
*
*/
@@ -125,7 +125,7 @@
unsigned long r6, unsigned long r7,
struct pt_regs regs)
{
- return do_sigaltstack(uss, uoss, regs.sp);
+ return do_sigaltstack(uss, uoss, regs.regs[15]);
}
@@ -136,7 +136,6 @@
struct sigframe
{
struct sigcontext sc;
- /* FPU data should come here: SH-3 has no FPU */
unsigned long extramask[_NSIG_WORDS-1];
char retcode[4];
};
@@ -147,10 +146,38 @@
void *puc;
struct siginfo info;
struct ucontext uc;
- /* FPU should come here: SH-3 has no FPU */
char retcode[4];
};
+#if defined(__SH4__)
+static inline int restore_sigcontext_fpu(struct sigcontext *sc)
+{
+ current->used_math = 1;
+ return __copy_from_user(&tsk->thread.fpu.hard, &sc->sc_fpregs[0],
+ sizeof(long)*(NUM_FPU_REGS*2+2));
+}
+
+static inline int save_sigcontext_fpu(struct sigcontext *sc)
+{
+ struct task_struct *tsk = current;
+
+ if (!tsk->used_math) {
+ sc->owend_fp = 0;
+ return 0;
+ }
+
+ sc->owend_fp = 1;
+
+ /* This will cause a "finit" to be triggered by the next
+ attempted FPU operation by the 'current' process.
+ */
+ tsk->used_math = 0;
+
+ unlazy_fpu(tsk);
+ return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.fpu.hard,
+ sizeof(long)*(NUM_FPU_REGS*2+2));
+}
+#endif
static int
restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *r0_p)
@@ -165,15 +192,28 @@
COPY(regs[8]); COPY(regs[9]);
COPY(regs[10]); COPY(regs[11]);
COPY(regs[12]); COPY(regs[13]);
- COPY(regs[14]); COPY(sp);
+ COPY(regs[14]); COPY(regs[15]);
COPY(gbr); COPY(mach);
COPY(macl); COPY(pr);
COPY(sr); COPY(pc);
#undef COPY
+#if defined(__SH4__)
+ {
+ int owned_fp;
+ struct task_struct *tsk = current;
+
+ regs->sr |= SR_FD; /* Release FPU */
+ clear_fpu(tsk);
+ current->used_math = 0;
+ __get_user (owned_fp, &context->sc_ownedfp);
+ if (owned_fp)
+ err |= restore_sigcontext_fpu(sc);
+ }
+#endif
+
regs->syscall_nr = -1; /* disable syscall checks */
err |= __get_user(*r0_p, &sc->sc_regs[0]);
-
return err;
}
@@ -181,7 +221,7 @@
unsigned long r6, unsigned long r7,
struct pt_regs regs)
{
- struct sigframe *frame = (struct sigframe *)regs.sp;
+ struct sigframe *frame = (struct sigframe *)regs.regs[15];
sigset_t set;
int r0;
@@ -214,7 +254,7 @@
unsigned long r6, unsigned long r7,
struct pt_regs regs)
{
- struct rt_sigframe *frame = (struct rt_sigframe *)regs.sp;
+ struct rt_sigframe *frame = (struct rt_sigframe *)regs.regs[15];
sigset_t set;
stack_t st;
int r0;
@@ -238,7 +278,7 @@
goto badframe;
/* It is more difficult to avoid calling this function than to
call it and ignore errors. */
- do_sigaltstack(&st, NULL, regs.sp);
+ do_sigaltstack(&st, NULL, regs.regs[15]);
return r0;
@@ -265,12 +305,16 @@
COPY(regs[8]); COPY(regs[9]);
COPY(regs[10]); COPY(regs[11]);
COPY(regs[12]); COPY(regs[13]);
- COPY(regs[14]); COPY(sp);
+ COPY(regs[14]); COPY(regs[15]);
COPY(gbr); COPY(mach);
COPY(macl); COPY(pr);
COPY(sr); COPY(pc);
#undef COPY
+#if defined(__SH4__)
+ err |= save_sigcontext_fpu(sc);
+#endif
+
/* non-iBCS2 extensions.. */
err |= __put_user(mask, &sc->oldmask);
@@ -296,7 +340,7 @@
int err = 0;
int signal;
- frame = get_sigframe(ka, regs->sp, sizeof(*frame));
+ frame = get_sigframe(ka, regs->regs[15], sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
@@ -334,7 +378,7 @@
goto give_sigsegv;
/* Set up registers for signal handler */
- regs->sp = (unsigned long) frame;
+ regs->regs[15] = (unsigned long) frame;
regs->regs[4] = signal; /* Arg for signal handler */
regs->pc = (unsigned long) ka->sa.sa_handler;
@@ -361,7 +405,7 @@
int err = 0;
int signal;
- frame = get_sigframe(ka, regs->sp, sizeof(*frame));
+ frame = get_sigframe(ka, regs->regs[15], sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
@@ -381,7 +425,8 @@
err |= __put_user(0, &frame->uc.uc_link);
err |= __put_user((void *)current->sas_ss_sp,
&frame->uc.uc_stack.ss_sp);
- err |= __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags);
+ err |= __put_user(sas_ss_flags(regs->regs[15]),
+ &frame->uc.uc_stack.ss_flags);
err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
err |= setup_sigcontext(&frame->uc.uc_mcontext,
regs, set->sig[0]);
@@ -407,7 +452,7 @@
goto give_sigsegv;
/* Set up registers for signal handler */
- regs->sp = (unsigned long) frame;
+ regs->regs[15] = (unsigned long) frame;
regs->regs[4] = signal; /* Arg for signal handler */
regs->pc = (unsigned long) ka->sa.sa_handler;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)