From 102d290eb9207e101107bf10526468296cd8663c Mon Sep 17 00:00:00 2001 From: Guillaume Souchere Date: Thu, 6 Mar 2025 12:52:13 +0100 Subject: [PATCH] fix(heap): Wrong address calculation in heap_caps_free Make sure that DRAM != IRAM before getting the DRAM address from a IRAM allocation. --- .../include/bootloader_memory_utils.h | 17 +++++++++++++---- .../esp_hw_support/include/esp_memory_utils.h | 17 +++++++++++++---- components/heap/heap_caps_base.c | 10 ++++++---- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/components/bootloader_support/include/bootloader_memory_utils.h b/components/bootloader_support/include/bootloader_memory_utils.h index 62769cfe7d..8999200d91 100644 --- a/components/bootloader_support/include/bootloader_memory_utils.h +++ b/components/bootloader_support/include/bootloader_memory_utils.h @@ -27,12 +27,21 @@ extern "C" { */ __attribute__((always_inline)) inline static bool esp_dram_match_iram(void) { - bool dram_match_iram = (SOC_DRAM_LOW == SOC_IRAM_LOW) && - (SOC_DRAM_HIGH == SOC_IRAM_HIGH); + return ((SOC_DRAM_LOW == SOC_IRAM_LOW) && (SOC_DRAM_HIGH == SOC_IRAM_HIGH)); +} + +/** + * @brief Check if the RTC IRAM and RTC DRAM are separate or using the same memory space + * + * @return true if the RTC DRAM and RTC IRAM are sharing the same memory space, false otherwise + */ +__attribute__((always_inline)) +inline static bool esp_rtc_dram_match_rtc_iram(void) { #if SOC_RTC_FAST_MEM_SUPPORTED - dram_match_iram &= (SOC_RTC_IRAM_LOW == SOC_RTC_DRAM_LOW); + return ((SOC_RTC_IRAM_LOW == SOC_RTC_DRAM_LOW) && (SOC_RTC_IRAM_HIGH == SOC_RTC_DRAM_HIGH)); +#else + return false; #endif - return dram_match_iram; } /** diff --git a/components/esp_hw_support/include/esp_memory_utils.h b/components/esp_hw_support/include/esp_memory_utils.h index 90652add40..64315e5e90 100644 --- a/components/esp_hw_support/include/esp_memory_utils.h +++ b/components/esp_hw_support/include/esp_memory_utils.h @@ -27,12 +27,21 @@ extern "C" { */ __attribute__((always_inline)) inline static bool esp_dram_match_iram(void) { - bool dram_match_iram = (SOC_DRAM_LOW == SOC_IRAM_LOW) && - (SOC_DRAM_HIGH == SOC_IRAM_HIGH); + return ((SOC_DRAM_LOW == SOC_IRAM_LOW) && (SOC_DRAM_HIGH == SOC_IRAM_HIGH)); +} + +/** + * @brief Check if the RTC IRAM and RTC DRAM are separate or using the same memory space + * + * @return true if the RTC DRAM and RTC IRAM are sharing the same memory space, false otherwise + */ +__attribute__((always_inline)) +inline static bool esp_rtc_dram_match_rtc_iram(void) { #if SOC_RTC_FAST_MEM_SUPPORTED - dram_match_iram &= (SOC_RTC_IRAM_LOW == SOC_RTC_DRAM_LOW); + return ((SOC_RTC_IRAM_LOW == SOC_RTC_DRAM_LOW) && (SOC_RTC_IRAM_HIGH == SOC_RTC_DRAM_HIGH)); +#else + return false; #endif - return dram_match_iram; } /** diff --git a/components/heap/heap_caps_base.c b/components/heap/heap_caps_base.c index 4ec7c408e3..33a7e3d62e 100644 --- a/components/heap/heap_caps_base.c +++ b/components/heap/heap_caps_base.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -56,7 +56,8 @@ HEAP_IRAM_ATTR void heap_caps_free( void *ptr) return; } - if (esp_ptr_in_diram_iram(ptr) || esp_ptr_in_rtc_iram_fast(ptr)) { + if ((!esp_dram_match_iram() && esp_ptr_in_diram_iram(ptr)) || + (!esp_rtc_dram_match_rtc_iram() && esp_ptr_in_rtc_iram_fast(ptr))) { //Memory allocated here is actually allocated in the DRAM alias region and //cannot be de-allocated as usual. dram_alloc_to_iram_addr stores a pointer to //the equivalent DRAM address, though; free that. @@ -119,8 +120,9 @@ HEAP_IRAM_ATTR NOINLINE_ATTR void *heap_caps_malloc_base( size_t size, uint32_t //This heap can satisfy all the requested capabilities. See if we can grab some memory using it. // If MALLOC_CAP_EXEC is requested but the DRAM and IRAM are on the same addresses (like on esp32c6) // proceed as for a default allocation. - if (((caps & MALLOC_CAP_EXEC) && !esp_dram_match_iram()) && - (esp_ptr_in_diram_dram((void *)heap->start) || esp_ptr_in_rtc_dram_fast((void *)heap->start))) { + if ((caps & MALLOC_CAP_EXEC) && + ((!esp_dram_match_iram() && esp_ptr_in_diram_dram((void *)heap->start)) || + (!esp_rtc_dram_match_rtc_iram() && esp_ptr_in_rtc_dram_fast((void *)heap->start)))) { //This is special, insofar that what we're going to get back is a DRAM address. If so, //we need to 'invert' it (lowest address in DRAM == highest address in IRAM and vice-versa) and //add a pointer to the DRAM equivalent before the address we're going to return.