Skip to content

Commit

Permalink
Merge branch 'feat/support_memory_protection_for_esp32c61' into 'master'
Browse files Browse the repository at this point in the history
Support memory protection for esp32c61

Closes IDF-9580

See merge request espressif/esp-idf!33103
  • Loading branch information
mahavirj committed Aug 29, 2024
2 parents 89c808c + eec9197 commit 2526ebd
Show file tree
Hide file tree
Showing 11 changed files with 172 additions and 109 deletions.
76 changes: 44 additions & 32 deletions components/esp_hw_support/port/esp32c5/cpu_region_protect.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
*
Expand All @@ -94,7 +96,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
Expand Down Expand Up @@ -128,33 +130,43 @@ 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
extern int _iram_end;
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(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_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
}
Expand All @@ -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

Expand All @@ -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");
}
6 changes: 3 additions & 3 deletions components/esp_hw_support/port/esp32c6/cpu_region_protect.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,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
Expand Down Expand Up @@ -136,7 +136,7 @@ void esp_cpu_configure_region_protection(void)
_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;
extern int _iram_text_end;
// 5. IRAM and DRAM
/* 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
Expand All @@ -145,7 +145,7 @@ void esp_cpu_configure_region_protection(void)
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(6, (int)&_iram_text_end, PMP_TOR | RX);
PMP_ENTRY_SET(7, SOC_DRAM_HIGH, PMP_TOR | RW);
#else
// 5. IRAM and DRAM
Expand Down
Loading

0 comments on commit 2526ebd

Please sign in to comment.