diff --git a/components/esp_hw_support/port/esp32c61/cpu_region_protect.c b/components/esp_hw_support/port/esp32c61/cpu_region_protect.c index f33f2aa7f4..7b0fffabd8 100644 --- a/components/esp_hw_support/port/esp32c61/cpu_region_protect.c +++ b/components/esp_hw_support/port/esp32c61/cpu_region_protect.c @@ -9,6 +9,7 @@ #include "soc/soc.h" #include "esp_cpu.h" #include "esp_fault.h" +#include "esp32c61/rom/rom_layout.h" #ifdef BOOTLOADER_BUILD // Without L bit set @@ -24,20 +25,55 @@ #define CONDITIONAL_RWX RWX #endif +#define ALIGN_UP_TO_MMU_PAGE_SIZE(addr) (((addr) + (SOC_MMU_PAGE_SIZE) - 1) & ~((SOC_MMU_PAGE_SIZE) - 1)) +#define ALIGN_DOWN_TO_MMU_PAGE_SIZE(addr) ((addr) & ~((SOC_MMU_PAGE_SIZE) - 1)) + static void esp_cpu_configure_invalid_regions(void) { - //TODO: [ESP32C61] IDF-9580 - abort(); + const unsigned PMA_NONE = PMA_L | PMA_EN; + __attribute__((unused)) const unsigned PMA_RW = PMA_L | PMA_EN | PMA_R | PMA_W; + __attribute__((unused)) const unsigned PMA_RX = PMA_L | PMA_EN | PMA_R | PMA_X; + __attribute__((unused)) const unsigned PMA_RWX = PMA_L | PMA_EN | PMA_R | PMA_W | PMA_X; + + // 0. Gap at bottom of address space + PMA_ENTRY_SET_NAPOT(0, 0, SOC_CPU_SUBSYSTEM_LOW, PMA_NAPOT | PMA_NONE); + + // 1. Gap between debug region & IROM + PMA_ENTRY_SET_TOR(1, SOC_CPU_SUBSYSTEM_HIGH, PMA_NONE); + PMA_ENTRY_SET_TOR(2, SOC_IROM_MASK_LOW, PMA_TOR | PMA_NONE); + + // 3. Gap between ROM & RAM + PMA_ENTRY_SET_TOR(3, SOC_DROM_MASK_HIGH, PMA_NONE); + PMA_ENTRY_SET_TOR(4, SOC_IRAM_LOW, PMA_TOR | PMA_NONE); + + // 4. Gap between DRAM and I_Cache + PMA_ENTRY_SET_TOR(5, SOC_IRAM_HIGH, PMA_NONE); + PMA_ENTRY_SET_TOR(6, SOC_IROM_LOW, PMA_TOR | PMA_NONE); + + // 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(7, SOC_IROM_LOW, (SOC_IROM_HIGH - SOC_IROM_LOW), PMA_NAPOT | PMA_RWX); + + // 6. Gap between D_Cache & LP_RAM + PMA_ENTRY_SET_TOR(8, SOC_DROM_HIGH, PMA_NONE); + PMA_ENTRY_SET_TOR(9, SOC_RTC_IRAM_LOW, PMA_TOR | PMA_NONE); + + // 7. Gap between LP memory & peripheral addresses + PMA_ENTRY_SET_TOR(10, SOC_RTC_IRAM_HIGH, PMA_NONE); + PMA_ENTRY_SET_TOR(11, SOC_PERIPHERAL_LOW, PMA_TOR | PMA_NONE); + + // 8. End of address space + PMA_ENTRY_SET_TOR(12, SOC_PERIPHERAL_HIGH, PMA_NONE); + PMA_ENTRY_SET_TOR(13, UINT32_MAX, PMA_TOR | PMA_NONE); } void esp_cpu_configure_region_protection(void) { - // ROM has configured the MSPI region with RX permission, we should add W attribute for psram - PMA_ENTRY_SET_NAPOT(0, SOC_IROM_LOW, (SOC_IROM_HIGH - SOC_IROM_LOW), PMA_NAPOT | PMA_L | PMA_EN | PMA_R | PMA_W | PMA_X); - return; /* Notes on implementation: * - * 1) Note: ESP32-C61 CPU doesn't support overlapping PMP regions + * 1) Note: ESP32-C61 CPU supports overlapping PMP regions * * 2) ESP32-C61 supports 16 PMA regions so we use this feature to block all the invalid address ranges * @@ -57,7 +93,7 @@ void esp_cpu_configure_region_protection(void) * * 2. Application build with CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT enabled * - We split the SRAM into IRAM and DRAM such that IRAM region cannot be written to - * and DRAM region cannot be executed. We use _iram_end and _data_start markers to set the boundaries. + * and DRAM region cannot be executed. We use _iram_text_end and _data_start markers to set the boundaries. * We also lock these entries so the R/W/X permissions are enforced even for machine mode * * 3. Application build with CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT disabled @@ -71,10 +107,10 @@ void esp_cpu_configure_region_protection(void) * We also lock these entries so the R/W/X permissions are enforced even for machine mode */ const unsigned NONE = PMP_L; - const unsigned R = PMP_L | PMP_R; - const unsigned RW = PMP_L | PMP_R | PMP_W; - const unsigned RX = PMP_L | PMP_R | PMP_X; - const unsigned RWX = PMP_L | PMP_R | PMP_W | PMP_X; + __attribute__((unused)) const unsigned R = PMP_L | PMP_R; + __attribute__((unused)) const unsigned RW = PMP_L | PMP_R | PMP_W; + __attribute__((unused)) const unsigned RX = PMP_L | PMP_R | PMP_X; + __attribute__((unused)) const unsigned RWX = PMP_L | PMP_R | PMP_W | PMP_X; // // Configure all the invalid address regions using PMA @@ -84,63 +120,73 @@ void esp_cpu_configure_region_protection(void) // Configure all the valid address regions using PMP // - // 1. CPU Subsystem region - contains debug mode code and interrupt config registers + // 1. CPU Subsystem region - contains interrupt config registers const uint32_t pmpaddr0 = PMPADDR_NAPOT(SOC_CPU_SUBSYSTEM_LOW, SOC_CPU_SUBSYSTEM_HIGH); PMP_ENTRY_SET(0, pmpaddr0, PMP_NAPOT | RWX); _Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region"); - // 2.1 I-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-ROM region"); - - // 2.2 D-ROM - PMP_ENTRY_SET(3, SOC_DROM_MASK_LOW, NONE); - PMP_ENTRY_SET(4, SOC_DROM_MASK_HIGH, PMP_TOR | R); - _Static_assert(SOC_DROM_MASK_LOW < SOC_DROM_MASK_HIGH, "Invalid D-ROM region"); + // 2. I/D-ROM + const uint32_t drom_start = (uint32_t) (ets_rom_layout_p->drom_start); + if ((drom_start & (SOC_CPU_PMP_REGION_GRANULARITY - 1)) == 0) { + PMP_ENTRY_SET(1, SOC_IROM_MASK_LOW, NONE); + PMP_ENTRY_SET(2, drom_start, PMP_TOR | RX); + PMP_ENTRY_SET(3, SOC_DROM_MASK_HIGH, PMP_TOR | RW); + } else { + const uint32_t pmpaddr1 = PMPADDR_NAPOT(SOC_IROM_MASK_LOW, SOC_IROM_MASK_HIGH); + PMP_ENTRY_SET(1, pmpaddr1, PMP_NAPOT | 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()); - // 5. IRAM and DRAM - // const uint32_t pmpaddr5 = PMPADDR_NAPOT(SOC_IRAM_LOW, SOC_IRAM_HIGH); - const uint32_t pmpaddr5 = PMPADDR_NAPOT(SOC_IRAM_LOW, 0x40880000); - PMP_ENTRY_SET(5, pmpaddr5, PMP_NAPOT | RWX); + PMP_ENTRY_SET(4, SOC_IRAM_LOW, NONE); + PMP_ENTRY_SET(5, 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 - extern int _iram_end; - // 5. IRAM and DRAM + extern int _iram_text_end; /* 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(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_end, PMP_TOR | RX); - PMP_ENTRY_SET(7, SOC_DRAM_HIGH, PMP_TOR | RW); + PMP_ENTRY_SET(4, SOC_IRAM_LOW, NONE); + PMP_ENTRY_SET(5, (int)&_iram_text_end, PMP_TOR | RX); + PMP_ENTRY_SET(6, SOC_DRAM_HIGH, PMP_TOR | RW); #else - // 5. IRAM and DRAM - // const uint32_t pmpaddr5 = PMPADDR_NAPOT(SOC_IRAM_LOW, SOC_IRAM_HIGH); - const uint32_t pmpaddr5 = PMPADDR_NAPOT(SOC_IRAM_LOW, 0x40880000); - PMP_ENTRY_SET(5, pmpaddr5, PMP_NAPOT | CONDITIONAL_RWX); + PMP_ENTRY_SET(4, SOC_IRAM_LOW, CONDITIONAL_NONE); + PMP_ENTRY_SET(5, SOC_IRAM_HIGH, PMP_TOR | CONDITIONAL_RWX); _Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region"); #endif } - // 4. I_Cache (flash) - const uint32_t pmpaddr8 = PMPADDR_NAPOT(SOC_IROM_LOW, SOC_IROM_HIGH); - PMP_ENTRY_SET(8, pmpaddr8, PMP_NAPOT | RX); - _Static_assert(SOC_IROM_LOW < SOC_IROM_HIGH, "Invalid I_Cache region"); + // 4. I_Cache / D_Cache (flash) +#if CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT && !BOOTLOADER_BUILD + extern int _instruction_reserved_end; + extern int _rodata_reserved_end; - // 5. D_Cache (flash) - const uint32_t pmpaddr9 = PMPADDR_NAPOT(SOC_DROM_LOW, SOC_DROM_HIGH); - PMP_ENTRY_SET(9, pmpaddr9, PMP_NAPOT | R); - _Static_assert(SOC_DROM_LOW < SOC_DROM_HIGH, "Invalid D_Cache region"); + 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)); - // 6. LP memory + PMP_ENTRY_CFG_RESET(7); + PMP_ENTRY_CFG_RESET(8); + PMP_ENTRY_CFG_RESET(9); + PMP_ENTRY_CFG_RESET(10); + PMP_ENTRY_SET(7, SOC_IROM_LOW, NONE); + PMP_ENTRY_SET(8, irom_resv_end, PMP_TOR | RX); + PMP_ENTRY_SET(9, drom_resv_end, PMP_TOR | R); +#else + const uint32_t pmpaddr7 = PMPADDR_NAPOT(SOC_IROM_LOW, SOC_IROM_HIGH); + // Add the W attribute in the case of PSRAM + PMP_ENTRY_SET(7, pmpaddr7, PMP_NAPOT | CONDITIONAL_RWX); + _Static_assert(SOC_IROM_LOW < SOC_IROM_HIGH, "Invalid I/D_Cache region"); +#endif + + // 5. LP memory #if CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT && !BOOTLOADER_BUILD extern int _rtc_text_end; /* Reset the corresponding PMP config because PMP_ENTRY_SET only sets the given bits @@ -149,26 +195,17 @@ void esp_cpu_configure_region_protection(void) PMP_ENTRY_CFG_RESET(10); PMP_ENTRY_CFG_RESET(11); PMP_ENTRY_CFG_RESET(12); - PMP_ENTRY_CFG_RESET(13); PMP_ENTRY_SET(10, SOC_RTC_IRAM_LOW, NONE); -#if CONFIG_ULP_COPROC_RESERVE_MEM - // First part of LP mem is reserved for coprocessor - PMP_ENTRY_SET(11, SOC_RTC_IRAM_LOW + CONFIG_ULP_COPROC_RESERVE_MEM, PMP_TOR | RW); -#else // CONFIG_ULP_COPROC_RESERVE_MEM - // Repeat same previous entry, to ensure next entry has correct base address (TOR) - PMP_ENTRY_SET(11, SOC_RTC_IRAM_LOW, NONE); -#endif // !CONFIG_ULP_COPROC_RESERVE_MEM - PMP_ENTRY_SET(12, (int)&_rtc_text_end, PMP_TOR | RX); - PMP_ENTRY_SET(13, 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 pmpaddr10 = PMPADDR_NAPOT(SOC_RTC_IRAM_LOW, SOC_RTC_IRAM_HIGH); PMP_ENTRY_SET(10, pmpaddr10, PMP_NAPOT | CONDITIONAL_RWX); _Static_assert(SOC_RTC_IRAM_LOW < SOC_RTC_IRAM_HIGH, "Invalid RTC IRAM region"); #endif - - // 7. Peripheral addresses - const uint32_t pmpaddr14 = PMPADDR_NAPOT(SOC_PERIPHERAL_LOW, SOC_PERIPHERAL_HIGH); - PMP_ENTRY_SET(14, pmpaddr14, PMP_NAPOT | RW); + // 6. Peripheral addresses + 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"); } diff --git a/components/esp_rom/esp32c61/include/esp32c61/rom/rom_layout.h b/components/esp_rom/esp32c61/include/esp32c61/rom/rom_layout.h index a7ae4e0ff7..c6d9fa0481 100644 --- a/components/esp_rom/esp32c61/include/esp32c61/rom/rom_layout.h +++ b/components/esp_rom/esp32c61/include/esp32c61/rom/rom_layout.h @@ -12,6 +12,7 @@ extern "C" { #endif +#define CORE_NUM 1 #define SUPPORT_BTDM 0 #define SUPPORT_BTBB 0 #define SUPPORT_WIFI 1 @@ -28,6 +29,10 @@ typedef struct { void *dram0_rtos_reserved_start; void *stack_sentry; void *stack; +#if (CORE_NUM == 2) + void *stack_sentry_app; + void *stack_app; +#endif #if SUPPORT_BTDM void *data_start_btdm; @@ -58,6 +63,7 @@ typedef struct { void *data_end_interface_net80211; void *bss_start_interface_net80211; void *bss_end_interface_net80211; + void *dram_start_pp; void *dram_end_pp; void *data_start_interface_pp; @@ -83,16 +89,15 @@ typedef struct { #if SUPPORT_USB_DWCOTG void *dram_start_usb_dwcotg_rom; void *dram_end_usb_dwcotg_rom; -#else - //Two reserved members are defined here, so the structure will not be broken, - //please keep in mind that there is no memory can be released between - //dram_start_usb_reserved_rom ~ dram_end_usb_reserved_rom. - void *dram_start_usb_reserved_rom; - void *dram_end_usb_reserved_rom; #endif void *dram_start_uart_rom; void *dram_end_uart_rom; + + void *eh_frame_vaddr_rom; + void *eh_frame_hdr_vaddr_rom; + + void *drom_start; } ets_rom_layout_t; extern const ets_rom_layout_t *const ets_rom_layout_p; diff --git a/components/soc/esp32c61/include/soc/soc.h b/components/soc/esp32c61/include/soc/soc.h index 97d0eafd5c..ab6fe10aac 100644 --- a/components/soc/esp32c61/include/soc/soc.h +++ b/components/soc/esp32c61/include/soc/soc.h @@ -154,9 +154,9 @@ #define SOC_DROM_LOW SOC_IROM_LOW #define SOC_DROM_HIGH SOC_IROM_HIGH #define SOC_IROM_MASK_LOW 0x40000000 -#define SOC_IROM_MASK_HIGH 0x4004AC00 -#define SOC_DROM_MASK_LOW 0x4004AC00 -#define SOC_DROM_MASK_HIGH 0x40070000 +#define SOC_IROM_MASK_HIGH 0x40040000 +#define SOC_DROM_MASK_LOW 0x40000000 +#define SOC_DROM_MASK_HIGH 0x40040000 #define SOC_IRAM_LOW 0x40800000 #define SOC_IRAM_HIGH 0x40850000 #define SOC_DRAM_LOW 0x40800000 diff --git a/components/soc/esp32c61/include/soc/soc_caps.h b/components/soc/esp32c61/include/soc/soc_caps.h index 17d31de5ad..4734aaa005 100644 --- a/components/soc/esp32c61/include/soc/soc_caps.h +++ b/components/soc/esp32c61/include/soc/soc_caps.h @@ -139,7 +139,7 @@ #define SOC_CPU_HAS_PMA 1 #define SOC_CPU_IDRAM_SPLIT_USING_PMP 1 -#define SOC_CPU_PMP_REGION_GRANULARITY 128 // TODO IDF-9580 check when doing PMP bringup +#define SOC_CPU_PMP_REGION_GRANULARITY 128 #define SOC_CPU_HAS_LOCKUP_RESET 1