[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-libc-dev] [bug #29774] prologue/epilogue stack pointer manipula
From: |
Galen Seitz |
Subject: |
Re: [avr-libc-dev] [bug #29774] prologue/epilogue stack pointer manipulation not interrupt safe in XMega |
Date: |
Wed, 05 May 2010 09:08:47 -0700 |
User-agent: |
Thunderbird 2.0.0.24 (X11/20100318) |
Matthew Vernon wrote:
...
The actual code from the list file for my XMega project is shown below. Note
that 0x3F is the status register (including interrupt enable), and 0x3D with
0x3E are the stack pointer.
The status register is preserved, then interrupts are cleared. Half of the
stack is written, the status register is restored, then the other half of the
stack is written. On most architectures this is correct as one instruction can
safely execute after enabling interrupts (restore SREG) before an interrupt
can occur.
0001b082 <__epilogue_restores__>:
...
1b0aa: 0f b6 in r0, 0x3f ; 63
1b0ac: f8 94 cli
1b0ae: de bf out 0x3e, r29 ; 62
1b0b0: 0f be out 0x3f, r0 ; 63
1b0b2: cd bf out 0x3d, r28 ; 61
1b0b4: ed 01 movw r28, r26
1b0b6: 08 95 ret
The XMega, however, can jump to an interrupt immediately after the status
register is restored and before the second half of the stack is written.
Therefore any interrupt code that uses the stack will potentially write to an
arbitrary memory location. In my application this results in stack corruption
and a function return to an arbitrary address.
...
This certainly looks like a problem. What version of gcc are you
using, and what patches have been applied?
I have gcc 4.3.3 plus multiple patches, in particular
gcc-4.3.3-xmega-v13. My gcc should closely match winavr20100110.
I'm not sure I'm looking in the correct place, but avr.c in my gcc
build has the following code:
const char *
output_movhi (rtx insn, rtx operands[], int *l)
{
...
if(AVR_XMEGA)
{
*l = 2;
return (AS2 (out,__SP_L__,%A1) CR_TAB
AS2 (out,__SP_H__,%B1));
}
else
{
*l = 5;
return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
"cli" CR_TAB
AS2 (out,__SP_H__,%B1) CR_TAB
AS2 (out,__SREG__,__tmp_reg__) CR_TAB
AS2 (out,__SP_L__,%A1));
This suggests that xmega code should simply be restoring the stack
pointer. (Note that on the xmega, when SPL is written all interrupts
are disabled for up to four instructions or until SPH is also
written.) However, when I look at the disassembly of the
__prologue_saves__ and __epilogue_restores__ code for the xmega
libgcc.a libraries, I see the code for the non-AVR_XMEGA path. The
libgcc.a libraries from winavr20100110 are the same.
This is effectively the limit of my gcc debugging skills. It would be
interesting to hear from someone who is more familiar with avr-gcc.
--
Galen Seitz
address@hidden