Skip to content

Commit 8a42163

Browse files
authored
Call umm_init just before starting SDK (#8207)
* Recover the BearSSL crash stack before the Heap is initialized and zeros it. * Added comments for hwdt_pre_sdk_init() * Keep Basic ASM version of app_entry_redefinable and removed alternate "C"/Extended ASM version. Update comments. * Improved example HwdtStackDump to use StackThunk
1 parent 69f8cd6 commit 8a42163

File tree

4 files changed

+65
-76
lines changed

4 files changed

+65
-76
lines changed

Diff for: cores/esp8266/core_esp8266_app_entry_noextra4k.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <c_types.h>
1010
#include "cont.h"
1111
#include "coredecls.h"
12+
#include <umm_malloc/umm_malloc.h>
1213

1314
void disable_extra4k_at_link_time (void)
1415
{
@@ -38,6 +39,7 @@ extern "C" void app_entry_redefinable(void)
3839
{
3940
g_pcont = &g_cont;
4041

42+
umm_init();
4143
/* Call the entry point of the SDK code. */
4244
call_user_start();
4345
}

Diff for: cores/esp8266/core_esp8266_main.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -318,14 +318,16 @@ extern "C" void app_entry_redefinable(void)
318318
cont_t s_cont __attribute__((aligned(16)));
319319
g_pcont = &s_cont;
320320

321+
/* Doing umm_init just once before starting the SDK, allowed us to remove
322+
test and init calls at each malloc API entry point, saving IRAM. */
323+
umm_init();
321324
/* Call the entry point of the SDK code. */
322325
call_user_start();
323326
}
324327
static void app_entry_custom (void) __attribute__((weakref("app_entry_redefinable")));
325328

326329
extern "C" void app_entry (void)
327330
{
328-
umm_init();
329331
return app_entry_custom();
330332
}
331333

@@ -367,7 +369,7 @@ extern "C" void user_init(void) {
367369
#if defined(UMM_HEAP_EXTERNAL)
368370
install_vm_exception_handler();
369371
#endif
370-
372+
371373
#if defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP)
372374
install_non32xfer_exception_handler();
373375
#endif

Diff for: cores/esp8266/hwdt_app_entry.cpp

+37-73
Original file line numberDiff line numberDiff line change
@@ -1048,6 +1048,22 @@ static void printSanityCheck() {
10481048
}
10491049
#endif //DEBUG_ESP_HWDT_DEV_DEBUG
10501050

1051+
/*
1052+
hwdt_pre_sdk_init() is the result of a hook for development diagnotics which
1053+
evolved and was generlized to run any optional diagnostic code supplied at
1054+
link time.
1055+
1056+
Summary of the hwdt_pre_sdk_init() runtime environment:
1057+
* The code can run from flash and use PROGMEM strings.
1058+
* All functions must be extern "C" type
1059+
* C/C++ runtime has not started. Structures have not been initialized and
1060+
should have the values prior to reboot. With the exception of hwdt_info,
1061+
which was updated before this call.
1062+
* You can reference hwdt_info.reset_reason to control the action of the diagnostic.
1063+
* The stack is on the SYS stack. You have about 3K available before you
1064+
overwrite ROM Data area.
1065+
* Printing will work best with ets_uart_printf and umm_info_safe_printf_P.
1066+
*/
10511067
void hwdt_pre_sdk_init(void) __attribute__((weak));
10521068
void hwdt_pre_sdk_init(void) {
10531069
#if defined(DEBUG_ESP_HWDT_DEV_DEBUG) && !defined(USE_IRAM)
@@ -1072,14 +1088,12 @@ void hwdt_pre_sdk_init_icache(void) {
10721088
Cache_Read_Disable();
10731089
}
10741090

1075-
1076-
#if 1
10771091
/*
1078-
An asm function alternative to the function with inline asm at the #else. I
1079-
find the inline asm requires constant inspection to verify that the compiler
1080-
optimizer does not clobber needed registers, after small changes in code or
1081-
compiler updates. Hints to the compiler don't always work for me. Last I
1082-
checked, the inline version below was working.
1092+
For app_entry_redefinable, use Basic ASM instead of "C" with Extended ASM. The
1093+
(inline) Extended ASM approach required constant inspection to verify that the
1094+
compiler's optimizer did not clobber needed registers or do something weird
1095+
after minor changes in code or compiler updates. Also, I think Basic ASM is
1096+
the safer route when changing the stack pointer multiple times.
10831097
*/
10841098
cont_t *hwdt_app_entry__cont_stack __attribute__((used)) = CONT_STACK;
10851099

@@ -1089,6 +1103,7 @@ asm (
10891103
".literal .g_pcont, g_pcont\n\t"
10901104
".literal .pcont_stack, hwdt_app_entry__cont_stack\n\t"
10911105
".literal .sys_stack_first, sys_stack_first\n\t"
1106+
".literal .umm_init, umm_init\n\t"
10921107
".literal .call_user_start, call_user_start\n\t"
10931108
".literal .get_noextra4k_g_pcont, get_noextra4k_g_pcont\n\t"
10941109
".align 4\n\t"
@@ -1135,90 +1150,39 @@ asm (
11351150
"l32r a13, .pcont_stack\n\t"
11361151
"l32r a0, .get_noextra4k_g_pcont\n\t"
11371152
"l32r a14, .g_pcont\n\t"
1153+
// We now switch to the SYS stack the SDK will use
11381154
"l32i.n a1, a2, 0\n\t" // delayed load for pipeline
11391155
"l32i.n a13, a13, 0\n\t"
11401156
"callx0 a0\n\t"
11411157
"moveqz a2, a13, a2\n\t"
11421158
"s32i.n a2, a14, 0\n\t"
11431159

1160+
/*
1161+
* Allow for running additional diagnotics supplied at link time.
1162+
*/
11441163
"call0 hwdt_pre_sdk_init_icache\n\t"
11451164

1165+
// In case somebody cares, leave things as we found them
1166+
// - Restore ROM BSS zeros.
11461167
"movi a2, 0x3FFFE000\n\t" // ROM BSS Area
11471168
"movi a3, 0x0b30\n\t" // ROM BSS Size
11481169
"call0 ets_bzero\n\t"
11491170

1171+
/*
1172+
* Up until this call, the heap at crash time has been available for
1173+
* analysis. This is needed for dumping the bearssl stack. Also, future
1174+
* improvements could possibly use hwdt_pre_sdk_init() to run other early
1175+
* diagnostic tools.
1176+
*/
1177+
"l32r a0, .umm_init\n\t"
1178+
"callx0 a0\n\t"
1179+
11501180
"l32r a3, .call_user_start\n\t"
11511181
"movi a0, 0x4000044c\n\t"
11521182
"jx a3\n\t"
11531183
".size app_entry_redefinable, .-app_entry_redefinable\n\t"
11541184
);
11551185

1156-
#else
1157-
void IRAM_ATTR app_entry_start(void) {
1158-
1159-
#ifdef USE_IRAM
1160-
handle_hwdt();
1161-
#else
1162-
handle_hwdt_icache();
1163-
#endif
1164-
1165-
/*
1166-
* Continuation context is in BSS.
1167-
*/
1168-
g_pcont = get_noextra4k_g_pcont();
1169-
1170-
if (!g_pcont) {
1171-
/*
1172-
* The continuation context is on the stack just after the reserved
1173-
* space for the ROM/eboot stack and before the SYS stack begins. All
1174-
* computations were done at top, save pointer to it now.
1175-
*/
1176-
g_pcont = CONT_STACK;
1177-
}
1178-
#if defined(DEBUG_ESP_HWDT_DEV_DEBUG) && !defined(USE_IRAM)
1179-
print_sanity_check_icache();
1180-
#endif
1181-
/*
1182-
* Use new calculated SYS stack from top.
1183-
* Call the entry point of the SDK code.
1184-
*/
1185-
asm volatile ("mov.n a1, %0\n\t"
1186-
"movi a0, 0x4000044c\n\t" /* Should never return; however, set return to Boot ROM Breakpoint */
1187-
"jx %1\n\t" ::
1188-
"r" (sys_stack_first), "r" (call_user_start):
1189-
"a0", "memory");
1190-
1191-
__builtin_unreachable();
1192-
}
1193-
1194-
void IRAM_ATTR app_entry_redefinable(void) {
1195-
/*
1196-
* There are 4 sections of code that share the stack starting near
1197-
* 0x40000000.
1198-
* 1) The Boot ROM (uses around 640 bytes)
1199-
* 2) The Bootloader, eboot.elf (last seen using 720 bytes.)
1200-
* 3) `app_entry_redefinable()` just before it starts the SDK.
1201-
* 4) The NONOS SDK, optionally the Core when the extra 4K option is
1202-
* selected.
1203-
*
1204-
* Use the ROM BSS zeroed out memory as the home for our temporary stack.
1205-
* This way no additional information will be lost. That will remove this
1206-
* tool from the list of possible concerns for stack overwrite.
1207-
*
1208-
*/
1209-
1210-
asm volatile ("movi a1, 0x3fffeb30\n\t"
1211-
"j app_entry_start" ::: "memory");
1212-
1213-
/*
1214-
* Keep this function with just asm seems to help avoid a stack frame being
1215-
* created for this function and things getting really confused.
1216-
*/
1217-
1218-
__builtin_unreachable();
1219-
}
1220-
#endif
1221-
12221186
#if defined(DEBUG_ESP_HWDT_INFO) || defined(ROM_STACK_DUMP)
12231187
void debug_hwdt_init(void) {
12241188
/*

Diff for: libraries/esp8266/examples/HwdtStackDump/HwdtStackDump.ino

+22-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
speed defaults to 115200 bps. The HWDT stack dump will always print on port
1111
'Serial'.
1212
13-
To demonstrates this tool, this Sketch offers a few options for crashing the
13+
To demonstrate this tool, this Sketch offers a few options for crashing the
1414
ESP8266 with and without a HWDT reset.
1515
1616
*/
@@ -20,6 +20,7 @@
2020
#include <Esp.h>
2121
#include <user_interface.h>
2222
#include <coredecls.h> // g_pcont - only needed for this debug demo
23+
#include <StackThunk.h>
2324

2425
#ifndef STASSID
2526
#define STASSID "your-ssid"
@@ -29,6 +30,22 @@
2930
const char* ssid = STASSID;
3031
const char* password = STAPSK;
3132

33+
////////////////////////////////////////////////////////////////////
34+
// This block is just for putting something on the BearSSL stack
35+
// to show that it has not been zeroed out before HWDT stack dump
36+
// gets to runs.
37+
extern "C" {
38+
#if CORE_MOCK
39+
#define thunk_ets_uart_printf ets_uart_printf
40+
41+
#else
42+
int thunk_ets_uart_printf(const char *format, ...) __attribute__((format(printf, 1, 2)));
43+
// Second stack thunked helper - this macro creates the global function thunk_ets_uart_printf
44+
make_stack_thunk(ets_uart_printf);
45+
#endif
46+
};
47+
////////////////////////////////////////////////////////////////////
48+
3249
void setup(void) {
3350
WiFi.persistent(false); // w/o this a flash write occurs at every boot
3451
WiFi.mode(WIFI_OFF);
@@ -39,6 +56,10 @@ void setup(void) {
3956
Serial.println(F("The Hardware Watchdog Timer Demo is starting ..."));
4057
Serial.println();
4158

59+
// This allows us to test dumping a BearSSL stack after HWDT.
60+
stack_thunk_add_ref();
61+
thunk_ets_uart_printf("Using Thunk Stack to print this line.\n\n");
62+
4263
// We don't need this for this example; however, starting WiFi uses a little
4364
// more of the SYS stack.
4465
WiFi.mode(WIFI_STA);

0 commit comments

Comments
 (0)