mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
feat(cpu_region_protect): Support memory protection in ESP32-C61
This commit is contained in:
parent
dc61456ad8
commit
eec9197d47
@ -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
|
||||
// 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, 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");
|
||||
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");
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user