forked from espressif/esp-idf
Merge branch 'esp32c2/IDRAM_PMP_split' into 'master'
esp32c2: Enable IRAM/DRAM split using PMP Closes IDF-3837 See merge request espressif/esp-idf!18156
This commit is contained in:
@@ -5,6 +5,29 @@
|
|||||||
*/
|
*/
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "esp_cpu.h"
|
#include "esp_cpu.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#if CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT && !BOOTLOADER_BUILD
|
||||||
|
extern int _iram_end;
|
||||||
|
extern int _data_start;
|
||||||
|
#define IRAM_END (int)&_iram_end
|
||||||
|
#define DRAM_START (int)&_data_start
|
||||||
|
#else
|
||||||
|
#define IRAM_END SOC_DIRAM_IRAM_HIGH
|
||||||
|
#define DRAM_START SOC_DIRAM_DRAM_LOW
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BOOTLOADER_BUILD
|
||||||
|
// Without L bit set
|
||||||
|
#define CONDITIONAL_NONE 0x0
|
||||||
|
#define CONDITIONAL_RX PMP_R | PMP_X
|
||||||
|
#define CONDITIONAL_RW PMP_R | PMP_W
|
||||||
|
#else
|
||||||
|
// With L bit set
|
||||||
|
#define CONDITIONAL_NONE NONE
|
||||||
|
#define CONDITIONAL_RX RX
|
||||||
|
#define CONDITIONAL_RW RW
|
||||||
|
#endif
|
||||||
|
|
||||||
void esp_cpu_configure_region_protection(void)
|
void esp_cpu_configure_region_protection(void)
|
||||||
{
|
{
|
||||||
@@ -19,47 +42,71 @@ void esp_cpu_configure_region_protection(void)
|
|||||||
* 3) 3-15 PMPADDR entries be hardcoded to fixed value, 0-2 PMPADDR be programmed to split ID SRAM
|
* 3) 3-15 PMPADDR entries be hardcoded to fixed value, 0-2 PMPADDR be programmed to split ID SRAM
|
||||||
* as IRAM/DRAM. All PMPCFG entryies be available.
|
* as IRAM/DRAM. All PMPCFG entryies be available.
|
||||||
*
|
*
|
||||||
|
* 4) Ideally, PMPADDR 0-2 entries should be configured twice, once during bootloader startup and another during app startup.
|
||||||
|
* However, the CPU currently always executes in machine mode and to enforce these permissions in machine mode, we need
|
||||||
|
* to set the Lock (L) bit but if set once, it cannot be reconfigured. So, we only configure 0-2 PMPADDR during app startup.
|
||||||
*/
|
*/
|
||||||
const unsigned NONE = PMP_L ;
|
const unsigned NONE = PMP_L ;
|
||||||
const unsigned R = PMP_L | PMP_R;
|
const unsigned R = PMP_L | PMP_R;
|
||||||
const unsigned X = PMP_L | PMP_X;
|
const unsigned X = PMP_L | PMP_X;
|
||||||
const unsigned RW = PMP_L | PMP_R | PMP_W;
|
const unsigned RW = PMP_L | PMP_R | PMP_W;
|
||||||
const unsigned RX = PMP_L | PMP_R | PMP_X;
|
const unsigned RX = PMP_L | PMP_R | PMP_X;
|
||||||
const unsigned RWX = PMP_L | PMP_R | PMP_W | PMP_X;
|
const unsigned RWX = PMP_L | PMP_R | PMP_W | PMP_X;
|
||||||
|
|
||||||
|
/* There are 3 configuration scenarios for PMPADDR 0-2
|
||||||
|
*
|
||||||
|
* 1. Bootloader build:
|
||||||
|
* - We cannot set the lock bit as we need to reconfigure it again for the application.
|
||||||
|
* We configure PMPADDR 0-1 to cover entire valid IRAM range and PMPADDR 2-3 to cover entire valid DRAM range.
|
||||||
|
*
|
||||||
|
* 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 accessed via DBUS
|
||||||
|
* and DRAM region cannot be accessed via IBUS. We use _iram_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
|
||||||
|
* - The IRAM-DRAM split is not enabled so we just need to ensure that access to only valid address ranges are successful
|
||||||
|
* so for that we set PMPADDR 0-1 to cover entire valid IRAM range and PMPADDR 2-3 to cover entire DRAM region.
|
||||||
|
* We also lock these entries so the R/W/X permissions are enforced even for machine mode
|
||||||
|
*
|
||||||
|
* PMPADDR 3-15 are hard-coded and are appicable to both, bootloader and application. So we configure and lock
|
||||||
|
* these during BOOTLOADER build itself. During application build, reconfiguration of these PMPADDR entries
|
||||||
|
* are silently ignored by the CPU
|
||||||
|
*/
|
||||||
|
|
||||||
// 1. IRAM
|
// 1. IRAM
|
||||||
PMP_ENTRY_SET(0,SOC_DIRAM_IRAM_LOW, NONE);
|
PMP_ENTRY_SET(0, SOC_DIRAM_IRAM_LOW, CONDITIONAL_NONE);
|
||||||
PMP_ENTRY_SET(1,SOC_DIRAM_IRAM_HIGH, PMP_TOR|RWX); //TODO IRAM/DRAM spilt address
|
PMP_ENTRY_SET(1, IRAM_END, PMP_TOR | CONDITIONAL_RX);
|
||||||
|
|
||||||
// 2. DRAM
|
// 2. DRAM
|
||||||
PMP_ENTRY_SET(2,SOC_DIRAM_DRAM_LOW, NONE); //TODO IRAM/DRAM spilt address
|
PMP_ENTRY_SET(2, DRAM_START, CONDITIONAL_NONE);
|
||||||
PMP_ENTRY_CFG_SET(3,PMP_TOR|RW);
|
PMP_ENTRY_CFG_SET(3, PMP_TOR | CONDITIONAL_RW);
|
||||||
|
|
||||||
// 3. Debug region
|
// 3. Debug region
|
||||||
PMP_ENTRY_CFG_SET(4,PMP_NAPOT|RWX);
|
PMP_ENTRY_CFG_SET(4, PMP_NAPOT | RWX);
|
||||||
|
|
||||||
// 4. DROM (flash dcache)
|
// 4. DROM (flash dcache)
|
||||||
PMP_ENTRY_CFG_SET(5,PMP_NAPOT|R);
|
PMP_ENTRY_CFG_SET(5, PMP_NAPOT | R);
|
||||||
|
|
||||||
// 5. DROM_MASK
|
// 5. DROM_MASK
|
||||||
PMP_ENTRY_CFG_SET(6,NONE);
|
PMP_ENTRY_CFG_SET(6, NONE);
|
||||||
PMP_ENTRY_CFG_SET(7,PMP_TOR|R);
|
PMP_ENTRY_CFG_SET(7, PMP_TOR | R);
|
||||||
|
|
||||||
// 6. IROM_MASK
|
// 6. IROM_MASK
|
||||||
PMP_ENTRY_CFG_SET(8,NONE);
|
PMP_ENTRY_CFG_SET(8, NONE);
|
||||||
PMP_ENTRY_CFG_SET(9,PMP_TOR|RX);
|
PMP_ENTRY_CFG_SET(9, PMP_TOR | RX);
|
||||||
|
|
||||||
// 7. IROM (flash icache)
|
// 7. IROM (flash icache)
|
||||||
PMP_ENTRY_CFG_SET(10,PMP_NAPOT|RX);
|
PMP_ENTRY_CFG_SET(10, PMP_NAPOT | RX);
|
||||||
|
|
||||||
// 8. Peripheral addresses
|
// 8. Peripheral addresses
|
||||||
PMP_ENTRY_CFG_SET(11,PMP_NAPOT|RW);
|
PMP_ENTRY_CFG_SET(11, PMP_NAPOT | RW);
|
||||||
|
|
||||||
// 9. SRAM (used as ICache)
|
// 9. SRAM (used as ICache)
|
||||||
PMP_ENTRY_CFG_SET(12,PMP_NAPOT|X);
|
PMP_ENTRY_CFG_SET(12, PMP_NAPOT | X);
|
||||||
|
|
||||||
// 10. no access to any address below(0x0-0xFFFF_FFFF)
|
// 10. no access to any address below(0x0-0xFFFF_FFFF)
|
||||||
PMP_ENTRY_CFG_SET(13,PMP_NA4|NONE);// last 4 bytes(0xFFFFFFFC)
|
PMP_ENTRY_CFG_SET(13, PMP_NA4 | NONE);// last 4 bytes(0xFFFFFFFC)
|
||||||
PMP_ENTRY_CFG_SET(14,NONE);
|
PMP_ENTRY_CFG_SET(14, NONE);
|
||||||
PMP_ENTRY_CFG_SET(15,PMP_TOR|NONE);
|
PMP_ENTRY_CFG_SET(15, PMP_TOR | NONE);
|
||||||
}
|
}
|
||||||
|
@@ -117,6 +117,18 @@ menu "ESP System Settings"
|
|||||||
|
|
||||||
menu "Memory protection"
|
menu "Memory protection"
|
||||||
|
|
||||||
|
config ESP_SYSTEM_PMP_IDRAM_SPLIT
|
||||||
|
bool "Enable IRAM/DRAM split protection"
|
||||||
|
depends on SOC_CPU_IDRAM_SPLIT_USING_PMP
|
||||||
|
default "y"
|
||||||
|
help
|
||||||
|
If enabled, the CPU watches all the memory access and raises an exception in case
|
||||||
|
of any memory violation. This feature automatically splits
|
||||||
|
the SRAM memory, using PMP, into data and instruction segments and sets Read/Execute permissions
|
||||||
|
for the instruction part (below given splitting address) and Read/Write permissions
|
||||||
|
for the data part (above the splitting address). The memory protection is effective
|
||||||
|
on all access through the IRAM0 and DRAM0 buses.
|
||||||
|
|
||||||
config ESP_SYSTEM_MEMPROT_DEPCHECK
|
config ESP_SYSTEM_MEMPROT_DEPCHECK
|
||||||
bool
|
bool
|
||||||
default y if IDF_TARGET_ESP32S2
|
default y if IDF_TARGET_ESP32S2
|
||||||
|
@@ -151,6 +151,10 @@ config SOC_CPU_WATCHPOINT_SIZE
|
|||||||
hex
|
hex
|
||||||
default 0x80000000
|
default 0x80000000
|
||||||
|
|
||||||
|
config SOC_CPU_IDRAM_SPLIT_USING_PMP
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
config SOC_GDMA_GROUPS
|
config SOC_GDMA_GROUPS
|
||||||
int
|
int
|
||||||
default 1
|
default 1
|
||||||
|
@@ -80,6 +80,8 @@
|
|||||||
|
|
||||||
#define SOC_CPU_WATCHPOINT_SIZE 0x80000000 // bytes
|
#define SOC_CPU_WATCHPOINT_SIZE 0x80000000 // bytes
|
||||||
|
|
||||||
|
#define SOC_CPU_IDRAM_SPLIT_USING_PMP 1
|
||||||
|
|
||||||
/*-------------------------- GDMA CAPS -------------------------------------*/
|
/*-------------------------- GDMA CAPS -------------------------------------*/
|
||||||
#define SOC_GDMA_GROUPS (1U) // Number of GDMA groups
|
#define SOC_GDMA_GROUPS (1U) // Number of GDMA groups
|
||||||
#define SOC_GDMA_PAIRS_PER_GROUP (1U) // Number of GDMA pairs in each group
|
#define SOC_GDMA_PAIRS_PER_GROUP (1U) // Number of GDMA pairs in each group
|
||||||
|
Reference in New Issue
Block a user