mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-04 13:14:32 +02:00
ci(hal): Add HAL/LL-based test app for the TEE and APM peripherals
This commit is contained in:
@@ -125,6 +125,7 @@
|
||||
/components/freertos/ @esp-idf-codeowners/system
|
||||
/components/hal/ @esp-idf-codeowners/peripherals
|
||||
/components/hal/test_apps/crypto/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/security
|
||||
/components/hal/test_apps/tee_apm/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/security
|
||||
/components/heap/ @esp-idf-codeowners/system
|
||||
/components/http_parser/ @esp-idf-codeowners/app-utilities
|
||||
/components/idf_test/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
|
||||
|
@@ -136,6 +136,7 @@ void esp_cpu_configure_region_protection(void)
|
||||
_Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region");
|
||||
|
||||
// 2. I/D-ROM
|
||||
#if CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT && !BOOTLOADER_BUILD
|
||||
const uint32_t drom_start = (uint32_t) (ets_rom_layout_p->drom_start);
|
||||
if ((drom_start & (SOC_CPU_PMP_REGION_GRANULARITY - 1)) == 0) {
|
||||
// We can skip configuring the PMP entry for the [SOC_IROM_MASK_LOW - drom_start]
|
||||
@@ -144,9 +145,11 @@ void esp_cpu_configure_region_protection(void)
|
||||
// the region as cacheable. Thus, we save on one PMP entry.
|
||||
PMP_ENTRY_SET(1, drom_start, NONE);
|
||||
PMP_ENTRY_SET(2, SOC_DROM_MASK_HIGH, PMP_TOR | R);
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
PMP_ENTRY_SET(1, SOC_IROM_MASK_LOW, NONE);
|
||||
PMP_ENTRY_SET(2, SOC_IROM_MASK_HIGH, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(2, SOC_IROM_MASK_HIGH, PMP_TOR | CONDITIONAL_RX);
|
||||
_Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region");
|
||||
}
|
||||
|
||||
|
@@ -133,14 +133,17 @@ void esp_cpu_configure_region_protection(void)
|
||||
_Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region");
|
||||
|
||||
// 2. I/D-ROM
|
||||
#if CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT && !BOOTLOADER_BUILD
|
||||
const uint32_t drom_start = (uint32_t) (ets_rom_layout_p->drom_start);
|
||||
if ((drom_start & (SOC_CPU_PMP_REGION_GRANULARITY - 1)) == 0) {
|
||||
PMP_ENTRY_SET(1, SOC_IROM_MASK_LOW, NONE);
|
||||
PMP_ENTRY_SET(2, drom_start, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(3, SOC_DROM_MASK_HIGH, PMP_TOR | RW);
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
const uint32_t pmpaddr1 = PMPADDR_NAPOT(SOC_IROM_MASK_LOW, SOC_IROM_MASK_HIGH);
|
||||
PMP_ENTRY_SET(1, pmpaddr1, PMP_NAPOT | RX);
|
||||
PMP_ENTRY_SET(1, pmpaddr1, PMP_NAPOT | CONDITIONAL_RX);
|
||||
_Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region");
|
||||
}
|
||||
|
||||
|
@@ -11,3 +11,7 @@ components/hal/test_apps/hal_i2c:
|
||||
components/hal/test_apps/hal_utils:
|
||||
enable:
|
||||
- if: IDF_TARGET == "linux"
|
||||
|
||||
components/hal/test_apps/tee_apm:
|
||||
disable:
|
||||
- if: IDF_TARGET not in ["esp32c6", "esp32h2", "esp32c5", "esp32c61"]
|
||||
|
@@ -268,6 +268,8 @@ void apm_hal_set_region_end_addr(apm_ctrl_module_t ctrl_mod, uint32_t regn_num,
|
||||
|
||||
void apm_hal_set_sec_mode_region_attr(apm_ctrl_module_t ctrl_mod, uint32_t regn_num, apm_security_mode_t mode, uint32_t regn_pms)
|
||||
{
|
||||
HAL_ASSERT(mode != APM_SEC_MODE_TEE);
|
||||
|
||||
switch (ctrl_mod) {
|
||||
case APM_CTRL_HP_APM:
|
||||
apm_ll_hp_apm_set_sec_mode_region_attr(regn_num, mode, regn_pms);
|
||||
|
15
components/hal/test_apps/tee_apm/CMakeLists.txt
Normal file
15
components/hal/test_apps/tee_apm/CMakeLists.txt
Normal 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")
|
149
components/hal/test_apps/tee_apm/README.md
Normal file
149
components/hal/test_apps/tee_apm/README.md
Normal 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>
|
||||
```
|
||||
|
||||
---
|
@@ -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()
|
@@ -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);
|
@@ -0,0 +1,5 @@
|
||||
[mapping:pms]
|
||||
archive: libpms.a
|
||||
entries:
|
||||
test_intr_utils (noflash)
|
||||
test_panic_handler (noflash)
|
@@ -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"
|
@@ -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)
|
@@ -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)
|
@@ -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)
|
@@ -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)
|
@@ -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);
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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();
|
||||
}
|
@@ -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
|
||||
}
|
@@ -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
|
@@ -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);
|
||||
}
|
@@ -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
|
@@ -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;
|
||||
}
|
@@ -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
|
4
components/hal/test_apps/tee_apm/main/CMakeLists.txt
Normal file
4
components/hal/test_apps/tee_apm/main/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
idf_component_register(SRCS "test_main.c" "test_pms.c"
|
||||
INCLUDE_DIRS ""
|
||||
PRIV_REQUIRES pms esp_psram
|
||||
WHOLE_ARCHIVE)
|
4
components/hal/test_apps/tee_apm/main/idf_component.yml
Normal file
4
components/hal/test_apps/tee_apm/main/idf_component.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
dependencies:
|
||||
ccomp_timer: "^1.0.0"
|
||||
test_utils:
|
||||
path: ${IDF_PATH}/tools/unit-test-app/components/test_utils
|
46
components/hal/test_apps/tee_apm/main/test_main.c
Normal file
46
components/hal/test_apps/tee_apm/main/test_main.c
Normal 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);
|
||||
}
|
246
components/hal/test_apps/tee_apm/main/test_pms.c
Normal file
246
components/hal/test_apps/tee_apm/main/test_pms.c
Normal 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 */
|
42
components/hal/test_apps/tee_apm/pytest_tee_apm_pms.py
Normal file
42
components/hal/test_apps/tee_apm/pytest_tee_apm_pms.py
Normal 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')
|
6
components/hal/test_apps/tee_apm/sdkconfig.defaults
Normal file
6
components/hal/test_apps/tee_apm/sdkconfig.defaults
Normal 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
|
@@ -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
|
@@ -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
|
@@ -0,0 +1,2 @@
|
||||
# Enable SPIRAM
|
||||
CONFIG_SPIRAM=y
|
@@ -0,0 +1,2 @@
|
||||
# Do not add LP_MEM to heap
|
||||
CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=n
|
Reference in New Issue
Block a user