Author Topic: Cortex-M hardware stack overflow detection  (Read 2270 times)

0 Members and 1 Guest are viewing this topic.

Offline bsonTopic starter

  • Supporter
  • ****
  • Posts: 2289
  • Country: us
Cortex-M hardware stack overflow detection
« on: May 13, 2024, 01:02:02 am »
I think it should be possible to use debug watchpoints to implement hardware stack overflow detection:
  • Set DHCSR.C_DEBUGEN=0 to prevent debug halting
  • Set DEMCR.MON_EN=1 to enable the DebugMonitor exception
  • Make sure there's an exception handler to properly panic and restart (or whatever action is desired)
  • Set a DWT mask and address to match a block past the stack
  • If alloca() exists, make sure it detects attempts to allocate past the end of the stack (this unrelated, but without it obviously alloca() could be used to step over the entire watchpoint block)
Has anyone experimented with this?  Does it work?  It would be nice because it requires only trivial setup, has no runtime overhead, and doesn't require code instrumentation.

Of course, it could also be made to halt instead of going into the exception handler if a debugger is attached - the debugger can then be used to check exactly what code is overflowing the stack.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11359
  • Country: us
    • Personal site
Re: Cortex-M hardware stack overflow detection
« Reply #1 on: May 13, 2024, 01:59:06 am »
This will have limited utility. The DWT address match can match on a word at most. So, it would detect direct writes just past the stack. But in real life those overflows rarely happen like that, most of the time you write way past.

Plus this would interfere with debuggers that often want full control over the debug registers.
Alex
 

Offline bsonTopic starter

  • Supporter
  • ****
  • Posts: 2289
  • Country: us
Re: Cortex-M hardware stack overflow detection
« Reply #2 on: May 13, 2024, 02:24:41 am »
Hmm, I thought it could mask the address... but maybe the mask is for data?
 

Offline bsonTopic starter

  • Supporter
  • ****
  • Posts: 2289
  • Country: us
Re: Cortex-M hardware stack overflow detection
« Reply #3 on: May 13, 2024, 02:29:03 am »
From https://developer.arm.com/documentation/ddi0403/d/Debug-Architecture/ARMv7-M-Debug/The-Data-Watchpoint-and-Trace-unit/The-DWT-comparators?lang=en

"For address matching, the comparator can use a mask, so it matches a range of addresses."

In fact, the mask is only used for address matching; for cycle or data matching it should be zero...
« Last Edit: May 13, 2024, 02:32:17 am by bson »
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11359
  • Country: us
    • Personal site
Re: Cortex-M hardware stack overflow detection
« Reply #4 on: May 13, 2024, 02:33:23 am »
You are still limited to blocks aligned at a block size. And you can only match on the unused area between the legitimate variables and the stack end. And this is pointless, you might as well extend the stack to that empty area.

If you configure the stack to start at the end of SRAM, then the free stack space is all the RAM that is not used by the variables. The only detection you can do here is a match right at the end of the stack.

Plus I would double check how big that mask is in real implementations. ARM documentation is very generic .
« Last Edit: May 13, 2024, 02:35:28 am by ataradov »
Alex
 

Offline bsonTopic starter

  • Supporter
  • ****
  • Posts: 2289
  • Country: us
Re: Cortex-M hardware stack overflow detection
« Reply #5 on: May 13, 2024, 03:14:28 am »
Yeah, I understand there is a tradeoff between the size of the guard block and reliability.  However, e.g. a 256-byte block might be worth it and sufficiently useful, especially if you suspect the possibility of stack overflows.  Functions that need more stack than that, without using alloca(), are pretty rare and can be instrumented to check or modified to use alloca() which is then instrumented to check.  This would also catch e.g. nested interrupt stack usage.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11359
  • Country: us
    • Personal site
