OpenCores
no use no use 1/1 no use no use
openrisc stack management
by jamesedgar on Sep 6, 2011
jamesedgar
Posts: 9
Joined: Sep 14, 2004
Last seen: Jun 26, 2020
I've got a version of telnet running on OpenRISC on a spartan 3 board. I have been seeing intermittent errors, and I discovered that the problem occurs when either the stack prologue or epilogue is interrupted. What occurs is (epilogue example) the stack pointer is changed in anticipation of recovering the return address, then the interrupt occurs and overwrites the return address.

Example:

before interrupt

network_device_read:
EA =0000eadc PA =0000eadc r2 =00000000 00006bc4 l.sw -8(r1),r2
r2 =0000eae4 r1 =0000eae4 00006bc8 l.addi r2,r1,0x0

//return address put on stack
EA =0000eae0 PA =0000eae0 r9 =0000aef4 00006bcc l.sw -4(r1),r9

//stack pointer moved to include added variables
r1 =0000ead8 r1 =0000ead8 00006bd0 l.addi r1,r1,-12

r3 =00000000 00006bd4 l.movhi r3,0
r3 =0000e300 r3 =0000e300 00006bd8 l.ori r3,r3,0xe300
r3 =00000000 EA =0000e300 PA =0000e300 00006bdc l.lwz r3,0x0(r3)
r3 =00000000 00006be0 l.sfeqi r3,0x0
SR =00008607 00006be4 l.bf 0x9
00006be8 l.nop 0
r3 =00000000 00006c08 l.addi r3,r0,0x0
r11=00000000 r3 =00000000 00006c0c l.ori r11,r3,0

//r1 moves back below return address in anticipation of reading return address
r1 =0000eae4 r2 =0000eae4 00006c10 l.ori r1,r2,0

Now the interrupt occurs. The stack pointer has already been moved below the return addresss

Finally, after the interrupt:

r31=00000000 EA =0000eae0 PA =0000eae0 0000100c l.lwz r31,0x70(r1)
r1 =0000eae4 r1 =0000eae4 00001010 l.addi r1,r1,0x74
00001014 l.rfe

//we're back, but now we need to recover return address from stack
r2 =00000000 EA =0000eadc PA =0000eadc 00006c14 l.lwz r2,-8(r1)

// return address is wrong since it was overwritten during the interrupt
r9 =00000000 EA =0000eae0 PA =0000eae0 00006c18 l.lwz r9,-4(r1)
r9 =00000000 00006c1c l.jr r9
00006c20 l.nop 0
00000000 l.j 0x0

The network device read function is only called from the main function. The code above was generated using gcc version 4.5.1-or32-1.0rc1 (OpenRISC 32-bit toolchain for or32-elf (built 20110213)) I know there is an option to use context switching which could solve the problem, but it is not clear how it would be possible to safely use interrupts without atomic pop and push instructions if context switching is not used.

Any suggestions?

Thanks,

Jamie
RE: openrisc stack management
by julius on Sep 6, 2011
julius
Posts: 363
Joined: Jul 1, 2008
Last seen: May 17, 2021
What exception handler code are you using?

It should step over the area known as the red zone, which is a certain amount of area underneath the stack pointer (up to 256 bytes I think) that can be used. If this area is avoided by the exception handler then all should be OK.

At least, I think this is the problem.

A quick test would be to compile all of your C code with the -mno-red-zone option.
RE: openrisc stack management
by jamesedgar on Sep 7, 2011
jamesedgar
Posts: 9
Joined: Sep 14, 2004
Last seen: Jun 26, 2020
Julius --

That was the solution. I had an older version of except.S that did not include any red zone space. Thanks for the info.

Jamie
no use no use 1/1 no use no use
© copyright 1999-2026 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.