From e3a8feedccd1e35e4760b639f71239c6fa94ca30 Mon Sep 17 00:00:00 2001 From: "nilesh.kale" Date: Wed, 11 Mar 2026 11:00:15 +0530 Subject: [PATCH] fix(cpu_region_protect): set DROM mask PMP entry to read-only PMP entry 3 (SOC_DROM_MASK_HIGH, TOR mode) in the memprot path was incorrectly granted RW permission on esp32h21 and esp32c61. The mask ROM data region is inherently read-only; remove the W bit. Also added necessary tests to check voilations and re-enabled tests for ESP32P4 --- .../port/esp32c61/cpu_region_protect.c | 2 +- .../system/panic/main/include/test_memprot.h | 6 +++++ .../system/panic/main/test_app_main.c | 4 +++ .../system/panic/main/test_memprot.c | 17 ++++++++++++ tools/test_apps/system/panic/pytest_panic.py | 26 +++++++++++++++++++ 5 files changed, 54 insertions(+), 1 deletion(-) diff --git a/components/esp_hw_support/port/esp32c61/cpu_region_protect.c b/components/esp_hw_support/port/esp32c61/cpu_region_protect.c index 0369f214071..ab6db249013 100644 --- a/components/esp_hw_support/port/esp32c61/cpu_region_protect.c +++ b/components/esp_hw_support/port/esp32c61/cpu_region_protect.c @@ -137,7 +137,7 @@ void esp_cpu_configure_region_protection(void) if ((drom_start & (SOC_CPU_PMP_REGION_GRANULARITY - 1)) == 0) { PMP_ENTRY_SET(1, SOC_IROM_MASK_LOW, NONE); PMP_ENTRY_SET(2, drom_start, PMP_TOR | RX); - PMP_ENTRY_SET(3, SOC_DROM_MASK_HIGH, PMP_TOR | RW); + PMP_ENTRY_SET(3, SOC_DROM_MASK_HIGH, PMP_TOR | R); } else { const uint32_t pmpaddr1 = PMPADDR_NAPOT(SOC_IROM_MASK_LOW, SOC_IROM_MASK_HIGH); PMP_ENTRY_SET(1, pmpaddr1, PMP_NAPOT | RX); diff --git a/tools/test_apps/system/panic/main/include/test_memprot.h b/tools/test_apps/system/panic/main/include/test_memprot.h index 54a5871b36e..7174d9c7505 100644 --- a/tools/test_apps/system/panic/main/include/test_memprot.h +++ b/tools/test_apps/system/panic/main/include/test_memprot.h @@ -63,6 +63,12 @@ void test_spiram_xip_irom_alignment_reg_execute_violation(void); void test_spiram_xip_drom_alignment_reg_execute_violation(void); +void test_irom_mask_reg_write_violation(void); + +#ifdef SOC_DROM_MASK_HIGH +void test_drom_mask_reg_write_violation(void); +#endif + void test_drom_reg_write_violation(void); void test_drom_reg_execute_violation(void); diff --git a/tools/test_apps/system/panic/main/test_app_main.c b/tools/test_apps/system/panic/main/test_app_main.c index 02de44f53dd..a6b8502c324 100644 --- a/tools/test_apps/system/panic/main/test_app_main.c +++ b/tools/test_apps/system/panic/main/test_app_main.c @@ -188,6 +188,10 @@ void app_main(void) #if CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT HANDLE_TEST(test_name, test_irom_reg_write_violation); + HANDLE_TEST(test_name, test_irom_mask_reg_write_violation); +#ifdef SOC_DROM_MASK_HIGH + HANDLE_TEST(test_name, test_drom_mask_reg_write_violation); +#endif HANDLE_TEST(test_name, test_drom_reg_write_violation); HANDLE_TEST(test_name, test_drom_reg_execute_violation); diff --git a/tools/test_apps/system/panic/main/test_memprot.c b/tools/test_apps/system/panic/main/test_memprot.c index d30ceccf2cc..987937bdbc9 100644 --- a/tools/test_apps/system/panic/main/test_memprot.c +++ b/tools/test_apps/system/panic/main/test_memprot.c @@ -299,6 +299,23 @@ void test_irom_reg_write_violation(void) *test_addr = RND_VAL; } +void test_irom_mask_reg_write_violation(void) +{ + uint32_t *test_addr = (uint32_t *)(SOC_IROM_MASK_LOW + 0x04); + printf("ROM (IROM Mask): Write operation | Address: %p\n", test_addr); + *test_addr = RND_VAL; +} + +#ifdef SOC_DROM_MASK_HIGH +void test_drom_mask_reg_write_violation(void) +{ + uint32_t *test_addr = (uint32_t *)(SOC_DROM_MASK_HIGH - 0x04); + printf("ROM (DROM Mask): Write operation | Address: %p\n", test_addr); + *test_addr = RND_VAL; +} + +#endif + void test_drom_reg_write_violation(void) { uint32_t *test_addr = (uint32_t *)((uint32_t)(foo_buf)); diff --git a/tools/test_apps/system/panic/pytest_panic.py b/tools/test_apps/system/panic/pytest_panic.py index ef499265f63..78b15eaab05 100644 --- a/tools/test_apps/system/panic/pytest_panic.py +++ b/tools/test_apps/system/panic/pytest_panic.py @@ -1114,6 +1114,32 @@ def drom_reg_write_violation(dut: PanicTestDut, test_func_name: str) -> None: dut.expect_cpu_reset() +def irom_mask_reg_write_violation(dut: PanicTestDut, test_func_name: str) -> None: + dut.run_test_func(test_func_name) + dut.expect_gme('Store access fault') + dut.expect_reg_dump(0) + dut.expect_cpu_reset() + + +@pytest.mark.generic +@idf_parametrize('config, target', CONFIGS_MEMPROT_FLASH_IDROM, indirect=['config', 'target']) +def test_irom_mask_reg_write_violation(dut: PanicTestDut, test_func_name: str) -> None: + irom_mask_reg_write_violation(dut, test_func_name) + + +def drom_mask_reg_write_violation(dut: PanicTestDut, test_func_name: str) -> None: + dut.run_test_func(test_func_name) + dut.expect_gme('Store access fault') + dut.expect_reg_dump(0) + dut.expect_cpu_reset() + + +@pytest.mark.generic +@idf_parametrize('config, target', CONFIGS_MEMPROT_FLASH_IDROM, indirect=['config', 'target']) +def test_drom_mask_reg_write_violation(dut: PanicTestDut, test_func_name: str) -> None: + drom_mask_reg_write_violation(dut, test_func_name) + + @pytest.mark.generic @idf_parametrize('config, target', CONFIGS_MEMPROT_FLASH_IDROM, indirect=['config', 'target']) def test_drom_reg_write_violation(dut: PanicTestDut, test_func_name: str) -> None: