From d8601f8245689dac20704b9237840380b0694d09 Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Sat, 21 Jun 2025 14:35:03 +0530 Subject: [PATCH 1/2] feat(hal): Add `CPU_APM` support for ESP32-C61 --- components/hal/apm_hal.c | 73 +++++++ components/hal/esp32c61/include/hal/apm_ll.h | 191 ++++++++++++++++++ components/hal/include/hal/apm_hal.h | 27 +++ .../esp32c61/include/soc/Kconfig.soc_caps.in | 4 + .../soc/esp32c61/include/soc/apm_defs.h | 2 + .../soc/esp32c61/include/soc/soc_caps.h | 1 + .../soc/esp32c61/register/soc/cpu_apm_reg.h | 74 +++---- 7 files changed, 335 insertions(+), 37 deletions(-) diff --git a/components/hal/apm_hal.c b/components/hal/apm_hal.c index 20325ad8ca..1591337a14 100644 --- a/components/hal/apm_hal.c +++ b/components/hal/apm_hal.c @@ -218,9 +218,82 @@ void apm_hal_enable_region_filter(apm_ctrl_module_t ctrl_mod, uint32_t regn_num, } } +void apm_hal_set_region_start_addr(apm_ctrl_module_t ctrl_mod, uint32_t regn_num, uint32_t addr) +{ + switch (ctrl_mod) { + case APM_CTRL_HP_APM: + apm_ll_hp_apm_set_region_start_addr(regn_num, addr); + break; +#if SOC_APM_LP_APM0_SUPPORTED + case APM_CTRL_LP_APM0: + apm_ll_lp_apm0_set_region_start_addr(regn_num, addr); + break; +#endif + case APM_CTRL_LP_APM: + apm_ll_lp_apm_set_region_start_addr(regn_num, addr); + break; +#if SOC_APM_CPU_APM_SUPPORTED + case APM_CTRL_CPU_APM: + apm_ll_cpu_apm_set_region_start_addr(regn_num, addr); + break; +#endif + default: + break; + } +} + +void apm_hal_set_region_end_addr(apm_ctrl_module_t ctrl_mod, uint32_t regn_num, uint32_t addr) +{ + switch (ctrl_mod) { + case APM_CTRL_HP_APM: + apm_ll_hp_apm_set_region_end_addr(regn_num, addr); + break; +#if SOC_APM_LP_APM0_SUPPORTED + case APM_CTRL_LP_APM0: + apm_ll_lp_apm0_set_region_end_addr(regn_num, addr); + break; +#endif + case APM_CTRL_LP_APM: + apm_ll_lp_apm_set_region_end_addr(regn_num, addr); + break; +#if SOC_APM_CPU_APM_SUPPORTED + case APM_CTRL_CPU_APM: + apm_ll_cpu_apm_set_region_end_addr(regn_num, addr); + break; +#endif + default: + break; + } +} + +void apm_hal_set_sec_mode_region_attr(apm_ctrl_module_t ctrl_mod, uint32_t regn_num, apm_security_mode_t mode, uint32_t regn_pms) +{ + switch (ctrl_mod) { + case APM_CTRL_HP_APM: + apm_ll_hp_apm_set_sec_mode_region_attr(regn_num, mode, regn_pms); + break; +#if SOC_APM_LP_APM0_SUPPORTED + case APM_CTRL_LP_APM0: + apm_ll_lp_apm0_set_sec_mode_region_attr(regn_num, mode, regn_pms); + break; +#endif + case APM_CTRL_LP_APM: + apm_ll_lp_apm_set_sec_mode_region_attr(regn_num, mode, regn_pms); + break; +#if SOC_APM_CPU_APM_SUPPORTED + case APM_CTRL_CPU_APM: + apm_ll_cpu_apm_set_sec_mode_region_attr(regn_num, mode, regn_pms); + break; +#endif + default: + break; + } +} + void apm_hal_set_region_filter_cfg(apm_ctrl_module_t ctrl_mod, apm_security_mode_t mode, const apm_hal_ctrl_region_cfg_t *regn_cfg) { HAL_ASSERT(regn_cfg); + HAL_ASSERT(mode != APM_SEC_MODE_TEE); switch (ctrl_mod) { case APM_CTRL_HP_APM: diff --git a/components/hal/esp32c61/include/hal/apm_ll.h b/components/hal/esp32c61/include/hal/apm_ll.h index 8f730df5e6..ff90cce104 100644 --- a/components/hal/esp32c61/include/hal/apm_ll.h +++ b/components/hal/esp32c61/include/hal/apm_ll.h @@ -14,6 +14,8 @@ #include "soc/hp_apm_struct.h" #include "soc/lp_apm_reg.h" #include "soc/lp_apm_struct.h" +#include "soc/cpu_apm_reg.h" +#include "soc/cpu_apm_struct.h" #include "soc/pcr_reg.h" #include "soc/interrupts.h" @@ -448,6 +450,195 @@ static inline int apm_ll_lp_apm_get_ctrl_intr_src(apm_ctrl_access_path_t path) return ETS_LP_APM_M0_INTR_SOURCE; } +/** + * @brief Enable/disable controller filter for specific path in CPU-APM + * + * @param path Access path + * @param enable True to enable, false to disable + */ +static inline void apm_ll_cpu_apm_enable_ctrl_filter(apm_ctrl_access_path_t path, bool enable) +{ + if (enable) { + REG_SET_BIT(CPU_APM_FUNC_CTRL_REG, BIT(path)); + } else { + REG_CLR_BIT(CPU_APM_FUNC_CTRL_REG, BIT(path)); + } +} + +/** + * @brief Enable/disable all controller filters in CPU-APM + * + * @param enable True to enable, false to disable + */ +static inline void apm_ll_cpu_apm_enable_ctrl_filter_all(bool enable) +{ + REG_WRITE(CPU_APM_FUNC_CTRL_REG, enable ? UINT32_MAX : 0); +} + +/** + * @brief Enable/disable region filter in CPU-APM + * + * @param regn_num Region number + * @param enable True to enable, false to disable + */ +static inline void apm_ll_cpu_apm_enable_region_filter(uint32_t regn_num, bool enable) +{ + if (enable) { + REG_SET_BIT(CPU_APM_REGION_FILTER_EN_REG, BIT(regn_num)); + } else { + REG_CLR_BIT(CPU_APM_REGION_FILTER_EN_REG, BIT(regn_num)); + } +} + +/** + * @brief Set region start address in CPU-APM + * + * @param regn_num Region number + * @param addr Start address + */ +static inline void apm_ll_cpu_apm_set_region_start_addr(uint32_t regn_num, uint32_t addr) +{ + REG_WRITE(CPU_APM_REGION0_ADDR_START_REG + APM_REGION_ADDR_OFFSET * regn_num, addr); +} + +/** + * @brief Set region end address in CPU-APM + * + * @param regn_num Region number + * @param addr End address + */ +static inline void apm_ll_cpu_apm_set_region_end_addr(uint32_t regn_num, uint32_t addr) +{ + REG_WRITE(CPU_APM_REGION0_ADDR_END_REG + APM_REGION_ADDR_OFFSET * regn_num, addr); +} + +/** + * @brief Set security mode region attributes in CPU-APM + * + * @param regn_num Region number + * @param mode Security mode + * @param regn_pms Region PMS attributes + */ +static inline void apm_ll_cpu_apm_set_sec_mode_region_attr(uint32_t regn_num, apm_security_mode_t mode, uint32_t regn_pms) +{ + uint32_t reg = CPU_APM_REGION0_ATTR_REG + APM_REGION_ATTR_OFFSET * regn_num; + uint32_t val = REG_READ(reg); + val &= ~APM_REGION_PMS_MASK(mode); + val |= APM_REGION_PMS_FIELD(mode, regn_pms); + REG_WRITE(reg, val); +} + +/** + * @brief Lock security mode region attributes in CPU-APM + * + * @param regn_num Region number + */ +static inline void apm_ll_cpu_apm_lock_sec_mode_region_attr(uint32_t regn_num) +{ + REG_SET_BIT(CPU_APM_REGION0_ATTR_REG + APM_REGION_ATTR_OFFSET * regn_num, APM_REGION_LOCK_BIT); +} + +/** + * @brief Get exception data (regn, master, security mode) from CPU-APM + * + * @param path Access path + * @return Exception data + */ +static inline uint32_t apm_ll_cpu_apm_get_excp_data(apm_ctrl_access_path_t path) +{ + return REG_READ(CPU_APM_M0_EXCEPTION_INFO0_REG + APM_EXCP_INFO_OFFSET * path); +} + +/** + * @brief Get exception status from CPU-APM + * + * @param path Access path + * @return Exception type + */ +static inline uint32_t apm_ll_cpu_apm_get_excp_type(apm_ctrl_access_path_t path) +{ + return REG_READ(CPU_APM_M0_STATUS_REG + APM_EXCP_INFO_OFFSET * path); +} + +/** + * @brief Get exception address from CPU-APM + * + * @param path Access path + * @return Exception address + */ +static inline uint32_t apm_ll_cpu_apm_get_excp_addr(apm_ctrl_access_path_t path) +{ + return REG_READ(CPU_APM_M0_EXCEPTION_INFO1_REG + APM_EXCP_INFO_OFFSET * path); +} + +/** + * @brief Get exception information from CPU-APM + * + * @param path Access path + * @param info Pointer to store exception information + */ +static inline void apm_ll_cpu_apm_get_excp_info(apm_ctrl_access_path_t path, apm_ctrl_exception_info_t *info) +{ + cpu_apm_m0_exception_info0_reg_t reg; + reg.val = apm_ll_cpu_apm_get_excp_data(path); + info->regn = reg.apm_m0_exception_region; + info->mode = reg.apm_m0_exception_mode; + info->id = reg.apm_m0_exception_id; + + info->type = apm_ll_cpu_apm_get_excp_type(path); + info->addr = apm_ll_cpu_apm_get_excp_addr(path); +} + +/** + * @brief Clear controller exception status in CPU-APM + * + * @param path Access path + */ +static inline void apm_ll_cpu_apm_clear_ctrl_excp_status(apm_ctrl_access_path_t path) +{ + REG_SET_BIT(CPU_APM_M0_STATUS_CLR_REG + APM_EXCP_INFO_OFFSET * path, APM_EXCP_STATUS_CLR_BIT); +} + +/** + * @brief Enable/disable controller interrupt in CPU-APM + * + * @param path Access path + * @param enable True to enable, false to disable + */ +static inline void apm_ll_cpu_apm_enable_ctrl_intr(apm_ctrl_access_path_t path, bool enable) +{ + if (enable) { + REG_SET_BIT(CPU_APM_INT_EN_REG, BIT(path)); + } else { + REG_CLR_BIT(CPU_APM_INT_EN_REG, BIT(path)); + } +} + +/** + * @brief Enable/disable controller clock gating in CPU-APM + * + * @param enable True to enable, false to disable + */ +static inline void apm_ll_cpu_apm_enable_ctrl_clk_gating(bool enable) +{ + if (enable) { + REG_CLR_BIT(CPU_APM_CLOCK_GATE_REG, CPU_APM_CLK_EN); + } else { + REG_SET_BIT(CPU_APM_CLOCK_GATE_REG, CPU_APM_CLK_EN); + } +} + +/** + * @brief Get controller interrupt source number from CPU-APM + * + * @param path Access path + * @return Interrupt source number + */ +static inline int apm_ll_cpu_apm_get_ctrl_intr_src(apm_ctrl_access_path_t path) +{ + return ETS_CPU_APM_M0_INTR_SOURCE + path; +} + /** * @brief Enable/disable APM reset event bypass * diff --git a/components/hal/include/hal/apm_hal.h b/components/hal/include/hal/apm_hal.h index 3e9bf80771..9e636c8a0c 100644 --- a/components/hal/include/hal/apm_hal.h +++ b/components/hal/include/hal/apm_hal.h @@ -253,6 +253,33 @@ void apm_hal_enable_ctrl_filter_all(bool enable); */ void apm_hal_enable_region_filter(apm_ctrl_module_t ctrl_mod, uint32_t regn_num, bool enable); +/** + * @brief Set the start address for the given region + * + * @param ctrl_mod APM controller module + * @param regn_num Region number + * @param addr Address + */ +void apm_hal_set_region_start_addr(apm_ctrl_module_t ctrl_mod, uint32_t regn_num, uint32_t addr); + +/** + * @brief Set the end address for the given region + * + * @param ctrl_mod APM controller module + * @param regn_num Region number + * @param addr Address + */ +void apm_hal_set_region_end_addr(apm_ctrl_module_t ctrl_mod, uint32_t regn_num, uint32_t addr); + +/** + * @brief Set the permissions for the specified security mode for the given region + * + * @param ctrl_mod APM controller module + * @param regn_num Region number + * @param mode Security mode + */ +void apm_hal_set_sec_mode_region_attr(apm_ctrl_module_t ctrl_mod, uint32_t regn_num, apm_security_mode_t mode, uint32_t regn_pms); + /** * @brief Set region filter configuration * diff --git a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in index 2eecd3321b..4f1406872d 100644 --- a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in @@ -999,6 +999,10 @@ config SOC_APM_CTRL_FILTER_SUPPORTED bool default y +config SOC_APM_CPU_APM_SUPPORTED + bool + default y + config SOC_APM_SUPPORT_CTRL_CFG_LOCK bool default y diff --git a/components/soc/esp32c61/include/soc/apm_defs.h b/components/soc/esp32c61/include/soc/apm_defs.h index a239f3b8b1..96b45ea89a 100644 --- a/components/soc/esp32c61/include/soc/apm_defs.h +++ b/components/soc/esp32c61/include/soc/apm_defs.h @@ -15,9 +15,11 @@ extern "C" { /* Number of paths for each supported APM controller */ #define APM_CTRL_HP_APM_PATH_NUM (4) #define APM_CTRL_LP_APM_PATH_NUM (1) +#define APM_CTRL_CPU_APM_PATH_NUM (2) /* Number of regions for each supported APM controller */ #define APM_CTRL_HP_APM_REGION_NUM (16) #define APM_CTRL_LP_APM_REGION_NUM (4) +#define APM_CTRL_CPU_APM_REGION_NUM (8) /* Register offset for TEE mode control */ #define APM_TEE_MODE_CTRL_OFFSET (0x04) diff --git a/components/soc/esp32c61/include/soc/soc_caps.h b/components/soc/esp32c61/include/soc/soc_caps.h index 6d973829bf..f7abd9703d 100644 --- a/components/soc/esp32c61/include/soc/soc_caps.h +++ b/components/soc/esp32c61/include/soc/soc_caps.h @@ -412,6 +412,7 @@ /*-------------------------- APM CAPS ----------------------------------------*/ #define SOC_APM_CTRL_FILTER_SUPPORTED 1 /*!< Support for APM control filter */ +#define SOC_APM_CPU_APM_SUPPORTED 1 /*!< Support for CPU APM control filter */ #define SOC_APM_SUPPORT_CTRL_CFG_LOCK 1 /*!< Support for APM controller configuration lock */ /*------------------------ Anti DPA (Security) CAPS --------------------------*/ diff --git a/components/soc/esp32c61/register/soc/cpu_apm_reg.h b/components/soc/esp32c61/register/soc/cpu_apm_reg.h index 10ca7c64e3..5468e047fc 100644 --- a/components/soc/esp32c61/register/soc/cpu_apm_reg.h +++ b/components/soc/esp32c61/register/soc/cpu_apm_reg.h @@ -14,7 +14,7 @@ extern "C" { /** CPU_APM_REGION_FILTER_EN_REG register * Region filter enable register */ -#define CPU_APM_REGION_FILTER_EN_REG (DR_REG_CPU_BASE + 0x0) +#define CPU_APM_REGION_FILTER_EN_REG (DR_REG_CPU_APM_REG_BASE + 0x0) /** CPU_APM_REGION_FILTER_EN : R/W; bitpos: [7:0]; default: 1; * Configure bit $n (0-7) to enable region $n. * 0: disable @@ -28,7 +28,7 @@ extern "C" { /** CPU_APM_REGION0_ADDR_START_REG register * Region address register */ -#define CPU_APM_REGION0_ADDR_START_REG (DR_REG_CPU_BASE + 0x4) +#define CPU_APM_REGION0_ADDR_START_REG (DR_REG_CPU_APM_REG_BASE + 0x4) /** CPU_APM_REGION0_ADDR_START_L : HRO; bitpos: [11:0]; default: 0; * Low 12 bit, start address of region 0. */ @@ -54,7 +54,7 @@ extern "C" { /** CPU_APM_REGION0_ADDR_END_REG register * Region address register */ -#define CPU_APM_REGION0_ADDR_END_REG (DR_REG_CPU_BASE + 0x8) +#define CPU_APM_REGION0_ADDR_END_REG (DR_REG_CPU_APM_REG_BASE + 0x8) /** CPU_APM_REGION0_ADDR_END_L : HRO; bitpos: [11:0]; default: 4095; * Low 12 bit, end address of region 0. */ @@ -80,7 +80,7 @@ extern "C" { /** CPU_APM_REGION0_ATTR_REG register * Region access authority attribute register */ -#define CPU_APM_REGION0_ATTR_REG (DR_REG_CPU_BASE + 0xc) +#define CPU_APM_REGION0_ATTR_REG (DR_REG_CPU_APM_REG_BASE + 0xc) /** CPU_APM_REGION0_R0_X : R/W; bitpos: [0]; default: 0; * Configures the execution authority of REE_MODE 0 in region 0. */ @@ -155,7 +155,7 @@ extern "C" { /** CPU_APM_REGION1_ADDR_START_REG register * Region address register */ -#define CPU_APM_REGION1_ADDR_START_REG (DR_REG_CPU_BASE + 0x10) +#define CPU_APM_REGION1_ADDR_START_REG (DR_REG_CPU_APM_REG_BASE + 0x10) /** CPU_APM_REGION1_ADDR_START_L : HRO; bitpos: [11:0]; default: 0; * Low 12 bit, start address of region 1. */ @@ -181,7 +181,7 @@ extern "C" { /** CPU_APM_REGION1_ADDR_END_REG register * Region address register */ -#define CPU_APM_REGION1_ADDR_END_REG (DR_REG_CPU_BASE + 0x14) +#define CPU_APM_REGION1_ADDR_END_REG (DR_REG_CPU_APM_REG_BASE + 0x14) /** CPU_APM_REGION1_ADDR_END_L : HRO; bitpos: [11:0]; default: 4095; * Low 12 bit, end address of region 1. */ @@ -207,7 +207,7 @@ extern "C" { /** CPU_APM_REGION1_ATTR_REG register * Region access authority attribute register */ -#define CPU_APM_REGION1_ATTR_REG (DR_REG_CPU_BASE + 0x18) +#define CPU_APM_REGION1_ATTR_REG (DR_REG_CPU_APM_REG_BASE + 0x18) /** CPU_APM_REGION1_R0_X : R/W; bitpos: [0]; default: 0; * Configures the execution authority of REE_MODE 0 in region 1. */ @@ -282,7 +282,7 @@ extern "C" { /** CPU_APM_REGION2_ADDR_START_REG register * Region address register */ -#define CPU_APM_REGION2_ADDR_START_REG (DR_REG_CPU_BASE + 0x1c) +#define CPU_APM_REGION2_ADDR_START_REG (DR_REG_CPU_APM_REG_BASE + 0x1c) /** CPU_APM_REGION2_ADDR_START_L : HRO; bitpos: [11:0]; default: 0; * Low 12 bit, start address of region 2. */ @@ -308,7 +308,7 @@ extern "C" { /** CPU_APM_REGION2_ADDR_END_REG register * Region address register */ -#define CPU_APM_REGION2_ADDR_END_REG (DR_REG_CPU_BASE + 0x20) +#define CPU_APM_REGION2_ADDR_END_REG (DR_REG_CPU_APM_REG_BASE + 0x20) /** CPU_APM_REGION2_ADDR_END_L : HRO; bitpos: [11:0]; default: 4095; * Low 12 bit, end address of region 2. */ @@ -334,7 +334,7 @@ extern "C" { /** CPU_APM_REGION2_ATTR_REG register * Region access authority attribute register */ -#define CPU_APM_REGION2_ATTR_REG (DR_REG_CPU_BASE + 0x24) +#define CPU_APM_REGION2_ATTR_REG (DR_REG_CPU_APM_REG_BASE + 0x24) /** CPU_APM_REGION2_R0_X : R/W; bitpos: [0]; default: 0; * Configures the execution authority of REE_MODE 0 in region 2. */ @@ -409,7 +409,7 @@ extern "C" { /** CPU_APM_REGION3_ADDR_START_REG register * Region address register */ -#define CPU_APM_REGION3_ADDR_START_REG (DR_REG_CPU_BASE + 0x28) +#define CPU_APM_REGION3_ADDR_START_REG (DR_REG_CPU_APM_REG_BASE + 0x28) /** CPU_APM_REGION3_ADDR_START_L : HRO; bitpos: [11:0]; default: 0; * Low 12 bit, start address of region 3. */ @@ -435,7 +435,7 @@ extern "C" { /** CPU_APM_REGION3_ADDR_END_REG register * Region address register */ -#define CPU_APM_REGION3_ADDR_END_REG (DR_REG_CPU_BASE + 0x2c) +#define CPU_APM_REGION3_ADDR_END_REG (DR_REG_CPU_APM_REG_BASE + 0x2c) /** CPU_APM_REGION3_ADDR_END_L : HRO; bitpos: [11:0]; default: 4095; * Low 12 bit, end address of region 3. */ @@ -461,7 +461,7 @@ extern "C" { /** CPU_APM_REGION3_ATTR_REG register * Region access authority attribute register */ -#define CPU_APM_REGION3_ATTR_REG (DR_REG_CPU_BASE + 0x30) +#define CPU_APM_REGION3_ATTR_REG (DR_REG_CPU_APM_REG_BASE + 0x30) /** CPU_APM_REGION3_R0_X : R/W; bitpos: [0]; default: 0; * Configures the execution authority of REE_MODE 0 in region 3. */ @@ -536,7 +536,7 @@ extern "C" { /** CPU_APM_REGION4_ADDR_START_REG register * Region address register */ -#define CPU_APM_REGION4_ADDR_START_REG (DR_REG_CPU_BASE + 0x34) +#define CPU_APM_REGION4_ADDR_START_REG (DR_REG_CPU_APM_REG_BASE + 0x34) /** CPU_APM_REGION4_ADDR_START_L : HRO; bitpos: [11:0]; default: 0; * Low 12 bit, start address of region 4. */ @@ -562,7 +562,7 @@ extern "C" { /** CPU_APM_REGION4_ADDR_END_REG register * Region address register */ -#define CPU_APM_REGION4_ADDR_END_REG (DR_REG_CPU_BASE + 0x38) +#define CPU_APM_REGION4_ADDR_END_REG (DR_REG_CPU_APM_REG_BASE + 0x38) /** CPU_APM_REGION4_ADDR_END_L : HRO; bitpos: [11:0]; default: 4095; * Low 12 bit, end address of region 4. */ @@ -588,7 +588,7 @@ extern "C" { /** CPU_APM_REGION4_ATTR_REG register * Region access authority attribute register */ -#define CPU_APM_REGION4_ATTR_REG (DR_REG_CPU_BASE + 0x3c) +#define CPU_APM_REGION4_ATTR_REG (DR_REG_CPU_APM_REG_BASE + 0x3c) /** CPU_APM_REGION4_R0_X : R/W; bitpos: [0]; default: 0; * Configures the execution authority of REE_MODE 0 in region 4. */ @@ -663,7 +663,7 @@ extern "C" { /** CPU_APM_REGION5_ADDR_START_REG register * Region address register */ -#define CPU_APM_REGION5_ADDR_START_REG (DR_REG_CPU_BASE + 0x40) +#define CPU_APM_REGION5_ADDR_START_REG (DR_REG_CPU_APM_REG_BASE + 0x40) /** CPU_APM_REGION5_ADDR_START_L : HRO; bitpos: [11:0]; default: 0; * Low 12 bit, start address of region 5. */ @@ -689,7 +689,7 @@ extern "C" { /** CPU_APM_REGION5_ADDR_END_REG register * Region address register */ -#define CPU_APM_REGION5_ADDR_END_REG (DR_REG_CPU_BASE + 0x44) +#define CPU_APM_REGION5_ADDR_END_REG (DR_REG_CPU_APM_REG_BASE + 0x44) /** CPU_APM_REGION5_ADDR_END_L : HRO; bitpos: [11:0]; default: 4095; * Low 12 bit, end address of region 5. */ @@ -715,7 +715,7 @@ extern "C" { /** CPU_APM_REGION5_ATTR_REG register * Region access authority attribute register */ -#define CPU_APM_REGION5_ATTR_REG (DR_REG_CPU_BASE + 0x48) +#define CPU_APM_REGION5_ATTR_REG (DR_REG_CPU_APM_REG_BASE + 0x48) /** CPU_APM_REGION5_R0_X : R/W; bitpos: [0]; default: 0; * Configures the execution authority of REE_MODE 0 in region 5. */ @@ -790,7 +790,7 @@ extern "C" { /** CPU_APM_REGION6_ADDR_START_REG register * Region address register */ -#define CPU_APM_REGION6_ADDR_START_REG (DR_REG_CPU_BASE + 0x4c) +#define CPU_APM_REGION6_ADDR_START_REG (DR_REG_CPU_APM_REG_BASE + 0x4c) /** CPU_APM_REGION6_ADDR_START_L : HRO; bitpos: [11:0]; default: 0; * Low 12 bit, start address of region 6. */ @@ -816,7 +816,7 @@ extern "C" { /** CPU_APM_REGION6_ADDR_END_REG register * Region address register */ -#define CPU_APM_REGION6_ADDR_END_REG (DR_REG_CPU_BASE + 0x50) +#define CPU_APM_REGION6_ADDR_END_REG (DR_REG_CPU_APM_REG_BASE + 0x50) /** CPU_APM_REGION6_ADDR_END_L : HRO; bitpos: [11:0]; default: 4095; * Low 12 bit, end address of region 6. */ @@ -842,7 +842,7 @@ extern "C" { /** CPU_APM_REGION6_ATTR_REG register * Region access authority attribute register */ -#define CPU_APM_REGION6_ATTR_REG (DR_REG_CPU_BASE + 0x54) +#define CPU_APM_REGION6_ATTR_REG (DR_REG_CPU_APM_REG_BASE + 0x54) /** CPU_APM_REGION6_R0_X : R/W; bitpos: [0]; default: 0; * Configures the execution authority of REE_MODE 0 in region 6. */ @@ -917,7 +917,7 @@ extern "C" { /** CPU_APM_REGION7_ADDR_START_REG register * Region address register */ -#define CPU_APM_REGION7_ADDR_START_REG (DR_REG_CPU_BASE + 0x58) +#define CPU_APM_REGION7_ADDR_START_REG (DR_REG_CPU_APM_REG_BASE + 0x58) /** CPU_APM_REGION7_ADDR_START_L : HRO; bitpos: [11:0]; default: 0; * Low 12 bit, start address of region 7. */ @@ -943,7 +943,7 @@ extern "C" { /** CPU_APM_REGION7_ADDR_END_REG register * Region address register */ -#define CPU_APM_REGION7_ADDR_END_REG (DR_REG_CPU_BASE + 0x5c) +#define CPU_APM_REGION7_ADDR_END_REG (DR_REG_CPU_APM_REG_BASE + 0x5c) /** CPU_APM_REGION7_ADDR_END_L : HRO; bitpos: [11:0]; default: 4095; * Low 12 bit, end address of region 7. */ @@ -969,7 +969,7 @@ extern "C" { /** CPU_APM_REGION7_ATTR_REG register * Region access authority attribute register */ -#define CPU_APM_REGION7_ATTR_REG (DR_REG_CPU_BASE + 0x60) +#define CPU_APM_REGION7_ATTR_REG (DR_REG_CPU_APM_REG_BASE + 0x60) /** CPU_APM_REGION7_R0_X : R/W; bitpos: [0]; default: 0; * Configures the execution authority of REE_MODE 0 in region 7. */ @@ -1044,7 +1044,7 @@ extern "C" { /** CPU_APM_FUNC_CTRL_REG register * APM function control register */ -#define CPU_APM_FUNC_CTRL_REG (DR_REG_CPU_BASE + 0xc4) +#define CPU_APM_FUNC_CTRL_REG (DR_REG_CPU_APM_REG_BASE + 0xc4) /** CPU_APM_M0_FUNC_EN : R/W; bitpos: [0]; default: 1; * PMS M0 function enable */ @@ -1063,7 +1063,7 @@ extern "C" { /** CPU_APM_M0_STATUS_REG register * M0 status register */ -#define CPU_APM_M0_STATUS_REG (DR_REG_CPU_BASE + 0xc8) +#define CPU_APM_M0_STATUS_REG (DR_REG_CPU_APM_REG_BASE + 0xc8) /** CPU_APM_M0_EXCEPTION_STATUS : RO; bitpos: [1:0]; default: 0; * Represents exception status. * bit0: 1 represents authority_exception @@ -1077,7 +1077,7 @@ extern "C" { /** CPU_APM_M0_STATUS_CLR_REG register * M0 status clear register */ -#define CPU_APM_M0_STATUS_CLR_REG (DR_REG_CPU_BASE + 0xcc) +#define CPU_APM_M0_STATUS_CLR_REG (DR_REG_CPU_APM_REG_BASE + 0xcc) /** CPU_APM_M0_EXCEPTION_STATUS_CLR : WT; bitpos: [0]; default: 0; * Configures to clear exception status. */ @@ -1089,7 +1089,7 @@ extern "C" { /** CPU_APM_M0_EXCEPTION_INFO0_REG register * M0 exception_info0 register */ -#define CPU_APM_M0_EXCEPTION_INFO0_REG (DR_REG_CPU_BASE + 0xd0) +#define CPU_APM_M0_EXCEPTION_INFO0_REG (DR_REG_CPU_APM_REG_BASE + 0xd0) /** CPU_APM_M0_EXCEPTION_REGION : RO; bitpos: [15:0]; default: 0; * Represents exception region. */ @@ -1115,7 +1115,7 @@ extern "C" { /** CPU_APM_M0_EXCEPTION_INFO1_REG register * M0 exception_info1 register */ -#define CPU_APM_M0_EXCEPTION_INFO1_REG (DR_REG_CPU_BASE + 0xd4) +#define CPU_APM_M0_EXCEPTION_INFO1_REG (DR_REG_CPU_APM_REG_BASE + 0xd4) /** CPU_APM_M0_EXCEPTION_ADDR : RO; bitpos: [31:0]; default: 0; * Represents exception addr. */ @@ -1127,7 +1127,7 @@ extern "C" { /** CPU_APM_M1_STATUS_REG register * M1 status register */ -#define CPU_APM_M1_STATUS_REG (DR_REG_CPU_BASE + 0xd8) +#define CPU_APM_M1_STATUS_REG (DR_REG_CPU_APM_REG_BASE + 0xd8) /** CPU_APM_M1_EXCEPTION_STATUS : RO; bitpos: [1:0]; default: 0; * Represents exception status. * bit0: 1 represents authority_exception @@ -1141,7 +1141,7 @@ extern "C" { /** CPU_APM_M1_STATUS_CLR_REG register * M1 status clear register */ -#define CPU_APM_M1_STATUS_CLR_REG (DR_REG_CPU_BASE + 0xdc) +#define CPU_APM_M1_STATUS_CLR_REG (DR_REG_CPU_APM_REG_BASE + 0xdc) /** CPU_APM_M1_EXCEPTION_STATUS_CLR : WT; bitpos: [0]; default: 0; * Configures to clear exception status. */ @@ -1153,7 +1153,7 @@ extern "C" { /** CPU_APM_M1_EXCEPTION_INFO0_REG register * M1 exception_info0 register */ -#define CPU_APM_M1_EXCEPTION_INFO0_REG (DR_REG_CPU_BASE + 0xe0) +#define CPU_APM_M1_EXCEPTION_INFO0_REG (DR_REG_CPU_APM_REG_BASE + 0xe0) /** CPU_APM_M1_EXCEPTION_REGION : RO; bitpos: [15:0]; default: 0; * Represents exception region. */ @@ -1179,7 +1179,7 @@ extern "C" { /** CPU_APM_M1_EXCEPTION_INFO1_REG register * M1 exception_info1 register */ -#define CPU_APM_M1_EXCEPTION_INFO1_REG (DR_REG_CPU_BASE + 0xe4) +#define CPU_APM_M1_EXCEPTION_INFO1_REG (DR_REG_CPU_APM_REG_BASE + 0xe4) /** CPU_APM_M1_EXCEPTION_ADDR : RO; bitpos: [31:0]; default: 0; * Represents exception addr. */ @@ -1191,7 +1191,7 @@ extern "C" { /** CPU_APM_INT_EN_REG register * APM interrupt enable register */ -#define CPU_APM_INT_EN_REG (DR_REG_CPU_BASE + 0x118) +#define CPU_APM_INT_EN_REG (DR_REG_CPU_APM_REG_BASE + 0x118) /** CPU_APM_M0_APM_INT_EN : R/W; bitpos: [0]; default: 0; * Configures to enable APM M0 interrupt. * 0: disable @@ -1214,7 +1214,7 @@ extern "C" { /** CPU_APM_CLOCK_GATE_REG register * Clock gating register */ -#define CPU_APM_CLOCK_GATE_REG (DR_REG_CPU_BASE + 0x7f8) +#define CPU_APM_CLOCK_GATE_REG (DR_REG_CPU_APM_REG_BASE + 0x7f8) /** CPU_APM_CLK_EN : R/W; bitpos: [0]; default: 1; * Configures whether to keep the clock always on. * 0: enable automatic clock gating @@ -1228,7 +1228,7 @@ extern "C" { /** CPU_APM_DATE_REG register * Version control register */ -#define CPU_APM_DATE_REG (DR_REG_CPU_BASE + 0x7fc) +#define CPU_APM_DATE_REG (DR_REG_CPU_APM_REG_BASE + 0x7fc) /** CPU_APM_DATE : R/W; bitpos: [27:0]; default: 37823248; * Version control register. */ From 15a4d63441685878d2855a45bb38ac4235d0cf06 Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Fri, 13 Jun 2025 16:26:11 +0530 Subject: [PATCH 2/2] ci(hal): Add HAL/LL-based test app for the TEE and APM peripherals --- .gitlab/CODEOWNERS | 1 + .../port/esp32c5/cpu_region_protect.c | 7 +- .../port/esp32c61/cpu_region_protect.c | 7 +- components/hal/.build-test-rules.yml | 4 + components/hal/apm_hal.c | 2 + .../hal/test_apps/tee_apm/CMakeLists.txt | 15 + components/hal/test_apps/tee_apm/README.md | 149 +++ .../tee_apm/components/pms/CMakeLists.txt | 25 + .../tee_apm/components/pms/include/test_pms.h | 36 + .../tee_apm/components/pms/linker.lf | 5 + .../priv_include/esp32c5/test_peri_apm_reg.h | 47 + .../priv_include/esp32c5/test_pms_params.h | 200 ++++ .../priv_include/esp32c6/test_pms_params.h | 171 ++++ .../priv_include/esp32c61/test_pms_params.h | 165 ++++ .../priv_include/esp32h2/test_pms_params.h | 151 +++ .../pms/priv_include/test_pms_priv.h | 99 ++ .../components/pms/src/test_apm_utils.c | 370 ++++++++ .../components/pms/src/test_intr_utils.c | 77 ++ .../components/pms/src/test_panic_handler.c | 82 ++ .../components/pms/src/test_setup_utils.c | 245 +++++ .../components/pms/src/test_tee_peri_apm.c | 310 +++++++ .../components/pms/src/test_tee_sys_apm.c | 865 ++++++++++++++++++ .../components/pms/src/test_tee_vectors.S | 326 +++++++ .../components/pms/src/ulp/ulp_lp_core_main.c | 109 +++ .../components/pms/src/ulp/ulp_vectors.S | 171 ++++ .../hal/test_apps/tee_apm/main/CMakeLists.txt | 4 + .../test_apps/tee_apm/main/idf_component.yml | 4 + .../hal/test_apps/tee_apm/main/test_main.c | 46 + .../hal/test_apps/tee_apm/main/test_pms.c | 246 +++++ .../test_apps/tee_apm/pytest_tee_apm_pms.py | 42 + .../hal/test_apps/tee_apm/sdkconfig.defaults | 6 + .../tee_apm/sdkconfig.defaults.esp32c5 | 7 + .../tee_apm/sdkconfig.defaults.esp32c6 | 4 + .../tee_apm/sdkconfig.defaults.esp32c61 | 2 + .../tee_apm/sdkconfig.defaults.esp32h2 | 2 + 35 files changed, 3998 insertions(+), 4 deletions(-) create mode 100644 components/hal/test_apps/tee_apm/CMakeLists.txt create mode 100644 components/hal/test_apps/tee_apm/README.md create mode 100644 components/hal/test_apps/tee_apm/components/pms/CMakeLists.txt create mode 100644 components/hal/test_apps/tee_apm/components/pms/include/test_pms.h create mode 100644 components/hal/test_apps/tee_apm/components/pms/linker.lf create mode 100644 components/hal/test_apps/tee_apm/components/pms/priv_include/esp32c5/test_peri_apm_reg.h create mode 100644 components/hal/test_apps/tee_apm/components/pms/priv_include/esp32c5/test_pms_params.h create mode 100644 components/hal/test_apps/tee_apm/components/pms/priv_include/esp32c6/test_pms_params.h create mode 100644 components/hal/test_apps/tee_apm/components/pms/priv_include/esp32c61/test_pms_params.h create mode 100644 components/hal/test_apps/tee_apm/components/pms/priv_include/esp32h2/test_pms_params.h create mode 100644 components/hal/test_apps/tee_apm/components/pms/priv_include/test_pms_priv.h create mode 100644 components/hal/test_apps/tee_apm/components/pms/src/test_apm_utils.c create mode 100644 components/hal/test_apps/tee_apm/components/pms/src/test_intr_utils.c create mode 100644 components/hal/test_apps/tee_apm/components/pms/src/test_panic_handler.c create mode 100644 components/hal/test_apps/tee_apm/components/pms/src/test_setup_utils.c create mode 100644 components/hal/test_apps/tee_apm/components/pms/src/test_tee_peri_apm.c create mode 100644 components/hal/test_apps/tee_apm/components/pms/src/test_tee_sys_apm.c create mode 100644 components/hal/test_apps/tee_apm/components/pms/src/test_tee_vectors.S create mode 100644 components/hal/test_apps/tee_apm/components/pms/src/ulp/ulp_lp_core_main.c create mode 100644 components/hal/test_apps/tee_apm/components/pms/src/ulp/ulp_vectors.S create mode 100644 components/hal/test_apps/tee_apm/main/CMakeLists.txt create mode 100644 components/hal/test_apps/tee_apm/main/idf_component.yml create mode 100644 components/hal/test_apps/tee_apm/main/test_main.c create mode 100644 components/hal/test_apps/tee_apm/main/test_pms.c create mode 100644 components/hal/test_apps/tee_apm/pytest_tee_apm_pms.py create mode 100644 components/hal/test_apps/tee_apm/sdkconfig.defaults create mode 100644 components/hal/test_apps/tee_apm/sdkconfig.defaults.esp32c5 create mode 100644 components/hal/test_apps/tee_apm/sdkconfig.defaults.esp32c6 create mode 100644 components/hal/test_apps/tee_apm/sdkconfig.defaults.esp32c61 create mode 100644 components/hal/test_apps/tee_apm/sdkconfig.defaults.esp32h2 diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS index f3853968fd..ffd23a77e6 100644 --- a/.gitlab/CODEOWNERS +++ b/.gitlab/CODEOWNERS @@ -125,6 +125,7 @@ /components/freertos/ @esp-idf-codeowners/system /components/hal/ @esp-idf-codeowners/peripherals /components/hal/test_apps/crypto/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/security +/components/hal/test_apps/tee_apm/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/security /components/heap/ @esp-idf-codeowners/system /components/http_parser/ @esp-idf-codeowners/app-utilities /components/idf_test/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system diff --git a/components/esp_hw_support/port/esp32c5/cpu_region_protect.c b/components/esp_hw_support/port/esp32c5/cpu_region_protect.c index 5de2dc4cf5..c4e9fb9bb8 100644 --- a/components/esp_hw_support/port/esp32c5/cpu_region_protect.c +++ b/components/esp_hw_support/port/esp32c5/cpu_region_protect.c @@ -136,6 +136,7 @@ void esp_cpu_configure_region_protection(void) _Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region"); // 2. I/D-ROM +#if CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT && !BOOTLOADER_BUILD 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] @@ -144,9 +145,11 @@ void esp_cpu_configure_region_protection(void) // 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); - } else { + } else +#endif + { PMP_ENTRY_SET(1, SOC_IROM_MASK_LOW, NONE); - PMP_ENTRY_SET(2, SOC_IROM_MASK_HIGH, PMP_TOR | RX); + PMP_ENTRY_SET(2, SOC_IROM_MASK_HIGH, PMP_TOR | CONDITIONAL_RX); _Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region"); } 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 080a56a24f..069c10ee24 100644 --- a/components/esp_hw_support/port/esp32c61/cpu_region_protect.c +++ b/components/esp_hw_support/port/esp32c61/cpu_region_protect.c @@ -133,14 +133,17 @@ void esp_cpu_configure_region_protection(void) _Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region"); // 2. I/D-ROM +#if CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT && !BOOTLOADER_BUILD 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 | RW); - } else { + } else +#endif + { const uint32_t pmpaddr1 = PMPADDR_NAPOT(SOC_IROM_MASK_LOW, SOC_IROM_MASK_HIGH); - PMP_ENTRY_SET(1, pmpaddr1, PMP_NAPOT | RX); + PMP_ENTRY_SET(1, pmpaddr1, PMP_NAPOT | CONDITIONAL_RX); _Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region"); } diff --git a/components/hal/.build-test-rules.yml b/components/hal/.build-test-rules.yml index 161bbc1df3..b4e746e70e 100644 --- a/components/hal/.build-test-rules.yml +++ b/components/hal/.build-test-rules.yml @@ -11,3 +11,7 @@ components/hal/test_apps/hal_i2c: components/hal/test_apps/hal_utils: enable: - if: IDF_TARGET == "linux" + +components/hal/test_apps/tee_apm: + disable: + - if: IDF_TARGET not in ["esp32c6", "esp32h2", "esp32c5", "esp32c61"] diff --git a/components/hal/apm_hal.c b/components/hal/apm_hal.c index 1591337a14..1fee887fff 100644 --- a/components/hal/apm_hal.c +++ b/components/hal/apm_hal.c @@ -268,6 +268,8 @@ void apm_hal_set_region_end_addr(apm_ctrl_module_t ctrl_mod, uint32_t regn_num, void apm_hal_set_sec_mode_region_attr(apm_ctrl_module_t ctrl_mod, uint32_t regn_num, apm_security_mode_t mode, uint32_t regn_pms) { + HAL_ASSERT(mode != APM_SEC_MODE_TEE); + switch (ctrl_mod) { case APM_CTRL_HP_APM: apm_ll_hp_apm_set_sec_mode_region_attr(regn_num, mode, regn_pms); diff --git a/components/hal/test_apps/tee_apm/CMakeLists.txt b/components/hal/test_apps/tee_apm/CMakeLists.txt new file mode 100644 index 0000000000..582823ff35 --- /dev/null +++ b/components/hal/test_apps/tee_apm/CMakeLists.txt @@ -0,0 +1,15 @@ +#This is the project CMakeLists.txt file for the test subproject +cmake_minimum_required(VERSION 3.16) + +# "Trim" the build. Include the minimal set of components, main, and anything it depends on. +set(COMPONENTS main) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +project(test_tee_apm) + +include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake) +message(STATUS "Checking tee/apm registers are not read-write by half-word") +check_register_rw_half_word(SOC_MODULES "*tee" # tee, lp_tee + "*apm *apm0" # hp_apm, lp_apm, cpu_apm, lp_apm0 + HAL_MODULES "apm") diff --git a/components/hal/test_apps/tee_apm/README.md b/components/hal/test_apps/tee_apm/README.md new file mode 100644 index 0000000000..62a5fdcd03 --- /dev/null +++ b/components/hal/test_apps/tee_apm/README.md @@ -0,0 +1,149 @@ +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | +| ----------------- | -------- | -------- | --------- | -------- | + +# APM (Access Permission Management) Peripheral Test App + +This application validates region-based memory and peripheral access control via the APM (Access Permission Management) subsystem. It is primarily intended for bring-up and SoC-level functional testing. + +Tests exercise various master-to-region accesses under different security modes (`TEE`, `REE0`, `REE1`, `REE2`). Outcomes are validated against expected APM behavior and known SoC-specific quirks. + +--- + +## Test Coverage + +### TEE mode default access behavior + +- **TEE Mode Default Access** + +Validates whether TEE mode has unrestricted access to regions not covered by APM entries. Confirms filtering issues on ESP32-C6 and ESP32-H2. + +### HP_CPU Access + +- **HP_CPU → CPU_PERI** +- **HP_CPU → HP_PERI** +- **HP_CPU → LP_PERI** +- **HP_CPU → HP_MEM** (if `SOC_APM_CPU_APM_SUPPORTED`) +- **HP_CPU → LP_MEM** (if `SOC_RTC_MEM_SUPPORTED`) + +Each scenario checks access permission enforcement for read-only and write-only settings across security modes. + +### GDMA Access + +- **GDMA → HP_MEM** +- **GDMA → EXT_MEM** (if `CONFIG_SPIRAM`) + +Validates region-based restrictions across modes using DMA transfers. + +### LP_CPU Access (if `CONFIG_ULP_COPROC_ENABLED`) + +- **LP_CPU → LP_PERI** +- **LP_CPU → LP_MEM** +- **LP_CPU → HP_MEM** + +### PERI_APM Tests (if `SOC_APM_SUPPORT_TEE_PERI_ACCESS_CTRL`) + +- **HP_CPU → HP_PERI** +- **HP_CPU → LP_PERI** +- **LP_CPU → HP_PERI** +- **LP_CPU → LP_PERI** + +Validates the per-peripheral access permissions for all security modes. + +--- + +## Target Extension Guide + +To add support for a new SoC target, create a test configuration header at: + +``` +components/pms/priv_include//test_pms_params.h +``` + +This header must define: + +### 1. GDMA APM Master ID + +Defined based on GDMA version: + +```c +#define TEST_GDMA_APM_MASTER_ID APM_MASTER_GDMA_GPSPI // For SOC_AHB_GDMA_VERSION == 1 +``` + +- `SOC_AHB_GDMA_VERSION == 1` → `GPSPI` +- `SOC_AHB_GDMA_VERSION == 2` → `26` (e.g., `GDMA_DUMMY10`) + +Refer to `hal/apm_types.h` or the SoC TRM. + +### 2. APM Controller and Path Definitions + +Specify APM controller and access path for each initiator-target pair: + +```c +#define HP_CPU_CPUPERI_APM_CTRL APM_CTRL_HP_APM +#define HP_CPU_CPUPERI_APM_PATH APM_CTRL_ACCESS_PATH_M0 +#define TEST_HP_CPU_CPUPERI_REGN_NUM 4 +``` + +Use the TRM to determine path-controller mappings. + +### 3. Peripheral Test Region Definitions + +Split the peripheral address space into testable regions: + +- Use `soc/reg_base.h` to get base addresses of peripherals. +- Align non-contiguous region boundaries to 4 KB using: + +```c +#define ALIGN_TO_NEXT_4KB(addr) (((addr) + 0x1000) & ~0xFFF) +``` + +#### CPU_PERI + +- Typically monitored by `HP_APM`. +- Includes blocks like `TRACE`, `ASSIST_DEBUG`, `INTPRI`, `CACHE`. +- `CPU_PERI` typically includes ~4 peripherals, and thus, 4 APM regions are sufficient for test coverage. + +#### LP_PERI + +- Monitored by `LP_APM`. +- Covers domains like `PMU`, `LP_IO`, `LP_AON`. +- For SoCs with `LP_CPU`, reserve the regions containing `PMU`, `LP_AON`, `LP_PERI`. These are reserved to allow test-case control and avoid undesired APM violations. + +```c +#define TEST_LP_PERI_RESV_MASK BIT(0) | BIT(2) | BIT(6) +``` + +#### HP_PERI + +- Monitored by `HP_APM`. +- Split into: `HP_PERI0`, `HP_PERI1`, and `HP_PERI2`. + Test APM regions should be proportionally allocated to these segments based on address space size. +- Reserve the region containing `UART0`, since it is often used by the log console. +- If `PERI_APM` is supported, reserve the regions with `TEE`, `LP_TEE`, `HP_APM`, `LP_APM`, `LP_APM0`, and `CPU_APM`, as these are inaccessible to the REE modes. + +```c +#define TEST_HP_PERI_RESV_MASK BIT(0) +``` + +--- + +## Building + +```bash +idf.py set-target +idf.py build +``` + +## Running the App + +```bash +idf.py flash monitor +``` + +## Running Tests + +```bash +pytest --target +``` + +--- \ No newline at end of file diff --git a/components/hal/test_apps/tee_apm/components/pms/CMakeLists.txt b/components/hal/test_apps/tee_apm/components/pms/CMakeLists.txt new file mode 100644 index 0000000000..2e9541335e --- /dev/null +++ b/components/hal/test_apps/tee_apm/components/pms/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.16) +idf_build_get_property(target IDF_TARGET) + +set(srcs "src/test_tee_vectors.S" + "src/test_panic_handler.c" + "src/test_intr_utils.c" + "src/test_apm_utils.c" + "src/test_setup_utils.c" + "src/test_tee_sys_apm.c") +if(CONFIG_SOC_APM_SUPPORT_TEE_PERI_ACCESS_CTRL) + list(APPEND srcs "src/test_tee_peri_apm.c") +endif() + +idf_component_register(SRCS "${srcs}" + INCLUDE_DIRS "include" "priv_include" + PRIV_INCLUDE_DIRS "priv_include/${target}" + REQUIRES ulp unity + LDFRAGMENTS linker.lf) + +if(CONFIG_ULP_COPROC_ENABLED) + set(ulp_app_name ulp_lp_core_${COMPONENT_NAME}) + set(ulp_rv_srcs "src/ulp/ulp_lp_core_main.c" "src/ulp/ulp_vectors.S") + set(ulp_exp_dep_srcs "src/test_tee_apm_pms.c") + ulp_embed_binary(${ulp_app_name} "${ulp_rv_srcs}" "${ulp_exp_dep_srcs}") +endif() diff --git a/components/hal/test_apps/tee_apm/components/pms/include/test_pms.h b/components/hal/test_apps/tee_apm/components/pms/include/test_pms.h new file mode 100644 index 0000000000..3eef2c8a6d --- /dev/null +++ b/components/hal/test_apps/tee_apm/components/pms/include/test_pms.h @@ -0,0 +1,36 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Test-cases */ +void test_sys_apm_master_hp_cpu_slave_hp_peri(void); + +void test_sys_apm_master_hp_cpu_slave_cpu_peri(void); + +void test_sys_apm_master_gdma_slave_hpmem(void); + +void test_sys_apm_master_hp_cpu_slave_lpmem(void); + +void test_sys_apm_master_lp_cpu_slave_lp_peri(void); + +void test_sys_apm_master_hp_cpu_slave_lp_peri(void); + +void test_sys_apm_master_lp_cpu_slave_lpmem(void); + +void test_sys_apm_master_lp_cpu_slave_hpmem(void); + +void test_sys_apm_master_gdma_slave_extmem(void); + +void test_sys_apm_master_hp_cpu_slave_hpmem(void); + +void test_peri_apm_master_hp_cpu_slave_hp_peri(void); + +void test_peri_apm_master_hp_cpu_slave_lp_peri(void); + +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); diff --git a/components/hal/test_apps/tee_apm/components/pms/linker.lf b/components/hal/test_apps/tee_apm/components/pms/linker.lf new file mode 100644 index 0000000000..0af8398a7e --- /dev/null +++ b/components/hal/test_apps/tee_apm/components/pms/linker.lf @@ -0,0 +1,5 @@ +[mapping:pms] +archive: libpms.a +entries: + test_intr_utils (noflash) + test_panic_handler (noflash) diff --git a/components/hal/test_apps/tee_apm/components/pms/priv_include/esp32c5/test_peri_apm_reg.h b/components/hal/test_apps/tee_apm/components/pms/priv_include/esp32c5/test_peri_apm_reg.h new file mode 100644 index 0000000000..6c2025bb12 --- /dev/null +++ b/components/hal/test_apps/tee_apm/components/pms/priv_include/esp32c5/test_peri_apm_reg.h @@ -0,0 +1,47 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "soc/reg_base.h" + +/********* For PERI_APM *********/ +#include "soc/uart_reg.h" +#include "soc/i2c_reg.h" +#include "soc/i2s_reg.h" +#include "soc/mcpwm_reg.h" +#include "soc/twaifd_reg.h" +#include "soc/ahb_dma_reg.h" +#include "soc/pau_reg.h" +#include "soc/interrupt_matrix_reg.h" +#include "soc/apb_saradc_reg.h" +#include "soc/timer_group_reg.h" +#include "soc/pcnt_reg.h" +#include "soc/io_mux_reg.h" +#include "soc/hp_system_reg.h" +#include "soc/pcr_reg.h" +#include "soc/spi_mem_reg.h" +#include "soc/hp_apm_reg.h" +#include "soc/cpu_apm_reg.h" +#include "soc/sha_reg.h" +#include "soc/cache_reg.h" +#include "soc/spi_reg.h" +#include "soc/bitscrambler_reg.h" +#include "soc/keymng_reg.h" +#include "soc/sdio_slc_host_reg.h" + +#include "soc/efuse_reg.h" +#include "soc/pmu_reg.h" +#include "soc/lp_clkrst_reg.h" +#include "soc/lp_aon_reg.h" +#include "soc/lp_wdt_reg.h" +#include "soc/lpperi_reg.h" +#include "soc/lp_analog_peri_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/lp_apm_reg.h" diff --git a/components/hal/test_apps/tee_apm/components/pms/priv_include/esp32c5/test_pms_params.h b/components/hal/test_apps/tee_apm/components/pms/priv_include/esp32c5/test_pms_params.h new file mode 100644 index 0000000000..0a78d3d6b3 --- /dev/null +++ b/components/hal/test_apps/tee_apm/components/pms/priv_include/esp32c5/test_pms_params.h @@ -0,0 +1,200 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "soc/soc.h" +#include "soc/reg_base.h" + +#include "hal/apm_types.h" +#include "esp_bit_defs.h" + +/* + * NOTE: By default, TEE mode should have unrestricted access to the entire CPU address space. + * However, for ESP32-C6 and ESP32-H2, it has been observed that when APM filters are enabled, + * TEE mode accesses are incorrectly being filtered based on the region configurations and + * access attributes set for REE[0..2] modes. + * + * This behaviour has been fixed on later SoCs. + */ +#define SOC_APM_CTRL_TEE_MODE_ACCESS_BUG 0 + +/********* GDMA APM master ID *********/ +#define TEST_GDMA_APM_MASTER_ID 26 /* GDMA_DUMMY10 */ + +/********* APM controller and path definitions *********/ +#define HP_CPU_CPUPERI_APM_CTRL APM_CTRL_HP_APM +#define HP_CPU_CPUPERI_APM_PATH APM_CTRL_ACCESS_PATH_M0 +/* NOTE: ESP32-C5 has only 4 CPU peripherals */ +#define TEST_HP_CPU_CPUPERI_REGN_NUM 4 + +#define GDMA_HPMEM_APM_CTRL APM_CTRL_HP_APM +#define GDMA_HPMEM_APM_PATH APM_CTRL_ACCESS_PATH_M1 +#define GDMA_HPMEM_TEST_REGN_NUM APM_CTRL_HP_APM_REGION_NUM + +#define LP_CPU_HPMEM_APM_CTRL APM_CTRL_HP_APM +#define LP_CPU_HPMEM_APM_PATH APM_CTRL_ACCESS_PATH_M2 +#define LP_CPU_HPMEM_TEST_REGN_NUM APM_CTRL_HP_APM_REGION_NUM + +#define HP_CPU_HPPERI_APM_CTRL APM_CTRL_HP_APM +#define HP_CPU_HPPERI_APM_PATH APM_CTRL_ACCESS_PATH_M3 +#define HP_CPU_HPPERI_TEST_REGN_NUM APM_CTRL_HP_APM_REGION_NUM + +#define GDMA_EXTMEM_APM_CTRL APM_CTRL_HP_APM +#define GDMA_EXTMEM_APM_PATH APM_CTRL_ACCESS_PATH_M4 +#define GDMA_EXTMEM_TEST_REGN_NUM APM_CTRL_HP_APM_REGION_NUM + +#define LP_CPU_LPMEM_APM_CTRL APM_CTRL_LP_APM +#define LP_CPU_LPMEM_APM_PATH APM_CTRL_ACCESS_PATH_M0 +#define LP_CPU_LPMEM_TEST_REGN_NUM APM_CTRL_LP_APM_REGION_NUM + +#define HP_CPU_LPPERI_APM_CTRL APM_CTRL_LP_APM +#define HP_CPU_LPPERI_APM_PATH APM_CTRL_ACCESS_PATH_M1 +#define HP_CPU_LPPERI_TEST_REGN_NUM APM_CTRL_LP_APM_REGION_NUM + +#define LP_CPU_LPPERI_APM_CTRL APM_CTRL_LP_APM +#define LP_CPU_LPPERI_APM_PATH APM_CTRL_ACCESS_PATH_M1 +#define LP_CPU_LPPERI_TEST_REGN_NUM APM_CTRL_LP_APM_REGION_NUM + +#define HP_CPU_LPMEM_APM_CTRL APM_CTRL_LP_APM0 +#define HP_CPU_LPMEM_APM_PATH APM_CTRL_ACCESS_PATH_M0 +#define HP_CPU_LPMEM_TEST_REGN_NUM APM_CTRL_LP_APM0_REGION_NUM + +#define HP_CPU_HPMEM_APM_CTRL APM_CTRL_CPU_APM +#define HP_CPU_HPMEM_I_APM_PATH APM_CTRL_ACCESS_PATH_M0 +#define HP_CPU_HPMEM_D_APM_PATH APM_CTRL_ACCESS_PATH_M1 +#define HP_CPU_HPMEM_TEST_REGN_NUM APM_CTRL_CPU_APM_REGION_NUM + +/********* APM peripheral space test regions *********/ +#define ALIGN_TO_NEXT_4KB(addr) (((addr) + 0x1000) & ~0xFFF) + +/********* CPU_PERI (4 regions) *********/ +#define TEST_CPU_PERI_REGION0_START DR_REG_TRACE_BASE +#define TEST_CPU_PERI_REGION0_END DR_REG_BUS_MONITOR_BASE +#define TEST_CPU_PERI_ADDR0 TEST_CPU_PERI_REGION0_START + +#define TEST_CPU_PERI_REGION1_START DR_REG_BUS_MONITOR_BASE +#define TEST_CPU_PERI_REGION1_END DR_REG_INTPRI_BASE +#define TEST_CPU_PERI_ADDR1 TEST_CPU_PERI_REGION1_START + +#define TEST_CPU_PERI_REGION2_START DR_REG_INTPRI_BASE +#define TEST_CPU_PERI_REGION2_END DR_REG_CACHE_BASE +#define TEST_CPU_PERI_ADDR2 TEST_CPU_PERI_REGION2_START + +#define TEST_CPU_PERI_REGION3_START DR_REG_CACHE_BASE +#define TEST_CPU_PERI_REGION3_END ALIGN_TO_NEXT_4KB(DR_REG_CACHE_BASE) +#define TEST_CPU_PERI_ADDR3 TEST_CPU_PERI_REGION3_START + +#define TEST_CPU_PERI_RESV_MASK (0U) + +/********* HP_PERI (16 regions) *********/ +/* PERI0 */ +/* 0: UART0 - I2C - Reserved (UART0 accessed) */ +#define TEST_HP_PERI_REGION0_START DR_REG_UART0_BASE +#define TEST_HP_PERI_REGION0_END DR_REG_I2C_BASE +#define TEST_HP_PERI_ADDR0 TEST_HP_PERI_REGION0_START + +#define TEST_HP_PERI_REGION1_START DR_REG_I2C_BASE +#define TEST_HP_PERI_REGION1_END DR_REG_TIMERG0_BASE +#define TEST_HP_PERI_ADDR1 TEST_HP_PERI_REGION1_START + +#define TEST_HP_PERI_REGION2_START DR_REG_TIMERG0_BASE +#define TEST_HP_PERI_REGION2_END DR_REG_I2S_BASE +#define TEST_HP_PERI_ADDR2 TEST_HP_PERI_REGION2_START + +#define TEST_HP_PERI_REGION3_START DR_REG_I2S_BASE +#define TEST_HP_PERI_REGION3_END DR_REG_INTMTX_BASE +#define TEST_HP_PERI_ADDR3 TEST_HP_PERI_REGION3_START + +#define TEST_HP_PERI_REGION4_START DR_REG_INTMTX_BASE +#define TEST_HP_PERI_REGION4_END DR_REG_MCPWM_BASE +#define TEST_HP_PERI_ADDR4 TEST_HP_PERI_REGION4_START + +#define TEST_HP_PERI_REGION5_START DR_REG_MCPWM_BASE +#define TEST_HP_PERI_REGION5_END DR_REG_SLCHOST_BASE +#define TEST_HP_PERI_ADDR5 TEST_HP_PERI_REGION5_START + +#define TEST_HP_PERI_REGION6_START DR_REG_SLCHOST_BASE +#define TEST_HP_PERI_REGION6_END ALIGN_TO_NEXT_4KB(DR_REG_PSRAM_MEM_MONITOR_BASE) +#define TEST_HP_PERI_ADDR6 TEST_HP_PERI_REGION6_START + +/* PERI1 */ +#define TEST_HP_PERI_REGION7_START DR_REG_AHB_DMA_BASE +#define TEST_HP_PERI_REGION7_END ALIGN_TO_NEXT_4KB(DR_REG_BITSCRAMBLER_BASE) +#define TEST_HP_PERI_ADDR7 TEST_HP_PERI_REGION7_START + +#define TEST_HP_PERI_REGION8_START DR_REG_KEYMNG_BASE +#define TEST_HP_PERI_REGION8_END DR_REG_RSA_BASE +#define TEST_HP_PERI_ADDR8 TEST_HP_PERI_REGION8_START + +#define TEST_HP_PERI_REGION9_START DR_REG_RSA_BASE +#define TEST_HP_PERI_REGION9_END DR_REG_DS_BASE +#define TEST_HP_PERI_ADDR9 TEST_HP_PERI_REGION9_START + +#define TEST_HP_PERI_REGION10_START DR_REG_DS_BASE +#define TEST_HP_PERI_REGION10_END ALIGN_TO_NEXT_4KB(DR_REG_ECDSA_BASE) +#define TEST_HP_PERI_ADDR10 TEST_HP_PERI_REGION10_START + +/* PERI2 */ +#define TEST_HP_PERI_REGION11_START DR_REG_IO_MUX_BASE +#define TEST_HP_PERI_REGION11_END DR_REG_MEM_MONITOR_BASE +#define TEST_HP_PERI_ADDR11 TEST_HP_PERI_REGION11_START + +#define TEST_HP_PERI_REGION12_START DR_REG_MEM_MONITOR_BASE +#define TEST_HP_PERI_REGION12_END DR_REG_HP_SYSTEM_BASE +#define TEST_HP_PERI_ADDR12 TEST_HP_PERI_REGION12_START + +#define TEST_HP_PERI_REGION13_START DR_REG_HP_SYSTEM_BASE +#define TEST_HP_PERI_REGION13_END DR_REG_TEE_BASE +#define TEST_HP_PERI_ADDR13 TEST_HP_PERI_REGION13_START + +/* 14: TEE - CPU_APM (TEE and APM CTRL protected by PERI_APM) */ +#define TEST_HP_PERI_REGION14_START DR_REG_TEE_BASE +#define TEST_HP_PERI_REGION14_END ALIGN_TO_NEXT_4KB(DR_REG_CPU_APM_BASE) +#define TEST_HP_PERI_ADDR14 TEST_HP_PERI_REGION14_START + +#define TEST_HP_PERI_REGION15_START DR_REG_MISC_BASE +#define TEST_HP_PERI_REGION15_END DR_REG_PMU_BASE +#define TEST_HP_PERI_ADDR15 TEST_HP_PERI_REGION15_START + +#define TEST_HP_PERI_RESV_MASK BIT(0) | BIT(14) + +/********* LP_PERI (8 regions) *********/ +/* 0: PMU - Reserved (PMU_LP_CPU_PWR1_REG accessed) */ +#define TEST_LP_PERI_REGION0_START DR_REG_PMU_BASE +#define TEST_LP_PERI_REGION0_END DR_REG_LP_CLKRST_BASE +#define TEST_LP_PERI_ADDR0 TEST_LP_PERI_REGION0_START + +#define TEST_LP_PERI_REGION1_START DR_REG_LP_CLKRST_BASE +#define TEST_LP_PERI_REGION1_END DR_REG_LP_AON_BASE +#define TEST_LP_PERI_ADDR1 TEST_LP_PERI_REGION1_START + +/* 2: LP_AON - Reserved (LP_AON_STOREn_REG accessed) */ +#define TEST_LP_PERI_REGION2_START DR_REG_LP_AON_BASE +#define TEST_LP_PERI_REGION2_END DR_REG_LP_UART_BASE +#define TEST_LP_PERI_ADDR2 TEST_LP_PERI_REGION2_START + +#define TEST_LP_PERI_REGION3_START DR_REG_LP_UART_BASE +#define TEST_LP_PERI_REGION3_END DR_REG_LP_WDT_BASE +#define TEST_LP_PERI_ADDR3 TEST_LP_PERI_REGION3_START + +#define TEST_LP_PERI_REGION4_START DR_REG_LP_WDT_BASE +#define TEST_LP_PERI_REGION4_END DR_REG_LP_I2C_ANA_MST_BASE +#define TEST_LP_PERI_ADDR4 TEST_LP_PERI_REGION4_START + +#define TEST_LP_PERI_REGION5_START DR_REG_LP_I2C_ANA_MST_BASE +#define TEST_LP_PERI_REGION5_END DR_REG_HUK_BASE +#define TEST_LP_PERI_ADDR5 TEST_LP_PERI_REGION5_START + +#define TEST_LP_PERI_REGION6_START DR_REG_HUK_BASE +#define TEST_LP_PERI_REGION6_END DR_REG_LP_IO_MUX_BASE +#define TEST_LP_PERI_ADDR6 TEST_LP_PERI_REGION6_START + +#define TEST_LP_PERI_REGION7_START DR_REG_LP_IO_MUX_BASE +#define TEST_LP_PERI_REGION7_END ALIGN_TO_NEXT_4KB(DR_REG_OTP_DEBUG_BASE) +#define TEST_LP_PERI_ADDR7 TEST_LP_PERI_REGION7_START + +#define TEST_LP_PERI_RESV_MASK BIT(0) | BIT(2) diff --git a/components/hal/test_apps/tee_apm/components/pms/priv_include/esp32c6/test_pms_params.h b/components/hal/test_apps/tee_apm/components/pms/priv_include/esp32c6/test_pms_params.h new file mode 100644 index 0000000000..e3a0f9478c --- /dev/null +++ b/components/hal/test_apps/tee_apm/components/pms/priv_include/esp32c6/test_pms_params.h @@ -0,0 +1,171 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "soc/soc.h" +#include "soc/reg_base.h" + +#include "hal/apm_types.h" +#include "esp_bit_defs.h" + +/* + * NOTE: By default, TEE mode should have unrestricted access to the entire CPU address space. + * However, for ESP32-C6 and ESP32-H2, it has been observed that when APM filters are enabled, + * TEE mode accesses are incorrectly being filtered based on the region configurations and + * access attributes set for REE[0..2] modes. + */ +#define SOC_APM_CTRL_TEE_MODE_ACCESS_BUG 1 + +/********* GDMA APM master ID *********/ +#define TEST_GDMA_APM_MASTER_ID APM_MASTER_GDMA_GPSPI + +/********* APM controller and path definitions *********/ +#define HP_CPU_CPUPERI_APM_CTRL APM_CTRL_HP_APM +#define HP_CPU_CPUPERI_APM_PATH APM_CTRL_ACCESS_PATH_M0 +/* NOTE: ESP32-C6 has only 4 CPU peripherals */ +#define TEST_HP_CPU_CPUPERI_REGN_NUM 4 + +#define GDMA_HPMEM_APM_CTRL APM_CTRL_HP_APM +#define GDMA_HPMEM_APM_PATH APM_CTRL_ACCESS_PATH_M1 +#define GDMA_HPMEM_TEST_REGN_NUM APM_CTRL_HP_APM_REGION_NUM + +#define LP_CPU_HPMEM_APM_CTRL APM_CTRL_HP_APM +#define LP_CPU_HPMEM_APM_PATH APM_CTRL_ACCESS_PATH_M2 +#define LP_CPU_HPMEM_TEST_REGN_NUM APM_CTRL_HP_APM_REGION_NUM + +#define HP_CPU_HPPERI_APM_CTRL APM_CTRL_HP_APM +#define HP_CPU_HPPERI_APM_PATH APM_CTRL_ACCESS_PATH_M3 +#define HP_CPU_HPPERI_TEST_REGN_NUM APM_CTRL_HP_APM_REGION_NUM + +#define LP_CPU_LPMEM_APM_CTRL APM_CTRL_LP_APM +#define LP_CPU_LPMEM_APM_PATH APM_CTRL_ACCESS_PATH_M0 +#define LP_CPU_LPMEM_TEST_REGN_NUM APM_CTRL_LP_APM_REGION_NUM + +#define HP_CPU_LPPERI_APM_CTRL APM_CTRL_LP_APM +#define HP_CPU_LPPERI_APM_PATH APM_CTRL_ACCESS_PATH_M1 +#define HP_CPU_LPPERI_TEST_REGN_NUM APM_CTRL_LP_APM_REGION_NUM + +#define LP_CPU_LPPERI_APM_CTRL APM_CTRL_LP_APM +#define LP_CPU_LPPERI_APM_PATH APM_CTRL_ACCESS_PATH_M1 +#define LP_CPU_LPPERI_TEST_REGN_NUM APM_CTRL_LP_APM_REGION_NUM + +#define HP_CPU_LPMEM_APM_CTRL APM_CTRL_LP_APM0 +#define HP_CPU_LPMEM_APM_PATH APM_CTRL_ACCESS_PATH_M0 +#define HP_CPU_LPMEM_TEST_REGN_NUM APM_CTRL_LP_APM0_REGION_NUM + +/********* APM peripheral space test regions *********/ +#define ALIGN_TO_NEXT_4KB(addr) (((addr) + 0x1000) & ~0xFFF) + +/********* CPU_PERI (4 regions) *********/ +#define TEST_CPU_PERI_REGION0_START DR_REG_TRACE_BASE +#define TEST_CPU_PERI_REGION0_END DR_REG_CPU_BUS_MONITOR_BASE +#define TEST_CPU_PERI_ADDR0 TEST_CPU_PERI_REGION0_START + +#define TEST_CPU_PERI_REGION1_START DR_REG_CPU_BUS_MONITOR_BASE +#define TEST_CPU_PERI_REGION1_END DR_REG_INTPRI_BASE +#define TEST_CPU_PERI_ADDR1 TEST_CPU_PERI_REGION1_START + +#define TEST_CPU_PERI_REGION2_START DR_REG_INTPRI_BASE +#define TEST_CPU_PERI_REGION2_END DR_REG_EXTMEM_BASE +#define TEST_CPU_PERI_ADDR2 TEST_CPU_PERI_REGION2_START + +#define TEST_CPU_PERI_REGION3_START DR_REG_EXTMEM_BASE +#define TEST_CPU_PERI_REGION3_END ALIGN_TO_NEXT_4KB(DR_REG_EXTMEM_BASE) +#define TEST_CPU_PERI_ADDR3 TEST_CPU_PERI_REGION3_START + +#define TEST_CPU_PERI_RESV_MASK (0U) + +/********* HP_PERI (16 regions) *********/ +/* PERI0 */ +/* 0: UART0 - I2C - Reserved (UART0 accessed) */ +#define TEST_HP_PERI_REGION0_START DR_REG_UART_BASE +#define TEST_HP_PERI_REGION0_END DR_REG_I2C_EXT_BASE +#define TEST_HP_PERI_ADDR0 TEST_HP_PERI_REGION0_START + +#define TEST_HP_PERI_REGION1_START DR_REG_I2C_EXT_BASE +#define TEST_HP_PERI_REGION1_END DR_REG_TIMERGROUP0_BASE +#define TEST_HP_PERI_ADDR1 TEST_HP_PERI_REGION1_START + +#define TEST_HP_PERI_REGION2_START DR_REG_TIMERGROUP0_BASE +#define TEST_HP_PERI_REGION2_END DR_REG_I2S_BASE +#define TEST_HP_PERI_ADDR2 TEST_HP_PERI_REGION2_START + +#define TEST_HP_PERI_REGION3_START DR_REG_I2S_BASE +#define TEST_HP_PERI_REGION3_END DR_REG_INTMTX_BASE +#define TEST_HP_PERI_ADDR3 TEST_HP_PERI_REGION3_START + +#define TEST_HP_PERI_REGION4_START DR_REG_INTMTX_BASE +#define TEST_HP_PERI_REGION4_END DR_REG_MCPWM_BASE +#define TEST_HP_PERI_ADDR4 TEST_HP_PERI_REGION4_START + +#define TEST_HP_PERI_REGION5_START DR_REG_MCPWM_BASE +#define TEST_HP_PERI_REGION5_END DR_REG_SLCHOST_BASE +#define TEST_HP_PERI_ADDR5 TEST_HP_PERI_REGION5_START + +#define TEST_HP_PERI_REGION6_START DR_REG_SLCHOST_BASE +#define TEST_HP_PERI_REGION6_END ALIGN_TO_NEXT_4KB(DR_REG_PVT_MONITOR_BASE) +#define TEST_HP_PERI_ADDR6 TEST_HP_PERI_REGION6_START + +/* PERI1 */ +#define TEST_HP_PERI_REGION7_START DR_REG_GDMA_BASE +#define TEST_HP_PERI_REGION7_END ALIGN_TO_NEXT_4KB(DR_REG_SPI2_BASE) +#define TEST_HP_PERI_ADDR7 TEST_HP_PERI_REGION7_START + +#define TEST_HP_PERI_REGION8_START DR_REG_AES_BASE +#define TEST_HP_PERI_REGION8_END DR_REG_RSA_BASE +#define TEST_HP_PERI_ADDR8 TEST_HP_PERI_REGION8_START + +#define TEST_HP_PERI_REGION9_START DR_REG_RSA_BASE +#define TEST_HP_PERI_REGION9_END DR_REG_DS_BASE +#define TEST_HP_PERI_ADDR9 TEST_HP_PERI_REGION9_START + +#define TEST_HP_PERI_REGION10_START DR_REG_DS_BASE +#define TEST_HP_PERI_REGION10_END ALIGN_TO_NEXT_4KB(DR_REG_HMAC_BASE) +#define TEST_HP_PERI_ADDR10 TEST_HP_PERI_REGION10_START + +/* PERI2 */ +#define TEST_HP_PERI_REGION11_START DR_REG_IO_MUX_BASE +#define TEST_HP_PERI_REGION11_END DR_REG_MEM_MONITOR_BASE +#define TEST_HP_PERI_ADDR11 TEST_HP_PERI_REGION11_START + +#define TEST_HP_PERI_REGION12_START DR_REG_MEM_MONITOR_BASE +#define TEST_HP_PERI_REGION12_END DR_REG_HP_SYSTEM_BASE +#define TEST_HP_PERI_ADDR12 TEST_HP_PERI_REGION12_START + +#define TEST_HP_PERI_REGION13_START DR_REG_HP_SYSTEM_BASE +#define TEST_HP_PERI_REGION13_END DR_REG_TEE_BASE +#define TEST_HP_PERI_ADDR13 TEST_HP_PERI_REGION13_START + +#define TEST_HP_PERI_REGION14_START DR_REG_TEE_BASE +#define TEST_HP_PERI_REGION14_END DR_REG_MISC_BASE +#define TEST_HP_PERI_ADDR14 TEST_HP_PERI_REGION14_START + +#define TEST_HP_PERI_REGION15_START DR_REG_MISC_BASE +#define TEST_HP_PERI_REGION15_END DR_REG_PMU_BASE +#define TEST_HP_PERI_ADDR15 TEST_HP_PERI_REGION15_START + +#define TEST_HP_PERI_RESV_MASK BIT(0) + +/********* LP_PERI (4 regions) *********/ +/* 0: PMU & LP_AON - Reserved (PMU_LP_CPU_PWR1_REG & LP_AON_STOREn_REG accessed) */ +#define TEST_LP_PERI_REGION0_START DR_REG_PMU_BASE +#define TEST_LP_PERI_REGION0_END DR_REG_LP_UART_BASE +#define TEST_LP_PERI_ADDR0 TEST_LP_PERI_REGION0_START + +#define TEST_LP_PERI_REGION1_START DR_REG_LP_UART_BASE +#define TEST_LP_PERI_REGION1_END DR_REG_LP_WDT_BASE +#define TEST_LP_PERI_ADDR1 TEST_LP_PERI_REGION1_START + +#define TEST_LP_PERI_REGION2_START DR_REG_LP_WDT_BASE +#define TEST_LP_PERI_REGION2_END DR_REG_LPPERI_BASE +#define TEST_LP_PERI_ADDR2 TEST_LP_PERI_REGION2_START + +#define TEST_LP_PERI_REGION3_START DR_REG_LPPERI_BASE +#define TEST_LP_PERI_REGION3_END ALIGN_TO_NEXT_4KB(DR_REG_OPT_DEBUG_BASE) +#define TEST_LP_PERI_ADDR3 TEST_LP_PERI_REGION3_START + +#define TEST_LP_PERI_RESV_MASK BIT(0) diff --git a/components/hal/test_apps/tee_apm/components/pms/priv_include/esp32c61/test_pms_params.h b/components/hal/test_apps/tee_apm/components/pms/priv_include/esp32c61/test_pms_params.h new file mode 100644 index 0000000000..e313af9cf3 --- /dev/null +++ b/components/hal/test_apps/tee_apm/components/pms/priv_include/esp32c61/test_pms_params.h @@ -0,0 +1,165 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "soc/soc.h" +#include "soc/reg_base.h" + +#include "hal/apm_types.h" +#include "esp_bit_defs.h" + +/* + * NOTE: By default, TEE mode should have unrestricted access to the entire CPU address space. + * However, for ESP32-C6 and ESP32-H2, it has been observed that when APM filters are enabled, + * TEE mode accesses are incorrectly being filtered based on the region configurations and + * access attributes set for REE[0..2] modes. + * + * This behaviour has been fixed on later SoCs. + */ +#define SOC_APM_CTRL_TEE_MODE_ACCESS_BUG 0 + +/********* GDMA APM master ID *********/ +#define TEST_GDMA_APM_MASTER_ID 26 /* GDMA_DUMMY10 */ + +/********* APM controller and path definitions *********/ +#define HP_CPU_CPUPERI_APM_CTRL APM_CTRL_HP_APM +#define HP_CPU_CPUPERI_APM_PATH APM_CTRL_ACCESS_PATH_M0 +/* NOTE: ESP32-C61 has only 4 CPU peripherals */ +#define TEST_HP_CPU_CPUPERI_REGN_NUM 4 + +#define GDMA_HPMEM_APM_CTRL APM_CTRL_HP_APM +#define GDMA_HPMEM_APM_PATH APM_CTRL_ACCESS_PATH_M1 +#define GDMA_HPMEM_TEST_REGN_NUM APM_CTRL_HP_APM_REGION_NUM + +#define HP_CPU_HPPERI_APM_CTRL APM_CTRL_HP_APM +#define HP_CPU_HPPERI_APM_PATH APM_CTRL_ACCESS_PATH_M2 +#define HP_CPU_HPPERI_TEST_REGN_NUM APM_CTRL_HP_APM_REGION_NUM + +#define GDMA_EXTMEM_APM_CTRL APM_CTRL_HP_APM +#define GDMA_EXTMEM_APM_PATH APM_CTRL_ACCESS_PATH_M3 +#define GDMA_EXTMEM_TEST_REGN_NUM APM_CTRL_HP_APM_REGION_NUM + +#define HP_CPU_LPPERI_APM_CTRL APM_CTRL_LP_APM +#define HP_CPU_LPPERI_APM_PATH APM_CTRL_ACCESS_PATH_M0 +#define HP_CPU_LPPERI_TEST_REGN_NUM APM_CTRL_LP_APM_REGION_NUM + +#define HP_CPU_HPMEM_APM_CTRL APM_CTRL_CPU_APM +#define HP_CPU_HPMEM_I_APM_PATH APM_CTRL_ACCESS_PATH_M0 +#define HP_CPU_HPMEM_D_APM_PATH APM_CTRL_ACCESS_PATH_M1 +#define HP_CPU_HPMEM_TEST_REGN_NUM APM_CTRL_CPU_APM_REGION_NUM + +/********* APM peripheral space test regions *********/ +#define ALIGN_TO_NEXT_4KB(addr) (((addr) + 0x1000) & ~0xFFF) + +/********* CPU_PERI (4 regions) *********/ +#define TEST_CPU_PERI_REGION0_START DR_REG_TRACE_BASE +#define TEST_CPU_PERI_REGION0_END DR_REG_BUS_MONITOR_BASE +#define TEST_CPU_PERI_ADDR0 TEST_CPU_PERI_REGION0_START + +#define TEST_CPU_PERI_REGION1_START DR_REG_BUS_MONITOR_BASE +#define TEST_CPU_PERI_REGION1_END DR_REG_INTPRI_BASE +#define TEST_CPU_PERI_ADDR1 TEST_CPU_PERI_REGION1_START + +#define TEST_CPU_PERI_REGION2_START DR_REG_INTPRI_BASE +#define TEST_CPU_PERI_REGION2_END DR_REG_CACHE_BASE +#define TEST_CPU_PERI_ADDR2 TEST_CPU_PERI_REGION2_START + +#define TEST_CPU_PERI_REGION3_START DR_REG_CACHE_BASE +#define TEST_CPU_PERI_REGION3_END ALIGN_TO_NEXT_4KB(DR_REG_CACHE_BASE) +#define TEST_CPU_PERI_ADDR3 TEST_CPU_PERI_REGION3_START + +#define TEST_CPU_PERI_RESV_MASK (0U) + +/********* HP_PERI (16 regions) *********/ +/* PERI0 */ +/* 0: UART0 - I2C - Reserved (UART0 accessed) */ +#define TEST_HP_PERI_REGION0_START DR_REG_UART0_BASE +#define TEST_HP_PERI_REGION0_END DR_REG_MSPI1_BASE +#define TEST_HP_PERI_ADDR0 TEST_HP_PERI_REGION0_START + +#define TEST_HP_PERI_REGION1_START DR_REG_MSPI1_BASE +#define TEST_HP_PERI_REGION1_END DR_REG_UART2_BASE +#define TEST_HP_PERI_ADDR1 TEST_HP_PERI_REGION1_START + +#define TEST_HP_PERI_REGION2_START DR_REG_UART2_BASE +#define TEST_HP_PERI_REGION2_END DR_REG_TIMG1_BASE +#define TEST_HP_PERI_ADDR2 TEST_HP_PERI_REGION2_START + +#define TEST_HP_PERI_REGION3_START DR_REG_TIMG1_BASE +#define TEST_HP_PERI_REGION3_END DR_REG_I2S_BASE +#define TEST_HP_PERI_ADDR3 TEST_HP_PERI_REGION3_START + +#define TEST_HP_PERI_REGION4_START DR_REG_I2S_BASE +#define TEST_HP_PERI_REGION4_END DR_REG_INTMTX_BASE +#define TEST_HP_PERI_ADDR4 TEST_HP_PERI_REGION4_START + +#define TEST_HP_PERI_REGION5_START DR_REG_INTMTX_BASE +#define TEST_HP_PERI_REGION5_END ALIGN_TO_NEXT_4KB(DR_REG_SOC_ETM_BASE) +#define TEST_HP_PERI_ADDR5 TEST_HP_PERI_REGION5_START + +#define TEST_HP_PERI_REGION6_START DR_REG_HINF_BASE +#define TEST_HP_PERI_REGION6_END DR_REG_HOST_BASE +#define TEST_HP_PERI_ADDR6 TEST_HP_PERI_REGION6_START + +#define TEST_HP_PERI_REGION7_START DR_REG_HOST_BASE +#define TEST_HP_PERI_REGION7_END ALIGN_TO_NEXT_4KB(DR_REG_PVT_BASE) +#define TEST_HP_PERI_ADDR7 TEST_HP_PERI_REGION7_START + +/* PERI1 */ +#define TEST_HP_PERI_REGION8_START DR_REG_AHB_DMA_BASE +#define TEST_HP_PERI_REGION8_END ALIGN_TO_NEXT_4KB(DR_REG_SPI2_BASE) +#define TEST_HP_PERI_ADDR8 TEST_HP_PERI_REGION8_START + +#define TEST_HP_PERI_REGION9_START DR_REG_SHA_BASE +#define TEST_HP_PERI_REGION9_END DR_REG_ECC_MULT_BASE +#define TEST_HP_PERI_ADDR9 TEST_HP_PERI_REGION9_START + +#define TEST_HP_PERI_REGION10_START DR_REG_ECC_MULT_BASE +#define TEST_HP_PERI_REGION10_END ALIGN_TO_NEXT_4KB(DR_REG_ECDSA_BASE) +#define TEST_HP_PERI_ADDR10 TEST_HP_PERI_REGION10_START + +/* PERI2 */ +#define TEST_HP_PERI_REGION11_START DR_REG_IO_MUX_BASE +#define TEST_HP_PERI_REGION11_END DR_REG_GPIO_BASE +#define TEST_HP_PERI_ADDR11 TEST_HP_PERI_REGION11_START + +#define TEST_HP_PERI_REGION12_START DR_REG_GPIO_BASE +#define TEST_HP_PERI_REGION12_END DR_REG_MEM_MONITOR_BASE +#define TEST_HP_PERI_ADDR12 TEST_HP_PERI_REGION12_START + +#define TEST_HP_PERI_REGION13_START DR_REG_MEM_MONITOR_BASE +#define TEST_HP_PERI_REGION13_END DR_REG_HP_SYSTEM_BASE +#define TEST_HP_PERI_ADDR13 TEST_HP_PERI_REGION13_START + +#define TEST_HP_PERI_REGION14_START DR_REG_HP_SYSTEM_BASE +#define TEST_HP_PERI_REGION14_END ALIGN_TO_NEXT_4KB(DR_REG_CPU_APM_REG_BASE) +#define TEST_HP_PERI_ADDR14 TEST_HP_PERI_REGION14_START + +#define TEST_HP_PERI_REGION15_START ALIGN_TO_NEXT_4KB(DR_REG_CPU_APM_REG_BASE) +#define TEST_HP_PERI_REGION15_END DR_REG_PMU_BASE +#define TEST_HP_PERI_ADDR15 TEST_HP_PERI_REGION15_START + +#define TEST_HP_PERI_RESV_MASK BIT(0) + +/********* LP_PERI (4 regions) *********/ +#define TEST_LP_PERI_REGION0_START DR_REG_PMU_BASE +#define TEST_LP_PERI_REGION0_END DR_REG_LP_AON_BASE +#define TEST_LP_PERI_ADDR0 TEST_LP_PERI_REGION0_START + +#define TEST_LP_PERI_REGION1_START DR_REG_LP_AON_BASE +#define TEST_LP_PERI_REGION1_END DR_REG_LP_ANA_BASE +#define TEST_LP_PERI_ADDR1 TEST_LP_PERI_REGION1_START + +#define TEST_LP_PERI_REGION2_START DR_REG_LP_ANA_BASE +#define TEST_LP_PERI_REGION2_END DR_REG_LP_IO_MUX_BASE +#define TEST_LP_PERI_ADDR2 TEST_LP_PERI_REGION2_START + +#define TEST_LP_PERI_REGION3_START DR_REG_LP_IO_MUX_BASE +#define TEST_LP_PERI_REGION3_END ALIGN_TO_NEXT_4KB(DR_REG_OTP_DEBUG_BASE) +#define TEST_LP_PERI_ADDR3 TEST_LP_PERI_REGION3_START + +#define TEST_LP_PERI_RESV_MASK (0U) diff --git a/components/hal/test_apps/tee_apm/components/pms/priv_include/esp32h2/test_pms_params.h b/components/hal/test_apps/tee_apm/components/pms/priv_include/esp32h2/test_pms_params.h new file mode 100644 index 0000000000..b22a7ce8c9 --- /dev/null +++ b/components/hal/test_apps/tee_apm/components/pms/priv_include/esp32h2/test_pms_params.h @@ -0,0 +1,151 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "soc/soc.h" +#include "soc/reg_base.h" + +#include "hal/apm_types.h" +#include "esp_bit_defs.h" + +/* + * NOTE: By default, TEE mode should have unrestricted access to the entire CPU address space. + * However, for ESP32-C6 and ESP32-H2, it has been observed that when APM filters are enabled, + * TEE mode accesses are incorrectly being filtered based on the region configurations and + * access attributes set for REE[0..2] modes. + */ +#define SOC_APM_CTRL_TEE_MODE_ACCESS_BUG 1 + +/********* GDMA APM master ID *********/ +#define TEST_GDMA_APM_MASTER_ID APM_MASTER_GDMA_GPSPI + +/********* APM controller and path definitions *********/ +#define HP_CPU_CPUPERI_APM_CTRL APM_CTRL_HP_APM +#define HP_CPU_CPUPERI_APM_PATH APM_CTRL_ACCESS_PATH_M0 +/* NOTE: ESP32-H2 has only 4 CPU peripherals */ +#define TEST_HP_CPU_CPUPERI_REGN_NUM 4 + +#define HP_CPU_LPMEM_APM_CTRL APM_CTRL_HP_APM +#define HP_CPU_LPMEM_APM_PATH APM_CTRL_ACCESS_PATH_M1 +/* NOTE: ESP32-H2 has only 4KB LP_MEM */ +#define HP_CPU_LPMEM_TEST_REGN_NUM 8 + +#define GDMA_HPMEM_APM_CTRL APM_CTRL_HP_APM +#define GDMA_HPMEM_APM_PATH APM_CTRL_ACCESS_PATH_M2 +#define GDMA_HPMEM_TEST_REGN_NUM APM_CTRL_HP_APM_REGION_NUM + +#define HP_CPU_HPPERI_APM_CTRL APM_CTRL_HP_APM +#define HP_CPU_HPPERI_APM_PATH APM_CTRL_ACCESS_PATH_M3 +#define HP_CPU_HPPERI_TEST_REGN_NUM APM_CTRL_HP_APM_REGION_NUM + +#define HP_CPU_LPPERI_APM_CTRL APM_CTRL_LP_APM +#define HP_CPU_LPPERI_APM_PATH APM_CTRL_ACCESS_PATH_M0 +#define HP_CPU_LPPERI_TEST_REGN_NUM APM_CTRL_LP_APM_REGION_NUM + +/********* APM peripheral space test regions *********/ +#define ALIGN_TO_NEXT_4KB(addr) (((addr) + 0x1000) & ~0xFFF) + +/********* CPU_PERI (4 regions) *********/ +#define TEST_CPU_PERI_REGION0_START DR_REG_TRACE_BASE +#define TEST_CPU_PERI_REGION0_END DR_REG_ASSIST_DEBUG_BASE +#define TEST_CPU_PERI_ADDR0 TEST_CPU_PERI_REGION0_START + +#define TEST_CPU_PERI_REGION1_START DR_REG_ASSIST_DEBUG_BASE +#define TEST_CPU_PERI_REGION1_END DR_REG_INTPRI_BASE +#define TEST_CPU_PERI_ADDR1 TEST_CPU_PERI_REGION1_START + +#define TEST_CPU_PERI_REGION2_START DR_REG_INTPRI_BASE +#define TEST_CPU_PERI_REGION2_END DR_REG_CACHE_BASE +#define TEST_CPU_PERI_ADDR2 TEST_CPU_PERI_REGION2_START + +#define TEST_CPU_PERI_REGION3_START DR_REG_CACHE_BASE +#define TEST_CPU_PERI_REGION3_END ALIGN_TO_NEXT_4KB(DR_REG_CACHE_BASE) +#define TEST_CPU_PERI_ADDR3 TEST_CPU_PERI_REGION3_START + +#define TEST_CPU_PERI_RESV_MASK (0U) + +/********* HP_PERI (16 regions) *********/ +/* PERI0 */ +/* 0: UART0 - I2C - Reserved (UART0 accessed) */ +#define TEST_HP_PERI_REGION0_START DR_REG_UART_BASE +#define TEST_HP_PERI_REGION0_END DR_REG_I2C_EXT0_BASE +#define TEST_HP_PERI_ADDR0 TEST_HP_PERI_REGION0_START + +#define TEST_HP_PERI_REGION1_START DR_REG_I2C_EXT0_BASE +#define TEST_HP_PERI_REGION1_END DR_REG_LEDC_BASE +#define TEST_HP_PERI_ADDR1 TEST_HP_PERI_REGION1_START + +#define TEST_HP_PERI_REGION2_START DR_REG_LEDC_BASE +#define TEST_HP_PERI_REGION2_END DR_REG_TWAI_BASE +#define TEST_HP_PERI_ADDR2 TEST_HP_PERI_REGION2_START + +#define TEST_HP_PERI_REGION3_START DR_REG_TWAI_BASE +#define TEST_HP_PERI_REGION3_END DR_REG_INTMTX_BASE +#define TEST_HP_PERI_ADDR3 TEST_HP_PERI_REGION3_START + +#define TEST_HP_PERI_REGION4_START DR_REG_INTMTX_BASE +#define TEST_HP_PERI_REGION4_END DR_REG_MCPWM_BASE +#define TEST_HP_PERI_ADDR4 TEST_HP_PERI_REGION4_START + +#define TEST_HP_PERI_REGION5_START DR_REG_MCPWM_BASE +#define TEST_HP_PERI_REGION5_END DR_REG_PARL_IO_BASE +#define TEST_HP_PERI_ADDR5 TEST_HP_PERI_REGION5_START + +#define TEST_HP_PERI_REGION6_START DR_REG_PARL_IO_BASE +#define TEST_HP_PERI_REGION6_END ALIGN_TO_NEXT_4KB(DR_REG_PVT_MONITOR_BASE) +#define TEST_HP_PERI_ADDR6 TEST_HP_PERI_REGION6_START + +/* PERI1 */ +#define TEST_HP_PERI_REGION7_START DR_REG_GDMA_BASE +#define TEST_HP_PERI_REGION7_END ALIGN_TO_NEXT_4KB(DR_REG_SPI2_BASE) +#define TEST_HP_PERI_ADDR7 TEST_HP_PERI_REGION7_START + +#define TEST_HP_PERI_REGION8_START DR_REG_AES_BASE +#define TEST_HP_PERI_REGION8_END DR_REG_RSA_BASE +#define TEST_HP_PERI_ADDR8 TEST_HP_PERI_REGION8_START + +#define TEST_HP_PERI_REGION9_START DR_REG_RSA_BASE +#define TEST_HP_PERI_REGION9_END DR_REG_DS_BASE +#define TEST_HP_PERI_ADDR9 TEST_HP_PERI_REGION9_START + +#define TEST_HP_PERI_REGION10_START DR_REG_DS_BASE +#define TEST_HP_PERI_REGION10_END ALIGN_TO_NEXT_4KB(DR_REG_ECDSA_BASE) +#define TEST_HP_PERI_ADDR10 TEST_HP_PERI_REGION10_START + +/* PERI2 */ +#define TEST_HP_PERI_REGION11_START DR_REG_IO_MUX_BASE +#define TEST_HP_PERI_REGION11_END DR_REG_MEM_MONITOR_BASE +#define TEST_HP_PERI_ADDR11 TEST_HP_PERI_REGION11_START + +#define TEST_HP_PERI_REGION12_START DR_REG_MEM_MONITOR_BASE +#define TEST_HP_PERI_REGION12_END DR_REG_HP_SYSTEM_BASE +#define TEST_HP_PERI_ADDR12 TEST_HP_PERI_REGION12_START + +#define TEST_HP_PERI_REGION13_START DR_REG_HP_SYSTEM_BASE +#define TEST_HP_PERI_REGION13_END DR_REG_TEE_BASE +#define TEST_HP_PERI_ADDR13 TEST_HP_PERI_REGION13_START + +#define TEST_HP_PERI_REGION14_START DR_REG_TEE_BASE +#define TEST_HP_PERI_REGION14_END DR_REG_MISC_BASE +#define TEST_HP_PERI_ADDR14 TEST_HP_PERI_REGION14_START + +#define TEST_HP_PERI_REGION15_START DR_REG_MISC_BASE +#define TEST_HP_PERI_REGION15_END DR_REG_PMU_BASE +#define TEST_HP_PERI_ADDR15 TEST_HP_PERI_REGION15_START + +#define TEST_HP_PERI_RESV_MASK BIT(0) + +/********* LP_PERI (2 regions) *********/ +#define TEST_LP_PERI_REGION0_START DR_REG_PMU_BASE +#define TEST_LP_PERI_REGION0_END DR_REG_LP_IO_BASE +#define TEST_LP_PERI_ADDR0 TEST_LP_PERI_REGION0_START + +#define TEST_LP_PERI_REGION1_START DR_REG_LP_IO_BASE +#define TEST_LP_PERI_REGION1_END ALIGN_TO_NEXT_4KB(DR_REG_OTP_DEBUG_BASE) +#define TEST_LP_PERI_ADDR1 TEST_LP_PERI_REGION1_START + +#define TEST_LP_PERI_RESV_MASK (0U) diff --git a/components/hal/test_apps/tee_apm/components/pms/priv_include/test_pms_priv.h b/components/hal/test_apps/tee_apm/components/pms/priv_include/test_pms_priv.h new file mode 100644 index 0000000000..3aa99c41a0 --- /dev/null +++ b/components/hal/test_apps/tee_apm/components/pms/priv_include/test_pms_priv.h @@ -0,0 +1,99 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +#include "soc/soc.h" +#include "soc/soc_caps.h" + +#include "soc/lp_aon_reg.h" +#include "hal/apm_types.h" + +/********* Panic Handler *********/ + +#define MCAUSE_INST_ACCESS_FAULT 1 +#define MCAUSE_ILLEGAL_INSTRUCTION 2 +#define MCAUSE_LOAD_ACCESS_FAULT 5 +#define MCAUSE_STORE_ACCESS_FAULT 7 + +/********* HP_CPU - LP_CPU messaging *********/ + +#define SEND_MSG(msg) REG_WRITE(LP_AON_STORE0_REG, msg) +#define RECV_MSG() REG_READ(LP_AON_STORE0_REG) + +#define SEND_ADDR(addr) REG_WRITE(LP_AON_STORE7_REG, addr) +#define RECV_ADDR() REG_READ(LP_AON_STORE7_REG) + +#define SEND_SIZE(size) REG_WRITE(LP_AON_STORE8_REG, size) +#define RECV_SIZE() REG_READ(LP_AON_STORE8_REG) + +#define SEND_EXCP(val) REG_WRITE(LP_AON_STORE9_REG, val) +#define RECV_EXCP() REG_READ(LP_AON_STORE9_REG) + +#define MSG_SLAVE_READ 0x11221122 +#define MSG_SLAVE_WRITE 0x33443344 +#define MSG_SLAVE_EXEC 0x55665566 +#define MSG_SLAVE_CLEAR 0x77887788 + +#if SOC_RTC_MEM_SUPPORTED +#define ADJUST_LP_MEM_ADDR(addr) \ + do { \ + if (((addr) >= (SOC_RTC_IRAM_LOW + 0x20000000)) \ + && ((addr) < (SOC_RTC_DRAM_HIGH + 0x20000000))) { \ + (addr) -= 0x20000000; \ + } \ + } while (0) +#endif + +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; + +/* Utility functions */ +void set_test_vector_table(void); +void restore_default_vector_table(void); +void test_m2u_switch(void); +void test_u2m_switch(void); + +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); + +void test_boot_lp_cpu(void); +void test_stop_lp_cpu(void); +void test_reset_lp_cpu(void); +void test_switch_lp_mem_speed(bool high_speed); + +void test_gdma_init(void); +void test_gdma_deinit(void); +void test_gdma_m2m_transfer(uint8_t *src, uint8_t *dest, size_t size); +void test_gdma_wait_done(void); + +void test_delay_us(uint32_t us); diff --git a/components/hal/test_apps/tee_apm/components/pms/src/test_apm_utils.c b/components/hal/test_apps/tee_apm/components/pms/src/test_apm_utils.c new file mode 100644 index 0000000000..cff666dc4a --- /dev/null +++ b/components/hal/test_apps/tee_apm/components/pms/src/test_apm_utils.c @@ -0,0 +1,370 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "soc/soc.h" +#include "soc/soc_caps.h" +#include "soc/interrupts.h" + +#include "soc/apm_defs.h" +#include "hal/apm_hal.h" +#include "hal/apm_types.h" + +#include "esp_attr.h" +#include "esp_intr_alloc.h" +#include "esp_rom_sys.h" + +#include "unity.h" + +/***************************** Utility - APM interrupts *****************************/ + +#define MAX_APM_CTRL_NUM (4) +#define MAX_APM_PATH_NUM (5) + +static intr_handle_t s_apm_intr_hdl[MAX_APM_CTRL_NUM][MAX_APM_PATH_NUM] = { 0 }; + +static void test_apm_ctrl_free_all_intr(void); + +/***************************** Utility - APM HAL *****************************/ + +void apm_hal_enable_region_filter_all(apm_ctrl_module_t ctrl_mod, bool enable) +{ + switch (ctrl_mod) { + case APM_CTRL_HP_APM: + REG_WRITE(HP_APM_REGION_FILTER_EN_REG, enable ? UINT32_MAX : 0); + break; +#if SOC_APM_LP_APM0_SUPPORTED + case APM_CTRL_LP_APM0: + REG_WRITE(LP_APM0_REGION_FILTER_EN_REG, enable ? UINT32_MAX : 0); + break; +#endif + case APM_CTRL_LP_APM: + REG_WRITE(LP_APM_REGION_FILTER_EN_REG, enable ? UINT32_MAX : 0); + break; +#if SOC_APM_CPU_APM_SUPPORTED + case APM_CTRL_CPU_APM: + REG_WRITE(CPU_APM_REGION_FILTER_EN_REG, enable ? UINT32_MAX : 0); + break; +#endif + default: + break; + } +} + +/********************************** APM Reset *************************************/ + +static void test_hp_apm_ctrl_reset(void) +{ + apm_hal_set_master_sec_mode_all(APM_SEC_MODE_TEE); + apm_ll_hp_apm_enable_ctrl_filter_all(false); + + for (int i = 0; i < APM_CTRL_HP_APM_REGION_NUM; i++) { + apm_ll_hp_apm_set_region_start_addr(i, 0x00U); + apm_ll_hp_apm_set_region_end_addr(i, UINT32_MAX); + apm_ll_hp_apm_set_sec_mode_region_attr(i, APM_SEC_MODE_REE0, APM_PERM_NONE); + apm_ll_hp_apm_set_sec_mode_region_attr(i, APM_SEC_MODE_REE1, APM_PERM_NONE); + apm_ll_hp_apm_set_sec_mode_region_attr(i, APM_SEC_MODE_REE2, APM_PERM_NONE); + } + + apm_hal_ctrl_info_t ctrl_info = { + .ctrl_mod = APM_CTRL_HP_APM, + }; + for (int i = 0; i < APM_CTRL_HP_APM_PATH_NUM; i++) { + ctrl_info.path = (apm_ctrl_access_path_t)i; + apm_hal_enable_intr(&ctrl_info, false); + apm_hal_clear_exception_status(&ctrl_info); + } +} + +#if SOC_APM_LP_APM0_SUPPORTED +static void test_lp_apm0_ctrl_reset(void) +{ + apm_hal_set_master_sec_mode_all(APM_SEC_MODE_TEE); + apm_ll_lp_apm0_enable_ctrl_filter_all(false); + + for (int i = 0; i < APM_CTRL_LP_APM0_REGION_NUM; i++) { + apm_ll_lp_apm0_set_region_start_addr(i, 0x00U); + apm_ll_lp_apm0_set_region_end_addr(i, UINT32_MAX); + apm_ll_lp_apm0_set_sec_mode_region_attr(i, APM_SEC_MODE_REE0, APM_PERM_NONE); + apm_ll_lp_apm0_set_sec_mode_region_attr(i, APM_SEC_MODE_REE1, APM_PERM_NONE); + apm_ll_lp_apm0_set_sec_mode_region_attr(i, APM_SEC_MODE_REE2, APM_PERM_NONE); + } + + apm_hal_ctrl_info_t ctrl_info = { + .ctrl_mod = APM_CTRL_LP_APM0, + }; + for (int i = 0; i < APM_CTRL_LP_APM0_PATH_NUM; i++) { + ctrl_info.path = (apm_ctrl_access_path_t)i; + apm_hal_enable_intr(&ctrl_info, false); + apm_hal_clear_exception_status(&ctrl_info); + } +} +#endif + +static void test_lp_apm_ctrl_reset(void) +{ + apm_hal_set_master_sec_mode_all(APM_SEC_MODE_TEE); + apm_ll_lp_apm_enable_ctrl_filter_all(false); + + for (int i = 0; i < APM_CTRL_LP_APM_REGION_NUM; i++) { + apm_ll_lp_apm_set_region_start_addr(i, 0x00U); + apm_ll_lp_apm_set_region_end_addr(i, UINT32_MAX); + apm_ll_lp_apm_set_sec_mode_region_attr(i, APM_SEC_MODE_REE0, APM_PERM_NONE); + apm_ll_lp_apm_set_sec_mode_region_attr(i, APM_SEC_MODE_REE1, APM_PERM_NONE); + apm_ll_lp_apm_set_sec_mode_region_attr(i, APM_SEC_MODE_REE2, APM_PERM_NONE); + } + + apm_hal_ctrl_info_t ctrl_info = { + .ctrl_mod = APM_CTRL_LP_APM, + }; + for (int i = 0; i < APM_CTRL_LP_APM_PATH_NUM; i++) { + ctrl_info.path = (apm_ctrl_access_path_t)i; + apm_hal_enable_intr(&ctrl_info, false); + apm_hal_clear_exception_status(&ctrl_info); + } +} + +#if SOC_APM_CPU_APM_SUPPORTED +static void test_cpu_apm_ctrl_reset(void) +{ + apm_hal_set_master_sec_mode_all(APM_SEC_MODE_TEE); + apm_ll_cpu_apm_enable_ctrl_filter_all(false); + + for (int i = 0; i < APM_CTRL_CPU_APM_REGION_NUM; i++) { + apm_ll_cpu_apm_set_region_start_addr(i, 0x00U); + apm_ll_cpu_apm_set_region_end_addr(i, UINT32_MAX); + apm_ll_cpu_apm_set_sec_mode_region_attr(i, APM_SEC_MODE_REE0, APM_PERM_NONE); + apm_ll_cpu_apm_set_sec_mode_region_attr(i, APM_SEC_MODE_REE1, APM_PERM_NONE); + apm_ll_cpu_apm_set_sec_mode_region_attr(i, APM_SEC_MODE_REE2, APM_PERM_NONE); + } + + apm_hal_ctrl_info_t ctrl_info = { + .ctrl_mod = APM_CTRL_CPU_APM, + }; + for (int i = 0; i < APM_CTRL_CPU_APM_PATH_NUM; i++) { + ctrl_info.path = (apm_ctrl_access_path_t)i; + apm_hal_enable_intr(&ctrl_info, false); + apm_hal_clear_exception_status(&ctrl_info); + } +} +#endif + +#if SOC_APM_SUPPORT_TEE_PERI_ACCESS_CTRL +static void test_tee_peri_access_reset(void) +{ + for (uint32_t mode = APM_SEC_MODE_REE0; mode <= APM_SEC_MODE_REE2; mode++) { + apm_hal_tee_set_peri_access_all(APM_TEE_CTRL_HP, (apm_security_mode_t)mode, APM_PERM_R | APM_PERM_W); + apm_hal_tee_set_peri_access_all(APM_TEE_CTRL_LP, (apm_security_mode_t)mode, APM_PERM_R | APM_PERM_W); + } +} +#endif + +void test_apm_ctrl_reset_all(void) +{ + test_hp_apm_ctrl_reset(); + test_lp_apm_ctrl_reset(); +#if SOC_APM_LP_APM0_SUPPORTED + test_lp_apm0_ctrl_reset(); +#endif +#if SOC_APM_CPU_APM_SUPPORTED + test_cpu_apm_ctrl_reset(); +#endif +#if SOC_APM_SUPPORT_TEE_PERI_ACCESS_CTRL + test_tee_peri_access_reset(); +#endif + test_apm_ctrl_free_all_intr(); +} + +/********************************** APM violation helper functions *************************************/ + +static const char *const excp_mid_strs[] = { + [APM_MASTER_HPCORE] = "HPCORE", +#if SOC_LP_CORE_SUPPORTED + [APM_MASTER_LPCORE] = "LPCORE", +#endif /* SOC_LP_CORE_SUPPORTED */ + [APM_MASTER_REGDMA] = "REGDMA", +#if SOC_SDIO_SLAVE_SUPPORTED + [APM_MASTER_SDIOSLV] = "SDIOSLV", +#endif /* SOC_SDIO_SLAVE_SUPPORTED */ + [APM_MASTER_MODEM] = "MODEM", + [APM_MASTER_MEM_MON] = "MEM_MONITOR", + [APM_MASTER_TRACE] = "TRACE", +#if SOC_SPIRAM_SUPPORTED + [APM_MASTER_PSRAM_MEM_MON] = "PSRAM_MEM_MONITOR", +#endif /* SOC_SPIRAM_SUPPORTED */ +#if SOC_GPSPI_SUPPORTED + [APM_MASTER_GDMA_GPSPI] = "GDMA_GPSPI", +#endif /* SOC_GPSPI_SUPPORTED */ +#if SOC_UHCI_SUPPORTED + [APM_MASTER_GDMA_UHCI] = "GDMA_UHCI", +#endif /* SOC_UHCI_SUPPORTED */ + [APM_MASTER_GDMA_I2S] = "GDMA_I2S", +#if SOC_AES_SUPPORTED + [APM_MASTER_GDMA_AES] = "GDMA_AES", +#endif /* SOC_AES_SUPPORTED */ + [APM_MASTER_GDMA_SHA] = "GDMA_SHA", + [APM_MASTER_GDMA_ADC] = "GDMA_ADC", +#if SOC_PARLIO_SUPPORTED + [APM_MASTER_GDMA_PARLIO] = "GDMA_PARLIO", +#endif /* SOC_PARLIO_SUPPORTED */ + [26] = "GDMA_DUMMYX", +}; + +static const char *apm_excp_mid_to_str(uint8_t mid) +{ + if (mid < sizeof(excp_mid_strs) / sizeof(excp_mid_strs[0]) && excp_mid_strs[mid]) { + return excp_mid_strs[mid]; + } + return "Unknown"; +} + +static const char *apm_excp_type_to_str(uint8_t type) +{ + char *excp_type = "Unknown"; + + if (type & BIT(0)) { + excp_type = "Authority exception"; + } else if (type & BIT(1)) { + excp_type = "Space exception"; + } + + return excp_type; +} + +static const char *apm_excp_ctrl_to_str(apm_ctrl_module_t ctrl_mod) +{ + char *excp_ctrl = NULL; + + switch (ctrl_mod) { + case APM_CTRL_HP_APM: + excp_ctrl = "HP_APM"; + break; +#if SOC_APM_LP_APM0_SUPPORTED + case APM_CTRL_LP_APM0: + excp_ctrl = "LP_APM0"; + break; +#endif + case APM_CTRL_LP_APM: + excp_ctrl = "LP_APM"; + break; +#if SOC_APM_CPU_APM_SUPPORTED + case APM_CTRL_CPU_APM: + excp_ctrl = "CPU_APM"; + break; +#endif + default: + excp_ctrl = "Unknown"; + break; + } + + return excp_ctrl; +} + +static const char *apm_excp_mode_to_str(uint8_t mode) +{ + char *excp_mode = NULL; + + switch (mode) { + case APM_SEC_MODE_TEE: + case APM_SEC_MODE_REE0: + excp_mode = "REE0"; + break; + case APM_SEC_MODE_REE1: + excp_mode = "REE1"; + break; + case APM_SEC_MODE_REE2: + excp_mode = "REE2"; + break; + default: + excp_mode = "Unknown"; + break; + } + + return excp_mode; +} + +/********************************** APM exception check *************************************/ + +#define ETS_HP_APM_INTR_SOURCE(n) (ETS_HP_APM_M0_INTR_SOURCE + n) +#if SOC_APM_LP_APM0_SUPPORTED +#define ETS_LP_APM0_INTR_SOURCE(n) (ETS_LP_APM0_INTR_SOURCE + n) +#endif +#define ETS_LP_APM_INTR_SOURCE(n) (ETS_LP_APM_M0_INTR_SOURCE + n) +#if SOC_APM_CPU_APM_SUPPORTED +#define ETS_CPU_APM_INTR_SOURCE(n) (ETS_CPU_APM_M0_INTR_SOURCE + n) +#endif + +volatile bool apm_master_excp_flag[APM_MASTER_MAX]; + +/* interrupt handler, clears the interrupt */ +IRAM_ATTR void apm_ctrl_intr_cb(void *arg) +{ + apm_hal_ctrl_info_t *ctrl_info = (apm_hal_ctrl_info_t *)arg; + apm_ctrl_exception_info_t excp_info = {}; + + apm_hal_get_exception_info(ctrl_info, &excp_info); + apm_hal_clear_exception_status(ctrl_info); + + apm_master_excp_flag[excp_info.id] = true; + + esp_rom_printf("APM violation: %s\n\r", apm_excp_type_to_str(excp_info.type)); + esp_rom_printf("Access addr: 0x%08x | Mode: %s\n\r", excp_info.addr, apm_excp_mode_to_str(excp_info.mode)); + esp_rom_printf("Module: %s | Path: %d\n\r", apm_excp_ctrl_to_str(ctrl_info->ctrl_mod), ctrl_info->path); + esp_rom_printf("Master: %s | Region: %d\n\r", apm_excp_mid_to_str(excp_info.id), (excp_info.regn == 0) ? 0 : (__builtin_ffs(excp_info.regn) - 1)); +} + +void test_apm_ctrl_enable_intr(apm_ctrl_module_t ctrl_mod, apm_ctrl_access_path_t path) +{ + apm_hal_ctrl_info_t *ctrl_info = calloc(1, sizeof(apm_hal_ctrl_info_t)); + TEST_ASSERT_NOT_NULL(ctrl_info); + + ctrl_info->ctrl_mod = ctrl_mod; + ctrl_info->path = path; + + int intr_src = -1; + switch (ctrl_mod) { + case APM_CTRL_HP_APM: + intr_src = ETS_HP_APM_INTR_SOURCE(path); + break; +#if SOC_APM_LP_APM0_SUPPORTED + case APM_CTRL_LP_APM0: + intr_src = ETS_LP_APM0_INTR_SOURCE(path); + break; +#endif + case APM_CTRL_LP_APM: + intr_src = ETS_LP_APM_INTR_SOURCE(path); + break; +#if SOC_APM_CPU_APM_SUPPORTED + case APM_CTRL_CPU_APM: + intr_src = ETS_CPU_APM_INTR_SOURCE(path); + break; +#endif + default: + TEST_ASSERT_MESSAGE(false, "Invalid APM module"); + return; + } + + uint32_t flags = ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL3; + intr_handle_t *handle = &s_apm_intr_hdl[ctrl_mod][path]; + TEST_ESP_OK(esp_intr_alloc(intr_src, flags, &apm_ctrl_intr_cb, ctrl_info, handle)); + + apm_hal_enable_intr(ctrl_info, true); +} + +static void test_apm_ctrl_free_all_intr(void) +{ + for (int ctrl_mod = 0; ctrl_mod < MAX_APM_CTRL_NUM; ctrl_mod++) { + for (int path = 0; path < MAX_APM_PATH_NUM; path++) { + if (s_apm_intr_hdl[ctrl_mod][path]) { + TEST_ESP_OK(esp_intr_free(s_apm_intr_hdl[ctrl_mod][path])); + s_apm_intr_hdl[ctrl_mod][path] = NULL; + } + } + } +} diff --git a/components/hal/test_apps/tee_apm/components/pms/src/test_intr_utils.c b/components/hal/test_apps/tee_apm/components/pms/src/test_intr_utils.c new file mode 100644 index 0000000000..92972cb881 --- /dev/null +++ b/components/hal/test_apps/tee_apm/components/pms/src/test_intr_utils.c @@ -0,0 +1,77 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "soc/soc_caps.h" +#include "esp_cpu.h" + +#include "riscv/encoding.h" +#include "riscv/csr.h" +#include "riscv/rv_utils.h" + +#include "esp_rom_sys.h" + +#if SOC_INT_PLIC_SUPPORTED +#include "esp_private/interrupt_plic.h" +#elif SOC_INT_CLIC_SUPPORTED +#include "esp_private/interrupt_clic.h" +#else +#include "esp_private/interrupt_intc.h" +#endif + +/********************************** Vector Table Redirection *******************************/ + +extern int _vector_table; +extern int _test_vector_table; + +void set_test_vector_table(void) +{ + rv_utils_intr_global_disable(); + rv_utils_set_mtvec((uintptr_t)&_test_vector_table); + rv_utils_intr_global_enable(); +} + +void restore_default_vector_table(void) +{ + rv_utils_intr_global_disable(); + rv_utils_set_mtvec((uintptr_t)&_vector_table); + rv_utils_intr_global_enable(); +} + +/********************************** Privilege Mode Switch *********************************/ + +void test_m2u_switch(void) +{ + int mode = esp_cpu_get_curr_privilege_level(); + assert(mode == PRV_M); + + asm volatile("ecall\n"); + + mode = esp_cpu_get_curr_privilege_level(); + assert(mode == PRV_U); +} + +void test_u2m_switch(void) +{ + int mode = esp_cpu_get_curr_privilege_level(); + assert(mode == PRV_U); + + asm volatile("ecall\n"); + + mode = esp_cpu_get_curr_privilege_level(); + assert(mode == PRV_M); +} + +/********************************** Interrupt Handler *************************************/ + +extern void _global_interrupt_handler(intptr_t sp, int mcause); + +/* called from test_tee_vectors.S */ +void _test_global_interrupt_handler(intptr_t sp, int mcause) +{ + _global_interrupt_handler(sp, mcause); +} diff --git a/components/hal/test_apps/tee_apm/components/pms/src/test_panic_handler.c b/components/hal/test_apps/tee_apm/components/pms/src/test_panic_handler.c new file mode 100644 index 0000000000..aea6d6d1d3 --- /dev/null +++ b/components/hal/test_apps/tee_apm/components/pms/src/test_panic_handler.c @@ -0,0 +1,82 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "soc/soc_caps.h" +#include "esp_macros.h" +#include "esp_rom_sys.h" +#include "esp_rom_uart.h" + +#include "riscv/csr.h" +#include "riscv/rvruntime-frames.h" +#include "esp_private/vectors_const.h" +#include "test_pms_priv.h" + +#define panic_print(format, ...) esp_rom_printf(DRAM_STR(format), ##__VA_ARGS__) + +void test_panicHandler(RvExcFrame *frame, int exccause) +{ + const RvExcFrame *regs = (const RvExcFrame *)frame; + const void *addr = (const void *)regs->mepc; + + static const char *reason[] = { + "Instruction address misaligned", + "Instruction access fault", + "Illegal instruction", + "Breakpoint", + "Load address misaligned", + "Load access fault", + "Store address misaligned", + "Store access fault", + "Environment call from U-mode", + "Environment call from S-mode", + NULL, + "Environment call from M-mode", + "Instruction page fault", + "Load page fault", + NULL, + "Store page fault", + }; + + const char *rsn = "Unknown"; + uint32_t mcause = regs->mcause & (VECTORS_MCAUSE_INTBIT_MASK | VECTORS_MCAUSE_REASON_MASK); + if (mcause < (sizeof(reason) / sizeof(reason[0]))) { + if (reason[mcause] != NULL) { + rsn = (reason[mcause]); + } + } + + if (mcause == MCAUSE_ILLEGAL_INSTRUCTION) { + frame->mepc = frame->ra; + return; + } + + /* PERI_APM access fault */ +#if SOC_APM_SUPPORT_TEE_PERI_ACCESS_CTRL + if (regs->mtval >= SOC_PERIPHERAL_LOW && regs->mtval < SOC_PERIPHERAL_HIGH) { + if (mcause == MCAUSE_LOAD_ACCESS_FAULT || mcause == MCAUSE_STORE_ACCESS_FAULT) { + panic_print("[PERI_APM] %s at 0x%08x\n\r", rsn, regs->mtval); + frame->mepc += 0x04U; + RV_WRITE_CSR(uscratch, regs->mtval); + return; + } + } +#endif + + panic_print("Guru Meditation Error: Core %d panic'ed (%s). Exception was unhandled.\n", regs->mhartid, rsn); + panic_print("Origin : %s\n\r", (regs->mstatus & MSTATUS_MPP) ? "M-mode" : "U-mode"); + panic_print("MEPC : %p | MCAUSE : 0x%08x\n\r", addr, mcause); + panic_print("MTVAL : 0x%08x | MSTATUS: 0x%08x\n\r", regs->mtval, regs->mstatus); + panic_print("MTVEC : 0x%08x\n\r", regs->mtvec); + panic_print("Rebooting...\r\n"); + + if (CONFIG_ESP_CONSOLE_UART_NUM >= 0) { + esp_rom_output_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM); + } + esp_rom_software_reset_system(); + ESP_INFINITE_LOOP(); +} diff --git a/components/hal/test_apps/tee_apm/components/pms/src/test_setup_utils.c b/components/hal/test_apps/tee_apm/components/pms/src/test_setup_utils.c new file mode 100644 index 0000000000..959044d477 --- /dev/null +++ b/components/hal/test_apps/tee_apm/components/pms/src/test_setup_utils.c @@ -0,0 +1,245 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "soc/soc.h" +#include "soc/soc_caps.h" + +#include "hal/gdma_ll.h" +#include "soc/gdma_channel.h" +#if SOC_AHB_GDMA_VERSION == 2 +#include "soc/ahb_dma_struct.h" +#elif SOC_AHB_GDMA_VERSION == 1 +#include "soc/gdma_struct.h" +#endif + +#include "soc/lp_aon_reg.h" +#include "soc/lpperi_reg.h" +#if CONFIG_ULP_COPROC_ENABLED +#include "ulp_lp_core.h" +#endif + +#include "esp_attr.h" +#include "esp_rom_lldesc.h" +#include "esp_rom_sys.h" + +#include "riscv/csr.h" +#include "riscv/rv_utils.h" + +#include "test_pms_priv.h" +#include "unity.h" +#include "sdkconfig.h" + +/***************************** Utility - LP_CPU *****************************/ + +#if CONFIG_ULP_COPROC_ENABLED +extern const uint8_t ulp_lp_core_main_bin_start[] asm("_binary_ulp_lp_core_pms_bin_start"); +extern const uint8_t ulp_lp_core_main_bin_end[] asm("_binary_ulp_lp_core_pms_bin_end"); + +void test_boot_lp_cpu(void) +{ + size_t ulp_lp_core_main_bin_size = (ulp_lp_core_main_bin_end - ulp_lp_core_main_bin_start); + TEST_ESP_OK(ulp_lp_core_load_binary((void*)ulp_lp_core_main_bin_start, ulp_lp_core_main_bin_size)); + + ulp_lp_core_cfg_t cfg = { + .wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU, + }; + + SEND_MSG(MSG_SLAVE_CLEAR); + TEST_ESP_OK(ulp_lp_core_run(&cfg)); +} + +void test_stop_lp_cpu(void) +{ + ulp_lp_core_stop(); +} + +void test_reset_lp_cpu(void) +{ + REG_SET_BIT(LPPERI_RESET_EN_REG, LPPERI_LP_CPU_RESET_EN); +} + +void test_switch_lp_mem_speed(bool high_speed) +{ + if (high_speed) { + REG_SET_BIT(LP_AON_LPBUS_REG, LP_AON_FAST_MEM_MUX_SEL); + } else { + REG_CLR_BIT(LP_AON_LPBUS_REG, LP_AON_FAST_MEM_MUX_SEL); + } + REG_SET_BIT(LP_AON_LPBUS_REG, LP_AON_FAST_MEM_MUX_SEL_UPDATE); +} +#endif + +/***************************** Utility - GDMA *****************************/ + +#if SOC_AHB_GDMA_VERSION == 2 +#define TEST_DMA_DEV (AHB_DMA) +#define DMA_LL_FUNC(func) ahb_dma_ll_##func +#define DMA_MEM_TRANS_EN_FIELD mem_trans_en_chn +#elif SOC_AHB_GDMA_VERSION == 1 +#define TEST_DMA_DEV (GDMA) +#define DMA_LL_FUNC(func) gdma_ll_##func +#define DMA_MEM_TRANS_EN_FIELD mem_trans_en +#endif + +#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_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_tx_disconnect_from_periph DMA_LL_FUNC(tx_disconnect_from_periph) +#define dma_ll_rx_disconnect_from_periph DMA_LL_FUNC(rx_disconnect_from_periph) +#define dma_ll_tx_set_desc_addr DMA_LL_FUNC(tx_set_desc_addr) +#define dma_ll_tx_start DMA_LL_FUNC(tx_start) +#define dma_ll_rx_set_desc_addr DMA_LL_FUNC(rx_set_desc_addr) +#define dma_ll_rx_start DMA_LL_FUNC(rx_start) +#define dma_ll_tx_stop DMA_LL_FUNC(tx_stop) +#define dma_ll_rx_stop DMA_LL_FUNC(rx_stop) +#define dma_ll_tx_set_priority DMA_LL_FUNC(tx_set_priority) +#define dma_ll_rx_set_priority DMA_LL_FUNC(rx_set_priority) +#define dma_ll_tx_enable_interrupt DMA_LL_FUNC(tx_enable_interrupt) +#define dma_ll_rx_enable_interrupt DMA_LL_FUNC(rx_enable_interrupt) +#define dma_ll_tx_clear_interrupt_status DMA_LL_FUNC(tx_clear_interrupt_status) +#define dma_ll_rx_clear_interrupt_status DMA_LL_FUNC(rx_clear_interrupt_status) +#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_BLK_LEN 1024 +#define TEST_DMA_MAX_BLK_NUM 32 + +DRAM_ATTR static lldesc_t tx_link[TEST_DMA_MAX_BLK_NUM]; +DRAM_ATTR static lldesc_t rx_link[TEST_DMA_MAX_BLK_NUM]; + +static void setup_gdma_link(lldesc_t *link, uint8_t *buf, size_t size, bool is_tx) +{ + int x = 0; + for (x = 0; x < size / TEST_DMA_BLK_LEN; x++) { + link[x].size = TEST_DMA_BLK_LEN; + link[x].length = TEST_DMA_BLK_LEN; + link[x].buf = buf; + link[x].eof = 0; + link[x].owner = 1; + link[x].empty = (uint32_t)&link[x + 1]; + buf += TEST_DMA_BLK_LEN; + } + + if (size % TEST_DMA_BLK_LEN) { + link[x].size = size % TEST_DMA_BLK_LEN; + link[x].length = size % TEST_DMA_BLK_LEN; + link[x].buf = buf; + link[x].eof = 1; + link[x].owner = 1; + link[x].empty = 0; + } else { + link[x - 1].eof = 1; + link[x - 1].owner = 1; + link[x - 1].empty = 0; + } + + if (is_tx) { + dma_ll_tx_set_desc_addr(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, (uint32_t)&link[0]); + } else { + dma_ll_rx_set_desc_addr(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, (uint32_t)&link[0]); + } +} + +void test_gdma_init(void) +{ + gdma_ll_enable_bus_clock(TEST_DMA_CHN_NUM, true); + gdma_ll_reset_register(TEST_DMA_CHN_NUM); + dma_ll_force_enable_reg_clock(&TEST_DMA_DEV, true); + +#if SOC_AHB_GDMA_VERSION == 2 + ahb_dma_ll_set_default_memory_range(&TEST_DMA_DEV); +#endif + + dma_ll_tx_reset_channel(&TEST_DMA_DEV, TEST_DMA_CHN_NUM); + dma_ll_rx_reset_channel(&TEST_DMA_DEV, TEST_DMA_CHN_NUM); + + dma_ll_tx_enable_interrupt(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, UINT32_MAX, false); + dma_ll_tx_clear_interrupt_status(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, UINT32_MAX); + + dma_ll_rx_enable_interrupt(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, UINT32_MAX, false); + dma_ll_rx_clear_interrupt_status(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, UINT32_MAX); + + dma_ll_tx_enable_data_burst(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, true); + dma_ll_tx_enable_descriptor_burst(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, true); + + dma_ll_rx_enable_data_burst(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, true); + dma_ll_rx_enable_descriptor_burst(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, true); + + 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, SOC_GDMA_TRIG_PERIPH_SPI2); + dma_ll_rx_connect_to_periph(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, SOC_GDMA_TRIG_PERIPH_SPI2, 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_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); +} + +void test_gdma_deinit(void) +{ + dma_ll_tx_stop(&TEST_DMA_DEV, TEST_DMA_CHN_NUM); + dma_ll_rx_stop(&TEST_DMA_DEV, TEST_DMA_CHN_NUM); + + dma_ll_tx_disconnect_from_periph(&TEST_DMA_DEV, TEST_DMA_CHN_NUM); + dma_ll_rx_disconnect_from_periph(&TEST_DMA_DEV, TEST_DMA_CHN_NUM); + + 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); +} + +void test_gdma_m2m_transfer(uint8_t *src, uint8_t *dest, size_t size) +{ + setup_gdma_link(tx_link, src, size, true); + setup_gdma_link(rx_link, dest, size, false); + + dma_ll_rx_start(&TEST_DMA_DEV, TEST_DMA_CHN_NUM); + dma_ll_tx_start(&TEST_DMA_DEV, TEST_DMA_CHN_NUM); +} + +void test_gdma_wait_done(void) +{ + while (1) { + uint32_t in_st = dma_ll_rx_get_interrupt_status(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, false); + dma_ll_rx_clear_interrupt_status(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, in_st); + if (in_st & GDMA_LL_EVENT_RX_SUC_EOF) { + break; + } + } +} + +/***************************** Miscellaneous *****************************/ + +IRAM_ATTR void test_delay_us(uint32_t us) +{ +#if SOC_CPU_HAS_CSR_PC + esp_rom_delay_us(us); +#else + if (RV_READ_CSR(CSR_PRV_MODE) == PRV_M) { + esp_rom_delay_us(us); + } else { + uint32_t start = RV_READ_CSR(cycle); + uint32_t end = us * esp_rom_get_cpu_ticks_per_us(); + + while ((RV_READ_CSR(cycle) - start) < end) { + /* nothing to do */ + } + } +#endif +} diff --git a/components/hal/test_apps/tee_apm/components/pms/src/test_tee_peri_apm.c b/components/hal/test_apps/tee_apm/components/pms/src/test_tee_peri_apm.c new file mode 100644 index 0000000000..6641bdac60 --- /dev/null +++ b/components/hal/test_apps/tee_apm/components/pms/src/test_tee_peri_apm.c @@ -0,0 +1,310 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "soc/apm_defs.h" +#include "hal/apm_hal.h" +#include "hal/apm_types.h" + +#include "esp_cpu.h" +#include "esp_bit_defs.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 "test_peri_apm_reg.h" + +#include "unity.h" + +#define TEST_VAL 0x0FACADE0 + +/***************************** PERI_APM *****************************/ + +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), + [APM_TEE_HP_PERIPH_I2S] = I2S_DATE_REG(0), + [APM_TEE_HP_PERIPH_PWM] = MCPWM_VERSION_REG(0), + [APM_TEE_HP_PERIPH_TWAI0] = TWAIFD_DATE_VER_REG(0), + [APM_TEE_HP_PERIPH_GDMA] = AHB_DMA_DATE_REG, + [APM_TEE_HP_PERIPH_REGDMA] = PAU_DATE_REG, + [APM_TEE_HP_PERIPH_INTMTX] = INTERRUPT_CORE0_INTERRUPT_DATE_REG, + [APM_TEE_HP_PERIPH_APB_ADC] = APB_SARADC_CTRL_DATE_REG, + [APM_TEE_HP_PERIPH_TG0] = TIMG_NTIMERS_DATE_REG(0), + [APM_TEE_HP_PERIPH_PCNT] = PCNT_DATE_REG, + [APM_TEE_HP_PERIPH_IOMUX] = IO_MUX_DATE_REG, + [APM_TEE_HP_PERIPH_SYSTEM_REG] = HP_SYSTEM_DATE_REG, + [APM_TEE_HP_PERIPH_PCR_REG] = PCR_DATE_REG, + [APM_TEE_HP_PERIPH_MSPI] = SPI_MEM_DATE_REG(0), + [APM_TEE_HP_PERIPH_HP_APM] = HP_APM_DATE_REG, + [APM_TEE_HP_PERIPH_CPU_APM] = CPU_APM_DATE_REG, + [APM_TEE_HP_PERIPH_CRYPTO] = SHA_DATE_REG, + [APM_TEE_HP_PERIPH_CACHE_CFG] = CACHE_DATE_REG, + [APM_TEE_HP_PERIPH_SPI2] = SPI_DATE_REG(0), + [APM_TEE_HP_PERIPH_BIT_SCRAMBLER] = BITSCRAMBLER_VERSION_REG, + [APM_TEE_HP_PERIPH_KEY_MANAGER] = KEYMNG_DATE_REG, + [APM_TEE_HP_PERIPH_SLC_HOST] = SDIO_SLC_HOST_DATE_REG, +}; + +static const uint32_t test_peri_apm_lp_peri_reg[] = { + [APM_TEE_LP_PERIPH_PMU] = PMU_DATE_REG, + [APM_TEE_LP_PERIPH_CLKRST] = LP_CLKRST_DATE_REG, + [APM_TEE_LP_PERIPH_LP_AON_CTRL] = LP_AON_DATE_REG, + [APM_TEE_LP_PERIPH_LP_WDT] = LP_WDT_DATE_REG, + [APM_TEE_LP_PERIPH_LP_PERI] = LPPERI_DATE_REG, + [APM_TEE_LP_PERIPH_LP_ANA_PERI] = LP_ANA_DATE_REG, + [APM_TEE_LP_PERIPH_UART] = LP_UART_ID_REG, + [APM_TEE_LP_PERIPH_I2C_ANA_MST] = LP_I2C_ANA_MST_DATE_REG, + [APM_TEE_LP_PERIPH_I2C_EXT] = LP_I2C_DATE_REG, + [APM_TEE_LP_PERIPH_HUK] = HUK_DATE_REG, + [APM_TEE_LP_PERIPH_LP_APM] = LP_APM_DATE_REG, +}; + +#define TEST_LP_CPU_HP_PERI_RESV_MASK (BIT64(APM_TEE_HP_PERIPH_CACHE_CFG) | \ + BIT64(APM_TEE_HP_PERIPH_HP_APM) | \ + BIT64(APM_TEE_HP_PERIPH_CPU_APM)) + +#define TEST_LP_CPU_LP_PERI_RESV_MASK (BIT64(APM_TEE_LP_PERIPH_PMU) | \ + BIT64(APM_TEE_LP_PERIPH_LP_AON_CTRL) | \ + BIT64(APM_TEE_LP_PERIPH_LP_PERI) | \ + BIT64(APM_TEE_LP_PERIPH_LP_APM)) + +IRAM_ATTR static uint32_t reg_read(uint32_t addr) +{ + uint32_t val; + asm volatile ( + "li t0, 0x100\n" + "lw %0, 0(%1)\n" + "1:\n" + "nop\n" + "addi t0, t0, -1\n" + "bnez t0, 1b\n" + : "=r"(val) + : "r"(addr) + : "t0", "memory" + ); + return val; +} + +IRAM_ATTR static void reg_write(uint32_t addr, uint32_t value) +{ + asm volatile ( + "li t0, 0x100\n" + "sw %1, 0(%0)\n" + "1:\n" + "nop\n" + "addi t0, t0, -1\n" + "bnez t0, 1b\n" + : + : "r"(addr), "r"(value) + : "t0", "memory" + ); +} + +IRAM_ATTR static void hp_cpu_peri_addr_rw(uint32_t peri_addr, uint32_t attr) +{ + RV_WRITE_CSR(uscratch, 0x00); + + reg_write(peri_addr, TEST_VAL); + test_delay_us(10000); + + bool can_write = (attr & APM_PERM_W); + if (!can_write) { + TEST_ASSERT_EQUAL_HEX32(peri_addr, RV_READ_CSR(uscratch)); + } + + RV_WRITE_CSR(uscratch, 0x00); + + volatile uint32_t val = reg_read(peri_addr); + (void)val; + test_delay_us(10000); + + bool can_read = (attr & APM_PERM_R); + if (!can_read) { + TEST_ASSERT_EQUAL_HEX32(peri_addr, RV_READ_CSR(uscratch)); + } + + RV_WRITE_CSR(uscratch, 0x00); +} + +IRAM_ATTR static void lp_cpu_peri_addr_rw(uint32_t peri_addr, uint32_t attr) +{ + test_reset_lp_cpu(); + + SEND_EXCP(0); + SEND_MSG(MSG_SLAVE_WRITE); + SEND_ADDR(peri_addr); + test_delay_us(10000); + + 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); + } + + SEND_EXCP(0); + SEND_MSG(MSG_SLAVE_READ); + SEND_ADDR(peri_addr); + test_delay_us(10000); + + 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); + } + + SEND_EXCP(0); +} + +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 void test_cpu_to_peri_access(const test_peri_apm_periph_cfg_t *cfg) +{ + typedef void (*peri_access_func_t)(uint32_t peri_addr, uint32_t attr); + peri_access_func_t cpu_peri_rw = NULL; + + switch (cfg->master_id) { + case APM_MASTER_HPCORE: + cpu_peri_rw = hp_cpu_peri_addr_rw; + break; +#if CONFIG_ULP_COPROC_ENABLED + case APM_MASTER_LPCORE: + cpu_peri_rw = lp_cpu_peri_addr_rw; + break; +#endif + default: + TEST_ASSERT_MESSAGE(false, "Unsupported master"); + return; + } + + for (uint32_t mode = APM_SEC_MODE_TEE; mode <= APM_SEC_MODE_REE2; mode++) { + apm_hal_set_master_sec_mode(BIT(cfg->master_id), (apm_security_mode_t)mode); + + for (uint32_t peri_idx = 0; peri_idx < cfg->test_reg_num; peri_idx++) { + uint32_t peri_addr = cfg->test_reg[peri_idx]; + if (peri_addr == 0 || (cfg->test_reg_resv_mask & BIT64(peri_idx))) { + continue; + } + + uint32_t pms_attr = APM_PERM_W; + apm_hal_tee_set_peri_access(cfg->ctrl_mod, BIT64(peri_idx), (apm_security_mode_t)mode, APM_PERM_NONE); + apm_hal_tee_set_peri_access(cfg->ctrl_mod, BIT64(peri_idx), (apm_security_mode_t)mode, pms_attr); + + bool is_switch_req = (cfg->master_id == APM_MASTER_HPCORE && mode != APM_SEC_MODE_TEE); + + if (is_switch_req) switch_priv_mode(); + cpu_peri_rw(peri_addr, pms_attr); + if (is_switch_req) switch_priv_mode(); + + pms_attr = APM_PERM_R; + apm_hal_tee_set_peri_access(cfg->ctrl_mod, BIT64(peri_idx), (apm_security_mode_t)mode, APM_PERM_NONE); + apm_hal_tee_set_peri_access(cfg->ctrl_mod, BIT64(peri_idx), (apm_security_mode_t)mode, pms_attr); + + if (is_switch_req) switch_priv_mode(); + cpu_peri_rw(peri_addr, pms_attr); + if (is_switch_req) switch_priv_mode(); + + apm_hal_tee_set_peri_access(cfg->ctrl_mod, BIT64(peri_idx), (apm_security_mode_t)mode, APM_PERM_R | APM_PERM_W); + } + } +} + +void test_peri_apm_master_hp_cpu_slave_hp_peri(void) +{ + test_apm_ctrl_reset_all(); + + test_peri_apm_periph_cfg_t cfg = { + .master_id = APM_MASTER_HPCORE, + .ctrl_mod = APM_TEE_CTRL_HP, + .test_reg = test_peri_apm_hp_peri_reg, + .test_reg_num = sizeof(test_peri_apm_hp_peri_reg) / sizeof(test_peri_apm_hp_peri_reg[0]), + }; + + set_test_vector_table(); + test_cpu_to_peri_access(&cfg); + restore_default_vector_table(); +} + +void test_peri_apm_master_hp_cpu_slave_lp_peri(void) +{ + test_apm_ctrl_reset_all(); + + test_peri_apm_periph_cfg_t cfg = { + .master_id = APM_MASTER_HPCORE, + .ctrl_mod = APM_TEE_CTRL_LP, + .test_reg = test_peri_apm_lp_peri_reg, + .test_reg_num = sizeof(test_peri_apm_lp_peri_reg) / sizeof(test_peri_apm_lp_peri_reg[0]), + }; + + test_boot_lp_cpu(); + + set_test_vector_table(); + test_cpu_to_peri_access(&cfg); + restore_default_vector_table(); + + test_stop_lp_cpu(); +} + +#if CONFIG_ULP_COPROC_ENABLED +void test_peri_apm_master_lp_cpu_slave_hp_peri(void) +{ + test_apm_ctrl_reset_all(); + + test_peri_apm_periph_cfg_t cfg = { + .master_id = APM_MASTER_LPCORE, + .ctrl_mod = APM_TEE_CTRL_HP, + .test_reg = test_peri_apm_hp_peri_reg, + .test_reg_num = sizeof(test_peri_apm_hp_peri_reg) / sizeof(test_peri_apm_hp_peri_reg[0]), + .test_reg_resv_mask = TEST_LP_CPU_HP_PERI_RESV_MASK, + }; + + test_boot_lp_cpu(); + + set_test_vector_table(); + test_cpu_to_peri_access(&cfg); + restore_default_vector_table(); + + test_stop_lp_cpu(); +} + +void test_peri_apm_master_lp_cpu_slave_lp_peri(void) +{ + test_apm_ctrl_reset_all(); + + test_peri_apm_periph_cfg_t cfg = { + .master_id = APM_MASTER_LPCORE, + .ctrl_mod = APM_TEE_CTRL_LP, + .test_reg = test_peri_apm_lp_peri_reg, + .test_reg_num = sizeof(test_peri_apm_lp_peri_reg) / sizeof(test_peri_apm_lp_peri_reg[0]), + .test_reg_resv_mask = TEST_LP_CPU_LP_PERI_RESV_MASK, + }; + + test_boot_lp_cpu(); + + set_test_vector_table(); + test_cpu_to_peri_access(&cfg); + restore_default_vector_table(); + + test_stop_lp_cpu(); +} +#endif diff --git a/components/hal/test_apps/tee_apm/components/pms/src/test_tee_sys_apm.c b/components/hal/test_apps/tee_apm/components/pms/src/test_tee_sys_apm.c new file mode 100644 index 0000000000..7d2321e547 --- /dev/null +++ b/components/hal/test_apps/tee_apm/components/pms/src/test_tee_sys_apm.c @@ -0,0 +1,865 @@ +/* + * SPDX-FileCopyrightText: 2025 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_types.h" + +#include "rom/cache.h" +#include "esp_rom_sys.h" +#include "esp_memory_utils.h" +#include "esp_heap_caps.h" + +#include "test_pms_priv.h" +#include "test_pms_params.h" + +#include "unity.h" + +#define TEST_VAL 0x0FACADE0 + +#if SOC_APM_SUPPORT_CTRL_CFG_LOCK +#define APM_REGION_ENTRY(path, id, start, end, perm) \ + APM_HAL_REGION_ENTRY(path, id, start, end, perm, false) +#else +#define APM_REGION_ENTRY(path, id, start, end, perm) \ + APM_HAL_REGION_ENTRY(path, id, start, end, perm) +#endif + +extern bool apm_master_excp_flag[APM_MASTER_MAX]; + +/***************************** APM setup for memory *****************************/ + +static void test_mem_apm_setup(test_sys_apm_mem_cfg_t *cfg, uint32_t test_start_addr, uint32_t test_end_addr) +{ + apm_hal_set_region_start_addr(cfg->ctrl_mod, 0, cfg->mem_start_addr); + apm_hal_set_region_end_addr(cfg->ctrl_mod, 0, test_start_addr - 1); + + apm_hal_set_region_start_addr(cfg->ctrl_mod, 1, test_end_addr); + apm_hal_set_region_end_addr(cfg->ctrl_mod, 1, cfg->mem_end_addr); + + for (uint32_t regn_idx = 0; regn_idx < cfg->regn_count; regn_idx++) { + if (regn_idx > 1) { + uint32_t regn_start = test_start_addr + (regn_idx - 2) * cfg->regn_sz; + uint32_t regn_end = regn_start + cfg->regn_sz - 1; + apm_hal_set_region_start_addr(cfg->ctrl_mod, regn_idx, regn_start); + apm_hal_set_region_end_addr(cfg->ctrl_mod, regn_idx, regn_end); + } + apm_hal_set_sec_mode_region_attr(cfg->ctrl_mod, regn_idx, APM_SEC_MODE_REE0, APM_PERM_ALL); + apm_hal_set_sec_mode_region_attr(cfg->ctrl_mod, regn_idx, APM_SEC_MODE_REE1, APM_PERM_ALL); + apm_hal_set_sec_mode_region_attr(cfg->ctrl_mod, regn_idx, APM_SEC_MODE_REE2, APM_PERM_ALL); + } + + test_apm_ctrl_enable_intr(cfg->ctrl_mod, cfg->path); + apm_hal_enable_region_filter_all(cfg->ctrl_mod, true); + apm_hal_enable_ctrl_filter(cfg->ctrl_mod, cfg->path, true); +} + +/***************************** GDMA: Utility *****************************/ + +static void gdma_xmem_addr_rw(uint8_t *src, uint8_t *dest, size_t size, uint32_t test_attr) +{ + apm_master_excp_flag[TEST_GDMA_APM_MASTER_ID] = false; + memset(src, TEST_VAL, size); + + 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_us(10000); + TEST_ASSERT(apm_master_excp_flag[TEST_GDMA_APM_MASTER_ID]); + test_gdma_wait_done(); + } else { + test_gdma_wait_done(); + test_delay_us(10000); + TEST_ASSERT_FALSE(apm_master_excp_flag[TEST_GDMA_APM_MASTER_ID]); + TEST_ASSERT_EQUAL_HEX8_ARRAY(src, dest, size); + } + + test_gdma_deinit(); + apm_master_excp_flag[TEST_GDMA_APM_MASTER_ID] = false; +} + +static void test_gdma_to_xmem_access(const test_sys_apm_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_INTERNAL); + TEST_ASSERT_NOT_NULL(test_dma_buf); + memset(test_dma_buf, 0x5A, cfg->regn_sz); + + for (uint32_t mode = APM_SEC_MODE_TEE; mode <= APM_SEC_MODE_REE2; mode++) { + apm_ll_hp_tee_set_master_sec_mode(TEST_GDMA_APM_MASTER_ID, (apm_security_mode_t)mode); + + 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); + 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); + + 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_ALL); + } + } + + free(test_dma_buf); +} + +/***************************** GDMA: HP_MEM *****************************/ + +void test_sys_apm_master_gdma_slave_hpmem(void) +{ + test_apm_ctrl_reset_all(); + + const uint32_t total_sz = (GDMA_HPMEM_TEST_REGN_NUM - 2) * 0x1000; + test_sys_apm_mem_cfg_t cfg = { + .ctrl_mod = GDMA_HPMEM_APM_CTRL, + .path = GDMA_HPMEM_APM_PATH, + .mem_start_addr = SOC_IRAM_LOW, + .mem_end_addr = SOC_DRAM_HIGH - 1, + .regn_count = GDMA_HPMEM_TEST_REGN_NUM, + .regn_sz = total_sz / (GDMA_HPMEM_TEST_REGN_NUM - 2), + }; + + uint8_t *test_hpmem_buf = heap_caps_aligned_alloc(cfg.regn_sz, total_sz, MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(test_hpmem_buf); + memset(test_hpmem_buf, 0xA5, total_sz); + + uint32_t test_start_addr = (uint32_t)test_hpmem_buf; + uint32_t test_end_addr = test_start_addr + total_sz; + test_mem_apm_setup(&cfg, test_start_addr, test_end_addr); + + test_gdma_to_xmem_access(&cfg, test_start_addr); + free(test_hpmem_buf); +} + +/***************************** GDMA: EXT_MEM *****************************/ + +#if CONFIG_SPIRAM +void test_sys_apm_master_gdma_slave_extmem(void) +{ + test_apm_ctrl_reset_all(); + + const uint32_t total_sz = (GDMA_EXTMEM_TEST_REGN_NUM - 2) * 0x1000; + test_sys_apm_mem_cfg_t cfg = { + .ctrl_mod = GDMA_EXTMEM_APM_CTRL, + .path = GDMA_EXTMEM_APM_PATH, + .mem_start_addr = SOC_EXTRAM_DATA_LOW, + .mem_end_addr = SOC_EXTRAM_DATA_HIGH - 1, + .regn_count = GDMA_EXTMEM_TEST_REGN_NUM, + .regn_sz = total_sz / (GDMA_EXTMEM_TEST_REGN_NUM - 2), + }; + + uint8_t *test_extmem_buf = heap_caps_aligned_alloc(cfg.regn_sz, total_sz, MALLOC_CAP_SPIRAM); + TEST_ASSERT_NOT_NULL(test_extmem_buf); + memset(test_extmem_buf, 0xA5, total_sz); + + uint32_t test_start_addr = (uint32_t)test_extmem_buf; + uint32_t test_end_addr = test_start_addr + total_sz; + test_mem_apm_setup(&cfg, test_start_addr, test_end_addr); + + test_gdma_to_xmem_access(&cfg, test_start_addr); + free(test_extmem_buf); +} +#endif + +/***************************** HP_CPU: Peripherals (Utility) *****************************/ + +static void hp_cpu_peri_addr_rw(uint32_t peri_addr, uint32_t attr) +{ + apm_master_excp_flag[APM_MASTER_HPCORE] = false; + + REG_WRITE(peri_addr, TEST_VAL); + test_delay_us(10000); + + bool can_write = (attr & APM_PERM_W); + TEST_ASSERT(apm_master_excp_flag[APM_MASTER_HPCORE] != can_write); + + apm_master_excp_flag[APM_MASTER_HPCORE] = false; + + volatile uint32_t val = REG_READ(peri_addr); + (void)val; + test_delay_us(10000); + + bool can_read = (attr & APM_PERM_R); + TEST_ASSERT(apm_master_excp_flag[APM_MASTER_HPCORE] != can_read); + + apm_master_excp_flag[APM_MASTER_HPCORE] = false; +} + +#if CONFIG_ULP_COPROC_ENABLED +static void lp_cpu_peri_addr_rw(uint32_t peri_addr, uint32_t attr) +{ + apm_master_excp_flag[APM_MASTER_LPCORE] = false; + test_reset_lp_cpu(); + + SEND_MSG(MSG_SLAVE_WRITE); + SEND_ADDR(peri_addr); + test_delay_us(10000); + + bool can_write = (attr & APM_PERM_W); + TEST_ASSERT(apm_master_excp_flag[APM_MASTER_LPCORE] != can_write); + + apm_master_excp_flag[APM_MASTER_LPCORE] = false; + + SEND_MSG(MSG_SLAVE_READ); + SEND_ADDR(peri_addr); + test_delay_us(10000); + + bool can_read = (attr & APM_PERM_R); + TEST_ASSERT(apm_master_excp_flag[APM_MASTER_LPCORE] != can_read); + + apm_master_excp_flag[APM_MASTER_LPCORE] = false; +} +#endif + +static void test_cpu_to_peri_access(const test_sys_apm_periph_cfg_t *cfg) +{ + typedef void (*peri_access_func_t)(uint32_t peri_addr, uint32_t attr); + peri_access_func_t cpu_peri_rw = NULL; + + switch (cfg->master_id) { + case APM_MASTER_HPCORE: + cpu_peri_rw = hp_cpu_peri_addr_rw; + break; +#if CONFIG_ULP_COPROC_ENABLED + case APM_MASTER_LPCORE: + cpu_peri_rw = lp_cpu_peri_addr_rw; + break; +#endif + default: + TEST_ASSERT_MESSAGE(false, "Unsupported master"); + return; + } + + for (uint32_t mode = APM_SEC_MODE_TEE; mode <= APM_SEC_MODE_REE2; mode++) { + apm_hal_set_master_sec_mode(BIT(cfg->master_id), (apm_security_mode_t)mode); + + for (uint32_t regn_idx = 0; regn_idx < cfg->test_addr_num; regn_idx++) { + if (BIT(regn_idx) & cfg->test_addr_resv_mask) { + continue; + } + + uint32_t pms_attr = APM_PERM_NONE; + if (mode == APM_SEC_MODE_TEE) { + pms_attr = APM_PERM_R | APM_PERM_W; + cpu_peri_rw(cfg->test_addr[regn_idx], pms_attr); + 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); + if (cfg->master_id == APM_MASTER_HPCORE) test_m2u_switch(); + cpu_peri_rw(cfg->test_addr[regn_idx], pms_attr); + if (cfg->master_id == APM_MASTER_HPCORE) test_u2m_switch(); + + 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); + if (cfg->master_id == APM_MASTER_HPCORE) test_m2u_switch(); + cpu_peri_rw(cfg->test_addr[regn_idx], pms_attr); + if (cfg->master_id == APM_MASTER_HPCORE) test_u2m_switch(); + + apm_hal_set_sec_mode_region_attr(cfg->ctrl_mod, regn_idx, mode, APM_PERM_R | APM_PERM_W); + } + } +} + +/***************************** HP_CPU: Peripherals (HP_PERI) *****************************/ + +static apm_hal_ctrl_region_cfg_t test_hp_peri_regn_cfg[] = { + APM_REGION_ENTRY(HP_CPU_HPPERI_APM_PATH, 0, TEST_HP_PERI_REGION0_START, TEST_HP_PERI_REGION0_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_HPPERI_APM_PATH, 1, TEST_HP_PERI_REGION1_START, TEST_HP_PERI_REGION1_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_HPPERI_APM_PATH, 2, TEST_HP_PERI_REGION2_START, TEST_HP_PERI_REGION2_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_HPPERI_APM_PATH, 3, TEST_HP_PERI_REGION3_START, TEST_HP_PERI_REGION3_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_HPPERI_APM_PATH, 4, TEST_HP_PERI_REGION4_START, TEST_HP_PERI_REGION4_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_HPPERI_APM_PATH, 5, TEST_HP_PERI_REGION5_START, TEST_HP_PERI_REGION5_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_HPPERI_APM_PATH, 6, TEST_HP_PERI_REGION6_START, TEST_HP_PERI_REGION6_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_HPPERI_APM_PATH, 7, TEST_HP_PERI_REGION7_START, TEST_HP_PERI_REGION7_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_HPPERI_APM_PATH, 8, TEST_HP_PERI_REGION8_START, TEST_HP_PERI_REGION8_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_HPPERI_APM_PATH, 9, TEST_HP_PERI_REGION9_START, TEST_HP_PERI_REGION9_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_HPPERI_APM_PATH, 10, TEST_HP_PERI_REGION10_START, TEST_HP_PERI_REGION10_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_HPPERI_APM_PATH, 11, TEST_HP_PERI_REGION11_START, TEST_HP_PERI_REGION11_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_HPPERI_APM_PATH, 12, TEST_HP_PERI_REGION12_START, TEST_HP_PERI_REGION12_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_HPPERI_APM_PATH, 13, TEST_HP_PERI_REGION13_START, TEST_HP_PERI_REGION13_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_HPPERI_APM_PATH, 14, TEST_HP_PERI_REGION14_START, TEST_HP_PERI_REGION14_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_HPPERI_APM_PATH, 15, TEST_HP_PERI_REGION15_START, TEST_HP_PERI_REGION15_END, APM_PERM_R | APM_PERM_W), +}; + +static uint32_t test_hp_peri_regn_addr[] = { + TEST_HP_PERI_ADDR0, TEST_HP_PERI_ADDR1, TEST_HP_PERI_ADDR2, TEST_HP_PERI_ADDR3, + TEST_HP_PERI_ADDR4, TEST_HP_PERI_ADDR5, TEST_HP_PERI_ADDR6, TEST_HP_PERI_ADDR7, + TEST_HP_PERI_ADDR8, TEST_HP_PERI_ADDR9, TEST_HP_PERI_ADDR10, TEST_HP_PERI_ADDR11, + TEST_HP_PERI_ADDR12, TEST_HP_PERI_ADDR13, TEST_HP_PERI_ADDR14, TEST_HP_PERI_ADDR15 +}; + +void test_sys_apm_master_hp_cpu_slave_hp_peri(void) +{ + test_apm_ctrl_reset_all(); + + apm_ctrl_module_t ctrl_mod = HP_CPU_HPPERI_APM_CTRL; + apm_ctrl_access_path_t path = HP_CPU_HPPERI_APM_PATH; + + uint32_t test_regn_num = sizeof(test_hp_peri_regn_cfg) / sizeof(test_hp_peri_regn_cfg[0]); + for (uint32_t regn_idx = 0; regn_idx < test_regn_num; regn_idx++) { + for (uint32_t mode = APM_SEC_MODE_REE0; mode <= APM_SEC_MODE_REE2; mode++) { + apm_hal_set_region_filter_cfg(ctrl_mod, (apm_security_mode_t)mode, &test_hp_peri_regn_cfg[regn_idx]); + } + } + + test_apm_ctrl_enable_intr(ctrl_mod, path); + apm_hal_enable_region_filter_all(ctrl_mod, true); + apm_hal_enable_ctrl_filter(ctrl_mod, path, true); + + test_sys_apm_periph_cfg_t cfg = { + .master_id = APM_MASTER_HPCORE, + .ctrl_mod = ctrl_mod, + .test_addr = test_hp_peri_regn_addr, + .test_addr_num = test_regn_num, + .test_addr_resv_mask = TEST_HP_PERI_RESV_MASK, + }; + + set_test_vector_table(); + test_cpu_to_peri_access(&cfg); + restore_default_vector_table(); +} + +/***************************** HP_CPU: Peripherals (CPU_PERI) *****************************/ + +static apm_hal_ctrl_region_cfg_t test_cpu_peri_regn_cfg[] = { + APM_REGION_ENTRY(HP_CPU_CPUPERI_APM_PATH, 0, TEST_CPU_PERI_REGION0_START, TEST_CPU_PERI_REGION0_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_CPUPERI_APM_PATH, 1, TEST_CPU_PERI_REGION1_START, TEST_CPU_PERI_REGION1_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_CPUPERI_APM_PATH, 2, TEST_CPU_PERI_REGION2_START, TEST_CPU_PERI_REGION2_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_CPUPERI_APM_PATH, 3, TEST_CPU_PERI_REGION3_START, TEST_CPU_PERI_REGION3_END, APM_PERM_R | APM_PERM_W), +}; + +static uint32_t test_cpu_peri_regn_addr[] = { + TEST_CPU_PERI_ADDR0, TEST_CPU_PERI_ADDR1, TEST_CPU_PERI_ADDR2, TEST_CPU_PERI_ADDR3, +}; + +void test_sys_apm_master_hp_cpu_slave_cpu_peri(void) +{ + test_apm_ctrl_reset_all(); + + apm_ctrl_module_t ctrl_mod = HP_CPU_CPUPERI_APM_CTRL; + apm_ctrl_access_path_t path = HP_CPU_CPUPERI_APM_PATH; + + uint32_t test_regn_num = sizeof(test_cpu_peri_regn_cfg) / sizeof(test_cpu_peri_regn_cfg[0]); + for (uint32_t regn_idx = 0; regn_idx < test_regn_num; regn_idx++) { + for (uint32_t mode = APM_SEC_MODE_REE0; mode <= APM_SEC_MODE_REE2; mode++) { + apm_hal_set_region_filter_cfg(ctrl_mod, (apm_security_mode_t)mode, &test_cpu_peri_regn_cfg[regn_idx]); + } + } + + test_apm_ctrl_enable_intr(ctrl_mod, path); + apm_hal_enable_region_filter_all(ctrl_mod, true); + apm_hal_enable_ctrl_filter(ctrl_mod, path, true); + + test_sys_apm_periph_cfg_t cfg = { + .master_id = APM_MASTER_HPCORE, + .ctrl_mod = ctrl_mod, + .test_addr = test_cpu_peri_regn_addr, + .test_addr_num = test_regn_num, + }; + + set_test_vector_table(); + test_cpu_to_peri_access(&cfg); + restore_default_vector_table(); +} + +/***************************** HP_CPU: Peripherals (LP_PERI) *****************************/ + +static apm_hal_ctrl_region_cfg_t test_lp_peri_regn_cfg[] = { + APM_REGION_ENTRY(HP_CPU_LPPERI_APM_PATH, 0, TEST_LP_PERI_REGION0_START, TEST_LP_PERI_REGION0_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_LPPERI_APM_PATH, 1, TEST_LP_PERI_REGION1_START, TEST_LP_PERI_REGION1_END, APM_PERM_R | APM_PERM_W), +#if APM_CTRL_LP_APM_REGION_NUM > 2 + APM_REGION_ENTRY(HP_CPU_LPPERI_APM_PATH, 2, TEST_LP_PERI_REGION2_START, TEST_LP_PERI_REGION2_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_LPPERI_APM_PATH, 3, TEST_LP_PERI_REGION3_START, TEST_LP_PERI_REGION3_END, APM_PERM_R | APM_PERM_W), +#endif +#if APM_CTRL_LP_APM_REGION_NUM > 4 + APM_REGION_ENTRY(HP_CPU_LPPERI_APM_PATH, 4, TEST_LP_PERI_REGION4_START, TEST_LP_PERI_REGION4_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_LPPERI_APM_PATH, 5, TEST_LP_PERI_REGION5_START, TEST_LP_PERI_REGION5_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_LPPERI_APM_PATH, 6, TEST_LP_PERI_REGION6_START, TEST_LP_PERI_REGION6_END, APM_PERM_R | APM_PERM_W), + APM_REGION_ENTRY(HP_CPU_LPPERI_APM_PATH, 7, TEST_LP_PERI_REGION7_START, TEST_LP_PERI_REGION7_END, APM_PERM_R | APM_PERM_W), +#endif +}; + +static uint32_t test_lp_peri_regn_addr[] = { + TEST_LP_PERI_ADDR0, TEST_LP_PERI_ADDR1, +#if APM_CTRL_LP_APM_REGION_NUM > 2 + TEST_LP_PERI_ADDR2, TEST_LP_PERI_ADDR3, +#endif +#if APM_CTRL_LP_APM_REGION_NUM > 4 + TEST_LP_PERI_ADDR4, TEST_LP_PERI_ADDR5, TEST_LP_PERI_ADDR6, TEST_LP_PERI_ADDR7, +#endif +}; + +void test_sys_apm_master_hp_cpu_slave_lp_peri(void) +{ + test_apm_ctrl_reset_all(); + apm_ctrl_module_t ctrl_mod = HP_CPU_LPPERI_APM_CTRL; + apm_ctrl_access_path_t path = HP_CPU_LPPERI_APM_PATH; + + uint32_t test_regn_num = sizeof(test_lp_peri_regn_cfg) / sizeof(test_lp_peri_regn_cfg[0]); + for (uint32_t regn_idx = 0; regn_idx < test_regn_num; regn_idx++) { + for (uint32_t mode = APM_SEC_MODE_REE0; mode <= APM_SEC_MODE_REE2; mode++) { + apm_hal_set_region_filter_cfg(ctrl_mod, (apm_security_mode_t)mode, &test_lp_peri_regn_cfg[regn_idx]); + } + } + + test_apm_ctrl_enable_intr(ctrl_mod, path); + apm_hal_enable_region_filter_all(ctrl_mod, true); + apm_hal_enable_ctrl_filter(ctrl_mod, path, true); + + test_sys_apm_periph_cfg_t cfg = { + .master_id = APM_MASTER_HPCORE, + .ctrl_mod = ctrl_mod, + .test_addr = test_lp_peri_regn_addr, + .test_addr_num = test_regn_num, + .test_addr_resv_mask = TEST_LP_PERI_RESV_MASK, + }; + + set_test_vector_table(); + test_cpu_to_peri_access(&cfg); + restore_default_vector_table(); +} + +/***************************** HP_CPU: LP_MEM *****************************/ + +static void write_dummy_code_to_mem(uint32_t start_addr, size_t size) +{ + const uint16_t nop_ins = 0x0001; + const uint16_t retw_ins = 0x8082; + uint16_t *addr = (uint16_t *)start_addr; + + size_t num_nops = (size / sizeof(uint16_t)) - 1; + for (size_t i = 0; i < num_nops; i++) { + addr[i] = nop_ins; + } + + if (size >= sizeof(uint16_t)) { + addr[num_nops] = retw_ins; + } + __asm__ volatile("fence"); +} + +static void hp_cpu_xmem_addr_rw(uint32_t mem_addr, size_t size, uint32_t attr) +{ + apm_master_excp_flag[APM_MASTER_HPCORE] = false; +#if SOC_RTC_MEM_SUPPORTED + ADJUST_LP_MEM_ADDR(mem_addr); +#endif + + volatile uint32_t *addr = (volatile uint32_t *)mem_addr; + uint32_t num_words = size / sizeof(uint32_t); + uint32_t step = (num_words / 16) ? (num_words / 16) : 1; + + for (uint32_t offs = 0; offs < num_words; offs += step) { + addr[offs] = TEST_VAL; + asm volatile ("nop"); + test_delay_us(10000); + + bool can_write = (attr & APM_PERM_W); + TEST_ASSERT(apm_master_excp_flag[APM_MASTER_HPCORE] != can_write); + + apm_master_excp_flag[APM_MASTER_HPCORE] = false; + + uint32_t val = addr[offs]; + (void)val; + asm volatile ("fence"); + test_delay_us(10000); + + bool can_read = (attr & APM_PERM_R); + TEST_ASSERT(apm_master_excp_flag[APM_MASTER_HPCORE] != can_read); + + apm_master_excp_flag[APM_MASTER_HPCORE] = false; + } +} + +static void hp_cpu_xmem_addr_x(uint32_t mem_addr, size_t size, uint32_t attr) +{ + apm_master_excp_flag[APM_MASTER_HPCORE] = false; +#if SOC_RTC_MEM_SUPPORTED + ADJUST_LP_MEM_ADDR(mem_addr); +#endif + write_dummy_code_to_mem(mem_addr, size); + + void (*func_ptr)(void); + func_ptr = (void(*)(void))(mem_addr); + func_ptr(); + test_delay_us(10000); + + bool can_execute = attr & APM_PERM_X; + TEST_ASSERT(apm_master_excp_flag[APM_MASTER_HPCORE] != can_execute); + + apm_master_excp_flag[APM_MASTER_HPCORE] = false; +} + +#if CONFIG_ULP_COPROC_ENABLED +static void lp_cpu_xmem_addr_rw(uint32_t mem_addr, size_t size, uint32_t attr) +{ + apm_master_excp_flag[APM_MASTER_LPCORE] = false; + ADJUST_LP_MEM_ADDR(mem_addr); + test_reset_lp_cpu(); + + SEND_MSG(MSG_SLAVE_WRITE); + SEND_ADDR(mem_addr); + SEND_SIZE(sizeof(uint32_t)); + test_delay_us(10000); + + bool can_write = (attr & APM_PERM_W); + TEST_ASSERT(apm_master_excp_flag[APM_MASTER_LPCORE] != can_write); + + apm_master_excp_flag[APM_MASTER_LPCORE] = false; + + SEND_MSG(MSG_SLAVE_READ); + SEND_ADDR(mem_addr); + test_delay_us(10000); + + bool can_read = (attr & APM_PERM_R); + TEST_ASSERT(apm_master_excp_flag[APM_MASTER_LPCORE] != can_read); + + apm_master_excp_flag[APM_MASTER_LPCORE] = false; +} + +static void lp_cpu_xmem_addr_x(uint32_t mem_addr, size_t size, uint32_t attr) +{ + apm_master_excp_flag[APM_MASTER_LPCORE] = false; + ADJUST_LP_MEM_ADDR(mem_addr); + write_dummy_code_to_mem(mem_addr, size); + test_reset_lp_cpu(); + + SEND_MSG(MSG_SLAVE_EXEC); + SEND_ADDR(mem_addr); + test_delay_us(10000); + + bool can_execute = (attr & APM_PERM_X); + TEST_ASSERT(apm_master_excp_flag[APM_MASTER_LPCORE] != can_execute); + + apm_master_excp_flag[APM_MASTER_LPCORE] = false; +} + +static void test_lp_cpu_to_hpmem_force_access(const test_sys_apm_mem_cfg_t *cfg, uint32_t test_start_addr) +{ + apm_ll_lp_tee_enable_force_hp_mem_access(true); + + for (uint32_t mode = APM_SEC_MODE_REE0; mode <= APM_SEC_MODE_REE2; mode++) { + apm_hal_set_master_sec_mode(BIT(cfg->master_id), (apm_security_mode_t)mode); + + for (uint32_t regn_idx = 2; regn_idx < cfg->regn_count; regn_idx++) { + uint32_t regn_start = test_start_addr + (regn_idx - 2) * cfg->regn_sz; + + apm_hal_set_sec_mode_region_attr(cfg->ctrl_mod, regn_idx, mode, APM_PERM_NONE); + lp_cpu_xmem_addr_rw(regn_start, cfg->regn_sz, APM_PERM_R | APM_PERM_W); + lp_cpu_xmem_addr_x(regn_start, cfg->regn_sz, APM_PERM_X); + } + } + + apm_ll_lp_tee_enable_force_hp_mem_access(false); +} +#endif + +static void test_cpu_to_xmem_access(test_sys_apm_mem_cfg_t *cfg, uint32_t test_start_addr) +{ + typedef void (*mem_access_func_t)(uint32_t mem_addr, size_t size, uint32_t attr); + mem_access_func_t cpu_mem_rw = NULL, cpu_mem_x = NULL; + + switch (cfg->master_id) { + case APM_MASTER_HPCORE: + cpu_mem_rw = hp_cpu_xmem_addr_rw; + cpu_mem_x = hp_cpu_xmem_addr_x; + break; +#if CONFIG_ULP_COPROC_ENABLED + case APM_MASTER_LPCORE: + cpu_mem_rw = lp_cpu_xmem_addr_rw; + cpu_mem_x = lp_cpu_xmem_addr_x; + break; +#endif + default: + TEST_ASSERT_MESSAGE(false, "Unsupported master"); + return; + } + + for (uint32_t mode = APM_SEC_MODE_TEE; mode <= APM_SEC_MODE_REE2; mode++) { + apm_hal_set_master_sec_mode(BIT(cfg->master_id), (apm_security_mode_t)mode); + + for (uint32_t regn_idx = 2; regn_idx < cfg->regn_count; regn_idx++) { + uint32_t regn_start = 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_ALL; + cpu_mem_rw(regn_start, cfg->regn_sz, pms_attr); + cpu_mem_x(regn_start, cfg->regn_sz, pms_attr); + 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); + if (cfg->master_id == APM_MASTER_HPCORE) test_m2u_switch(); + cpu_mem_rw(regn_start, cfg->regn_sz, pms_attr); + cpu_mem_x(regn_start, cfg->regn_sz, pms_attr); + if (cfg->master_id == APM_MASTER_HPCORE) test_u2m_switch(); + + 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); + if (cfg->master_id == APM_MASTER_HPCORE) test_m2u_switch(); + cpu_mem_rw(regn_start, cfg->regn_sz, pms_attr); + if (cfg->master_id == APM_MASTER_HPCORE) test_u2m_switch(); + + apm_hal_set_sec_mode_region_attr(cfg->ctrl_mod, regn_idx, mode, APM_PERM_ALL); + } + } +} + +#if SOC_RTC_MEM_SUPPORTED +void test_sys_apm_master_hp_cpu_slave_lpmem(void) +{ + test_apm_ctrl_reset_all(); + + const uint32_t total_sz = (HP_CPU_LPMEM_TEST_REGN_NUM - 2) * 0x100; + test_sys_apm_mem_cfg_t cfg = { + .master_id = APM_MASTER_HPCORE, + .ctrl_mod = HP_CPU_LPMEM_APM_CTRL, + .path = HP_CPU_LPMEM_APM_PATH, + .mem_start_addr = SOC_RTC_IRAM_LOW, + .mem_end_addr = SOC_RTC_DRAM_HIGH - 1, + .regn_count = HP_CPU_LPMEM_TEST_REGN_NUM, + .regn_sz = total_sz / (HP_CPU_LPMEM_TEST_REGN_NUM - 2), + }; + + uint32_t test_start_addr = cfg.mem_start_addr + (cfg.mem_end_addr - cfg.mem_start_addr) / 4 + 1; + uint32_t test_end_addr = test_start_addr + total_sz; + test_mem_apm_setup(&cfg, test_start_addr, test_end_addr); + + set_test_vector_table(); + test_cpu_to_xmem_access(&cfg, test_start_addr); + restore_default_vector_table(); +} +#endif + +#if SOC_APM_CPU_APM_SUPPORTED +void test_sys_apm_master_hp_cpu_slave_hpmem(void) +{ + test_apm_ctrl_reset_all(); + + const uint32_t total_sz = (HP_CPU_HPMEM_TEST_REGN_NUM - 2) * 0x1000; + test_sys_apm_mem_cfg_t cfg = { + .master_id = APM_MASTER_HPCORE, + .ctrl_mod = HP_CPU_HPMEM_APM_CTRL, + .path = HP_CPU_HPMEM_I_APM_PATH, + .mem_start_addr = SOC_IRAM_LOW, + .mem_end_addr = SOC_DRAM_HIGH - 1, + .regn_count = HP_CPU_HPMEM_TEST_REGN_NUM, + .regn_sz = total_sz / (HP_CPU_HPMEM_TEST_REGN_NUM - 2), + }; + + uint8_t *test_hpmem_buf = heap_caps_aligned_alloc(cfg.regn_sz, total_sz, MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(test_hpmem_buf); + memset(test_hpmem_buf, 0xA5, total_sz); + + uint32_t test_start_addr = (uint32_t)test_hpmem_buf; + uint32_t test_end_addr = test_start_addr + total_sz; + test_mem_apm_setup(&cfg, test_start_addr, test_end_addr); + + test_apm_ctrl_enable_intr(cfg.ctrl_mod, HP_CPU_HPMEM_D_APM_PATH); + apm_hal_enable_ctrl_filter(cfg.ctrl_mod, HP_CPU_HPMEM_D_APM_PATH, true); + + set_test_vector_table(); + test_cpu_to_xmem_access(&cfg, test_start_addr); + restore_default_vector_table(); + + free(test_hpmem_buf); +} +#endif + +/***************************** LP_CPU: Peripherals (LP_PERI) *****************************/ + +#if CONFIG_ULP_COPROC_ENABLED +void test_sys_apm_master_lp_cpu_slave_lp_peri(void) +{ + test_apm_ctrl_reset_all(); + + apm_ctrl_module_t ctrl_mod = LP_CPU_LPPERI_APM_CTRL; + apm_ctrl_access_path_t path = LP_CPU_LPPERI_APM_PATH; + + uint32_t test_regn_num = sizeof(test_lp_peri_regn_cfg) / sizeof(test_lp_peri_regn_cfg[0]); + for (uint32_t regn_idx = 0; regn_idx < test_regn_num; regn_idx++) { + for (uint32_t mode = APM_SEC_MODE_REE0; mode <= APM_SEC_MODE_REE2; mode++) { + apm_hal_set_region_filter_cfg(ctrl_mod, (apm_security_mode_t)mode, &test_lp_peri_regn_cfg[regn_idx]); + } + } + + test_apm_ctrl_enable_intr(ctrl_mod, path); + apm_hal_enable_region_filter_all(ctrl_mod, true); + apm_hal_enable_ctrl_filter(ctrl_mod, path, true); + + test_sys_apm_periph_cfg_t cfg = { + .master_id = APM_MASTER_LPCORE, + .ctrl_mod = ctrl_mod, + .test_addr = test_lp_peri_regn_addr, + .test_addr_num = test_regn_num, + .test_addr_resv_mask = TEST_LP_PERI_RESV_MASK, + }; + + test_boot_lp_cpu(); + + set_test_vector_table(); + test_cpu_to_peri_access(&cfg); + restore_default_vector_table(); + + test_stop_lp_cpu(); +} + +void test_sys_apm_master_lp_cpu_slave_lpmem(void) +{ + test_apm_ctrl_reset_all(); + + const uint32_t total_sz = (HP_CPU_LPMEM_TEST_REGN_NUM - 2) * 0x100; + test_sys_apm_mem_cfg_t cfg = { + .master_id = APM_MASTER_LPCORE, + .ctrl_mod = LP_CPU_LPMEM_APM_CTRL, + .path = LP_CPU_LPMEM_APM_PATH, + .mem_start_addr = SOC_RTC_IRAM_LOW + 0x20000000, + .mem_end_addr = SOC_RTC_DRAM_HIGH + 0x20000000 - 1, + .regn_count = LP_CPU_LPMEM_TEST_REGN_NUM, + .regn_sz = total_sz / (LP_CPU_LPMEM_TEST_REGN_NUM - 2), + }; + + uint32_t test_start_addr = cfg.mem_start_addr + (cfg.mem_end_addr - cfg.mem_start_addr) / 4 + 1; + uint32_t test_end_addr = test_start_addr + total_sz; + test_mem_apm_setup(&cfg, test_start_addr, test_end_addr); + + test_switch_lp_mem_speed(false); + test_boot_lp_cpu(); + + set_test_vector_table(); + test_cpu_to_xmem_access(&cfg, test_start_addr); + restore_default_vector_table(); + + test_stop_lp_cpu(); + test_switch_lp_mem_speed(true); +} + +void test_sys_apm_master_lp_cpu_slave_hpmem(void) +{ + test_apm_ctrl_reset_all(); + + const uint32_t total_sz = (LP_CPU_HPMEM_TEST_REGN_NUM - 2) * 0x1000; + test_sys_apm_mem_cfg_t cfg = { + .master_id = APM_MASTER_LPCORE, + .ctrl_mod = LP_CPU_HPMEM_APM_CTRL, + .path = LP_CPU_HPMEM_APM_PATH, + .mem_start_addr = SOC_IRAM_LOW, + .mem_end_addr = SOC_DRAM_HIGH - 1, + .regn_count = LP_CPU_HPMEM_TEST_REGN_NUM, + .regn_sz = total_sz / (LP_CPU_HPMEM_TEST_REGN_NUM - 2), + }; + + uint8_t *test_hpmem_buf = heap_caps_aligned_alloc(cfg.regn_sz, total_sz, MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(test_hpmem_buf); + memset(test_hpmem_buf, 0xA5, total_sz); + + uint32_t test_start_addr = (uint32_t)test_hpmem_buf; + uint32_t test_end_addr = test_start_addr + total_sz; + test_mem_apm_setup(&cfg, test_start_addr, test_end_addr); + + set_test_vector_table(); + + test_boot_lp_cpu(); + test_lp_cpu_to_hpmem_force_access(&cfg, test_start_addr); + test_cpu_to_xmem_access(&cfg, test_start_addr); + test_stop_lp_cpu(); + + restore_default_vector_table(); + free(test_hpmem_buf); +} +#endif + +/***************************** TEE mode default access *****************************/ + +static void setup_apm_regn_cfg(apm_ctrl_module_t ctrl_mod, uint32_t regn_num, uint32_t start_addr, uint32_t end_addr) +{ + apm_hal_set_region_start_addr(ctrl_mod, regn_num, start_addr); + apm_hal_set_region_end_addr(ctrl_mod, regn_num, end_addr); + apm_hal_enable_region_filter(ctrl_mod, regn_num, true); +} + +static void test_tee_mode_apm_setup(test_sys_apm_mem_cfg_t *cfg, uint32_t test_start_addr, uint32_t test_end_addr) +{ + setup_apm_regn_cfg(cfg->ctrl_mod, 0, cfg->mem_start_addr, test_start_addr - 1); + setup_apm_regn_cfg(cfg->ctrl_mod, 1, test_end_addr, cfg->mem_end_addr); + + test_apm_ctrl_enable_intr(cfg->ctrl_mod, cfg->path); + apm_hal_enable_ctrl_filter(cfg->ctrl_mod, cfg->path, true); +} + +void test_tee_mode_default_access(void) +{ + test_apm_ctrl_reset_all(); + + const uint32_t total_sz = 0x1000; + test_sys_apm_mem_cfg_t cfg = { + .ctrl_mod = GDMA_HPMEM_APM_CTRL, + .path = GDMA_HPMEM_APM_PATH, + .mem_start_addr = SOC_IRAM_LOW, + .mem_end_addr = SOC_DRAM_HIGH - 1, + }; + + uint8_t *test_hpmem_buf = heap_caps_aligned_alloc(total_sz, total_sz, MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(test_hpmem_buf); + memset(test_hpmem_buf, 0xA5, total_sz); + + uint8_t *test_dma_buf = heap_caps_aligned_alloc(total_sz, total_sz, MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(test_dma_buf); + memset(test_dma_buf, 0xA5, total_sz); + + 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; +#if SOC_APM_CTRL_TEE_MODE_ACCESS_BUG + pms_attr = APM_PERM_NONE; +#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); + + free(test_dma_buf); + free(test_hpmem_buf); +} diff --git a/components/hal/test_apps/tee_apm/components/pms/src/test_tee_vectors.S b/components/hal/test_apps/tee_apm/components/pms/src/test_tee_vectors.S new file mode 100644 index 0000000000..a14c7ec914 --- /dev/null +++ b/components/hal/test_apps/tee_apm/components/pms/src/test_tee_vectors.S @@ -0,0 +1,326 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/soc.h" +#include "soc/soc_caps.h" +#include "soc/interrupt_reg.h" + +#include "riscv/encoding.h" +#include "riscv/rvruntime-frames.h" +#include "esp_private/panic_reason.h" +#include "esp_private/vectors_const.h" + +#include "sdkconfig.h" + + .equ SAVE_REGS, 32 + .equ CONTEXT_SIZE, (SAVE_REGS * 4) + .equ panic_from_excp, test_panicHandler + .equ ECALL_U_MODE, 0x8 + .equ ECALL_M_MODE, 0xb + +/* Macro which first allocates space on the stack to save general + * purpose registers, and then save them. GP register is excluded. + * The default size allocated on the stack is CONTEXT_SIZE, but it + * can be overridden. */ +.macro save_general_regs cxt_size=CONTEXT_SIZE + addi sp, sp, -\cxt_size + sw ra, RV_STK_RA(sp) + sw tp, RV_STK_TP(sp) + sw t0, RV_STK_T0(sp) + sw t1, RV_STK_T1(sp) + sw t2, RV_STK_T2(sp) + sw s0, RV_STK_S0(sp) + sw s1, RV_STK_S1(sp) + sw a0, RV_STK_A0(sp) + sw a1, RV_STK_A1(sp) + sw a2, RV_STK_A2(sp) + sw a3, RV_STK_A3(sp) + sw a4, RV_STK_A4(sp) + sw a5, RV_STK_A5(sp) + sw a6, RV_STK_A6(sp) + sw a7, RV_STK_A7(sp) + sw s2, RV_STK_S2(sp) + sw s3, RV_STK_S3(sp) + sw s4, RV_STK_S4(sp) + sw s5, RV_STK_S5(sp) + sw s6, RV_STK_S6(sp) + sw s7, RV_STK_S7(sp) + sw s8, RV_STK_S8(sp) + sw s9, RV_STK_S9(sp) + sw s10, RV_STK_S10(sp) + sw s11, RV_STK_S11(sp) + sw t3, RV_STK_T3(sp) + sw t4, RV_STK_T4(sp) + sw t5, RV_STK_T5(sp) + sw t6, RV_STK_T6(sp) +.endm + +.macro save_mepc + csrr t0, mepc + sw t0, RV_STK_MEPC(sp) +.endm + +.macro save_mcsr + csrr t0, mstatus + sw t0, RV_STK_MSTATUS(sp) + csrr t0, mtvec + sw t0, RV_STK_MTVEC(sp) + csrr t0, mcause + sw t0, RV_STK_MCAUSE(sp) + csrr t0, mtval + sw t0, RV_STK_MTVAL(sp) + csrr t0, mhartid + sw t0, RV_STK_MHARTID(sp) +.endm + +/* Restore the general purpose registers (excluding gp) from the context on + * the stack. The context is then deallocated. The default size is CONTEXT_SIZE + * but it can be overridden. */ +.macro restore_general_regs cxt_size=CONTEXT_SIZE + lw ra, RV_STK_RA(sp) + lw tp, RV_STK_TP(sp) + lw t0, RV_STK_T0(sp) + lw t1, RV_STK_T1(sp) + lw t2, RV_STK_T2(sp) + lw s0, RV_STK_S0(sp) + lw s1, RV_STK_S1(sp) + lw a0, RV_STK_A0(sp) + lw a1, RV_STK_A1(sp) + lw a2, RV_STK_A2(sp) + lw a3, RV_STK_A3(sp) + lw a4, RV_STK_A4(sp) + lw a5, RV_STK_A5(sp) + lw a6, RV_STK_A6(sp) + lw a7, RV_STK_A7(sp) + lw s2, RV_STK_S2(sp) + lw s3, RV_STK_S3(sp) + lw s4, RV_STK_S4(sp) + lw s5, RV_STK_S5(sp) + lw s6, RV_STK_S6(sp) + lw s7, RV_STK_S7(sp) + lw s8, RV_STK_S8(sp) + lw s9, RV_STK_S9(sp) + lw s10, RV_STK_S10(sp) + lw s11, RV_STK_S11(sp) + lw t3, RV_STK_T3(sp) + lw t4, RV_STK_T4(sp) + lw t5, RV_STK_T5(sp) + lw t6, RV_STK_T6(sp) + addi sp,sp, \cxt_size +.endm + +.macro restore_mepc + lw t0, RV_STK_MEPC(sp) + csrw mepc, t0 +.endm + +.macro restore_mcsr + lw t0, RV_STK_MSTATUS(sp) + csrw mstatus, t0 + lw t0, RV_STK_MTVEC(sp) + csrw mtvec, t0 + lw t0, RV_STK_MCAUSE(sp) + csrw mcause, t0 + lw t0, RV_STK_MTVAL(sp) + csrw mtval, t0 + lw t0, RV_STK_MHARTID(sp) + csrw mhartid, t0 +.endm + + .section .iram1, "ax" + /* This is the vector table. MTVEC points here. + * + * Use 4-byte instructions here. 1 instruction = 1 entry of the table. + * The CPU jumps to MTVEC (i.e. the first entry) in case of an exception, + * and (MTVEC & 0xfffffffc) + (mcause & 0x7fffffff) * 4, in case of an interrupt. + * + * Note: for the PULP, we need to place this on a 256-byte boundary, as PULP + * only uses the 24 MSBs of the MTVEC, i.e. (MTVEC & 0xffffff00). + */ + .balign 0x100 + .option push + .option norvc + .global _test_vector_table + .type _test_vector_table, @function +_test_vector_table: + j _test_panic_handler /* exception handler, entry 0 */ +#if !SOC_INT_CLIC_SUPPORTED + .rept 31 + j _test_interrupt_handler /* 31 identical entries, all pointing to the interrupt handler */ + .endr +#endif + .size _test_vector_table, .-_test_vector_table + + .option pop + + /* Exception handler. */ + .global _test_panic_handler + .type _test_panic_handler, @function +_test_panic_handler: + /* Backup t0, t1 on the stack before using it */ + addi sp, sp, -16 + sw t0, 0(sp) + sw t1, 4(sp) + + /* Read mcause */ + csrr t0, mcause + li t1, VECTORS_MCAUSE_REASON_MASK + and t0, t0, t1 + + /* Check whether the exception is an M-mode ecall */ + li t1, ECALL_M_MODE + beq t0, t1, _test_machine_ecall + + /* Check whether the exception is an U-mode ecall */ + li t1, ECALL_U_MODE + beq t0, t1, _test_user_ecall + + /* Restore t0, t1 from the stack */ + lw t1, 4(sp) + lw t0, 0(sp) + addi sp, sp, 16 + + /* Not an exception raised by the ecall instruction */ + save_general_regs RV_STK_FRMSZ + sw gp, RV_STK_GP(sp) + addi t0, sp, RV_STK_FRMSZ + sw t0, RV_STK_SP(sp) + save_mepc + save_mcsr + + /* Executing the panic handler */ + mv a0, sp + csrr a1, mcause + li t0, VECTORS_MCAUSE_REASON_MASK + and a1, a1, t0 + jal panic_from_excp + + /* We arrive here if the exception handler has returned. */ + restore_mepc + restore_general_regs RV_STK_FRMSZ + mret + + .size _test_panic_handler, .-_test_panic_handler + + /* ECALL handler. */ + .type _test_ecall_handler, @function +_test_ecall_handler: + /* M-mode ecall handler */ + /* Currently in M-mode and switch to U-mode */ +_test_machine_ecall: + csrr t0, mepc + addi t0, t0, 4 + csrw mepc, t0 + li t1, MSTATUS_MPP + csrc mstatus, t1 +#if !SOC_CPU_HAS_CSR_PC + csrsi mcounteren, 0x7 +#endif + + /* Restore t0, t1 from the stack */ + lw t1, 4(sp) + lw t0, 0(sp) + addi sp, sp, 16 + mret + + /* U-mode ecall handler */ + /* Currently in U-mode and switch to M-mode */ +_test_user_ecall: + csrr t0, mepc + addi t0, t0, 4 + csrw mepc, t0 + li t1, MSTATUS_MPP + csrs mstatus, t1 + + /* Restore t0, t1 from the stack */ + lw t1, 4(sp) + lw t0, 0(sp) + addi sp, sp, 16 + mret + + .size _test_ecall_handler, .-_test_ecall_handler + + .global rtos_int_enter + .global rtos_int_exit + .global _test_global_interrupt_handler + /* Interrupt handler */ + .type _test_interrupt_handler, @function +_test_interrupt_handler: + /* Start by saving the general purpose registers and the PC value before + * the interrupt happened. */ + save_general_regs + save_mepc + + /* Save GP and SP here. */ + sw gp, RV_STK_GP(sp) + addi a0, sp, CONTEXT_SIZE + sw a0, RV_STK_SP(sp) + + /* Notify the RTOS that an interrupt occurred, it will save the current stack pointer + * in the running TCB, no need to pass it as a parameter + * Returns an abstract context in a0, needs to be passed to `rtos_int_exit` */ + call rtos_int_enter + mv s4, a0 + /* If this is a non-nested interrupt, SP now points to the interrupt stack */ + + /* Before dispatch c handler, restore interrupt to enable nested intr */ + csrr s1, mcause + csrr s2, mstatus + +#if !SOC_INT_HW_NESTED_SUPPORTED + /* Save the interrupt threshold level */ + li t0, INTERRUPT_CURRENT_CORE_INT_THRESH_REG + lw s3, 0(t0) + + /* Increase interrupt threshold level */ + li t2, VECTORS_MCAUSE_REASON_MASK + and t1, s1, t2 /* t1 = mcause & mask */ + slli t1, t1, 2 /* t1 = mcause * 4 */ + li t2, INTERRUPT_PRIO_REG(0) + add t1, t2, t1 /* t1 = INTERRUPT_PRIO_REG + 4 * mcause */ + lw t2, 0(t1) /* t2 = INTERRUPT_PRIO_REG[mcause] */ + addi t2, t2, 1 /* t2 = t2 +1 */ + sw t2, 0(t0) /* INTERRUPT_CURRENT_CORE_INT_THRESH_REG = t2 */ + fence +#endif + + csrsi mstatus, MSTATUS_MIE + /* MIE set. Nested interrupts can now occur */ + + /* call the C dispatcher */ + mv a0, sp /* argument 1, stack pointer */ + mv a1, s1 /* argument 2, interrupt number (mcause) */ + /* mask off the interrupt flag of mcause */ + li t0, VECTORS_MCAUSE_REASON_MASK + and a1, a1, t0 + jal _test_global_interrupt_handler + + /* After dispatch c handler, disable interrupt to make freertos make context switch */ + + csrci mstatus, MSTATUS_MIE + /* MIE cleared. Nested interrupts are disabled */ + +#if !SOC_INT_HW_NESTED_SUPPORTED + /* restore the interrupt threshold level */ + li t0, INTERRUPT_CURRENT_CORE_INT_THRESH_REG + sw s3, 0(t0) + fence +#endif + + /* The RTOS will restore the current TCB stack pointer. This routine will preserve s1 and s2. + * Returns the new `mstatus` value. */ + mv a0, s2 /* a0 = mstatus */ + mv a1, s4 /* a1 = abstract context returned by `rtos_int_enter` */ + call rtos_int_exit + + /* Restore the rest of the registers. */ + csrw mcause, s1 + csrw mstatus, a0 + restore_mepc + restore_general_regs + /* exit, this will also re-enable the interrupts */ + mret + .size _test_interrupt_handler, .-_test_interrupt_handler diff --git a/components/hal/test_apps/tee_apm/components/pms/src/ulp/ulp_lp_core_main.c b/components/hal/test_apps/tee_apm/components/pms/src/ulp/ulp_lp_core_main.c new file mode 100644 index 0000000000..e91aea1d0f --- /dev/null +++ b/components/hal/test_apps/tee_apm/components/pms/src/ulp/ulp_lp_core_main.c @@ -0,0 +1,109 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "soc/soc.h" +#include "riscv/csr.h" +#include "riscv/rv_utils.h" + +#include "ulp_lp_core_utils.h" +#include "test_pms_priv.h" + +extern int _vector_table; +extern int _test_vector_table; + +void set_test_vector_table(void) +{ + rv_utils_intr_global_disable(); + rv_utils_set_mtvec((uintptr_t)&_test_vector_table); + rv_utils_intr_global_enable(); +} + +void restore_default_vector_table(void) +{ + rv_utils_intr_global_disable(); + rv_utils_set_mtvec((uintptr_t)&_vector_table); + rv_utils_intr_global_enable(); +} + +void test_panicHandler(void *frame, int exccause) +{ + switch (exccause) { + case MCAUSE_INST_ACCESS_FAULT: + SEND_EXCP(1); + break; + case MCAUSE_LOAD_ACCESS_FAULT: + SEND_EXCP(5); + break; + case MCAUSE_STORE_ACCESS_FAULT: + SEND_EXCP(7); + break; + default: + SEND_EXCP(0xFFU); + break; + } + + SEND_ADDR(RV_READ_CSR(mtval)); + ulp_lp_core_delay_us(3000U); + return; +} + +/** + * @brief Test LP CPU access to memory/peripherals + * + * The HP CPU communicates with LP CPU through LP_AON_STORE registers + * and sends the following parameters: + * - Access command: read, write, execute, or clear (MSG_SLAVE_*) + * - Target address for the operation + * - Data or size value (for write operation) + * + * The LP CPU continuously polls for commands and processes them: + * - MSG_SLAVE_READ: Reads a 32-bit value from the given address + * - MSG_SLAVE_WRITE: Writes the given 32-bit value to the given address + * - MSG_SLAVE_EXEC: Jumps to and executes code at the given address + * - MSG_SLAVE_CLEAR: No operation; polling continues + * + * If an access fault occurs (instruction, load, or store fault), the panic handler + * captures the cause and faulting address using the exception frame and mtval CSR. + * The handler then sends this information back to the HP CPU for verifying the fault. + */ +int main(void) +{ + set_test_vector_table(); + + while (1) { + uint32_t test_msg = RECV_MSG(); + if (test_msg == MSG_SLAVE_CLEAR) { + ulp_lp_core_delay_us(5000U); + continue; + } + + uint32_t test_addr = RECV_ADDR(); + uint32_t test_size = RECV_SIZE(); + + switch (test_msg) { + case MSG_SLAVE_READ: + (void)REG_READ(test_addr); + break; + case MSG_SLAVE_WRITE: + REG_WRITE(test_addr, test_size); + break; + case MSG_SLAVE_EXEC: { + void (*func_ptr)(void) = (void (*)(void))(test_addr); + func_ptr(); + break; + } + default: + break; + } + SEND_MSG(MSG_SLAVE_CLEAR); + } + + restore_default_vector_table(); + return 0; +} diff --git a/components/hal/test_apps/tee_apm/components/pms/src/ulp/ulp_vectors.S b/components/hal/test_apps/tee_apm/components/pms/src/ulp/ulp_vectors.S new file mode 100644 index 0000000000..fccd30a1f2 --- /dev/null +++ b/components/hal/test_apps/tee_apm/components/pms/src/ulp/ulp_vectors.S @@ -0,0 +1,171 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "riscv/encoding.h" +#include "riscv/rvruntime-frames.h" +#include "esp_private/panic_reason.h" + + .equ SAVE_REGS, 32 + .equ CONTEXT_SIZE, (SAVE_REGS * 4) + .global test_panicHandler + +/* Macro which first allocates space on the stack to save general + * purpose registers, and then save them. GP register is excluded. + * The default size allocated on the stack is CONTEXT_SIZE, but it + * can be overridden. */ +.macro save_general_regs cxt_size=CONTEXT_SIZE + addi sp, sp, -\cxt_size + sw ra, RV_STK_RA(sp) + sw tp, RV_STK_TP(sp) + sw t0, RV_STK_T0(sp) + sw t1, RV_STK_T1(sp) + sw t2, RV_STK_T2(sp) + sw s0, RV_STK_S0(sp) + sw s1, RV_STK_S1(sp) + sw a0, RV_STK_A0(sp) + sw a1, RV_STK_A1(sp) + sw a2, RV_STK_A2(sp) + sw a3, RV_STK_A3(sp) + sw a4, RV_STK_A4(sp) + sw a5, RV_STK_A5(sp) + sw a6, RV_STK_A6(sp) + sw a7, RV_STK_A7(sp) + sw s2, RV_STK_S2(sp) + sw s3, RV_STK_S3(sp) + sw s4, RV_STK_S4(sp) + sw s5, RV_STK_S5(sp) + sw s6, RV_STK_S6(sp) + sw s7, RV_STK_S7(sp) + sw s8, RV_STK_S8(sp) + sw s9, RV_STK_S9(sp) + sw s10, RV_STK_S10(sp) + sw s11, RV_STK_S11(sp) + sw t3, RV_STK_T3(sp) + sw t4, RV_STK_T4(sp) + sw t5, RV_STK_T5(sp) + sw t6, RV_STK_T6(sp) +.endm + +.macro save_mepc + csrr t0, mepc + sw t0, RV_STK_MEPC(sp) +.endm + +.macro save_mcsr + csrr t0, mstatus + sw t0, RV_STK_MSTATUS(sp) + csrr t0, mtvec + sw t0, RV_STK_MTVEC(sp) + csrr t0, mcause + sw t0, RV_STK_MCAUSE(sp) + csrr t0, mtval + sw t0, RV_STK_MTVAL(sp) + csrr t0, mhartid + sw t0, RV_STK_MHARTID(sp) +.endm + +/* Restore the general purpose registers (excluding gp) from the context on + * the stack. The context is then deallocated. The default size is CONTEXT_SIZE + * but it can be overridden. */ +.macro restore_general_regs cxt_size=CONTEXT_SIZE + lw ra, RV_STK_RA(sp) + lw tp, RV_STK_TP(sp) + lw t0, RV_STK_T0(sp) + lw t1, RV_STK_T1(sp) + lw t2, RV_STK_T2(sp) + lw s0, RV_STK_S0(sp) + lw s1, RV_STK_S1(sp) + lw a0, RV_STK_A0(sp) + lw a1, RV_STK_A1(sp) + lw a2, RV_STK_A2(sp) + lw a3, RV_STK_A3(sp) + lw a4, RV_STK_A4(sp) + lw a5, RV_STK_A5(sp) + lw a6, RV_STK_A6(sp) + lw a7, RV_STK_A7(sp) + lw s2, RV_STK_S2(sp) + lw s3, RV_STK_S3(sp) + lw s4, RV_STK_S4(sp) + lw s5, RV_STK_S5(sp) + lw s6, RV_STK_S6(sp) + lw s7, RV_STK_S7(sp) + lw s8, RV_STK_S8(sp) + lw s9, RV_STK_S9(sp) + lw s10, RV_STK_S10(sp) + lw s11, RV_STK_S11(sp) + lw t3, RV_STK_T3(sp) + lw t4, RV_STK_T4(sp) + lw t5, RV_STK_T5(sp) + lw t6, RV_STK_T6(sp) + addi sp,sp, \cxt_size +.endm + +.macro restore_mepc + lw t0, RV_STK_MEPC(sp) + csrw mepc, t0 +.endm + +.macro restore_mcsr + lw t0, RV_STK_MSTATUS(sp) + csrw mstatus, t0 + lw t0, RV_STK_MTVEC(sp) + csrw mtvec, t0 + lw t0, RV_STK_MCAUSE(sp) + csrw mcause, t0 + lw t0, RV_STK_MTVAL(sp) + csrw mtval, t0 + lw t0, RV_STK_MHARTID(sp) + csrw mhartid, t0 +.endm + + .section .text, "ax" + + .balign 0x100, 0xff + .option push + .option norvc + .global _test_vector_table + .type _test_vector_table, @function +_test_vector_table: + j _test_panic_handler /* exception handler, entry 0 */ + .rept 31 + j _test_interrupt_handler /* 31 identical entries, all pointing to the interrupt handler */ + .endr + + .size _test_vector_table, .-_test_vector_table + + .option pop + + .balign 0x4, 0xff + .global _test_panic_handler + .type _test_panic_handler, @function +_test_panic_handler: + save_general_regs RV_STK_FRMSZ + sw gp, RV_STK_GP(sp) + addi t0, sp, RV_STK_FRMSZ + sw t0, RV_STK_SP(sp) + save_mepc + save_mcsr + + /* Executing the panic handler */ + mv a0, sp + csrr a1, mcause + jal test_panicHandler + + /* We arrive here if the exception handler has returned. */ + restore_mepc + restore_general_regs RV_STK_FRMSZ + + csrw mepc, ra + mret + + .size _test_panic_handler, .-_test_panic_handler + + .balign 0x4, 0xff + .global _test_interrupt_handler + .type _test_interrupt_handler, @function +_test_interrupt_handler: + mret + .size _test_interrupt_handler, .-_test_interrupt_handler diff --git a/components/hal/test_apps/tee_apm/main/CMakeLists.txt b/components/hal/test_apps/tee_apm/main/CMakeLists.txt new file mode 100644 index 0000000000..ce32878745 --- /dev/null +++ b/components/hal/test_apps/tee_apm/main/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "test_main.c" "test_pms.c" + INCLUDE_DIRS "" + PRIV_REQUIRES pms esp_psram + WHOLE_ARCHIVE) diff --git a/components/hal/test_apps/tee_apm/main/idf_component.yml b/components/hal/test_apps/tee_apm/main/idf_component.yml new file mode 100644 index 0000000000..c0428d208c --- /dev/null +++ b/components/hal/test_apps/tee_apm/main/idf_component.yml @@ -0,0 +1,4 @@ +dependencies: + ccomp_timer: "^1.0.0" + test_utils: + path: ${IDF_PATH}/tools/unit-test-app/components/test_utils diff --git a/components/hal/test_apps/tee_apm/main/test_main.c b/components/hal/test_apps/tee_apm/main/test_main.c new file mode 100644 index 0000000000..09a2e5f578 --- /dev/null +++ b/components/hal/test_apps/tee_apm/main/test_main.c @@ -0,0 +1,46 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "unity.h" +#include "memory_checks.h" + +/* setUp runs before every test */ +void setUp(void) +{ + test_utils_record_free_mem(); + test_utils_set_leak_level(CONFIG_UNITY_CRITICAL_LEAK_LEVEL_GENERAL, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL); + test_utils_set_leak_level(CONFIG_UNITY_WARN_LEAK_LEVEL_GENERAL, ESP_LEAK_TYPE_WARNING, ESP_COMP_LEAK_GENERAL); + test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_LWIP); +} + +/* tearDown runs after every test */ +void tearDown(void) +{ + /* some FreeRTOS stuff is cleaned up by idle task */ + vTaskDelay(5); + + /* clean up some of the newlib's lazy allocations */ + esp_reent_cleanup(); + + /* check if unit test has caused heap corruption in any heap */ + TEST_ASSERT_MESSAGE(heap_caps_check_integrity(MALLOC_CAP_INVALID, true), "The test has corrupted the heap"); + + test_utils_finish_and_evaluate_leaks(test_utils_get_leak_level(ESP_LEAK_TYPE_WARNING, ESP_COMP_LEAK_ALL), + test_utils_get_leak_level(ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_ALL)); + +} + +static void test_task(void *pvParameters) +{ + vTaskDelay(10); /* Delay a bit to let the main task be deleted */ + unity_run_menu(); +} + +void app_main(void) +{ + xTaskCreatePinnedToCore(test_task, "testTask", CONFIG_UNITY_FREERTOS_STACK_SIZE, NULL, CONFIG_UNITY_FREERTOS_PRIORITY, NULL, CONFIG_UNITY_FREERTOS_CPU); +} diff --git a/components/hal/test_apps/tee_apm/main/test_pms.c b/components/hal/test_apps/tee_apm/main/test_pms.c new file mode 100644 index 0000000000..a0181a9c3a --- /dev/null +++ b/components/hal/test_apps/tee_apm/main/test_pms.c @@ -0,0 +1,246 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/soc_caps.h" +#include "unity.h" +#include "test_pms.h" + +#include "sdkconfig.h" + +/** + * Test default access behavior for TEE mode + * + * Verifies the expected default access policy for TEE mode as defined by APM design. + * Typically, masters in TEE mode should have full access to memory regions not explicitly + * covered by an APM region entry. + * + * On ESP32-C6 and ESP32-H2, a known hardware bug causes TEE-mode masters to be denied access + * to such regions, incorrectly triggering APM exceptions. This test validates that behavior. + * + * The test allocates a region in HP_MEM without an APM region entry and performs GDMA + * read/write operations in TEE mode. It confirms: + * - On affected SoCs (e.g., C6, H2): APM exceptions are expected. + * - On unaffected SoCs: GDMA access should succeed without any APM violations. + */ +TEST_CASE("Test TEE mode default access", "[SYS_APM]") +{ + test_tee_mode_default_access(); +} + +/** + * Test HP-CPU access to CPU_PERI + * + * SYS_APM uses region-based access control with start/end address boundaries and per-mode permissions. + * Configures multiple APM regions covering the CPU_PERI address space. For each region + * and security mode (TEE, REE0, REE1, REE2), tests HP-CPU read/write access with varying + * permissions: R-only (read passes, write fails) and W-only (write passes, read fail). + * Verifies enforcement of APM access control by asserting expected APM violations. + */ +TEST_CASE("Test HP_CPU -> CPU_PERI access", "[SYS_APM]") +{ + test_sys_apm_master_hp_cpu_slave_cpu_peri(); +} + +/** + * Test HP-CPU access to HP_PERI + * + * Configures multiple APM regions covering the HP_PERI address space. For each region + * and security mode (TEE, REE0, REE1, REE2), tests HP-CPU read/write access with varying + * permissions: R-only (read passes, write fails) and W-only (write passes, read fail). + * Verifies enforcement of APM access control by asserting expected APM violations. + */ +TEST_CASE("Test HP_CPU -> HP_PERI access", "[SYS_APM]") +{ + test_sys_apm_master_hp_cpu_slave_hp_peri(); +} + +/** + * Test HP-CPU access to LP_PERI + * + * SYS_APM uses region-based access control with start/end address boundaries and per-mode permissions. + * Configures multiple APM regions covering the LP_PERI address space. For each region + * and security mode (TEE, REE0, REE1, REE2), tests HP-CPU read/write access with varying + * permissions: R-only (read passes, write fails) and W-only (write passes, read fail). + * Verifies enforcement of APM access control by asserting expected APM violations. + */ +TEST_CASE("Test HP_CPU -> LP_PERI access", "[SYS_APM]") +{ + test_sys_apm_master_hp_cpu_slave_lp_peri(); +} + +#if SOC_APM_CPU_APM_SUPPORTED +/** + * Test HP-CPU access to HP_MEM + * + * SYS_APM uses region-based access control with start/end address boundaries and per-mode permissions. + * Divides a contiguous HP_MEM block into multiple APM regions and configures + * their boundaries. For each region and security mode (TEE, REE0, REE1, REE2), tests + * HP-CPU read/write access with varying permissions: R-only (read passes, write fails) and + * W-only (write passes, read and execute fail). Verifies enforcement of APM access control by + * asserting expected APM violations. + */ +TEST_CASE("Test HP_CPU -> HP_MEM access", "[SYS_APM]") +{ + test_sys_apm_master_hp_cpu_slave_hpmem(); +} +#endif /* SOC_APM_CPU_APM_SUPPORTED */ + +#if SOC_RTC_MEM_SUPPORTED +/** + * Test HP-CPU access to LP_MEM + * + * SYS_APM uses region-based access control with start/end address boundaries and per-mode permissions. + * Divides a contiguous LP_MEM block into multiple APM regions and configures + * their boundaries. For each region and security mode (TEE, REE0, REE1, REE2), tests + * HP-CPU read/write access with varying permissions: R-only (read passes, write fails) and + * W-only (write passes, read and execute fail). Verifies enforcement of APM access control by + * asserting expected APM violations. + */ +TEST_CASE("Test HP_CPU -> LP_MEM access", "[SYS_APM]") +{ + test_sys_apm_master_hp_cpu_slave_lpmem(); +} +#endif /* SOC_RTC_MEM_SUPPORTED */ + +/** + * Test GDMA access to HP_MEM + * + * SYS_APM uses region-based access control with start/end address boundaries and per-mode permissions. + * Divides a contiguous HP_MEM block into multiple APM regions and configures + * their boundaries. For each region and security mode (TEE, REE0, REE1, REE2), tests + * GDMA read/write access with varying permissions: R-only (read passes, write fails) and + * W-only (write passes, read fails). Verifies enforcement of APM access control by + * asserting expected APM violations. + */ +TEST_CASE("Test GDMA -> HP_MEM access", "[SYS_APM]") +{ + test_sys_apm_master_gdma_slave_hpmem(); +} + +#if CONFIG_SPIRAM +/** + * Test GDMA access to EXT_MEM (SPIRAM) + * + * SYS_APM uses region-based access control with start/end address boundaries and per-mode permissions. + * Divides a contiguous EXT_MEM block into multiple APM regions and configures + * their boundaries. For each region and security mode (TEE, REE0, REE1, REE2), tests + * GDMA read/write access with varying permissions: R-only (read passes, write fails) and + * W-only (write passes, read fails). Verifies enforcement of APM access control by + * asserting expected APM violations. + */ +TEST_CASE("Test GDMA -> EXT_MEM access", "[SYS_APM]") +{ + test_sys_apm_master_gdma_slave_extmem(); +} +#endif /* CONFIG_SPIRAM */ + +#if CONFIG_ULP_COPROC_ENABLED +/** + * Test LP-CPU access to LP_PERI + * + * SYS_APM uses region-based access control with start/end address boundaries and per-mode permissions. + * Configures multiple APM regions covering the LP_PERI address space. For each region + * and security mode (TEE, REE0, REE1, REE2), tests LP-CPU read/write access with varying + * permissions: R-only (read passes, write fails) and W-only (write passes, read fail). + * Verifies enforcement of APM access control by asserting expected APM violations. + */ +TEST_CASE("Test LP_CPU -> LP_PERI access", "[SYS_APM]") +{ + test_sys_apm_master_lp_cpu_slave_lp_peri(); +} + +/** + * Test LP-CPU access to LP_MEM + * + * SYS_APM uses region-based access control with start/end address boundaries and per-mode permissions. + * Divides a contiguous LP_MEM block into multiple APM regions and configures + * their boundaries. For each region and security mode (TEE, REE0, REE1, REE2), tests + * LP-CPU read/write access with varying permissions: R-only (read passes, write fails) and + * W-only (write passes, read and execute fail). Verifies enforcement of APM access control by + * asserting expected APM violations. + */ +TEST_CASE("Test LP_CPU -> LP_MEM access", "[SYS_APM]") +{ + test_sys_apm_master_lp_cpu_slave_lpmem(); +} + +/** + * Test LP-CPU access to HP_MEM + * + * SYS_APM uses region-based access control with start/end address boundaries and per-mode permissions. + * Divides a contiguous HP_MEM block into multiple APM regions and configures + * their boundaries. For each region and security mode (TEE, REE0, REE1, REE2), tests + * LP-CPU read/write access with varying permissions: R-only (read passes, write fails) and + * W-only (write passes, read and execute fail). Verifies enforcement of APM access control by + * asserting expected APM violations. + * + * Also verifies that LP-CPU can forcibly access HP_MEM regardless of APM permission settings. + */ +TEST_CASE("Test LP_CPU -> HP_MEM access", "[SYS_APM]") +{ + test_sys_apm_master_lp_cpu_slave_hpmem(); +} +#endif /* CONFIG_ULP_COPROC_ENABLED */ + +#if SOC_APM_SUPPORT_TEE_PERI_ACCESS_CTRL +/** + * Test HP-CPU access to HP_PERI using PERI_APM + * + * PERI_APM uses per-peripheral based access control with per-mode permissions. + * For each peripheral and security mode (TEE, REE0, REE1, REE2), tests HP-CPU + * read/write access with varying permissions: R-only (read passes, write fails) and + * W-only (write passes, read fail). Verifies enforcement of access control + * by asserting expected load/store access faults. + */ +TEST_CASE("Test HP_CPU -> HP_PERI access", "[PERI_APM]") +{ + test_peri_apm_master_hp_cpu_slave_hp_peri(); +} + +/** + * Test HP-CPU access to LP_PERI using PERI_APM + * + * PERI_APM uses per-peripheral based access control with per-mode permissions. + * For each peripheral and security mode (TEE, REE0, REE1, REE2), tests HP-CPU + * read/write access with varying permissions: R-only (read passes, write fails) and + * W-only (write passes, read fail). Verifies enforcement of access control + * by asserting expected load/store access faults. + */ +TEST_CASE("Test HP_CPU -> LP_PERI access", "[PERI_APM]") +{ + test_peri_apm_master_hp_cpu_slave_lp_peri(); +} + +#if CONFIG_ULP_COPROC_ENABLED +/** + * Test LP-CPU access to HP_PERI using PERI_APM + * + * PERI_APM uses per-peripheral based access control with per-mode permissions. + * For each peripheral and security mode (TEE, REE0, REE1, REE2), tests LP-CPU + * read/write access with varying permissions: R-only (read passes, write fails) and + * W-only (write passes, read fail). Verifies enforcement of access control + * by asserting expected load/store access faults. + */ +TEST_CASE("Test LP_CPU -> HP_PERI access", "[PERI_APM]") +{ + test_peri_apm_master_lp_cpu_slave_hp_peri(); +} + +/** + * Test LP-CPU access to LP_PERI using PERI_APM + * + * PERI_APM uses per-peripheral based access control with per-mode permissions. + * For each peripheral and security mode (TEE, REE0, REE1, REE2), tests LP-CPU + * read/write access with varying permissions: R-only (read passes, write fails) and + * W-only (write passes, read fail). Verifies enforcement of access control + * by asserting expected load/store access faults. + */ +TEST_CASE("Test LP_CPU -> LP_PERI access", "[PERI_APM]") +{ + test_peri_apm_master_lp_cpu_slave_lp_peri(); +} +#endif /* CONFIG_ULP_COPROC_ENABLED */ +#endif /* SOC_APM_SUPPORT_TEE_PERI_ACCESS_CTRL */ diff --git a/components/hal/test_apps/tee_apm/pytest_tee_apm_pms.py b/components/hal/test_apps/tee_apm/pytest_tee_apm_pms.py new file mode 100644 index 0000000000..12801bef72 --- /dev/null +++ b/components/hal/test_apps/tee_apm/pytest_tee_apm_pms.py @@ -0,0 +1,42 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +import pytest +from pytest_embedded_idf import IdfDut +from pytest_embedded_idf.utils import idf_parametrize + +# ---------------- Pytest build parameters ---------------- + +SOC_SYS_APM_SUPPORTED = ['esp32c6', 'esp32h2', 'esp32c5', 'esp32c61'] +SOC_PERI_APM_SUPPORTED = ['esp32c5'] + +CONFIG_SYS_APM = [ + # 'config, target, markers', + ('default', target, (pytest.mark.generic,)) + for target in SOC_SYS_APM_SUPPORTED +] + +CONFIG_PERI_APM = [ + # 'config, target, markers', + ('default', target, (pytest.mark.generic,)) + for target in SOC_PERI_APM_SUPPORTED +] + +# ---------------- TEE default tests ---------------- + + +@idf_parametrize( + 'config, target, markers', + CONFIG_SYS_APM, + indirect=['config', 'target'], +) +def test_tee_sys_apm(dut: IdfDut) -> None: + dut.run_all_single_board_cases(group='SYS_APM') + + +@idf_parametrize( + 'config, target, markers', + CONFIG_PERI_APM, + indirect=['config', 'target'], +) +def test_tee_peri_apm(dut: IdfDut) -> None: + dut.run_all_single_board_cases(group='PERI_APM') diff --git a/components/hal/test_apps/tee_apm/sdkconfig.defaults b/components/hal/test_apps/tee_apm/sdkconfig.defaults new file mode 100644 index 0000000000..25034d54b3 --- /dev/null +++ b/components/hal/test_apps/tee_apm/sdkconfig.defaults @@ -0,0 +1,6 @@ +# Test-app related +CONFIG_FREERTOS_HZ=1000 +CONFIG_ESP_INT_WDT=n +CONFIG_ESP_TASK_WDT_INIT=n +CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y +CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT=n diff --git a/components/hal/test_apps/tee_apm/sdkconfig.defaults.esp32c5 b/components/hal/test_apps/tee_apm/sdkconfig.defaults.esp32c5 new file mode 100644 index 0000000000..0139d521ec --- /dev/null +++ b/components/hal/test_apps/tee_apm/sdkconfig.defaults.esp32c5 @@ -0,0 +1,7 @@ +# 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 diff --git a/components/hal/test_apps/tee_apm/sdkconfig.defaults.esp32c6 b/components/hal/test_apps/tee_apm/sdkconfig.defaults.esp32c6 new file mode 100644 index 0000000000..593734bd07 --- /dev/null +++ b/components/hal/test_apps/tee_apm/sdkconfig.defaults.esp32c6 @@ -0,0 +1,4 @@ +# Enable LP core +CONFIG_ULP_COPROC_ENABLED=y +CONFIG_ULP_COPROC_RESERVE_MEM=8192 +CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=n diff --git a/components/hal/test_apps/tee_apm/sdkconfig.defaults.esp32c61 b/components/hal/test_apps/tee_apm/sdkconfig.defaults.esp32c61 new file mode 100644 index 0000000000..5665cfbb5c --- /dev/null +++ b/components/hal/test_apps/tee_apm/sdkconfig.defaults.esp32c61 @@ -0,0 +1,2 @@ +# Enable SPIRAM +CONFIG_SPIRAM=y diff --git a/components/hal/test_apps/tee_apm/sdkconfig.defaults.esp32h2 b/components/hal/test_apps/tee_apm/sdkconfig.defaults.esp32h2 new file mode 100644 index 0000000000..ee4295c47d --- /dev/null +++ b/components/hal/test_apps/tee_apm/sdkconfig.defaults.esp32h2 @@ -0,0 +1,2 @@ +# Do not add LP_MEM to heap +CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=n