mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-10-30 20:51:41 +00: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/freertos/                 @esp-idf-codeowners/system | ||||||
| /components/hal/                      @esp-idf-codeowners/peripherals | /components/hal/                      @esp-idf-codeowners/peripherals | ||||||
| /components/hal/test_apps/crypto/     @esp-idf-codeowners/peripherals @esp-idf-codeowners/security | /components/hal/test_apps/crypto/     @esp-idf-codeowners/peripherals @esp-idf-codeowners/security | ||||||
|  | /components/hal/test_apps/tee_apm/    @esp-idf-codeowners/peripherals @esp-idf-codeowners/security | ||||||
| /components/heap/                     @esp-idf-codeowners/system | /components/heap/                     @esp-idf-codeowners/system | ||||||
| /components/http_parser/              @esp-idf-codeowners/app-utilities | /components/http_parser/              @esp-idf-codeowners/app-utilities | ||||||
| /components/idf_test/                 @esp-idf-codeowners/peripherals @esp-idf-codeowners/system | /components/idf_test/                 @esp-idf-codeowners/peripherals @esp-idf-codeowners/system | ||||||
|   | |||||||
| @@ -136,6 +136,7 @@ void esp_cpu_configure_region_protection(void) | |||||||
|     _Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region"); |     _Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region"); | ||||||
|  |  | ||||||
|     // 2. I/D-ROM |     // 2. I/D-ROM | ||||||
|  | #if CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT && !BOOTLOADER_BUILD | ||||||
|     const uint32_t drom_start = (uint32_t) (ets_rom_layout_p->drom_start); |     const uint32_t drom_start = (uint32_t) (ets_rom_layout_p->drom_start); | ||||||
|     if ((drom_start & (SOC_CPU_PMP_REGION_GRANULARITY - 1)) == 0) { |     if ((drom_start & (SOC_CPU_PMP_REGION_GRANULARITY - 1)) == 0) { | ||||||
|         // We can skip configuring the PMP entry for the [SOC_IROM_MASK_LOW - drom_start] |         // We can skip configuring the PMP entry for the [SOC_IROM_MASK_LOW - drom_start] | ||||||
| @@ -144,9 +145,11 @@ void esp_cpu_configure_region_protection(void) | |||||||
|         // the region as cacheable. Thus, we save on one PMP entry. |         // the region as cacheable. Thus, we save on one PMP entry. | ||||||
|         PMP_ENTRY_SET(1, drom_start, NONE); |         PMP_ENTRY_SET(1, drom_start, NONE); | ||||||
|         PMP_ENTRY_SET(2, SOC_DROM_MASK_HIGH, PMP_TOR | R); |         PMP_ENTRY_SET(2, SOC_DROM_MASK_HIGH, PMP_TOR | R); | ||||||
|     } else { |     } else | ||||||
|  | #endif | ||||||
|  |     { | ||||||
|         PMP_ENTRY_SET(1, SOC_IROM_MASK_LOW, NONE); |         PMP_ENTRY_SET(1, SOC_IROM_MASK_LOW, NONE); | ||||||
|         PMP_ENTRY_SET(2, SOC_IROM_MASK_HIGH, PMP_TOR | RX); |         PMP_ENTRY_SET(2, SOC_IROM_MASK_HIGH, PMP_TOR | CONDITIONAL_RX); | ||||||
|         _Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region"); |         _Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -133,14 +133,17 @@ void esp_cpu_configure_region_protection(void) | |||||||
|     _Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region"); |     _Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region"); | ||||||
|  |  | ||||||
|     // 2. I/D-ROM |     // 2. I/D-ROM | ||||||
|  | #if CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT && !BOOTLOADER_BUILD | ||||||
|     const uint32_t drom_start = (uint32_t) (ets_rom_layout_p->drom_start); |     const uint32_t drom_start = (uint32_t) (ets_rom_layout_p->drom_start); | ||||||
|     if ((drom_start & (SOC_CPU_PMP_REGION_GRANULARITY - 1)) == 0) { |     if ((drom_start & (SOC_CPU_PMP_REGION_GRANULARITY - 1)) == 0) { | ||||||
|         PMP_ENTRY_SET(1, SOC_IROM_MASK_LOW, NONE); |         PMP_ENTRY_SET(1, SOC_IROM_MASK_LOW, NONE); | ||||||
|         PMP_ENTRY_SET(2, drom_start, PMP_TOR | RX); |         PMP_ENTRY_SET(2, drom_start, PMP_TOR | RX); | ||||||
|         PMP_ENTRY_SET(3, SOC_DROM_MASK_HIGH, PMP_TOR | RW); |         PMP_ENTRY_SET(3, SOC_DROM_MASK_HIGH, PMP_TOR | RW); | ||||||
|     } else { |     } else | ||||||
|  | #endif | ||||||
|  |     { | ||||||
|         const uint32_t pmpaddr1 = PMPADDR_NAPOT(SOC_IROM_MASK_LOW, SOC_IROM_MASK_HIGH); |         const uint32_t pmpaddr1 = PMPADDR_NAPOT(SOC_IROM_MASK_LOW, SOC_IROM_MASK_HIGH); | ||||||
|         PMP_ENTRY_SET(1, pmpaddr1, PMP_NAPOT | RX); |         PMP_ENTRY_SET(1, pmpaddr1, PMP_NAPOT | CONDITIONAL_RX); | ||||||
|         _Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region"); |         _Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,3 +11,7 @@ components/hal/test_apps/hal_i2c: | |||||||
| components/hal/test_apps/hal_utils: | components/hal/test_apps/hal_utils: | ||||||
|   enable: |   enable: | ||||||
|     - if: IDF_TARGET == "linux" |     - if: IDF_TARGET == "linux" | ||||||
|  |  | ||||||
|  | components/hal/test_apps/tee_apm: | ||||||
|  |   disable: | ||||||
|  |     - if: IDF_TARGET not in ["esp32c6", "esp32h2", "esp32c5", "esp32c61"] | ||||||
|   | |||||||
| @@ -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) | 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) { |     switch (ctrl_mod) { | ||||||
|         case APM_CTRL_HP_APM: |         case APM_CTRL_HP_APM: | ||||||
|             apm_ll_hp_apm_set_sec_mode_region_attr(regn_num, mode, regn_pms); |             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
	 Laukik Hase
					Laukik Hase