diff --git a/components/esp_hw_support/port/esp32c5/cpu_region_protect.c b/components/esp_hw_support/port/esp32c5/cpu_region_protect.c index b9e1e0310f..cd054372da 100644 --- a/components/esp_hw_support/port/esp32c5/cpu_region_protect.c +++ b/components/esp_hw_support/port/esp32c5/cpu_region_protect.c @@ -8,6 +8,7 @@ #include "soc/soc.h" #include "esp_cpu.h" #include "esp_fault.h" +#include "esp32c5/rom/rom_layout.h" #ifdef BOOTLOADER_BUILD // Without L bit set @@ -55,6 +56,7 @@ static void esp_cpu_configure_invalid_regions(void) // 5. ROM has configured the MSPI region with RX permission, we should add W attribute for psram and lock the configuration // This function sets invalid regions but this is a valid memory region configuration that could have // been configured using PMP as well, but due to insufficient PMP entries we are configuring this using PMA. + // This entry is also required to be set using PMA because the region needs to be configured as cacheable. PMA_ENTRY_SET_NAPOT(9, SOC_IROM_LOW, (SOC_IROM_HIGH - SOC_IROM_LOW), PMA_NAPOT | PMA_RWX); // 6. Gap between D_Cache & LP_RAM @@ -74,7 +76,7 @@ void esp_cpu_configure_region_protection(void) { /* Notes on implementation: * - * 1) Note: ESP32-C5 CPU support overlapping PMP regions // TODO: verify this statement? + * 1) Note: ESP32-C5 CPU support overlapping PMP regions * * 2) ESP32-C5 supports 16 PMA regions so we use this feature to block all the invalid address ranges * @@ -128,17 +130,27 @@ void esp_cpu_configure_region_protection(void) _Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region"); // 2. I/D-ROM - PMP_ENTRY_SET(1, SOC_IROM_MASK_LOW, NONE); - PMP_ENTRY_SET(2, SOC_IROM_MASK_HIGH, PMP_TOR | RX); - _Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region"); + const uint32_t drom_start = (uint32_t) (ets_rom_layout_p->drom_start); + if ((drom_start & (SOC_CPU_PMP_REGION_GRANULARITY - 1)) == 0) { + // We can skip configuring the PMP entry for the [SOC_IROM_MASK_LOW - drom_start] + // region as RX, as we already have configured a PMA entry with RX permissions for the + // [SOC_IROM_MASK_LOW - SOC_DROM_MASK_HIGH] region that helps us to also configure + // the region as cacheable. Thus, we save on one PMP entry. + PMP_ENTRY_SET(1, drom_start, NONE); + PMP_ENTRY_SET(2, SOC_DROM_MASK_HIGH, PMP_TOR | R); + } else { + PMP_ENTRY_SET(1, SOC_IROM_MASK_LOW, NONE); + PMP_ENTRY_SET(2, SOC_IROM_MASK_HIGH, PMP_TOR | RX); + _Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region"); + } // 3. IRAM and DRAM if (esp_cpu_dbgr_is_attached()) { // Anti-FI check that cpu is really in ocd mode ESP_FAULT_ASSERT(esp_cpu_dbgr_is_attached()); - PMP_ENTRY_SET(5, SOC_IRAM_LOW, NONE); - PMP_ENTRY_SET(6, SOC_IRAM_HIGH, PMP_TOR | RWX); + PMP_ENTRY_SET(3, SOC_IRAM_LOW, NONE); + PMP_ENTRY_SET(4, SOC_IRAM_HIGH, PMP_TOR | RWX); _Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region"); } else { #if CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT && !BOOTLOADER_BUILD @@ -146,15 +158,15 @@ void esp_cpu_configure_region_protection(void) /* Reset the corresponding PMP config because PMP_ENTRY_SET only sets the given bits * Bootloader might have given extra permissions and those won't be cleared */ + PMP_ENTRY_CFG_RESET(3); + PMP_ENTRY_CFG_RESET(4); PMP_ENTRY_CFG_RESET(5); - PMP_ENTRY_CFG_RESET(6); - PMP_ENTRY_CFG_RESET(7); - PMP_ENTRY_SET(5, SOC_IRAM_LOW, NONE); - PMP_ENTRY_SET(6, (int)&_iram_text_end, PMP_TOR | RX); - PMP_ENTRY_SET(7, SOC_DRAM_HIGH, PMP_TOR | RW); + PMP_ENTRY_SET(3, SOC_IRAM_LOW, NONE); + PMP_ENTRY_SET(4, (int)&_iram_text_end, PMP_TOR | RX); + PMP_ENTRY_SET(5, SOC_DRAM_HIGH, PMP_TOR | RW); #else - PMP_ENTRY_SET(5, SOC_IRAM_LOW, CONDITIONAL_NONE); - PMP_ENTRY_SET(6, SOC_IRAM_HIGH, PMP_TOR | CONDITIONAL_RWX); + PMP_ENTRY_SET(3, SOC_IRAM_LOW, CONDITIONAL_NONE); + PMP_ENTRY_SET(4, SOC_IRAM_HIGH, PMP_TOR | CONDITIONAL_RWX); _Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region"); #endif } @@ -167,16 +179,16 @@ void esp_cpu_configure_region_protection(void) const uint32_t irom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)(&_instruction_reserved_end)); const uint32_t drom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)(&_rodata_reserved_end)); + PMP_ENTRY_CFG_RESET(6); + PMP_ENTRY_CFG_RESET(7); PMP_ENTRY_CFG_RESET(8); - PMP_ENTRY_CFG_RESET(9); - PMP_ENTRY_CFG_RESET(10); - PMP_ENTRY_SET(8, SOC_IROM_LOW, NONE); - PMP_ENTRY_SET(9, irom_resv_end, PMP_TOR | RX); - PMP_ENTRY_SET(10, drom_resv_end, PMP_TOR | R); + PMP_ENTRY_SET(6, SOC_IROM_LOW, NONE); + PMP_ENTRY_SET(7, irom_resv_end, PMP_TOR | RX); + PMP_ENTRY_SET(8, drom_resv_end, PMP_TOR | R); #else - const uint32_t pmpaddr8 = PMPADDR_NAPOT(SOC_IROM_LOW, SOC_IROM_HIGH); + const uint32_t pmpaddr6 = PMPADDR_NAPOT(SOC_IROM_LOW, SOC_IROM_HIGH); // Add the W attribute in the case of PSRAM - PMP_ENTRY_SET(8, pmpaddr8, PMP_NAPOT | CONDITIONAL_RWX); + PMP_ENTRY_SET(6, pmpaddr6, PMP_NAPOT | CONDITIONAL_RWX); _Static_assert(SOC_IROM_LOW < SOC_IROM_HIGH, "Invalid I/D_Cache region"); #endif @@ -187,25 +199,25 @@ void esp_cpu_configure_region_protection(void) /* Reset the corresponding PMP config because PMP_ENTRY_SET only sets the given bits * Bootloader might have given extra permissions and those won't be cleared */ + PMP_ENTRY_CFG_RESET(9); + PMP_ENTRY_CFG_RESET(10); PMP_ENTRY_CFG_RESET(11); PMP_ENTRY_CFG_RESET(12); - PMP_ENTRY_CFG_RESET(13); - PMP_ENTRY_CFG_RESET(14); - PMP_ENTRY_SET(11, SOC_RTC_IRAM_LOW, NONE); + PMP_ENTRY_SET(9, SOC_RTC_IRAM_LOW, NONE); // First part of LP mem is reserved for ULP coprocessor - PMP_ENTRY_SET(12, (int)&_rtc_text_start, PMP_TOR | RW); + PMP_ENTRY_SET(10, (int)&_rtc_text_start, PMP_TOR | RW); - PMP_ENTRY_SET(13, (int)&_rtc_text_end, PMP_TOR | RX); - PMP_ENTRY_SET(14, SOC_RTC_IRAM_HIGH, PMP_TOR | RW); + PMP_ENTRY_SET(11, (int)&_rtc_text_end, PMP_TOR | RX); + PMP_ENTRY_SET(12, SOC_RTC_IRAM_HIGH, PMP_TOR | RW); #else - const uint32_t pmpaddr11 = PMPADDR_NAPOT(SOC_RTC_IRAM_LOW, SOC_RTC_IRAM_HIGH); - PMP_ENTRY_SET(11, pmpaddr11, PMP_NAPOT | CONDITIONAL_RWX); + const uint32_t pmpaddr9 = PMPADDR_NAPOT(SOC_RTC_IRAM_LOW, SOC_RTC_IRAM_HIGH); + PMP_ENTRY_SET(9, pmpaddr9, PMP_NAPOT | CONDITIONAL_RWX); _Static_assert(SOC_RTC_IRAM_LOW < SOC_RTC_IRAM_HIGH, "Invalid RTC IRAM region"); #endif // 6. Peripheral addresses - const uint32_t pmpaddr15 = PMPADDR_NAPOT(SOC_PERIPHERAL_LOW, SOC_PERIPHERAL_HIGH); - PMP_ENTRY_SET(15, pmpaddr15, PMP_NAPOT | RW); + const uint32_t pmpaddr13 = PMPADDR_NAPOT(SOC_PERIPHERAL_LOW, SOC_PERIPHERAL_HIGH); + PMP_ENTRY_SET(13, pmpaddr13, PMP_NAPOT | RW); _Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region"); }