Re: Cortex-M hardware stack overflow detection
« Reply #6 on: May 13, 2024, 03:44:36 am »
I just checked and it looks like Cortex-M7 DWT implements all 5 bits of the mask register, so it should be possible to reserve a 256 byte gap for this check. It is better than nothing, of course. But I'm still not convinced it is going to be a significant measure.
Alex
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14634
  • Country: fr
Re: Cortex-M hardware stack overflow detection
« Reply #7 on: May 13, 2024, 04:03:28 am »
It should work for "basic" stack overflows (stack *growing* past its limit), but would not catch all out-of-bounds writes of objects that are supposed to be on the stack.
So, it would still cover one potential issue, having not sized the stack properly. And out-of-bounds writes of stack arrays by a few items.
 

Online ejeffrey

  • Super Contributor
  • ***
  • Posts: 3762
  • Country: us
Re: Cortex-M hardware stack overflow detection
« Reply #8 on: May 13, 2024, 06:14:49 am »
Since the stack grows down, overflowing automatic arrays will overwrite previous stack frames and not trigger this type of detection.  Array underflows are a lot less common.

It really just protects you from infinite recursion or putting huge arrays on the stack.
 

Offline wek

  • Frequent Contributor
  • **
  • Posts: 498
  • Country: sk
Re: Cortex-M hardware stack overflow detection
« Reply #9 on: May 13, 2024, 10:43:55 am »
I'd probably employ the MPU for this task (where available of course). I'd very much like to retain debugging facilities for... well... debugging...

And what if memory utilization is such that stack almost meets data?

JW
 

Offline radiolistener

  • Super Contributor
  • ***
  • Posts: 3479
  • Country: ua
Re: Cortex-M hardware stack overflow detection
« Reply #10 on: May 13, 2024, 10:50:52 am »
You can fill the stack memory with 0xff (you can do it on init) and then check the memory state with debugger after test running. You can see how much stack was used for each your thread and in case of needs you can increase stack for the thread which has too small margin till the end.

When you see that the stack for some thread don't have 0xff at the end, that's an indication that the stack overflow happens and something bad happens.

In that way you can check which thread is okay and which one eats too many stack and is too close to stack border.
« Last Edit: May 13, 2024, 10:54:37 am by radiolistener »
 

Online eutectique

  • Frequent Contributor
  • **
  • Posts: 412
  • Country: be
Re: Cortex-M hardware stack overflow detection
« Reply #11 on: May 13, 2024, 10:55:06 am »
In systems without RTOS, I usually place the stack in the beginning of RAM. If stack grows out of proportions and overflows into non-existent address space, the Data Abort handler will catch it. The handler then saves the necessary registers into no-init RAM, and reboots. The bootloader (if any) or the firmware then checks the no-init RAM and reports the crash via CAN, BLE, or whatever means of communication are available.
 
The following users thanked this post: xvr

Offline peter-h

  • Super Contributor
  • ***
  • Posts: 3743
  • Country: gb
  • Doing electronics since the 1960s...
Re: Cortex-M hardware stack overflow detection
« Reply #12 on: May 13, 2024, 12:33:34 pm »
I was just going to post exactly that :)

It will pick up overflow of the "general stack" - the one used for interrupts, which uses the SP which is loaded at startup. The RTOS then configures things so it uses its own task stacks, one for each task, when it switches tasks. Interrupts still run on the general stack - there are two SPs. Gosh it's a while since I looked into this...

So this way you could do stack overflow due to ISRs, and stack overflow before the RTOS starts up.

For overflow of task stacks, FreeRTOS can do that optionally, but in software. RTOS task stack management is actually a much bigger problem; I fill the RTOS space with "s" or some such and have a GUI tool for displaying it. Not ideal really.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Online jnk0le

  • Regular Contributor
  • *
  • Posts: 52
  • Country: pl
Re: Cortex-M hardware stack overflow detection
« Reply #13 on: May 13, 2024, 02:00:43 pm »
In addition, armv8m has a hardware stack limits.
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4087
  • Country: nz
