Merge branch 'ci/tee_apm_pms_test_app' into 'master'

ci(hal): Add HAL/LL-based test app for the TEE and APM peripherals

Closes IDF-8614, IDF-8615, IDF-9229, IDF-9230, IDF-10422, IDF-12646, IDF-12647, IDF-12648, IDF-12649, and IDF-12877

See merge request espressif/esp-idf!39873
This commit is contained in:
Laukik Hase
2025-07-03 10:08:58 +05:30
41 changed files with 4333 additions and 41 deletions

View File

@@ -125,6 +125,7 @@
/components/freertos/ @esp-idf-codeowners/system /components/freertos/ @esp-idf-codeowners/system
/components/hal/ @esp-idf-codeowners/peripherals /components/hal/ @esp-idf-codeowners/peripherals
/components/hal/test_apps/crypto/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/security /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/heap/ @esp-idf-codeowners/system
/components/http_parser/ @esp-idf-codeowners/app-utilities /components/http_parser/ @esp-idf-codeowners/app-utilities
/components/idf_test/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system /components/idf_test/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system

View File

@@ -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"); _Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region");
// 2. I/D-ROM // 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); const uint32_t drom_start = (uint32_t) (ets_rom_layout_p->drom_start);
if ((drom_start & (SOC_CPU_PMP_REGION_GRANULARITY - 1)) == 0) { 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] // 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. // the region as cacheable. Thus, we save on one PMP entry.
PMP_ENTRY_SET(1, drom_start, NONE); PMP_ENTRY_SET(1, drom_start, NONE);
PMP_ENTRY_SET(2, SOC_DROM_MASK_HIGH, PMP_TOR | R); 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(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"); _Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region");
} }

View File

@@ -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"); _Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region");
// 2. I/D-ROM // 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); const uint32_t drom_start = (uint32_t) (ets_rom_layout_p->drom_start);
if ((drom_start & (SOC_CPU_PMP_REGION_GRANULARITY - 1)) == 0) { if ((drom_start & (SOC_CPU_PMP_REGION_GRANULARITY - 1)) == 0) {
PMP_ENTRY_SET(1, SOC_IROM_MASK_LOW, NONE); PMP_ENTRY_SET(1, SOC_IROM_MASK_LOW, NONE);
PMP_ENTRY_SET(2, drom_start, PMP_TOR | RX); PMP_ENTRY_SET(2, drom_start, PMP_TOR | RX);
PMP_ENTRY_SET(3, SOC_DROM_MASK_HIGH, PMP_TOR | RW); PMP_ENTRY_SET(3, SOC_DROM_MASK_HIGH, PMP_TOR | RW);
} else { } else
#endif
{
const uint32_t pmpaddr1 = PMPADDR_NAPOT(SOC_IROM_MASK_LOW, SOC_IROM_MASK_HIGH); 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"); _Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region");
} }

View File

@@ -11,3 +11,7 @@ components/hal/test_apps/hal_i2c:
components/hal/test_apps/hal_utils: components/hal/test_apps/hal_utils:
enable: enable:
- if: IDF_TARGET == "linux" - if: IDF_TARGET == "linux"
components/hal/test_apps/tee_apm:
disable:
- if: IDF_TARGET not in ["esp32c6", "esp32h2", "esp32c5", "esp32c61"]

View File

