mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
Merge branch 'feat/pma_pmp_lock_policy' into 'master'
Stop locking PMP in the bootloader and freeze the entry layout See merge request espressif/esp-idf!50326
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -14,19 +14,7 @@
|
||||
#include "esp_private/esp_psram_extram.h"
|
||||
#endif /* !BOOTLOADER_BUILD && CONFIG_SPIRAM */
|
||||
|
||||
#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
|
||||
#define CONDITIONAL_RWX PMP_R | PMP_W | PMP_X
|
||||
#else
|
||||
// With L bit set
|
||||
#define CONDITIONAL_NONE NONE
|
||||
#define CONDITIONAL_RX RX
|
||||
#define CONDITIONAL_RW RW
|
||||
#define CONDITIONAL_RWX RWX
|
||||
#endif
|
||||
#include "pmp_layout.h"
|
||||
|
||||
#define ALIGN_UP_TO_MMU_PAGE_SIZE(addr) ESP_ALIGN_UP(addr, SOC_MMU_PAGE_SIZE)
|
||||
#define ALIGN_DOWN_TO_MMU_PAGE_SIZE(addr) ESP_ALIGN_DOWN(addr, SOC_MMU_PAGE_SIZE)
|
||||
@@ -92,39 +80,22 @@ static void esp_cpu_configure_invalid_regions(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
void esp_cpu_configure_region_protection(void)
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
static void esp_cpu_configure_valid_regions(void)
|
||||
{
|
||||
/* Notes on implementation:
|
||||
/* There are 3 configuration scenarios for SRAM in the application
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* 3) We use combination of NAPOT (Naturally Aligned Power Of Two) and TOR (top of range)
|
||||
* entries to map all the valid address space, bottom to top. This leaves us with some extra PMP entries
|
||||
* which can be used to provide more granular access
|
||||
*
|
||||
* 4) Entries are grouped in order with some static asserts to try and verify everything is
|
||||
* correct.
|
||||
*/
|
||||
|
||||
/* There are 4 configuration scenarios for SRAM
|
||||
*
|
||||
* 1. Bootloader build:
|
||||
* - We cannot set the lock bit as we need to reconfigure it again for the application.
|
||||
* We configure PMP to cover entire valid IRAM and DRAM range.
|
||||
*
|
||||
* 2. Application build with CONFIG_ESP_SYSTEM_MEMPROT enabled
|
||||
* 1. Application build with CONFIG_ESP_SYSTEM_MEMPROT 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_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_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP disabled
|
||||
* 2. Application build with CONFIG_ESP_SYSTEM_MEMPROT 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 PMP to cover entire valid IRAM and DRAM region.
|
||||
* We also lock these entries so the R/W/X permissions are enforced even for machine mode
|
||||
*
|
||||
* 4. CPU is in OCD debug mode
|
||||
* 3. CPU is in OCD debug mode
|
||||
* - The IRAM-DRAM split is not enabled so that OpenOCD can write and execute from IRAM.
|
||||
* We set PMP to cover entire valid IRAM and DRAM region.
|
||||
* We also lock these entries so the R/W/X permissions are enforced even for machine mode
|
||||
@@ -135,43 +106,33 @@ void esp_cpu_configure_region_protection(void)
|
||||
__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
|
||||
//
|
||||
esp_cpu_configure_invalid_regions();
|
||||
|
||||
/* NOTE: When ESP-TEE is active, only configure invalid memory regions in bootloader
|
||||
* to prevent errors before TEE initialization. TEE will handle all other
|
||||
* memory protection.
|
||||
*/
|
||||
#if CONFIG_SECURE_ENABLE_TEE && BOOTLOADER_BUILD
|
||||
return;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Configure all the valid address regions using PMP
|
||||
//
|
||||
|
||||
// 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);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_CPU_SUBSYSTEM, pmpaddr0, PMP_NAPOT | RWX);
|
||||
_Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region");
|
||||
|
||||
// 2. I/D-ROM
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP
|
||||
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);
|
||||
/* No cfg reset on the two ROM entries, deliberately: v6.0/v6.1
|
||||
* bootloaders lock PMP_ENTRY_ROM_LOW at SOC_IROM_MASK_LOW, so on such
|
||||
* devices the TOR region below spans the ROM text and must keep the X
|
||||
* bit those bootloaders left in PMP_ENTRY_ROM_HIGH. PMP_ENTRY_SET only
|
||||
* ORs cfg bits and cannot clear it; on newer bootloaders (no PMP
|
||||
* writes) the entries are clean and ROM data gets the intended R.
|
||||
*/
|
||||
PMP_ENTRY_SET(PMP_ENTRY_ROM_LOW, drom_start, NONE);
|
||||
PMP_ENTRY_SET(PMP_ENTRY_ROM_HIGH, SOC_DROM_MASK_HIGH, PMP_TOR | R);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
PMP_ENTRY_SET(1, SOC_IROM_MASK_LOW, NONE);
|
||||
PMP_ENTRY_SET(2, SOC_IROM_MASK_HIGH, PMP_TOR | CONDITIONAL_RX);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_ROM_LOW, SOC_IROM_MASK_LOW, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_ROM_HIGH, SOC_IROM_MASK_HIGH, PMP_TOR | RX);
|
||||
_Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region");
|
||||
}
|
||||
|
||||
@@ -180,38 +141,31 @@ void esp_cpu_configure_region_protection(void)
|
||||
// Anti-FI check that cpu is really in ocd mode
|
||||
ESP_FAULT_ASSERT(esp_cpu_dbgr_is_attached());
|
||||
|
||||
PMP_ENTRY_SET(3, SOC_IRAM_LOW, NONE);
|
||||
PMP_ENTRY_SET(4, SOC_IRAM_HIGH, PMP_TOR | RWX);
|
||||
PMP_RESET_AND_ENTRY_SET(3, SOC_IRAM_LOW, NONE);
|
||||
PMP_RESET_AND_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_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP
|
||||
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_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);
|
||||
PMP_RESET_AND_ENTRY_SET(3, SOC_IRAM_LOW, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(4, (int)&_iram_text_end, PMP_TOR | RX);
|
||||
PMP_RESET_AND_ENTRY_SET(5, SOC_DRAM_HIGH, PMP_TOR | RW);
|
||||
#else
|
||||
PMP_ENTRY_SET(3, SOC_IRAM_LOW, CONDITIONAL_NONE);
|
||||
PMP_ENTRY_SET(4, SOC_IRAM_HIGH, PMP_TOR | CONDITIONAL_RWX);
|
||||
PMP_RESET_AND_ENTRY_SET(3, SOC_IRAM_LOW, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(4, SOC_IRAM_HIGH, PMP_TOR | RWX);
|
||||
_Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
|
||||
#endif
|
||||
}
|
||||
|
||||
// 4. I_Cache / D_Cache (flash)
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP
|
||||
extern int _instruction_reserved_end;
|
||||
extern int _rodata_reserved_end;
|
||||
|
||||
const uint32_t page_aligned_irom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)(&_instruction_reserved_end));
|
||||
__attribute__((unused)) const uint32_t page_aligned_drom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)(&_rodata_reserved_end));
|
||||
|
||||
PMP_ENTRY_CFG_RESET(6);
|
||||
PMP_ENTRY_SET(6, SOC_IROM_LOW, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(6, SOC_IROM_LOW, NONE);
|
||||
|
||||
/**
|
||||
Virtual space layout:
|
||||
@@ -238,68 +192,85 @@ void esp_cpu_configure_region_protection(void)
|
||||
if CONFIG_SPIRAM: [_rodata_reserved_end, page_aligned_drom_resv_end + available_psram_heap] in heap / reserved for mapping (RW)
|
||||
*/
|
||||
|
||||
PMP_ENTRY_CFG_RESET(7);
|
||||
PMP_ENTRY_CFG_RESET(8);
|
||||
PMP_ENTRY_CFG_RESET(9);
|
||||
|
||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION
|
||||
PMP_ENTRY_SET(7, (uint32_t)(&_instruction_reserved_end), PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(8, page_aligned_irom_resv_end, PMP_TOR | RW);
|
||||
PMP_RESET_AND_ENTRY_SET(7, (uint32_t)(&_instruction_reserved_end), PMP_TOR | RX);
|
||||
PMP_RESET_AND_ENTRY_SET(8, page_aligned_irom_resv_end, PMP_TOR | RW);
|
||||
#else
|
||||
PMP_ENTRY_SET(7, page_aligned_irom_resv_end, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(8, page_aligned_irom_resv_end, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(7, page_aligned_irom_resv_end, PMP_TOR | RX);
|
||||
PMP_RESET_AND_ENTRY_SET(8, page_aligned_irom_resv_end, NONE);
|
||||
#endif /* CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION */
|
||||
|
||||
#if CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION
|
||||
PMP_ENTRY_SET(9, (uint32_t)(&_rodata_reserved_end), PMP_TOR | R);
|
||||
PMP_RESET_AND_ENTRY_SET(9, (uint32_t)(&_rodata_reserved_end), PMP_TOR | R);
|
||||
#else
|
||||
PMP_ENTRY_SET(9, page_aligned_drom_resv_end, PMP_TOR | R);
|
||||
PMP_RESET_AND_ENTRY_SET(9, page_aligned_drom_resv_end, PMP_TOR | R);
|
||||
#endif /* CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION */
|
||||
|
||||
#if CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION
|
||||
size_t available_psram_heap = esp_psram_get_heap_size_to_protect();
|
||||
PMP_ENTRY_CFG_RESET(10);
|
||||
PMP_ENTRY_SET(10, ESP_ALIGN_UP(page_aligned_drom_resv_end + available_psram_heap, SOC_CPU_PMP_REGION_GRANULARITY), PMP_TOR | RW);
|
||||
PMP_RESET_AND_ENTRY_SET(10, ESP_ALIGN_UP(page_aligned_drom_resv_end + available_psram_heap, SOC_CPU_PMP_REGION_GRANULARITY), PMP_TOR | RW);
|
||||
#endif /* CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION */
|
||||
#else
|
||||
const uint32_t pmpaddr6 = PMPADDR_NAPOT(SOC_IROM_LOW, SOC_IROM_HIGH);
|
||||
// Add the W attribute in the case of PSRAM
|
||||
PMP_ENTRY_SET(6, pmpaddr6, PMP_NAPOT | CONDITIONAL_RWX);
|
||||
PMP_RESET_AND_ENTRY_SET(6, pmpaddr6, PMP_NAPOT | RWX);
|
||||
_Static_assert(SOC_IROM_LOW < SOC_IROM_HIGH, "Invalid I/D_Cache region");
|
||||
#endif
|
||||
|
||||
// 5. LP memory
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP
|
||||
extern int _rtc_text_start;
|
||||
extern int _rtc_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(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_RESET_AND_ENTRY_SET(11, SOC_RTC_IRAM_LOW, NONE);
|
||||
|
||||
// First part of LP mem is reserved for ULP coprocessor
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT_PMP_LP_CORE_RESERVE_MEM_EXEC
|
||||
PMP_ENTRY_SET(12, (int)&_rtc_text_start, PMP_TOR | RWX);
|
||||
PMP_RESET_AND_ENTRY_SET(12, (int)&_rtc_text_start, PMP_TOR | RWX);
|
||||
#else
|
||||
PMP_ENTRY_SET(12, (int)&_rtc_text_start, PMP_TOR | RW);
|
||||
PMP_RESET_AND_ENTRY_SET(12, (int)&_rtc_text_start, PMP_TOR | RW);
|
||||
#endif
|
||||
|
||||
PMP_ENTRY_SET(13, (int)&_rtc_text_end, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(14, SOC_RTC_IRAM_HIGH, PMP_TOR | RW);
|
||||
PMP_RESET_AND_ENTRY_SET(13, (int)&_rtc_text_end, PMP_TOR | RX);
|
||||
PMP_RESET_AND_ENTRY_SET(14, 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);
|
||||
PMP_RESET_AND_ENTRY_SET(11, pmpaddr11, PMP_NAPOT | RWX);
|
||||
_Static_assert(SOC_RTC_IRAM_LOW < SOC_RTC_IRAM_HIGH, "Invalid RTC IRAM region");
|
||||
#endif
|
||||
|
||||
// 6. Peripheral addresses
|
||||
PMP_ENTRY_CFG_RESET(15);
|
||||
const uint32_t pmpaddr15 = PMPADDR_NAPOT(SOC_PERIPHERAL_LOW, SOC_PERIPHERAL_HIGH);
|
||||
PMP_ENTRY_SET(15, pmpaddr15, PMP_NAPOT | RW);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_PERIPHERAL, pmpaddr15, PMP_NAPOT | RW);
|
||||
_Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region");
|
||||
}
|
||||
#endif // BOOTLOADER_BUILD
|
||||
|
||||
void esp_cpu_configure_region_protection(void)
|
||||
{
|
||||
/* Notes on implementation:
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* 3) We use combination of NAPOT (Naturally Aligned Power Of Two) and TOR (top of range)
|
||||
* entries to map all the valid address space, bottom to top. This leaves us with some extra PMP entries
|
||||
* which can be used to provide more granular access
|
||||
*
|
||||
* 4) Entries are grouped in order with some static asserts to try and verify everything is
|
||||
* correct.
|
||||
*/
|
||||
|
||||
/* The invalid (PMA) regions are configured in both the bootloader and the
|
||||
* application; the valid (PMP) regions are configured and locked by the
|
||||
* application only (an unlocked PMP entry does not apply to M-mode, and a
|
||||
* locked one would survive into the application with no way to reconfigure
|
||||
* it until the next CPU reset). */
|
||||
esp_cpu_configure_invalid_regions();
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
esp_cpu_configure_valid_regions();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "esp_assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ESP32-C5 PMP entry layout: a bootloader<->application ABI. An entry the
|
||||
* (non-updatable) bootloader locks cannot be reconfigured until CPU reset, so
|
||||
* the index of any entry a shipped bootloader locks is frozen.
|
||||
*
|
||||
* Entries locked by shipped bootloader generations (MP baseline v5.5):
|
||||
* v5.5 : 0, 1-2 (ROM), 15 (peripherals)
|
||||
* v6.0 / v6.1 : 0, 1 (ROM), 15 (peripherals)
|
||||
* >= v6.2 : none
|
||||
*/
|
||||
#define PMP_ENTRY_CPU_SUBSYSTEM 0 /* NAPOT RWX */
|
||||
#define PMP_ENTRY_ROM_LOW 1 /* TOR base */
|
||||
#define PMP_ENTRY_ROM_HIGH 2 /* TOR R or RX */
|
||||
/* 3..14: application-owned SRAM/flash/LP-RAM split, programmed by plain index
|
||||
* in cpu_region_protect.c; not part of the ABI, not frozen here. */
|
||||
#define PMP_ENTRY_PERIPHERAL 15 /* NAPOT RW */
|
||||
|
||||
ESP_STATIC_ASSERT(PMP_ENTRY_CPU_SUBSYSTEM == 0
|
||||
&& PMP_ENTRY_ROM_LOW == 1 && PMP_ENTRY_ROM_HIGH == 2
|
||||
&& PMP_ENTRY_PERIPHERAL == 15,
|
||||
"Entries locked by shipped bootloaders are a frozen ABI and must never move");
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -10,22 +10,7 @@
|
||||
#include "esp_cpu.h"
|
||||
#include "esp_fault.h"
|
||||
#include "esp_macros.h"
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
// Without L bit set
|
||||
#define CONDITIONAL_NONE 0x0
|
||||
#define CONDITIONAL_R PMP_R
|
||||
#define CONDITIONAL_RX PMP_R | PMP_X
|
||||
#define CONDITIONAL_RW PMP_R | PMP_W
|
||||
#define CONDITIONAL_RWX PMP_R | PMP_W | PMP_X
|
||||
#else
|
||||
// With L bit set
|
||||
#define CONDITIONAL_NONE NONE
|
||||
#define CONDITIONAL_R R
|
||||
#define CONDITIONAL_RX RX
|
||||
#define CONDITIONAL_RW RW
|
||||
#define CONDITIONAL_RWX RWX
|
||||
#endif
|
||||
#include "pmp_layout.h"
|
||||
|
||||
#define ALIGN_UP_TO_MMU_PAGE_SIZE(addr) ESP_ALIGN_UP(addr, SOC_MMU_PAGE_SIZE)
|
||||
#define ALIGN_DOWN_TO_MMU_PAGE_SIZE(addr) ESP_ALIGN_DOWN(addr, SOC_MMU_PAGE_SIZE)
|
||||
@@ -69,6 +54,125 @@ static void esp_cpu_configure_invalid_regions(void)
|
||||
PMA_ENTRY_CFG_RESET(15);
|
||||
}
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
static void esp_cpu_configure_valid_regions(void)
|
||||
{
|
||||
/* There are 3 configuration scenarios for SRAM in the application
|
||||
*
|
||||
* 1. Application build with CONFIG_ESP_SYSTEM_MEMPROT 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_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
|
||||
*
|
||||
* 2. Application build with CONFIG_ESP_SYSTEM_MEMPROT 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 PMP to cover entire valid IRAM and DRAM region.
|
||||
* We also lock these entries so the R/W/X permissions are enforced even for machine mode
|
||||
*
|
||||
* 3. CPU is in OCD debug mode
|
||||
* - The IRAM-DRAM split is not enabled so that OpenOCD can write and execute from IRAM.
|
||||
* We set PMP to cover entire valid IRAM and DRAM region.
|
||||
* We also lock these entries so the R/W/X permissions are enforced even for machine mode
|
||||
*/
|
||||
const unsigned NONE = PMP_L;
|
||||
__attribute__((unused)) 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;
|
||||
|
||||
// 1. CPU Subsystem region - contains debug mode code and interrupt config registers
|
||||
const uint32_t pmpaddr0 = PMPADDR_NAPOT(SOC_CPU_SUBSYSTEM_LOW, SOC_CPU_SUBSYSTEM_HIGH);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_CPU_SUBSYSTEM, pmpaddr0, PMP_NAPOT | RWX);
|
||||
_Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region");
|
||||
|
||||
// 2.1 I-ROM
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_IROM_LOW, SOC_IROM_MASK_LOW, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_IROM_HIGH, 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 - redundant with the I-ROM entry above (same range, already
|
||||
* locked RX); kept as a separate pair only to pin the app's IRAM/DRAM split
|
||||
* to entries 5-7.
|
||||
*
|
||||
* C6's ROM mask is not a power of two, so ROM needs a TOR pair on entries
|
||||
* 1-2. Commit d4167fea60c (v6.0) dropped this D-ROM pair and moved the split
|
||||
* down onto entries 3-4 - which bootloaders up to v5.2.1 lock as D-ROM. A
|
||||
* locked PMP entry can't be reconfigured until CPU reset, so such an app
|
||||
* can't gain IRAM execute permission and resets before app_main().
|
||||
* v5.2.2 freed 3-4, so only pre-v5.2.2 C6 bootloaders break.
|
||||
*/
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_DROM_LOW, SOC_DROM_MASK_LOW, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_DROM_HIGH, SOC_DROM_MASK_HIGH, PMP_TOR | R);
|
||||
_Static_assert(SOC_DROM_MASK_LOW < SOC_DROM_MASK_HIGH, "Invalid D-ROM region");
|
||||
|
||||
if (esp_cpu_dbgr_is_attached()) {
|
||||
// Anti-FI check that cpu is really in ocd mode
|
||||
ESP_FAULT_ASSERT(esp_cpu_dbgr_is_attached());
|
||||
|
||||
// 3. IRAM and DRAM
|
||||
const uint32_t pmpaddr5 = PMPADDR_NAPOT(SOC_IRAM_LOW, SOC_IRAM_HIGH);
|
||||
PMP_RESET_AND_ENTRY_SET(5, pmpaddr5, PMP_NAPOT | RWX);
|
||||
_Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
|
||||
} else {
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP
|
||||
extern int _iram_text_end;
|
||||
// 3. IRAM and DRAM
|
||||
PMP_RESET_AND_ENTRY_SET(5, SOC_IRAM_LOW, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(6, (int)&_iram_text_end, PMP_TOR | RX);
|
||||
PMP_RESET_AND_ENTRY_SET(7, SOC_DRAM_HIGH, PMP_TOR | RW);
|
||||
#else
|
||||
// 3. IRAM and DRAM
|
||||
const uint32_t pmpaddr5 = PMPADDR_NAPOT(SOC_IRAM_LOW, SOC_IRAM_HIGH);
|
||||
PMP_RESET_AND_ENTRY_SET(5, pmpaddr5, PMP_NAPOT | RWX);
|
||||
_Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP
|
||||
extern int _instruction_reserved_end;
|
||||
extern int _rodata_reserved_end;
|
||||
|
||||
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));
|
||||
|
||||
// 4. I_Cache / D_Cache (flash)
|
||||
PMP_RESET_AND_ENTRY_SET(8, SOC_IROM_LOW, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(9, irom_resv_end, PMP_TOR | RX);
|
||||
PMP_RESET_AND_ENTRY_SET(10, drom_resv_end, PMP_TOR | R);
|
||||
#else
|
||||
// 4. I_Cache / D_Cache (flash)
|
||||
const uint32_t pmpaddr8 = PMPADDR_NAPOT(SOC_IROM_LOW, SOC_IROM_HIGH);
|
||||
PMP_RESET_AND_ENTRY_SET(8, pmpaddr8, PMP_NAPOT | RX);
|
||||
_Static_assert(SOC_IROM_LOW < SOC_IROM_HIGH, "Invalid I/D_Cache region");
|
||||
#endif
|
||||
|
||||
// 5. LP memory
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP
|
||||
extern int _rtc_text_start;
|
||||
extern int _rtc_text_end;
|
||||
PMP_RESET_AND_ENTRY_SET(11, SOC_RTC_IRAM_LOW, NONE);
|
||||
|
||||
// First part of LP mem is reserved for ULP coprocessor
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT_PMP_LP_CORE_RESERVE_MEM_EXEC
|
||||
PMP_RESET_AND_ENTRY_SET(12, (int)&_rtc_text_start, PMP_TOR | RWX);
|
||||
#else
|
||||
PMP_RESET_AND_ENTRY_SET(12, (int)&_rtc_text_start, PMP_TOR | RW);
|
||||
#endif
|
||||
PMP_RESET_AND_ENTRY_SET(13, (int)&_rtc_text_end, PMP_TOR | RX);
|
||||
PMP_RESET_AND_ENTRY_SET(14, SOC_RTC_IRAM_HIGH, PMP_TOR | RW);
|
||||
#else
|
||||
const uint32_t pmpaddr11 = PMPADDR_NAPOT(SOC_RTC_IRAM_LOW, SOC_RTC_IRAM_HIGH);
|
||||
PMP_RESET_AND_ENTRY_SET(11, pmpaddr11, PMP_NAPOT | 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_RESET_AND_ENTRY_SET(PMP_ENTRY_PERIPHERAL, pmpaddr15, PMP_NAPOT | RW);
|
||||
_Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region");
|
||||
}
|
||||
#endif // BOOTLOADER_BUILD
|
||||
|
||||
void esp_cpu_configure_region_protection(void)
|
||||
{
|
||||
/* Notes on implementation:
|
||||
@@ -85,162 +189,14 @@ void esp_cpu_configure_region_protection(void)
|
||||
* correct.
|
||||
*/
|
||||
|
||||
/* There are 4 configuration scenarios for SRAM
|
||||
*
|
||||
* 1. Bootloader build:
|
||||
* - We cannot set the lock bit as we need to reconfigure it again for the application.
|
||||
* We configure PMP to cover entire valid IRAM and DRAM range.
|
||||
*
|
||||
* 2. Application build with CONFIG_ESP_SYSTEM_MEMPROT 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_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_MEMPROT 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 PMP to cover entire valid IRAM and DRAM region.
|
||||
* We also lock these entries so the R/W/X permissions are enforced even for machine mode
|
||||
*
|
||||
* 4. CPU is in OCD debug mode
|
||||
* - The IRAM-DRAM split is not enabled so that OpenOCD can write and execute from IRAM.
|
||||
* We set PMP to cover entire valid IRAM and DRAM region.
|
||||
* We also lock these entries so the R/W/X permissions are enforced even for machine mode
|
||||
*/
|
||||
const unsigned NONE = PMP_L;
|
||||
__attribute__((unused)) 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;
|
||||
|
||||
//
|
||||
// Configure all the invalid address regions using PMA
|
||||
//
|
||||
/* The invalid (PMA) regions are configured in both the bootloader and the
|
||||
* application; the valid (PMP) regions are configured and locked by the
|
||||
* application only (an unlocked PMP entry does not apply to M-mode, and a
|
||||
* locked one would survive into the application with no way to reconfigure
|
||||
* it until the next CPU reset). */
|
||||
esp_cpu_configure_invalid_regions();
|
||||
|
||||
/* NOTE: When ESP-TEE is active, only configure invalid memory regions in bootloader
|
||||
* to prevent errors before TEE initialization. TEE will handle all other
|
||||
* memory protection.
|
||||
*/
|
||||
#if CONFIG_SECURE_ENABLE_TEE && BOOTLOADER_BUILD
|
||||
return;
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
esp_cpu_configure_valid_regions();
|
||||
#endif
|
||||
|
||||
//
|
||||
// Configure all the valid address regions using PMP
|
||||
//
|
||||
|
||||
// 1. CPU Subsystem region - contains debug mode code and 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 - redundant with the I-ROM entry above (same range, already
|
||||
* locked RX); kept as a separate pair only to pin the app's IRAM/DRAM split
|
||||
* to entries 5-7.
|
||||
*
|
||||
* C6's ROM mask is not a power of two, so ROM needs a TOR pair on entries
|
||||
* 1-2. Commit d4167fea60c (v6.0) dropped this D-ROM pair and moved the split
|
||||
* down onto entries 3-4 - which bootloaders up to v5.2.1 lock as D-ROM. A
|
||||
* locked PMP entry can't be reconfigured until CPU reset, so such an app
|
||||
* can't gain IRAM execute permission and resets before app_main() (GitHub
|
||||
* #18769). v5.2.2 freed 3-4, so only pre-v5.2.2 C6 bootloaders break.
|
||||
*
|
||||
* CFG_RESET clears stale config a v6.0/v6.0.1 bootloader left here
|
||||
* (PMP_ENTRY_SET only ORs bits); no-op once 3-4 are locked. CONDITIONAL_*
|
||||
* keeps 3-4 locked in the app but unlocked in the bootloader (redundant, so
|
||||
* no protection lost), letting a future app reclaim them once pre-v5.2.2
|
||||
* bootloaders are out of support.
|
||||
*/
|
||||
PMP_ENTRY_CFG_RESET(3);
|
||||
PMP_ENTRY_CFG_RESET(4);
|
||||
PMP_ENTRY_SET(3, SOC_DROM_MASK_LOW, CONDITIONAL_NONE);
|
||||
PMP_ENTRY_SET(4, SOC_DROM_MASK_HIGH, PMP_TOR | CONDITIONAL_R);
|
||||
_Static_assert(SOC_DROM_MASK_LOW < SOC_DROM_MASK_HIGH, "Invalid D-ROM region");
|
||||
|
||||
if (esp_cpu_dbgr_is_attached()) {
|
||||
// Anti-FI check that cpu is really in ocd mode
|
||||
ESP_FAULT_ASSERT(esp_cpu_dbgr_is_attached());
|
||||
|
||||
// 3. IRAM and DRAM
|
||||
const uint32_t pmpaddr5 = PMPADDR_NAPOT(SOC_IRAM_LOW, SOC_IRAM_HIGH);
|
||||
PMP_ENTRY_SET(5, pmpaddr5, PMP_NAPOT | RWX);
|
||||
_Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
|
||||
} else {
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD
|
||||
extern int _iram_text_end;
|
||||
// 3. 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
|
||||
*/
|
||||
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);
|
||||
#else
|
||||
// 3. IRAM and DRAM
|
||||
const uint32_t pmpaddr5 = PMPADDR_NAPOT(SOC_IRAM_LOW, SOC_IRAM_HIGH);
|
||||
PMP_ENTRY_SET(5, pmpaddr5, PMP_NAPOT | CONDITIONAL_RWX);
|
||||
_Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD
|
||||
extern int _instruction_reserved_end;
|
||||
extern int _rodata_reserved_end;
|
||||
|
||||
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));
|
||||
|
||||
// 4. I_Cache / D_Cache (flash)
|
||||
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);
|
||||
#else
|
||||
// 4. I_Cache / D_Cache (flash)
|
||||
const uint32_t pmpaddr8 = PMPADDR_NAPOT(SOC_IROM_LOW, SOC_IROM_HIGH);
|
||||
PMP_ENTRY_SET(8, pmpaddr8, PMP_NAPOT | CONDITIONAL_RX);
|
||||
_Static_assert(SOC_IROM_LOW < SOC_IROM_HIGH, "Invalid I/D_Cache region");
|
||||
#endif
|
||||
|
||||
// 5. LP memory
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD
|
||||
extern int _rtc_text_start;
|
||||
extern int _rtc_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(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);
|
||||
|
||||
// First part of LP mem is reserved for ULP coprocessor
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT_PMP_LP_CORE_RESERVE_MEM_EXEC
|
||||
PMP_ENTRY_SET(12, (int)&_rtc_text_start, PMP_TOR | RWX);
|
||||
#else
|
||||
PMP_ENTRY_SET(12, (int)&_rtc_text_start, PMP_TOR | RW);
|
||||
#endif
|
||||
PMP_ENTRY_SET(13, (int)&_rtc_text_end, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(14, 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);
|
||||
_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);
|
||||
_Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "esp_assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ESP32-C6 PMP entry layout: a bootloader<->application ABI. An entry the
|
||||
* (non-updatable) bootloader locks cannot be reconfigured until CPU reset, so
|
||||
* the index of any entry a shipped bootloader locks is frozen.
|
||||
* The layout below matches v5.2.2..v5.5; older generations that locked a
|
||||
* different value on a shared index cannot be helped (their lock wins).
|
||||
*
|
||||
* Entries locked by shipped bootloader generations:
|
||||
* <= v5.2.1 : 0, 1-2 (I-ROM), 3-4 (D-ROM), 8-9 (cache), 14 (periph)
|
||||
* v5.2.2 .. v5.5 : 0, 1-2 (I-ROM), 15 (peripherals)
|
||||
* v6.0 / v6.1 : 0, 1-2 (I-ROM), 13 (peripherals)
|
||||
* >= v6.2 : none
|
||||
*/
|
||||
#define PMP_ENTRY_CPU_SUBSYSTEM 0 /* NAPOT RWX */
|
||||
#define PMP_ENTRY_IROM_LOW 1 /* TOR base */
|
||||
#define PMP_ENTRY_IROM_HIGH 2 /* TOR RX */
|
||||
#define PMP_ENTRY_DROM_LOW 3 /* TOR base (locked by <= v5.2.1) */
|
||||
#define PMP_ENTRY_DROM_HIGH 4 /* TOR R (locked by <= v5.2.1) */
|
||||
/* 5..14: application-owned SRAM/flash/LP-RAM split, programmed by plain index
|
||||
* in cpu_region_protect.c; not part of the ABI, not frozen here. */
|
||||
#define PMP_ENTRY_PERIPHERAL 15 /* NAPOT RW */
|
||||
|
||||
ESP_STATIC_ASSERT(PMP_ENTRY_CPU_SUBSYSTEM == 0
|
||||
&& PMP_ENTRY_IROM_LOW == 1 && PMP_ENTRY_IROM_HIGH == 2
|
||||
&& PMP_ENTRY_DROM_LOW == 3 && PMP_ENTRY_DROM_HIGH == 4
|
||||
&& PMP_ENTRY_PERIPHERAL == 15,
|
||||
"Entries locked by shipped bootloaders are a frozen ABI and must never move");
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -15,19 +15,7 @@
|
||||
#include "esp_private/esp_psram_extram.h"
|
||||
#endif /* !BOOTLOADER_BUILD && CONFIG_SPIRAM */
|
||||
|
||||
#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
|
||||
#define CONDITIONAL_RWX PMP_R | PMP_W | PMP_X
|
||||
#else
|
||||
// With L bit set
|
||||
#define CONDITIONAL_NONE NONE
|
||||
#define CONDITIONAL_RX RX
|
||||
#define CONDITIONAL_RW RW
|
||||
#define CONDITIONAL_RWX RWX
|
||||
#endif
|
||||
#include "pmp_layout.h"
|
||||
|
||||
#define ALIGN_UP_TO_MMU_PAGE_SIZE(addr) ESP_ALIGN_UP(addr, SOC_MMU_PAGE_SIZE)
|
||||
#define ALIGN_DOWN_TO_MMU_PAGE_SIZE(addr) ESP_ALIGN_DOWN(addr, SOC_MMU_PAGE_SIZE)
|
||||
@@ -76,39 +64,22 @@ static void esp_cpu_configure_invalid_regions(void)
|
||||
PMA_ENTRY_CFG_RESET(15);
|
||||
}
|
||||
|
||||
void esp_cpu_configure_region_protection(void)
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
static void esp_cpu_configure_valid_regions(void)
|
||||
{
|
||||
/* Notes on implementation:
|
||||
/* There are 3 configuration scenarios for SRAM in the application
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* 3) We use combination of NAPOT (Naturally Aligned Power Of Two) and TOR (top of range)
|
||||
* entries to map all the valid address space, bottom to top. This leaves us with some extra PMP entries
|
||||
* which can be used to provide more granular access
|
||||
*
|
||||
* 4) Entries are grouped in order with some static asserts to try and verify everything is
|
||||
* correct.
|
||||
*/
|
||||
|
||||
/* There are 4 configuration scenarios for SRAM
|
||||
*
|
||||
* 1. Bootloader build:
|
||||
* - We cannot set the lock bit as we need to reconfigure it again for the application.
|
||||
* We configure PMP to cover entire valid IRAM and DRAM range.
|
||||
*
|
||||
* 2. Application build with CONFIG_ESP_SYSTEM_MEMPROT enabled
|
||||
* 1. Application build with CONFIG_ESP_SYSTEM_MEMPROT 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_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_MEMPROT disabled
|
||||
* 2. Application build with CONFIG_ESP_SYSTEM_MEMPROT 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 PMP to cover entire valid IRAM and DRAM region.
|
||||
* We also lock these entries so the R/W/X permissions are enforced even for machine mode
|
||||
*
|
||||
* 4. CPU is in OCD debug mode
|
||||
* 3. CPU is in OCD debug mode
|
||||
* - The IRAM-DRAM split is not enabled so that OpenOCD can write and execute from IRAM.
|
||||
* We set PMP to cover entire valid IRAM and DRAM region.
|
||||
* We also lock these entries so the R/W/X permissions are enforced even for machine mode
|
||||
@@ -119,40 +90,23 @@ void esp_cpu_configure_region_protection(void)
|
||||
__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
|
||||
//
|
||||
esp_cpu_configure_invalid_regions();
|
||||
|
||||
/* NOTE: When ESP-TEE is active, only configure invalid memory regions in bootloader
|
||||
* to prevent errors before TEE initialization. TEE will handle all other
|
||||
* memory protection.
|
||||
*/
|
||||
#if CONFIG_SECURE_ENABLE_TEE && BOOTLOADER_BUILD
|
||||
return;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Configure all the valid address regions using PMP
|
||||
//
|
||||
|
||||
// 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);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_CPU_SUBSYSTEM, pmpaddr0, PMP_NAPOT | RWX);
|
||||
_Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region");
|
||||
|
||||
// 2. I/D-ROM
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP
|
||||
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 | R);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_ROM_LOW, SOC_IROM_MASK_LOW, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_ROM_TEXT_HIGH, drom_start, PMP_TOR | RX);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_ROM_HIGH, SOC_DROM_MASK_HIGH, PMP_TOR | R);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
const uint32_t pmpaddr1 = PMPADDR_NAPOT(SOC_IROM_MASK_LOW, SOC_IROM_MASK_HIGH);
|
||||
PMP_ENTRY_SET(1, pmpaddr1, PMP_NAPOT | CONDITIONAL_RX);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_ROM_LOW, pmpaddr1, PMP_NAPOT | RX);
|
||||
_Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region");
|
||||
}
|
||||
|
||||
@@ -161,38 +115,31 @@ void esp_cpu_configure_region_protection(void)
|
||||
// Anti-FI check that cpu is really in ocd mode
|
||||
ESP_FAULT_ASSERT(esp_cpu_dbgr_is_attached());
|
||||
|
||||
PMP_ENTRY_SET(4, SOC_IRAM_LOW, NONE);
|
||||
PMP_ENTRY_SET(5, SOC_IRAM_HIGH, PMP_TOR | RWX);
|
||||
PMP_RESET_AND_ENTRY_SET(4, SOC_IRAM_LOW, NONE);
|
||||
PMP_RESET_AND_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_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP
|
||||
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_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);
|
||||
PMP_RESET_AND_ENTRY_SET(4, SOC_IRAM_LOW, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(5, (int)&_iram_text_end, PMP_TOR | RX);
|
||||
PMP_RESET_AND_ENTRY_SET(6, SOC_DRAM_HIGH, PMP_TOR | RW);
|
||||
#else
|
||||
PMP_ENTRY_SET(4, SOC_IRAM_LOW, CONDITIONAL_NONE);
|
||||
PMP_ENTRY_SET(5, SOC_IRAM_HIGH, PMP_TOR | CONDITIONAL_RWX);
|
||||
PMP_RESET_AND_ENTRY_SET(4, SOC_IRAM_LOW, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(5, SOC_IRAM_HIGH, PMP_TOR | RWX);
|
||||
_Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
|
||||
#endif
|
||||
}
|
||||
|
||||
// 4. I_Cache / D_Cache (flash)
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP
|
||||
extern int _instruction_reserved_end;
|
||||
extern int _rodata_reserved_end;
|
||||
|
||||
const uint32_t page_aligned_irom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)(&_instruction_reserved_end));
|
||||
__attribute__((unused)) const uint32_t page_aligned_drom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)(&_rodata_reserved_end));
|
||||
|
||||
PMP_ENTRY_CFG_RESET(7);
|
||||
PMP_ENTRY_SET(7, SOC_IROM_LOW, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(7, SOC_IROM_LOW, NONE);
|
||||
|
||||
/**
|
||||
Virtual space layout:
|
||||
@@ -219,38 +166,63 @@ void esp_cpu_configure_region_protection(void)
|
||||
if CONFIG_SPIRAM: [_rodata_reserved_end, page_aligned_drom_resv_end + available_psram_heap] in heap / reserved for mapping (RW)
|
||||
*/
|
||||
|
||||
PMP_ENTRY_CFG_RESET(8);
|
||||
PMP_ENTRY_CFG_RESET(9);
|
||||
PMP_ENTRY_CFG_RESET(10);
|
||||
|
||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION
|
||||
PMP_ENTRY_SET(8, (uint32_t)(&_instruction_reserved_end), PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(9, page_aligned_irom_resv_end, PMP_TOR | RW);
|
||||
PMP_RESET_AND_ENTRY_SET(8, (uint32_t)(&_instruction_reserved_end), PMP_TOR | RX);
|
||||
PMP_RESET_AND_ENTRY_SET(9, page_aligned_irom_resv_end, PMP_TOR | RW);
|
||||
#else
|
||||
PMP_ENTRY_SET(8, page_aligned_irom_resv_end, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(9, page_aligned_irom_resv_end, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(8, page_aligned_irom_resv_end, PMP_TOR | RX);
|
||||
PMP_RESET_AND_ENTRY_SET(9, page_aligned_irom_resv_end, NONE);
|
||||
#endif /* CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION */
|
||||
|
||||
#if CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION
|
||||
PMP_ENTRY_SET(10, (uint32_t)(&_rodata_reserved_end), PMP_TOR | R);
|
||||
PMP_RESET_AND_ENTRY_SET(10, (uint32_t)(&_rodata_reserved_end), PMP_TOR | R);
|
||||
#else
|
||||
PMP_ENTRY_SET(10, page_aligned_drom_resv_end, PMP_TOR | R);
|
||||
PMP_RESET_AND_ENTRY_SET(10, page_aligned_drom_resv_end, PMP_TOR | R);
|
||||
#endif /* CONFIG_SPIRAM_RODATA && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION*/
|
||||
|
||||
#if CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION
|
||||
size_t available_psram_heap = esp_psram_get_heap_size_to_protect();
|
||||
PMP_ENTRY_CFG_RESET(11);
|
||||
PMP_ENTRY_SET(11, ESP_ALIGN_UP(page_aligned_drom_resv_end + available_psram_heap, SOC_CPU_PMP_REGION_GRANULARITY), PMP_TOR | RW);
|
||||
PMP_RESET_AND_ENTRY_SET(11, ESP_ALIGN_UP(page_aligned_drom_resv_end + available_psram_heap, SOC_CPU_PMP_REGION_GRANULARITY), PMP_TOR | RW);
|
||||
#endif /* CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION */
|
||||
#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);
|
||||
PMP_RESET_AND_ENTRY_SET(7, pmpaddr7, PMP_NAPOT | RWX);
|
||||
_Static_assert(SOC_IROM_LOW < SOC_IROM_HIGH, "Invalid I/D_Cache region");
|
||||
#endif
|
||||
|
||||
// 5. Peripheral addresses
|
||||
const uint32_t pmpaddr12 = PMPADDR_NAPOT(SOC_PERIPHERAL_LOW, SOC_PERIPHERAL_HIGH);
|
||||
PMP_ENTRY_SET(12, pmpaddr12, PMP_NAPOT | RW);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_PERIPHERAL, pmpaddr12, PMP_NAPOT | RW);
|
||||
_Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region");
|
||||
}
|
||||
#endif // BOOTLOADER_BUILD
|
||||
|
||||
void esp_cpu_configure_region_protection(void)
|
||||
{
|
||||
/* Notes on implementation:
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* 3) We use combination of NAPOT (Naturally Aligned Power Of Two) and TOR (top of range)
|
||||
* entries to map all the valid address space, bottom to top. This leaves us with some extra PMP entries
|
||||
* which can be used to provide more granular access
|
||||
*
|
||||
* 4) Entries are grouped in order with some static asserts to try and verify everything is
|
||||
* correct.
|
||||
*/
|
||||
|
||||
/* The invalid (PMA) regions are configured in both the bootloader and the
|
||||
* application; the valid (PMP) regions are configured and locked by the
|
||||
* application only (an unlocked PMP entry does not apply to M-mode, and a
|
||||
* locked one would survive into the application with no way to reconfigure
|
||||
* it until the next CPU reset). */
|
||||
esp_cpu_configure_invalid_regions();
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
esp_cpu_configure_valid_regions();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "esp_assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ESP32-C61 PMP entry layout: a bootloader<->application ABI. An entry the
|
||||
* (non-updatable) bootloader locks cannot be reconfigured until CPU reset, so
|
||||
* the index of any entry a shipped bootloader locks is frozen.
|
||||
*
|
||||
* Entries locked by shipped bootloader generations (MP baseline v5.5):
|
||||
* v5.5 : 0, 1-3 (ROM), 12 (peripherals)
|
||||
* v6.0 / v6.1 : 0, 12 (peripherals)
|
||||
* >= v6.2 : none
|
||||
*/
|
||||
#define PMP_ENTRY_CPU_SUBSYSTEM 0 /* NAPOT RWX */
|
||||
#define PMP_ENTRY_ROM_LOW 1 /* TOR base, or NAPOT RX (unaligned branch) */
|
||||
#define PMP_ENTRY_ROM_TEXT_HIGH 2 /* TOR RX (aligned branch) */
|
||||
#define PMP_ENTRY_ROM_HIGH 3 /* TOR R (aligned branch) */
|
||||
/* 4..11: application-owned SRAM/flash split, programmed by plain index in
|
||||
* cpu_region_protect.c; not part of the ABI, not frozen here. */
|
||||
#define PMP_ENTRY_PERIPHERAL 12 /* NAPOT RW */
|
||||
|
||||
ESP_STATIC_ASSERT(PMP_ENTRY_CPU_SUBSYSTEM == 0
|
||||
&& PMP_ENTRY_ROM_LOW == 1 && PMP_ENTRY_ROM_TEXT_HIGH == 2
|
||||
&& PMP_ENTRY_ROM_HIGH == 3
|
||||
&& PMP_ENTRY_PERIPHERAL == 12,
|
||||
"Entries locked by shipped bootloaders are a frozen ABI and must never move");
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -10,22 +10,7 @@
|
||||
#include "esp_cpu.h"
|
||||
#include "esp_fault.h"
|
||||
#include "esp_macros.h"
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
// Without L bit set
|
||||
#define CONDITIONAL_NONE 0x0
|
||||
#define CONDITIONAL_R PMP_R
|
||||
#define CONDITIONAL_RX PMP_R | PMP_X
|
||||
#define CONDITIONAL_RW PMP_R | PMP_W
|
||||
#define CONDITIONAL_RWX PMP_R | PMP_W | PMP_X
|
||||
#else
|
||||
// With L bit set
|
||||
#define CONDITIONAL_NONE NONE
|
||||
#define CONDITIONAL_R R
|
||||
#define CONDITIONAL_RX RX
|
||||
#define CONDITIONAL_RW RW
|
||||
#define CONDITIONAL_RWX RWX
|
||||
#endif
|
||||
#include "pmp_layout.h"
|
||||
|
||||
#define ALIGN_UP_TO_MMU_PAGE_SIZE(addr) ESP_ALIGN_UP(addr, SOC_MMU_PAGE_SIZE)
|
||||
#define ALIGN_DOWN_TO_MMU_PAGE_SIZE(addr) ESP_ALIGN_DOWN(addr, SOC_MMU_PAGE_SIZE)
|
||||
@@ -69,6 +54,118 @@ static void esp_cpu_configure_invalid_regions(void)
|
||||
PMA_ENTRY_CFG_RESET(15);
|
||||
}
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
static void esp_cpu_configure_valid_regions(void)
|
||||
{
|
||||
/* There are 3 configuration scenarios for SRAM in the application
|
||||
*
|
||||
* 1. Application build with CONFIG_ESP_SYSTEM_MEMPROT 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_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
|
||||
*
|
||||
* 2. Application build with CONFIG_ESP_SYSTEM_MEMPROT 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 PMP to cover entire valid IRAM and DRAM region.
|
||||
* We also lock these entries so the R/W/X permissions are enforced even for machine mode
|
||||
*
|
||||
* 3. CPU is in OCD debug mode
|
||||
* - The IRAM-DRAM split is not enabled so that OpenOCD can write and execute from IRAM.
|
||||
* We set PMP to cover entire valid IRAM and DRAM region.
|
||||
* We also lock these entries so the R/W/X permissions are enforced even for machine mode
|
||||
*/
|
||||
const unsigned NONE = PMP_L;
|
||||
__attribute__((unused)) 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;
|
||||
|
||||
// 1. CPU Subsystem region - contains debug mode code and interrupt config registers
|
||||
const uint32_t pmpaddr0 = PMPADDR_NAPOT(SOC_CPU_SUBSYSTEM_LOW, SOC_CPU_SUBSYSTEM_HIGH);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_CPU_SUBSYSTEM, pmpaddr0, PMP_NAPOT | RWX);
|
||||
_Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region");
|
||||
|
||||
// 2.1 I-ROM
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_IROM_LOW, SOC_IROM_MASK_LOW, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_IROM_HIGH, 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 - redundant with the I-ROM entry above (same range, already
|
||||
* locked RX); kept as a separate pair only to pin the app's IRAM/DRAM split
|
||||
* to entries 5-7.
|
||||
*
|
||||
* H2's ROM mask is a power of two, so commit d4167fea60c (v6.0) folded ROM
|
||||
* into a single NAPOT entry (1) and moved the split down onto entry 2 -
|
||||
* which every pre-v6.0 bootloader locks as the I-ROM TOR top. A locked PMP
|
||||
* entry can't be reconfigured until CPU reset, so such an app can't gain
|
||||
* IRAM execute permission and resets before app_main().
|
||||
* ROM was never a single NAPOT before v6.0, so ALL pre-v6.0 bootloaders
|
||||
* break (unlike C6, where only pre-v5.2.2 do).
|
||||
*/
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_DROM_LOW, SOC_DROM_MASK_LOW, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_DROM_HIGH, SOC_DROM_MASK_HIGH, PMP_TOR | R);
|
||||
_Static_assert(SOC_DROM_MASK_LOW < SOC_DROM_MASK_HIGH, "Invalid D-ROM region");
|
||||
|
||||
if (esp_cpu_dbgr_is_attached()) {
|
||||
// Anti-FI check that cpu is really in ocd mode
|
||||
ESP_FAULT_ASSERT(esp_cpu_dbgr_is_attached());
|
||||
|
||||
// 3. IRAM and DRAM
|
||||
PMP_RESET_AND_ENTRY_SET(5, SOC_IRAM_LOW, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(6, SOC_IRAM_HIGH, PMP_TOR | RWX);
|
||||
_Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
|
||||
} else {
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP
|
||||
extern int _iram_text_end;
|
||||
// 3. IRAM and DRAM
|
||||
PMP_RESET_AND_ENTRY_SET(5, SOC_IRAM_LOW, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(6, (int)&_iram_text_end, PMP_TOR | RX);
|
||||
PMP_RESET_AND_ENTRY_SET(7, SOC_DRAM_HIGH, PMP_TOR | RW);
|
||||
#else
|
||||
// 3. IRAM and DRAM
|
||||
PMP_RESET_AND_ENTRY_SET(5, SOC_IRAM_LOW, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(6, SOC_IRAM_HIGH, PMP_TOR | RWX);
|
||||
_Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP
|
||||
extern int _instruction_reserved_end;
|
||||
extern int _rodata_reserved_end;
|
||||
|
||||
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));
|
||||
|
||||
// 4. I_Cache / D_Cache (flash)
|
||||
PMP_RESET_AND_ENTRY_SET(8, SOC_IROM_LOW, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(9, irom_resv_end, PMP_TOR | RX);
|
||||
PMP_RESET_AND_ENTRY_SET(10, drom_resv_end, PMP_TOR | R);
|
||||
#else
|
||||
// 4. I_Cache / D_Cache (flash)
|
||||
const uint32_t pmpaddr8 = PMPADDR_NAPOT(SOC_IROM_LOW, SOC_IROM_HIGH);
|
||||
PMP_RESET_AND_ENTRY_SET(8, pmpaddr8, PMP_NAPOT | RX);
|
||||
_Static_assert(SOC_IROM_LOW < SOC_IROM_HIGH, "Invalid I/D_Cache region");
|
||||
#endif
|
||||
|
||||
// 5. LP memory
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP
|
||||
extern int _rtc_text_end;
|
||||
PMP_RESET_AND_ENTRY_SET(11, SOC_RTC_IRAM_LOW, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(12, (int)&_rtc_text_end, PMP_TOR | RX);
|
||||
PMP_RESET_AND_ENTRY_SET(13, SOC_RTC_IRAM_HIGH, PMP_TOR | RW);
|
||||
#else
|
||||
const uint32_t pmpaddr11 = PMPADDR_NAPOT(SOC_RTC_IRAM_LOW, SOC_RTC_IRAM_HIGH);
|
||||
PMP_RESET_AND_ENTRY_SET(11, pmpaddr11, PMP_NAPOT | RWX);
|
||||
_Static_assert(SOC_RTC_IRAM_LOW < SOC_RTC_IRAM_HIGH, "Invalid RTC IRAM region");
|
||||
#endif
|
||||
|
||||
// 6. Peripheral addresses
|
||||
const uint32_t pmpaddr14 = PMPADDR_NAPOT(SOC_PERIPHERAL_LOW, SOC_PERIPHERAL_HIGH);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_PERIPHERAL, pmpaddr14, PMP_NAPOT | RW);
|
||||
_Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region");
|
||||
}
|
||||
#endif // BOOTLOADER_BUILD
|
||||
|
||||
void esp_cpu_configure_region_protection(void)
|
||||
{
|
||||
/* Notes on implementation:
|
||||
@@ -85,155 +182,14 @@ void esp_cpu_configure_region_protection(void)
|
||||
* correct.
|
||||
*/
|
||||
|
||||
/* There are 4 configuration scenarios for SRAM
|
||||
*
|
||||
* 1. Bootloader build:
|
||||
* - We cannot set the lock bit as we need to reconfigure it again for the application.
|
||||
* We configure PMP to cover entire valid IRAM and DRAM range.
|
||||
*
|
||||
* 2. Application build with CONFIG_ESP_SYSTEM_MEMPROT 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_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_MEMPROT 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 PMP to cover entire valid IRAM and DRAM region.
|
||||
* We also lock these entries so the R/W/X permissions are enforced even for machine mode
|
||||
*
|
||||
* 4. CPU is in OCD debug mode
|
||||
* - The IRAM-DRAM split is not enabled so that OpenOCD can write and execute from IRAM.
|
||||
* We set PMP to cover entire valid IRAM and DRAM region.
|
||||
* We also lock these entries so the R/W/X permissions are enforced even for machine mode
|
||||
*/
|
||||
const unsigned NONE = PMP_L;
|
||||
__attribute__((unused)) 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;
|
||||
|
||||
//
|
||||
// Configure all the invalid address regions using PMA
|
||||
//
|
||||
/* The invalid (PMA) regions are configured in both the bootloader and the
|
||||
* application; the valid (PMP) regions are configured and locked by the
|
||||
* application only (an unlocked PMP entry does not apply to M-mode, and a
|
||||
* locked one would survive into the application with no way to reconfigure
|
||||
* it until the next CPU reset). */
|
||||
esp_cpu_configure_invalid_regions();
|
||||
|
||||
/* NOTE: When ESP-TEE is active, only configure invalid memory regions in bootloader
|
||||
* to prevent errors before TEE initialization. TEE will handle all other
|
||||
* memory protection.
|
||||
*/
|
||||
#if CONFIG_SECURE_ENABLE_TEE && BOOTLOADER_BUILD
|
||||
return;
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
esp_cpu_configure_valid_regions();
|
||||
#endif
|
||||
|
||||
//
|
||||
// Configure all the valid address regions using PMP
|
||||
//
|
||||
|
||||
// 1. CPU Subsystem region - contains debug mode code and 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 - redundant with the I-ROM entry above (same range, already
|
||||
* locked RX); kept as a separate pair only to pin the app's IRAM/DRAM split
|
||||
* to entries 5-7.
|
||||
*
|
||||
* H2's ROM mask is a power of two, so commit d4167fea60c (v6.0) folded ROM
|
||||
* into a single NAPOT entry (1) and moved the split down onto entry 2 -
|
||||
* which every pre-v6.0 bootloader locks as the I-ROM TOR top. A locked PMP
|
||||
* entry can't be reconfigured until CPU reset, so such an app can't gain
|
||||
* IRAM execute permission and resets before app_main() (GitHub #18769).
|
||||
* ROM was never a single NAPOT before v6.0, so ALL pre-v6.0 bootloaders
|
||||
* break (unlike C6, where only pre-v5.2.2 do).
|
||||
*
|
||||
* CFG_RESET clears stale config a v6.0/v6.0.1 bootloader left here
|
||||
* (PMP_ENTRY_SET only ORs bits); no-op once these are locked. CONDITIONAL_*
|
||||
* keeps 3-4 locked in the app but unlocked in the bootloader (redundant, so
|
||||
* no protection lost), letting a future app reclaim them once pre-v5.2.3
|
||||
* bootloaders are out of support.
|
||||
*/
|
||||
PMP_ENTRY_CFG_RESET(3);
|
||||
PMP_ENTRY_CFG_RESET(4);
|
||||
PMP_ENTRY_SET(3, SOC_DROM_MASK_LOW, CONDITIONAL_NONE);
|
||||
PMP_ENTRY_SET(4, SOC_DROM_MASK_HIGH, PMP_TOR | CONDITIONAL_R);
|
||||
_Static_assert(SOC_DROM_MASK_LOW < SOC_DROM_MASK_HIGH, "Invalid D-ROM region");
|
||||
|
||||
if (esp_cpu_dbgr_is_attached()) {
|
||||
// Anti-FI check that cpu is really in ocd mode
|
||||
ESP_FAULT_ASSERT(esp_cpu_dbgr_is_attached());
|
||||
|
||||
// 3. IRAM and DRAM
|
||||
PMP_ENTRY_SET(5, SOC_IRAM_LOW, NONE);
|
||||
PMP_ENTRY_SET(6, SOC_IRAM_HIGH, PMP_TOR | RWX);
|
||||
_Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
|
||||
} else {
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD
|
||||
extern int _iram_text_end;
|
||||
// 3. 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
|
||||
*/
|
||||
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);
|
||||
#else
|
||||
// 3. IRAM and DRAM
|
||||
PMP_ENTRY_SET(5, SOC_IRAM_LOW, CONDITIONAL_NONE);
|
||||
PMP_ENTRY_SET(6, SOC_IRAM_HIGH, PMP_TOR | CONDITIONAL_RWX);
|
||||
_Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD
|
||||
extern int _instruction_reserved_end;
|
||||
extern int _rodata_reserved_end;
|
||||
|
||||
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));
|
||||
|
||||
// 4. I_Cache / D_Cache (flash)
|
||||
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);
|
||||
#else
|
||||
// 4. I_Cache / D_Cache (flash)
|
||||
const uint32_t pmpaddr8 = PMPADDR_NAPOT(SOC_IROM_LOW, SOC_IROM_HIGH);
|
||||
PMP_ENTRY_SET(8, pmpaddr8, PMP_NAPOT | CONDITIONAL_RX);
|
||||
_Static_assert(SOC_IROM_LOW < SOC_IROM_HIGH, "Invalid I/D_Cache region");
|
||||
#endif
|
||||
|
||||
// 5. LP memory
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD
|
||||
extern int _rtc_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(11);
|
||||
PMP_ENTRY_CFG_RESET(12);
|
||||
PMP_ENTRY_CFG_RESET(13);
|
||||
PMP_ENTRY_SET(11, SOC_RTC_IRAM_LOW, NONE);
|
||||
PMP_ENTRY_SET(12, (int)&_rtc_text_end, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(13, 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);
|
||||
_Static_assert(SOC_RTC_IRAM_LOW < SOC_RTC_IRAM_HIGH, "Invalid RTC IRAM region");
|
||||
#endif
|
||||
|
||||
// 6. Peripheral addresses
|
||||
PMP_ENTRY_CFG_RESET(14);
|
||||
const uint32_t pmpaddr14 = PMPADDR_NAPOT(SOC_PERIPHERAL_LOW, SOC_PERIPHERAL_HIGH);
|
||||
PMP_ENTRY_SET(14, pmpaddr14, PMP_NAPOT | RW);
|
||||
_Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "esp_assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ESP32-H2 PMP entry layout: a bootloader<->application ABI. An entry the
|
||||
* (non-updatable) bootloader locks cannot be reconfigured until CPU reset, so
|
||||
* the index of any entry a shipped bootloader locks is frozen.
|
||||
* The layout below matches v5.2.2..v5.5; older generations that locked a
|
||||
* different value on a shared index cannot be helped (their lock wins).
|
||||
*
|
||||
* Entries locked by shipped bootloader generations:
|
||||
* <= v5.2.1 : 0, 1-2 (I-ROM), 3-4 (D-ROM), 8-9 (cache), 13 (periph)
|
||||
* v5.2.2 .. v5.5 : 0, 1-2 (I-ROM), 14 (peripherals)
|
||||
* v6.0 / v6.1 : 0, 1 (ROM), 11 (peripherals)
|
||||
* >= v6.2 : none
|
||||
*/
|
||||
#define PMP_ENTRY_CPU_SUBSYSTEM 0 /* NAPOT RWX */
|
||||
#define PMP_ENTRY_IROM_LOW 1 /* TOR base */
|
||||
#define PMP_ENTRY_IROM_HIGH 2 /* TOR RX */
|
||||
#define PMP_ENTRY_DROM_LOW 3 /* TOR base (locked by <= v5.2.1) */
|
||||
#define PMP_ENTRY_DROM_HIGH 4 /* TOR R (locked by <= v5.2.1) */
|
||||
/* 5..13: application-owned SRAM/flash/LP-RAM split, programmed by plain index
|
||||
* in cpu_region_protect.c; not part of the ABI, not frozen here. */
|
||||
#define PMP_ENTRY_PERIPHERAL 14 /* NAPOT RW */
|
||||
|
||||
ESP_STATIC_ASSERT(PMP_ENTRY_CPU_SUBSYSTEM == 0
|
||||
&& PMP_ENTRY_IROM_LOW == 1 && PMP_ENTRY_IROM_HIGH == 2
|
||||
&& PMP_ENTRY_DROM_LOW == 3 && PMP_ENTRY_DROM_HIGH == 4
|
||||
&& PMP_ENTRY_PERIPHERAL == 14,
|
||||
"Entries locked by shipped bootloaders are a frozen ABI and must never move");
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -18,22 +18,7 @@
|
||||
|
||||
#include "soc/chip_revision.h"
|
||||
#include "hal/config.h"
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
// Without L bit set
|
||||
#define CONDITIONAL_NONE 0x0
|
||||
#define CONDITIONAL_R PMP_R
|
||||
#define CONDITIONAL_RX PMP_R | PMP_X
|
||||
#define CONDITIONAL_RW PMP_R | PMP_W
|
||||
#define CONDITIONAL_RWX PMP_R | PMP_W | PMP_X
|
||||
#else
|
||||
// With L bit set
|
||||
#define CONDITIONAL_NONE NONE
|
||||
#define CONDITIONAL_R R
|
||||
#define CONDITIONAL_RX RX
|
||||
#define CONDITIONAL_RW RW
|
||||
#define CONDITIONAL_RWX RWX
|
||||
#endif
|
||||
#include "pmp_layout.h"
|
||||
|
||||
#define ALIGN_UP_TO_MMU_PAGE_SIZE(addr) ESP_ALIGN_UP(addr, SOC_MMU_PAGE_SIZE)
|
||||
#define ALIGN_DOWN_TO_MMU_PAGE_SIZE(addr) ESP_ALIGN_DOWN(addr, SOC_MMU_PAGE_SIZE)
|
||||
@@ -85,6 +70,7 @@ static void esp_cpu_configure_invalid_regions(void)
|
||||
PMA_RESET_AND_ENTRY_SET_TOR(15, UINT32_MAX, PMA_TOR | PMA_NONE);
|
||||
}
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300
|
||||
// Helper macro to set both cached and non-cached PMP entries with the same permissions
|
||||
#define PMP_ENTRY_SET_CACHED_AND_UNCACHED(cached_entry, non_cached_entry, addr, perm) \
|
||||
@@ -103,7 +89,7 @@ static void esp_cpu_configure_region_protection_rev_v3(void)
|
||||
|
||||
// 1. CPU Subsystem region - contains debug mode code and interrupt config registers
|
||||
const uint32_t pmpaddr0 = PMPADDR_NAPOT(SOC_CPU_SUBSYSTEM_LOW, SOC_CPU_SUBSYSTEM_HIGH);
|
||||
PMP_RESET_AND_ENTRY_SET(0, pmpaddr0, PMP_NAPOT | RW);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_CPU_SUBSYSTEM, pmpaddr0, PMP_NAPOT | RW);
|
||||
_Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region");
|
||||
|
||||
// 2. HP-CPU SPM
|
||||
@@ -111,15 +97,15 @@ static void esp_cpu_configure_region_protection_rev_v3(void)
|
||||
|
||||
// 3. CPU Peripherals
|
||||
const uint32_t pmpaddr1 = PMPADDR_NAPOT(CPU_PERIPH_LOW, CPU_PERIPH_HIGH);
|
||||
PMP_RESET_AND_ENTRY_SET(1, pmpaddr1, PMP_NAPOT | RW);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_CPU_PERIPHERAL, pmpaddr1, PMP_NAPOT | RW);
|
||||
_Static_assert(CPU_PERIPH_LOW < CPU_PERIPH_HIGH, "Invalid CPU peripheral region");
|
||||
|
||||
// 4. I/D-ROM
|
||||
const uint32_t pmpaddr2 = PMPADDR_NAPOT(SOC_IROM_MASK_LOW, SOC_IROM_MASK_HIGH);
|
||||
PMP_RESET_AND_ENTRY_SET(2, pmpaddr2, PMP_NAPOT | RX);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_ROM, pmpaddr2, PMP_NAPOT | RX);
|
||||
|
||||
const uint32_t pmpaddr3 = PMPADDR_NAPOT(CACHE_LL_L2MEM_NON_CACHE_ADDR(SOC_IROM_MASK_LOW), CACHE_LL_L2MEM_NON_CACHE_ADDR(SOC_IROM_MASK_HIGH));
|
||||
PMP_RESET_AND_ENTRY_SET(3, pmpaddr3, PMP_NAPOT | RX);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_ROM_UNCACHED_REV_V3, pmpaddr3, PMP_NAPOT | RX);
|
||||
|
||||
_Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region");
|
||||
|
||||
@@ -133,20 +119,20 @@ static void esp_cpu_configure_region_protection_rev_v3(void)
|
||||
|
||||
_Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
|
||||
} else {
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP
|
||||
extern int _iram_text_end;
|
||||
|
||||
PMP_ENTRY_SET_CACHED_AND_UNCACHED(4, 7, SOC_IRAM_LOW, NONE);
|
||||
PMP_ENTRY_SET_CACHED_AND_UNCACHED(5, 8, (int)&_iram_text_end, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET_CACHED_AND_UNCACHED(6, 9, SOC_DRAM_HIGH, PMP_TOR | RW);
|
||||
#else
|
||||
PMP_ENTRY_SET_CACHED_AND_UNCACHED(4, 6, SOC_IRAM_LOW, CONDITIONAL_NONE);
|
||||
PMP_ENTRY_SET_CACHED_AND_UNCACHED(5, 7, SOC_IRAM_HIGH, PMP_TOR | CONDITIONAL_RWX);
|
||||
PMP_ENTRY_SET_CACHED_AND_UNCACHED(4, 6, SOC_IRAM_LOW, NONE);
|
||||
PMP_ENTRY_SET_CACHED_AND_UNCACHED(5, 7, SOC_IRAM_HIGH, PMP_TOR | RWX);
|
||||
_Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP
|
||||
extern int _instruction_reserved_end;
|
||||
extern int _rodata_reserved_end;
|
||||
|
||||
@@ -198,30 +184,30 @@ static void esp_cpu_configure_region_protection_rev_v3(void)
|
||||
PMP_ENTRY_SET_CACHED_AND_UNCACHED(22, 26, page_aligned_drom_resv_end, PMP_TOR | R);
|
||||
|
||||
#else
|
||||
#if !BOOTLOADER_BUILD && CONFIG_SPIRAM
|
||||
#if CONFIG_SPIRAM
|
||||
const uint32_t pmpaddr10 = PMPADDR_NAPOT(SOC_EXTRAM_LOW, SOC_EXTRAM_HIGH);
|
||||
PMP_RESET_AND_ENTRY_SET(10, pmpaddr10, PMP_NAPOT | CONDITIONAL_RWX);
|
||||
PMP_RESET_AND_ENTRY_SET(10, pmpaddr10, PMP_NAPOT | RWX);
|
||||
|
||||
const uint32_t pmpaddr11 = PMPADDR_NAPOT(CACHE_LL_L2MEM_NON_CACHE_ADDR(SOC_EXTRAM_LOW), CACHE_LL_L2MEM_NON_CACHE_ADDR(SOC_EXTRAM_HIGH));
|
||||
PMP_RESET_AND_ENTRY_SET(11, pmpaddr11, PMP_NAPOT | CONDITIONAL_RWX);
|
||||
PMP_RESET_AND_ENTRY_SET(11, pmpaddr11, PMP_NAPOT | RWX);
|
||||
_Static_assert(SOC_EXTRAM_LOW < SOC_EXTRAM_HIGH, "Invalid I/D_EXTRAM region");
|
||||
#endif /* !BOOTLOADER_BUILD && CONFIG_SPIRAM */
|
||||
#endif /* CONFIG_SPIRAM */
|
||||
|
||||
const uint32_t pmpaddr12 = PMPADDR_NAPOT(SOC_IROM_LOW, SOC_IROM_HIGH);
|
||||
PMP_RESET_AND_ENTRY_SET(12, pmpaddr12, PMP_NAPOT | CONDITIONAL_RX);
|
||||
PMP_RESET_AND_ENTRY_SET(12, pmpaddr12, PMP_NAPOT | RX);
|
||||
|
||||
const uint32_t pmpaddr13 = PMPADDR_NAPOT(CACHE_LL_L2MEM_NON_CACHE_ADDR(SOC_IROM_LOW), CACHE_LL_L2MEM_NON_CACHE_ADDR(SOC_IROM_HIGH));
|
||||
PMP_RESET_AND_ENTRY_SET(13, pmpaddr13, PMP_NAPOT | CONDITIONAL_RX);
|
||||
PMP_RESET_AND_ENTRY_SET(13, pmpaddr13, PMP_NAPOT | RX);
|
||||
_Static_assert(SOC_IROM_LOW < SOC_IROM_HIGH, "Invalid I/D_Cache region");
|
||||
#endif
|
||||
|
||||
// 8. Peripheral addresses
|
||||
const uint32_t pmpaddr27 = PMPADDR_NAPOT(SOC_PERIPHERAL_LOW, SOC_PERIPHERAL_HIGH);
|
||||
PMP_RESET_AND_ENTRY_SET(27, pmpaddr27, PMP_NAPOT | RW);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_PERIPHERAL_REV_V3, pmpaddr27, PMP_NAPOT | RW);
|
||||
_Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region");
|
||||
|
||||
// 9. LP memory and LP peripherals
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP
|
||||
extern int _rtc_text_start;
|
||||
extern int _rtc_text_end;
|
||||
|
||||
@@ -239,35 +225,152 @@ static void esp_cpu_configure_region_protection_rev_v3(void)
|
||||
PMP_RESET_AND_ENTRY_SET(31, SOC_LP_PERIPH_HIGH, PMP_TOR | RW);
|
||||
#else
|
||||
const uint32_t pmpaddr28 = PMPADDR_NAPOT(SOC_RTC_IRAM_LOW, SOC_RTC_IRAM_HIGH);
|
||||
PMP_RESET_AND_ENTRY_SET(28, pmpaddr28, PMP_NAPOT | CONDITIONAL_RWX);
|
||||
PMP_RESET_AND_ENTRY_SET(28, pmpaddr28, PMP_NAPOT | RWX);
|
||||
_Static_assert(SOC_RTC_IRAM_LOW < SOC_RTC_IRAM_HIGH, "Invalid RTC IRAM region");
|
||||
|
||||
PMP_RESET_AND_ENTRY_SET(29, SOC_LP_PERIPH_LOW, NONE);
|
||||
PMP_RESET_AND_ENTRY_SET(30, SOC_LP_PERIPH_HIGH, PMP_TOR | CONDITIONAL_RW);
|
||||
PMP_RESET_AND_ENTRY_SET(30, SOC_LP_PERIPH_HIGH, PMP_TOR | RW);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
// Default rev < 3.0 layout: flash 6-8, LP-RAM 9-12, peripheral 13. Used on a
|
||||
// v5.3/v5.4 bootloader (peripheral locked at 13) or when PSRAM protection is off.
|
||||
static void esp_cpu_configure_region_protection_rev_less_than_v3_default(void)
|
||||
{
|
||||
__attribute__((unused)) const unsigned NONE = PMP_L;
|
||||
__attribute__((unused)) 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;
|
||||
__attribute__((unused)) const unsigned RWX = PMP_L | PMP_R | PMP_W | PMP_X;
|
||||
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP
|
||||
extern int _instruction_reserved_end;
|
||||
extern int _rodata_reserved_end;
|
||||
|
||||
const uint32_t page_aligned_irom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)(&_instruction_reserved_end));
|
||||
const uint32_t page_aligned_drom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)(&_rodata_reserved_end));
|
||||
|
||||
// 5. I_Cache / D_Cache (flash)
|
||||
PMP_ENTRY_CFG_RESET(6);
|
||||
PMP_ENTRY_CFG_RESET(7);
|
||||
PMP_ENTRY_CFG_RESET(8);
|
||||
PMP_ENTRY_SET(6, SOC_IROM_LOW, NONE);
|
||||
PMP_ENTRY_SET(7, page_aligned_irom_resv_end, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(8, page_aligned_drom_resv_end, PMP_TOR | R);
|
||||
#else
|
||||
// 5. I_Cache / D_Cache (flash)
|
||||
const uint32_t pmpaddr6 = PMPADDR_NAPOT(SOC_IROM_LOW, SOC_IROM_HIGH);
|
||||
PMP_ENTRY_SET(6, pmpaddr6, PMP_NAPOT | RX);
|
||||
_Static_assert(SOC_IROM_LOW < SOC_IROM_HIGH, "Invalid I/D_Cache region");
|
||||
#endif
|
||||
|
||||
// 6. LP memory
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP
|
||||
extern int _rtc_text_start;
|
||||
extern int _rtc_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(9);
|
||||
PMP_ENTRY_CFG_RESET(10);
|
||||
PMP_ENTRY_CFG_RESET(11);
|
||||
PMP_ENTRY_CFG_RESET(12);
|
||||
PMP_ENTRY_SET(9, SOC_RTC_IRAM_LOW, NONE);
|
||||
// First part of LP mem is reserved for RTC reserved mem (shared between bootloader and app)
|
||||
// as well as memory for ULP coprocessor
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT_PMP_LP_CORE_RESERVE_MEM_EXEC
|
||||
PMP_ENTRY_SET(10, (int)&_rtc_text_start, PMP_TOR | RWX);
|
||||
#else
|
||||
PMP_ENTRY_SET(10, (int)&_rtc_text_start, PMP_TOR | RW);
|
||||
#endif
|
||||
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 pmpaddr9 = PMPADDR_NAPOT(SOC_RTC_IRAM_LOW, SOC_RTC_IRAM_HIGH);
|
||||
PMP_ENTRY_SET(9, pmpaddr9, PMP_NAPOT | RWX);
|
||||
_Static_assert(SOC_RTC_IRAM_LOW < SOC_RTC_IRAM_HIGH, "Invalid RTC IRAM region");
|
||||
#endif
|
||||
|
||||
// 7. Peripheral addresses
|
||||
const uint32_t pmpaddr13 = PMPADDR_NAPOT(SOC_PERIPHERAL_LOW, SOC_PERIPHERAL_HIGH);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_PERIPHERAL_REV_LESS_THAN_V3, pmpaddr13, PMP_NAPOT | RW);
|
||||
_Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region");
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && CONFIG_SPIRAM_XIP_FROM_PSRAM && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION
|
||||
// PSRAM-protected rev < 3.0 layout: flash/ext-RAM 6-10, LP-RAM 11-14, peripheral
|
||||
// 15. Fits only when the bootloader left entry 13 free (v5.5+).
|
||||
static void esp_cpu_configure_region_protection_rev_less_than_v3_psram(void)
|
||||
{
|
||||
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;
|
||||
__attribute__((unused)) const unsigned RWX = PMP_L | PMP_R | PMP_W | PMP_X;
|
||||
|
||||
extern int _instruction_reserved_end;
|
||||
extern int _rodata_reserved_end;
|
||||
extern int _rtc_text_start;
|
||||
extern int _rtc_text_end;
|
||||
|
||||
const uint32_t page_aligned_irom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)(&_instruction_reserved_end));
|
||||
const uint32_t page_aligned_drom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)(&_rodata_reserved_end));
|
||||
|
||||
// 5. I_Cache / D_Cache (flash) and external RAM
|
||||
PMP_ENTRY_CFG_RESET(6);
|
||||
PMP_ENTRY_CFG_RESET(7);
|
||||
PMP_ENTRY_CFG_RESET(8);
|
||||
PMP_ENTRY_CFG_RESET(9);
|
||||
PMP_ENTRY_SET(6, SOC_EXTRAM_LOW, NONE);
|
||||
PMP_ENTRY_SET(7, (uint32_t)(&_instruction_reserved_end), PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(8, page_aligned_irom_resv_end, PMP_TOR | RW);
|
||||
PMP_ENTRY_SET(9, (uint32_t)(&_rodata_reserved_end), PMP_TOR | R);
|
||||
|
||||
const size_t available_psram_heap = esp_psram_get_heap_size_to_protect();
|
||||
PMP_ENTRY_CFG_RESET(10);
|
||||
PMP_ENTRY_SET(10, ESP_ALIGN_UP(page_aligned_drom_resv_end + available_psram_heap, SOC_CPU_PMP_REGION_GRANULARITY), PMP_TOR | RW);
|
||||
|
||||
// 6. LP memory
|
||||
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);
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT_PMP_LP_CORE_RESERVE_MEM_EXEC
|
||||
PMP_ENTRY_SET(12, (int)&_rtc_text_start, PMP_TOR | RWX);
|
||||
#else
|
||||
PMP_ENTRY_SET(12, (int)&_rtc_text_start, PMP_TOR | RW);
|
||||
#endif
|
||||
PMP_ENTRY_SET(13, (int)&_rtc_text_end, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(14, SOC_RTC_IRAM_HIGH, PMP_TOR | RW);
|
||||
|
||||
// 7. Peripheral addresses
|
||||
const uint32_t pmpaddr15 = PMPADDR_NAPOT(SOC_PERIPHERAL_LOW, SOC_PERIPHERAL_HIGH);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_PERIPHERAL_REV_LESS_THAN_V3_SPIRAM_MEMPROT_EN, pmpaddr15, PMP_NAPOT | RW);
|
||||
_Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region");
|
||||
}
|
||||
#endif
|
||||
|
||||
static void esp_cpu_configure_region_protection_rev_less_than_v3(void)
|
||||
{
|
||||
const unsigned NONE = PMP_L;
|
||||
__attribute__((unused)) 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;
|
||||
|
||||
// 1. CPU Subsystem region - contains debug mode code and interrupt config registers
|
||||
const uint32_t pmpaddr0 = PMPADDR_NAPOT(SOC_CPU_SUBSYSTEM_LOW, SOC_CPU_SUBSYSTEM_HIGH);
|
||||
PMP_ENTRY_SET(0, pmpaddr0, PMP_NAPOT | RW);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_CPU_SUBSYSTEM, pmpaddr0, PMP_NAPOT | RW);
|
||||
_Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region");
|
||||
|
||||
// 2. CPU Peripherals
|
||||
const uint32_t pmpaddr1 = PMPADDR_NAPOT(CPU_PERIPH_LOW, CPU_PERIPH_HIGH);
|
||||
PMP_ENTRY_SET(1, pmpaddr1, PMP_NAPOT | RW);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_CPU_PERIPHERAL, pmpaddr1, PMP_NAPOT | RW);
|
||||
_Static_assert(CPU_PERIPH_LOW < CPU_PERIPH_HIGH, "Invalid CPU peripheral region");
|
||||
|
||||
// 3. I/D-ROM
|
||||
const uint32_t pmpaddr2 = PMPADDR_NAPOT(SOC_IROM_MASK_LOW, SOC_IROM_MASK_HIGH);
|
||||
PMP_ENTRY_SET(2, pmpaddr2, PMP_NAPOT | RX);
|
||||
PMP_RESET_AND_ENTRY_SET(PMP_ENTRY_ROM, pmpaddr2, PMP_NAPOT | RX);
|
||||
_Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region");
|
||||
|
||||
if (esp_cpu_dbgr_is_attached()) {
|
||||
@@ -279,7 +382,7 @@ static void esp_cpu_configure_region_protection_rev_less_than_v3(void)
|
||||
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_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP
|
||||
extern int _iram_text_end;
|
||||
// 4. IRAM and DRAM
|
||||
/* Reset the corresponding PMP config because PMP_ENTRY_SET only sets the given bits
|
||||
@@ -293,85 +396,36 @@ static void esp_cpu_configure_region_protection_rev_less_than_v3(void)
|
||||
PMP_ENTRY_SET(5, SOC_DRAM_HIGH, PMP_TOR | RW);
|
||||
#else
|
||||
// 4. IRAM and DRAM
|
||||
PMP_ENTRY_SET(3, SOC_IRAM_LOW, CONDITIONAL_NONE);
|
||||
PMP_ENTRY_SET(4, SOC_IRAM_HIGH, PMP_TOR | CONDITIONAL_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");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD
|
||||
extern int _instruction_reserved_end;
|
||||
extern int _rodata_reserved_end;
|
||||
|
||||
const uint32_t page_aligned_irom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)(&_instruction_reserved_end));
|
||||
__attribute__((unused)) const uint32_t page_aligned_drom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)(&_rodata_reserved_end));
|
||||
|
||||
// 5. I_Cache / D_Cache (flash)
|
||||
#if CONFIG_SPIRAM_XIP_FROM_PSRAM && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION
|
||||
// We could have split CONFIG_SPIRAM_XIP_FROM_PSRAM into CONFIG_SPIRAM_FETCH_INSTRUCTIONS and CONFIG_SPIRAM_RODATA
|
||||
// but we don't have enough PMP entries to do so thus not allowing us finer control over the memory regions
|
||||
PMP_ENTRY_CFG_RESET(6);
|
||||
PMP_ENTRY_CFG_RESET(7);
|
||||
PMP_ENTRY_CFG_RESET(8);
|
||||
PMP_ENTRY_CFG_RESET(9);
|
||||
|
||||
PMP_ENTRY_SET(6, SOC_EXTRAM_LOW, NONE);
|
||||
PMP_ENTRY_SET(7, (uint32_t)(&_instruction_reserved_end), PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(8, page_aligned_irom_resv_end, PMP_TOR | RW);
|
||||
PMP_ENTRY_SET(9, (uint32_t)(&_rodata_reserved_end), PMP_TOR | R);
|
||||
|
||||
size_t available_psram_heap = esp_psram_get_heap_size_to_protect();
|
||||
PMP_ENTRY_CFG_RESET(10);
|
||||
PMP_ENTRY_SET(10, ESP_ALIGN_UP(page_aligned_drom_resv_end + available_psram_heap, SOC_CPU_PMP_REGION_GRANULARITY), PMP_TOR | RW);
|
||||
#else
|
||||
PMP_ENTRY_CFG_RESET(6);
|
||||
PMP_ENTRY_CFG_RESET(7);
|
||||
PMP_ENTRY_CFG_RESET(8);
|
||||
PMP_ENTRY_SET(6, SOC_IROM_LOW, NONE);
|
||||
PMP_ENTRY_SET(7, page_aligned_irom_resv_end, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(8, page_aligned_drom_resv_end, PMP_TOR | R);
|
||||
#endif /* CONFIG_SPIRAM_XIP_FROM_PSRAM && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION */
|
||||
#else
|
||||
// 5. I_Cache / D_Cache (flash)
|
||||
const uint32_t pmpaddr6 = PMPADDR_NAPOT(SOC_IROM_LOW, SOC_IROM_HIGH);
|
||||
PMP_ENTRY_SET(6, pmpaddr6, PMP_NAPOT | CONDITIONAL_RX);
|
||||
_Static_assert(SOC_IROM_LOW < SOC_IROM_HIGH, "Invalid I/D_Cache region");
|
||||
/* The flash, LP memory and peripheral entries have two layouts. The PSRAM
|
||||
* layout needs all 16 entries and only fits when the bootloader left entry 13
|
||||
* free; a v5.3/v5.4 bootloader locks the peripheral there, so fall back to the
|
||||
* default layout (no PSRAM protection) on those devices. */
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && CONFIG_SPIRAM_XIP_FROM_PSRAM && CONFIG_SPIRAM_PRE_CONFIGURE_MEMORY_PROTECTION
|
||||
if (!(PMP_ENTRY_CFG_READ(PMP_ENTRY_PERIPHERAL_REV_LESS_THAN_V3) & PMP_L)) {
|
||||
esp_cpu_configure_region_protection_rev_less_than_v3_psram();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// 6. LP memory
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT && CONFIG_ESP_SYSTEM_MEMPROT_PMP && !BOOTLOADER_BUILD
|
||||
extern int _rtc_text_start;
|
||||
extern int _rtc_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(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);
|
||||
// First part of LP mem is reserved for RTC reserved mem (shared between bootloader and app)
|
||||
// as well as memory for ULP coprocessor
|
||||
#if CONFIG_ESP_SYSTEM_MEMPROT_PMP_LP_CORE_RESERVE_MEM_EXEC
|
||||
PMP_ENTRY_SET(12, (int)&_rtc_text_start, PMP_TOR | RWX);
|
||||
#else
|
||||
PMP_ENTRY_SET(12, (int)&_rtc_text_start, PMP_TOR | RW);
|
||||
#endif
|
||||
PMP_ENTRY_SET(13, (int)&_rtc_text_end, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(14, 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);
|
||||
_Static_assert(SOC_RTC_IRAM_LOW < SOC_RTC_IRAM_HIGH, "Invalid RTC IRAM region");
|
||||
#endif
|
||||
|
||||
// 7. Peripheral addresses
|
||||
const uint32_t pmpaddr15 = PMPADDR_NAPOT(SOC_PERIPHERAL_LOW, SOC_PERIPHERAL_HIGH);
|
||||
PMP_ENTRY_SET(15, pmpaddr15, PMP_NAPOT | RW);
|
||||
_Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region");
|
||||
esp_cpu_configure_region_protection_rev_less_than_v3_default();
|
||||
}
|
||||
#endif
|
||||
|
||||
static void esp_cpu_configure_valid_regions(void)
|
||||
{
|
||||
#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300
|
||||
esp_cpu_configure_region_protection_rev_v3();
|
||||
#else
|
||||
esp_cpu_configure_region_protection_rev_less_than_v3();
|
||||
#endif
|
||||
}
|
||||
#endif // BOOTLOADER_BUILD
|
||||
|
||||
void esp_cpu_configure_region_protection(void)
|
||||
{
|
||||
/* Notes on implementation:
|
||||
@@ -401,40 +455,14 @@ void esp_cpu_configure_region_protection(void)
|
||||
* c. External flash, External RAM, HP ROM, HP L2MEM (direct access)
|
||||
*/
|
||||
|
||||
/* There are 4 configuration scenarios for SRAM
|
||||
*
|
||||
* 1. Bootloader build:
|
||||
* - We cannot set the lock bit as we need to reconfigure it again for the application.
|
||||
* We configure PMP to cover entire valid IRAM and DRAM range.
|
||||
*
|
||||
* 2. Application build with CONFIG_ESP_SYSTEM_MEMPROT 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_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_MEMPROT 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 PMP to cover entire valid IRAM and DRAM region.
|
||||
* We also lock these entries so the R/W/X permissions are enforced even for machine mode
|
||||
*
|
||||
* 4. CPU is in OCD debug mode
|
||||
* - The IRAM-DRAM split is not enabled so that OpenOCD can write and execute from IRAM.
|
||||
* We set PMP to cover entire valid IRAM and DRAM region.
|
||||
* We also lock these entries so the R/W/X permissions are enforced even for machine mode
|
||||
*/
|
||||
//
|
||||
// Configure all the invalid address regions using PMA
|
||||
//
|
||||
/* The invalid (PMA) regions are configured in both the bootloader and the
|
||||
* application; the valid (PMP) regions are configured and locked by the
|
||||
* application only (an unlocked PMP entry does not apply to M-mode, and a
|
||||
* locked one would survive into the application with no way to reconfigure
|
||||
* it until the next CPU reset). */
|
||||
esp_cpu_configure_invalid_regions();
|
||||
|
||||
//
|
||||
// Configure all the valid address regions using PMP
|
||||
//
|
||||
|
||||
#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300
|
||||
esp_cpu_configure_region_protection_rev_v3();
|
||||
#else
|
||||
esp_cpu_configure_region_protection_rev_less_than_v3();
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
esp_cpu_configure_valid_regions();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "esp_assert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ESP32-P4 PMP entry layout: a bootloader<->application ABI. An entry the
|
||||
* (non-updatable) bootloader locks cannot be reconfigured until CPU reset, so
|
||||
* the index of any entry a shipped bootloader locks is frozen.
|
||||
* Two incompatible layouts selected by chip revision (>= 3.0); binaries do not
|
||||
* mix, so each has its own index namespace. Entries 0-2 are shared.
|
||||
*
|
||||
* Locked by shipped bootloader generations:
|
||||
* rev < 3.0 v5.3/v5.4 : 0-2 (ROM), 13 (periph); v5.5..v6.1 : 0-2, 15
|
||||
* rev >= 3.0 v6.0/v6.1 : 0-3 (ROM cached+uncached), 27 (periph)
|
||||
* >= v6.2 : none
|
||||
*/
|
||||
#define PMP_ENTRY_CPU_SUBSYSTEM 0 /* NAPOT RW, both layouts */
|
||||
#define PMP_ENTRY_CPU_PERIPHERAL 1 /* NAPOT RW, both layouts */
|
||||
#define PMP_ENTRY_ROM 2 /* NAPOT RX, both layouts */
|
||||
|
||||
/* rev < 3.0 has two application layouts, chosen at runtime by probing which
|
||||
* peripheral entry the bootloader locked (see cpu_region_protect.c):
|
||||
* - default : SRAM/flash 3-8, LP-RAM 9-12, peripheral 13; 14-15 free.
|
||||
* - PSRAM-protected : SRAM/flash/ext-RAM 3-10, LP-RAM 11-14, peripheral 15.
|
||||
* The PSRAM layout is taken only on v5.5+ bootloaders (which leave 13 free and
|
||||
* lock the peripheral at 15); a v5.3/v5.4 bootloader locks the peripheral at 13,
|
||||
* forcing the default layout. Entries 13 and 15 are both peripheral homes locked
|
||||
* by shipped bootloaders and must never be repurposed for a non-peripheral region. */
|
||||
#define PMP_ENTRY_PERIPHERAL_REV_LESS_THAN_V3 13 /* NAPOT RW, default layout */
|
||||
#define PMP_ENTRY_PERIPHERAL_REV_LESS_THAN_V3_SPIRAM_MEMPROT_EN 15 /* NAPOT RW, PSRAM layout */
|
||||
|
||||
/* rev >= 3.0: 4..26 (SRAM/ext-RAM/flash cached+uncached aliases) and 28..31
|
||||
* (LP) are application-owned; their indices shift with the memprot config, so
|
||||
* they are programmed by plain index in cpu_region_protect.c, not named here. */
|
||||
#define PMP_ENTRY_ROM_UNCACHED_REV_V3 3 /* NAPOT RX */
|
||||
#define PMP_ENTRY_PERIPHERAL_REV_V3 27 /* NAPOT RW */
|
||||
|
||||
ESP_STATIC_ASSERT(PMP_ENTRY_CPU_SUBSYSTEM == 0 && PMP_ENTRY_CPU_PERIPHERAL == 1
|
||||
&& PMP_ENTRY_ROM == 2,
|
||||
"Shared entries are a frozen ABI and must never move");
|
||||
ESP_STATIC_ASSERT(PMP_ENTRY_PERIPHERAL_REV_LESS_THAN_V3 == 13
|
||||
&& PMP_ENTRY_PERIPHERAL_REV_LESS_THAN_V3_SPIRAM_MEMPROT_EN == 15,
|
||||
"rev < 3.0 peripheral entries are locked by shipped bootloaders and must never move");
|
||||
ESP_STATIC_ASSERT(PMP_ENTRY_ROM_UNCACHED_REV_V3 == 3 && PMP_ENTRY_PERIPHERAL_REV_V3 == 27,
|
||||
"rev >= 3.0 entries locked by shipped bootloaders are a frozen ABI and must never move");
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -24,3 +24,4 @@ ESP-IDF 6.x Migration Guide
|
||||
|
||||
release-6.x/6.0/index
|
||||
release-6.x/6.1/index
|
||||
release-6.x/6.2/index
|
||||
|
||||
9
docs/en/migration-guides/release-6.x/6.2/index.rst
Normal file
9
docs/en/migration-guides/release-6.x/6.2/index.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
Migration from 6.1 to 6.2
|
||||
--------------------------
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
security
|
||||
15
docs/en/migration-guides/release-6.x/6.2/security.rst
Normal file
15
docs/en/migration-guides/release-6.x/6.2/security.rst
Normal file
@@ -0,0 +1,15 @@
|
||||
Security
|
||||
========
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
Memory Protection
|
||||
-----------------
|
||||
|
||||
Starting from **ESP-IDF v6.2**, on ESP32-C5, ESP32-C6, ESP32-C61, ESP32-H2, and ESP32-P4 the second stage bootloader no longer configures or locks any RISC-V PMP entries. The complete PMP configuration is now programmed and locked by the application during early startup.
|
||||
|
||||
A PMP entry locked by the bootloader cannot be reconfigured until the next CPU reset. Since the bootloader on a deployed device is generally never updated, entries locked by an older bootloader could conflict with the PMP layout expected by an application built with a newer ESP-IDF version, leading to boot failures or to memory protection being silently inactive.
|
||||
|
||||
Applications built with ESP-IDF are not affected, as they program and lock the full PMP configuration themselves during startup, before any application code runs.
|
||||
|
||||
Custom (non-ESP-IDF) applications launched by the ESP-IDF second stage bootloader must not assume that any PMP entries are pre-configured or locked at handoff. Previously, the bootloader configured and locked entries covering, e.g., the ROM and the peripheral address spaces; such applications must now program their own PMP configuration.
|
||||
@@ -24,3 +24,4 @@
|
||||
|
||||
release-6.x/6.0/index
|
||||
release-6.x/6.1/index
|
||||
release-6.x/6.2/index
|
||||
|
||||
9
docs/zh_CN/migration-guides/release-6.x/6.2/index.rst
Normal file
9
docs/zh_CN/migration-guides/release-6.x/6.2/index.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
从 6.1 迁移到 6.2
|
||||
------------------
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
security
|
||||
15
docs/zh_CN/migration-guides/release-6.x/6.2/security.rst
Normal file
15
docs/zh_CN/migration-guides/release-6.x/6.2/security.rst
Normal file
@@ -0,0 +1,15 @@
|
||||
安全性
|
||||
======
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
内存保护
|
||||
--------
|
||||
|
||||
从 **ESP-IDF v6.2** 开始,在 ESP32-C5、ESP32-C6、ESP32-C61、ESP32-H2 和 ESP32-P4 上,二级引导加载程序不再配置或锁定任何 RISC-V PMP 表项。完整的 PMP 配置改由应用程序在启动早期编程并锁定。
|
||||
|
||||
被引导加载程序锁定的 PMP 表项在下一次 CPU 复位前无法重新配置。由于已部署设备上的引导加载程序通常不会更新,旧版引导加载程序锁定的表项可能与使用较新 ESP-IDF 版本构建的应用程序所期望的 PMP 布局发生冲突,导致启动失败,或使内存保护在没有任何提示的情况下失效。
|
||||
|
||||
使用 ESP-IDF 构建的应用程序不受影响,因为应用程序会在启动阶段、任何应用代码运行之前,自行编程并锁定完整的 PMP 配置。
|
||||
|
||||
由 ESP-IDF 二级引导加载程序启动的自定义(非 ESP-IDF)应用程序不得假定交接时任何 PMP 表项已被预先配置或锁定。此前,引导加载程序会配置并锁定覆盖 ROM 和外设地址空间等区域的表项;此类应用程序现在必须自行完成 PMP 配置。
|
||||
@@ -610,6 +610,10 @@ def test_panic_handler_crash1(dut: PanicTestDut, config: str, test_func_name: st
|
||||
|
||||
# Memprot-related tests are supported only on targets with PMS/PMA peripheral;
|
||||
# currently ESP32-S2, ESP32-C3, ESP32-C2, ESP32-H2, ESP32-H21, ESP32-C6, ESP32-P4, ESP32-C5 and ESP32-C61 are supported
|
||||
# ESP32-P4 rev < 3.0 runs on a dedicated rev 1.x runner (its binary is built for
|
||||
# and only boots on rev < 3.0 silicon), so its configs carry the esp32p4_rev1 marker.
|
||||
P4_REV_LESS_THAN_V3_MARKER = pytest.mark.esp32p4_rev1
|
||||
|
||||
CONFIGS_MEMPROT_IDRAM = list(
|
||||
zip(
|
||||
[
|
||||
@@ -624,7 +628,9 @@ CONFIGS_MEMPROT_IDRAM = list(
|
||||
],
|
||||
['esp32s2', 'esp32c3', 'esp32c2', 'esp32c5', 'esp32c61', 'esp32h2', 'esp32p4', 'esp32h21'],
|
||||
)
|
||||
)
|
||||
) + [
|
||||
('memprot_esp32p4_rev_less_than_v3', 'esp32p4', P4_REV_LESS_THAN_V3_MARKER),
|
||||
]
|
||||
|
||||
CONFIGS_MEMPROT_IDRAM_L2_MEM_NON_CACHE = list(zip(['memprot_esp32p4'], ['esp32p4']))
|
||||
|
||||
@@ -643,7 +649,9 @@ CONFIGS_MEMPROT_RTC_FAST_MEM = list(
|
||||
],
|
||||
['esp32s2', 'esp32c3', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32h21'],
|
||||
)
|
||||
)
|
||||
) + [
|
||||
('memprot_esp32p4_rev_less_than_v3', 'esp32p4', P4_REV_LESS_THAN_V3_MARKER),
|
||||
]
|
||||
|
||||
CONFIGS_MEMPROT_RTC_SLOW_MEM = list(zip(['memprot_esp32s2'], ['esp32s2']))
|
||||
|
||||
@@ -659,16 +667,24 @@ CONFIGS_MEMPROT_FLASH_IDROM = list(
|
||||
],
|
||||
['esp32c5', 'esp32c6', 'esp32c61', 'esp32h2', 'esp32p4', 'esp32h21'],
|
||||
)
|
||||
)
|
||||
) + [
|
||||
('memprot_esp32p4_rev_less_than_v3', 'esp32p4', P4_REV_LESS_THAN_V3_MARKER),
|
||||
]
|
||||
|
||||
CONFIGS_MEMPROT_FLASH_IDROM_L2_NON_CACHE = list(zip(['memprot_esp32p4'], ['esp32p4']))
|
||||
|
||||
CONFIGS_MEMPROT_SPIRAM_XIP_IROM_ALIGNMENT_HEAP = list(
|
||||
zip(
|
||||
['memprot_spiram_xip_esp32c5', 'memprot_spiram_xip_esp32c61', 'memprot_spiram_xip_esp32p4'],
|
||||
[
|
||||
'memprot_spiram_xip_esp32c5',
|
||||
'memprot_spiram_xip_esp32c61',
|
||||
'memprot_spiram_xip_esp32p4',
|
||||
],
|
||||
['esp32c5', 'esp32c61', 'esp32p4'],
|
||||
)
|
||||
)
|
||||
) + [
|
||||
('memprot_spiram_xip_esp32p4_rev_less_than_v3', 'esp32p4', P4_REV_LESS_THAN_V3_MARKER),
|
||||
]
|
||||
|
||||
CONFIGS_MEMPROT_SPIRAM_XIP_IROM_ALIGNMENT_HEAP_L2_NON_CACHE = list(
|
||||
zip(
|
||||
@@ -688,7 +704,9 @@ CONFIGS_MEMPROT_SPIRAM_XIP_DROM_ALIGNMENT_HEAP = list(
|
||||
],
|
||||
['esp32s3', 'esp32c5', 'esp32c61', 'esp32p4'],
|
||||
)
|
||||
)
|
||||
) + [
|
||||
('memprot_spiram_xip_esp32p4_rev_less_than_v3', 'esp32p4', P4_REV_LESS_THAN_V3_MARKER),
|
||||
]
|
||||
|
||||
CONFIGS_MEMPROT_SPIRAM_XIP_DROM_ALIGNMENT_HEAP_L2_NON_CACHE = list(
|
||||
zip(
|
||||
@@ -709,7 +727,9 @@ CONFIGS_MEMPROT_INVALID_REGION_PROTECTION_USING_PMA = list(
|
||||
],
|
||||
['esp32c5', 'esp32c6', 'esp32c61', 'esp32h2', 'esp32p4', 'esp32h21'],
|
||||
)
|
||||
)
|
||||
) + [
|
||||
('memprot_esp32p4_rev_less_than_v3', 'esp32p4', P4_REV_LESS_THAN_V3_MARKER),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.generic
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
# Restricting to ESP32P4
|
||||
CONFIG_IDF_TARGET="esp32p4"
|
||||
|
||||
# Target the rev < 3.0 PMP layout (16 entries)
|
||||
CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y
|
||||
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=360
|
||||
|
||||
# Enabling memory protection
|
||||
CONFIG_ESP_SYSTEM_MEMPROT=y
|
||||
|
||||
# Enable memprot test
|
||||
CONFIG_TEST_MEMPROT=y
|
||||
|
||||
# Enable SPIRAM to check the alignment gap's memory protection
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_SPIRAM_USE_CAPS_ALLOC=y
|
||||
@@ -0,0 +1,17 @@
|
||||
# Restricting to ESP32P4
|
||||
CONFIG_IDF_TARGET="esp32p4"
|
||||
|
||||
# Target the rev < 3.0 PMP layout (16 entries)
|
||||
CONFIG_ESP32P4_SELECTS_REV_LESS_V3=y
|
||||
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=360
|
||||
|
||||
# Enabling memory protection
|
||||
CONFIG_ESP_SYSTEM_MEMPROT=y
|
||||
|
||||
# Enable memprot test
|
||||
CONFIG_TEST_MEMPROT=y
|
||||
|
||||
# Enable SPIRAM to check the alignment gap's memory protection
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_SPIRAM_USE_CAPS_ALLOC=y
|
||||
CONFIG_SPIRAM_XIP_FROM_PSRAM=y
|
||||
@@ -68,7 +68,7 @@ class PanicTestDut(IdfDut):
|
||||
return self.target in ['esp32', 'esp32s3', 'esp32p4', 'esp32h4', 'esp32s31']
|
||||
|
||||
def run_test_func(self, test_func_name: str) -> None:
|
||||
if self.target == 'esp32p4' and not self.app.sdkconfig.get('ESP32P4_SELECTS_REV_LESS_V3'):
|
||||
if self.target == 'esp32p4':
|
||||
self.write('\n')
|
||||
self.expect_exact('Enter test name:')
|
||||
self.write(test_func_name)
|
||||
|
||||
Reference in New Issue
Block a user