[prev in list] [next in list] [prev in thread] [next in thread] 

List:       uclinux-dev
Subject:    [uClinux-dev] patch: coldfire stack alignment
From:       Stuart Hughes <stuarth () freescale ! com>
Date:       2005-11-25 10:01:47
Message-ID: 4386E10B.50909 () freescale ! com
[Download RAW message or body]

Hi everyone,

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.

Regards, Stuart


["kernel-2.6.12-uc-stack-alignment.patch" (text/plain)]

diff --exclude CVS -uNr linux-2.6.x/arch/m68knommu/kernel/signal.c \
                linux-2.6.x.modified/arch/m68knommu/kernel/signal.c
--- linux-2.6.x/arch/m68knommu/kernel/signal.c	Tue Jul  5 01:11:49 2005
+++ linux-2.6.x.modified/arch/m68knommu/kernel/signal.c	Thu Nov 24 16:50:09 2005
@@ -285,6 +285,7 @@
 	regs->d1 = context.sc_d1;
 	regs->a0 = context.sc_a0;
 	regs->a1 = context.sc_a1;
+	((struct switch_stack *)regs - 1)->a5 = context.sc_a5;
 	regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
 	regs->pc = context.sc_pc;
 	regs->orig_d0 = -1;		/* disable syscall checks */
@@ -498,6 +499,7 @@
 	sc->sc_d1 = regs->d1;
 	sc->sc_a0 = regs->a0;
 	sc->sc_a1 = regs->a1;
+	sc->sc_a5 = ((struct switch_stack *)regs - 1)->a5;
 	sc->sc_sr = regs->sr;
 	sc->sc_pc = regs->pc;
 	sc->sc_formatvec = regs->format << 12 | regs->vector;
@@ -597,6 +599,9 @@
 	/* Set up registers for signal handler */
 	wrusp ((unsigned long) frame);
 	regs->pc = (unsigned long) ka->sa.sa_handler;
+	((struct switch_stack *)regs - 1)->a5 = current->mm->start_data;
+	regs->format = 0x4; /*set format byte to make stack appear modulo 4 
+						which it will be when doing the rte */
 
 adjust_stack:
 	/* Prepare to skip over the extra stuff in the exception frame.  */
@@ -664,6 +669,9 @@
 	/* Set up registers for signal handler */
 	wrusp ((unsigned long) frame);
 	regs->pc = (unsigned long) ka->sa.sa_handler;
+	((struct switch_stack *)regs - 1)->a5 = current->mm->start_data;
+	regs->format = 0x4; /*set format byte to make stack appear modulo 4 
+						which it will be when doing the rte */
 
 adjust_stack:
 	/* Prepare to skip over the extra stuff in the exception frame.  */
diff --exclude CVS -uNr linux-2.6.x/include/asm-m68knommu/sigcontext.h \
                linux-2.6.x.modified/include/asm-m68knommu/sigcontext.h
--- linux-2.6.x/include/asm-m68knommu/sigcontext.h	Sat Mar  2 15:01:11 2002
+++ linux-2.6.x.modified/include/asm-m68knommu/sigcontext.h	Thu Nov 24 16:43:03 2005
@@ -8,6 +8,7 @@
 	unsigned long  sc_d1;
 	unsigned long  sc_a0;
 	unsigned long  sc_a1;
+	unsigned long  sc_a5;
 	unsigned short sc_sr;
 	unsigned long  sc_pc;
 	unsigned short sc_formatvec;



_______________________________________________
uClinux-dev mailing list
uClinux-dev@uclinux.org
http://mailman.uclinux.org/mailman/listinfo/uclinux-dev
This message was resent by uclinux-dev@uclinux.org

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic