Skip to content

Commit bea71f1

Browse files
Merge branch 'safetydance' of https://github.com/earlephilhower/Arduino into safetydance
2 parents 086b9c9 + 5886d52 commit bea71f1

23 files changed

+454
-248
lines changed

cores/esp8266/core_esp8266_app_entry_noextra4k.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,19 @@ extern "C" void app_entry_redefinable(void)
3939
{
4040
g_pcont = &g_cont;
4141

42+
#ifdef UMM_INIT_USE_IRAM
43+
/*
44+
* Legacy option: the umm_init() call path must reside in IRAM.
45+
*/
4246
umm_init();
47+
#else
48+
/*
49+
* Instruction cache is enabled/disabled around running umm_init().
50+
* Allows the use of IROM (flash) to store umm_init().
51+
*/
52+
mmu_wrap_irom_fn(umm_init);
53+
#endif
54+
4355
/* Call the entry point of the SDK code. */
4456
call_user_start();
4557
}

cores/esp8266/core_esp8266_main.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,12 @@ extern "C" void app_entry_redefinable(void)
365365

366366
/* Doing umm_init just once before starting the SDK, allowed us to remove
367367
test and init calls at each malloc API entry point, saving IRAM. */
368+
#ifdef UMM_INIT_USE_IRAM
368369
umm_init();
370+
#else
371+
// umm_init() is in IROM
372+
mmu_wrap_irom_fn(umm_init);
373+
#endif
369374
/* Call the entry point of the SDK code. */
370375
call_user_start();
371376
}

cores/esp8266/heap.cpp

+12-5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include <stdlib.h>
77
#include "umm_malloc/umm_malloc.h"
8+
extern "C" size_t umm_umul_sat(const size_t a, const size_t b);;
89

910
// Need FORCE_ALWAYS_INLINE to put HeapSelect class constructor/deconstructor in IRAM
1011
#define FORCE_ALWAYS_INLINE_HEAP_SELECT
@@ -153,7 +154,7 @@ void* _calloc_r(struct _reent* unused, size_t count, size_t size)
153154
{
154155
(void) unused;
155156
void *ret = calloc(count, size);
156-
PTR_CHECK__LOG_LAST_FAIL(ret, count * size);
157+
PTR_CHECK__LOG_LAST_FAIL(ret, umm_umul_sat(count, size));
157158
return ret;
158159
}
159160

@@ -247,8 +248,11 @@ void* IRAM_ATTR calloc(size_t count, size_t size)
247248
INTEGRITY_CHECK__ABORT();
248249
POISON_CHECK__ABORT();
249250
void* ret = UMM_CALLOC(count, size);
250-
PTR_CHECK__LOG_LAST_FAIL(ret, count * size);
251-
OOM_CHECK__PRINT_OOM(ret, size);
251+
#if defined(DEBUG_ESP_OOM)
252+
size_t total_size = umm_umul_sat(count, size);// For logging purposes
253+
#endif
254+
PTR_CHECK__LOG_LAST_FAIL(ret, total_size);
255+
OOM_CHECK__PRINT_OOM(ret, total_size);
252256
return ret;
253257
}
254258

@@ -287,8 +291,11 @@ void* IRAM_ATTR heap_pvPortCalloc(size_t count, size_t size, const char* file, i
287291
INTEGRITY_CHECK__PANIC_FL(file, line);
288292
POISON_CHECK__PANIC_FL(file, line);
289293
void* ret = UMM_CALLOC(count, size);
290-
PTR_CHECK__LOG_LAST_FAIL_FL(ret, count * size, file, line);
291-
OOM_CHECK__PRINT_LOC(ret, size, file, line);
294+
#if defined(DEBUG_ESP_OOM)
295+
size_t total_size = umm_umul_sat(count, size);
296+
#endif
297+
PTR_CHECK__LOG_LAST_FAIL_FL(ret, total_size, file, line);
298+
OOM_CHECK__PRINT_LOC(ret, total_size, file, line);
292299
return ret;
293300
}
294301

cores/esp8266/hwdt_app_entry.cpp

+30-32
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@
275275
#include <esp8266_peri.h>
276276
#include <uart.h>
277277
#include <pgmspace.h>
278+
#include "mmu_iram.h"
278279

279280
extern "C" {
280281
#include <user_interface.h>
@@ -1007,6 +1008,18 @@ STATIC void IRAM_MAYBE handle_hwdt(void) {
10071008
#endif
10081009
}
10091010

1011+
#if defined(DEBUG_ESP_HWDT_DEV_DEBUG) && !defined(USE_IRAM)
1012+
static void printSanityCheck() {
1013+
ETS_PRINTF("\n\nsys_stack_first: %p\n", sys_stack_first);
1014+
ETS_PRINTF( "CONT_STACK: %p\n", CONT_STACK);
1015+
ETS_PRINTF( "g_pcont: %p\n", g_pcont);
1016+
ETS_PRINTF( "ROM_STACK: %p\n", ROM_STACK);
1017+
ETS_PRINTF( "get_noextra4k_g_pcont(): %p\n", get_noextra4k_g_pcont());
1018+
ETS_PRINTF( "g_rom_stack: %p\n", g_rom_stack);
1019+
ETS_PRINTF( "g_rom_stack_A16_sz: 0x%08X\n\n", g_rom_stack_A16_sz);
1020+
}
1021+
#endif //DEBUG_ESP_HWDT_DEV_DEBUG
1022+
10101023
/*
10111024
* Using Cache_Read_Enable/Cache_Read_Disable to reduce IRAM usage. Moved
10121025
* strings and most functions to flash. At this phase of the startup, "C++" has
@@ -1019,34 +1032,11 @@ STATIC void IRAM_MAYBE handle_hwdt(void) {
10191032
* https://richard.burtons.org/2015/06/12/esp8266-cache_read_enable/.
10201033
* Additional insight can be gleemed from reviewing the ESP8266_RTOS_SDK.
10211034
* (eg. ../components/bootloader_support/src/bootloader_utility.c)
1035+
*
1036+
* The logic to use Cache_Read_Enable and Cache_Read_Disable has been
1037+
* generalized into a wrapper function, mmu_wrap_irom_fn, and moved to
1038+
* mmu_iram.cpp.
10221039
*/
1023-
#define ICACHE_SIZE_32 1
1024-
#define ICACHE_SIZE_16 0
1025-
1026-
extern "C" void Cache_Read_Disable(void);
1027-
extern "C" void Cache_Read_Enable(uint8_t map, uint8_t p, uint8_t v);
1028-
1029-
#ifndef USE_IRAM
1030-
static void IRAM_ATTR __attribute__((noinline)) handle_hwdt_icache() __attribute__((used));
1031-
void handle_hwdt_icache() {
1032-
Cache_Read_Enable(0, 0, ICACHE_SIZE_16);
1033-
handle_hwdt();
1034-
Cache_Read_Disable();
1035-
}
1036-
#endif // USE_IRAM
1037-
1038-
1039-
#if defined(DEBUG_ESP_HWDT_DEV_DEBUG) && !defined(USE_IRAM)
1040-
static void printSanityCheck() {
1041-
ETS_PRINTF("\n\nsys_stack_first: %p\n", sys_stack_first);
1042-
ETS_PRINTF( "CONT_STACK: %p\n", CONT_STACK);
1043-
ETS_PRINTF( "g_pcont: %p\n", g_pcont);
1044-
ETS_PRINTF( "ROM_STACK: %p\n", ROM_STACK);
1045-
ETS_PRINTF( "get_noextra4k_g_pcont(): %p\n", get_noextra4k_g_pcont());
1046-
ETS_PRINTF( "g_rom_stack: %p\n", g_rom_stack);
1047-
ETS_PRINTF( "g_rom_stack_A16_sz: 0x%08X\n\n", g_rom_stack_A16_sz);
1048-
}
1049-
#endif //DEBUG_ESP_HWDT_DEV_DEBUG
10501040

10511041
/*
10521042
hwdt_pre_sdk_init() is the result of a hook for development diagnotics which
@@ -1071,9 +1061,8 @@ void hwdt_pre_sdk_init(void) {
10711061
#endif
10721062
}
10731063

1074-
static void IRAM_ATTR __attribute__((noinline)) hwdt_pre_sdk_init_icache(void) __attribute__((used));
1064+
static void __attribute__((noinline)) hwdt_pre_sdk_init_icache(void) __attribute__((used));
10751065
void hwdt_pre_sdk_init_icache(void) {
1076-
Cache_Read_Enable(0, 0, ICACHE_SIZE_16);
10771066
#ifdef DEBUG_ESP_HWDT_UART_SPEED
10781067
const uint32_t uart_divisor = set_uart_speed(0, DEBUG_ESP_HWDT_UART_SPEED);
10791068
#endif
@@ -1085,7 +1074,6 @@ void hwdt_pre_sdk_init_icache(void) {
10851074
adjust_uart_speed(uart_divisor);
10861075
}
10871076
#endif
1088-
Cache_Read_Disable();
10891077
}
10901078

10911079
/*
@@ -1106,6 +1094,7 @@ asm (
11061094
".literal .umm_init, umm_init\n\t"
11071095
".literal .call_user_start, call_user_start\n\t"
11081096
".literal .get_noextra4k_g_pcont, get_noextra4k_g_pcont\n\t"
1097+
".literal .mmu_wrap_irom_fn, mmu_wrap_irom_fn\n\t"
11091098
".align 4\n\t"
11101099
".global app_entry_redefinable\n\t"
11111100
".type app_entry_redefinable, @function\n\t"
@@ -1129,7 +1118,9 @@ asm (
11291118
#ifdef USE_IRAM
11301119
"call0 handle_hwdt\n\t"
11311120
#else
1132-
"call0 handle_hwdt_icache\n\t"
1121+
"l32r a0, .mmu_wrap_irom_fn\n\t"
1122+
"movi a2, handle_hwdt\n\t"
1123+
"callx0 a0\n\t"
11331124
#endif
11341125
/*
11351126
* Use new calculated SYS stack from top.
@@ -1160,7 +1151,9 @@ asm (
11601151
/*
11611152
* Allow for running additional diagnotics supplied at link time.
11621153
*/
1163-
"call0 hwdt_pre_sdk_init_icache\n\t"
1154+
"l32r a0, .mmu_wrap_irom_fn\n\t"
1155+
"movi a2, hwdt_pre_sdk_init_icache\n\t"
1156+
"callx0 a0\n\t"
11641157

11651158
// In case somebody cares, leave things as we found them
11661159
// - Restore ROM BSS zeros.
@@ -1174,7 +1167,12 @@ asm (
11741167
* improvements could possibly use hwdt_pre_sdk_init() to run other early
11751168
* diagnostic tools.
11761169
*/
1170+
#ifdef UMM_INIT_USE_IRAM
11771171
"l32r a0, .umm_init\n\t"
1172+
#else
1173+
"l32r a0, .mmu_wrap_irom_fn\n\t"
1174+
"l32r a2, .umm_init\n\t"
1175+
#endif
11781176
"callx0 a0\n\t"
11791177

11801178
"l32r a3, .call_user_start\n\t"

cores/esp8266/mmu_iram.cpp

+18-2
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@
1919
#include "mmu_iram.h"
2020
#include <user_interface.h>
2121

22+
#define ICACHE_SIZE_32 1
23+
#define ICACHE_SIZE_16 0
24+
2225
extern "C" {
2326

2427
#if (MMU_ICACHE_SIZE == 0x4000)
25-
#define SOC_CACHE_SIZE 0 // 16KB
28+
#define SOC_CACHE_SIZE ICACHE_SIZE_16
2629
#pragma message("ICACHE size 16K")
2730
#else
28-
#define SOC_CACHE_SIZE 1 // 32KB
31+
#define SOC_CACHE_SIZE ICACHE_SIZE_32
2932
#endif
3033

3134
#if (MMU_ICACHE_SIZE == 0x4000)
@@ -185,8 +188,21 @@ extern "C" void pinMode( uint8_t pin, uint8_t mode ) {
185188

186189
__pinMode( pin, mode );
187190
}
191+
#else // #ifdef DEV_DEBUG_PRINT
192+
extern void Cache_Read_Disable(void);
188193
#endif // #ifdef DEV_DEBUG_PRINT
189194

195+
#else // #if (MMU_ICACHE_SIZE == 0x4000)
196+
extern void Cache_Read_Enable(uint8_t map, uint8_t p, uint8_t v);
190197
#endif // #if (MMU_ICACHE_SIZE == 0x4000)
191198

199+
/*
200+
* This wrapper is for running code from IROM (flash) before the SDK starts.
201+
*/
202+
void IRAM_ATTR mmu_wrap_irom_fn(void (*fn)(void)) {
203+
Cache_Read_Enable(0, 0, ICACHE_SIZE_16);
204+
fn();
205+
Cache_Read_Disable();
206+
}
207+
192208
};

cores/esp8266/mmu_iram.h

+18
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,24 @@ DBG_MMU_FLUSH(0)
8080
#define DBG_MMU_PRINTF(...) do {} while(false)
8181
#endif // defined(DEV_DEBUG_PRINT) || defined(DEBUG_ESP_MMU)
8282

83+
/*
84+
* This wrapper is for running code from IROM (flash) before the SDK starts.
85+
*
86+
* Wraps a `void fn(void)` call with calls to enable and disable iCACHE.
87+
* Allows a function that resides in IROM to run before the SDK starts.
88+
*
89+
* Do not use once the SDK has started.
90+
*
91+
* Because the SDK initialization code has not run, nearly all the SDK functions
92+
* are not safe to call.
93+
*
94+
* Note printing at this early stage is complicated. To gain more insight,
95+
* review DEV_DEBUG_PRINT build path in mmu_iram.cpp. To handle strings stored
96+
* in IROM, review printing method and comments in hwdt_app_entry.cpp.
97+
*
98+
*/
99+
void IRAM_ATTR mmu_wrap_irom_fn(void (*fn)(void));
100+
83101
static inline __attribute__((always_inline))
84102
bool mmu_is_iram(const void *addr) {
85103
const uintptr_t iram_start = (uintptr_t)XCHAL_INSTRAM1_VADDR;

cores/esp8266/umm_malloc/umm_info.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
void *umm_info(void *ptr, bool force) {
2929
UMM_CRITICAL_DECL(id_info);
3030

31-
UMM_INIT_HEAP;
31+
UMM_CHECK_INITIALIZED();
3232

3333
uint16_t blockNo = 0;
3434

cores/esp8266/umm_malloc/umm_integrity.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ bool umm_integrity_check(void) {
3333
uint16_t prev;
3434
uint16_t cur;
3535

36-
UMM_INIT_HEAP;
36+
UMM_CHECK_INITIALIZED();
3737

3838
/* Iterate through all free blocks */
3939
prev = 0;

cores/esp8266/umm_malloc/umm_local.c

+30-2
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ void *umm_poison_realloc_fl(void *ptr, size_t size, const char *file, int line)
137137

138138
ptr = get_unpoisoned_check_neighbors(ptr, file, line);
139139

140-
size += poison_size(size);
140+
add_poison_size(&size);
141141
ret = umm_realloc(ptr, size);
142142

143143
ret = get_poisoned(ret, size);
@@ -166,7 +166,7 @@ size_t umm_block_size(void) {
166166
#if defined(UMM_STATS) || defined(UMM_STATS_FULL)
167167
// Keep complete call path in IRAM
168168
size_t umm_free_heap_size_lw(void) {
169-
UMM_INIT_HEAP;
169+
UMM_CHECK_INITIALIZED();
170170

171171
umm_heap_context_t *_context = umm_get_current_heap();
172172
return (size_t)_context->UMM_FREE_BLOCKS * sizeof(umm_block);
@@ -296,4 +296,32 @@ size_t ICACHE_FLASH_ATTR umm_get_free_null_count(void) {
296296
}
297297
#endif // UMM_STATS_FULL
298298

299+
#if defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE)
300+
/*
301+
* Saturated unsigned add
302+
* Poison added to allocation size requires overflow protection.
303+
*/
304+
static size_t umm_uadd_sat(const size_t a, const size_t b) {
305+
size_t r = a + b;
306+
if (r < a) {
307+
return SIZE_MAX;
308+
}
309+
return r;
310+
}
311+
#endif
312+
313+
/*
314+
* Use platform-specific functions to protect against unsigned overflow/wrap by
315+
* implementing saturated unsigned multiply.
316+
* The function umm_calloc requires a saturated multiply function.
317+
*/
318+
size_t umm_umul_sat(const size_t a, const size_t b) {
319+
size_t r;
320+
if (__builtin_mul_overflow(a, b, &r)) {
321+
return SIZE_MAX;
322+
}
323+
return r;
324+
}
325+
326+
299327
#endif // BUILD_UMM_MALLOC_C

cores/esp8266/umm_malloc/umm_local.h

+8
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@
1515
#define memset ets_memset
1616

1717

18+
/*
19+
* Saturated unsigned add and unsigned multiply
20+
*/
21+
size_t umm_umul_sat(const size_t a, const size_t b); // share with heap.cpp
22+
#if defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE)
23+
static size_t umm_uadd_sat(const size_t a, const size_t b);
24+
#endif
25+
1826
/*
1927
* This redefines DBGLOG_FORCE defined in dbglog/dbglog.h
2028
* Just for printing from umm_info() which is assumed to always be called from

0 commit comments

Comments
 (0)