aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68knommu/kernel
diff options
context:
space:
mode:
authorGreg Ungerer <gerg@snapgear.com>2006-01-10 01:42:59 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-10 12:31:26 -0500
commit01829e7212dd9ba3fa68bf8afffc9a175c44cb04 (patch)
treeb8d6169303950a6b5e5049c3cde35433b25640e0 /arch/m68knommu/kernel
parentafc7cd8950572786c87ad081d8e65e5ea58b563c (diff)
[PATCH] m68knommu: fix a5 reg corruption in signal handlers
This is a patch adapted from a posting by Andrea Tarani which was pointed out to me by Bernardo Innocenti. Thanks to both of them for their help and patience. The original posting is here: http://mailman.uclinux.org/pipermail/uclinux-dev/2005-July/033543.html The problem first manifest itself as busybox ping terminating with an "Illegal instruction". I reduced this to a test case and found that variable size arrays allocated on the stack could lead to stacks not aligned on 32 bit boundaries. For the Coldfire this proved fatal. Having been pointed out this patch by Bernardo, I applied it and it fixed the first test case. I then went back to busybox's ping. This still failed with "Illegal instruction", but in a different way. Before it depended on the size allocated for the ping buffer, now it happened every time. I also found it depended on optimisation level (gcc-3.4.0) -Os was okay but not -O2. After a lot of looking, it turned out that register a5 was being corrupted by the signal handler (after applying the patch). I re-worked the patch a bit to save/restore a5 and now all seems well. Patch submitted by Stuart Hughs <stuarth@freescale.com> Signed-off-by: Greg Ungerer <gerg@uclinux.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/m68knommu/kernel')
-rw-r--r--arch/m68knommu/kernel/signal.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c
index 43a2726c0d0a..e1b3aa39e270 100644
--- a/arch/m68knommu/kernel/signal.c
+++ b/arch/m68knommu/kernel/signal.c
@@ -285,6 +285,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp,
285 regs->d1 = context.sc_d1; 285 regs->d1 = context.sc_d1;
286 regs->a0 = context.sc_a0; 286 regs->a0 = context.sc_a0;
287 regs->a1 = context.sc_a1; 287 regs->a1 = context.sc_a1;
288 ((struct switch_stack *)regs - 1)->a5 = context.sc_a5;
288 regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff); 289 regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
289 regs->pc = context.sc_pc; 290 regs->pc = context.sc_pc;
290 regs->orig_d0 = -1; /* disable syscall checks */ 291 regs->orig_d0 = -1; /* disable syscall checks */
@@ -498,6 +499,7 @@ static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
498 sc->sc_d1 = regs->d1; 499 sc->sc_d1 = regs->d1;
499 sc->sc_a0 = regs->a0; 500 sc->sc_a0 = regs->a0;
500 sc->sc_a1 = regs->a1; 501 sc->sc_a1 = regs->a1;
502 sc->sc_a5 = ((struct switch_stack *)regs - 1)->a5;
501 sc->sc_sr = regs->sr; 503 sc->sc_sr = regs->sr;
502 sc->sc_pc = regs->pc; 504 sc->sc_pc = regs->pc;
503 sc->sc_formatvec = regs->format << 12 | regs->vector; 505 sc->sc_formatvec = regs->format << 12 | regs->vector;
@@ -597,6 +599,9 @@ static void setup_frame (int sig, struct k_sigaction *ka,
597 /* Set up registers for signal handler */ 599 /* Set up registers for signal handler */
598 wrusp ((unsigned long) frame); 600 wrusp ((unsigned long) frame);
599 regs->pc = (unsigned long) ka->sa.sa_handler; 601 regs->pc = (unsigned long) ka->sa.sa_handler;
602 ((struct switch_stack *)regs - 1)->a5 = current->mm->start_data;
603 regs->format = 0x4; /*set format byte to make stack appear modulo 4
604 which it will be when doing the rte */
600 605
601adjust_stack: 606adjust_stack:
602 /* Prepare to skip over the extra stuff in the exception frame. */ 607 /* Prepare to skip over the extra stuff in the exception frame. */
@@ -664,6 +669,9 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
664 /* Set up registers for signal handler */ 669 /* Set up registers for signal handler */
665 wrusp ((unsigned long) frame); 670 wrusp ((unsigned long) frame);
666 regs->pc = (unsigned long) ka->sa.sa_handler; 671 regs->pc = (unsigned long) ka->sa.sa_handler;
672 ((struct switch_stack *)regs - 1)->a5 = current->mm->start_data;
673 regs->format = 0x4; /*set format byte to make stack appear modulo 4
674 which it will be when doing the rte */
667 675
668adjust_stack: 676adjust_stack:
669 /* Prepare to skip over the extra stuff in the exception frame. */ 677 /* Prepare to skip over the extra stuff in the exception frame. */