@@ -218,9 +218,84 @@ 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)
{
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);
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) 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(regn_cfg);
HAL_ASSERT(mode != APM_SEC_MODE_TEE);
switch (ctrl_mod) { switch (ctrl_mod) {
case APM_CTRL_HP_APM: case APM_CTRL_HP_APM:

View File

@@ -14,6 +14,8 @@
#include "soc/hp_apm_struct.h" #include "soc/hp_apm_struct.h"
#include "soc/lp_apm_reg.h" #include "soc/lp_apm_reg.h"
#include "soc/lp_apm_struct.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/pcr_reg.h"
#include "soc/interrupts.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; 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 * @brief Enable/disable APM reset event bypass
* *

View File

@@ -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); 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 * @brief Set region filter configuration
* *

View File

@@ -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")

View File

@@ -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/<target>/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 <TARGET>
idf.py build
```
## Running the App
```bash
idf.py flash monitor
```
## Running Tests
```bash
pytest --target <TARGET>
```
---

View File

@@ -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()

View File

@@ -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);

View File

@@ -0,0 +1,5 @@
[mapping:pms]
archive: libpms.a
entries:
test_intr_utils (noflash)
test_panic_handler (noflash)

View File

@@ -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"

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -0,0 +1,99 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#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);

View File

@@ -0,0 +1,370 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#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;
}
}
}
}

View File

@@ -0,0 +1,77 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <assert.h>
#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);
}

View File

@@ -0,0 +1,82 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stddef.h>
#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();
}

View File

@@ -0,0 +1,245 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <stdbool.h>
#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
}

View File

@@ -0,0 +1,310 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <string.h>
#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

View File

@@ -0,0 +1,865 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <string.h>
#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);
}

View File

@@ -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

View File

@@ -0,0 +1,109 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <stdint.h>
#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;
}

View File

@@ -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

View File

@@ -0,0 +1,4 @@
idf_component_register(SRCS "test_main.c" "test_pms.c"
INCLUDE_DIRS ""
PRIV_REQUIRES pms esp_psram
WHOLE_ARCHIVE)

View File

@@ -0,0 +1,4 @@
dependencies:
ccomp_timer: "^1.0.0"
test_utils:
path: ${IDF_PATH}/tools/unit-test-app/components/test_utils

View File

@@ -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);
}

View File

@@ -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 */

View File

@@ -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')

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,2 @@
# Enable SPIRAM
CONFIG_SPIRAM=y

View File

@@ -0,0 +1,2 @@
# Do not add LP_MEM to heap
CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=n

View File

@@ -999,6 +999,10 @@ config SOC_APM_CTRL_FILTER_SUPPORTED
bool bool
default y default y
config SOC_APM_CPU_APM_SUPPORTED
bool
default y
config SOC_APM_SUPPORT_CTRL_CFG_LOCK config SOC_APM_SUPPORT_CTRL_CFG_LOCK
bool bool
default y default y

View File

@@ -15,9 +15,11 @@ extern "C" {
/* Number of paths for each supported APM controller */ /* Number of paths for each supported APM controller */
#define APM_CTRL_HP_APM_PATH_NUM (4) #define APM_CTRL_HP_APM_PATH_NUM (4)
#define APM_CTRL_LP_APM_PATH_NUM (1) #define APM_CTRL_LP_APM_PATH_NUM (1)
#define APM_CTRL_CPU_APM_PATH_NUM (2)
/* Number of regions for each supported APM controller */ /* Number of regions for each supported APM controller */
#define APM_CTRL_HP_APM_REGION_NUM (16) #define APM_CTRL_HP_APM_REGION_NUM (16)
#define APM_CTRL_LP_APM_REGION_NUM (4) #define APM_CTRL_LP_APM_REGION_NUM (4)
#define APM_CTRL_CPU_APM_REGION_NUM (8)
/* Register offset for TEE mode control */ /* Register offset for TEE mode control */
#define APM_TEE_MODE_CTRL_OFFSET (0x04) #define APM_TEE_MODE_CTRL_OFFSET (0x04)

View File

@@ -412,6 +412,7 @@
/*-------------------------- APM CAPS ----------------------------------------*/ /*-------------------------- APM CAPS ----------------------------------------*/
#define SOC_APM_CTRL_FILTER_SUPPORTED 1 /*!< Support for APM control filter */ #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 */ #define SOC_APM_SUPPORT_CTRL_CFG_LOCK 1 /*!< Support for APM controller configuration lock */
/*------------------------ Anti DPA (Security) CAPS --------------------------*/ /*------------------------ Anti DPA (Security) CAPS --------------------------*/

View File

@@ -14,7 +14,7 @@ extern "C" {
/** CPU_APM_REGION_FILTER_EN_REG register /** CPU_APM_REGION_FILTER_EN_REG register
* Region filter enable 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; /** CPU_APM_REGION_FILTER_EN : R/W; bitpos: [7:0]; default: 1;
* Configure bit $n (0-7) to enable region $n. * Configure bit $n (0-7) to enable region $n.
* 0: disable * 0: disable
@@ -28,7 +28,7 @@ extern "C" {
/** CPU_APM_REGION0_ADDR_START_REG register /** CPU_APM_REGION0_ADDR_START_REG register
* Region address 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; /** CPU_APM_REGION0_ADDR_START_L : HRO; bitpos: [11:0]; default: 0;
* Low 12 bit, start address of region 0. * Low 12 bit, start address of region 0.
*/ */
@@ -54,7 +54,7 @@ extern "C" {
/** CPU_APM_REGION0_ADDR_END_REG register /** CPU_APM_REGION0_ADDR_END_REG register
* Region address 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; /** CPU_APM_REGION0_ADDR_END_L : HRO; bitpos: [11:0]; default: 4095;
* Low 12 bit, end address of region 0. * Low 12 bit, end address of region 0.
*/ */
@@ -80,7 +80,7 @@ extern "C" {
/** CPU_APM_REGION0_ATTR_REG register /** CPU_APM_REGION0_ATTR_REG register
* Region access authority attribute 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; /** CPU_APM_REGION0_R0_X : R/W; bitpos: [0]; default: 0;
* Configures the execution authority of REE_MODE 0 in region 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 /** CPU_APM_REGION1_ADDR_START_REG register
* Region address 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; /** CPU_APM_REGION1_ADDR_START_L : HRO; bitpos: [11:0]; default: 0;
* Low 12 bit, start address of region 1. * Low 12 bit, start address of region 1.
*/ */
@@ -181,7 +181,7 @@ extern "C" {
/** CPU_APM_REGION1_ADDR_END_REG register /** CPU_APM_REGION1_ADDR_END_REG register
* Region address 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; /** CPU_APM_REGION1_ADDR_END_L : HRO; bitpos: [11:0]; default: 4095;
* Low 12 bit, end address of region 1. * Low 12 bit, end address of region 1.
*/ */
@@ -207,7 +207,7 @@ extern "C" {
/** CPU_APM_REGION1_ATTR_REG register /** CPU_APM_REGION1_ATTR_REG register
* Region access authority attribute 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; /** CPU_APM_REGION1_R0_X : R/W; bitpos: [0]; default: 0;
* Configures the execution authority of REE_MODE 0 in region 1. * Configures the execution authority of REE_MODE 0 in region 1.
*/ */
@@ -282,7 +282,7 @@ extern "C" {
/** CPU_APM_REGION2_ADDR_START_REG register /** CPU_APM_REGION2_ADDR_START_REG register
* Region address 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; /** CPU_APM_REGION2_ADDR_START_L : HRO; bitpos: [11:0]; default: 0;
* Low 12 bit, start address of region 2. * Low 12 bit, start address of region 2.
*/ */
@@ -308,7 +308,7 @@ extern "C" {
/** CPU_APM_REGION2_ADDR_END_REG register /** CPU_APM_REGION2_ADDR_END_REG register
* Region address 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; /** CPU_APM_REGION2_ADDR_END_L : HRO; bitpos: [11:0]; default: 4095;
* Low 12 bit, end address of region 2. * Low 12 bit, end address of region 2.
*/ */
@@ -334,7 +334,7 @@ extern "C" {
/** CPU_APM_REGION2_ATTR_REG register /** CPU_APM_REGION2_ATTR_REG register
* Region access authority attribute 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; /** CPU_APM_REGION2_R0_X : R/W; bitpos: [0]; default: 0;
* Configures the execution authority of REE_MODE 0 in region 2. * Configures the execution authority of REE_MODE 0 in region 2.
*/ */
@@ -409,7 +409,7 @@ extern "C" {
/** CPU_APM_REGION3_ADDR_START_REG register /** CPU_APM_REGION3_ADDR_START_REG register
* Region address 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; /** CPU_APM_REGION3_ADDR_START_L : HRO; bitpos: [11:0]; default: 0;
* Low 12 bit, start address of region 3. * Low 12 bit, start address of region 3.
*/ */
@@ -435,7 +435,7 @@ extern "C" {
/** CPU_APM_REGION3_ADDR_END_REG register /** CPU_APM_REGION3_ADDR_END_REG register
* Region address 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; /** CPU_APM_REGION3_ADDR_END_L : HRO; bitpos: [11:0]; default: 4095;
* Low 12 bit, end address of region 3. * Low 12 bit, end address of region 3.
*/ */
@@ -461,7 +461,7 @@ extern "C" {
/** CPU_APM_REGION3_ATTR_REG register /** CPU_APM_REGION3_ATTR_REG register
* Region access authority attribute 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; /** CPU_APM_REGION3_R0_X : R/W; bitpos: [0]; default: 0;
* Configures the execution authority of REE_MODE 0 in region 3. * Configures the execution authority of REE_MODE 0 in region 3.
*/ */
@@ -536,7 +536,7 @@ extern "C" {
/** CPU_APM_REGION4_ADDR_START_REG register /** CPU_APM_REGION4_ADDR_START_REG register
* Region address 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; /** CPU_APM_REGION4_ADDR_START_L : HRO; bitpos: [11:0]; default: 0;
* Low 12 bit, start address of region 4. * Low 12 bit, start address of region 4.
*/ */
@@ -562,7 +562,7 @@ extern "C" {
/** CPU_APM_REGION4_ADDR_END_REG register /** CPU_APM_REGION4_ADDR_END_REG register
* Region address 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; /** CPU_APM_REGION4_ADDR_END_L : HRO; bitpos: [11:0]; default: 4095;
* Low 12 bit, end address of region 4. * Low 12 bit, end address of region 4.
*/ */
@@ -588,7 +588,7 @@ extern "C" {
/** CPU_APM_REGION4_ATTR_REG register /** CPU_APM_REGION4_ATTR_REG register
* Region access authority attribute 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; /** CPU_APM_REGION4_R0_X : R/W; bitpos: [0]; default: 0;
* Configures the execution authority of REE_MODE 0 in region 4. * Configures the execution authority of REE_MODE 0 in region 4.
*/ */
@@ -663,7 +663,7 @@ extern "C" {
/** CPU_APM_REGION5_ADDR_START_REG register /** CPU_APM_REGION5_ADDR_START_REG register
* Region address 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; /** CPU_APM_REGION5_ADDR_START_L : HRO; bitpos: [11:0]; default: 0;
* Low 12 bit, start address of region 5. * Low 12 bit, start address of region 5.
*/ */
@@ -689,7 +689,7 @@ extern "C" {
/** CPU_APM_REGION5_ADDR_END_REG register /** CPU_APM_REGION5_ADDR_END_REG register
* Region address 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; /** CPU_APM_REGION5_ADDR_END_L : HRO; bitpos: [11:0]; default: 4095;
* Low 12 bit, end address of region 5. * Low 12 bit, end address of region 5.
*/ */
@@ -715,7 +715,7 @@ extern "C" {
/** CPU_APM_REGION5_ATTR_REG register /** CPU_APM_REGION5_ATTR_REG register
* Region access authority attribute 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; /** CPU_APM_REGION5_R0_X : R/W; bitpos: [0]; default: 0;
* Configures the execution authority of REE_MODE 0 in region 5. * Configures the execution authority of REE_MODE 0 in region 5.
*/ */
@@ -790,7 +790,7 @@ extern "C" {
/** CPU_APM_REGION6_ADDR_START_REG register /** CPU_APM_REGION6_ADDR_START_REG register
* Region address 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; /** CPU_APM_REGION6_ADDR_START_L : HRO; bitpos: [11:0]; default: 0;
* Low 12 bit, start address of region 6. * Low 12 bit, start address of region 6.
*/ */
@@ -816,7 +816,7 @@ extern "C" {
/** CPU_APM_REGION6_ADDR_END_REG register /** CPU_APM_REGION6_ADDR_END_REG register
* Region address 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; /** CPU_APM_REGION6_ADDR_END_L : HRO; bitpos: [11:0]; default: 4095;
* Low 12 bit, end address of region 6. * Low 12 bit, end address of region 6.
*/ */
@@ -842,7 +842,7 @@ extern "C" {
/** CPU_APM_REGION6_ATTR_REG register /** CPU_APM_REGION6_ATTR_REG register
* Region access authority attribute 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; /** CPU_APM_REGION6_R0_X : R/W; bitpos: [0]; default: 0;
* Configures the execution authority of REE_MODE 0 in region 6. * Configures the execution authority of REE_MODE 0 in region 6.
*/ */
@@ -917,7 +917,7 @@ extern "C" {
/** CPU_APM_REGION7_ADDR_START_REG register /** CPU_APM_REGION7_ADDR_START_REG register
* Region address 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; /** CPU_APM_REGION7_ADDR_START_L : HRO; bitpos: [11:0]; default: 0;
* Low 12 bit, start address of region 7. * Low 12 bit, start address of region 7.
*/ */
@@ -943,7 +943,7 @@ extern "C" {
/** CPU_APM_REGION7_ADDR_END_REG register /** CPU_APM_REGION7_ADDR_END_REG register
* Region address 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; /** CPU_APM_REGION7_ADDR_END_L : HRO; bitpos: [11:0]; default: 4095;
* Low 12 bit, end address of region 7. * Low 12 bit, end address of region 7.
*/ */
@@ -969,7 +969,7 @@ extern "C" {
/** CPU_APM_REGION7_ATTR_REG register /** CPU_APM_REGION7_ATTR_REG register
* Region access authority attribute 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; /** CPU_APM_REGION7_R0_X : R/W; bitpos: [0]; default: 0;
* Configures the execution authority of REE_MODE 0 in region 7. * Configures the execution authority of REE_MODE 0 in region 7.
*/ */
@@ -1044,7 +1044,7 @@ extern "C" {
/** CPU_APM_FUNC_CTRL_REG register /** CPU_APM_FUNC_CTRL_REG register
* APM function control 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; /** CPU_APM_M0_FUNC_EN : R/W; bitpos: [0]; default: 1;
* PMS M0 function enable * PMS M0 function enable
*/ */
@@ -1063,7 +1063,7 @@ extern "C" {
/** CPU_APM_M0_STATUS_REG register /** CPU_APM_M0_STATUS_REG register
* M0 status 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; /** CPU_APM_M0_EXCEPTION_STATUS : RO; bitpos: [1:0]; default: 0;
* Represents exception status. * Represents exception status.
* bit0: 1 represents authority_exception * bit0: 1 represents authority_exception
@@ -1077,7 +1077,7 @@ extern "C" {
/** CPU_APM_M0_STATUS_CLR_REG register /** CPU_APM_M0_STATUS_CLR_REG register
* M0 status clear 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; /** CPU_APM_M0_EXCEPTION_STATUS_CLR : WT; bitpos: [0]; default: 0;
* Configures to clear exception status. * Configures to clear exception status.
*/ */
@@ -1089,7 +1089,7 @@ extern "C" {
/** CPU_APM_M0_EXCEPTION_INFO0_REG register /** CPU_APM_M0_EXCEPTION_INFO0_REG register
* M0 exception_info0 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; /** CPU_APM_M0_EXCEPTION_REGION : RO; bitpos: [15:0]; default: 0;
* Represents exception region. * Represents exception region.
*/ */
@@ -1115,7 +1115,7 @@ extern "C" {
/** CPU_APM_M0_EXCEPTION_INFO1_REG register /** CPU_APM_M0_EXCEPTION_INFO1_REG register
* M0 exception_info1 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; /** CPU_APM_M0_EXCEPTION_ADDR : RO; bitpos: [31:0]; default: 0;
* Represents exception addr. * Represents exception addr.
*/ */
@@ -1127,7 +1127,7 @@ extern "C" {
/** CPU_APM_M1_STATUS_REG register /** CPU_APM_M1_STATUS_REG register
* M1 status 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; /** CPU_APM_M1_EXCEPTION_STATUS : RO; bitpos: [1:0]; default: 0;
* Represents exception status. * Represents exception status.
* bit0: 1 represents authority_exception * bit0: 1 represents authority_exception
@@ -1141,7 +1141,7 @@ extern "C" {
/** CPU_APM_M1_STATUS_CLR_REG register /** CPU_APM_M1_STATUS_CLR_REG register
* M1 status clear 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; /** CPU_APM_M1_EXCEPTION_STATUS_CLR : WT; bitpos: [0]; default: 0;
* Configures to clear exception status. * Configures to clear exception status.
*/ */
@@ -1153,7 +1153,7 @@ extern "C" {
/** CPU_APM_M1_EXCEPTION_INFO0_REG register /** CPU_APM_M1_EXCEPTION_INFO0_REG register
* M1 exception_info0 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; /** CPU_APM_M1_EXCEPTION_REGION : RO; bitpos: [15:0]; default: 0;
* Represents exception region. * Represents exception region.
*/ */
@@ -1179,7 +1179,7 @@ extern "C" {
/** CPU_APM_M1_EXCEPTION_INFO1_REG register /** CPU_APM_M1_EXCEPTION_INFO1_REG register
* M1 exception_info1 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; /** CPU_APM_M1_EXCEPTION_ADDR : RO; bitpos: [31:0]; default: 0;
* Represents exception addr. * Represents exception addr.
*/ */
@@ -1191,7 +1191,7 @@ extern "C" {
/** CPU_APM_INT_EN_REG register /** CPU_APM_INT_EN_REG register
* APM interrupt enable 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; /** CPU_APM_M0_APM_INT_EN : R/W; bitpos: [0]; default: 0;
* Configures to enable APM M0 interrupt. * Configures to enable APM M0 interrupt.
* 0: disable * 0: disable
@@ -1214,7 +1214,7 @@ extern "C" {
/** CPU_APM_CLOCK_GATE_REG register /** CPU_APM_CLOCK_GATE_REG register
* Clock gating 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; /** CPU_APM_CLK_EN : R/W; bitpos: [0]; default: 1;
* Configures whether to keep the clock always on. * Configures whether to keep the clock always on.
* 0: enable automatic clock gating * 0: enable automatic clock gating
@@ -1228,7 +1228,7 @@ extern "C" {
/** CPU_APM_DATE_REG register /** CPU_APM_DATE_REG register
* Version control 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; /** CPU_APM_DATE : R/W; bitpos: [27:0]; default: 37823248;
* Version control register. * Version control register.
*/ */