Re: Cortex-M hardware stack overflow detection
« Reply #14 on: May 14, 2024, 04:23:37 am »
Does Cortex M not have an equivalent to RISC-V's "PMP" (Physical Memory Protection) unit? Pretty much anything with M and U modes will have at least 8 PMP regions. If U mode code accesses outside them then it traps. M mode software can save/restore the PMP settings on thread switch, so every thread can be protected from the others.

Combine this with the "stack is at the lowest addresses and grows down, heap is at the upper addresses and grows up" idea and you only need 1 PMP region per thread (at least for data).
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11359
  • Country: us
    • Personal site
Re: Cortex-M hardware stack overflow detection
« Reply #15 on: May 14, 2024, 04:54:00 am »
The original post discussed the most basic scenario where there is just Data+BSS at the beginning of SRAM (fixed) and stack at the end of SRAM (grows down).

Placing the Data+BSS at the end of SRAM and the stack at the beginning is a great idea. I don't see any downsides doing that.

RTOS and protection of individual tasks is entirely different story. You can use MPU for that, but it is still limited with the region sizes and alignment requirements.  It is more headache than it is worth.

Alex
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14634
  • Country: fr
Re: Cortex-M hardware stack overflow detection
« Reply #16 on: May 14, 2024, 05:02:03 am »
I agree with Bruce though, memory protection is increasingly available on even entry-level MCUs and can definitely be put to good use, *even* if you don't write fancy "multi-thread" stuff wtih an RTOS.
That's something many of us are not used to yet on MCUs, but I'm definitely getting into that.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11359
  • Country: us
    • Personal site
Re: Cortex-M hardware stack overflow detection
« Reply #17 on: May 14, 2024, 05:09:48 am »
But the issue here is that there is no way to distinguish stack overflow from a legitimate memory access.
Alex
 

Offline Berni

  • Super Contributor
  • ***
  • Posts: 4995
  • Country: si
Re: Cortex-M hardware stack overflow detection
« Reply #18 on: May 14, 2024, 05:29:37 am »
Most of the bigger ARM Cortex chips have a MPU in them and that will provide more effective memory protection.

Tho the MPU is rarely used since people don't bother to set it up (Unless you have a RTOS that does it for you) and its effectiveness does depend on how your memory is structured. Just stick to good coding practices (like checking array sizes) and if you want to be safe run some static code analysis tools over your source code. These will catch more memory related bugs since a lot of the time the code will garble the existing data in RAM that it should have access to anyway (so the MPU will not detect it)

I suppose the most common bug that would eat up the whole stack would be a infinite recursion loop. But that will likely run off the end of the RAM area and then hardfault with a bus exception.

I personally only ever used the MPU to disable caching on some areas used for DMA buffers so that i didn't have to constantly be doing the cache flushing dance around those areas.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14634
  • Country: fr
Re: Cortex-M hardware stack overflow detection
« Reply #19 on: May 14, 2024, 05:45:31 am »
But the issue here is that there is no way to distinguish stack overflow from a legitimate memory access.

One approach is to set up 2 small memory regions with the MPU, one right before the stack, and one right after, both as 'read-only'.
This will waste some RAM, but if you place the stack either at the beginning of the RAM, or at the end, you'll waste only 1 small block of RAM, and not 2. The other region will be outside of RAM.

Of course, it won't catch write attempts of items supposedly on the stack, but so out-of-bounds that write accesses would lie outside of the protected regions without passing through them, but the most common cases (purely stack overflows and out-of-bounds accesses due to off-by-one errors) will be caught this way, because the CPU will inevitably attempt to write just past the stack in either direction, and fall into one of the protected regions. Not 100% failsafe of course (but that would require much more sophisticated approaches anyway), but still a nice addition for very little cost.
 
The following users thanked this post: tellurium

Offline peter-h

  • Super Contributor
  • ***
  • Posts: 3743
  • Country: gb
  • Doing electronics since the 1960s...
