kopia lustrzana https://github.com/espressif/esp-idf
Merge branch 'feature/c3_stack_watchpoint' into 'master'
c3 stack watchpoint Closes IDF-2307 See merge request espressif/esp-idf!11576pull/6416/head
commit
ca7cc79d6b
|
@ -99,14 +99,19 @@ menu "FreeRTOS"
|
|||
FreeRTOS can check if a stack has overflown its bounds by checking either the value of
|
||||
the stack pointer or by checking the integrity of canary bytes. (See FREERTOS_CHECK_STACKOVERFLOW
|
||||
for more information.) These checks only happen on a context switch, and the situation that caused
|
||||
the stack overflow may already be long gone by then. This option will use the debug memory
|
||||
watchpoint 1 (the second one) to allow breaking into the debugger (or panic'ing) as soon as any
|
||||
the stack overflow may already be long gone by then. This option will use the last debug memory
|
||||
watchpoint to allow breaking into the debugger (or panic'ing) as soon as any
|
||||
of the last 32 bytes on the stack of a task are overwritten. The side effect is that using gdb, you
|
||||
effectively only have one watchpoint; the 2nd one is overwritten as soon as a task switch happens.
|
||||
effectively have one hardware watchpoint less because the last one is overwritten as soon as a task
|
||||
switch happens.
|
||||
|
||||
This check only triggers if the stack overflow writes within 4 bytes of the end of the stack, rather than
|
||||
overshooting further, so it is worth combining this approach with one of the other stack overflow check
|
||||
methods.
|
||||
Another consequence is that due to alignment requirements of the watchpoint, the usable stack size
|
||||
decreases by up to 60 bytes. This is because the watchpoint region has to be aligned to its size and the
|
||||
size for the stack watchpoint in IDF is 32 bytes.
|
||||
|
||||
This check only triggers if the stack overflow writes within 32 bytes near the end of the stack, rather
|
||||
than overshooting further, so it is worth combining this approach with one of the other stack overflow
|
||||
check methods.
|
||||
|
||||
When this watchpoint is hit, gdb will stop with a SIGTRAP message. When no JTAG OCD is attached, esp-idf
|
||||
will panic on an unhandled debug exception.
|
||||
|
|
|
@ -94,6 +94,7 @@
|
|||
#include "esp_intr_alloc.h"
|
||||
#include "esp_private/crosscore_int.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_debug_helpers.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
/**
|
||||
|
@ -279,9 +280,12 @@ void vPortYield(void)
|
|||
|
||||
}
|
||||
|
||||
#define STACK_WATCH_AREA_SIZE 32
|
||||
void vPortSetStackWatchpoint(void *pxStackStart)
|
||||
{
|
||||
(void)pxStackStart; // TODO ESP32-C3 IDF-2207
|
||||
uint32_t addr = (uint32_t)pxStackStart;
|
||||
addr = (addr + (STACK_WATCH_AREA_SIZE - 1)) & (~(STACK_WATCH_AREA_SIZE - 1));
|
||||
esp_set_watchpoint(7, (char *)addr, STACK_WATCH_AREA_SIZE, ESP_WATCHPOINT_STORE);
|
||||
}
|
||||
|
||||
BaseType_t xPortInIsrContext(void)
|
||||
|
|
|
@ -107,14 +107,15 @@ static inline void cpu_ll_set_watchpoint(int id,
|
|||
{
|
||||
uint32_t addr_napot;
|
||||
RV_WRITE_CSR(tselect,id);
|
||||
RV_SET_CSR(CSR_TCONTROL,TCONTROL_MTE);
|
||||
RV_SET_CSR(CSR_TCONTROL, TCONTROL_MPTE | TCONTROL_MTE);
|
||||
RV_SET_CSR(CSR_TDATA1, TDATA1_USER|TDATA1_MACHINE);
|
||||
RV_SET_CSR_FIELD(CSR_TDATA1, TDATA1_MATCH, 1);
|
||||
addr_napot = ((uint32_t)addr)|((size>>1)-1);
|
||||
if(on_read) {
|
||||
// add 0 in napot encoding
|
||||
addr_napot = ((uint32_t) addr) | ((size >> 1) - 1);
|
||||
if (on_read) {
|
||||
RV_SET_CSR(CSR_TDATA1, TDATA1_LOAD);
|
||||
}
|
||||
if(on_write) {
|
||||
if (on_write) {
|
||||
RV_SET_CSR(CSR_TDATA1, TDATA1_STORE);
|
||||
}
|
||||
RV_WRITE_CSR(tdata2,addr_napot);
|
||||
|
|
|
@ -90,13 +90,14 @@ extern "C" {
|
|||
#define CSR_TDATA1 0x7a1
|
||||
|
||||
#define TCONTROL_MTE (1<<3) /*R/W, Current M mode trigger enable bit*/
|
||||
#define TCONTROL_MPTE (1<<7) /*R/W, Previous M mode trigger enable bit*/
|
||||
|
||||
#define TDATA1_LOAD (1<<0) /*R/W,Fire trigger on load address match*/
|
||||
#define TDATA1_STORE (1<<1) /*R/W,Fire trigger on store address mat*/
|
||||
#define TDATA1_EXECUTE (1<<2) /*R/W,Fire trigger on instruction fetch address match*/
|
||||
#define TDATA1_USER (1<<3) /*R/W,allow trigger to be fired in user mode*/
|
||||
#define TDATA1_MACHINE (1<<6) /*R/W,Allow trigger to be fired while hart is executing in machine mode*/
|
||||
#define TDATA1_MATCH
|
||||
#define TDATA1_MATCH (1<<7)
|
||||
#define TDATA1_MATCH_V (0xF) /*R/W,Address match type :0 : Exact byte match 1 : NAPOT range match */
|
||||
#define TDATA1_MATCH_S (7)
|
||||
|
||||
|
|
|
@ -100,19 +100,39 @@ static void IRAM_ATTR test_int_wdt_cache_disabled(void)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function overwrites the stack beginning from the valid area continuously towards and beyond
|
||||
* the end of the stack (stack base) of the current task.
|
||||
* This is to test stack protection measures like a watchpoint at the end of the stack.
|
||||
*
|
||||
* @note: This test DOES NOT write beyond the stack limit. It only writes up to exactly the limit itself.
|
||||
* The FreeRTOS stack protection mechanisms all trigger shortly before the end of the stack.
|
||||
*/
|
||||
static void test_stack_overflow(void)
|
||||
{
|
||||
register uint32_t* sp asm("sp");
|
||||
uint32_t *end = sp - CONFIG_ESP_MAIN_TASK_STACK_SIZE;
|
||||
TaskStatus_t pxTaskStatus;
|
||||
vTaskGetInfo(NULL, &pxTaskStatus, pdFALSE, pdFALSE);
|
||||
uint32_t *end = (uint32_t*) pxTaskStatus.pxStackBase;
|
||||
|
||||
// offset - 20 bytes from SP in order to not corrupt the current frame.
|
||||
// Need to write from higher to lower addresses since the stack grows downwards and the watchpoint/canary is near
|
||||
// the end of the stack (lowest address).
|
||||
for (uint32_t* ptr = sp - 5; ptr != end; --ptr) {
|
||||
*ptr = rand();
|
||||
*ptr = 0;
|
||||
}
|
||||
|
||||
// trigger a context switch to initiate checking the FreeRTOS stack canary
|
||||
vTaskDelay(pdMS_TO_TICKS(0));
|
||||
}
|
||||
|
||||
static void test_illegal_instruction(void)
|
||||
{
|
||||
#if __XTENSA__
|
||||
__asm__ __volatile__("ill");
|
||||
#elif __riscv
|
||||
__asm__ __volatile__("unimp");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_instr_fetch_prohibited(void)
|
||||
|
|
|
@ -10,3 +10,6 @@ CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y
|
|||
|
||||
# To panic on task WDT
|
||||
CONFIG_ESP_TASK_WDT_PANIC=y
|
||||
|
||||
# For vTaskGetInfo() used in test_stack_overflow()
|
||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||
|
|
Ładowanie…
Reference in New Issue