summaryrefslogtreecommitdiffstats
path: root/arch/m68k/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68k/kernel/signal.c')
-rw-r--r--arch/m68k/kernel/signal.c104
1 files changed, 56 insertions, 48 deletions
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index a2b9ce1d4..f35dd94c5 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -14,6 +14,10 @@
* 68060 fixes by Jesper Skov
*
* 1997-12-01 Modified for POSIX.1b signals by Andreas Schwab
+ *
+ * mathemu support by Roman Zippel
+ * (Note: fpstate in the signal context is completly ignored for the emulator
+ * and the internal floating point format is put on stack)
*/
/*
@@ -156,6 +160,9 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss)
/*
* Do a signal return; undo the signal stack.
+ *
+ * Keep the return code on the stack quadword aligned!
+ * That makes the cache flush below easier.
*/
struct sigframe
@@ -175,9 +182,9 @@ struct rt_sigframe
int sig;
struct siginfo *pinfo;
void *puc;
+ char retcode[8];
struct siginfo info;
struct ucontext uc;
- char retcode[8];
};
@@ -187,6 +194,13 @@ static inline int restore_fpu_state(struct sigcontext *sc)
{
int err = 1;
+ if (FPU_IS_EMU) {
+ /* restore registers */
+ memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
+ memcpy(current->thread.fp, sc->sc_fpregs, 24);
+ return 0;
+ }
+
if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
/* Verify the frame format. */
if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version))
@@ -239,6 +253,18 @@ static inline int rt_restore_fpu_state(struct ucontext *uc)
fpregset_t fpregs;
int err = 1;
+ if (FPU_IS_EMU) {
+ /* restore fpu control register */
+ if (__copy_from_user(current->thread.fpcntl,
+ &uc->uc_mcontext.fpregs.f_pcr, 12))
+ goto out;
+ /* restore all other fpu register */
+ if (__copy_from_user(current->thread.fp,
+ uc->uc_mcontext.fpregs.f_fpregs, 96))
+ goto out;
+ return 0;
+ }
+
if (__get_user(*(long *)fpstate, (long *)&uc->uc_fpstate))
goto out;
if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
@@ -478,7 +504,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 - 24);
+ struct sigframe *frame = (struct sigframe *)(usp - 4);
sigset_t set;
int d0;
@@ -536,6 +562,13 @@ badframe:
static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
{
+ if (FPU_IS_EMU) {
+ /* save registers */
+ memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12);
+ memcpy(sc->sc_fpregs, current->thread.fp, 24);
+ return;
+ }
+
__asm__ volatile (".chip 68k/68881\n\t"
"fsave %0\n\t"
".chip 68k"
@@ -567,6 +600,16 @@ static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs)
int context_size = CPU_IS_060 ? 8 : 0;
int err = 0;
+ if (FPU_IS_EMU) {
+ /* save fpu control register */
+ err |= copy_to_user(&uc->uc_mcontext.fpregs.f_pcr,
+ current->thread.fpcntl, 12);
+ /* save all other fpu register */
+ err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
+ current->thread.fp, 96);
+ return err;
+ }
+
__asm__ volatile (".chip 68k/68881\n\t"
"fsave %0\n\t"
".chip 68k"
@@ -677,25 +720,6 @@ static inline void push_cache (unsigned long vaddr)
"cpushl %%bc,(%0)\n\t"
".chip 68k"
: : "a" (temp));
- if (((vaddr + 8) ^ vaddr) & ~15) {
- if (((vaddr + 8) ^ vaddr) & PAGE_MASK)
- __asm__ __volatile__ (".chip 68040\n\t"
- "nop\n\t"
- "ptestr (%1)\n\t"
- "movec %%mmusr,%0\n\t"
- ".chip 68k"
- : "=r" (temp)
- : "a" (vaddr + 8));
-
- temp &= PAGE_MASK;
- temp |= (vaddr + 8) & ~PAGE_MASK;
-
- __asm__ __volatile__ (".chip 68040\n\t"
- "nop\n\t"
- "cpushl %%bc,(%0)\n\t"
- ".chip 68k"
- : : "a" (temp));
- }
}
else if (CPU_IS_060) {
unsigned long temp;
@@ -708,18 +732,6 @@ static inline void push_cache (unsigned long vaddr)
"cpushl %%bc,(%0)\n\t"
".chip 68k"
: : "a" (temp));
- if (((vaddr + 8) ^ vaddr) & ~15) {
- if (((vaddr + 8) ^ vaddr) & PAGE_MASK)
- __asm__ __volatile__ (".chip 68060\n\t"
- "plpar (%0)\n\t"
- ".chip 68k"
- : "=a" (temp)
- : "0" (vaddr + 8));
- __asm__ __volatile__ (".chip 68060\n\t"
- "cpushl %%bc,(%0)\n\t"
- ".chip 68k"
- : : "a" (temp));
- }
}
else {
/*
@@ -797,11 +809,9 @@ static void setup_frame (int sig, struct k_sigaction *ka,
/* Set up to return from userspace. */
err |= __put_user(frame->retcode, &frame->pretcode);
- /* addaw #20,sp */
- err |= __put_user(0xdefc0014, (long *)(frame->retcode + 0));
/* moveq #,d0; trap #0 */
err |= __put_user(0x70004e40 + (__NR_sigreturn << 16),
- (long *)(frame->retcode + 4));
+ (long *)(frame->retcode));
if (err)
goto give_sigsegv;
@@ -881,10 +891,10 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up to return from userspace. */
err |= __put_user(frame->retcode, &frame->pretcode);
- /* movel #,d0; trap #0 */
- err |= __put_user(0x203c, (short *)(frame->retcode + 0));
- err |= __put_user(__NR_rt_sigreturn, (long *)(frame->retcode + 2));
- err |= __put_user(0x4e40, (short *)(frame->retcode + 6));
+ /* moveq #,d0; notb d0; trap #0 */
+ err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16),
+ (long *)(frame->retcode + 0));
+ err |= __put_user(0x4e40, (short *)(frame->retcode + 4));
if (err)
goto give_sigsegv;
@@ -964,11 +974,10 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
- recalc_sigpending(current);
- }
+ recalc_sigpending(current);
}
/*
@@ -985,7 +994,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
siginfo_t info;
struct k_sigaction *ka;
- current->tss.esp0 = (unsigned long) regs;
+ current->thread.esp0 = (unsigned long) regs;
if (!oldset)
oldset = &current->blocked;
@@ -1084,14 +1093,13 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGIOT: case SIGFPE: case SIGSEGV:
- if (current->binfmt
- && current->binfmt->core_dump
- && current->binfmt->core_dump(signr, regs))
+ if (do_coredump(signr, regs))
exit_code |= 0x80;
/* FALLTHRU */
default:
sigaddset(&current->signal, signr);
+ recalc_sigpending(current);
current->flags |= PF_SIGNALED;
do_exit(exit_code);
/* NOTREACHED */