Re: Cortex-M hardware stack overflow detection
« Reply #20 on: May 14, 2024, 09:14:35 am »
How about this for another idea...

If you have overrun the stack, an ISR will still execute (provided there is physical RAM there, and if there isn't, it will still get entered provided that writing to nonexistent RAM doesn't trigger a trap) even if it is corrupting memory. It will also return OK but we aren't necessarily interested in that.

So how about checking the SP value at the start of any regular (e.g. 1kHz tick) ISR and if found below the stack, take some action e.g. somehow report it, and then reboot the CPU.

In an embedded system, if the stack has overflowed then you are already buggered, there is no meaningful error recovery anyway since RAM is already corrupted, and in most products there is no way to report the error anyway :)

FWIW I have found RTOS stacks to be a far bigger issue than the general stack which is not normally big and just services pre-RTOS-start code, and ISRs. I have 8k for it and only about 1k is ever used. RTOS stacks are a much harder issue because you have one per task and you have to somehow make sure each one is big enough. In most cases the only way is to run the product for a long time and see how far each (custom-prefilled) stack area has been overwritten.
« Last Edit: May 14, 2024, 10:51:17 am by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline S. Petrukhin

  • Super Contributor
  • ***
  • Posts: 1269
  • Country: ru
Re: Cortex-M hardware stack overflow detection
« Reply #21 on: May 14, 2024, 02:32:04 pm »
A little abstract...
It is convenient to use CCM for stack.
This will not save you from overflowing, but...
And sorry for my English.
 

Offline peter-h

  • Super Contributor
  • ***
  • Posts: 3743
  • Country: gb
  • Doing electronics since the 1960s...
Re: Cortex-M hardware stack overflow detection
« Reply #22 on: May 15, 2024, 06:40:11 am »
Indeed; the CCM is handy for this; also handy for the block of RAM for FreeRTOS (if 64k is enough for the RTOS task stacks which usually it is; in my box I have > 20 tasks and it all sits in the CCM) and handy for the RAM block for MbedTLS too. You just can't execute code from the CCM (in the 32F4) or put the vector table in there.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline bsonTopic starter

  • Supporter
  • ****
  • Posts: 2289
  • Country: us
Re: Cortex-M hardware stack overflow detection
« Reply #23 on: May 15, 2024, 10:03:21 pm »
You can fill the stack memory with 0xff (you can do it on init) and then check the memory state with debugger after test running. You can see how much stack was used for each your thread and in case of needs you can increase stack for the thread which has too small margin till the end.

When you see that the stack for some thread don't have 0xff at the end, that's an indication that the stack overflow happens and something bad happens.

In that way you can check which thread is okay and which one eats too many stack and is too close to stack border.
If you allocate all your dynamic memory on the thread stack, then a bug will easily cause a stack overflow.  Detecting it after the fact is trivial, as you outline.  Finding out when and where exactly it happens so you can track down the bug is the problem actually addressed here and is often NOT trivial.  An Debug exception on the first overflowing access is a very good start to tracking down such obscure bugs.  Because of the nature of stack allocation, when you overflow the stack frame chain contains the allocation history.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4219
  • Country: us
Re: Cortex-M hardware stack overflow detection
« Reply #24 on: May 16, 2024, 12:23:01 am »
Quote
Does Cortex M not have an equivalent to RISC-V's "PMP" (Physical Memory Protection) unit?
ARMv7m (M3, M4, and higher?) have a "Memory Protection Unit" (MPU) that supports the ARM "Protected Memory System Archiecture."On M0 and M0+ it's optional.No mapping or address translation - just "protection", so protecting a stack still means "wasting" at least 32 bytes of memory.
(The idea of putting the "bottom" of your stack at 0 is temping, but there tends to be other things that are also nice to put there.  (a relocated vector table has relatively nasty alignment requirements, for instance.))
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf