diff --git a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/CMakeLists.txt b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/CMakeLists.txt index 663c9e76214..54747409590 100644 --- a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/CMakeLists.txt +++ b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/CMakeLists.txt @@ -5,11 +5,13 @@ set(srcs "src/common/test_intr_utils.c" "src/common/test_panic_handler.c") if(CONFIG_SOC_SUPPORT_TEE_SYS_APM_TEST) + list(APPEND srcs "src/common/test_apm_utils.c" + "src/common/test_setup_utils.c" + "src/pms/test_tee_vectors.S") if(CONFIG_SOC_APM_CTRL_FILTER_SUPPORTED) - list(APPEND srcs "src/common/test_apm_utils.c" - "src/common/test_setup_utils.c" - "src/pms/test_tee_sys_apm.c" - "src/pms/test_tee_vectors.S") + list(APPEND srcs "src/pms/test_tee_sys_apm.c") + else() + list(APPEND srcs "src/pms/test_tee_pms.c") endif() endif() @@ -27,7 +29,7 @@ idf_component_register(SRCS "${srcs}" INCLUDE_DIRS "include" "priv_include" PRIV_INCLUDE_DIRS "priv_include/${target}" REQUIRES ulp unity esp_hal_security - PRIV_REQUIRES esp_hal_timg + PRIV_REQUIRES esp_hal_timg esp_mm LDFRAGMENTS linker.lf) if(CONFIG_ULP_COPROC_ENABLED) diff --git a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/include/test_pms.h b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/include/test_pms.h index 3eef2c8a6d4..113614b3891 100644 --- a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/include/test_pms.h +++ b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/include/test_pms.h @@ -1,10 +1,13 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ +#include "soc/soc_caps.h" + /* Test-cases */ +#if SOC_APM_CTRL_FILTER_SUPPORTED void test_sys_apm_master_hp_cpu_slave_hp_peri(void); void test_sys_apm_master_hp_cpu_slave_cpu_peri(void); @@ -34,3 +37,20 @@ void test_peri_apm_master_lp_cpu_slave_hp_peri(void); void test_peri_apm_master_lp_cpu_slave_lp_peri(void); void test_tee_mode_default_access(void); +#else +void test_sys_pms_master_hp_cpu_slave_hp_peri(void); + +void test_sys_pms_master_hp_cpu_slave_lp_peri(void); + +void test_sys_pms_master_hp_cpu_peri_regn_access(void); + +void test_sys_pms_master_lp_cpu_slave_hp_peri(void); + +void test_sys_pms_master_lp_cpu_slave_lp_peri(void); + +void test_sys_pms_master_lp_cpu_peri_regn_access(void); + +void test_sys_pms_master_gdma_slave_hp_mem(void); + +void test_sys_pms_master_gdma_slave_ext_mem(void); +#endif diff --git a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32c5/test_pms_params.h b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32c5/test_pms_params.h index b8ff56f4f9f..46edb21c5ec 100644 --- a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32c5/test_pms_params.h +++ b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32c5/test_pms_params.h @@ -23,7 +23,7 @@ #define SOC_APM_CTRL_TEE_MODE_ACCESS_BUG 0 /********* GDMA APM master ID *********/ -#define TEST_GDMA_APM_MASTER_ID 26 /* GDMA_DUMMY10 */ +#define TEST_GDMA_APM_MASTER_ID 27 /* GDMA_DUMMY11 */ /********* APM controller and path definitions *********/ #define HP_CPU_CPUPERI_APM_CTRL APM_CTRL_HP_APM @@ -202,8 +202,6 @@ /********* For PERI_APM *********/ #include "soc/reg_base.h" - -/********* For PERI_APM *********/ #include "soc/uart_reg.h" #include "soc/i2c_reg.h" #include "soc/i2s_reg.h" diff --git a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32c6/test_pms_params.h b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32c6/test_pms_params.h index e3a0f9478c7..e975e389af7 100644 --- a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32c6/test_pms_params.h +++ b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32c6/test_pms_params.h @@ -21,7 +21,7 @@ #define SOC_APM_CTRL_TEE_MODE_ACCESS_BUG 1 /********* GDMA APM master ID *********/ -#define TEST_GDMA_APM_MASTER_ID APM_MASTER_GDMA_GPSPI +#define TEST_GDMA_APM_MASTER_ID 27 /* GDMA_DUMMY11 */ /********* APM controller and path definitions *********/ #define HP_CPU_CPUPERI_APM_CTRL APM_CTRL_HP_APM diff --git a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32c61/test_pms_params.h b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32c61/test_pms_params.h index e313af9cf35..65ecc7b239c 100644 --- a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32c61/test_pms_params.h +++ b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32c61/test_pms_params.h @@ -23,7 +23,7 @@ #define SOC_APM_CTRL_TEE_MODE_ACCESS_BUG 0 /********* GDMA APM master ID *********/ -#define TEST_GDMA_APM_MASTER_ID 26 /* GDMA_DUMMY10 */ +#define TEST_GDMA_APM_MASTER_ID 27 /* GDMA_DUMMY11 */ /********* APM controller and path definitions *********/ #define HP_CPU_CPUPERI_APM_CTRL APM_CTRL_HP_APM diff --git a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32h2/test_pms_params.h b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32h2/test_pms_params.h index b22a7ce8c93..349dd905274 100644 --- a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32h2/test_pms_params.h +++ b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32h2/test_pms_params.h @@ -21,7 +21,7 @@ #define SOC_APM_CTRL_TEE_MODE_ACCESS_BUG 1 /********* GDMA APM master ID *********/ -#define TEST_GDMA_APM_MASTER_ID APM_MASTER_GDMA_GPSPI +#define TEST_GDMA_APM_MASTER_ID 27 /* GDMA_DUMMY11 */ /********* APM controller and path definitions *********/ #define HP_CPU_CPUPERI_APM_CTRL APM_CTRL_HP_APM diff --git a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32p4/test_pms_params.h b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32p4/test_pms_params.h new file mode 100644 index 00000000000..8c539bd4eba --- /dev/null +++ b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32p4/test_pms_params.h @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "hal/apm_types.h" +#include "soc/apm_defs.h" + +#define ALIGN_TO_NEXT_4KB(addr) (((addr) + 0x1000) & ~0xFFF) + +/********* For DMA_PMS *********/ + +#define GDMA_HPMEM_TEST_REGN_NUM APM_DMA_PMS_REGION_NUM +#define GDMA_HPMEM_TEST_REGN_SIZE APM_DMA_PMS_REGION_ADDR_ALIGN +/* Reserved regions for HPMEM test: [0] pre-buf, [1] post-buf */ +#define GDMA_HPMEM_TEST_REGN_RESV_NUM 2 + +#define GDMA_EXTMEM_TEST_REGN_NUM APM_DMA_PMS_REGION_NUM +#define GDMA_EXTMEM_TEST_REGN_SIZE APM_DMA_PMS_REGION_ADDR_ALIGN +/* Reserved regions for EXTMEM test: [0] pre-buf, [1] post-buf, [2] full HP-mem + * TODO: Investigate why [2] is required for EXT_MEM case + */ +#define GDMA_EXTMEM_TEST_REGN_RESV_NUM 3 + +/********* For HP_PERI_PMS *********/ + +#include "soc/timer_group_reg.h" +#include "soc/i2c_reg.h" +#include "soc/i2s_reg.h" +#include "soc/pcnt_reg.h" +#include "soc/uart_reg.h" +#include "soc/spi_reg.h" +#include "soc/ledc_reg.h" +#include "soc/adc_reg.h" +#include "soc/parl_io_reg.h" +#include "soc/rmt_reg.h" +#include "soc/gpio_reg.h" +#include "soc/io_mux_reg.h" +#include "soc/cache_reg.h" +#include "soc/hp_system_reg.h" +#include "soc/bitscrambler_reg.h" +#include "soc/trace_reg.h" +#include "soc/sha_reg.h" +#include "soc/assist_debug_reg.h" +#include "soc/parl_io_reg.h" +#include "soc/io_mux_reg.h" + +/********* For HP2LP_PERI_PMS *********/ + +#include "soc/lp_timer_reg.h" +#include "soc/lp_analog_peri_reg.h" +#include "soc/pmu_reg.h" +#include "soc/lp_wdt_reg.h" +#include "soc/lp_uart_reg.h" +#include "soc/lp_i2c_reg.h" +#include "soc/lp_i2c_ana_mst_reg.h" +#include "soc/huk_reg.h" +#include "soc/efuse_reg.h" +#include "soc/lp_iomux_reg.h" +#include "soc/trng_reg.h" diff --git a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/test_pms_priv.h b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/test_pms_priv.h index a11275e29af..6b1c1d705f6 100644 --- a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/test_pms_priv.h +++ b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/priv_include/test_pms_priv.h @@ -18,6 +18,7 @@ #include "soc/lp_system_reg.h" #define LP_STORE_REG_PREFIX(reg) LP_SYSTEM_REG_LP_STORE##reg##_REG #endif + #include "hal/apm_types.h" /********* Panic Handler *********/ @@ -35,8 +36,8 @@ #define SEND_ADDR(addr) REG_WRITE(LP_STORE_REG_PREFIX(7), addr) #define RECV_ADDR() REG_READ(LP_STORE_REG_PREFIX(7)) -#define SEND_SIZE(size) REG_WRITE(LP_STORE_REG_PREFIX(8), size) -#define RECV_SIZE() REG_READ(LP_STORE_REG_PREFIX(8)) +#define SEND_DATA(data) REG_WRITE(LP_STORE_REG_PREFIX(8), data) +#define RECV_DATA() REG_READ(LP_STORE_REG_PREFIX(8)) #define SEND_EXCP(val) REG_WRITE(LP_STORE_REG_PREFIX(9), val) #define RECV_EXCP() REG_READ(LP_STORE_REG_PREFIX(9)) @@ -57,35 +58,12 @@ #endif #if SOC_APM_CTRL_FILTER_SUPPORTED -typedef struct { - apm_master_id_t master_id; - apm_ctrl_module_t ctrl_mod; - const uint32_t *test_addr; - uint32_t test_addr_num; - uint32_t test_addr_resv_mask; -} test_sys_apm_periph_cfg_t; - -typedef struct { - apm_master_id_t master_id; - apm_ctrl_module_t ctrl_mod; - apm_ctrl_access_path_t path; - uint32_t mem_start_addr; - uint32_t mem_end_addr; - uint32_t regn_count; - uint32_t regn_sz; -} test_sys_apm_mem_cfg_t; - -typedef struct { - apm_master_id_t master_id; - apm_tee_ctrl_module_t ctrl_mod; - const uint32_t *test_reg; - uint32_t test_reg_num; - uint64_t test_reg_resv_mask; -} test_peri_apm_periph_cfg_t; - void apm_hal_enable_region_filter_all(apm_ctrl_module_t ctrl_mod, bool enable); void test_apm_ctrl_reset_all(void); void test_apm_ctrl_enable_intr(apm_ctrl_module_t ctrl_mod, apm_ctrl_access_path_t path); +#else +void test_pms_ctrl_reset_all(void); +void test_pms_enable_intr(apm_ctrl_module_t ctrl_mod); #endif /* Utility functions */ @@ -97,7 +75,9 @@ void test_u2m_switch(void); void test_boot_lp_cpu(void); void test_stop_lp_cpu(void); void test_reset_lp_cpu(void); +#if SOC_LP_AON_SUPPORTED void test_switch_lp_mem_speed(bool high_speed); +#endif void test_gdma_init(void); void test_gdma_deinit(void); diff --git a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/common/test_apm_utils.c b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/common/test_apm_utils.c index 5ea7373eb0e..404be071c1f 100644 --- a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/common/test_apm_utils.c +++ b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/common/test_apm_utils.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,6 +11,11 @@ #include "soc/soc.h" #include "soc/soc_caps.h" #include "soc/interrupts.h" +#if SOC_CPU_CORES_NUM > 1 +#include "soc/interrupt_core0_reg.h" +#else +#include "soc/interrupt_matrix_reg.h" +#endif #include "soc/apm_defs.h" #include "hal/apm_hal.h" @@ -22,6 +27,7 @@ #include "unity.h" +#if SOC_APM_CTRL_FILTER_SUPPORTED /***************************** Utility - APM interrupts *****************************/ #define MAX_APM_CTRL_NUM (4) @@ -213,7 +219,7 @@ static const char *const excp_mid_strs[] = { #if SOC_PARLIO_SUPPORTED [APM_MASTER_GDMA_PARLIO] = "GDMA_PARLIO", #endif /* SOC_PARLIO_SUPPORTED */ - [26] = "GDMA_DUMMYX", + [27] = "GDMA_DUMMYX", }; static const char *apm_excp_mid_to_str(uint8_t mid) @@ -368,3 +374,232 @@ static void test_apm_ctrl_free_all_intr(void) } } } +#elif SOC_APM_SUPPORTED +/***************************** Utility - PMS interrupts *****************************/ + +#include "soc/icm_sys_reg.h" +#include "hal/lp_sys_ll.h" +#include "test_pms_params.h" + +static intr_handle_t s_pms_hp_intr_hdl = NULL; +static intr_handle_t s_pms_lp_intr_hdl = NULL; + +volatile bool pms_lp_excp_flag = false; +volatile uint32_t pms_lp_excp_addr = 0; +volatile bool pms_dma_excp_flag = false; + +/***************************** PMS exception check *****************************/ + +static const char *apm_excp_type_to_str(bool is_secure) +{ + char *excp_type = "Unknown"; + + if (is_secure) { + excp_type = "Space exception"; + } else { + excp_type = "Authority exception"; + } + + return excp_type; +} + +static const char *apm_excp_src_to_str(apm_ctrl_exception_type type) +{ + char *excp_src = "Unknown"; + + switch (type) { + case APM_EXCP_HP_AXI: + excp_src = "HP_AXI"; + break; + case APM_EXCP_HP_AHB: + excp_src = "HP_AHB"; + break; + case APM_EXCP_LP_AHB: + excp_src = "LP_AHB"; + break; + case APM_EXCP_LP_IDBUS: + excp_src = "LP_IDBUS"; + break; + default: + break; + } + + return excp_src; +} + +IRAM_ATTR static void pms_log_violation(apm_ctrl_exception_type type, apm_ctrl_exception_info_t *info) +{ + apm_hal_get_exception_info(type, info); + esp_rom_printf("PMS violation: %s\n\r", apm_excp_type_to_str(info->is_secure)); + esp_rom_printf("Access addr: 0x%08x | Type: %s\n\r", info->addr, info->is_wr ? "Write" : "Read"); + esp_rom_printf("Master: %d | Source: %s\n\r", info->id, apm_excp_src_to_str(type)); +} + +IRAM_ATTR static void pms_hp_intr_cb(void *arg) +{ + apm_ctrl_exception_info_t info; + uint32_t status = apm_hal_get_intr_status(); + + if (status & APM_EXCP_HP_AXI) { + pms_log_violation(APM_EXCP_HP_AXI, &info); + } + if (status & APM_EXCP_HP_AHB) { + pms_log_violation(APM_EXCP_HP_AHB, &info); + pms_dma_excp_flag = true; + } + + apm_hal_clear_intr(APM_CTRL_DMA_PMS); + apm_hal_clear_intr(APM_CTRL_HP_PERI_PMS); + apm_hal_clear_intr(APM_CTRL_LP2HP_PERI_PMS); +} + +IRAM_ATTR static void pms_lp_intr_cb(void *arg) +{ + apm_ctrl_exception_info_t info; + uint32_t status = apm_hal_get_intr_status(); + + if (status & APM_EXCP_LP_AHB) { + pms_log_violation(APM_EXCP_LP_AHB, &info); + pms_lp_excp_addr = info.addr; + pms_lp_excp_flag = true; + } + if (status & APM_EXCP_LP_IDBUS) { + pms_log_violation(APM_EXCP_LP_IDBUS, &info); + pms_lp_excp_addr = info.addr; + pms_lp_excp_flag = true; + } + + apm_hal_clear_intr(APM_CTRL_HP2LP_PERI_PMS); + apm_hal_clear_intr(APM_CTRL_LP_PERI_PMS); +} + +void test_pms_enable_intr(apm_ctrl_module_t ctrl_mod) +{ + /* TODO: Investigate why this is required */ + REG_CLR_BIT(ICM_INT_ENA_REG, ICM_REG_DLOCK_INT_ENA); + + int intr_src = apm_hal_get_intr_src_num(ctrl_mod); + TEST_ASSERT(intr_src >= 0); + + uint32_t flags = ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL3; + + switch (ctrl_mod) { + case APM_CTRL_DMA_PMS: + case APM_CTRL_HP_PERI_PMS: + case APM_CTRL_LP2HP_PERI_PMS: + if (!s_pms_hp_intr_hdl) { + TEST_ESP_OK(esp_intr_alloc(intr_src, flags, &pms_hp_intr_cb, NULL, &s_pms_hp_intr_hdl)); + } + break; + case APM_CTRL_LP_PERI_PMS: + case APM_CTRL_HP2LP_PERI_PMS: + if (!s_pms_lp_intr_hdl) { + TEST_ESP_OK(esp_intr_alloc(intr_src, flags, &pms_lp_intr_cb, NULL, &s_pms_lp_intr_hdl)); + } + break; + default: + TEST_ASSERT_MESSAGE(false, "Invalid PMS module"); + return; + } + + apm_hal_enable_intr(ctrl_mod, true); +} + +static void test_pms_free_all_intr(void) +{ + if (s_pms_hp_intr_hdl) { + esp_intr_free(s_pms_hp_intr_hdl); + s_pms_hp_intr_hdl = NULL; + } + if (s_pms_lp_intr_hdl) { + esp_intr_free(s_pms_lp_intr_hdl); + s_pms_lp_intr_hdl = NULL; + } +} + +/********************************** PMS Reset *************************************/ + +static void test_dma_pms_reset(void) +{ + for (uint32_t regn = 0; regn < APM_DMA_PMS_REGION_NUM; regn++) { + apm_hal_dma_pms_set_region_bounds(regn, 0x00U, UINT32_MAX); + } + + for (uint32_t mid = 0; mid < APM_MASTER_DMA_MAX; mid++) { + apm_hal_dma_pms_set_master_region_attr((apm_master_dma_id_t)mid, UINT32_MAX, UINT32_MAX); + } + + apm_hal_enable_intr(APM_CTRL_DMA_PMS, false); + apm_hal_clear_intr(APM_CTRL_DMA_PMS); +} + +static void test_hp_peri_pms_reset(void) +{ + const apm_hal_pms_hp_peri_cfg_t cfg = { + .cpu_peri = UINT32_MAX, + .hp_peri0 = UINT32_MAX, + .hp_peri1 = UINT64_MAX, + }; + for (int core = 0; core < SOC_CPU_CORES_NUM; core++) { + apm_hal_hp_peri_pms_set_hpcpu_access(core, APM_SEC_MODE_TEE, &cfg); + apm_hal_hp_peri_pms_set_hpcpu_access(core, APM_SEC_MODE_REE, &cfg); + } + + apm_hal_enable_intr(APM_CTRL_HP_PERI_PMS, false); + apm_hal_clear_intr(APM_CTRL_HP_PERI_PMS); +} + +static void test_hp2lp_peri_pms_reset(void) +{ + uint32_t cfg_mask = UINT32_MAX; + for (int core = 0; core < SOC_CPU_CORES_NUM; core++) { + apm_hal_hp2lp_peri_pms_set_hpcpu_access(core, APM_SEC_MODE_TEE, cfg_mask); + apm_hal_hp2lp_peri_pms_set_hpcpu_access(core, APM_SEC_MODE_REE, cfg_mask); + } + + apm_hal_enable_intr(APM_CTRL_HP2LP_PERI_PMS, false); + apm_hal_clear_intr(APM_CTRL_HP2LP_PERI_PMS); +} + +static void test_lp_peri_pms_reset(void) +{ + uint32_t cfg_mask = UINT32_MAX; + apm_hal_lp_peri_pms_set_lpcpu_access(cfg_mask); + + for (uint32_t regn = 0; regn < APM_LP_PERI_PMS_REGION_NUM; regn++) { + apm_hal_lp_peri_pms_set_region_bounds(regn, 0x00U, UINT32_MAX); + } + + for (uint32_t mid = 0; mid < APM_MASTER_DMA; mid++) { + apm_hal_lp_peri_pms_set_master_region_attr(mid, APM_SEC_MODE_TEE, UINT32_MAX); + apm_hal_lp_peri_pms_set_master_region_attr(mid, APM_SEC_MODE_REE, UINT32_MAX); + } + + apm_hal_enable_intr(APM_CTRL_LP_PERI_PMS, false); + apm_hal_clear_intr(APM_CTRL_LP_PERI_PMS); +} + +static void test_lp2hp_peri_pms_reset(void) +{ + const apm_hal_pms_hp_peri_cfg_t cfg = { + .cpu_peri = UINT32_MAX, + .hp_peri0 = UINT32_MAX, + .hp_peri1 = UINT64_MAX, + }; + apm_hal_lp2hp_peri_pms_set_lpcpu_access(&cfg); + + apm_hal_enable_intr(APM_CTRL_LP2HP_PERI_PMS, false); + apm_hal_clear_intr(APM_CTRL_LP2HP_PERI_PMS); + lp_sys_ll_enable_lp_core_err_resp(true); +} + +void test_pms_ctrl_reset_all(void) +{ + test_dma_pms_reset(); + test_hp_peri_pms_reset(); + test_hp2lp_peri_pms_reset(); + test_lp_peri_pms_reset(); + test_lp2hp_peri_pms_reset(); + test_pms_free_all_intr(); +} +#endif diff --git a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/common/test_panic_handler.c b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/common/test_panic_handler.c index 7709e4a7e33..f93ac02d9fe 100644 --- a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/common/test_panic_handler.c +++ b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/common/test_panic_handler.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -61,11 +61,18 @@ void test_panicHandler(RvExcFrame *frame, int exccause) } return; } + /* PERI_APM access fault */ -#if SOC_APM_SUPPORT_TEE_PERI_ACCESS_CTRL +#if SOC_APM_SUPPORT_TEE_PERI_ACCESS_CTRL || !SOC_APM_CTRL_FILTER_SUPPORTED +#if CONFIG_IDF_TARGET_ESP32P4 + if ((regs->mtval >= CPU_PERIPH_LOW && regs->mtval < CPU_PERIPH_HIGH) || + (regs->mtval >= SOC_PERIPHERAL_LOW && regs->mtval < SOC_PERIPHERAL_HIGH) || + (regs->mtval >= SOC_LP_PERIPH_LOW && regs->mtval < SOC_LP_PERIPH_HIGH)) { +#else if (regs->mtval >= SOC_PERIPHERAL_LOW && regs->mtval < SOC_PERIPHERAL_HIGH) { +#endif if (mcause == MCAUSE_LOAD_ACCESS_FAULT || mcause == MCAUSE_STORE_ACCESS_FAULT) { - panic_print("[PERI_APM] %s at 0x%08x\n\r", rsn, regs->mtval); + panic_print("[PERI_ACC] %s at 0x%08x (%s)\n\r", rsn, regs->mtval, (regs->mstatus & MSTATUS_MPP) ? "M-mode" : "U-mode"); frame->mepc += 0x04U; RV_WRITE_CSR(uscratch, regs->mtval); return; diff --git a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/common/test_setup_utils.c b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/common/test_setup_utils.c index 84567627489..18e687b5099 100644 --- a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/common/test_setup_utils.c +++ b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/common/test_setup_utils.c @@ -13,18 +13,27 @@ #include "hal/gdma_ll.h" #include "hal/gdma_types.h" #if SOC_AHB_GDMA_VERSION == 2 +#include "hal/ahb_dma_ll.h" #include "soc/ahb_dma_struct.h" #elif SOC_AHB_GDMA_VERSION == 1 #include "soc/gdma_struct.h" #endif +#include "esp_private/periph_ctrl.h" #if CONFIG_ULP_COPROC_ENABLED -#include "soc/lp_aon_reg.h" #include "soc/lpperi_reg.h" +#if SOC_LP_AON_SUPPORTED +#include "soc/lp_aon_reg.h" +#define LP_CPU_RST_EN (LPPERI_LP_CPU_RESET_EN) +#else +#include "soc/lp_system_reg.h" +#define LP_CPU_RST_EN (LPPERI_RST_EN_LP_CORE) +#endif #include "ulp_lp_core.h" #endif #include "esp_attr.h" +#include "esp_cache.h" #include "esp_rom_lldesc.h" #include "esp_rom_sys.h" @@ -61,9 +70,11 @@ void test_stop_lp_cpu(void) void test_reset_lp_cpu(void) { - REG_SET_BIT(LPPERI_RESET_EN_REG, LPPERI_LP_CPU_RESET_EN); + REG_SET_BIT(LPPERI_RESET_EN_REG, LP_CPU_RST_EN); + REG_CLR_BIT(LPPERI_RESET_EN_REG, LP_CPU_RST_EN); } +#if SOC_LP_AON_SUPPORTED void test_switch_lp_mem_speed(bool high_speed) { if (high_speed) { @@ -74,6 +85,7 @@ void test_switch_lp_mem_speed(bool high_speed) REG_SET_BIT(LP_AON_LPBUS_REG, LP_AON_FAST_MEM_MUX_SEL_UPDATE); } #endif +#endif /***************************** Utility - GDMA *****************************/ @@ -87,15 +99,21 @@ void test_switch_lp_mem_speed(bool high_speed) #define DMA_MEM_TRANS_EN_FIELD mem_trans_en #endif +#if SOC_RCC_IS_INDEPENDENT +#define GDMA_RCC_ATOMIC() +#else /* !SOC_RCC_IS_INDEPENDENT */ +#define GDMA_RCC_ATOMIC() PERIPH_RCC_ATOMIC() +#endif /* SOC_RCC_IS_INDEPENDENT */ + #define dma_ll_force_enable_reg_clock DMA_LL_FUNC(force_enable_reg_clock) #define dma_ll_tx_enable_data_burst DMA_LL_FUNC(tx_enable_data_burst) #define dma_ll_tx_enable_descriptor_burst DMA_LL_FUNC(tx_enable_descriptor_burst) #define dma_ll_rx_enable_data_burst DMA_LL_FUNC(rx_enable_data_burst) #define dma_ll_rx_enable_descriptor_burst DMA_LL_FUNC(rx_enable_descriptor_burst) #define dma_ll_tx_reset_channel DMA_LL_FUNC(tx_reset_channel) -#define dma_ll_tx_connect_to_periph DMA_LL_FUNC(tx_connect_to_periph) +#define dma_ll_tx_connect_to_mem DMA_LL_FUNC(tx_connect_to_mem) #define dma_ll_rx_reset_channel DMA_LL_FUNC(rx_reset_channel) -#define dma_ll_rx_connect_to_periph DMA_LL_FUNC(rx_connect_to_periph) +#define dma_ll_rx_connect_to_mem DMA_LL_FUNC(rx_connect_to_mem) #define dma_ll_tx_disconnect_all DMA_LL_FUNC(tx_disconnect_all) #define dma_ll_rx_disconnect_all DMA_LL_FUNC(rx_disconnect_all) #define dma_ll_tx_set_desc_addr DMA_LL_FUNC(tx_set_desc_addr) @@ -113,10 +131,13 @@ void test_switch_lp_mem_speed(bool high_speed) #define dma_ll_tx_get_interrupt_status DMA_LL_FUNC(tx_get_interrupt_status) #define dma_ll_rx_get_interrupt_status DMA_LL_FUNC(rx_get_interrupt_status) -#define TEST_DMA_CHN_NUM 0 +#define TEST_DMA_GRP_NUM 0 +#define TEST_DMA_CHN_NUM 1 #define TEST_DMA_BLK_LEN 1024 #define TEST_DMA_MAX_BLK_NUM 32 +#define SOC_GDMA_TRIG_PERIPH_DUMMY (11) + DRAM_ATTR static lldesc_t tx_link[TEST_DMA_MAX_BLK_NUM]; DRAM_ATTR static lldesc_t rx_link[TEST_DMA_MAX_BLK_NUM]; @@ -146,6 +167,11 @@ static void setup_gdma_link(lldesc_t *link, uint8_t *buf, size_t size, bool is_t link[x - 1].empty = 0; } +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + size_t num_desc = (size + TEST_DMA_BLK_LEN - 1) / TEST_DMA_BLK_LEN; + esp_cache_msync(&link[0], num_desc * sizeof(lldesc_t), ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); +#endif + if (is_tx) { dma_ll_tx_set_desc_addr(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, (uint32_t)&link[0]); } else { @@ -155,8 +181,10 @@ static void setup_gdma_link(lldesc_t *link, uint8_t *buf, size_t size, bool is_t void test_gdma_init(void) { - gdma_ll_enable_bus_clock(TEST_DMA_CHN_NUM, true); - gdma_ll_reset_register(TEST_DMA_CHN_NUM); + GDMA_RCC_ATOMIC() { + gdma_ll_enable_bus_clock(TEST_DMA_GRP_NUM, true); + gdma_ll_reset_register(TEST_DMA_GRP_NUM); + } dma_ll_force_enable_reg_clock(&TEST_DMA_DEV, true); #if SOC_AHB_GDMA_VERSION == 2 @@ -181,9 +209,8 @@ void test_gdma_init(void) dma_ll_tx_set_priority(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, 1); dma_ll_rx_set_priority(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, 1); - dma_ll_tx_connect_to_periph(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, SOC_GDMA_TRIG_PERIPH_SPI2); - dma_ll_rx_connect_to_periph(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, SOC_GDMA_TRIG_PERIPH_SPI2); - TEST_DMA_DEV.channel[TEST_DMA_CHN_NUM].in.in_conf0.DMA_MEM_TRANS_EN_FIELD = 1; + dma_ll_tx_connect_to_mem(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, SOC_GDMA_TRIG_PERIPH_DUMMY); + dma_ll_rx_connect_to_mem(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, SOC_GDMA_TRIG_PERIPH_DUMMY); dma_ll_tx_enable_interrupt(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, GDMA_LL_EVENT_TX_EOF, true); dma_ll_rx_enable_interrupt(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, GDMA_LL_EVENT_RX_SUC_EOF, true); @@ -200,8 +227,10 @@ void test_gdma_deinit(void) dma_ll_tx_reset_channel(&TEST_DMA_DEV, TEST_DMA_CHN_NUM); dma_ll_rx_reset_channel(&TEST_DMA_DEV, TEST_DMA_CHN_NUM); - gdma_ll_reset_register(TEST_DMA_CHN_NUM); - gdma_ll_enable_bus_clock(TEST_DMA_CHN_NUM, false); + GDMA_RCC_ATOMIC() { + gdma_ll_reset_register(TEST_DMA_GRP_NUM); + gdma_ll_enable_bus_clock(TEST_DMA_GRP_NUM, false); + } } void test_gdma_m2m_transfer(uint8_t *src, uint8_t *dest, size_t size) diff --git a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/pms/test_tee_peri_apm.c b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/pms/test_tee_peri_apm.c index 4768ec17000..bee5f6e4afc 100644 --- a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/pms/test_tee_peri_apm.c +++ b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/pms/test_tee_peri_apm.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,6 +27,14 @@ /***************************** PERI_APM *****************************/ +typedef struct { + apm_master_id_t master_id; + apm_tee_ctrl_module_t ctrl_mod; + const uint32_t *test_reg; + uint32_t test_reg_num; + uint64_t test_reg_resv_mask; +} test_peri_apm_periph_cfg_t; + static const uint32_t test_peri_apm_hp_peri_reg[] = { [APM_TEE_HP_PERIPH_UART1] = UART_DATE_REG(1), [APM_TEE_HP_PERIPH_I2C_EXT0] = I2C_DATE_REG(0), @@ -130,30 +138,35 @@ IRAM_ATTR static void hp_cpu_peri_addr_rw(uint32_t peri_addr, uint32_t attr) IRAM_ATTR static void lp_cpu_peri_addr_rw(uint32_t peri_addr, uint32_t attr) { - test_reset_lp_cpu(); + SEND_MSG(MSG_SLAVE_CLEAR); + test_delay_ms(5); SEND_EXCP(0); - SEND_MSG(MSG_SLAVE_WRITE); SEND_ADDR(peri_addr); + SEND_DATA(TEST_VAL); + SEND_MSG(MSG_SLAVE_WRITE); test_delay_ms(10); bool can_write = (attr & APM_PERM_W); if (!can_write) { TEST_ASSERT(RECV_EXCP() == MCAUSE_STORE_ACCESS_FAULT); TEST_ASSERT_EQUAL_HEX32(peri_addr, RECV_ADDR()); - esp_rom_printf("[PERI_APM] Store access fault at 0x%08x\n", peri_addr); + esp_rom_printf("[PERI_ACC] Store access fault at 0x%08x\n", peri_addr); } + SEND_MSG(MSG_SLAVE_CLEAR); + test_delay_ms(5); + SEND_EXCP(0); - SEND_MSG(MSG_SLAVE_READ); SEND_ADDR(peri_addr); + SEND_MSG(MSG_SLAVE_READ); test_delay_ms(10); bool can_read = (attr & APM_PERM_R); if (!can_read) { TEST_ASSERT(RECV_EXCP() == MCAUSE_LOAD_ACCESS_FAULT); TEST_ASSERT_EQUAL_HEX32(peri_addr, RECV_ADDR()); - esp_rom_printf("[PERI_APM] Load access fault at 0x%08x\n", peri_addr); + esp_rom_printf("[PERI_ACC] Load access fault at 0x%08x\n", peri_addr); } SEND_EXCP(0); diff --git a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/pms/test_tee_pms.c b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/pms/test_tee_pms.c new file mode 100644 index 00000000000..411ac2d0ba8 --- /dev/null +++ b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/pms/test_tee_pms.c @@ -0,0 +1,740 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "soc/soc.h" +#include "soc/soc_caps.h" +#include "soc/apm_defs.h" + +#include "hal/apm_hal.h" +#include "hal/apm_ll.h" +#include "hal/apm_types.h" + +#include "esp_attr.h" +#include "esp_cpu.h" +#include "esp_rom_sys.h" + +#include "riscv/csr.h" +#include "riscv/rv_utils.h" + +#include "test_pms_priv.h" +#include "test_pms_params.h" + +#include "esp_cache.h" +#include "esp_heap_caps.h" +#include "esp_memory_utils.h" + +#include "unity.h" + +#define TEST_VAL 0x0FACADE0 + +extern volatile bool pms_lp_excp_flag; +extern volatile uint32_t pms_lp_excp_addr; +extern volatile bool pms_dma_excp_flag; + +/***************************** HP/HP2LP PERI_PMS & LP/LP2HP PERI_PMS *****************************/ + +typedef enum { + HP_PERI0, + HP_PERI1, + CPU_PERI, + LP_PERI +} test_pms_peri_grp_t; + +typedef struct { + apm_master_id_t master_id; + apm_ctrl_module_t ctrl_mod; + const uint32_t *test_reg; + uint32_t test_reg_num; + test_pms_peri_grp_t test_peri_grp; +} test_pms_periph_cfg_t; + +static const uint32_t test_cpu_peri_reg[] = { + [APM_SLAVE_TRACE0] = TRACE_DATE_REG(0), + [APM_SLAVE_TRACE1] = TRACE_DATE_REG(1), + [APM_SLAVE_CACHE] = CACHE_DATE_REG, +}; + +static const uint32_t test_hp_peri0_reg[] = { + [APM_SLAVE_HP_CRYPTO] = SHA_DATE_REG, + [APM_SLAVE_HP_RMT] = RMT_DATE_REG, + [APM_SLAVE_HP_BITSCRAMBLER] = BITSCRAMBLER_VERSION_REG, +}; + +static const uint32_t test_hp_peri1_reg[] = { + [APM_SLAVE_HP_TG0] = TIMG_NTIMERS_DATE_REG(0), + [APM_SLAVE_HP_I2C0] = I2C_DATE_REG(0), + [APM_SLAVE_HP_I2S0] = I2S_DATE_REG(0), + [APM_SLAVE_HP_PCNT] = PCNT_DATE_REG, + [APM_SLAVE_HP_UART2] = UART_DATE_REG(2), + [APM_SLAVE_HP_PARLIO] = PARL_IO_VERSION_REG, + [APM_SLAVE_HP_GPSPI2] = SPI_DATE_REG(2), + [APM_SLAVE_HP_LEDC] = LEDC_DATE_REG, + [APM_SLAVE_HP_ADC] = ADC_CTRL_DATE_REG, + [APM_SLAVE_HP_GPIO] = GPIO_DATE_REG, + [APM_SLAVE_HP_IOMUX] = IO_MUX_DATE_REG, + [APM_SLAVE_HP_SYS_REG] = HP_SYSTEM_VER_DATE_REG, +}; + +static const uint32_t test_lp_peri_reg[] = { + [APM_SLAVE_LP_TIMER] = LP_TIMER_DATE_REG, + [APM_SLAVE_LP_ANAPERI] = LP_ANALOG_PERI_DATE_REG, + [APM_SLAVE_LP_WDT] = LP_WDT_DATE_REG, + [APM_SLAVE_LP_UART] = LP_UART_ID_REG, + [APM_SLAVE_LP_I2C] = LP_I2C_DATE_REG, + [APM_SLAVE_LP_I2CMST] = LP_I2C_ANA_MST_DATE_REG, + [APM_SLAVE_LP_IOMUX] = LP_IOMUX_VER_DATE_REG, + [APM_SLAVE_LP_HUK] = HUK_DATE_REG, + [APM_SLAVE_LP_TRNG] = RNG_DATE_REG, +}; + +FORCE_INLINE_ATTR uint32_t reg_read(uint32_t addr) +{ + uint32_t value; + __asm__ volatile( + "lw %0, 0(%1)\n" + "fence\n" + "nop\nnop\nnop\nnop\n" + : "=r"(value) + : "r"(addr) + : "memory" + ); + return value; +} + +FORCE_INLINE_ATTR void reg_write(uint32_t addr, uint32_t value) +{ + __asm__ volatile( + "sw %1, 0(%0)\n" + "fence\n" + "nop\nnop\nnop\nnop\n" + : + : "r"(addr), "r"(value) + : "memory" + ); +} + +IRAM_ATTR static void hp_cpu_peri_addr_rw(uint32_t peri_addr, bool should_panic) +{ + RV_WRITE_CSR(uscratch, 0x00); + + reg_write(peri_addr, TEST_VAL); + test_delay_ms(10); + + if (should_panic) { + TEST_ASSERT_EQUAL_HEX32(peri_addr, RV_READ_CSR(uscratch)); + } else { + TEST_ASSERT_EQUAL_HEX32(0x00, RV_READ_CSR(uscratch)); + } + + RV_WRITE_CSR(uscratch, 0x00); + + volatile uint32_t val = reg_read(peri_addr); + (void)val; + test_delay_ms(10); + + if (should_panic) { + TEST_ASSERT_EQUAL_HEX32(peri_addr, RV_READ_CSR(uscratch)); + } else { + TEST_ASSERT_EQUAL_HEX32(0x00, RV_READ_CSR(uscratch)); + } + + RV_WRITE_CSR(uscratch, 0x00); +} + +#if CONFIG_ULP_COPROC_ENABLED +IRAM_ATTR static void lp_cpu_peri_addr_rw(uint32_t peri_addr, bool should_panic) +{ + bool is_lp_peri = (peri_addr >= SOC_LP_PERIPH_LOW && peri_addr < SOC_LP_PERIPH_HIGH); + + SEND_MSG(MSG_SLAVE_CLEAR); + test_delay_ms(5); + + if (is_lp_peri) { + pms_lp_excp_flag = false; + pms_lp_excp_addr = UINT32_MAX; + } else { + SEND_EXCP(0); + } + SEND_ADDR(peri_addr); + SEND_DATA(TEST_VAL); + SEND_MSG(MSG_SLAVE_WRITE); + test_delay_ms(10); + + if (should_panic) { + if (is_lp_peri) { + TEST_ASSERT_TRUE(pms_lp_excp_flag); + TEST_ASSERT_EQUAL_HEX32(peri_addr, pms_lp_excp_addr); + } else { + TEST_ASSERT(RECV_EXCP() == MCAUSE_STORE_ACCESS_FAULT); + TEST_ASSERT_EQUAL_HEX32(peri_addr, RECV_ADDR()); + esp_rom_printf("[PERI_ACC] Store access fault at 0x%08x\n", peri_addr); + } + } else { + if (is_lp_peri) { + TEST_ASSERT_FALSE(pms_lp_excp_flag); + } else { + TEST_ASSERT(RECV_EXCP() == 0); + } + } + + SEND_MSG(MSG_SLAVE_CLEAR); + test_delay_ms(5); + + if (is_lp_peri) { + pms_lp_excp_flag = false; + pms_lp_excp_addr = UINT32_MAX; + } else { + SEND_EXCP(0); + } + SEND_ADDR(peri_addr); + SEND_MSG(MSG_SLAVE_READ); + test_delay_ms(10); + + if (should_panic) { + if (is_lp_peri) { + TEST_ASSERT_TRUE(pms_lp_excp_flag); + TEST_ASSERT_EQUAL_HEX32(peri_addr, pms_lp_excp_addr); + } else { + TEST_ASSERT(RECV_EXCP() == MCAUSE_LOAD_ACCESS_FAULT); + TEST_ASSERT_EQUAL_HEX32(peri_addr, RECV_ADDR()); + esp_rom_printf("[PERI_ACC] Load access fault at 0x%08x\n", peri_addr); + } + } else { + if (is_lp_peri) { + TEST_ASSERT_FALSE(pms_lp_excp_flag); + } else { + TEST_ASSERT(RECV_EXCP() == 0); + } + } +} +#endif + +IRAM_ATTR static void switch_priv_mode(void) +{ + int mode = esp_cpu_get_curr_privilege_level(); + if (mode == PRV_M) { + rv_utils_intr_global_disable(); + test_m2u_switch(); + } else { + test_u2m_switch(); + rv_utils_intr_global_enable(); + } +} + +static const apm_hal_pms_regn_cfg_t test_hp_peri_regn_cfg[] = { + /* cpu_peri */ + APM_HAL_PMS_REGION_ENTRY(0, REG_TRACE_BASE(0), REG_TRACE_BASE(1)), + APM_HAL_PMS_REGION_ENTRY(1, DR_REG_CACHE_BASE, ALIGN_TO_NEXT_4KB(DR_REG_CACHE_BASE)), + /* hp_peri */ + APM_HAL_PMS_REGION_ENTRY(2, DR_REG_SHA_BASE, DR_REG_RSA_BASE), + APM_HAL_PMS_REGION_ENTRY(3, DR_REG_RMT_BASE, DR_REG_BITSCRAMBLER_BASE), + APM_HAL_PMS_REGION_ENTRY(4, DR_REG_PCNT_BASE, DR_REG_UART0_BASE), + APM_HAL_PMS_REGION_ENTRY(5, DR_REG_PARIO_BASE, DR_REG_SPI2_BASE), + APM_HAL_PMS_REGION_ENTRY(6, DR_REG_GPIO_BASE, DR_REG_IO_MUX_BASE), + APM_HAL_PMS_REGION_ENTRY(7, DR_REG_IO_MUX_BASE, DR_REG_SYSTIMER_BASE), +}; + +static const uint32_t test_hp_peri_regn_addr[] = { + TRACE_DATE_REG(0), CACHE_DATE_REG, SHA_DATE_REG, RMT_DATE_REG, + PCNT_DATE_REG, PARL_IO_VERSION_REG, GPIO_DATE_REG, IO_MUX_DATE_REG, +}; + +static const apm_hal_pms_regn_cfg_t test_lp_peri_regn_cfg[] = { + /* lp_peri */ + APM_HAL_PMS_REGION_ENTRY(0, DR_REG_LP_TIMER_BASE, DR_REG_LP_ANALOG_PERI_BASE), + APM_HAL_PMS_REGION_ENTRY(1, DR_REG_LP_ANALOG_PERI_BASE, DR_REG_LP_HUK_BASE), + APM_HAL_PMS_REGION_ENTRY(2, DR_REG_LP_HUK_BASE, DR_REG_PMU_BASE), + APM_HAL_PMS_REGION_ENTRY(3, DR_REG_LP_WDT_BASE, DR_REG_LP_MB_BASE), + APM_HAL_PMS_REGION_ENTRY(4, DR_REG_LP_UART_BASE, DR_REG_LP_I2C_BASE), + APM_HAL_PMS_REGION_ENTRY(5, DR_REG_LP_I2C_BASE, DR_REG_LP_SPI_BASE), + APM_HAL_PMS_REGION_ENTRY(6, DR_REG_LP_I2C_ANA_MST_BASE, DR_REG_LP_I2S_BASE), + APM_HAL_PMS_REGION_ENTRY(7, DR_REG_LP_TRNG_BASE, DR_REG_LP_ADC_BASE), +}; + +static const uint32_t test_lp_peri_regn_addr[] = { + LP_TIMER_DATE_REG, LP_ANALOG_PERI_DATE_REG, HUK_DATE_REG, LP_WDT_DATE_REG, + LP_UART_ID_REG, LP_I2C_DATE_REG, LP_I2C_ANA_MST_DATE_REG, RNG_DATE_REG, +}; + +static void test_hp_cpu_to_peri_access(const test_pms_periph_cfg_t *cfg) +{ + apm_hal_pms_hp_peri_cfg_t hp_peri_cfg = { + .cpu_peri = UINT32_MAX, + .hp_peri0 = UINT32_MAX, + .hp_peri1 = UINT64_MAX, + }; + const uint32_t lp_peri_cfg = UINT32_MAX; + + for (uint32_t mode = APM_SEC_MODE_TEE; mode <= APM_SEC_MODE_REE; mode++) { + apm_hal_hp_peri_pms_set_hpcpu_access(0, (apm_security_mode_t)mode, &hp_peri_cfg); + apm_hal_hp2lp_peri_pms_set_hpcpu_access(0, (apm_security_mode_t)mode, lp_peri_cfg); + + for (uint32_t sid = 0; sid < cfg->test_reg_num; sid++) { + uint32_t peri_addr = cfg->test_reg[sid]; + if (peri_addr == 0) { + continue; + } + bool is_switch_req = (mode == APM_SEC_MODE_REE); + + if (is_switch_req) { + switch_priv_mode(); + } + hp_cpu_peri_addr_rw(peri_addr, false); + if (is_switch_req) { + switch_priv_mode(); + } + + switch (cfg->ctrl_mod) { + case APM_CTRL_HP_PERI_PMS: + switch (cfg->test_peri_grp) { + case HP_PERI0: + hp_peri_cfg.hp_peri0 &= ~BIT(sid); + break; + case HP_PERI1: + hp_peri_cfg.hp_peri1 &= ~BIT64(sid); + break; + case CPU_PERI: + hp_peri_cfg.cpu_peri &= ~BIT(sid); + break; + default: + TEST_ASSERT_MESSAGE(false, "Invalid group"); + return; + } + apm_hal_hp_peri_pms_set_hpcpu_access(0, (apm_security_mode_t)mode, &hp_peri_cfg); + break; + case APM_CTRL_HP2LP_PERI_PMS: + apm_hal_hp2lp_peri_pms_set_hpcpu_access(0, (apm_security_mode_t)mode, lp_peri_cfg & ~BIT(sid)); + break; + default: + break; + } + memset(&hp_peri_cfg, 0xFF, sizeof(hp_peri_cfg)); + + if (is_switch_req) { + switch_priv_mode(); + } + hp_cpu_peri_addr_rw(peri_addr, true); + if (is_switch_req) { + switch_priv_mode(); + } + } + } +} + +static void test_hp_cpu_to_peri_access_regn(const test_pms_periph_cfg_t *cfg) +{ + const apm_hal_pms_regn_cfg_t *regn_cfg; + if (cfg->test_peri_grp == LP_PERI) { + regn_cfg = test_lp_peri_regn_cfg; + } else { + regn_cfg = test_hp_peri_regn_cfg; + } + + apm_hal_lp_peri_pms_set_region_cfg(cfg->test_reg_num, regn_cfg); + + for (uint32_t mode = APM_SEC_MODE_TEE; mode <= APM_SEC_MODE_REE; mode++) { + bool is_switch_req = (mode == APM_SEC_MODE_REE); + for (uint32_t rid = 0; rid < cfg->test_reg_num; rid++) { + uint32_t peri_addr = cfg->test_reg[rid]; + + apm_hal_lp_peri_pms_set_master_region_attr(cfg->master_id, (apm_security_mode_t)mode, UINT32_MAX); + + if (is_switch_req) { + switch_priv_mode(); + } + hp_cpu_peri_addr_rw(peri_addr, false); + if (is_switch_req) { + switch_priv_mode(); + } + + apm_hal_lp_peri_pms_set_master_region_attr(cfg->master_id, (apm_security_mode_t)mode, UINT32_MAX & ~BIT(rid)); + + if (is_switch_req) { + switch_priv_mode(); + } + hp_cpu_peri_addr_rw(peri_addr, true); + if (is_switch_req) { + switch_priv_mode(); + } + } + } +} + +#if CONFIG_ULP_COPROC_ENABLED +static void test_lp_cpu_to_peri_access(const test_pms_periph_cfg_t *cfg) +{ + apm_hal_pms_hp_peri_cfg_t hp_peri_cfg = { + .cpu_peri = UINT32_MAX, + .hp_peri0 = UINT32_MAX, + .hp_peri1 = UINT64_MAX, + }; + const uint32_t lp_peri_cfg = UINT32_MAX; + + for (uint32_t sid = 0; sid < cfg->test_reg_num; sid++) { + uint32_t peri_addr = cfg->test_reg[sid]; + if (peri_addr == 0) { + continue; + } + + apm_hal_lp_peri_pms_set_lpcpu_access(lp_peri_cfg); + apm_hal_lp2hp_peri_pms_set_lpcpu_access(&hp_peri_cfg); + lp_cpu_peri_addr_rw(peri_addr, false); + + switch (cfg->ctrl_mod) { + case APM_CTRL_LP_PERI_PMS: + apm_hal_lp_peri_pms_set_lpcpu_access(lp_peri_cfg & ~BIT(sid)); + break; + case APM_CTRL_LP2HP_PERI_PMS: + switch (cfg->test_peri_grp) { + case HP_PERI0: + hp_peri_cfg.hp_peri0 &= ~BIT(sid); + break; + case HP_PERI1: + hp_peri_cfg.hp_peri1 &= ~BIT64(sid); + break; + case CPU_PERI: + hp_peri_cfg.cpu_peri &= ~BIT(sid); + break; + default: + TEST_ASSERT_MESSAGE(false, "Invalid group"); + return; + } + apm_hal_lp2hp_peri_pms_set_lpcpu_access(&hp_peri_cfg); + break; + default: + break; + } + memset(&hp_peri_cfg, 0xFF, sizeof(hp_peri_cfg)); + + lp_cpu_peri_addr_rw(peri_addr, true); + } +} + +static void test_lp_cpu_to_peri_access_regn(const test_pms_periph_cfg_t *cfg) +{ + const apm_hal_pms_regn_cfg_t *regn_cfg; + if (cfg->test_peri_grp == LP_PERI) { + regn_cfg = test_lp_peri_regn_cfg; + } else { + regn_cfg = test_hp_peri_regn_cfg; + } + + apm_hal_lp_peri_pms_set_region_cfg(cfg->test_reg_num, regn_cfg); + + for (uint32_t rid = 0; rid < cfg->test_reg_num; rid++) { + uint32_t peri_addr = cfg->test_reg[rid]; + + apm_hal_lp_peri_pms_set_master_region_attr(cfg->master_id, APM_SEC_MODE_TEE, UINT32_MAX); + lp_cpu_peri_addr_rw(peri_addr, false); + + apm_hal_lp_peri_pms_set_master_region_attr(cfg->master_id, APM_SEC_MODE_TEE, UINT32_MAX & ~BIT(rid)); + lp_cpu_peri_addr_rw(peri_addr, true); + } +} +#endif + +void test_sys_pms_master_hp_cpu_slave_hp_peri(void) +{ + const test_pms_periph_cfg_t cfgs[] = { + { + .master_id = APM_MASTER_HPCPU0, + .ctrl_mod = APM_CTRL_HP_PERI_PMS, + .test_reg = test_hp_peri0_reg, + .test_reg_num = sizeof(test_hp_peri0_reg) / sizeof(test_hp_peri0_reg[0]), + .test_peri_grp = HP_PERI0, + }, + { + .master_id = APM_MASTER_HPCPU0, + .ctrl_mod = APM_CTRL_HP_PERI_PMS, + .test_reg = test_hp_peri1_reg, + .test_reg_num = sizeof(test_hp_peri1_reg) / sizeof(test_hp_peri1_reg[0]), + .test_peri_grp = HP_PERI1, + }, + { + .master_id = APM_MASTER_HPCPU0, + .ctrl_mod = APM_CTRL_HP_PERI_PMS, + .test_reg = test_cpu_peri_reg, + .test_reg_num = sizeof(test_cpu_peri_reg) / sizeof(test_cpu_peri_reg[0]), + .test_peri_grp = CPU_PERI, + }, + }; + + test_pms_ctrl_reset_all(); + set_test_vector_table(); + + for (int i = 0; i < sizeof(cfgs) / sizeof(cfgs[0]); i++) { + test_hp_cpu_to_peri_access(&cfgs[i]); + } + + restore_default_vector_table(); +} + +void test_sys_pms_master_hp_cpu_slave_lp_peri(void) +{ + const test_pms_periph_cfg_t cfg = { + .master_id = APM_MASTER_HPCPU0, + .ctrl_mod = APM_CTRL_HP2LP_PERI_PMS, + .test_reg = test_lp_peri_reg, + .test_reg_num = sizeof(test_lp_peri_reg) / sizeof(test_lp_peri_reg[0]), + }; + + test_pms_ctrl_reset_all(); + set_test_vector_table(); + + test_hp_cpu_to_peri_access(&cfg); + + restore_default_vector_table(); +} + +void test_sys_pms_master_hp_cpu_peri_regn_access(void) +{ + const test_pms_periph_cfg_t hp_peri_regn_cfg = { + .master_id = APM_MASTER_HPCPU0, + .test_reg = test_hp_peri_regn_addr, + .test_reg_num = sizeof(test_hp_peri_regn_addr) / sizeof(test_hp_peri_regn_addr[0]), + }; + + const test_pms_periph_cfg_t lp_peri_regn_cfg = { + .master_id = APM_MASTER_HPCPU0, + .test_reg = test_lp_peri_regn_addr, + .test_reg_num = sizeof(test_lp_peri_regn_addr) / sizeof(test_lp_peri_regn_addr[0]), + .test_peri_grp = LP_PERI, + }; + + test_pms_ctrl_reset_all(); + set_test_vector_table(); + + test_hp_cpu_to_peri_access_regn(&hp_peri_regn_cfg); + test_hp_cpu_to_peri_access_regn(&lp_peri_regn_cfg); + + restore_default_vector_table(); +} + +#if CONFIG_ULP_COPROC_ENABLED +void test_sys_pms_master_lp_cpu_slave_hp_peri(void) +{ + const test_pms_periph_cfg_t cfgs[] = { + { + .master_id = APM_MASTER_LPCPU, + .ctrl_mod = APM_CTRL_LP2HP_PERI_PMS, + .test_reg = test_hp_peri0_reg, + .test_reg_num = sizeof(test_hp_peri0_reg) / sizeof(test_hp_peri0_reg[0]), + .test_peri_grp = HP_PERI0, + }, + { + .master_id = APM_MASTER_LPCPU, + .ctrl_mod = APM_CTRL_LP2HP_PERI_PMS, + .test_reg = test_hp_peri1_reg, + .test_reg_num = sizeof(test_hp_peri1_reg) / sizeof(test_hp_peri1_reg[0]), + .test_peri_grp = HP_PERI1, + }, + { + .master_id = APM_MASTER_LPCPU, + .ctrl_mod = APM_CTRL_LP2HP_PERI_PMS, + .test_reg = test_cpu_peri_reg, + .test_reg_num = sizeof(test_cpu_peri_reg) / sizeof(test_cpu_peri_reg[0]), + .test_peri_grp = CPU_PERI, + }, + }; + + test_pms_ctrl_reset_all(); + test_boot_lp_cpu(); + set_test_vector_table(); + + for (int i = 0; i < sizeof(cfgs) / sizeof(cfgs[0]); i++) { + test_lp_cpu_to_peri_access(&cfgs[i]); + } + + restore_default_vector_table(); + test_stop_lp_cpu(); +} + +void test_sys_pms_master_lp_cpu_slave_lp_peri(void) +{ + const test_pms_periph_cfg_t cfg = { + .master_id = APM_MASTER_LPCPU, + .ctrl_mod = APM_CTRL_LP_PERI_PMS, + .test_reg = test_lp_peri_reg, + .test_reg_num = sizeof(test_lp_peri_reg) / sizeof(test_lp_peri_reg[0]), + }; + + test_pms_ctrl_reset_all(); + test_pms_enable_intr(APM_CTRL_LP_PERI_PMS); + test_boot_lp_cpu(); + + set_test_vector_table(); + test_lp_cpu_to_peri_access(&cfg); + restore_default_vector_table(); + + test_stop_lp_cpu(); +} + +void test_sys_pms_master_lp_cpu_peri_regn_access(void) +{ + const test_pms_periph_cfg_t hp_peri_regn_cfg = { + .master_id = APM_MASTER_LPCPU, + .test_reg = test_hp_peri_regn_addr, + .test_reg_num = sizeof(test_hp_peri_regn_addr) / sizeof(test_hp_peri_regn_addr[0]), + }; + + const test_pms_periph_cfg_t lp_peri_regn_cfg = { + .master_id = APM_MASTER_LPCPU, + .test_reg = test_lp_peri_regn_addr, + .test_reg_num = sizeof(test_lp_peri_regn_addr) / sizeof(test_lp_peri_regn_addr[0]), + .test_peri_grp = LP_PERI, + }; + + test_pms_ctrl_reset_all(); + test_pms_enable_intr(APM_CTRL_LP_PERI_PMS); + test_boot_lp_cpu(); + + set_test_vector_table(); + test_lp_cpu_to_peri_access_regn(&hp_peri_regn_cfg); + test_lp_cpu_to_peri_access_regn(&lp_peri_regn_cfg); + restore_default_vector_table(); + + test_stop_lp_cpu(); +} +#endif + +/***************************** DMA_PMS *****************************/ + +typedef struct { + apm_master_dma_id_t master_id; + uint32_t mem_start_addr; + uint32_t mem_end_addr; + uint32_t regn_count; + uint32_t regn_sz; + bool is_ext_mem; +} test_dma_pms_mem_cfg_t; + +#define GDMA_TEST_REGN_RESV_NUM(is_ext_mem) \ + ((is_ext_mem) ? GDMA_EXTMEM_TEST_REGN_RESV_NUM : GDMA_HPMEM_TEST_REGN_RESV_NUM) + +static void test_dma_pms_mem_setup(const test_dma_pms_mem_cfg_t *cfg, uint32_t test_start, uint32_t test_end) +{ + apm_hal_pms_regn_cfg_t regn_cfgs[GDMA_HPMEM_TEST_REGN_NUM] = {0}; + + regn_cfgs[0] = (apm_hal_pms_regn_cfg_t)APM_HAL_PMS_REGION_ENTRY(0, cfg->mem_start_addr, test_start); + regn_cfgs[1] = (apm_hal_pms_regn_cfg_t)APM_HAL_PMS_REGION_ENTRY(1, test_end, cfg->mem_end_addr); + + const uint32_t test_regn_start = GDMA_TEST_REGN_RESV_NUM(cfg->is_ext_mem); + if (cfg->is_ext_mem) { + regn_cfgs[2] = (apm_hal_pms_regn_cfg_t)APM_HAL_PMS_REGION_ENTRY(2, SOC_IRAM_LOW, SOC_DRAM_HIGH); + } + + for (uint32_t idx = test_regn_start; idx < cfg->regn_count; idx++) { + uint32_t regn_start = test_start + (idx - test_regn_start) * cfg->regn_sz; + regn_cfgs[idx] = (apm_hal_pms_regn_cfg_t)APM_HAL_PMS_REGION_ENTRY(idx, regn_start, regn_start + cfg->regn_sz); + } + + apm_hal_dma_pms_set_region_cfg(GDMA_HPMEM_TEST_REGN_NUM, regn_cfgs); +} + +static void gdma_hpmem_addr_rw(uint8_t *src, uint8_t *dest, size_t size, bool should_panic) +{ + pms_dma_excp_flag = false; + memset(src, 0xA5, size); + esp_cache_msync(src, size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); + + test_gdma_init(); + test_gdma_m2m_transfer(src, dest, size); + + test_delay_ms(10); + if (should_panic) { + TEST_ASSERT(pms_dma_excp_flag); + } else { + test_gdma_wait_done(); + esp_cache_msync(dest, size, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + TEST_ASSERT_FALSE(pms_dma_excp_flag); + TEST_ASSERT_EQUAL_HEX8_ARRAY(src, dest, size); + } + + test_gdma_deinit(); + pms_dma_excp_flag = false; +} + +static void test_gdma_to_xmem_access(const test_dma_pms_mem_cfg_t *cfg, uint32_t test_start_addr) +{ + uint8_t *test_dma_buf = heap_caps_aligned_alloc(cfg->regn_sz, cfg->regn_sz, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(test_dma_buf); + memset(test_dma_buf, 0x5A, cfg->regn_sz); + + const uint32_t test_regn_start = GDMA_TEST_REGN_RESV_NUM(cfg->is_ext_mem); + const uint32_t resv_regn = BIT(test_regn_start) - 1; + + for (uint32_t regn_idx = test_regn_start; regn_idx < cfg->regn_count; regn_idx++) { + uint8_t *regn_start = (uint8_t *)(test_start_addr + (regn_idx - test_regn_start) * cfg->regn_sz); + + apm_hal_dma_pms_set_master_region_attr(cfg->master_id, resv_regn, resv_regn | BIT(regn_idx)); + gdma_hpmem_addr_rw(regn_start, test_dma_buf, cfg->regn_sz, true); + gdma_hpmem_addr_rw(test_dma_buf, regn_start, cfg->regn_sz, false); + + apm_hal_dma_pms_set_master_region_attr(cfg->master_id, resv_regn | BIT(regn_idx), resv_regn); + gdma_hpmem_addr_rw(regn_start, test_dma_buf, cfg->regn_sz, false); + gdma_hpmem_addr_rw(test_dma_buf, regn_start, cfg->regn_sz, true); + + apm_hal_dma_pms_set_master_region_attr(cfg->master_id, UINT32_MAX, UINT32_MAX); + } + + free(test_dma_buf); +} + +void test_sys_pms_master_gdma_slave_hp_mem(void) +{ + test_pms_ctrl_reset_all(); + test_pms_enable_intr(APM_CTRL_DMA_PMS); + + const uint32_t total_sz = (GDMA_HPMEM_TEST_REGN_NUM - GDMA_HPMEM_TEST_REGN_RESV_NUM) * GDMA_HPMEM_TEST_REGN_SIZE; + test_dma_pms_mem_cfg_t cfg = { + .master_id = APM_MASTER_DMA_AHB_PDMA_DUMMY, + .mem_start_addr = SOC_IRAM_LOW, + .mem_end_addr = SOC_DRAM_HIGH, + .regn_count = GDMA_HPMEM_TEST_REGN_NUM, + .regn_sz = GDMA_HPMEM_TEST_REGN_SIZE, + }; + + uint8_t *test_hpmem_buf = heap_caps_aligned_alloc(cfg.regn_sz, total_sz, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(test_hpmem_buf); + + uint32_t test_start_addr = (uint32_t)test_hpmem_buf; + uint32_t test_end_addr = test_start_addr + total_sz; + test_dma_pms_mem_setup(&cfg, test_start_addr, test_end_addr); + + test_gdma_to_xmem_access(&cfg, test_start_addr); + free(test_hpmem_buf); +} + +#if CONFIG_SPIRAM +void test_sys_pms_master_gdma_slave_ext_mem(void) +{ + test_pms_ctrl_reset_all(); + test_pms_enable_intr(APM_CTRL_DMA_PMS); + + const uint32_t total_sz = (GDMA_HPMEM_TEST_REGN_NUM - GDMA_EXTMEM_TEST_REGN_RESV_NUM) * GDMA_HPMEM_TEST_REGN_SIZE; + test_dma_pms_mem_cfg_t cfg = { + .master_id = APM_MASTER_DMA_AHB_PDMA_DUMMY, + .mem_start_addr = SOC_EXTRAM_LOW, + .mem_end_addr = SOC_EXTRAM_HIGH, + .regn_count = GDMA_HPMEM_TEST_REGN_NUM, + .regn_sz = GDMA_HPMEM_TEST_REGN_SIZE, + .is_ext_mem = true, + }; + + uint8_t *test_extmem_buf = heap_caps_aligned_alloc(cfg.regn_sz, total_sz, MALLOC_CAP_SPIRAM); + TEST_ASSERT_NOT_NULL(test_extmem_buf); + + uint32_t test_start_addr = (uint32_t)test_extmem_buf; + uint32_t test_end_addr = test_start_addr + total_sz; + test_dma_pms_mem_setup(&cfg, test_start_addr, test_end_addr); + + test_gdma_to_xmem_access(&cfg, test_start_addr); + free(test_extmem_buf); +} +#endif diff --git a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/pms/test_tee_sys_apm.c b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/pms/test_tee_sys_apm.c index 6f8de78a6b4..23c3ef3d4d2 100644 --- a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/pms/test_tee_sys_apm.c +++ b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/pms/test_tee_sys_apm.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,9 +14,8 @@ #include "hal/apm_hal.h" #include "hal/apm_types.h" -#include "rom/cache.h" +#include "esp_cache.h" #include "esp_rom_sys.h" -#include "esp_memory_utils.h" #include "esp_heap_caps.h" #include "test_pms_priv.h" @@ -34,7 +33,25 @@ APM_HAL_REGION_ENTRY(path, id, start, end, perm) #endif -extern bool apm_master_excp_flag[APM_MASTER_MAX]; +typedef struct { + apm_master_id_t master_id; + apm_ctrl_module_t ctrl_mod; + apm_ctrl_access_path_t path; + uint32_t mem_start_addr; + uint32_t mem_end_addr; + uint32_t regn_count; + uint32_t regn_sz; +} test_sys_apm_mem_cfg_t; + +typedef struct { + apm_master_id_t master_id; + apm_ctrl_module_t ctrl_mod; + const uint32_t *test_addr; + uint32_t test_addr_num; + uint32_t test_addr_resv_mask; +} test_sys_apm_periph_cfg_t; + +extern volatile bool apm_master_excp_flag[APM_MASTER_MAX]; /***************************** APM setup for memory *****************************/ @@ -65,31 +82,21 @@ static void test_mem_apm_setup(test_sys_apm_mem_cfg_t *cfg, uint32_t test_start_ /***************************** GDMA: Utility *****************************/ -static void gdma_xmem_addr_rw(uint8_t *src, uint8_t *dest, size_t size, uint32_t test_attr) +static void gdma_xmem_addr_rw(uint8_t *src, uint8_t *dest, size_t size, bool should_panic) { apm_master_excp_flag[TEST_GDMA_APM_MASTER_ID] = false; - memset(src, TEST_VAL, size); + memset(src, 0xA5, size); + esp_cache_msync(src, size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); test_gdma_init(); -#if CONFIG_SPIRAM - if (esp_ptr_external_ram(src)) { - Cache_WriteBack_Addr((uint32_t)src, size); - } -#endif test_gdma_m2m_transfer(src, dest, size); -#if CONFIG_SPIRAM - if (esp_ptr_external_ram(dest)) { - Cache_Invalidate_Addr((uint32_t)dest, size); - } -#endif - if (!test_attr) { - test_delay_ms(10); + test_delay_ms(10); + if (should_panic) { TEST_ASSERT(apm_master_excp_flag[TEST_GDMA_APM_MASTER_ID]); - test_gdma_wait_done(); } else { test_gdma_wait_done(); - test_delay_ms(10); + esp_cache_msync(dest, size, ESP_CACHE_MSYNC_FLAG_DIR_M2C); TEST_ASSERT_FALSE(apm_master_excp_flag[TEST_GDMA_APM_MASTER_ID]); TEST_ASSERT_EQUAL_HEX8_ARRAY(src, dest, size); } @@ -109,26 +116,22 @@ static void test_gdma_to_xmem_access(const test_sys_apm_mem_cfg_t *cfg, uint32_t for (uint32_t regn_idx = 2; regn_idx < cfg->regn_count; regn_idx++) { uint8_t *regn_start = (uint8_t *)(test_start_addr + (regn_idx - 2) * cfg->regn_sz); - uint32_t pms_attr = APM_PERM_NONE; if (mode == APM_SEC_MODE_TEE) { - pms_attr = APM_PERM_R | APM_PERM_W; - gdma_xmem_addr_rw(regn_start, test_dma_buf, cfg->regn_sz, pms_attr & APM_PERM_R); - gdma_xmem_addr_rw(test_dma_buf, regn_start, cfg->regn_sz, pms_attr & APM_PERM_W); + gdma_xmem_addr_rw(regn_start, test_dma_buf, cfg->regn_sz, false); + gdma_xmem_addr_rw(test_dma_buf, regn_start, cfg->regn_sz, false); continue; } - pms_attr = APM_PERM_W; apm_hal_set_sec_mode_region_attr(cfg->ctrl_mod, regn_idx, mode, APM_PERM_NONE); - apm_hal_set_sec_mode_region_attr(cfg->ctrl_mod, regn_idx, mode, pms_attr); - gdma_xmem_addr_rw(regn_start, test_dma_buf, cfg->regn_sz, pms_attr & APM_PERM_R); - gdma_xmem_addr_rw(test_dma_buf, regn_start, cfg->regn_sz, pms_attr & APM_PERM_W); + apm_hal_set_sec_mode_region_attr(cfg->ctrl_mod, regn_idx, mode, APM_PERM_W); + gdma_xmem_addr_rw(regn_start, test_dma_buf, cfg->regn_sz, true); + gdma_xmem_addr_rw(test_dma_buf, regn_start, cfg->regn_sz, false); - pms_attr = APM_PERM_R; apm_hal_set_sec_mode_region_attr(cfg->ctrl_mod, regn_idx, mode, APM_PERM_NONE); - apm_hal_set_sec_mode_region_attr(cfg->ctrl_mod, regn_idx, mode, pms_attr); - gdma_xmem_addr_rw(regn_start, test_dma_buf, cfg->regn_sz, pms_attr & APM_PERM_R); - gdma_xmem_addr_rw(test_dma_buf, regn_start, cfg->regn_sz, pms_attr & APM_PERM_W); + apm_hal_set_sec_mode_region_attr(cfg->ctrl_mod, regn_idx, mode, APM_PERM_R); + gdma_xmem_addr_rw(regn_start, test_dma_buf, cfg->regn_sz, false); + gdma_xmem_addr_rw(test_dma_buf, regn_start, cfg->regn_sz, true); apm_hal_set_sec_mode_region_attr(cfg->ctrl_mod, regn_idx, mode, APM_PERM_ALL); } @@ -545,7 +548,7 @@ static void lp_cpu_xmem_addr_rw(uint32_t mem_addr, size_t size, uint32_t attr) SEND_MSG(MSG_SLAVE_WRITE); SEND_ADDR(mem_addr); - SEND_SIZE(sizeof(uint32_t)); + SEND_DATA(sizeof(uint32_t)); test_delay_ms(10); bool can_write = (attr & APM_PERM_W); @@ -868,13 +871,13 @@ void test_tee_mode_default_access(void) test_tee_mode_apm_setup(&cfg, (uint32_t)test_hpmem_buf, (uint32_t)test_hpmem_buf + total_sz); apm_ll_hp_tee_set_master_sec_mode(TEST_GDMA_APM_MASTER_ID, APM_SEC_MODE_TEE); - uint32_t pms_attr = APM_PERM_R | APM_PERM_W; + bool should_panic = false; #if SOC_APM_CTRL_TEE_MODE_ACCESS_BUG - pms_attr = APM_PERM_NONE; + should_panic = true; #endif - gdma_xmem_addr_rw(test_hpmem_buf, test_dma_buf, total_sz, pms_attr & APM_PERM_R); - gdma_xmem_addr_rw(test_dma_buf, test_hpmem_buf, total_sz, pms_attr & APM_PERM_W); + gdma_xmem_addr_rw(test_hpmem_buf, test_dma_buf, total_sz, should_panic); + gdma_xmem_addr_rw(test_dma_buf, test_hpmem_buf, total_sz, should_panic); free(test_dma_buf); free(test_hpmem_buf); diff --git a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/ulp/ulp_lp_core_main.c b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/ulp/ulp_lp_core_main.c index 44feb46850a..4e282fed2d7 100644 --- a/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/ulp/ulp_lp_core_main.c +++ b/components/esp_hal_security/test_apps/tee/components/pms_and_cpu_intr/src/ulp/ulp_lp_core_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,6 +8,7 @@ #include #include "soc/soc.h" +#include "esp_attr.h" #include "riscv/csr.h" #include "riscv/rv_utils.h" @@ -53,6 +54,32 @@ void test_panicHandler(void *frame, int exccause) return; } +NOINLINE_ATTR static uint32_t reg_read(uint32_t addr) +{ + uint32_t value; + __asm__ volatile( + "lw %0, 0(%1)\n" + "fence\n" + "nop\nnop\nnop\nnop\n" + : "=r"(value) + : "r"(addr) + : "memory" + ); + return value; +} + +NOINLINE_ATTR static void reg_write(uint32_t addr, uint32_t value) +{ + __asm__ volatile( + "sw %1, 0(%0)\n" + "fence\n" + "nop\nnop\nnop\nnop\n" + : + : "r"(addr), "r"(value) + : "memory" + ); +} + /** * @brief Test LP CPU access to memory/peripherals * @@ -84,14 +111,14 @@ int main(void) } uint32_t test_addr = RECV_ADDR(); - uint32_t test_size = RECV_SIZE(); + uint32_t test_data = RECV_DATA(); switch (test_msg) { case MSG_SLAVE_READ: - (void)REG_READ(test_addr); + (void)reg_read(test_addr); break; case MSG_SLAVE_WRITE: - REG_WRITE(test_addr, test_size); + reg_write(test_addr, test_data); break; case MSG_SLAVE_EXEC: { void (*func_ptr)(void) = (void (*)(void))(test_addr); diff --git a/components/esp_hal_security/test_apps/tee/main/test_pms.c b/components/esp_hal_security/test_apps/tee/main/test_pms.c index 297e582a5ad..631be942763 100644 --- a/components/esp_hal_security/test_apps/tee/main/test_pms.c +++ b/components/esp_hal_security/test_apps/tee/main/test_pms.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -245,4 +245,116 @@ TEST_CASE("Test LP_CPU -> LP_PERI access", "[PERI_APM]") } #endif /* CONFIG_ULP_COPROC_ENABLED */ #endif +#else +/** + * Test HP-CPU access to HP_PERI + * + * PMS uses per-peripheral based access control with per-master read/write permissions. + * For each peripheral, tests HP-CPU read/write access with varying permissions: + * all access (both read and write pass) and no access (both read and write fail). + * Verifies enforcement of PMS access control by asserting expected load/store access faults. + */ +TEST_CASE("Test HP_CPU -> HP_PERI access", "[SYS_APM]") +{ + test_sys_pms_master_hp_cpu_slave_hp_peri(); +} + +/** + * Test HP-CPU access to LP_PERI + * + * PMS uses per-peripheral based access control with per-master read/write permissions. + * For each peripheral, tests HP-CPU read/write access with varying permissions: + * all access (both read and write pass) and no access (both read and write fail). + * Verifies enforcement of PMS access control by asserting expected load/store access faults. + */ +TEST_CASE("Test HP_CPU -> LP_PERI access", "[SYS_APM]") +{ + test_sys_pms_master_hp_cpu_slave_lp_peri(); +} + +/** + * Test HP-CPU access to HP_PERI and LP_PERI (configurable regions) + * + * PMS also provides region-based access control with start/end address boundaries and per-master + * read/write permissions. Configures PMS regions covering HP_PERI and LP_PERI address + * ranges. For each region, tests HP-CPU read/write access with varying permissions in + * both TEE and REE modes: all access (both read and write pass) and no access (both read + * and write fail). Verifies enforcement of PMS access control by asserting expected PMS violations. + */ +TEST_CASE("Test HP_CPU -> PERI access (configurable regions)", "[SYS_APM]") +{ + test_sys_pms_master_hp_cpu_peri_regn_access(); +} + +#if CONFIG_ULP_COPROC_ENABLED +/** + * Test LP-CPU access to HP_PERI + * + * PMS uses per-peripheral based access control with per-master read/write permissions. + * For each peripheral, tests LP-CPU read/write access with varying permissions: + * all access (both read and write pass) and no access (both read and write fail). + * Verifies enforcement of PMS access control by asserting expected load/store access faults. + */ +TEST_CASE("Test LP_CPU -> HP_PERI access", "[SYS_APM]") +{ + test_sys_pms_master_lp_cpu_slave_hp_peri(); +} + +/** + * Test LP-CPU access to LP_PERI + * + * PMS uses per-peripheral based access control with per-master read/write permissions. + * For each peripheral, tests LP-CPU read/write access with varying permissions: + * all access (both read and write pass) and no access (both read and write fail). + * Verifies enforcement of PMS access control by asserting expected PMS violations. + */ +TEST_CASE("Test LP_CPU -> LP_PERI access", "[SYS_APM]") +{ + test_sys_pms_master_lp_cpu_slave_lp_peri(); +} + +/** + * Test LP-CPU access to HP_PERI and LP_PERI (configurable regions) + * + * PMS uses region-based access control with start/end address boundaries and per-master + * read/write permissions. Configures PMS regions covering HP_PERI and LP_PERI address + * ranges. For each region, tests LP-CPU read/write access with varying permissions: + * all access (both read and write pass) and no access (both read and write fail). + * Verifies enforcement of PMS access control by asserting expected PMS violations. + */ +TEST_CASE("Test LP_CPU -> PERI access (configurable regions)", "[SYS_APM]") +{ + test_sys_pms_master_lp_cpu_peri_regn_access(); +} +#endif /* CONFIG_ULP_COPROC_ENABLED */ + +/** + * Test GDMA access to HP_MEM + * + * PMS uses region-based access control with start/end address boundaries and per-master + * read/write permissions. Divides a contiguous HP_MEM block into multiple PMS regions and + * configures their boundaries. For each region, tests GDMA read/write access with varying + * permissions: R-only (read passes, write fails) and W-only (write passes, read fails). + * Verifies enforcement of PMS access control by asserting expected PMS violations. + */ +TEST_CASE("Test GDMA -> HP_MEM access", "[SYS_APM]") +{ + test_sys_pms_master_gdma_slave_hp_mem(); +} + +#if CONFIG_SPIRAM +/** + * Test GDMA access to EXT_MEM (SPIRAM) + * + * PMS uses region-based access control with start/end address boundaries and per-master + * read/write permissions. Divides a contiguous EXT_MEM block into multiple PMS regions and + * configures their boundaries. For each region, tests GDMA read/write access with varying + * permissions: R-only (read passes, write fails) and W-only (write passes, read fails). + * Verifies enforcement of PMS access control by asserting expected PMS violations. + */ +TEST_CASE("Test GDMA -> EXT_MEM access", "[SYS_APM]") +{ + test_sys_pms_master_gdma_slave_ext_mem(); +} +#endif /* CONFIG_SPIRAM */ #endif /* SOC_APM_CTRL_FILTER_SUPPORTED */ diff --git a/components/esp_hal_security/test_apps/tee/pytest_pms_and_cpu_intr.py b/components/esp_hal_security/test_apps/tee/pytest_pms_and_cpu_intr.py index 729db08e3ac..348a2b7b47f 100644 --- a/components/esp_hal_security/test_apps/tee/pytest_pms_and_cpu_intr.py +++ b/components/esp_hal_security/test_apps/tee/pytest_pms_and_cpu_intr.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded_idf import IdfDut @@ -6,7 +6,7 @@ from pytest_embedded_idf.utils import idf_parametrize # ---------------- Pytest build parameters ---------------- -SOC_SUPPORT_SYS_APM_TEST = ['esp32c6', 'esp32h2', 'esp32c5', 'esp32c61'] +SOC_SUPPORT_SYS_APM_TEST = ['esp32c6', 'esp32h2', 'esp32c5', 'esp32c61', 'esp32p4'] SOC_SUPPORT_PERI_APM_TEST = ['esp32c5'] SOC_SUPPORT_INTR_TEST = ['esp32c5', 'esp32c61', 'esp32p4'] diff --git a/components/esp_hal_security/test_apps/tee/sdkconfig.defaults.esp32p4 b/components/esp_hal_security/test_apps/tee/sdkconfig.defaults.esp32p4 index 153bd95bfc9..7b7e4c56a9e 100644 --- a/components/esp_hal_security/test_apps/tee/sdkconfig.defaults.esp32p4 +++ b/components/esp_hal_security/test_apps/tee/sdkconfig.defaults.esp32p4 @@ -2,3 +2,11 @@ # U-mode for multicore SoCs. Thus, TEE interrupt tests will # run only in unicore mode till then. CONFIG_FREERTOS_UNICORE=y + +# Enable LP core +CONFIG_ULP_COPROC_ENABLED=y +CONFIG_ULP_COPROC_RESERVE_MEM=8192 +CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=n + +# Enable SPIRAM +CONFIG_SPIRAM=y