From 11d3a2480f50ed8414d05a5e555a47b09c2cce6c Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Wed, 30 Apr 2025 19:32:05 +0530 Subject: [PATCH 1/4] feat(esp_tee): Support for ESP32-C5 - the `esp_tee` component --- components/esp_tee/CMakeLists.txt | 6 +- components/esp_tee/Kconfig.projbuild | 2 +- .../esp_tee/include/private/esp_tee_binary.h | 6 +- .../scripts/esp32c5/sec_srv_tbl_default.yml | 332 +++++++++ .../esp_tee/src/esp_secure_service_wrapper.c | 34 + components/esp_tee/src/esp_tee_u2m_switch.S | 8 +- .../attestation/esp_att_utils_part_info.c | 2 +- .../esp_tee/subproject/main/CMakeLists.txt | 9 +- .../arch/riscv/esp_tee_vector_table_clic.S | 107 +++ ...or_table.S => esp_tee_vector_table_plic.S} | 4 +- .../main/arch/riscv/esp_tee_vectors_clic.S | 628 ++++++++++++++++++ ...p_tee_vectors.S => esp_tee_vectors_plic.S} | 2 +- .../subproject/main/common/multi_heap.c | 31 +- .../main/common/panic/esp_tee_panic.c | 17 +- .../main/common/panic/panic_helper_riscv.c | 40 +- .../main/core/esp_secure_services.c | 7 + .../main/core/esp_secure_services_iram.c | 49 +- .../subproject/main/core/esp_tee_intr.c | 19 +- .../esp_tee/subproject/main/idf_component.yml | 2 +- .../subproject/main/ld/esp32c5/esp_tee.ld.in | 302 +++++++++ .../main/soc/esp32c5/esp_tee_apm_prot_cfg.c | 266 ++++++++ .../soc/esp32c5/esp_tee_pmp_pma_prot_cfg.c | 108 +++ .../main/soc/esp32c5/esp_tee_secure_sys_cfg.c | 131 ++++ .../soc/esp32c5/include/esp_tee_intr_defs.h | 40 ++ .../soc/esp32c5/include/esp_tee_rv_utils.h | 131 ++++ .../main/soc/esp32c6/esp_tee_secure_sys_cfg.c | 13 +- .../main/soc/esp32h2/esp_tee_secure_sys_cfg.c | 11 +- 27 files changed, 2261 insertions(+), 46 deletions(-) create mode 100644 components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml create mode 100644 components/esp_tee/subproject/main/arch/riscv/esp_tee_vector_table_clic.S rename components/esp_tee/subproject/main/arch/riscv/{esp_tee_vector_table.S => esp_tee_vector_table_plic.S} (96%) create mode 100644 components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors_clic.S rename components/esp_tee/subproject/main/arch/riscv/{esp_tee_vectors.S => esp_tee_vectors_plic.S} (99%) create mode 100644 components/esp_tee/subproject/main/ld/esp32c5/esp_tee.ld.in create mode 100644 components/esp_tee/subproject/main/soc/esp32c5/esp_tee_apm_prot_cfg.c create mode 100644 components/esp_tee/subproject/main/soc/esp32c5/esp_tee_pmp_pma_prot_cfg.c create mode 100644 components/esp_tee/subproject/main/soc/esp32c5/esp_tee_secure_sys_cfg.c create mode 100644 components/esp_tee/subproject/main/soc/esp32c5/include/esp_tee_intr_defs.h create mode 100644 components/esp_tee/subproject/main/soc/esp32c5/include/esp_tee_rv_utils.h diff --git a/components/esp_tee/CMakeLists.txt b/components/esp_tee/CMakeLists.txt index e3df1b47ce..fd39d792bf 100644 --- a/components/esp_tee/CMakeLists.txt +++ b/components/esp_tee/CMakeLists.txt @@ -6,8 +6,10 @@ idf_build_get_property(target IDF_TARGET) # headers & sources here are compiled into the app, not the esp_tee binary # (see subproject/ for the esp_tee binary build files) -# ESP-TEE is currently supported only on the ESP32-C6 and ESP32-H2 SoCs -if(NOT ${target} STREQUAL "esp32c6" AND NOT ${target} STREQUAL "esp32h2") +# ESP-TEE is currently supported only on the ESP32-C6, H2 and C5 SoCs +set(SUPPORTED_TARGETS "esp32c6" "esp32h2" "esp32c5") +if(NOT target IN_LIST SUPPORTED_TARGETS) + message(STATUS "ESP-TEE is currently supported only on the ${SUPPORTED_TARGETS} SoCs") return() endif() diff --git a/components/esp_tee/Kconfig.projbuild b/components/esp_tee/Kconfig.projbuild index 897491fc8c..3fbf151f87 100644 --- a/components/esp_tee/Kconfig.projbuild +++ b/components/esp_tee/Kconfig.projbuild @@ -1,5 +1,5 @@ menu "ESP-TEE (Trusted Execution Environment)" - depends on IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32H2 + depends on IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32H2 || IDF_TARGET_ESP32C5 config SECURE_ENABLE_TEE bool "Enable the ESP-TEE framework" diff --git a/components/esp_tee/include/private/esp_tee_binary.h b/components/esp_tee/include/private/esp_tee_binary.h index 40edae82ad..c66f3ad617 100644 --- a/components/esp_tee/include/private/esp_tee_binary.h +++ b/components/esp_tee/include/private/esp_tee_binary.h @@ -10,13 +10,17 @@ extern "C" { #endif +#include "soc/soc_caps.h" #include "sdkconfig.h" /* Declarations used inside TEE binary, only */ #define portNUM_PROCESSORS (1) #define configNUM_CORES (portNUM_PROCESSORS) -#define TEE_SECURE_INUM (14) +#define TEE_SECURE_INUM (31) +#if SOC_INT_CLIC_SUPPORTED +#define TEE_PASS_INUM (30) +#endif #define ESP_TEE_M2U_SWITCH_MAGIC 0xfedef diff --git a/components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml b/components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml new file mode 100644 index 0000000000..963bb6ef69 --- /dev/null +++ b/components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml @@ -0,0 +1,332 @@ +secure_services: + - family: misc + entries: + - id: 0 + type: custom + function: invalid_secure_service + args: 0 + # ID: 1-4 (4) - External memory (Flash) protection [SPI0] + - family: flash_protection_spi0 + entries: + - id: 1 + type: IDF + function: mmu_hal_map_region + args: 6 + - id: 2 + type: IDF + function: mmu_hal_unmap_region + args: 3 + - id: 3 + type: IDF + function: mmu_hal_vaddr_to_paddr + args: 4 + - id: 4 + type: IDF + function: mmu_hal_paddr_to_vaddr + args: 5 + - id: 5 + type: IDF + function: Cache_Set_IDROM_MMU_Size + args: 2 + # ID: 6-22 (17) - External memory (Flash) protection [SPI1] + - family: flash_protection_spi1 + entries: + - id: 6 + type: IDF + function: spi_flash_hal_check_status + args: 1 + - id: 7 + type: IDF + function: spi_flash_hal_common_command + args: 2 + - id: 8 + type: IDF + function: spi_flash_hal_device_config + args: 1 + - id: 9 + type: IDF + function: spi_flash_hal_erase_block + args: 2 + - id: 10 + type: IDF + function: spi_flash_hal_erase_chip + args: 1 + - id: 11 + type: IDF + function: spi_flash_hal_erase_sector + args: 2 + - id: 12 + type: IDF + function: spi_flash_hal_program_page + args: 4 + - id: 13 + type: IDF + function: spi_flash_hal_read + args: 4 + - id: 14 + type: IDF + function: spi_flash_hal_resume + args: 1 + - id: 15 + type: IDF + function: spi_flash_hal_set_write_protect + args: 2 + - id: 16 + type: IDF + function: spi_flash_hal_setup_read_suspend + args: 2 + - id: 17 + type: IDF + function: spi_flash_hal_supports_direct_read + args: 2 + - id: 18 + type: IDF + function: spi_flash_hal_supports_direct_write + args: 2 + - id: 19 + type: IDF + function: spi_flash_hal_suspend + args: 1 + - id: 20 + type: IDF + function: bootloader_flash_execute_command_common + args: 7 + - id: 21 + type: IDF + function: memspi_host_flush_cache + args: 3 + - id: 22 + type: IDF + function: spi_flash_chip_generic_config_host_io_mode + args: 2 + # ID: 30-53 (24) - Interrupt Handling + - family: interrupt_handling + entries: + - id: 30 + type: IDF + function: esp_rom_route_intr_matrix + args: 3 + - id: 31 + type: IDF + function: rv_utils_intr_enable + args: 1 + - id: 32 + type: IDF + function: rv_utils_intr_disable + args: 1 + - id: 33 + type: IDF + function: rv_utils_intr_set_priority + args: 2 + - id: 34 + type: IDF + function: rv_utils_intr_set_type + args: 2 + - id: 35 + type: IDF + function: rv_utils_intr_set_threshold + args: 1 + - id: 36 + type: IDF + function: rv_utils_intr_edge_ack + args: 1 + - id: 37 + type: IDF + function: rv_utils_intr_global_enable + args: 0 + - id: 38 + type: IDF + function: rv_utils_intr_get_enabled_mask + args: 0 + - id: 39 + type: IDF + function: rv_utils_set_cycle_count + args: 1 + - id: 40 + type: IDF + function: rv_utils_en_branch_predictor + args: 0 + - id: 41 + type: IDF + function: rv_utils_dis_branch_predictor + args: 0 + - id: 42 + type: IDF + function: rv_utils_wfe_mode_enable + args: 1 + - id: 43 + type: IDF + function: esprv_int_set_vectored + args: 2 + # ID: 54-85 (32) - HAL + - family: hal + entries: + - id: 54 + type: IDF + function: wdt_hal_init + args: 4 + - id: 55 + type: IDF + function: wdt_hal_deinit + args: 1 + # ID: 86-133 (48) - Crypto + - family: crypto + entries: + - id: 86 + type: IDF + function: esp_aes_intr_alloc + args: 0 + - id: 87 + type: IDF + function: esp_aes_crypt_cbc + args: 6 + - id: 88 + type: IDF + function: esp_aes_crypt_cfb8 + args: 6 + - id: 89 + type: IDF + function: esp_aes_crypt_cfb128 + args: 7 + - id: 90 + type: IDF + function: esp_aes_crypt_ctr + args: 7 + - id: 91 + type: IDF + function: esp_aes_crypt_ecb + args: 4 + - id: 92 + type: IDF + function: esp_aes_crypt_ofb + args: 6 + - id: 93 + type: IDF + function: esp_sha + args: 4 + - id: 94 + type: IDF + function: esp_sha_block + args: 3 + - id: 95 + type: IDF + function: esp_sha_dma + args: 6 + - id: 96 + type: IDF + function: esp_sha_read_digest_state + args: 2 + - id: 97 + type: IDF + function: esp_sha_write_digest_state + args: 2 + - id: 98 + type: IDF + function: esp_crypto_sha_enable_periph_clk + args: 1 + - id: 99 + type: IDF + function: esp_hmac_calculate + args: 4 + - id: 100 + type: IDF + function: esp_hmac_jtag_enable + args: 2 + - id: 101 + type: IDF + function: esp_hmac_jtag_disable + args: 0 + - id: 102 + type: IDF + function: esp_ds_sign + args: 4 + - id: 103 + type: IDF + function: esp_ds_start_sign + args: 4 + - id: 104 + type: IDF + function: esp_ds_is_busy + args: 0 + - id: 105 + type: IDF + function: esp_ds_finish_sign + args: 2 + - id: 106 + type: IDF + function: esp_ds_encrypt_params + args: 4 + - id: 107 + type: IDF + function: esp_crypto_mpi_enable_periph_clk + args: 1 + - id: 108 + type: IDF + function: esp_ecc_point_multiply + args: 4 + - id: 109 + type: IDF + function: esp_ecc_point_verify + args: 1 + - id: 110 + type: IDF + function: esp_crypto_ecc_enable_periph_clk + args: 1 + - id: 111 + type: IDF + function: esp_sha_set_mode + args: 1 + - id: 112 + type: IDF + function: esp_sha_512_t_init_hash + args: 1 + # ID: 134-169 (36) - Reserved for future use + - family: attestation + entries: + - id: 170 + type: custom + function: esp_tee_att_generate_token + args: 6 + # ID: 175-194 (20) - Secure Storage + - family: secure_storage + entries: + - id: 175 + type: custom + function: esp_tee_sec_storage_clear_key + args: 1 + - id: 176 + type: custom + function: esp_tee_sec_storage_gen_key + args: 1 + - id: 177 + type: custom + function: esp_tee_sec_storage_ecdsa_sign + args: 4 + - id: 178 + type: custom + function: esp_tee_sec_storage_ecdsa_get_pubkey + args: 2 + - id: 179 + type: custom + function: esp_tee_sec_storage_aead_encrypt + args: 4 + - id: 180 + type: custom + function: esp_tee_sec_storage_aead_decrypt + args: 4 + # ID: 195-199 (5) - OTA + - family: ota + entries: + - id: 195 + type: custom + function: esp_tee_ota_begin + args: 0 + - id: 196 + type: custom + function: esp_tee_ota_write + args: 3 + - id: 197 + type: custom + function: esp_tee_ota_end + args: 0 + # ID: 200+ - User-defined diff --git a/components/esp_tee/src/esp_secure_service_wrapper.c b/components/esp_tee/src/esp_secure_service_wrapper.c index a993f46765..da4f557c85 100644 --- a/components/esp_tee/src/esp_secure_service_wrapper.c +++ b/components/esp_tee/src/esp_secure_service_wrapper.c @@ -20,6 +20,7 @@ #include "esp_flash.h" #include "soc/soc_caps.h" +#include "sdkconfig.h" #include "esp_tee.h" #include "secure_service_num.h" @@ -31,6 +32,13 @@ void IRAM_ATTR __wrap_esp_rom_route_intr_matrix(int cpu_no, uint32_t model_num, esp_tee_service_call(4, SS_ESP_ROM_ROUTE_INTR_MATRIX, cpu_no, model_num, intr_num); } +#if SOC_INT_CLIC_SUPPORTED +void IRAM_ATTR __wrap_esprv_int_set_vectored(int rv_int_num, bool vectored) +{ + esp_tee_service_call(3, SS_ESPRV_INT_SET_VECTORED, rv_int_num, vectored); +} +#endif + /* ---------------------------------------------- RTC_WDT ------------------------------------------------- */ void __wrap_wdt_hal_init(wdt_hal_context_t *hal, wdt_inst_t wdt_inst, uint32_t prescaler, bool enable_intr) @@ -222,6 +230,13 @@ void __wrap_esp_crypto_sha_enable_periph_clk(bool enable) esp_tee_service_call(2, SS_ESP_CRYPTO_SHA_ENABLE_PERIPH_CLK, enable); } +#if SOC_SHA_SUPPORT_SHA512_T +int __wrap_esp_sha_512_t_init_hash(uint16_t t) +{ + return esp_tee_service_call(2, SS_ESP_SHA_512_T_INIT_HASH, t); +} +#endif + /* ---------------------------------------------- HMAC ------------------------------------------------- */ esp_err_t __wrap_esp_hmac_calculate(hmac_key_id_t key_id, const void *message, size_t message_len, uint8_t *hmac) @@ -365,6 +380,25 @@ bool IRAM_ATTR __wrap_mmu_hal_paddr_to_vaddr(uint32_t mmu_id, uint32_t paddr, mm return esp_tee_service_call(6, SS_MMU_HAL_PADDR_TO_VADDR, mmu_id, paddr, target, type, out_vaddr); } +/** + * NOTE: This ROM-provided API is intended to configure the Cache MMU size for + * instruction (irom) and rodata (drom) sections in flash. + * + * On ESP32-C5, it also sets the start pages for flash irom and drom sections, + * which involves accessing MMU registers directly. + * + * However, these MMU registers are protected by the APM and direct access + * from the REE results in a fault. + * + * To prevent this, we wrap this function to be routed as a TEE service call. + */ +#if CONFIG_IDF_TARGET_ESP32C5 +void IRAM_ATTR __wrap_Cache_Set_IDROM_MMU_Size(uint32_t irom_size, uint32_t drom_size) +{ + esp_tee_service_call(3, SS_CACHE_SET_IDROM_MMU_SIZE, irom_size, drom_size); +} +#endif + #if CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1 /* ---------------------------------------------- SPI Flash HAL ------------------------------------------------- */ diff --git a/components/esp_tee/src/esp_tee_u2m_switch.S b/components/esp_tee/src/esp_tee_u2m_switch.S index ae53876c3d..62cf3bd266 100644 --- a/components/esp_tee/src/esp_tee_u2m_switch.S +++ b/components/esp_tee/src/esp_tee_u2m_switch.S @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,6 +8,6 @@ .global _u2m_switch .type _u2m_switch, @function _u2m_switch: - ecall - fence - ret + ecall + fence + ret diff --git a/components/esp_tee/subproject/components/attestation/esp_att_utils_part_info.c b/components/esp_tee/subproject/components/attestation/esp_att_utils_part_info.c index 46d8f8597e..bdab8b5fd0 100644 --- a/components/esp_tee/subproject/components/attestation/esp_att_utils_part_info.c +++ b/components/esp_tee/subproject/components/attestation/esp_att_utils_part_info.c @@ -100,7 +100,7 @@ esp_err_t get_flash_contents_sha256(uint32_t flash_offset, uint32_t len, uint8_t uint32_t mmap_len = MIN(len, partial_image_len); const void *image = esp_tee_flash_mmap(flash_offset, mmap_len); if (image == NULL) { - mbedtls_sha256_finish(&ctx, NULL); + mbedtls_sha256_free(&ctx); return ESP_FAIL; } mbedtls_sha256_update(&ctx, image, mmap_len); diff --git a/components/esp_tee/subproject/main/CMakeLists.txt b/components/esp_tee/subproject/main/CMakeLists.txt index 9127646233..83a77c34ce 100644 --- a/components/esp_tee/subproject/main/CMakeLists.txt +++ b/components/esp_tee/subproject/main/CMakeLists.txt @@ -14,8 +14,13 @@ set(srcs "core/esp_tee_init.c" "core/esp_secure_service_table.c") # Arch specific implementation for TEE -list(APPEND srcs "arch/${arch}/esp_tee_vectors.S" - "arch/${arch}/esp_tee_vector_table.S") +if(CONFIG_SOC_INT_PLIC_SUPPORTED) + list(APPEND srcs "arch/${arch}/esp_tee_vectors_plic.S" + "arch/${arch}/esp_tee_vector_table_plic.S") +elseif(CONFIG_SOC_INT_CLIC_SUPPORTED) + list(APPEND srcs "arch/${arch}/esp_tee_vectors_clic.S" + "arch/${arch}/esp_tee_vector_table_clic.S") +endif() # SoC specific implementation for TEE list(APPEND srcs "soc/${target}/esp_tee_secure_sys_cfg.c" diff --git a/components/esp_tee/subproject/main/arch/riscv/esp_tee_vector_table_clic.S b/components/esp_tee/subproject/main/arch/riscv/esp_tee_vector_table_clic.S new file mode 100644 index 0000000000..98e728dab8 --- /dev/null +++ b/components/esp_tee/subproject/main/arch/riscv/esp_tee_vector_table_clic.S @@ -0,0 +1,107 @@ +/* + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "sdkconfig.h" +#include "soc/soc.h" + +/* The system interrupts are not used for now, so trigger a panic every time one occurs. */ +#define _system_int_handler _tee_panic_handler + + /* Handlers defined in the `vector.S` file, common to all RISC-V targets */ + .global _tee_ns_intr_handler + .global _tee_panic_handler + + .section .exception_vectors_table.text + + /* Prevent the compiler from generating 2-byte instruction in the vector tables */ + .option push + .option norvc + + /** + * Non-hardware vectored interrupt entry. MTVEC CSR points here. + * + * On targets that use CLIC as their interrupt controller, when an exception occurs, the CPU + * jumps to the address stored in MTVEC[31:6] << 6. The CPU will also jump to this location + * if an interrupt is configured as non-vectored (CLIC_INT_ATTR.shv = 0). + * + * Because of the left-shift `<< 6`, this entry must be aligned on 64. + */ + .global _vector_table + .type _vector_table, @function + .balign 0x40 +_vector_table: + j _tee_panic_handler + .size _vector_table, .-_vector_table + + + /** + * Vectored interrupt table. MTVT CSR points here. + * + * If an interrupt occurs and is configured as (hardware) vectored, the CPU will jump to + * MTVT[31:0] + 4 * interrupt_id + * + * In the case of the ESP32P4, the interrupt matrix, between the CPU interrupt lines + * and the peripherals, offers 32 lines. As such, the interrupt_id between 0 and 31. + * + * Since the interrupts are initialized as vectored on CPU start, we can manage the special + * interrupts ETS_T1_WDT_INUM, ETS_CACHEERR_INUM and ETS_MEMPROT_ERR_INUM here. + */ + .balign 0x40 + .global _mtvt_table + .type _mtvt_table, @function +_mtvt_table: + .word _system_int_handler /* 0: System interrupt number. Exceptions are non-vectored, won't load this. */ + .word _system_int_handler /* 1: System interrupt number */ + .word _system_int_handler /* 2: System interrupt number */ + .word _system_int_handler /* 3: System interrupt number */ + .word _system_int_handler /* 4: System interrupt number */ + .word _system_int_handler /* 5: System interrupt number */ + .word _system_int_handler /* 6: System interrupt number */ + .word _system_int_handler /* 7: System interrupt number */ + .word _system_int_handler /* 8: System interrupt number */ + .word _system_int_handler /* 9: System interrupt number */ + .word _system_int_handler /* 10: System interrupt number */ + .word _system_int_handler /* 11: System interrupt number */ + .word _system_int_handler /* 12: System interrupt number */ + .word _system_int_handler /* 13: System interrupt number */ + .word _system_int_handler /* 14: System interrupt number */ + .word _system_int_handler /* 15: System interrupt number */ + .word _tee_ns_intr_handler /* 16: Free interrupt number */ + .word _tee_ns_intr_handler /* 17: Free interrupt number */ + .word _tee_ns_intr_handler /* 18: Free interrupt number */ + .word _tee_ns_intr_handler /* 19: Free interrupt number */ + .word _tee_ns_intr_handler /* 20: Free interrupt number */ + .word _tee_ns_intr_handler /* 21: Free interrupt number */ + .word _tee_ns_intr_handler /* 22: Free interrupt number */ + .word _tee_ns_intr_handler /* 23: Free interrupt number */ + .word _tee_ns_intr_handler /* 24: Free interrupt number */ + .word _tee_ns_intr_handler /* 25: Free interrupt number */ + .word _tee_ns_intr_handler /* 26: Free interrupt number */ + .word _tee_ns_intr_handler /* 27: Free interrupt number */ + .word _tee_ns_intr_handler /* 28: Free interrupt number */ + .word _tee_ns_intr_handler /* 29: Free interrupt number */ + .word _tee_ns_intr_handler /* 30: Free interrupt number */ + .word _tee_ns_intr_handler /* 31: Free interrupt number */ + .word _tee_ns_intr_handler /* 32: Free interrupt number */ + .word _tee_ns_intr_handler /* 33: Free interrupt number */ + .word _tee_ns_intr_handler /* 34: Free interrupt number */ + .word _tee_ns_intr_handler /* 35: Free interrupt number */ + .word _tee_ns_intr_handler /* 36: Free interrupt number */ + .word _tee_ns_intr_handler /* 37: Free interrupt number */ + .word _tee_ns_intr_handler /* 38: Free interrupt number */ + .word _tee_ns_intr_handler /* 39: Free interrupt number */ + .word _tee_panic_handler /* 40: ETS_INT_WDT_INUM (+16) panic-interrupt (soc-level panic) */ + .word _tee_panic_handler /* 41: ETS_CACHEERR_INUM (+16) panic-interrupt (soc-level panic) */ + /* NOTE: Triggers panic irrespective of the Kconfig setting with ESP-TEE */ + .word _tee_panic_handler /* 42: ETS_MEMPROT_ERR_INUM (+16) handler (soc-level panic) */ + /* TODO: [IDF-10770] Not supported yet with ESP-TEE */ + .word _tee_panic_handler /* 43: ETS_ASSIST_DEBUG_INUM (+16) handler (soc-level panic) */ + .word _tee_ns_intr_handler /* 44: ETS_IPC_ISR_INUM (+16) handler*/ + .word _tee_ns_intr_handler /* 45: Free interrupt number */ + .word _tee_ns_intr_handler /* 46: ESP-TEE: U-mode interrupt delegation entry */ + .word _tee_s_intr_handler /* 47: ESP-TEE: Secure interrupt handler entry */ + + .size _mtvt_table, .-_mtvt_table + .option pop diff --git a/components/esp_tee/subproject/main/arch/riscv/esp_tee_vector_table.S b/components/esp_tee/subproject/main/arch/riscv/esp_tee_vector_table_plic.S similarity index 96% rename from components/esp_tee/subproject/main/arch/riscv/esp_tee_vector_table.S rename to components/esp_tee/subproject/main/arch/riscv/esp_tee_vector_table_plic.S index 9826ea129c..d985c64e08 100644 --- a/components/esp_tee/subproject/main/arch/riscv/esp_tee_vector_table.S +++ b/components/esp_tee/subproject/main/arch/riscv/esp_tee_vector_table_plic.S @@ -51,7 +51,7 @@ _vector_table: j _tee_ns_intr_handler /* 11: Free interrupt number */ j _tee_ns_intr_handler /* 12: Free interrupt number */ j _tee_ns_intr_handler /* 13: Free interrupt number */ - j _tee_s_intr_handler /* 14: ESP-TEE: Secure interrupt handler entry */ + j _tee_ns_intr_handler /* 14: Free interrupt number */ j _tee_ns_intr_handler /* 15: Free interrupt number */ j _tee_ns_intr_handler /* 16: Free interrupt number */ j _tee_ns_intr_handler /* 17: Free interrupt number */ @@ -70,7 +70,7 @@ _vector_table: j _tee_ns_intr_handler /* 28: Free interrupt number */ j _tee_ns_intr_handler /* 29: Free interrupt number */ j _tee_ns_intr_handler /* 30: Free interrupt number */ - j _tee_ns_intr_handler /* 31: Free interrupt number */ + j _tee_s_intr_handler /* 31: ESP-TEE: Secure interrupt handler entry */ j _panic_handler /* exception handler, entry 0 */ .size _vector_table, .-_vector_table diff --git a/components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors_clic.S b/components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors_clic.S new file mode 100644 index 0000000000..c511506c9e --- /dev/null +++ b/components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors_clic.S @@ -0,0 +1,628 @@ +/* + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/soc.h" +#include "soc/soc_caps.h" +#include "soc/clic_reg.h" + +#include "riscv/encoding.h" +#include "riscv/rvruntime-frames.h" +#include "esp_private/vectors_const.h" + +#include "esp_tee.h" +#include "esp_tee_intr_defs.h" +#include "sdkconfig.h" + + .equ SAVE_REGS, 32 + .equ CONTEXT_SIZE, (SAVE_REGS * 4) + .equ panic_from_exception, tee_panic_from_exc + .equ panic_from_isr, tee_panic_from_isr + .equ MAGIC, 0x1f + .equ RTNVAL, 0xc0de + .equ ECALL_U_MODE, 0x8 + .equ ECALL_M_MODE, 0xb + .equ CSR_UINTTHRESH, 0x047 + + .global esp_tee_global_interrupt_handler + .global esp_tee_service_dispatcher + .global _tee_s_entry + + .section .data + + .align 4 + .global _ns_sp +_ns_sp: + .word 0 + + .align 4 + .global _s_sp +_s_sp: + .word 0 + +/* 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, mtval + sw t0, RV_STK_MTVAL(sp) + csrr t0, mhartid + sw t0, RV_STK_MHARTID(sp) + csrr t0, mcause + sw t0, RV_STK_MCAUSE(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 store_magic_general_regs + lui ra, MAGIC + lui tp, MAGIC + lui t0, MAGIC + lui t1, MAGIC + lui t2, MAGIC + lui s0, MAGIC + lui s1, MAGIC + lui a0, MAGIC + lui a1, MAGIC + lui a2, MAGIC + lui a3, MAGIC + lui a4, MAGIC + lui a5, MAGIC + lui a6, MAGIC + lui a7, MAGIC + lui s2, MAGIC + lui s3, MAGIC + lui s4, MAGIC + lui s5, MAGIC + lui s6, MAGIC + lui s7, MAGIC + lui s8, MAGIC + lui s9, MAGIC + lui s10, MAGIC + lui s11, MAGIC + lui t3, MAGIC + lui t4, MAGIC + lui t5, MAGIC + lui t6, MAGIC +.endm + + .section .exception_vectors.text, "ax" + + /* Exception handler. */ + .global _tee_panic_handler + .type _tee_panic_handler, @function +_tee_panic_handler: + /* Exception handler. */ + .global _panic_handler + .type _panic_handler, @function +_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_INTBIT_MASK | 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, _machine_ecall + + /* Check whether the exception is an U-mode ecall */ + li t1, ECALL_U_MODE + beq t0, t1, _user_ecall + + /* Restore t0, t1 from the stack */ + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 16 + +_actual_panic: + /* Not an ecall, proceed to the panic handler */ + /* Allocate space on the stack and store general purpose registers */ + save_general_regs RV_STK_FRMSZ + + /* As gp register is not saved by the macro, save it here */ + sw gp, RV_STK_GP(sp) + + /* Same goes for the SP value before trapping */ + addi t0, sp, RV_STK_FRMSZ /* restore sp with the value when trap happened */ + + /* Save CSRs */ + sw t0, RV_STK_SP(sp) + save_mepc + save_mcsr + + /* Keep mcause in s0, only the exception code and interrupt bit are relevant */ + csrr s0, mcause + li t1, VECTORS_MCAUSE_INTBIT_MASK | VECTORS_MCAUSE_REASON_MASK + and s0, s0, t1 + + /* Call panic_from_exception(sp) or panic_from_isr(sp) + * depending on whether we have a pseudo excause or not. + * If mcause's highest bit is 1, then an interrupt called this routine, + * so we have a pseudo excause. Else, it is due to a exception, we don't + * have an pseudo excause */ + mv a0, sp + mv a1, s0 + /* Branches instructions don't accept immediates values, so use t1 to + * store our comparator */ + li t0, 0x80000000 + bgeu a1, t0, _call_panic_handler + sw a1, RV_STK_MCAUSE(sp) + /* exception_from_panic never returns */ + jal panic_from_exception + /* We arrive here if the exception handler has returned. */ + j _return_from_exception + +_call_panic_handler: + /* Remove highest bit from mcause (a1) register and save it in the + * structure */ + not t0, t0 + and a1, a1, t0 +#if CONFIG_SOC_INT_CLIC_SUPPORTED + /* When CLIC is supported, external interrupts are shifted by 16, deduct this difference from mcause */ + add a1, a1, -16 +#endif // CONFIG_SOC_INT_CLIC_SUPPORTED + sw a1, RV_STK_MCAUSE(sp) + jal panic_from_isr + + /* We arrive here if the exception handler has returned. This means that + * the exception was handled, and the execution flow should resume. + * Restore the registers and return from the exception. + */ +_return_from_exception: + restore_mepc + /* MTVEC and SP are assumed to be unmodified. + * MSTATUS, MHARTID, MTVAL are read-only and not restored. */ + lw gp, RV_STK_GP(sp) + restore_general_regs RV_STK_FRMSZ + mret + + .size _panic_handler, .-_panic_handler + + /* ECALL handler. */ + .type _ecall_handler, @function +_ecall_handler: + /* M-mode ecall handler */ +_machine_ecall: + /* Enable the U-mode delegation of all interrupts */ + li t0, INTMTX_SIG_IDX_ASSERT_IN_SEC_REG + li t1, 0x00 + sw t1, 0(t0) + fence + /* Verify the above */ +_1: + lw t2, 0(t0) + bne t2, t1, _2 + + /* Set the privilege mode to transition to after mret to U-mode */ + li t0, MSTATUS_MPP + csrc mstatus, t0 + + /* Check whether this is the first M-mode ecall (see esp_tee_init) and skip context restoration */ + lui t0, ESP_TEE_M2U_SWITCH_MAGIC + beq a1, t0, _skip_ctx_restore + + /* Switching back to the saved REE stack */ + la t0, _ns_sp + lw sp, 0(t0) + fence + + /* Backup the A0 register + * This point is reached after an ecall is triggered after executing the secure service. + * The A0 register contains the return value of the corresponding service. + * After restoring the entire register context, we assign A0 the value back to the return value. */ + csrw mscratch, a0 + restore_general_regs + csrrw a0, mscratch, zero + +_skip_ctx_restore: + /* Copy the ra register to mepc which contains the user app entry point (i.e. call_start_cpu0) */ + csrw mepc, ra + + /* Jump to the REE */ + mret + + /* U-mode ecall handler */ +_user_ecall: + /* Check whether we are returning after servicing an U-mode interrupt */ + lui t0, RTNVAL + csrrw t1, mscratch, zero + beq t0, t1, _rtn_from_ns_int + + /* Restore t0, t1 from the stack */ + lw t0, 0(sp) + lw t1, 4(sp) + addi sp, sp, 16 + + /* This point is reached when a secure service call is issued from the REE */ + /* Save register context and mepc */ + save_general_regs + save_mepc + + /* Save the U-mode (i.e. REE) stack pointer */ + la t0, _ns_sp + sw sp, 0(t0) + + /* Switch to the M-mode (i.e. TEE) stack */ + la sp, _tee_stack + + /* Load the TEE entry point (see _tee_s_entry) in the mepc */ + la t0, _tee_s_entry + csrw mepc, t0 + + /* Disable the U-mode delegation of all interrupts */ + li t0, INTMTX_SIG_IDX_ASSERT_IN_SEC_REG + li t1, TEE_PASS_INUM + CLIC_EXT_INTR_NUM_OFFSET + sw t1, 0(t0) + fence + /* Verify the above */ +_2: + lw t2, 0(t0) + bne t2, t1, _2 + + /* Set the privilege mode to transition to after mret to M-mode */ + li t0, MSTATUS_MPP + csrs mstatus, t0 + + mret + + /* This point is reached after servicing a U-mode interrupt occurred + * while executing a secure service */ +_rtn_from_ns_int: + /* Disable the U-mode interrupt delegation */ + li t0, INTMTX_SIG_IDX_ASSERT_IN_SEC_REG + li t1, TEE_PASS_INUM + CLIC_EXT_INTR_NUM_OFFSET + sw t1, 0(t0) + fence + /* Verify the above */ +_3: + lw t2, 0(t0) + bne t2, t1, _2 + + /* Restore the secure stack pointer */ + la t0, _s_sp + lw sp, 0(t0) + + /* Set the privilege mode to transition to after mret to M-mode */ + li t0, MSTATUS_MPP + csrs mstatus, t0 + + /* Restore register context and resume the secure service */ + restore_mepc + restore_general_regs + + mret + + .size _ecall_handler, .-_ecall_handler + + /* This is the interrupt handler for the U-mode interrupts. + * It saves the registers on the stack, re-enables the interrupt delegation, + * then jumps to the U-mode global interrupt handler, */ + .global _tee_ns_intr_handler + .type _tee_ns_intr_handler, @function +_tee_ns_intr_handler: + /* Start by saving the general purpose registers and the PC value before + * the interrupt happened. */ + save_general_regs + save_mepc + + /* Though it is not necessary we save GP and SP here. + * SP is necessary to help GDB to properly unwind + * the backtrace of threads preempted by interrupts (OS tick etc.). + * GP is saved just to have its proper value in GDB. */ + /* As gp register is not saved by the macro, save it here */ + sw gp, RV_STK_GP(sp) + /* Same goes for the SP value before trapping */ + addi t0, sp, CONTEXT_SIZE /* restore sp with the value when interrupt happened */ + /* Save SP */ + sw t0, RV_STK_SP(sp) + + /* + * NOTE: Since this is a delegated U-mode interrupt routed through M-mode, the U-mode CSRs + * (like ucause, uintstatus, and uintthresh) are not automatically populated by hardware. + * + * To correctly simulate the U-mode interrupt context, we must explicitly update: + * - ucause: to reflect the interrupt source (including EXCCODE, INTBIT, and PIE). + * - uintthresh: to the level of the interrupt being serviced. + * + * uintstatus is read-only and will be zero in this scenario. + * However, CLIC uses max(uintstatus.uil, uintthresh.th) to determine active interrupt level. + * So, setting uintthresh to the current interrupt level ensures that only higher-priority + * U-mode interrupts can preempt while this one is being handled. + */ + /* Pass the interrupt ID to be serviced to U-mode */ + li t2, INTMTX_SEC_STATUS_REG + lw t0, 0(t2) + li t1, 0 + +_find_intr_loop: + and t2, t0, 1 + bnez t2, _found_intr + srai t0, t0, 1 + addi t1, t1, 1 + bnez t0, _find_intr_loop + + /* should not reach here */ + li t1, -1 + unimp +_found_intr: + addi t6, t1, CLIC_EXT_INTR_NUM_OFFSET + + /* Update ucause */ + csrr t0, ucause + li t1, VECTORS_MCAUSE_REASON_MASK + not t1, t1 + and t0, t0, t1 + or t0, t0, t6 + li t1, VECTORS_MCAUSE_INTBIT_MASK + or t0, t0, t1 + csrw ucause, t0 + + /* Update the new the U-mode interrupt threshold */ + li t1, DR_REG_CLIC_CTRL_BASE + slli t2, t6, 2 + add t1, t1, t2 + lw t2, 0(t1) + fence + srli t2, t2, CLIC_INT_CTL_S + csrw CSR_UINTTHRESH, t2 + + /* Enable the U-mode interrupt delegation */ + li t0, INTMTX_SIG_IDX_ASSERT_IN_SEC_REG + li t1, 0x00 + sw t1, 0(t0) + fence + /* Verify the above */ +_4: + lw t2, 0(t0) + bne t2, t1, _2 + + /* For U-mode interrupts, we use mret to switch to U-mode after executing the below steps - */ + /* Disable the U-mode global interrupts */ + csrci ustatus, USTATUS_UIE + + /* Configure `uepc` with the U-mode ecall handler (see u2m_switch) so that we can + * return to M-mode after handling the interrupt */ + la t0, esp_tee_app_config + lw t1, ESP_TEE_CFG_OFFS_NS_ENTRY_ADDR(t0) + csrw uepc, t1 + + /* Set the program counter to the U-mode global interrupt handler (see _interrupt_handler) */ + lw t1, ESP_TEE_CFG_OFFS_NS_INTR_HANDLER(t0) + csrw mepc, t1 + + /* Set the privilege mode to transition to after mret to U-mode */ + li t1, MSTATUS_MPP + csrc mstatus, t1 + + /* Save the current secure stack pointer and switch to the U-mode interrupt stack + * saved while entering the secure service call routine (see `sec_world_entry`) */ + la t0, _s_sp + sw sp, 0(t0) + la t1, _ns_sp + lw sp, 0(t1) + + /* Set a flag to identify the next U2M switch would be after handling a U-mode interrupt */ + lui t0, RTNVAL + csrw mscratch, t0 + + /* Place magic bytes in all the general registers */ + store_magic_general_regs + + mret + + .size _tee_ns_intr_handler, .-_tee_ns_intr_handler + + /* This is the interrupt handler for the M-mode interrupts. + * It saves the registers on the stack, prepares for interrupt nesting, + * re-enables the interrupts, then jumps to the C dispatcher in esp_tee_intr.c. */ + .global _tee_s_intr_handler + .type _tee_s_intr_handler, @function +_tee_s_intr_handler: + /* Start by saving the general purpose registers and the PC value before + * the interrupt happened. */ + save_general_regs RV_STK_FRMSZ + save_mepc + + /* Though it is not necessary we save GP and SP here. + * SP is necessary to help GDB to properly unwind + * the backtrace of threads preempted by interrupts (OS tick etc.). + * GP is saved just to have its proper value in GDB. */ + /* As gp register is not saved by the macro, save it here */ + sw gp, RV_STK_GP(sp) + /* Same goes for the SP value before trapping */ + addi t0, sp, RV_STK_FRMSZ /* restore sp with the value when interrupt happened */ + /* Save SP */ + sw t0, RV_STK_SP(sp) + + /* Check if the interrupt source is related to an APM exception */ + /* Define the addresses of the registers */ + li t0, INTMTX_STATUS_REG_0 + /* Load the values from the registers */ + lw t1, 0(t0) + /* Define the masks */ + li t2, TEE_SECURE_INT_APM_MASK_0 + /* Apply the masks */ + and t1, t1, t2 + /* Check if any of the masked bits are set */ + bnez t1, _save_reg_ctx + + /* Repeat for the other status register */ + li t0, INTMTX_STATUS_REG_1 + lw t1, 0(t0) + li t2, TEE_SECURE_INT_APM_MASK_1 + and t1, t1, t2 + bnez t1, _save_reg_ctx + + /* Continue normal execution */ + j _continue + +_save_reg_ctx: + /* Save CSR context here */ + save_mcsr + /* NOTE: With ESP-TEE, since APM violations trigger a panic, it's safe to use the mscratch + * register to pass on the stack pointer to the APM violation handler */ + csrw mscratch, sp + j _intr_hdlr_exec + +_continue: + /* Before doing anything preserve the stack pointer */ + mv s11, sp + /* Switch to the TEE interrupt stack */ + la sp, _tee_intr_stack + /* 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 + + /* TODO: [IDF-9972] Nested interrupts are not supported yet */ + # csrsi mstatus, MSTATUS_MIE + # /* MIE set. Nested interrupts can now occur */ + + #ifdef CONFIG_PM_TRACE + li a0, 0 /* = ESP_PM_TRACE_IDLE */ + #if SOC_CPU_CORES_NUM == 1 + li a1, 0 /* No need to check core ID on single core hardware */ + #else + csrr a1, mhartid + #endif + la t0, esp_pm_trace_exit + jalr t0 /* absolute jump, avoid the 1 MiB range constraint */ + #endif + + #ifdef CONFIG_PM_ENABLE + la t0, esp_pm_impl_isr_hook + jalr t0 /* absolute jump, avoid the 1 MiB range constraint */ + #endif + +_intr_hdlr_exec: + /* 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_INTBIT_MASK | VECTORS_MCAUSE_REASON_MASK + and a1, a1, t0 + + jal esp_tee_global_interrupt_handler + + /* TODO: [IDF-9972] Nested interrupts are not supported yet */ + # csrci mstatus, MSTATUS_MIE + # /* MIE cleared. Nested interrupts are disabled */ + + /* restore the rest of the registers */ + csrw mcause, s1 + csrw mstatus, s2 + + /* Restoring the stack pointer */ + mv sp, s11 + + restore_mepc + restore_general_regs RV_STK_FRMSZ + /* exit, this will also re-enable the interrupts */ + mret + + .size _tee_s_intr_handler, .-_tee_s_intr_handler + + .section .text, "ax" + + .align 4 + .type _tee_s_entry, @function +_tee_s_entry: + /* Jump to the secure service dispatcher */ + jal esp_tee_service_dispatcher + + /* Fire an M-ecall */ + mv a1, zero + ecall + fence + + .size _tee_s_entry, .-_tee_s_entry diff --git a/components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors.S b/components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors_plic.S similarity index 99% rename from components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors.S rename to components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors_plic.S index bc797366a6..88b4a6ca4d 100644 --- a/components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors.S +++ b/components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors_plic.S @@ -23,7 +23,7 @@ .equ RTNVAL, 0xc0de .equ ECALL_U_MODE, 0x8 .equ ECALL_M_MODE, 0xb - .equ TEE_INTR_DELEG_MASK, 0xffffbfff + .equ TEE_INTR_DELEG_MASK, ~(1U << TEE_SECURE_INUM) .global esp_tee_global_interrupt_handler .global esp_tee_service_dispatcher diff --git a/components/esp_tee/subproject/main/common/multi_heap.c b/components/esp_tee/subproject/main/common/multi_heap.c index 985bbfde47..4261bd73dd 100644 --- a/components/esp_tee/subproject/main/common/multi_heap.c +++ b/components/esp_tee/subproject/main/common/multi_heap.c @@ -39,22 +39,37 @@ static void assert_valid_block(const heap_t *heap, const block_header_t *block) esp_err_t esp_tee_heap_init(void *start_ptr, size_t size) { assert(start_ptr); - if (size < (tlsf_size() + tlsf_block_size_min() + sizeof(heap_t))) { - // Region too small to be a heap. + + heap_t *result = (heap_t *)start_ptr; + size_t usable_size = size - sizeof(heap_t); + +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 + bool too_small = (usable_size < tlsf_size() + tlsf_block_size_min()); +#else + bool too_small = (size < sizeof(heap_t)); +#endif + + if (too_small) { return ESP_ERR_INVALID_SIZE; } - heap_t *result = (heap_t *)start_ptr; - size -= sizeof(heap_t); +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 + void *heap = tlsf_create_with_pool(start_ptr + sizeof(heap_t), usable_size); + size_t overhead = tlsf_size(); +#else + size_t max_bytes = 0; + void *heap = tlsf_create_with_pool(start_ptr + sizeof(heap_t), usable_size, max_bytes); + size_t overhead = tlsf_size(heap); +#endif - result->heap_data = tlsf_create_with_pool(start_ptr + sizeof(heap_t), size); - if (result->heap_data == NULL) { + if (heap == NULL) { return ESP_FAIL; } + result->heap_data = heap; result->lock = NULL; - result->free_bytes = size - tlsf_size(); - result->pool_size = size; + result->free_bytes = usable_size - overhead; + result->pool_size = usable_size; result->minimum_free_bytes = result->free_bytes; tee_heap = (multi_heap_handle_t)result; diff --git a/components/esp_tee/subproject/main/common/panic/esp_tee_panic.c b/components/esp_tee/subproject/main/common/panic/esp_tee_panic.c index a4911bace1..3fee6d506e 100644 --- a/components/esp_tee/subproject/main/common/panic/esp_tee_panic.c +++ b/components/esp_tee/subproject/main/common/panic/esp_tee_panic.c @@ -10,13 +10,21 @@ #include "esp_macros.h" #include "esp_rom_sys.h" #include "esp_rom_serial_output.h" -#include "rom/cache.h" #include "riscv/rv_utils.h" #include "riscv/rvruntime-frames.h" +#include "hal/cache_types.h" +#include "hal/cache_ll.h" +#include "hal/cache_hal.h" #include "hal/apm_hal.h" +#if SOC_INT_PLIC_SUPPORTED +#include "soc/plic_reg.h" +#elif SOC_INT_CLIC_SUPPORTED +#include "soc/clic_reg.h" +#endif + #include "esp_tee.h" #include "esp_tee_apm_intr.h" #include "esp_tee_rv_utils.h" @@ -32,11 +40,16 @@ static void tee_panic_end(void) rv_utils_tee_intr_global_disable(); // Disable the cache - Cache_Disable_ICache(); + cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); // Clear the interrupt controller configurations +#if SOC_INT_PLIC_SUPPORTED memset((void *)DR_REG_PLIC_MX_BASE, 0x00, (PLIC_MXINT_CLAIM_REG + 4 - DR_REG_PLIC_MX_BASE)); memset((void *)DR_REG_PLIC_UX_BASE, 0x00, (PLIC_UXINT_CLAIM_REG + 4 - DR_REG_PLIC_UX_BASE)); +#elif SOC_INT_CLIC_SUPPORTED + memset((void *)DR_REG_CLIC_CTRL_BASE, 0x00, (REG_GET_FIELD(CLIC_INT_INFO_REG, CLIC_INT_INFO_NUM_INT)) * 4); + REG_WRITE(CLIC_INT_THRESH_REG, 0x00); +#endif // Make sure all the panic handler output is sent from UART FIFO if (CONFIG_ESP_CONSOLE_UART_NUM >= 0) { diff --git a/components/esp_tee/subproject/main/common/panic/panic_helper_riscv.c b/components/esp_tee/subproject/main/common/panic/panic_helper_riscv.c index 56fd980a6c..9525ce551f 100644 --- a/components/esp_tee/subproject/main/common/panic/panic_helper_riscv.c +++ b/components/esp_tee/subproject/main/common/panic/panic_helper_riscv.c @@ -7,11 +7,12 @@ #include "esp_attr.h" #include "esp_rom_sys.h" #include "esp_private/panic_reason.h" +#include "esp_private/vectors_const.h" #include "riscv/csr.h" #include "riscv/encoding.h" #include "riscv/rvruntime-frames.h" - +#include "soc/tee_reg.h" #include "esp_tee.h" #include "panic_helper.h" #include "sdkconfig.h" @@ -60,16 +61,26 @@ void panic_print_registers(const void *f, int core) const char *name; uint32_t value; } csr_regs[] = { - { "MIE ", RV_READ_CSR(mie) }, - { "MIP ", RV_READ_CSR(mip) }, - { "MSCRATCH", RV_READ_CSR(mscratch) }, - { "UEPC ", RV_READ_CSR(uepc) }, - { "USTATUS ", RV_READ_CSR(ustatus) }, - { "UTVEC ", RV_READ_CSR(utvec) }, - { "UCAUSE ", RV_READ_CSR(ucause) }, - { "UTVAL ", RV_READ_CSR(utval) }, - { "UIE ", RV_READ_CSR(uie) }, - { "UIP ", RV_READ_CSR(uip) }, + { "MSCRATCH ", RV_READ_CSR(mscratch) }, + { "UEPC ", RV_READ_CSR(uepc) }, + { "USTATUS ", RV_READ_CSR(ustatus) }, + { "UTVEC ", RV_READ_CSR(utvec) }, + { "UCAUSE ", RV_READ_CSR(ucause) }, +#if CONFIG_IDF_TARGET_ESP32C6 + { "MIE ", RV_READ_CSR(mie) }, + { "MIP ", RV_READ_CSR(mip) }, + { "UTVAL ", RV_READ_CSR(utval) }, + { "UIE ", RV_READ_CSR(uie) }, + { "UIP ", RV_READ_CSR(uip) }, +#endif +#if CONFIG_IDF_TARGET_ESP32C5 + { "USCRATCH ", RV_READ_CSR(0x040) }, + { "MEXSTATUS ", RV_READ_CSR(0x7E1) }, + { "MINTSTATUS", RV_READ_CSR(0xFB1) }, + { "MINTTHRESH", RV_READ_CSR(0x347) }, + { "UINTSTATUS", RV_READ_CSR(0xCB1) }, + { "UINTTHRESH", RV_READ_CSR(0x047) }, +#endif }; tee_panic_print("\n\n"); @@ -116,9 +127,10 @@ void panic_print_exccause(const void *f, int core) }; const char *rsn = NULL; - if (regs->mcause < (sizeof(reason) / sizeof(reason[0]))) { - if (reason[regs->mcause] != NULL) { - rsn = (reason[regs->mcause]); + 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]); } } diff --git a/components/esp_tee/subproject/main/core/esp_secure_services.c b/components/esp_tee/subproject/main/core/esp_secure_services.c index 1cd85be67a..9995165cc5 100644 --- a/components/esp_tee/subproject/main/core/esp_secure_services.c +++ b/components/esp_tee/subproject/main/core/esp_secure_services.c @@ -203,6 +203,13 @@ void _ss_esp_crypto_sha_enable_periph_clk(bool enable) esp_crypto_sha_enable_periph_clk(enable); } +#if SOC_SHA_SUPPORT_SHA512_T +int _ss_esp_sha_512_t_init_hash(uint16_t t) +{ + return esp_sha_512_t_init_hash(t); +} +#endif + /* ---------------------------------------------- HMAC ------------------------------------------------- */ esp_err_t _ss_esp_hmac_calculate(hmac_key_id_t key_id, const void *message, size_t message_len, uint8_t *hmac) diff --git a/components/esp_tee/subproject/main/core/esp_secure_services_iram.c b/components/esp_tee/subproject/main/core/esp_secure_services_iram.c index 17b2bc2e61..8263a6e728 100644 --- a/components/esp_tee/subproject/main/core/esp_secure_services_iram.c +++ b/components/esp_tee/subproject/main/core/esp_secure_services_iram.c @@ -12,12 +12,14 @@ #include "hal/mmu_types.h" #include "hal/mmu_hal.h" #include "hal/wdt_hal.h" +#include "rom/cache.h" #include "hal/spi_flash_hal.h" #include "hal/spi_flash_types.h" #include "spi_flash_chip_generic.h" #include "memspi_host_driver.h" #include "esp_flash.h" +#include "riscv/rv_utils.h" #include "esp_tee.h" #include "esp_tee_memory_utils.h" @@ -63,7 +65,7 @@ void _ss_rv_utils_intr_set_threshold(int priority_threshold) void _ss_rv_utils_intr_edge_ack(uint32_t intr_num) { - rv_utils_tee_intr_edge_ack(intr_num); + rv_utils_intr_edge_ack(intr_num); } void _ss_rv_utils_intr_global_enable(void) @@ -71,6 +73,42 @@ void _ss_rv_utils_intr_global_enable(void) rv_utils_tee_intr_global_enable(); } +uint32_t _ss_rv_utils_intr_get_enabled_mask(void) +{ + return rv_utils_intr_get_enabled_mask(); +} + +void _ss_rv_utils_set_cycle_count(uint32_t ccount) +{ + rv_utils_set_cycle_count(ccount); +} + +#if SOC_BRANCH_PREDICTOR_SUPPORTED +void _ss_rv_utils_en_branch_predictor(void) +{ + rv_utils_en_branch_predictor(); +} + +void _ss_rv_utils_dis_branch_predictor(void) +{ + rv_utils_dis_branch_predictor(); +} +#endif + +#if SOC_CPU_SUPPORT_WFE +void _ss_rv_utils_wfe_mode_enable(bool en) +{ + rv_utils_wfe_mode_enable(en); +} +#endif + +#if SOC_INT_CLIC_SUPPORTED +void _ss_esprv_int_set_vectored(int rv_int_num, bool vectored) +{ + esprv_int_set_vectored(rv_int_num, vectored); +} +#endif + /* ---------------------------------------------- RTC_WDT ------------------------------------------------- */ void _ss_wdt_hal_init(wdt_hal_context_t *hal, wdt_inst_t wdt_inst, uint32_t prescaler, bool enable_intr) @@ -164,6 +202,7 @@ void _ss_mmu_hal_map_region(uint32_t mmu_id, mmu_target_t mem_type, uint32_t vad bool vaddr_chk = esp_tee_flash_check_vaddr_in_tee_region(vaddr); bool paddr_chk = esp_tee_flash_check_paddr_in_tee_region(paddr); if (vaddr_chk || paddr_chk) { + ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x | 0x%08x", __func__, vaddr, paddr); return; } ESP_FAULT_ASSERT(!vaddr_chk && !paddr_chk); @@ -175,6 +214,7 @@ void _ss_mmu_hal_unmap_region(uint32_t mmu_id, uint32_t vaddr, uint32_t len) { bool vaddr_chk = esp_tee_flash_check_vaddr_in_tee_region(vaddr); if (vaddr_chk) { + ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, vaddr); return; } ESP_FAULT_ASSERT(!vaddr_chk); @@ -202,6 +242,13 @@ bool _ss_mmu_hal_paddr_to_vaddr(uint32_t mmu_id, uint32_t paddr, mmu_target_t ta return mmu_hal_paddr_to_vaddr(mmu_id, paddr, target, type, out_vaddr); } +#if CONFIG_IDF_TARGET_ESP32C5 +void _ss_Cache_Set_IDROM_MMU_Size(uint32_t irom_size, uint32_t drom_size) +{ + Cache_Set_IDROM_MMU_Size(irom_size, drom_size); +} +#endif + #if CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1 /* ---------------------------------------------- SPI Flash HAL ------------------------------------------------- */ diff --git a/components/esp_tee/subproject/main/core/esp_tee_intr.c b/components/esp_tee/subproject/main/core/esp_tee_intr.c index ef0cb14e3d..27eac49e55 100644 --- a/components/esp_tee/subproject/main/core/esp_tee_intr.c +++ b/components/esp_tee/subproject/main/core/esp_tee_intr.c @@ -60,8 +60,23 @@ void esp_tee_route_intr_matrix(int cpu_no, uint32_t model_num, uint32_t intr_num if (esp_tee_is_intr_src_protected(model_num) || intr_num == TEE_SECURE_INUM) { return; } +#if SOC_INT_CLIC_SUPPORTED + if (intr_num == TEE_PASS_INUM) { + return; + } +#endif esp_rom_route_intr_matrix(cpu_no, model_num, intr_num); + ESP_LOGV(TAG, "Connected src %d to int %d (cpu %d)", model_num, intr_num, cpu_no); + +#if SOC_INT_CLIC_SUPPORTED + if (intr_num != ETS_T1_WDT_INUM && intr_num != ETS_CACHEERR_INUM) { + /* Configure interrupts to be visible in the TEE (M-mode) */ + REG_SET_BIT(DR_REG_INTMTX_BASE + 4 * model_num, BIT(8)); + /* Configure interrupts to be serviced in the REE (U-mode) */ + rv_utils_tee_intr_set_mode(intr_num, PRV_U); + } +#endif } /** @@ -73,7 +88,7 @@ void esp_tee_route_intr_matrix(int cpu_no, uint32_t model_num, uint32_t intr_num static intr_handler_t tee_set_interrupt_handler(void *arg) { tee_handler_table_entry *entry; - intr_handler_t old; + intr_handler_t old; vector_desc_t *vd = (vector_desc_t *)arg; int source = vd->source; @@ -119,7 +134,7 @@ int esp_tee_intr_deregister(void *arg) tee_set_interrupt_handler(vd); // Setting back the default value for interrupt pin. - esp_rom_route_intr_matrix(cpu, vd->source, 0); + esp_rom_route_intr_matrix(cpu, vd->source, ETS_INVALID_INUM); return 0; } diff --git a/components/esp_tee/subproject/main/idf_component.yml b/components/esp_tee/subproject/main/idf_component.yml index 4f7ce5ca99..76f3ab9988 100644 --- a/components/esp_tee/subproject/main/idf_component.yml +++ b/components/esp_tee/subproject/main/idf_component.yml @@ -3,4 +3,4 @@ dependencies: espressif/json_generator: version: "^1.1.2" rules: - - if: "target in [esp32c6, esp32h2]" + - if: "target in [esp32c6, esp32h2, esp32c5]" diff --git a/components/esp_tee/subproject/main/ld/esp32c5/esp_tee.ld.in b/components/esp_tee/subproject/main/ld/esp32c5/esp_tee.ld.in new file mode 100644 index 0000000000..845051f3bc --- /dev/null +++ b/components/esp_tee/subproject/main/ld/esp32c5/esp_tee.ld.in @@ -0,0 +1,302 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" + +#define SRAM_IRAM_START (0x40800000) +#define SRAM_IRAM_TEE_ORG (SRAM_IRAM_START) +#define SRAM_DRAM_TEE_ORG (SRAM_IRAM_START) + +#define SRAM_IRAM_ORG (SRAM_IRAM_TEE_ORG + CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE) + +#define SRAM_DRAM_TEE_SIZE (CONFIG_SECURE_TEE_DRAM_SIZE - CONFIG_SECURE_TEE_STACK_SIZE - CONFIG_SECURE_TEE_INTR_STACK_SIZE) +#define SRAM_DRAM_TEE_END (SRAM_DRAM_TEE_ORG + CONFIG_SECURE_TEE_IRAM_SIZE + SRAM_DRAM_TEE_SIZE) + +#define I_D_SRAM_TEE_SIZE (CONFIG_SECURE_TEE_IRAM_SIZE + SRAM_DRAM_TEE_SIZE) + +/* TEE interrupt stack is placed at the end of the TEE DRAM segment. + * The top of the TEE stack is before the end of interrupt stack + * and the bottom of the stack is at _heap_end. + */ +#define SRAM_STACK_TEE_ORG (SRAM_DRAM_TEE_END) +#define SRAM_INTR_STACK_TEE_ORG (SRAM_DRAM_TEE_END + CONFIG_SECURE_TEE_STACK_SIZE) + +#define FLASH_IROM_TEE_ORG (0x42000000) +#define FLASH_DROM_TEE_ORG (0x42000000) +#define I_D_FLASH_TEE_SIZE (CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE) + +/** + * These values are the same in every app binary for the same chip target. + * + * Values that may change when the app is rebuilt, or in a new ESP-IDF version, + * should be stored via esp_app_tee_config structure + */ + +#if CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS +PROVIDE ( esp_tee_app_config = SRAM_IRAM_ORG + 0x22b0 ); +#else +PROVIDE ( esp_tee_app_config = SRAM_IRAM_ORG + 0x2b0 ); +#endif + +PROVIDE ( GDMA = 0x60080000 ); + +/* Default entry point: */ +ENTRY(esp_tee_init); + +MEMORY +{ +/* IRAM Configuration */ + iram_tee_seg (RX) : org = SRAM_IRAM_TEE_ORG, len = I_D_SRAM_TEE_SIZE + +/* DRAM Configuration */ + dram_tee_seg (RW) : org = SRAM_DRAM_TEE_ORG, len = I_D_SRAM_TEE_SIZE + +/* TEE Stack Configuration */ + stack_tee_seg (RW) : org = SRAM_STACK_TEE_ORG, len = CONFIG_SECURE_TEE_STACK_SIZE + +/* TEE Interrupt Stack Configuration */ + intr_stack_tee_seg (RW) : org = SRAM_INTR_STACK_TEE_ORG, len = CONFIG_SECURE_TEE_INTR_STACK_SIZE + +/* TEE flash data section */ + flash_data_seg (R) : org = FLASH_DROM_TEE_ORG + 0x20, len = I_D_FLASH_TEE_SIZE - 0x20 + +/* TEE flash text section */ + flash_text_seg (RX): org = FLASH_IROM_TEE_ORG + 0x20, len = I_D_FLASH_TEE_SIZE - 0x20 +} + +SECTIONS +{ + /** + * This section is required to skip .iram.tee_text area because iram_tee_seg and + * dram_tee_seg reflect the same address space on different buses. + */ + .dram.tee_dummy (NOLOAD): + { + . = ORIGIN(dram_tee_seg) + CONFIG_SECURE_TEE_IRAM_SIZE; + } > dram_tee_seg + + .dram.tee.bss (NOLOAD) : + { + . = ALIGN (8); + _tee_dram_start = ABSOLUTE(.); + _tee_bss_start = ABSOLUTE(.); + *(.bss .bss.*) + *(.sbss .sbss.*) + . = ALIGN (8); + _tee_bss_end = ABSOLUTE(.); + } > dram_tee_seg + + .dram.tee.data : + { + _data_start = ABSOLUTE(.); + *(.data .data.*) + *(.sdata .sdata.*) + *(.dram1 .dram1.*) + . = ALIGN(4); + _data_end = ABSOLUTE(.); + } > dram_tee_seg + + .dram.tee.rodata : + { + _rodata_start = ABSOLUTE(.); + /* TEE flash manager */ + *libtee_flash_mgr.a:*(.rodata .srodata .rodata.* .srodata.*) + *libbootloader_support.a:bootloader_flash.*(.rodata .srodata .rodata.* .srodata.*) + /* Secure services */ + *libmain.a:esp_secure_services_iram.c.*(.rodata .srodata .rodata.* .srodata.*) + *libmain.a:esp_secure_dispatcher.c.*(.rodata .srodata .rodata.* .srodata.*) + /* Panic handler */ + *libmain.a:panic_helper_riscv.*(.rodata .srodata .rodata.* .srodata.*) + *libmain.a:esp_tee_apm_intr.c.*(.rodata .srodata .rodata.* .srodata.*) + /* HAL (noflash) */ + *libhal.a:mmu_hal.c*(.rodata .srodata .rodata.* .srodata.*) + *libhal.a:cache_hal.c*(.rodata .srodata .rodata.* .srodata.*) + _rodata_end = ABSOLUTE(.); + _tee_dram_end = ABSOLUTE(.); + } > dram_tee_seg + + .dram.tee.heap : + { + . = ALIGN (16); + _tee_heap_start = ABSOLUTE(.); + . = ORIGIN(dram_tee_seg) + LENGTH(dram_tee_seg); + _tee_heap_end = ABSOLUTE(.); + } > dram_tee_seg + + .dram.tee.stack : + { + . = ALIGN (16); + _tee_stack_bottom = ABSOLUTE(.); + . = ORIGIN(stack_tee_seg) + LENGTH(stack_tee_seg); + _tee_stack = ABSOLUTE(.); + } > stack_tee_seg + + .dram.tee.intr_stack : + { + . = ALIGN (16); + _tee_intr_stack_bottom = ABSOLUTE(.); + . = ORIGIN(intr_stack_tee_seg) + LENGTH(intr_stack_tee_seg); + _tee_intr_stack = ABSOLUTE(.); + } > intr_stack_tee_seg + + .flash.rodata : + { + _tee_xip_data_start = ABSOLUTE(.); + *(.rodata_desc .rodata_desc.*) /* Should be the first. TEE App version info. DO NOT PUT ANYTHING BEFORE IT! */ + *(.rodata .rodata.*) + *(.srodata .srodata.*) + *(.gcc_except_table .gcc_except_table.*) + _tee_xip_data_end = ABSOLUTE(.); + } > flash_data_seg + + .flash.text_dummy (NOLOAD): + { + . = ALIGN(ALIGNOF(.flash.rodata)); + /* Create an empty gap as big as .flash.rodata section */ + . = . + SIZEOF(.flash.rodata); + /* Prepare the alignment of the section above. Few bytes (0x20) must be + * added for the mapping header. */ + . = ALIGN(CONFIG_MMU_PAGE_SIZE) + 0x20; + } > flash_text_seg + + +/* HAL modules and their memory placement: + * + * +-----------+---------------+--------+ + * | Module | Section | Memory | + * +-----------+---------------+--------+ + * | MMU | text+rodata | SRAM | + * | CACHE | text+rodata | SRAM | + * | WDT | text | SRAM | + * | APM | text | Flash* | + * | AES | text | Flash | + * | SHA | text | Flash | + * | HMAC | text | Flash | + * | DS | text | Flash | + * | ECC | text | Flash | + * | BROWNOUT | text | Flash | + * | EFUSE | text | Flash | + * | LPTIMER | text | Flash | + * | SPI_FLASH | text | Flash | + * +-----------+---------------+--------+ + * + * By default, for ESP-TEE, text sections are placed in SRAM while rodata sections go to the flash. + * Therefore, only HAL modules that require SRAM placement for proper functionality are located there, + * while the remaining modules are placed in flash memory. + */ + + .flash.text : + { + _tee_xip_text_start = ABSOLUTE(.); + /* Secure Services */ + *libmain.a:esp_secure_services.c*(.literal .text .literal.* .text.*) + /* HAL */ + *libhal.a:aes_hal.c*(.literal .text .literal.* .text.*) + *libhal.a:sha_hal.c*(.literal .text .literal.* .text.*) + *libhal.a:hmac_hal.c*(.literal .text .literal.* .text.*) + *libhal.a:ds_hal.c*(.literal .text .literal.* .text.*) + *libhal.a:ecc_hal.c*(.literal .text .literal.* .text.*) + /* NOTE: There is a possibility of APM violations (SPI1 flash protection) + * being triggered with the flash cache disabled */ +#if !CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1 + *libhal.a:apm_hal.c*(.literal .text .literal.* .text.*) +#endif + *libhal.a:brownout_hal.c*(.literal .text .literal.* .text.*) + *libhal.a:spi_flash_hal.c*(.literal .text .literal.* .text.*) + /* These HAL modules have functions marked with the IRAM_ATTR attribute which get placed in the SRAM */ + *libhal.a:efuse_hal.c*(.literal .text .literal.* .text.*) + *libhal.a:lp_timer_hal.c*(.literal .text .literal.* .text.*) + /* Mbedtls for TEE */ + *libmbedtls.a:*(.literal .text .literal.* .text.*) + *libmbedcrypto.a:*(.literal .text .literal.* .text.*) + /* HMAC-DS layer */ + *libesp_security.a:*(.literal .text .literal.* .text.*) + /* NVS flash and related modules */ + *libnvs_flash.a:*(.literal .text .literal.* .text.*) + *libstdc++.a:*(.literal .text .literal.* .text.*) + *libgcc.a:*(.literal .text .literal.* .text.*) + /* esp_partition API */ + *libesp_partition.a:*(.literal .text .literal.* .text.*) + /* TEE attestation module */ + *libattestation.a:*(.literal .text .literal.* .text.*) + *json_generator.a:*(.literal .text .literal.* .text.*) + /* TEE test module */ + *libtest_sec_srv.a:*(.literal .text .literal.* .text.*) + _tee_xip_text_end = ABSOLUTE(.); + _tee_xip_end = ABSOLUTE(.); + } > flash_text_seg + + .iram.tee.text : + { + /* Vectors go to start of IRAM */ + ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); + _tee_vec_start = ABSOLUTE(.); + KEEP(*(.exception_vectors_table.text)); + KEEP(*(.exception_vectors.text)); + . = ALIGN(4); + _invalid_pc_placeholder = ABSOLUTE(.); + _tee_vec_end = ABSOLUTE(.); + + _tee_iram_start = ABSOLUTE(.); + *(.literal .text .iram1 .literal.* .text.* .iram1.*) + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + _tee_iram_end = ABSOLUTE(.); + } > iram_tee_seg + + .riscv.attributes 0: { *(.riscv.attributes) } + + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .debug_pubtypes 0 : { *(.debug_pubtypes) } + /* DWARF 3 */ + .debug_ranges 0 : { *(.debug_ranges) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* GNU DWARF 2 extensions */ + .debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) } + .debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) } + /* DWARF 4 */ + .debug_types 0 : { *(.debug_types) } + /* DWARF 5 */ + .debug_addr 0 : { *(.debug_addr) } + .debug_line_str 0 : { *(.debug_line_str) } + .debug_loclists 0 : { *(.debug_loclists) } + .debug_macro 0 : { *(.debug_macro) } + .debug_names 0 : { *(.debug_names) } + .debug_rnglists 0 : { *(.debug_rnglists) } + .debug_str_offsets 0 : { *(.debug_str_offsets) } + + .comment 0 : { *(.comment) } + .note.GNU-stack 0: { *(.note.GNU-stack) } + + /** + * Discarding .rela.* sections results in the following mapping: + * .rela.text.* -> .text.* + * .rela.data.* -> .data.* + * And so forth... + */ + /DISCARD/ : { *(.rela.*) } +} + +ASSERT ((_tee_iram_end < _tee_dram_start), "Error: TEE IRAM segment overflowed into the DRAM segment!"); diff --git a/components/esp_tee/subproject/main/soc/esp32c5/esp_tee_apm_prot_cfg.c b/components/esp_tee/subproject/main/soc/esp32c5/esp_tee_apm_prot_cfg.c new file mode 100644 index 0000000000..494f288a0c --- /dev/null +++ b/components/esp_tee/subproject/main/soc/esp32c5/esp_tee_apm_prot_cfg.c @@ -0,0 +1,266 @@ +/* + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include "soc/soc.h" +#include "soc/soc_caps.h" +#include "soc/spi_mem_c_reg.h" +#include "soc/efuse_reg.h" +#include "soc/pcr_reg.h" +#include "soc/lp_analog_peri_reg.h" +#include "soc/lp_wdt_reg.h" + +#include "soc/apm_defs.h" +#include "hal/apm_types.h" +#include "hal/apm_hal.h" + +#include "esp_log.h" +#include "esp_bit_defs.h" +#include "esp_tee.h" +#include "esp_tee_intr.h" + +extern void tee_apm_violation_isr(void *arg); + +static const char *TAG = "esp_tee_apm_prot_cfg"; + +/* NOTE: Figuring out the eFuse protection range based on where the TEE secure storage key is stored */ +#if CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE +#if CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID < 0 +#error "TEE: eFuse protection region for APM out of range! (see CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID)" +#endif +#define LP_APM_EFUSE_REG_START \ + (EFUSE_RD_KEY0_DATA0_REG + (CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID * 0x20)) + +#define LP_APM_EFUSE_REG_END \ + (EFUSE_RD_KEY1_DATA0_REG + (CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID * 0x20)) +#elif CONFIG_SECURE_TEE_SEC_STG_MODE_DEVELOPMENT +#define LP_APM_EFUSE_REG_START EFUSE_RD_KEY5_DATA0_REG +#if CONFIG_SECURE_TEE_TEST_MODE +#define LP_APM_EFUSE_REG_END EFUSE_RD_SYS_PART2_DATA0_REG +#else +#define LP_APM_EFUSE_REG_END LP_APM_EFUSE_REG_START +#endif +#endif + +/* NOTE: Flash protection over the SPI1 controller */ +#define HP_APM_SPI1_REG_START DR_REG_SPIMEM1_BASE +#if CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1 +#define HP_APM_SPI1_REG_END DR_REG_I2C_BASE +#else +#define HP_APM_SPI1_REG_END HP_APM_SPI1_REG_START +#endif + +/* NOTE: Super-Watchdog and Brownout Detector protection */ +#define LP_APM_SWD_REG_START (LP_WDT_SWD_CONFIG_REG) +#define LP_APM_SWD_REG_END (LP_WDT_INT_CLR_REG + 4U) +#define LP_APM_BOD_REG_START (LP_ANA_BOD_MODE0_CNTL_REG) +#define LP_APM_BOD_REG_END (LP_ANA_LP_INT_CLR_REG + 4U) + +/* NOTE: Following are the master IDs for setting the security mode and access through APM: + * +---------+-------------+ + * | Bit | Source | + * +---------+-------------+ + * | 0 | HP CPU | + * | 1 | LP CPU | + * | 2 | reserved | + * | 3 | SDIO_SLV | + * | 4 | reserved | + * | 5 | MEM_MONITOR | + * | 6 | TRACE | + * | 7~15 | reserved | + * | 16 | SPI2 | + * | 17 | Dummy-1 | + * | 18 | UHCI | + * | 19 | I2S | + * | 20 | Dummy-4 | + * | 21 | Dummy-5 | + * | 22 | AES | + * | 23 | SHA | + * | 24 | ADC | + * | 25 | PARLIO | + * | 26~31 | Dummy-10~15 | + * +---------+-------------+ + */ + +#define APM_MASTERS_ALL (UINT32_MAX) +#define APM_MASTERS_HP_CPU (BIT(APM_MASTER_HPCORE)) +#define APM_MASTERS_LP_CPU (BIT(APM_MASTER_LPCORE)) +#define APM_MASTERS_GDMA_CRYPTO (BIT(APM_MASTER_GDMA_AES) | BIT(APM_MASTER_GDMA_SHA)) +#define APM_MASTERS_TEE (APM_MASTERS_HP_CPU | APM_MASTERS_GDMA_CRYPTO) +#define APM_MASTERS_REE (APM_MASTERS_ALL & ~(APM_MASTERS_TEE)) + +#define APM_PERIPH_ALL (UINT64_MAX) +#define APM_PERIPH_HP_PMS (BIT64(APM_TEE_HP_PERIPH_HP_APM) | BIT64(APM_TEE_HP_PERIPH_CPU_APM) | BIT64(APM_TEE_HP_PERIPH_TEE)) +#define APM_PERIPH_LP_PMS (BIT64(APM_TEE_LP_PERIPH_LP_TEE) | BIT64(APM_TEE_LP_PERIPH_LP_APM)) +#define APM_PERIPH_HP_REE (APM_PERIPH_ALL & ~(APM_PERIPH_HP_PMS)) +#define APM_PERIPH_LP_REE (APM_PERIPH_ALL & ~(APM_PERIPH_LP_PMS)) + +/*----------------------- REE0 mode configuration -----------------------*/ + +/*----------------------- HP_APM configuration -----------------------*/ + +/* HP_APM: REE0 mode accessible regions */ +static apm_hal_ctrl_region_cfg_t hp_apm_regn_cfg_ree0[] = { + /* Region 0: CPU peripherals (RW) */ + APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M0, 0, DR_REG_TRACE_BASE, 0x600D0000, APM_PERM_R | APM_PERM_W, true), + + /* NOTE: Without this entry, the REE D/IRAM region becomes inaccessible to + * the MODEM master, resulting in an APM violation during Wi-Fi initialization. + */ + /* Region 1: REE SRAM region (RW) - for all other masters except LP_CORE */ + APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M1, 1, SOC_NS_IRAM_START, SOC_IRAM_HIGH, APM_PERM_R | APM_PERM_W, true), + /* Region 1: REE SRAM region (RW) - for all LP_CORE */ + APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M2, 1, SOC_NS_IRAM_START, SOC_IRAM_HIGH, APM_PERM_R | APM_PERM_W, true), + + /* Region 2: Peripherals [Start - MMU] (RW) */ + /* Protected: MMU */ + APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M3, 2, SOC_PERIPHERAL_LOW, SPI_MEM_MMU_ITEM_CONTENT_REG(0), APM_PERM_R | APM_PERM_W, true), + + /* Region 3: Peripherals [MMU - SPI1] (RW) */ + /* Protected: SPI1 */ + APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M3, 3, SPI_MEM_MMU_POWER_CTRL_REG(0), HP_APM_SPI1_REG_START, APM_PERM_R | APM_PERM_W, true), + + /* Region 4: Peripherals [SPI1 - Interrupt Matrix] (RW) */ + /* Protected: Interrupt Matrix */ + APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M3, 4, HP_APM_SPI1_REG_END, DR_REG_INTMTX_BASE, APM_PERM_R | APM_PERM_W, true), + + /* Region 5/6: Peripherals [H/W Lock - HMAC] (RW) */ + /* Protected: AES, SHA, ECC, DS, HMAC */ + APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M3, 5, DR_REG_PCNT_BASE, DR_REG_AES_BASE, APM_PERM_R | APM_PERM_W, true), + APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M3, 6, DR_REG_RSA_BASE, DR_REG_ECC_MULT_BASE, APM_PERM_R | APM_PERM_W, true), + + /* Region 7/8/9: Peripherals [ECDSA - PMU] (RW) */ + /* Protected: AES, SHA, ECC, DS and HMAC PCRs */ + APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M3, 7, DR_REG_ECDSA_BASE, PCR_AES_CONF_REG, APM_PERM_R | APM_PERM_W, true), + APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M3, 8, PCR_RSA_CONF_REG, PCR_ECC_CONF_REG, APM_PERM_R | APM_PERM_W, true), + APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M3, 9, PCR_ECDSA_CONF_REG, DR_REG_PMU_BASE, APM_PERM_R | APM_PERM_W, true), + + /* Region 10: EXT_MEM region (RW) */ + APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M4, 10, SOC_S_DROM_HIGH, SOC_EXTRAM_DATA_HIGH, APM_PERM_R | APM_PERM_W, true), +}; + +/* HP_APM: REE0 mode masters' configuration */ +static apm_hal_ctrl_sec_mode_cfg_t hp_apm_ctrl_sec_mode_cfg_ree0 = + APM_HAL_SEC_MODE_CFG(APM_CTRL_HP_APM, APM_SEC_MODE_REE0, hp_apm_regn_cfg_ree0); + +/*----------------------- LP_APM configuration -----------------------*/ + +static apm_hal_ctrl_region_cfg_t lp_apm_regn_cfg_ree0[] = { + /* Region 0: RTC memory (RWX) */ + /* NOTE: LP_MEM gets automatically remapped to an offset of 0x20000000 + * when accessed in low-speed mode */ + APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M0, 0, SOC_RTC_IRAM_LOW + 0x20000000, SOC_RTC_IRAM_HIGH + 0x20000000, APM_PERM_ALL, true), + + /* Region 1: LP Peripherals [PMU - SWDT] (RW) */ + /* Protected: SWDT */ + APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M1, 1, DR_REG_PMU_BASE, LP_APM_SWD_REG_START, APM_PERM_R | APM_PERM_W, true), + + /* Region 2: LP Peripherals [SWDT - BOD] (RW) */ + /* Protected: BOD */ + APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M1, 2, LP_APM_SWD_REG_END, LP_APM_BOD_REG_START, APM_PERM_R | APM_PERM_W, true), + + /* Region 3: LP Peripherals [BOD - eFuse BLK x] (RW) */ + /* Protected: eFuse BLK x */ + APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M1, 3, LP_APM_BOD_REG_END, LP_APM_EFUSE_REG_START, APM_PERM_R | APM_PERM_W, true), + + /* Region 4: LP Peripherals [eFuse - END] (RW) */ + APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M1, 4, LP_APM_EFUSE_REG_END, DR_REG_TRACE_BASE, APM_PERM_R | APM_PERM_W, true), +}; + +/* LP_APM: REE0 mode masters' configuration */ +static apm_hal_ctrl_sec_mode_cfg_t lp_apm_ctrl_sec_mode_cfg_ree0 = + APM_HAL_SEC_MODE_CFG(APM_CTRL_LP_APM, APM_SEC_MODE_REE0, lp_apm_regn_cfg_ree0); + +/*----------------------- LP_APM0 configuration -----------------------*/ + +/* LP_APM0: REE0 mode accessible regions */ +static apm_hal_ctrl_region_cfg_t lp_apm0_regn_cfg_ree0[] = { + /* Region 0: RTC memory (RWX) */ + APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M0, 0, SOC_RTC_IRAM_LOW, SOC_RTC_IRAM_HIGH, APM_PERM_ALL, true), +}; + +/* LP_APM0: REE0 mode masters' configuration */ +static apm_hal_ctrl_sec_mode_cfg_t lp_apm0_ctrl_sec_mode_cfg_ree0 = + APM_HAL_SEC_MODE_CFG(APM_CTRL_LP_APM0, APM_SEC_MODE_REE0, lp_apm0_regn_cfg_ree0); + +/*----------------------- CPU_APM configuration -----------------------*/ + +/* CPU_APM: REE0 mode accessible regions */ +static apm_hal_ctrl_region_cfg_t cpu_apm_regn_cfg_ree0[] = { + /* Region 0: All SRAM access (RWX) */ + APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M0, 0, SOC_IRAM_LOW, SOC_DRAM_HIGH, APM_PERM_ALL, true), + APM_HAL_REGION_ENTRY(APM_CTRL_ACCESS_PATH_M1, 0, SOC_IRAM_LOW, SOC_DRAM_HIGH, APM_PERM_ALL, true), +}; + +/* CPU_APM: REE0 mode masters' configuration */ +static apm_hal_ctrl_sec_mode_cfg_t cpu_apm_ctrl_sec_mode_cfg_ree0 = + APM_HAL_SEC_MODE_CFG(APM_CTRL_CPU_APM, APM_SEC_MODE_REE0, cpu_apm_regn_cfg_ree0); + +/*---------------- TEE APM Setup -----------------------*/ + +static void enable_apm_intr(apm_ctrl_module_t ctrl_mod, uint32_t path_count) +{ + for (uint32_t i = 0; i < path_count; i++) { + apm_hal_ctrl_info_t *ctrl_info = calloc(1, sizeof(apm_hal_ctrl_info_t)); + assert(ctrl_info != NULL); + + ctrl_info->ctrl_mod = ctrl_mod; + ctrl_info->path = i; + + int intr_src_num = apm_hal_get_intr_src_num(ctrl_info); + + struct vector_desc_t apm_vd = {0}; + apm_vd.source = intr_src_num; + apm_vd.isr = tee_apm_violation_isr; + apm_vd.arg = (void *)ctrl_info; + + /* Register interrupt handler with TEE. */ + esp_tee_intr_register((void *)&apm_vd); + + /* Enable APM Ctrl interrupt for access path(M[0:n]) */ + apm_hal_clear_exception_status(ctrl_info); + apm_hal_enable_intr(ctrl_info, true); + } +} + +void esp_tee_configure_apm_protection(void) +{ + /* Disable all control filter first to have full access of address rage. */ + apm_hal_enable_ctrl_filter_all(false); + + /* HP_APM REE0 configuration. */ + apm_hal_set_ctrl_sec_mode_cfg(&hp_apm_ctrl_sec_mode_cfg_ree0); + /* HP_APM interrupt configuration. */ + enable_apm_intr(APM_CTRL_HP_APM, APM_CTRL_HP_APM_PATH_NUM); + ESP_LOGD(TAG, "[HP_APM] Configured for REE0"); + + /* LP_APM REE0 configuration. */ + apm_hal_set_ctrl_sec_mode_cfg(&lp_apm_ctrl_sec_mode_cfg_ree0); + /* LP_APM interrupt configuration. */ + enable_apm_intr(APM_CTRL_LP_APM, APM_CTRL_LP_APM_PATH_NUM); + ESP_LOGD(TAG, "[LP_APM] Configured for REE0"); + + /* LP_APM0 REE0 configuration. */ + apm_hal_set_ctrl_sec_mode_cfg(&lp_apm0_ctrl_sec_mode_cfg_ree0); + /* LP_APM0 interrupt configuration. */ + enable_apm_intr(APM_CTRL_LP_APM0, APM_CTRL_LP_APM0_PATH_NUM); + ESP_LOGD(TAG, "[LP_APM0] Configured for REE0"); + + /* CPU_APM REE0 configuration. */ + apm_hal_set_ctrl_sec_mode_cfg(&cpu_apm_ctrl_sec_mode_cfg_ree0); + /* CPU_APM interrupt configuration. */ + enable_apm_intr(APM_CTRL_CPU_APM, APM_CTRL_CPU_APM_PATH_NUM); + ESP_LOGD(TAG, "[CPU_APM] Configured for REE0"); + + /* Switch HP_CPU to TEE mode and rest of the masters to REE0 mode */ + apm_hal_set_master_sec_mode(APM_MASTERS_TEE, APM_SEC_MODE_TEE); + apm_hal_set_master_sec_mode(APM_MASTERS_REE, APM_SEC_MODE_REE0); + apm_hal_lock_master_sec_mode(APM_MASTERS_ALL); + + /* Open up all peripherals to REE0 mode*/ + apm_hal_tee_set_peri_access(APM_TEE_CTRL_HP, APM_PERIPH_HP_REE, APM_SEC_MODE_REE0, APM_PERM_R | APM_PERM_W); + apm_hal_tee_set_peri_access(APM_TEE_CTRL_LP, APM_PERIPH_LP_REE, APM_SEC_MODE_REE0, APM_PERM_R | APM_PERM_W); +} diff --git a/components/esp_tee/subproject/main/soc/esp32c5/esp_tee_pmp_pma_prot_cfg.c b/components/esp_tee/subproject/main/soc/esp32c5/esp_tee_pmp_pma_prot_cfg.c new file mode 100644 index 0000000000..4f08db8df8 --- /dev/null +++ b/components/esp_tee/subproject/main/soc/esp32c5/esp_tee_pmp_pma_prot_cfg.c @@ -0,0 +1,108 @@ +/* + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "sdkconfig.h" +#include "soc/soc.h" +#include "soc/ext_mem_defs.h" +#include "esp_cpu.h" +#include "esp_fault.h" +#include "esp32c5/rom/rom_layout.h" +#include "esp_tee.h" + +void esp_tee_configure_region_protection(void) +{ + /* Notes on implementation: + * + * 1) Note: ESP32-C5 CPU support overlapping PMP regions + * + * 2) ESP32-C5 supports 16 PMA regions so we use this feature to block all the invalid address ranges + * + * 3) We use combination of NAPOT (Naturally Aligned Power Of Two) and TOR (top of range) + * entries to map all the valid address space, bottom to top. This leaves us with some extra PMP entries + * which can be used to provide more granular access + * + * 4) Entries are grouped in order with some static asserts to try and verify everything is + * correct. + */ + const unsigned NONE = PMP_L; + const unsigned R = PMP_L | PMP_R; + const unsigned RW = PMP_L | PMP_R | PMP_W; + const unsigned RX = PMP_L | PMP_R | PMP_X; + const unsigned RWX = PMP_L | PMP_R | PMP_W | PMP_X; + + // + // Configure all the valid address regions using PMP + // + + // 1. CPU Subsystem region - contains interrupt config registers + PMP_ENTRY_CFG_RESET(0); + const uint32_t pmpaddr0 = PMPADDR_NAPOT(SOC_CPU_SUBSYSTEM_LOW, SOC_CPU_SUBSYSTEM_HIGH); + PMP_ENTRY_SET(0, pmpaddr0, PMP_NAPOT | RWX); + _Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region"); + + // 2. I/D-ROM + PMP_ENTRY_CFG_RESET(1); + PMP_ENTRY_CFG_RESET(2); + PMP_ENTRY_CFG_RESET(3); + const uint32_t drom_start = (uint32_t)(ets_rom_layout_p->drom_start); + if ((drom_start & (SOC_CPU_PMP_REGION_GRANULARITY - 1)) == 0) { + PMP_ENTRY_SET(1, SOC_IROM_MASK_LOW, NONE); + PMP_ENTRY_SET(2, drom_start, PMP_TOR | RX); + PMP_ENTRY_SET(3, SOC_DROM_MASK_HIGH, PMP_TOR | R); + } else { + PMP_ENTRY_SET(1, SOC_IROM_MASK_LOW, NONE); + PMP_ENTRY_SET(2, SOC_IROM_MASK_HIGH, PMP_TOR | RX); + _Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region"); + } + + // 3. IRAM and DRAM + PMP_ENTRY_CFG_RESET(4); + PMP_ENTRY_CFG_RESET(5); + PMP_ENTRY_CFG_RESET(6); + if (esp_cpu_dbgr_is_attached()) { + // Anti-FI check that cpu is really in ocd mode + ESP_FAULT_ASSERT(esp_cpu_dbgr_is_attached()); + PMP_ENTRY_SET(4, SOC_IRAM_LOW, NONE); + PMP_ENTRY_SET(5, SOC_IRAM_HIGH, PMP_TOR | RWX); + _Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region"); + } else { + // TODO: [IDF-13827] TEE SRAM region to be partitioned into text and data sections using APM + // REE SRAM (D/IRAM) + PMP_ENTRY_SET(4, (int)SOC_NS_IRAM_START, NONE); + PMP_ENTRY_SET(5, (int)esp_tee_app_config.ns_iram_end, PMP_TOR | RX); + PMP_ENTRY_SET(6, SOC_DRAM_HIGH, PMP_TOR | RW); + } + + const uint32_t s_irom_resv_end = SOC_IROM_LOW + CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE; + const uint32_t ns_irom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)esp_tee_app_config.ns_irom_end); + const uint32_t ns_drom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)esp_tee_app_config.ns_drom_end); + const uint32_t ns_drom_mmap_end = (uint32_t)(SOC_S_MMU_MMAP_RESV_START_VADDR); + + // 4. I_Cache / D_Cache (flash) - REE + PMP_ENTRY_CFG_RESET(7); + PMP_ENTRY_CFG_RESET(8); + PMP_ENTRY_CFG_RESET(9); + PMP_ENTRY_CFG_RESET(10); + PMP_ENTRY_SET(7, s_irom_resv_end, NONE); + PMP_ENTRY_SET(8, ns_irom_resv_end, PMP_TOR | RX); + PMP_ENTRY_SET(9, ns_drom_resv_end, PMP_TOR | R); + PMP_ENTRY_SET(10, ns_drom_mmap_end, PMP_TOR | RX); + + // 5. LP memory + // TODO: LP memory to be further partitioned into text and data regions using APM + PMP_ENTRY_CFG_RESET(11); + const uint32_t pmpaddr11 = PMPADDR_NAPOT(SOC_RTC_IRAM_LOW, SOC_RTC_IRAM_HIGH); + PMP_ENTRY_SET(11, pmpaddr11, PMP_NAPOT | RWX); + _Static_assert(SOC_RTC_IRAM_LOW < SOC_RTC_IRAM_HIGH, "Invalid RTC IRAM region"); + + // 6. Peripheral addresses + PMP_ENTRY_CFG_RESET(12); + const uint32_t pmpaddr12 = PMPADDR_NAPOT(SOC_PERIPHERAL_LOW, SOC_PERIPHERAL_HIGH); + PMP_ENTRY_SET(12, pmpaddr12, PMP_NAPOT | RW); + _Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region"); + + //TODO: Add protection for SPIRAM +} diff --git a/components/esp_tee/subproject/main/soc/esp32c5/esp_tee_secure_sys_cfg.c b/components/esp_tee/subproject/main/soc/esp32c5/esp_tee_secure_sys_cfg.c new file mode 100644 index 0000000000..cec537a13c --- /dev/null +++ b/components/esp_tee/subproject/main/soc/esp32c5/esp_tee_secure_sys_cfg.c @@ -0,0 +1,131 @@ +/* + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +#include "riscv/rv_utils.h" +#include "riscv/encoding.h" + +#include "hal/apm_hal.h" +#include "hal/aes_ll.h" +#include "hal/sha_ll.h" +#include "hal/hmac_ll.h" +#include "hal/ds_ll.h" +#include "hal/ecc_ll.h" + +#include "soc/clic_reg.h" +#include "soc/interrupts.h" + +#include "esp_tee.h" +#include "esp_tee_intr.h" +#include "esp_tee_rv_utils.h" + +#include "esp_cpu.h" +#include "esp_log.h" + +#define CSR_MCOUNTEREN 0x306 + +#define _m2u_switch(arg0, arg1) \ + ({ \ + register uintptr_t ra asm("ra") = (uintptr_t)(arg0); \ + register uintptr_t a1 asm("a1") = (uintptr_t)(arg1); \ + asm volatile("ecall" : :"r"(ra), "r"(a1) : ); \ + }) + +#define SET_BIT(t, n) (t |= (1UL << (n))) +#define CLR_BIT(t, n) (t &= ~(1UL << (n))) + +static const char *TAG = "esp_tee_secure_sys_cfg"; + +extern uint32_t _vector_table; +extern uint32_t _mtvt_table; + +void esp_tee_soc_secure_sys_init(void) +{ + ESP_LOGI(TAG, "Current privilege level - 0x%x", esp_cpu_get_curr_privilege_level()); + + /* Setting the M-mode vector table */ + rv_utils_set_mtvec((uint32_t)&_vector_table); + rv_utils_set_mtvt((uint32_t)&_mtvt_table); + + /* Disable global interrupts */ + RV_CLEAR_CSR(mstatus, MSTATUS_UIE); + RV_CLEAR_CSR(mstatus, MSTATUS_MIE); + + /* Enabled support for U-mode interrupts */ + REG_SET_FIELD(CLIC_INT_CONFIG_REG, CLIC_INT_CONFIG_NMBITS, 0x01); + REG_SET_FIELD(CLIC_INT_CONFIG_REG, CLIC_INT_CONFIG_UNLBITS, NLBITS); + REG_SET_FIELD(CLIC_INT_CONFIG_REG, CLIC_INT_CONFIG_MNLBITS, NLBITS); + + /* Allow reading the cycle counter CSRs from U-mode */ + RV_WRITE_CSR(CSR_MCOUNTEREN, 0x07); + + /* Clearing all interrupt configurations */ + uint32_t core_id = esp_cpu_get_core_id(); + for (int i = 0; i < ETS_MAX_INTR_SOURCE; i++) { + interrupt_clic_ll_route(core_id, i, ETS_INVALID_INUM); + REG_CLR_BIT(DR_REG_INTMTX_BASE + 4 * i, BIT(8)); + } + + /* TODO: IDF-8958 + * The values for the secure interrupt number and priority and + * the interrupt priority threshold (for both M and U mode) need + * to be investigated further + */ + esprv_int_set_threshold(0); + + esprv_int_set_priority(TEE_SECURE_INUM, 7); + esprv_int_set_type(TEE_SECURE_INUM, ESP_CPU_INTR_TYPE_LEVEL); + esprv_int_enable(BIT(TEE_SECURE_INUM)); + esprv_int_set_vectored(TEE_SECURE_INUM, true); + rv_utils_tee_intr_set_mode(TEE_SECURE_INUM, PRV_M); + + esprv_int_set_priority(TEE_PASS_INUM, 1); + esprv_int_set_type(TEE_PASS_INUM, ESP_CPU_INTR_TYPE_LEVEL); + esprv_int_enable(BIT(TEE_PASS_INUM)); + esprv_int_set_vectored(TEE_PASS_INUM, true); + rv_utils_tee_intr_set_mode(TEE_PASS_INUM, PRV_M); + + ESP_LOGD(TAG, "Initial interrupt config -"); + ESP_LOGD(TAG, "mtvec: 0x%08x", RV_READ_CSR(mtvec)); + ESP_LOGD(TAG, "mtvt: 0x%08x", RV_READ_CSR(MTVT_CSR)); + ESP_LOGD(TAG, "mstatus: 0x%08x", RV_READ_CSR(mstatus)); + ESP_LOGD(TAG, "mcounteren: 0x%08x", RV_READ_CSR(CSR_MCOUNTEREN)); + + /* PMP, PMA and APM configuration to isolate the resources between TEE and REE. */ + esp_tee_configure_region_protection(); + esp_tee_configure_apm_protection(); + + /* Protect secure interrupt sources */ + esp_tee_protect_intr_src(ETS_LP_APM_M0_INTR_SOURCE); // LP_APM_M0 + esp_tee_protect_intr_src(ETS_LP_APM_M1_INTR_SOURCE); // LP_APM_M1 + esp_tee_protect_intr_src(ETS_HP_APM_M0_INTR_SOURCE); // HP_APM_M0 + esp_tee_protect_intr_src(ETS_HP_APM_M1_INTR_SOURCE); // HP_APM_M1 + esp_tee_protect_intr_src(ETS_HP_APM_M2_INTR_SOURCE); // HP_APM_M2 + esp_tee_protect_intr_src(ETS_HP_APM_M3_INTR_SOURCE); // HP_APM_M3 + esp_tee_protect_intr_src(ETS_HP_APM_M4_INTR_SOURCE); // HP_APM_M4 + esp_tee_protect_intr_src(ETS_LP_APM0_INTR_SOURCE); // LP_APM0 + esp_tee_protect_intr_src(ETS_CPU_APM_M0_INTR_SOURCE); // CPU_APM_M0 + esp_tee_protect_intr_src(ETS_CPU_APM_M1_INTR_SOURCE); // CPU_APM_M1 + esp_tee_protect_intr_src(ETS_AES_INTR_SOURCE); // AES + esp_tee_protect_intr_src(ETS_SHA_INTR_SOURCE); // SHA + esp_tee_protect_intr_src(ETS_ECC_INTR_SOURCE); // ECC + + /* Disable protected crypto peripheral clocks; they will be toggled as needed when the peripheral is in use */ + aes_ll_enable_bus_clock(false); + sha_ll_enable_bus_clock(false); + hmac_ll_enable_bus_clock(false); + ds_ll_enable_bus_clock(false); + ecc_ll_enable_bus_clock(false); +} + +IRAM_ATTR inline void esp_tee_switch_to_ree(uint32_t ns_entry_addr) +{ + /* 2nd argument is used as magic value to detect very first M2U switch */ + /* TBD: clean this up and use proper temporary register instead of a1 */ + /* Switch to non-secure world and launch App. */ + _m2u_switch(ns_entry_addr, ESP_TEE_M2U_SWITCH_MAGIC << 12); +} diff --git a/components/esp_tee/subproject/main/soc/esp32c5/include/esp_tee_intr_defs.h b/components/esp_tee/subproject/main/soc/esp32c5/include/esp_tee_intr_defs.h new file mode 100644 index 0000000000..84c22e073c --- /dev/null +++ b/components/esp_tee/subproject/main/soc/esp32c5/include/esp_tee_intr_defs.h @@ -0,0 +1,40 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include "soc/interrupt_matrix_reg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// LP_APM_M0_INTR, LP_APM_M1_INTR +#define TEE_SECURE_INT_APM_MASK_0 (0x00300000) +// HP_APM_M0_INTR, HP_APM_M1_INTR, HP_APM_M2_INTR, HP_APM_M3_INTR, +// HP_APM_M4_INTR, LP_APM0_INTR, CPU_APM_M0_INTR, CPU_APM_M1_INTR +#define TEE_SECURE_INT_APM_MASK_1 (0x00000FF0) + +// LP_RTC_TIMER_INTR +#define TEE_SECURE_INT_MASK_0 (TEE_SECURE_INT_APM_MASK_0 | 0x00008000) +#if !CONFIG_SECURE_TEE_TEST_MODE +#define TEE_SECURE_INT_MASK_1 (TEE_SECURE_INT_APM_MASK_1) +#else +// + TG0_T0_INTR (only for test mode) +#define TEE_SECURE_INT_MASK_1 (TEE_SECURE_INT_APM_MASK_1 | 0x02000000) +#endif +// AES_INTR, SHA_INTR, ECC_INTR +#define TEE_SECURE_INT_MASK_2 (0x0002C000) + +#define INTMTX_STATUS_REG_0 (INTERRUPT_CORE0_INT_STATUS_REG_0_REG) +#define INTMTX_STATUS_REG_1 (INTERRUPT_CORE0_INT_STATUS_REG_1_REG) +#define INTMTX_STATUS_REG_2 (INTERRUPT_CORE0_INT_STATUS_REG_2_REG) + +#define INTMTX_SEC_STATUS_REG (INTERRUPT_CORE0_SECURE_STATUS_REG) +#define INTMTX_SIG_IDX_ASSERT_IN_SEC_REG (INTERRUPT_CORE0_SIG_IDX_ASSERT_IN_SEC_REG) + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_tee/subproject/main/soc/esp32c5/include/esp_tee_rv_utils.h b/components/esp_tee/subproject/main/soc/esp32c5/include/esp_tee_rv_utils.h new file mode 100644 index 0000000000..aff52514b8 --- /dev/null +++ b/components/esp_tee/subproject/main/soc/esp32c5/include/esp_tee_rv_utils.h @@ -0,0 +1,131 @@ +/* + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include + +#include "riscv/csr.h" +#include "riscv/interrupt.h" + +#include "hal/interrupt_clic_ll.h" +#include "soc/interrupt_reg.h" +#include "soc/clic_reg.h" + +#include "esp_attr.h" +#include "esp_tee.h" + +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MCOUNTEREN_CSR 0x306 +#define MTVT_CSR 0x307 +#define MINTSTATUS_CSR 0xFB1 +#define MINTTHRESH_CSR 0x347 +#define UINTTHRESH_CSR 0x047 + +FORCE_INLINE_ATTR void rv_utils_tee_intr_global_enable(void) +{ + /* + * Set the the U-mode previous enable global interrupts state + * + * NOTE: The TICK interrupt is setup before this service call and thus, + * it occurs in the return path of this call. + * + * Before entering the U-mode interrupt handler routine, USTATUS:UIE is + * cleared to disable U-mode interrupts temporarily. + * + * While exiting the above routine, URET is executed, setting USTATUS:UIE + * to the value of USTATUS:UPIE. However, since no interrupts were enabled + * previously, USTATUS:UPIE and thus, USTATUS:UIE is cleared. + * + * The service call completes and returns to U-mode with USTATUS:UIE disabled, + * preventing any further interrupts in U-mode. + * + */ + RV_SET_CSR(ustatus, USTATUS_UPIE); + /* Enabling the global M-mode and U-mode interrupts */ + RV_SET_CSR(ustatus, USTATUS_UIE); + RV_SET_CSR(mstatus, MSTATUS_UIE); + RV_SET_CSR(mstatus, MSTATUS_MIE); +} + +FORCE_INLINE_ATTR void rv_utils_tee_intr_global_disable(void) +{ + RV_CLEAR_CSR(ustatus, USTATUS_UIE); + RV_CLEAR_CSR(mstatus, MSTATUS_UIE); + RV_CLEAR_CSR(mstatus, MSTATUS_MIE); +} + +FORCE_INLINE_ATTR void rv_utils_tee_intr_enable(uint32_t intr_mask) +{ + // Machine mode + // Disable all interrupts to make updating of the interrupt mask atomic. + unsigned old_xstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE); + while (intr_mask != 0) { + // __builtin_ffs returns one plus the index of the lsb 1-bit of x. If x is zero, returns zero + uint32_t intr_num = __builtin_ffs(intr_mask) - 1; + *(uint8_t volatile *)(BYTE_CLIC_INT_IE_REG(intr_num + CLIC_EXT_INTR_NUM_OFFSET)) = BYTE_CLIC_INT_IE; + intr_mask &= (intr_mask - 1); + } + RV_SET_CSR(mstatus, old_xstatus & MSTATUS_MIE); +} + +FORCE_INLINE_ATTR void rv_utils_tee_intr_disable(uint32_t intr_mask) +{ + // Machine mode + // Disable all interrupts to make updating of the interrupt mask atomic. + unsigned old_xstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE); + while (intr_mask != 0) { + // __builtin_ffs returns one plus the index of the lsb 1-bit of x. If x is zero, returns zero + uint32_t intr_num = __builtin_ffs(intr_mask) - 1; + *(uint8_t volatile *)(BYTE_CLIC_INT_IE_REG(intr_num + CLIC_EXT_INTR_NUM_OFFSET)) = 0; + intr_mask &= (intr_mask - 1); + } + RV_SET_CSR(mstatus, old_xstatus & MSTATUS_MIE); +} + +FORCE_INLINE_ATTR void rv_utils_tee_intr_set_type(int intr_num, enum intr_type type) +{ + assert(intr_num >= 0 && intr_num < SOC_CPU_INTR_NUM); + /* TODO: CLIC supports both rising and falling edge triggered interrupts. + * Currently only rising edge is implemented. + */ + volatile uint8_t *attr_reg = (volatile uint8_t *)BYTE_CLIC_INT_ATTR_REG(intr_num + CLIC_EXT_INTR_NUM_OFFSET); + uint8_t attr = *attr_reg; + attr &= ~BYTE_CLIC_INT_ATTR_TRIG_M; + if (type == INTR_TYPE_EDGE) { + attr |= (INTR_TYPE_EDGE << BYTE_CLIC_INT_ATTR_TRIG_S); + } + *attr_reg = attr; +} + +FORCE_INLINE_ATTR void rv_utils_tee_intr_set_priority(int rv_int_num, int priority) +{ + assert(rv_int_num >= 0 && rv_int_num < SOC_CPU_INTR_NUM); + *(uint8_t volatile *)(BYTE_CLIC_INT_CTL_REG(rv_int_num + CLIC_EXT_INTR_NUM_OFFSET)) = (priority << BYTE_CLIC_INT_CTL_S); +} + +FORCE_INLINE_ATTR void rv_utils_tee_intr_set_threshold(int priority_threshold) +{ + uint32_t adj_threshold = ((priority_threshold << (8 - NLBITS)) | 0x1f); + REG_SET_FIELD(CLIC_INT_THRESH_REG, CLIC_CPU_INT_THRESH, adj_threshold); + RV_WRITE_CSR(MINTTHRESH_CSR, adj_threshold); + RV_WRITE_CSR(UINTTHRESH_CSR, adj_threshold); +} + +FORCE_INLINE_ATTR void rv_utils_tee_intr_set_mode(int rv_int_num, int mode) +{ + assert(rv_int_num >= 0 && rv_int_num < SOC_CPU_INTR_NUM); + REG_SET_FIELD(CLIC_INT_CTRL_REG(rv_int_num + CLIC_EXT_INTR_NUM_OFFSET), CLIC_INT_ATTR_MODE, mode); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_tee/subproject/main/soc/esp32c6/esp_tee_secure_sys_cfg.c b/components/esp_tee/subproject/main/soc/esp32c6/esp_tee_secure_sys_cfg.c index 6d10ba9f56..0802611ea0 100644 --- a/components/esp_tee/subproject/main/soc/esp32c6/esp_tee_secure_sys_cfg.c +++ b/components/esp_tee/subproject/main/soc/esp32c6/esp_tee_secure_sys_cfg.c @@ -10,6 +10,9 @@ #include "riscv/encoding.h" #include "esp_private/interrupt_plic.h" +#include "soc/plic_reg.h" +#include "soc/interrupts.h" + #include "esp_cpu.h" #include "esp_log.h" #include "hal/apm_hal.h" @@ -57,20 +60,24 @@ void esp_tee_soc_secure_sys_init(void) /* All interrupts except the TEE secure interrupt are delegated to the U-mode */ RV_WRITE_CSR(mideleg, UINT32_MAX); - RV_CLEAR_CSR(mideleg, TEE_SECURE_INUM); + RV_CLEAR_CSR(mideleg, BIT(TEE_SECURE_INUM)); + + /* Clearing all interrupt configurations */ + uint32_t core_id = esp_cpu_get_core_id(); + for (int i = 0; i < ETS_MAX_INTR_SOURCE; i++) { + esp_rom_route_intr_matrix(core_id, i, ETS_INVALID_INUM); + } /* TODO: IDF-8958 * The values for the secure interrupt number and priority and * the interrupt priority threshold (for both M and U mode) need * to be investigated further */ -#ifdef SOC_CPU_HAS_FLEXIBLE_INTC /* TODO: Currently, we do not allow interrupts to be set up with a priority greater than 7, see intr_alloc.c */ esprv_int_set_priority(TEE_SECURE_INUM, 7); esprv_int_set_type(TEE_SECURE_INUM, ESP_CPU_INTR_TYPE_LEVEL); esprv_int_set_threshold(RVHAL_INTR_ENABLE_THRESH); esprv_int_enable(BIT(TEE_SECURE_INUM)); -#endif ESP_LOGD(TAG, "Initial interrupt config -"); ESP_LOGD(TAG, "mideleg: 0x%08x", RV_READ_CSR(mideleg)); diff --git a/components/esp_tee/subproject/main/soc/esp32h2/esp_tee_secure_sys_cfg.c b/components/esp_tee/subproject/main/soc/esp32h2/esp_tee_secure_sys_cfg.c index 3efc9e81d9..1cd42774f3 100644 --- a/components/esp_tee/subproject/main/soc/esp32h2/esp_tee_secure_sys_cfg.c +++ b/components/esp_tee/subproject/main/soc/esp32h2/esp_tee_secure_sys_cfg.c @@ -10,6 +10,9 @@ #include "riscv/encoding.h" #include "esp_private/interrupt_plic.h" +#include "soc/plic_reg.h" +#include "soc/interrupts.h" + #include "esp_cpu.h" #include "esp_log.h" #include "hal/apm_hal.h" @@ -57,7 +60,13 @@ void esp_tee_soc_secure_sys_init(void) /* All interrupts except the TEE secure interrupt are delegated to the U-mode */ RV_WRITE_CSR(mideleg, UINT32_MAX); - RV_CLEAR_CSR(mideleg, TEE_SECURE_INUM); + RV_CLEAR_CSR(mideleg, BIT(TEE_SECURE_INUM)); + + /* Clearing all interrupt configurations */ + uint32_t core_id = esp_cpu_get_core_id(); + for (int i = 0; i < ETS_MAX_INTR_SOURCE; i++) { + esp_rom_route_intr_matrix(core_id, i, ETS_INVALID_INUM); + } /* TODO: IDF-8958 * The values for the secure interrupt number and priority and From 340de9823aa43b462b33794294a38fa0d016f1b4 Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Wed, 30 Apr 2025 19:43:30 +0530 Subject: [PATCH 2/4] feat(esp_tee): Support for ESP32-C5 - the rest of the components --- components/esp_hw_support/include/esp_cpu.h | 25 ++++- .../port/esp32c5/mspi_timing_tuning_configs.h | 8 +- .../port/esp32c5/CMakeLists.txt | 4 +- .../port/esp32c5/cpu_region_protect.c | 8 ++ .../port/esp32c5/esp_cpu_intr.c | 17 ++- .../port/esp32c6/esp_cpu_intr.c | 4 +- .../port/esp32h2/cpu_region_protect.c | 4 + .../port/esp32h2/esp_cpu_intr.c | 4 +- .../esp_mm/port/esp32c5/ext_mem_layout.c | 33 +++++- components/esp_rom/CMakeLists.txt | 9 +- components/esp_rom/esp32c5/ld/esp32c5.rom.ld | 2 +- components/esp_rom/include/esp_rom_tlsf.h | 16 ++- .../esp_rom/patches/esp_rom_cache_esp32c5.c | 32 ++++++ components/esp_rom/patches/esp_rom_sys.c | 2 +- components/esp_system/ld/esp32c5/memory.ld.in | 20 +++- .../esp_system/ld/esp32c5/sections.ld.in | 13 +++ components/esp_system/port/cpu_start.c | 32 ++++-- components/esp_system/port/soc/esp32c5/clk.c | 6 +- components/hal/spi_flash_hal_common.inc | 13 ++- .../priv_include/esp32c5/test_rv_utils.h | 4 - .../priv_include/esp32c61/test_rv_utils.h | 4 - components/heap/port/esp32c5/memory_layout.c | 15 ++- .../esp_tee/esp_tee_crypto_shared_gdma.c | 105 +++++++++++------- .../mbedtls/esp_tee/esp_tee_mbedtls_config.h | 12 ++ components/riscv/CMakeLists.txt | 2 + .../include/esp_private/interrupt_clic.h | 56 ++++++++-- components/riscv/include/riscv/interrupt.h | 2 +- components/riscv/include/riscv/rv_utils.h | 16 ++- components/riscv/interrupt_clic.c | 43 ++++++- components/riscv/vectors.S | 23 ++++ components/soc/esp32c5/register/soc/tee_reg.h | 1 - 31 files changed, 437 insertions(+), 98 deletions(-) create mode 100644 components/esp_rom/patches/esp_rom_cache_esp32c5.c diff --git a/components/esp_hw_support/include/esp_cpu.h b/components/esp_hw_support/include/esp_cpu.h index 1ae8d4daa2..cbecbafff6 100644 --- a/components/esp_hw_support/include/esp_cpu.h +++ b/components/esp_hw_support/include/esp_cpu.h @@ -271,15 +271,33 @@ FORCE_INLINE_ATTR void esp_cpu_intr_set_mtvt_addr(const void *mtvt_addr) { rv_utils_set_mtvt((uint32_t)mtvt_addr); } + +/** + * @brief Set the base address of the current CPU's Interrupt Vector Table (XTVT), based + * on the current privilege level + * + * @param xtvt_addr Interrupt Vector Table's base address + * + * @note The XTVT table is only applicable when CLIC is supported + */ +FORCE_INLINE_ATTR void esp_cpu_intr_set_xtvt_addr(const void *xtvt_addr) +{ + rv_utils_set_xtvt((uint32_t)xtvt_addr); +} #endif //#if SOC_INT_CLIC_SUPPORTED #if SOC_CPU_SUPPORT_WFE /** * @brief Disable the WFE (wait for event) feature for CPU. */ -FORCE_INLINE_ATTR void rv_utils_disable_wfe_mode(void) +FORCE_INLINE_ATTR void esp_cpu_disable_wfe_mode(void) { +#if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD + extern esprv_int_mgmt_t esp_tee_intr_sec_srv_cb; + esp_tee_intr_sec_srv_cb(2, SS_RV_UTILS_WFE_MODE_ENABLE, false); +#else rv_utils_wfe_mode_enable(false); +#endif } #endif @@ -450,9 +468,14 @@ FORCE_INLINE_ATTR uint32_t esp_cpu_intr_get_enabled_mask(void) { #ifdef __XTENSA__ return xt_utils_intr_get_enabled_mask(); +#else +#if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD && CONFIG_IDF_TARGET_ESP32C5 + extern esprv_int_mgmt_t esp_tee_intr_sec_srv_cb; + return esp_tee_intr_sec_srv_cb(1, SS_RV_UTILS_INTR_GET_ENABLED_MASK); #else return rv_utils_intr_get_enabled_mask(); #endif +#endif } /** diff --git a/components/esp_hw_support/mspi_timing_tuning/port/esp32c5/mspi_timing_tuning_configs.h b/components/esp_hw_support/mspi_timing_tuning/port/esp32c5/mspi_timing_tuning_configs.h index a4a623e598..82558dbb9e 100644 --- a/components/esp_hw_support/mspi_timing_tuning/port/esp32c5/mspi_timing_tuning_configs.h +++ b/components/esp_hw_support/mspi_timing_tuning/port/esp32c5/mspi_timing_tuning_configs.h @@ -28,7 +28,10 @@ #define MSPI_TIMING_FLASH_MODULE_CLOCK 120 #endif //------------------------------------FLASH Needs Tuning or not-------------------------------------// -#if MSPI_TIMING_FLASH_STR_MODE +/* TODO: [ESP-TEE | IDF-10425] The SPI1 controller is protected by APM when ESP-TEE is enabled. + * MSPI tuning requires access to this controller, so it is currently disabled. + */ +#if MSPI_TIMING_FLASH_STR_MODE && !CONFIG_SECURE_ENABLE_TEE #define MSPI_TIMING_FLASH_NEEDS_TUNING (MSPI_TIMING_FLASH_MODULE_CLOCK > 40) #endif @@ -45,7 +48,8 @@ #define MSPI_TIMING_PSRAM_MODULE_CLOCK 10 //Define this to 10MHz #endif //------------------------------------PSRAM Needs Tuning or not-------------------------------------// -#if MSPI_TIMING_PSRAM_STR_MODE +/* TODO: [ESP-TEE | IDF-10425] */ +#if MSPI_TIMING_PSRAM_STR_MODE && !CONFIG_SECURE_ENABLE_TEE #define MSPI_TIMING_PSRAM_NEEDS_TUNING (MSPI_TIMING_PSRAM_MODULE_CLOCK > 40) #endif diff --git a/components/esp_hw_support/port/esp32c5/CMakeLists.txt b/components/esp_hw_support/port/esp32c5/CMakeLists.txt index 3d96ad1e1c..e1c7e438aa 100644 --- a/components/esp_hw_support/port/esp32c5/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32c5/CMakeLists.txt @@ -1,3 +1,5 @@ +idf_build_get_property(non_os_build NON_OS_BUILD) + set(srcs "rtc_clk_init.c" "rtc_time.c" "rtc_clk.c" @@ -8,7 +10,7 @@ set(srcs "rtc_clk_init.c" "ocode_init.c" ) -if(NOT BOOTLOADER_BUILD) +if(NOT non_os_build) list(APPEND srcs "sar_periph_ctrl.c") endif() diff --git a/components/esp_hw_support/port/esp32c5/cpu_region_protect.c b/components/esp_hw_support/port/esp32c5/cpu_region_protect.c index 91e2e00783..7b3a6dc369 100644 --- a/components/esp_hw_support/port/esp32c5/cpu_region_protect.c +++ b/components/esp_hw_support/port/esp32c5/cpu_region_protect.c @@ -126,6 +126,14 @@ void esp_cpu_configure_region_protection(void) // esp_cpu_configure_invalid_regions(); + /* NOTE: When ESP-TEE is active, only configure invalid memory regions in bootloader + * to prevent errors before TEE initialization. TEE will handle all other + * memory protection. + */ +#if CONFIG_SECURE_ENABLE_TEE && BOOTLOADER_BUILD + return; +#endif + // // Configure all the valid address regions using PMP // diff --git a/components/esp_hw_support/port/esp32c5/esp_cpu_intr.c b/components/esp_hw_support/port/esp32c5/esp_cpu_intr.c index ded3030aeb..65d5b02e68 100644 --- a/components/esp_hw_support/port/esp32c5/esp_cpu_intr.c +++ b/components/esp_hw_support/port/esp32c5/esp_cpu_intr.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,7 +15,20 @@ void esp_cpu_intr_get_desc(int core_id, int intr_num, esp_cpu_intr_desc_t *intr_ * Reserve interrupt line 1 for the Wifi controller. * Reserve interrupt line 6 since it is used for disabling interrupts in the interrupt allocator (INT_MUX_DISABLED_INTNO) */ - const uint32_t rsvd_mask = BIT(1) | BIT(6); + const uint32_t base_rsvd_mask = BIT(1) | BIT(6); + + /* On the ESP32-C5, interrupt 31 is reserved for ESP-TEE + * for operations related to secure peripherals under its control + * (e.g. AES, SHA, APM) + * + * Interrupt 30 is reserved for handling REE interrupts occurring in TEE. + */ +#if CONFIG_SECURE_ENABLE_TEE + const uint32_t rsvd_mask = base_rsvd_mask | BIT(30) | BIT(31); +#else + const uint32_t rsvd_mask = base_rsvd_mask; +#endif + intr_desc_ret->priority = 1; intr_desc_ret->type = ESP_CPU_INTR_TYPE_NA; intr_desc_ret->flags = esp_riscv_intr_num_flags(intr_num, rsvd_mask); diff --git a/components/esp_hw_support/port/esp32c6/esp_cpu_intr.c b/components/esp_hw_support/port/esp32c6/esp_cpu_intr.c index 2eb79bdd3a..6cb8c037ef 100644 --- a/components/esp_hw_support/port/esp32c6/esp_cpu_intr.c +++ b/components/esp_hw_support/port/esp32c6/esp_cpu_intr.c @@ -19,12 +19,12 @@ void esp_cpu_intr_get_desc(int core_id, int intr_num, esp_cpu_intr_desc_t *intr_ // [TODO: IDF-2465] const uint32_t base_rsvd_mask = BIT(1) | BIT(3) | BIT(4) | BIT(6) | BIT(7); - /* On the ESP32-C6, interrupt 14 is reserved for ESP-TEE + /* On the ESP32-C6, interrupt 31 is reserved for ESP-TEE * for operations related to secure peripherals under its control * (e.g. AES, SHA, APM) */ #if CONFIG_SECURE_ENABLE_TEE - const uint32_t rsvd_mask = base_rsvd_mask | BIT(14); + const uint32_t rsvd_mask = base_rsvd_mask | BIT(31); #else const uint32_t rsvd_mask = base_rsvd_mask; #endif diff --git a/components/esp_hw_support/port/esp32h2/cpu_region_protect.c b/components/esp_hw_support/port/esp32h2/cpu_region_protect.c index a222a60318..698295b018 100644 --- a/components/esp_hw_support/port/esp32h2/cpu_region_protect.c +++ b/components/esp_hw_support/port/esp32h2/cpu_region_protect.c @@ -62,6 +62,10 @@ static void esp_cpu_configure_invalid_regions(void) // 7. End of address space PMA_ENTRY_SET_TOR(11, SOC_PERIPHERAL_HIGH, PMA_NONE); PMA_ENTRY_SET_TOR(12, UINT32_MAX, PMA_TOR | PMA_NONE); + + PMA_ENTRY_CFG_RESET(13); + PMA_ENTRY_CFG_RESET(14); + PMA_ENTRY_CFG_RESET(15); } void esp_cpu_configure_region_protection(void) diff --git a/components/esp_hw_support/port/esp32h2/esp_cpu_intr.c b/components/esp_hw_support/port/esp32h2/esp_cpu_intr.c index bace035293..5114ae24a8 100644 --- a/components/esp_hw_support/port/esp32h2/esp_cpu_intr.c +++ b/components/esp_hw_support/port/esp32h2/esp_cpu_intr.c @@ -18,12 +18,12 @@ void esp_cpu_intr_get_desc(int core_id, int intr_num, esp_cpu_intr_desc_t *intr_ // [TODO: IDF-2465] const uint32_t base_rsvd_mask = BIT(3) | BIT(4) | BIT(6) | BIT(7); - /* On the ESP32-H2, interrupt 14 is reserved for ESP-TEE + /* On the ESP32-H2, interrupt 31 is reserved for ESP-TEE * for operations related to secure peripherals under its control * (e.g. AES, SHA, APM) */ #if CONFIG_SECURE_ENABLE_TEE - const uint32_t rsvd_mask = base_rsvd_mask | BIT(14); + const uint32_t rsvd_mask = base_rsvd_mask | BIT(31); #else const uint32_t rsvd_mask = base_rsvd_mask; #endif diff --git a/components/esp_mm/port/esp32c5/ext_mem_layout.c b/components/esp_mm/port/esp32c5/ext_mem_layout.c index 5797513f45..7bd1b804cd 100644 --- a/components/esp_mm/port/esp32c5/ext_mem_layout.c +++ b/components/esp_mm/port/esp32c5/ext_mem_layout.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,6 +10,31 @@ #include "../ext_mem_layout.h" #include "hal/mmu_types.h" +/* NOTE: With ESP-TEE enabled: + * - The start address is moved by the size of TEE IDROM segments since these + * segments are placed at the start of the linear address space + * - TEE IROM and DROM segments are both 64KB (CONFIG_SECURE_TEE_IROM_SIZE, + * CONFIG_SECURE_TEE_DROM_SIZE) for now. Thus, the number of reserved entries + * from the start would be (64KB + 64KB)/MMU_PAGE_SIZE + * - The last few MMU entries are reserved for TEE flash operations. The number + * of reserved entries matches the size of TEE IDROM segments (IROM + DROM) + * plus one additional entry, i.e. (64KB + 64KB)/MMU_PAGE_SIZE + 1 + */ +#if CONFIG_SECURE_ENABLE_TEE +#define TEE_MMU_MEM_REG_START_OFFS (CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE) +#define TEE_MMU_RESV_PAGES ((CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE) / CONFIG_MMU_PAGE_SIZE) +#define TEE_MMU_MEM_REG_END_OFFS ((TEE_MMU_RESV_PAGES + 1) * CONFIG_MMU_PAGE_SIZE) + +#define MMU_MEM_REG_START_ADDR_W_TEE (SOC_MMU_IRAM0_LINEAR_ADDRESS_LOW + TEE_MMU_MEM_REG_START_OFFS) +#define MMU_MEM_REG_END_ADDR_W_TEE (SOC_MMU_IRAM0_LINEAR_ADDRESS_HIGH - TEE_MMU_MEM_REG_END_OFFS) + +#define MMU_IRAM0_LINEAR_ADDRESS_LOW MMU_MEM_REG_START_ADDR_W_TEE +#define MMU_IRAM0_LINEAR_ADDRESS_HIGH MMU_MEM_REG_END_ADDR_W_TEE +#else +#define MMU_IRAM0_LINEAR_ADDRESS_LOW SOC_MMU_IRAM0_LINEAR_ADDRESS_LOW +#define MMU_IRAM0_LINEAR_ADDRESS_HIGH SOC_MMU_IRAM0_LINEAR_ADDRESS_HIGH +#endif + /** * The start addresses in this list should always be sorted from low to high, as MMU driver will need to * coalesce adjacent regions @@ -17,9 +42,9 @@ // TODO: [ESP32C5] IDF-8658 const mmu_mem_region_t g_mmu_mem_regions[SOC_MMU_LINEAR_ADDRESS_REGION_NUM] = { [0] = { - .start = SOC_MMU_IRAM0_LINEAR_ADDRESS_LOW, - .end = SOC_MMU_IRAM0_LINEAR_ADDRESS_HIGH, - .size = SOC_BUS_SIZE(SOC_MMU_IRAM0_LINEAR), + .start = MMU_IRAM0_LINEAR_ADDRESS_LOW, + .end = MMU_IRAM0_LINEAR_ADDRESS_HIGH, + .size = MMU_IRAM0_LINEAR_ADDRESS_HIGH - MMU_IRAM0_LINEAR_ADDRESS_LOW, .bus_id = CACHE_BUS_IBUS0 | CACHE_BUS_DBUS0, .targets = MMU_TARGET_FLASH0 | MMU_TARGET_PSRAM0, .caps = MMU_MEM_CAP_EXEC | MMU_MEM_CAP_READ | MMU_MEM_CAP_WRITE | MMU_MEM_CAP_32BIT | MMU_MEM_CAP_8BIT, diff --git a/components/esp_rom/CMakeLists.txt b/components/esp_rom/CMakeLists.txt index aa575b9256..69e01d0abd 100644 --- a/components/esp_rom/CMakeLists.txt +++ b/components/esp_rom/CMakeLists.txt @@ -75,6 +75,10 @@ if(CONFIG_ESP_ROM_NO_USB_SERIAL_OUTPUT_API) list(APPEND sources "patches/esp_rom_usb_serial.c") endif() +if(CONFIG_SECURE_ENABLE_TEE AND CONFIG_IDF_TARGET_ESP32C5 AND NOT ESP_TEE_BUILD) + list(APPEND sources "patches/esp_rom_cache_esp32c5.c") +endif() + idf_component_register(SRCS ${sources} INCLUDE_DIRS ${include_dirs} PRIV_REQUIRES ${private_required_comp} @@ -142,6 +146,9 @@ endif() if(ESP_TEE_BUILD) rom_linker_script("spiflash") rom_linker_script("heap") + if(CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT) + rom_linker_script("newlib-nano") + endif() endif() if(BOOTLOADER_BUILD) @@ -388,7 +395,7 @@ else() # Regular app build endif() endif() - if(CONFIG_ESP_ROM_DELAY_US_PATCH AND + if(CONFIG_ESP_ROM_DELAY_US_PATCH AND CONFIG_SECURE_ENABLE_TEE AND (CONFIG_ESP32C5_REV_MIN_FULL LESS_EQUAL 100 OR CONFIG_ESP32C61_REV_MIN_FULL LESS_EQUAL 100)) # Force the linker to include esp_rom_sys.c for ets_ops_set_rom_patches constructor target_link_libraries(${COMPONENT_LIB} PRIVATE "-u ets_ops_set_rom_patches") diff --git a/components/esp_rom/esp32c5/ld/esp32c5.rom.ld b/components/esp_rom/esp32c5/ld/esp32c5.rom.ld index 7abce52964..a4bb7e2ddf 100644 --- a/components/esp_rom/esp32c5/ld/esp32c5.rom.ld +++ b/components/esp_rom/esp32c5/ld/esp32c5.rom.ld @@ -219,7 +219,7 @@ Cache_Suspend_Cache = 0x400006b4; Cache_Resume_Cache = 0x400006b8; Cache_Freeze_Enable = 0x400006bc; Cache_Freeze_Disable = 0x400006c0; -Cache_Set_IDROM_MMU_Size = 0x400006c4; +PROVIDE ( Cache_Set_IDROM_MMU_Size = 0x400006c4 ); Cache_Get_IROM_MMU_End = 0x400006c8; Cache_Get_DROM_MMU_End = 0x400006cc; Cache_MMU_Init = 0x400006d0; diff --git a/components/esp_rom/include/esp_rom_tlsf.h b/components/esp_rom/include/esp_rom_tlsf.h index dc9481d0e2..89fdfb7533 100644 --- a/components/esp_rom/include/esp_rom_tlsf.h +++ b/components/esp_rom/include/esp_rom_tlsf.h @@ -6,6 +6,7 @@ #pragma once #include #include +#include "sdkconfig.h" #ifdef __cplusplus extern "C" { @@ -17,8 +18,17 @@ typedef void* tlsf_t; typedef void* pool_t; /* Create/destroy a memory pool. */ +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 tlsf_t tlsf_create(void* mem); tlsf_t tlsf_create_with_pool(void* mem, size_t bytes); +size_t tlsf_size(void); +#else +tlsf_t tlsf_create(void* mem, size_t max_bytes); +tlsf_t tlsf_create_with_pool(void* mem, size_t pool_bytes, size_t max_bytes); +size_t tlsf_size(tlsf_t tlsf); +#endif + +void tlsf_destroy(tlsf_t tlsf); pool_t tlsf_get_pool(tlsf_t tlsf); /* Add/remove memory pools. */ @@ -36,7 +46,6 @@ void tlsf_free(tlsf_t tlsf, void* ptr); size_t tlsf_block_size(void* ptr); /* Overheads/limits of internal structures. */ -size_t tlsf_size(void); size_t tlsf_pool_overhead(void); size_t tlsf_alloc_overhead(void); @@ -47,7 +56,12 @@ size_t tlsf_alloc_overhead(void); */ size_t tlsf_align_size(void); size_t tlsf_block_size_min(void); +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 size_t tlsf_block_size_max(void); +#else +size_t tlsf_block_size_max(tlsf_t tlsf); +#endif +size_t tlsf_fit_size(tlsf_t tlsf, size_t size); /* NOTE: The consumer of this callback function (tlsf_walk_pool) is patched * in IDF builds to address issues in the ROM implementation. For TEE build, diff --git a/components/esp_rom/patches/esp_rom_cache_esp32c5.c b/components/esp_rom/patches/esp_rom_cache_esp32c5.c new file mode 100644 index 0000000000..7115c54a1e --- /dev/null +++ b/components/esp_rom/patches/esp_rom_cache_esp32c5.c @@ -0,0 +1,32 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp32c5/rom/cache.h" + +/** + * @brief Dummy implementation of Cache_Set_IDROM_MMU_Size from ROM. + * + * NOTE: This ROM-provided API is intended to configure the Cache MMU size for + * instruction (irom) and rodata (drom) sections in flash. + * + * On ESP32-C5, it also sets the start pages for flash irom and drom sections, + * which involves accessing MMU registers directly. However, these MMU registers + * are protected by the APM and direct access from the REE results in a fault. + * + * To prevent this: + * - Mark this symbol with the `PROVIDE` attribute in the ROM linker script. + * - Define this dummy function as a stub implementation. + * - Wrap this function to be routed as a TEE service call + * + * @param irom_size Size of the instruction ROM region. + * @param drom_size Size of the data ROM region. + */ +void Cache_Set_IDROM_MMU_Size(uint32_t irom_size, uint32_t drom_size) +{ + (void)irom_size; + (void)drom_size; +} diff --git a/components/esp_rom/patches/esp_rom_sys.c b/components/esp_rom/patches/esp_rom_sys.c index 8c5c897d05..b645ee0648 100644 --- a/components/esp_rom/patches/esp_rom_sys.c +++ b/components/esp_rom/patches/esp_rom_sys.c @@ -117,7 +117,7 @@ uint32_t esp_rom_get_bootloader_offset(void) } #endif // SOC_RECOVERY_BOOTLOADER_SUPPORTED -#if ESP_ROM_DELAY_US_PATCH && !NON_OS_BUILD +#if ESP_ROM_DELAY_US_PATCH && CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD #if CONFIG_ESP32C5_REV_MIN_FULL <= 100 || CONFIG_ESP32C61_REV_MIN_FULL <= 100 #include "riscv/rv_utils.h" diff --git a/components/esp_system/ld/esp32c5/memory.ld.in b/components/esp_system/ld/esp32c5/memory.ld.in index 8fcc73f037..160b3232a4 100644 --- a/components/esp_system/ld/esp32c5/memory.ld.in +++ b/components/esp_system/ld/esp32c5/memory.ld.in @@ -15,7 +15,13 @@ #include "sdkconfig.h" #include "ld.common" -#define SRAM_SEG_START 0x40800000 +#if !CONFIG_SECURE_ENABLE_TEE +#define SRAM_SEG_START (0x40800000) +#else +#define SRAM_SEG_START (0x40800000 + CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE) +#define FLASH_SEG_OFFSET (CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE) +#endif // CONFIG_SECURE_ENABLE_TEE + #define SRAM_SEG_END 0x4084E5A0 /* 2nd stage bootloader iram_loader_seg start address */ #define SRAM_SEG_SIZE SRAM_SEG_END - SRAM_SEG_START @@ -33,8 +39,14 @@ MEMORY */ #if CONFIG_APP_BUILD_USE_FLASH_SECTIONS +#if CONFIG_SECURE_ENABLE_TEE + /* Flash mapped instruction data */ + irom_seg (RX) : org = 0x42000020 + FLASH_SEG_OFFSET, + len = IDRAM0_2_SEG_SIZE - FLASH_SEG_OFFSET - 0x20 +#else /* Flash mapped instruction data */ irom_seg (RX) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20 +#endif /** * (0x20 offset above is a convenience for the app binary image generation. @@ -52,8 +64,14 @@ MEMORY sram_seg (RWX) : org = SRAM_SEG_START, len = SRAM_SEG_SIZE #if CONFIG_APP_BUILD_USE_FLASH_SECTIONS +#if CONFIG_SECURE_ENABLE_TEE /* Flash mapped constant data */ + drom_seg (R) : org = 0x42000020 + FLASH_SEG_OFFSET, + len = IDRAM0_2_SEG_SIZE - FLASH_SEG_OFFSET - 0x20 +#else + /* Flash mapped instruction data */ drom_seg (R) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20 +#endif /* (See irom_seg for meaning of 0x20 offset in the above.) */ #endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS diff --git a/components/esp_system/ld/esp32c5/sections.ld.in b/components/esp_system/ld/esp32c5/sections.ld.in index 74bf089be3..43be52efc7 100644 --- a/components/esp_system/ld/esp32c5/sections.ld.in +++ b/components/esp_system/ld/esp32c5/sections.ld.in @@ -158,9 +158,22 @@ SECTIONS _iram_start = ABSOLUTE(.); /* Vectors go to start of IRAM */ ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); + _vector_table_start = ABSOLUTE(.); KEEP(*(.exception_vectors_table.text)); KEEP(*(.exception_vectors.text)); + ALIGNED_SYMBOL(4, _invalid_pc_placeholder) + + /* esp_tee_config_t structure: used to share information between the TEE and REE + * (e.g. interrupt handler addresses, REE flash text-rodata boundaries, etc.) + * This symbol is expected by the TEE at an offset of 0x2b0 from the vector table start. + */ +#if CONFIG_SECURE_ENABLE_TEE + ALIGNED_SYMBOL(0x10, _esp_tee_app_cfg) + ASSERT(ABSOLUTE(.) == _vector_table_start + 0x2b0, "esp_tee_app_cfg must be at an offset 0x2b0 from the vector table start"); + *libesp_tee.a:(.esp_tee_app_cfg); +#endif + /* Code marked as running out of IRAM */ _iram_text_start = ABSOLUTE(.); diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index 807eeabe52..dae1e0dbd2 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -172,8 +172,13 @@ static volatile bool s_resume_cores; static void core_intr_matrix_clear(void) { - uint32_t core_id = esp_cpu_get_core_id(); + __attribute__((unused)) uint32_t core_id = esp_cpu_get_core_id(); + /* NOTE: With ESP-TEE enabled, each iteration in this loop results in a service call. + * To accelerate the boot-up process, the interrupt configuration is pre-cleared in the TEE, + * allowing this step to be safely skipped here. + */ +#if !CONFIG_SECURE_ENABLE_TEE for (int i = 0; i < ETS_MAX_INTR_SOURCE; i++) { #if SOC_INT_CLIC_SUPPORTED interrupt_clic_ll_route(core_id, i, ETS_INVALID_INUM); @@ -181,6 +186,7 @@ static void core_intr_matrix_clear(void) esp_rom_route_intr_matrix(core_id, i, ETS_INVALID_INUM); #endif // SOC_INT_CLIC_SUPPORTED } +#endif // !CONFIG_SECURE_ENABLE_TEE #if SOC_INT_CLIC_SUPPORTED for (int i = 0; i < 32; i++) { @@ -382,6 +388,15 @@ FORCE_INLINE_ATTR IRAM_ATTR void init_cpu(void) ); #endif + /* NOTE: When ESP-TEE is enabled, this sets up the callback function + * which redirects all the interrupt management for the REE (user app) + * to the TEE by raising the appropriate service calls. + */ +#if CONFIG_SECURE_ENABLE_TEE + extern uint32_t esp_tee_service_call(int argc, ...); + esprv_int_setup_mgmt_cb((void *)esp_tee_service_call); +#endif + #if SOC_BRANCH_PREDICTOR_SUPPORTED esp_cpu_branch_prediction_enable(); #endif @@ -391,19 +406,12 @@ FORCE_INLINE_ATTR IRAM_ATTR void init_cpu(void) /* When hardware vectored interrupts are enabled in CLIC, * the CPU jumps to this base address + 4 * interrupt_id. */ - esp_cpu_intr_set_mtvt_addr(&_mtvt_table); + /* NOTE: When ESP-TEE is enabled, this sets up the U-mode + * interrupt vector table (UTVT) */ + esp_cpu_intr_set_xtvt_addr(&_mtvt_table); #endif #if SOC_CPU_SUPPORT_WFE - rv_utils_disable_wfe_mode(); -#endif - - /* NOTE: When ESP-TEE is enabled, this sets up the callback function - * which redirects all the interrupt management for the REE (user app) - * to the TEE by raising the appropriate service calls. - */ -#if CONFIG_SECURE_ENABLE_TEE - extern uint32_t esp_tee_service_call(int argc, ...); - esprv_int_setup_mgmt_cb((void *)esp_tee_service_call); + esp_cpu_disable_wfe_mode(); #endif } diff --git a/components/esp_system/port/soc/esp32c5/clk.c b/components/esp_system/port/soc/esp32c5/clk.c index 49afeba1eb..07a9890ae5 100644 --- a/components/esp_system/port/soc/esp32c5/clk.c +++ b/components/esp_system/port/soc/esp32c5/clk.c @@ -305,6 +305,7 @@ __attribute__((weak)) void esp_perip_clk_init(void) assist_debug_ll_enable_bus_clock(false); #endif mpi_ll_enable_bus_clock(false); +#if !CONFIG_SECURE_ENABLE_TEE aes_ll_enable_bus_clock(false); sha_ll_enable_bus_clock(false); ecc_ll_enable_bus_clock(false); @@ -312,9 +313,10 @@ __attribute__((weak)) void esp_perip_clk_init(void) ds_ll_enable_bus_clock(false); apm_ll_hp_tee_enable_clk_gating(true); apm_ll_lp_tee_enable_clk_gating(true); - uhci_ll_enable_bus_clock(0, false); apm_ll_hp_apm_enable_ctrl_clk_gating(true); apm_ll_cpu_apm_enable_ctrl_clk_gating(true); +#endif + uhci_ll_enable_bus_clock(0, false); // TODO: Replace with hal implementation REG_CLR_BIT(PCR_TRACE_CONF_REG, PCR_TRACE_CLK_EN); @@ -346,8 +348,10 @@ __attribute__((weak)) void esp_perip_clk_init(void) _lp_clkrst_ll_enable_lp_ana_i2c_clock(false); _lp_clkrst_ll_enable_lp_ext_i2c_clock(false); +#if !CONFIG_SECURE_ENABLE_TEE apm_ll_lp_apm_enable_ctrl_clk_gating(true); apm_ll_lp_apm0_enable_ctrl_clk_gating(true); +#endif WRITE_PERI_REG(LP_CLKRST_LP_CLK_PO_EN_REG, 0); } } diff --git a/components/hal/spi_flash_hal_common.inc b/components/hal/spi_flash_hal_common.inc index 83757d8dd9..9146fbd202 100644 --- a/components/hal/spi_flash_hal_common.inc +++ b/components/hal/spi_flash_hal_common.inc @@ -131,7 +131,15 @@ esp_err_t spi_flash_hal_configure_host_io_mode( addr_bitlen += SPI_FLASH_LL_CONTINUOUS_MODE_BIT_NUMS; #endif spi_flash_ll_set_extra_address(dev, 0); -#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL + // TODO: [IDF-13582] + // Currently, REE and TEE use different sets of APIs for flash operations - + // REE uses the IDF SPI flash driver while TEE call the ROM APIs. This inconsistency + // leads to compatibility issues on ESP32-C5. + // One specific issue arises when esp_flash_read() is used in REE, which internally + // calls spi_flash_ll_wb_mode_enable(). This function enables the WB mode bit in + // the flash write operation. However, the ROM API does not support this + // feature, resulting in failures when TEE attempts to access flash after this call. +#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL && !CONFIG_SECURE_ENABLE_TEE spi_flash_ll_wb_mode_enable(dev, true); #endif } @@ -208,7 +216,8 @@ esp_err_t spi_flash_hal_common_command(spi_flash_host_inst_t *host, spi_flash_tr if (trans->miso_len > 0) { spi_flash_ll_get_buffer_data(dev, trans->miso_data, trans->miso_len); } -#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL + // TODO: [IDF-13582] +#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL && !CONFIG_SECURE_ENABLE_TEE spi_flash_ll_wb_mode_enable(dev, false); #endif return ESP_OK; diff --git a/components/hal/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32c5/test_rv_utils.h b/components/hal/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32c5/test_rv_utils.h index 8865e9076b..39218839f3 100644 --- a/components/hal/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32c5/test_rv_utils.h +++ b/components/hal/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32c5/test_rv_utils.h @@ -22,10 +22,6 @@ #include "sdkconfig.h" -#define UTVT_CSR (0x007) -#define UINTSTATUS_CSR (0xCB1) -#define UINTTHRESH_CSR (0x047) - #ifdef __cplusplus extern "C" { #endif diff --git a/components/hal/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32c61/test_rv_utils.h b/components/hal/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32c61/test_rv_utils.h index 8865e9076b..39218839f3 100644 --- a/components/hal/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32c61/test_rv_utils.h +++ b/components/hal/test_apps/tee/components/pms_and_cpu_intr/priv_include/esp32c61/test_rv_utils.h @@ -22,10 +22,6 @@ #include "sdkconfig.h" -#define UTVT_CSR (0x007) -#define UINTSTATUS_CSR (0xCB1) -#define UINTTHRESH_CSR (0x047) - #ifdef __cplusplus extern "C" { #endif diff --git a/components/heap/port/esp32c5/memory_layout.c b/components/heap/port/esp32c5/memory_layout.c index 4fbc9b6f1f..797c4b0a88 100644 --- a/components/heap/port/esp32c5/memory_layout.c +++ b/components/heap/port/esp32c5/memory_layout.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,6 +12,11 @@ #include "heap_memory_layout.h" #include "esp_heap_caps.h" +#if CONFIG_SECURE_ENABLE_TEE +#define SRAM_DIRAM_TEE_ORG (SOC_DIRAM_IRAM_LOW) +#define SRAM_DIRAM_TEE_END (SRAM_DIRAM_TEE_ORG + CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE) +#endif + /** * @brief Memory type descriptors. These describe the capabilities of a type of memory in the SoC. * Each type of memory map consists of one or more regions in the address space. @@ -97,6 +102,14 @@ SOC_RESERVE_MEMORY_REGION((intptr_t)&_data_start, (intptr_t)&_heap_start, dram_d // Target has a shared D/IRAM virtual address, no need to calculate I_D_OFFSET like previous chips SOC_RESERVE_MEMORY_REGION((intptr_t)&_iram_start, (intptr_t)&_iram_end, iram_code); +/* NOTE: When ESP-TEE is enabled, the start of the internal SRAM +* is used by the TEE and is protected from any REE access using +* memory protection mechanisms employed by ESP-TEE. +*/ +#if CONFIG_SECURE_ENABLE_TEE +SOC_RESERVE_MEMORY_REGION((intptr_t)SRAM_DIRAM_TEE_ORG, (intptr_t)(SRAM_DIRAM_TEE_END), tee_diram); +#endif + #ifdef CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP SOC_RESERVE_MEMORY_REGION(SOC_RTC_DRAM_LOW, (intptr_t)&_rtc_force_slow_end, rtcram_data); #endif diff --git a/components/mbedtls/esp_tee/esp_tee_crypto_shared_gdma.c b/components/mbedtls/esp_tee/esp_tee_crypto_shared_gdma.c index 78e71c24ac..29b55762e5 100644 --- a/components/mbedtls/esp_tee/esp_tee_crypto_shared_gdma.c +++ b/components/mbedtls/esp_tee/esp_tee_crypto_shared_gdma.c @@ -10,15 +10,10 @@ #include "mbedtls/aes.h" #include "esp_crypto_dma.h" -#include "hal/clk_gate_ll.h" -#include "hal/gdma_ll.h" #include "hal/gdma_types.h" #include "hal/aes_hal.h" -#include "soc/lldesc.h" -#include "soc/periph_defs.h" #include "soc/gdma_channel.h" -#include "soc/gdma_struct.h" #include "soc/soc_caps.h" #include "esp_tee_crypto_shared_gdma.h" @@ -27,6 +22,38 @@ #define TEE_CRYPTO_GDMA_CH (0) +#if SOC_AHB_GDMA_VERSION == 2 +#include "hal/ahb_dma_ll.h" +#include "soc/ahb_dma_struct.h" +#define DMA_DEV (AHB_DMA) +#define DMA_LL_FUNC(func) ahb_dma_ll_##func +#elif SOC_AHB_GDMA_VERSION == 1 +#include "hal/gdma_ll.h" +#include "soc/gdma_struct.h" +#define DMA_DEV (GDMA) +#define DMA_LL_FUNC(func) gdma_ll_##func +#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) + /* * NOTE: [ESP-TEE] This is a low-level (LL), non-OS version of * port/crypto_shared_gdma/esp_crypto_shared_gdma.c that defines @@ -37,30 +64,23 @@ static void crypto_shared_gdma_init(void) { - // enable APB to access GDMA registers - periph_ll_enable_clk_clear_rst(PERIPH_GDMA_MODULE); - // enable gdma clock - gdma_ll_force_enable_reg_clock(&GDMA, true); + gdma_ll_enable_bus_clock(0, true); + gdma_ll_reset_register(0); + dma_ll_force_enable_reg_clock(&DMA_DEV, true); // setting the transfer ability - gdma_ll_tx_enable_data_burst(&GDMA, TEE_CRYPTO_GDMA_CH, true); - gdma_ll_tx_enable_descriptor_burst(&GDMA, TEE_CRYPTO_GDMA_CH, true); + dma_ll_tx_enable_data_burst(&DMA_DEV, TEE_CRYPTO_GDMA_CH, true); + dma_ll_tx_enable_descriptor_burst(&DMA_DEV, TEE_CRYPTO_GDMA_CH, true); - gdma_ll_rx_enable_data_burst(&GDMA, TEE_CRYPTO_GDMA_CH, false); - gdma_ll_rx_enable_descriptor_burst(&GDMA, TEE_CRYPTO_GDMA_CH, true); + dma_ll_rx_enable_data_burst(&DMA_DEV, TEE_CRYPTO_GDMA_CH, false); + dma_ll_rx_enable_descriptor_burst(&DMA_DEV, TEE_CRYPTO_GDMA_CH, true); -#if SOC_GDMA_SUPPORT_PSRAM - gdma_ll_tx_set_block_size_psram(&GDMA, TEE_CRYPTO_GDMA_CH, GDMA_LL_EXT_MEM_BK_SIZE_16B); - gdma_ll_rx_set_block_size_psram(&GDMA, TEE_CRYPTO_GDMA_CH, GDMA_LL_EXT_MEM_BK_SIZE_16B); -#endif // SOC_GDMA_SUPPORT_PSRAM - - gdma_ll_tx_reset_channel(&GDMA, TEE_CRYPTO_GDMA_CH); - gdma_ll_tx_connect_to_periph(&GDMA, TEE_CRYPTO_GDMA_CH, GDMA_TRIG_PERIPH_M2M, SOC_GDMA_TRIG_PERIPH_M2M0); - - gdma_ll_rx_reset_channel(&GDMA, TEE_CRYPTO_GDMA_CH); - gdma_ll_rx_connect_to_periph(&GDMA, TEE_CRYPTO_GDMA_CH, GDMA_TRIG_PERIPH_M2M, SOC_GDMA_TRIG_PERIPH_M2M0); + dma_ll_tx_reset_channel(&DMA_DEV, TEE_CRYPTO_GDMA_CH); + dma_ll_tx_connect_to_periph(&DMA_DEV, TEE_CRYPTO_GDMA_CH, GDMA_TRIG_PERIPH_M2M, SOC_GDMA_TRIG_PERIPH_M2M0); + dma_ll_rx_reset_channel(&DMA_DEV, TEE_CRYPTO_GDMA_CH); + dma_ll_rx_connect_to_periph(&DMA_DEV, TEE_CRYPTO_GDMA_CH, GDMA_TRIG_PERIPH_M2M, SOC_GDMA_TRIG_PERIPH_M2M0); } esp_err_t esp_tee_crypto_shared_gdma_start(const crypto_dma_desc_t *input, const crypto_dma_desc_t *output, gdma_trigger_peripheral_t periph) @@ -76,40 +96,39 @@ esp_err_t esp_tee_crypto_shared_gdma_start(const crypto_dma_desc_t *input, const crypto_shared_gdma_init(); - gdma_ll_tx_disconnect_from_periph(&GDMA, TEE_CRYPTO_GDMA_CH); - gdma_ll_rx_disconnect_from_periph(&GDMA, TEE_CRYPTO_GDMA_CH); + dma_ll_tx_disconnect_from_periph(&DMA_DEV, TEE_CRYPTO_GDMA_CH); + dma_ll_rx_disconnect_from_periph(&DMA_DEV, TEE_CRYPTO_GDMA_CH); - gdma_ll_tx_reset_channel(&GDMA, TEE_CRYPTO_GDMA_CH); - gdma_ll_tx_connect_to_periph(&GDMA, TEE_CRYPTO_GDMA_CH, periph, periph_inst_id); + dma_ll_tx_reset_channel(&DMA_DEV, TEE_CRYPTO_GDMA_CH); + dma_ll_tx_connect_to_periph(&DMA_DEV, TEE_CRYPTO_GDMA_CH, periph, periph_inst_id); - gdma_ll_rx_reset_channel(&GDMA, TEE_CRYPTO_GDMA_CH); - gdma_ll_rx_connect_to_periph(&GDMA, TEE_CRYPTO_GDMA_CH, periph, periph_inst_id); + dma_ll_rx_reset_channel(&DMA_DEV, TEE_CRYPTO_GDMA_CH); + dma_ll_rx_connect_to_periph(&DMA_DEV, TEE_CRYPTO_GDMA_CH, periph, periph_inst_id); - gdma_ll_tx_set_desc_addr(&GDMA, TEE_CRYPTO_GDMA_CH, (intptr_t)input); - gdma_ll_tx_start(&GDMA, TEE_CRYPTO_GDMA_CH); + dma_ll_tx_set_desc_addr(&DMA_DEV, TEE_CRYPTO_GDMA_CH, (intptr_t)input); + dma_ll_tx_start(&DMA_DEV, TEE_CRYPTO_GDMA_CH); - gdma_ll_rx_set_desc_addr(&GDMA, TEE_CRYPTO_GDMA_CH, (intptr_t)output); - gdma_ll_rx_start(&GDMA, TEE_CRYPTO_GDMA_CH); + dma_ll_rx_set_desc_addr(&DMA_DEV, TEE_CRYPTO_GDMA_CH, (intptr_t)output); + dma_ll_rx_start(&DMA_DEV, TEE_CRYPTO_GDMA_CH); return ESP_OK; } void esp_tee_crypto_shared_gdma_free(void) { - gdma_ll_tx_stop(&GDMA, TEE_CRYPTO_GDMA_CH); - gdma_ll_rx_stop(&GDMA, TEE_CRYPTO_GDMA_CH); + dma_ll_tx_stop(&DMA_DEV, TEE_CRYPTO_GDMA_CH); + dma_ll_rx_stop(&DMA_DEV, TEE_CRYPTO_GDMA_CH); - gdma_ll_tx_disconnect_from_periph(&GDMA, TEE_CRYPTO_GDMA_CH); - gdma_ll_rx_disconnect_from_periph(&GDMA, TEE_CRYPTO_GDMA_CH); + dma_ll_tx_disconnect_from_periph(&DMA_DEV, TEE_CRYPTO_GDMA_CH); + dma_ll_rx_disconnect_from_periph(&DMA_DEV, TEE_CRYPTO_GDMA_CH); - gdma_ll_tx_set_priority(&GDMA, TEE_CRYPTO_GDMA_CH, 0); - gdma_ll_rx_set_priority(&GDMA, TEE_CRYPTO_GDMA_CH, 0); + dma_ll_tx_set_priority(&DMA_DEV, TEE_CRYPTO_GDMA_CH, 0); + dma_ll_rx_set_priority(&DMA_DEV, TEE_CRYPTO_GDMA_CH, 0); // disable gdma clock - gdma_ll_force_enable_reg_clock(&GDMA, false); - - // disable APB for GDMA registers - periph_ll_disable_clk_set_rst(PERIPH_GDMA_MODULE); + gdma_ll_enable_bus_clock(0, false); + gdma_ll_reset_register(0); + dma_ll_force_enable_reg_clock(&DMA_DEV, false); } /* ---------------------------------------------- DMA Implementations: AES ------------------------------------------------- */ diff --git a/components/mbedtls/esp_tee/esp_tee_mbedtls_config.h b/components/mbedtls/esp_tee/esp_tee_mbedtls_config.h index 14078e2bd2..5021e43c92 100644 --- a/components/mbedtls/esp_tee/esp_tee_mbedtls_config.h +++ b/components/mbedtls/esp_tee/esp_tee_mbedtls_config.h @@ -22,6 +22,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "soc/soc_caps.h" #include "sdkconfig.h" #ifndef ESP_TEE_MBEDTLS_CONFIG_H @@ -50,13 +51,24 @@ #define MBEDTLS_ECP_C #define MBEDTLS_ECDSA_C +#if CONFIG_MBEDTLS_SHA1_C #define MBEDTLS_SHA1_C +#endif #define MBEDTLS_SHA224_C #define MBEDTLS_SHA256_C +#if SOC_SHA_SUPPORT_SHA512 && CONFIG_MBEDTLS_SHA512_C +#define MBEDTLS_SHA384_C +#define MBEDTLS_SHA512_C +#endif #if CONFIG_MBEDTLS_HARDWARE_SHA +#if CONFIG_MBEDTLS_SHA1_C #define MBEDTLS_SHA1_ALT +#endif #define MBEDTLS_SHA256_ALT +#if SOC_SHA_SUPPORT_SHA512 && CONFIG_MBEDTLS_SHA512_C +#define MBEDTLS_SHA512_ALT +#endif #endif #ifdef CONFIG_MBEDTLS_HARDWARE_ECC diff --git a/components/riscv/CMakeLists.txt b/components/riscv/CMakeLists.txt index 1db27908e9..12872530fe 100644 --- a/components/riscv/CMakeLists.txt +++ b/components/riscv/CMakeLists.txt @@ -15,6 +15,8 @@ elseif(esp_tee_build) set(srcs "rv_utils.c") if(CONFIG_SOC_INT_PLIC_SUPPORTED) list(APPEND srcs "interrupt_plic.c") + elseif(CONFIG_SOC_INT_CLIC_SUPPORTED) + list(APPEND srcs "interrupt_clic.c") endif() else() set(priv_requires soc hal) diff --git a/components/riscv/include/esp_private/interrupt_clic.h b/components/riscv/include/esp_private/interrupt_clic.h index 83fa3e3505..695edf9c17 100644 --- a/components/riscv/include/esp_private/interrupt_clic.h +++ b/components/riscv/include/esp_private/interrupt_clic.h @@ -44,6 +44,7 @@ extern "C" { * @brief CSR to set the interrupt jump table address is MTVT. */ #define MTVT_CSR 0x307 +#define UTVT_CSR 0x007 #if CONFIG_IDF_TARGET_ESP32P4 && CONFIG_ESP32P4_SELECTS_REV_LESS_V2 @@ -61,7 +62,9 @@ extern "C" { /* The ESP32-C5 (MP), C61, H4 and P4 (since REV2) use the standard CLIC specification, for example, it defines the mintthresh CSR */ #define INTTHRESH_STANDARD 1 #define MINTSTATUS_CSR 0xFB1 +#define UINTSTATUS_CSR 0xCB1 #define MINTTHRESH_CSR 0x347 +#define UINTTHRESH_CSR 0x047 #else #error "Check the implementation of the CLIC on this target." @@ -114,7 +117,11 @@ extern "C" { #define RVHAL_INTR_ENABLE_THRESH_CLIC (CLIC_INT_THRESH(RVHAL_INTR_ENABLE_THRESH)) - +#if CONFIG_SECURE_ENABLE_TEE +#define IS_PRV_M_MODE() (RV_READ_CSR(CSR_PRV_MODE) == PRV_M) +#else +#define IS_PRV_M_MODE() (1UL) +#endif FORCE_INLINE_ATTR void assert_valid_rv_int_num(int rv_int_num) @@ -132,7 +139,12 @@ FORCE_INLINE_ATTR void assert_valid_rv_int_num(int rv_int_num) FORCE_INLINE_ATTR uint32_t rv_utils_get_interrupt_threshold(void) { #if INTTHRESH_STANDARD - uint32_t threshold = RV_READ_CSR(MINTTHRESH_CSR); + uint32_t threshold; + if (IS_PRV_M_MODE()) { + threshold = RV_READ_CSR(MINTTHRESH_CSR); + } else { + threshold = RV_READ_CSR(UINTTHRESH_CSR); + } #else uint32_t threshold = REG_READ(CLIC_INT_THRESH_REG); #endif @@ -148,6 +160,19 @@ FORCE_INLINE_ATTR void rv_utils_set_mtvt(uint32_t mtvt_val) RV_WRITE_CSR(MTVT_CSR, mtvt_val); } +/** + * @brief Set the XTVT CSR value (based on the current privilege mode), + * used as a base address for the interrupt jump table + */ +FORCE_INLINE_ATTR void rv_utils_set_xtvt(uint32_t xtvt_val) +{ + if (IS_PRV_M_MODE()) { + RV_WRITE_CSR(MTVT_CSR, xtvt_val); + } else { + RV_WRITE_CSR(UTVT_CSR, xtvt_val); + } +} + #if SOC_CPU_SUPPORT_WFE /** * @brief Set the MEXSTATUS_WFFEN value, used to enable/disable wait for event mode. @@ -167,7 +192,11 @@ FORCE_INLINE_ATTR void rv_utils_wfe_mode_enable(bool en) */ FORCE_INLINE_ATTR uint32_t rv_utils_get_interrupt_level_regval(void) { - return RV_READ_CSR(MINTSTATUS_CSR); + if (IS_PRV_M_MODE()) { + return RV_READ_CSR(MINTSTATUS_CSR); + } else { + return RV_READ_CSR(UINTSTATUS_CSR); + } } /** @@ -175,9 +204,14 @@ FORCE_INLINE_ATTR uint32_t rv_utils_get_interrupt_level_regval(void) */ FORCE_INLINE_ATTR uint32_t rv_utils_get_interrupt_level(void) { - const uint32_t mintstatus = RV_READ_CSR(MINTSTATUS_CSR); + uint32_t xintstatus; + if (IS_PRV_M_MODE()) { + xintstatus = RV_READ_CSR(MINTSTATUS_CSR); + } else { + xintstatus = RV_READ_CSR(UINTSTATUS_CSR); + } /* Extract the level from this field */ - return CLIC_STATUS_TO_INT(mintstatus); + return CLIC_STATUS_TO_INT(xintstatus); } /** @@ -190,7 +224,11 @@ FORCE_INLINE_ATTR uint32_t rv_utils_get_interrupt_level(void) FORCE_INLINE_ATTR void rv_utils_restore_intlevel_regval(uint32_t restoreval) { #if INTTHRESH_STANDARD - RV_WRITE_CSR(MINTTHRESH_CSR, restoreval); + if (IS_PRV_M_MODE()) { + RV_WRITE_CSR(MINTTHRESH_CSR, restoreval); + } else { + RV_WRITE_CSR(UINTTHRESH_CSR, restoreval); + } #else REG_WRITE(CLIC_INT_THRESH_REG, restoreval); /** @@ -224,7 +262,11 @@ FORCE_INLINE_ATTR void rv_utils_restore_intlevel(uint32_t restoreval) FORCE_INLINE_ATTR uint32_t rv_utils_set_intlevel_regval(uint32_t intlevel) { #if INTTHRESH_STANDARD - return RV_SWAP_CSR(MINTTHRESH_CSR, intlevel); + if (IS_PRV_M_MODE()) { + return RV_SWAP_CSR(MINTTHRESH_CSR, intlevel); + } else { + return RV_SWAP_CSR(UINTTHRESH_CSR, intlevel); + } #else // !INTTHRESH_STANDARD uint32_t old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE); uint32_t old_thresh = REG_READ(CLIC_INT_THRESH_REG); diff --git a/components/riscv/include/riscv/interrupt.h b/components/riscv/include/riscv/interrupt.h index f500b6174b..a487c1c34b 100644 --- a/components/riscv/include/riscv/interrupt.h +++ b/components/riscv/include/riscv/interrupt.h @@ -149,7 +149,7 @@ void esprv_int_set_vectored(int rv_int_num, bool vectored); /*************************** ESP-TEE specific ***************************/ /** Function prototype executing interrupt configuration APIs as service calls */ -typedef void (*esprv_int_mgmt_t)(int argc, ...); +typedef uint32_t (*esprv_int_mgmt_t)(int argc, ...); /** * @brief Setup the callback function which executes the interrupt diff --git a/components/riscv/include/riscv/rv_utils.h b/components/riscv/include/riscv/rv_utils.h index 7a0ebbfcef..a4e533f443 100644 --- a/components/riscv/include/riscv/rv_utils.h +++ b/components/riscv/include/riscv/rv_utils.h @@ -118,7 +118,11 @@ FORCE_INLINE_ATTR uint32_t __attribute__((always_inline)) rv_utils_get_cycle_cou FORCE_INLINE_ATTR void __attribute__((always_inline)) rv_utils_set_cycle_count(uint32_t ccount) { #if !SOC_CPU_HAS_CSR_PC +#if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD + esp_tee_intr_sec_srv_cb(2, SS_RV_UTILS_SET_CYCLE_COUNT, ccount); +#else RV_WRITE_CSR(mcycle, ccount); +#endif #else if (IS_PRV_M_MODE()) { RV_WRITE_CSR(CSR_PCCR_MACHINE, ccount); @@ -404,8 +408,8 @@ FORCE_INLINE_ATTR void rv_utils_clear_breakpoint(int bp_num) { RV_WRITE_CSR(tselect, bp_num); /* tdata1 is a WARL(write any read legal) register - * We can just write 0 to it - */ + * We can just write 0 to it + */ RV_WRITE_CSR(tdata1, 0); } @@ -481,12 +485,20 @@ FORCE_INLINE_ATTR bool rv_utils_compare_and_set(volatile uint32_t *addr, uint32_ #if SOC_BRANCH_PREDICTOR_SUPPORTED FORCE_INLINE_ATTR void rv_utils_en_branch_predictor(void) { +#if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD + esp_tee_intr_sec_srv_cb(1, SS_RV_UTILS_EN_BRANCH_PREDICTOR); +#else RV_SET_CSR(MHCR, MHCR_RS|MHCR_BFE|MHCR_BTB); +#endif } FORCE_INLINE_ATTR void rv_utils_dis_branch_predictor(void) { +#if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD + esp_tee_intr_sec_srv_cb(1, SS_RV_UTILS_DIS_BRANCH_PREDICTOR); +#else RV_CLEAR_CSR(MHCR, MHCR_RS|MHCR_BFE|MHCR_BTB); +#endif } #endif diff --git a/components/riscv/interrupt_clic.c b/components/riscv/interrupt_clic.c index d6a98618f4..95d48a3cc4 100644 --- a/components/riscv/interrupt_clic.c +++ b/components/riscv/interrupt_clic.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -40,3 +40,44 @@ void esprv_int_set_vectored(int rv_int_num, bool vectored) { interrupt_clic_ll_set_vectored(rv_int_num + RV_EXTERNAL_INT_OFFSET, vectored); } + + +#if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD +DRAM_ATTR esprv_int_mgmt_t esp_tee_intr_sec_srv_cb = NULL; + +void esprv_int_setup_mgmt_cb(void *fptr) +{ + esp_tee_intr_sec_srv_cb = (esprv_int_mgmt_t)fptr; +} + + +/* NOTE: Overriding ROM-based interrupt configuration symbols */ +void esprv_int_enable(uint32_t unmask) +{ + rv_utils_intr_enable(unmask); +} + + +void esprv_int_disable(uint32_t mask) +{ + rv_utils_intr_disable(mask); +} + + +void esprv_int_set_type(int intr_num, enum intr_type type) +{ + rv_utils_intr_set_type(intr_num, type); +} + + +void esprv_int_set_priority(int rv_int_num, int priority) +{ + rv_utils_intr_set_priority(rv_int_num, priority); +} + + +void esprv_int_set_threshold(int priority_threshold) +{ + rv_utils_intr_set_threshold(priority_threshold); +} +#endif diff --git a/components/riscv/vectors.S b/components/riscv/vectors.S index 47d0b372d9..56542f2505 100644 --- a/components/riscv/vectors.S +++ b/components/riscv/vectors.S @@ -17,6 +17,8 @@ .equ EXC_ILLEGAL_INSTRUCTION, 0x2 .equ panic_from_exception, xt_unhandled_exception .equ panic_from_isr, panicHandler + .equ CSR_UINTSTATUS, 0xCB1 + .equ CSR_UINTTHRESH, 0x047 #if ( SOC_CPU_COPROC_NUM > 0 ) /* Targets with coprocessors present a special CSR to get Illegal Instruction exception reason */ @@ -90,8 +92,11 @@ sw t0, RV_STK_MSTATUS(sp) csrr t0, utvec sw t0, RV_STK_MTVEC(sp) + /* NOTE: C6 and H2 possess the utval CSR, but rest of the SoCs don't */ + #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 csrr t0, utval sw t0, RV_STK_MTVAL(sp) + #endif #else csrr t0, mstatus sw t0, RV_STK_MSTATUS(sp) @@ -467,6 +472,24 @@ _tee_interrupt_handler: li t0, INTERRUPT_CURRENT_CORE_INT_THRESH_REG sw s3, 0(t0) fence +#elif CONFIG_SECURE_ENABLE_TEE + /* Restore the U-mode interrupt threshold level. + * + * If uintstatus == 0, it means we have returned here after servicing a + * U-mode interrupt that was delegated via M-mode. In this case, we should + * reset the threshold to the minimum valid level. + * + * If uintstatus != 0, we are currently handling a U-mode interrupt that + * either originated directly in U-mode or is a nested U-mode interrupt. + * In this case, the threshold must be retained, so we skip the reset. + */ + csrr t0, CSR_UINTSTATUS + bnez t0, _skip_thresh_reset + csrr t0, CSR_UINTTHRESH + li t1, (1 << (8 - NLBITS) - 1) + beq t0, t1, _skip_thresh_reset + csrw CSR_UINTTHRESH, t1 +_skip_thresh_reset: #endif // !SOC_INT_HW_NESTED_SUPPORTED /* The RTOS will restore the current TCB stack pointer. This routine will preserve s1 and s2. diff --git a/components/soc/esp32c5/register/soc/tee_reg.h b/components/soc/esp32c5/register/soc/tee_reg.h index 398d4bc235..0b17fa32c6 100644 --- a/components/soc/esp32c5/register/soc/tee_reg.h +++ b/components/soc/esp32c5/register/soc/tee_reg.h @@ -5,7 +5,6 @@ */ #pragma once -#include #include "soc/soc.h" #ifdef __cplusplus extern "C" { From ab8400df4ae9c7c5d137bd4ae35ef65ab579b06f Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Thu, 29 May 2025 19:21:04 +0530 Subject: [PATCH 3/4] ci(esp_tee): Refactor the ESP-TEE test-cases - Improve the interrupt-related test cases - Fix potential issues in the task-switching test during secure service calls --- .../test_sec_srv/include/esp_tee_test.h | 29 +- .../test_sec_srv/sec_srv_tbl_test.yml | 48 ++-- .../test_sec_srv/src/test_dummy_srv.c | 2 +- .../test_sec_srv/src/test_dummy_srv_wrapper.c | 8 +- .../test_sec_srv/src/test_interrupt.c | 260 +++++++++--------- .../test_sec_srv/src/test_sec_srv.c | 28 +- .../main/test_esp_tee_ctx_switch.c | 120 +++++--- .../tee_test_fw/main/test_esp_tee_interrupt.c | 198 +++++-------- 8 files changed, 321 insertions(+), 372 deletions(-) diff --git a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/include/esp_tee_test.h b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/include/esp_tee_test.h index 4874ccc5c7..bb4eec7c45 100644 --- a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/include/esp_tee_test.h +++ b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/include/esp_tee_test.h @@ -9,36 +9,11 @@ extern "C" { #endif -#include #include "esp_attr.h" -#define TEE_TEST_INT_COUNT 3 +#define ESP_TEE_TEST_INTR_ITER (4) -uint32_t NOINLINE_ATTR esp_tee_service_add(uint32_t a, uint32_t b); - -uint32_t NOINLINE_ATTR esp_tee_service_sub(uint32_t a, uint32_t b); - -uint32_t NOINLINE_ATTR esp_tee_service_mul(uint32_t a, uint32_t b); - -uint32_t NOINLINE_ATTR esp_tee_service_div(uint32_t a, uint32_t b); - -int esp_tee_secure_int_test(void); - -int esp_tee_non_secure_int_test(volatile uint32_t* volatile ns_int_count); - -int esp_tee_test_int_count(uint32_t *secure_int_count); - -int esp_tee_test_store_prohibited(uint32_t type); - -int esp_tee_test_illegal_instr(void); - -int esp_tee_test_instr_fetch_prohibited(uint32_t type); - -void NOINLINE_ATTR dummy_secure_service(int a, int b, int c, int d, int e, int f, int g, int h, int *i); - -uint32_t add_in_loop(uint32_t a, uint32_t b, uint32_t iter); - -int _ss_esp_tee_test_heap_malloc_write_free(void); +void NOINLINE_ATTR esp_tee_test_dummy_sec_srv(int a, int b, int c, int d, int e, int f, int g, int h, int *i); #ifdef __cplusplus } diff --git a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/sec_srv_tbl_test.yml b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/sec_srv_tbl_test.yml index d62238944a..98d7001ffa 100644 --- a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/sec_srv_tbl_test.yml +++ b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/sec_srv_tbl_test.yml @@ -3,73 +3,69 @@ secure_services: entries: - id: 200 type: custom - function: esp_tee_service_add + function: esp_tee_test_service_add args: 2 - id: 201 type: custom - function: esp_tee_service_sub + function: esp_tee_test_service_sub args: 2 - id: 202 type: custom - function: esp_tee_service_mul + function: esp_tee_test_service_mul args: 2 - id: 203 type: custom - function: esp_tee_service_div + function: esp_tee_test_service_div args: 2 - id: 204 type: custom - function: esp_tee_test_timer_init - args: 1 + function: esp_tee_test_tee_intr_in_tee + args: 0 - id: 205 type: custom - function: esp_tee_secure_int_test - args: 0 + function: esp_tee_test_ree_intr_in_tee + args: 1 - id: 206 type: custom - function: esp_tee_non_secure_int_test - args: 1 + function: esp_tee_test_tee_intr_in_ree + args: 2 - id: 207 - type: custom - function: esp_tee_test_int_count - args: 1 - - id: 208 type: custom function: esp_tee_test_resv_reg1_write_violation args: 0 - - id: 209 + - id: 208 type: custom function: esp_tee_test_resv_reg1_exec_violation args: 0 - - id: 210 + - id: 209 type: custom function: esp_tee_test_iram_reg1_write_violation args: 0 - - id: 211 + - id: 210 type: custom function: esp_tee_test_iram_reg2_write_violation args: 0 - - id: 212 + - id: 211 type: custom function: esp_tee_test_dram_reg1_exec_violation args: 0 - - id: 213 + - id: 212 type: custom function: esp_tee_test_dram_reg2_exec_violation args: 0 - - id: 214 + - id: 213 type: custom function: esp_tee_test_illegal_instruction args: 0 + - id: 214 + type: custom + function: esp_tee_test_dummy_sec_srv + args: 9 - id: 215 type: custom - function: dummy_secure_service - args: 9 + function: esp_tee_test_priv_mode_switch + args: 2 - id: 216 - type: custom - function: add_in_loop - args: 3 - - id: 217 type: custom function: esp_tee_test_heap_malloc_write_free args: 0 diff --git a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_dummy_srv.c b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_dummy_srv.c index 049d59290c..585efc071c 100644 --- a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_dummy_srv.c +++ b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_dummy_srv.c @@ -9,7 +9,7 @@ #include "multi_heap.h" -void NOINLINE_ATTR _ss_dummy_secure_service(int a, int b, int c, int d, int e, int f, int g, int h, int *i) +void NOINLINE_ATTR _ss_esp_tee_test_dummy_sec_srv(int a, int b, int c, int d, int e, int f, int g, int h, int *i) { esp_rom_printf("Dummy secure service\n"); *i = a + b + c + d + e + f + g + h; diff --git a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_dummy_srv_wrapper.c b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_dummy_srv_wrapper.c index d31b968ce7..d9ca82e80e 100644 --- a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_dummy_srv_wrapper.c +++ b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_dummy_srv_wrapper.c @@ -1,14 +1,14 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include #include "secure_service_num.h" #include "esp_tee.h" -#include "esp_err.h" +#include "esp_attr.h" -void dummy_secure_service(int a, int b, int c, int d, int e, int f, int g, int h, int *i) +void NOINLINE_ATTR esp_tee_test_dummy_sec_srv(int a, int b, int c, int d, int e, int f, int g, int h, int *i) { - esp_tee_service_call(10, SS_DUMMY_SECURE_SERVICE, a, b, c, d, e, f, g, h, i); + esp_tee_service_call(10, SS_ESP_TEE_TEST_DUMMY_SEC_SRV, a, b, c, d, e, f, g, h, i); } diff --git a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_interrupt.c b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_interrupt.c index 760244c95b..17ce1321d4 100644 --- a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_interrupt.c +++ b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_interrupt.c @@ -4,174 +4,168 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + #include "esp_cpu.h" -#include "esp_log.h" -#include "riscv/csr.h" +#include "esp_rom_sys.h" -#include "hal/timer_ll.h" -#include "hal/clk_gate_ll.h" - -#include "soc/timer_group_reg.h" +#include "soc/soc.h" +#include "soc/interrupts.h" #include "soc/interrupt_matrix_reg.h" +#include "soc/pcr_reg.h" +#include "hal/timer_ll.h" #include "esp_tee.h" #include "esp_tee_intr.h" #include "esp_tee_test.h" -#define TIMER_DIVIDER 80 // Hardware timer clock divider -#define TIMER_RESOLUTION_HZ 1000000 // 1MHz resolution -#define TIMER_ALARM_PERIOD_S 0.10 // sample test interval for the first timer +static const char *TAG __attribute__((unused)) = "esp_tee_intr_test"; -/* TEE uses Group0 Timer0 */ -#define TEE_SECURE_GROUP 0 -#define TEE_SECURE_TIMER 0 +/* ---------------------------------------------------- Utility functions ---------------------------------------------------- */ -static const char *TAG = "esp_tee_intr_test"; +#define TEST_TIMER_GROUP (0) +#define TEST_TIMER_ID (0) +#define TEST_TIMER_DIVIDER (80) -static timg_dev_t *timg_hw = (&TIMERG0); +#define TEST_TIMER_RESOLUTION_HZ (1000000ULL) // 1MHz, 1 tick = 1us +#define TIMER_ALARM_PERIOD_S (0.25f) // 250ms @ resolution 1MHz -uint32_t *psecure_int_count = NULL; +static timg_dev_t *timg_dev = TIMER_LL_GET_HW(TEST_TIMER_GROUP); -static void IRAM_ATTR timer_group0_isr(void *arg) +static void IRAM_ATTR test_timer_isr(void *arg) { - ESP_LOGI(TAG, "Timer ISR Handler from World %d!", esp_cpu_get_curr_privilege_level()); + uint32_t *intr_count = (uint32_t *)arg; + *intr_count = *intr_count + 1; + esp_rom_printf("[mode: %d] Interrupt triggered (%d)\n", esp_cpu_get_curr_privilege_level(), *intr_count); - /* For interrupt test. */ - *psecure_int_count = *psecure_int_count + 1; - - /* Clear interrupt */ - timer_ll_clear_intr_status(timg_hw, TIMER_LL_EVENT_ALARM(TEE_SECURE_TIMER)); - - /* Re-enable the alarm. */ - timer_ll_enable_alarm(timg_hw, TEE_SECURE_TIMER, true); + /* Clear interrupt and re-enable the alarm */ + timer_ll_clear_intr_status(timg_dev, TIMER_LL_EVENT_ALARM(TEST_TIMER_ID)); + timer_ll_enable_alarm(timg_dev, TEST_TIMER_ID, true); } -static void tee_timer_enable(void) +static void test_timer_deinit(void) { - struct vector_desc_t timer_vd = { 0, NULL, NULL, NULL }; + const uint32_t timer_id = TEST_TIMER_ID; - // init timer_vc - timer_vd.source = ETS_TG0_T0_LEVEL_INTR_SOURCE; - timer_vd.isr = timer_group0_isr; + // Disable and clear timer state + timer_ll_enable_counter(timg_dev, timer_id, false); + timer_ll_enable_auto_reload(timg_dev, timer_id, false); + timer_ll_enable_alarm(timg_dev, timer_id, false); - ESP_LOGI(TAG, "Enabling test timer from secure world"); + timer_ll_enable_intr(timg_dev, TIMER_LL_EVENT_ALARM(timer_id), false); + timer_ll_clear_intr_status(timg_dev, TIMER_LL_EVENT_ALARM(timer_id)); - /* Enable TG0 peripheral module */ - _timer_ll_enable_bus_clock(TEE_SECURE_GROUP, true); - _timer_ll_reset_register(TEE_SECURE_GROUP); - - /* Stop counter, alarm, auto-reload at first place */ - timer_ll_enable_clock(TEE_SECURE_GROUP, TEE_SECURE_TIMER, true); - timer_ll_enable_counter(timg_hw, TEE_SECURE_TIMER, false); - timer_ll_enable_auto_reload(timg_hw, TEE_SECURE_TIMER, false); - timer_ll_enable_alarm(timg_hw, TEE_SECURE_TIMER, false); - - // Set clock source - timer_ll_set_clock_source(TEE_SECURE_GROUP, TEE_SECURE_TIMER, GPTIMER_CLK_SRC_DEFAULT); - timer_ll_set_clock_prescale(timg_hw, TEE_SECURE_TIMER, TIMER_DIVIDER); - - // Initialize counter value to zero - timer_ll_set_reload_value(timg_hw, TEE_SECURE_TIMER, 0); - timer_ll_trigger_soft_reload(timg_hw, TEE_SECURE_TIMER); - - // set counting direction - timer_ll_set_count_direction(timg_hw, TEE_SECURE_TIMER, GPTIMER_COUNT_UP); - - // disable interrupt - timer_ll_enable_intr(timg_hw, TIMER_LL_EVENT_ALARM(TEE_SECURE_TIMER), false); - // clear pending interrupt event - timer_ll_clear_intr_status(timg_hw, TIMER_LL_EVENT_ALARM(TEE_SECURE_TIMER)); - - esp_tee_intr_register((void *)&timer_vd); - timer_ll_enable_intr(timg_hw, TIMER_LL_EVENT_ALARM(TEE_SECURE_TIMER), true); - - timer_ll_set_reload_value(timg_hw, TEE_SECURE_TIMER, 0); - - // enable timer interrupt - timer_ll_enable_intr(timg_hw, TIMER_LL_EVENT_ALARM(TEE_SECURE_TIMER), true); - - // set timer alarm - uint64_t alarm_value = (TIMER_ALARM_PERIOD_S * TIMER_RESOLUTION_HZ); - timer_ll_set_alarm_value(timg_hw, TEE_SECURE_TIMER, alarm_value); - - timer_ll_enable_auto_reload(timg_hw, TEE_SECURE_TIMER, true); - timer_ll_enable_alarm(timg_hw, TEE_SECURE_TIMER, true); - timer_ll_enable_counter(timg_hw, TEE_SECURE_TIMER, true); -} - -static void tee_timer_disable(void) -{ - ESP_LOGI(TAG, "Disabling test timer from secure world"); - - /* Init timer interrupt vector descriptor */ - struct vector_desc_t timer_vd = { 0, NULL, NULL, NULL }; - timer_vd.source = ETS_TG0_T0_LEVEL_INTR_SOURCE; - timer_vd.isr = timer_group0_isr; + // Reset the counter + uint64_t prev_val = timer_ll_get_reload_value(timg_dev, timer_id); + timer_ll_set_reload_value(timg_dev, timer_id, 0); + timer_ll_trigger_soft_reload(timg_dev, timer_id); + timer_ll_set_reload_value(timg_dev, timer_id, prev_val); + // Deregister ISR + struct vector_desc_t timer_vd = { + .source = ETS_TG0_T0_LEVEL_INTR_SOURCE, + }; esp_tee_intr_deregister((void *)&timer_vd); - - /* Disable timer */ - timer_ll_enable_counter(timg_hw, TEE_SECURE_TIMER, false); - timer_ll_enable_auto_reload(timg_hw, TEE_SECURE_TIMER, false); - timer_ll_enable_alarm(timg_hw, TEE_SECURE_TIMER, false); - - /* Disable and clear interrupt */ - timer_ll_enable_intr(timg_hw, TIMER_LL_EVENT_ALARM(TEE_SECURE_TIMER), false); - timer_ll_clear_intr_status(timg_hw, TIMER_LL_EVENT_ALARM(TEE_SECURE_TIMER)); - - /* Disable TG0 peripheral module */ - // periph_ll_disable_clk_set_rst(PERIPH_TIMG0_MODULE); + timer_ll_enable_clock(TEST_TIMER_GROUP, timer_id, false); } -void _ss_esp_tee_test_timer_init(bool enable) +static void test_timer_init(volatile uint32_t *arg) { - if (enable) { - tee_timer_enable(); - } else { - tee_timer_disable(); - } + const uint32_t group_id = TEST_TIMER_GROUP; + const uint32_t timer_id = TEST_TIMER_ID; + + test_timer_deinit(); + + // Enable peripheral clock and reset hardware + _timer_ll_enable_bus_clock(group_id, true); + _timer_ll_reset_register(group_id); + + // Select clock source and enable module clock + // Enable the default clock source PLL_F80M + REG_SET_BIT(PCR_PLL_DIV_CLK_EN_REG, PCR_PLL_80M_CLK_EN); + timer_ll_set_clock_source(group_id, timer_id, GPTIMER_CLK_SRC_DEFAULT); + timer_ll_enable_clock(group_id, timer_id, true); + timer_ll_set_clock_prescale(timg_dev, timer_id, TEST_TIMER_DIVIDER); + timer_ll_set_count_direction(timg_dev, timer_id, GPTIMER_COUNT_UP); + + // Register ISR + struct vector_desc_t timer_vd = { + .source = ETS_TG0_T0_LEVEL_INTR_SOURCE, + .isr = test_timer_isr, + .arg = (void *)arg, + }; + esp_tee_intr_register((void *)&timer_vd); + timer_ll_enable_intr(timg_dev, TIMER_LL_EVENT_ALARM(timer_id), true); + + // Configure and enable timer alarm + timer_ll_set_alarm_value(timg_dev, timer_id, TIMER_ALARM_PERIOD_S * TEST_TIMER_RESOLUTION_HZ); + timer_ll_enable_auto_reload(timg_dev, timer_id, true); + timer_ll_enable_alarm(timg_dev, timer_id, true); + timer_ll_enable_counter(timg_dev, timer_id, true); } -/** - * Secure interrupt in secure world test. - */ -int _ss_esp_tee_secure_int_test(void) +/* ---------------------------------------------------- Test cases ---------------------------------------------------- */ + +uint32_t _ss_esp_tee_test_tee_intr_in_tee(void) { - ESP_LOGD(TAG, "In WORLD %d", esp_cpu_get_curr_privilege_level()); - volatile uint32_t secure_int_count = 0; - psecure_int_count = (uint32_t *)&secure_int_count; + esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level(); + assert((mode == ESP_CPU_S_MODE) && "Incorrect privilege mode!"); - _ss_esp_tee_test_timer_init(true); - while (secure_int_count < TEE_TEST_INT_COUNT); - _ss_esp_tee_test_timer_init(false); + volatile uint32_t tee_intr_count = 0; + test_timer_init(&tee_intr_count); - ESP_LOGD(TAG, "Exiting WORLD %d", esp_cpu_get_curr_privilege_level()); - return secure_int_count; -} - -/** - * Non-Secure interrupt in secure world test. - */ -int _ss_esp_tee_non_secure_int_test(volatile uint32_t *volatile ns_int_count) -{ - ESP_LOGD(TAG, "In WORLD %d", esp_cpu_get_curr_privilege_level()); - - uint32_t count = 0; - count = *ns_int_count; - - while ((*ns_int_count < TEE_TEST_INT_COUNT)) { - if (*ns_int_count > count) { - count = *ns_int_count; - ESP_LOGI(TAG, "Interrupt count %d", count); - } + while (tee_intr_count < ESP_TEE_TEST_INTR_ITER) { + esp_rom_delay_us(10 * 1000U); } - ESP_LOGD(TAG, "Exiting WORLD %d", esp_cpu_get_curr_privilege_level()); + test_timer_deinit(); + + mode = esp_cpu_get_curr_privilege_level(); + assert((mode == ESP_CPU_S_MODE) && "Incorrect privilege mode!"); + return tee_intr_count; +} + +uint32_t _ss_esp_tee_test_tee_intr_in_ree(int stage, volatile uint32_t *volatile intr_count) +{ + esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level(); + assert((mode == ESP_CPU_S_MODE) && "Incorrect privilege mode!"); + + switch (stage) { + case 0: + test_timer_init(intr_count); + break; + case 1: + test_timer_deinit(); + break; + default: + assert(false && "Invalid stage!"); + break; + } + + mode = esp_cpu_get_curr_privilege_level(); + assert((mode == ESP_CPU_S_MODE) && "Incorrect privilege mode!"); return 0; } -int _ss_esp_tee_test_int_count(uint32_t *secure_int_count) +uint32_t _ss_esp_tee_test_ree_intr_in_tee(volatile uint32_t *volatile intr_count) { - psecure_int_count = secure_int_count; - return (*psecure_int_count); + esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level(); + assert((mode == ESP_CPU_S_MODE) && "Incorrect privilege mode!"); + + uint32_t prev_count = 0; + while (true) { + uint32_t curr_count = *intr_count; + if (curr_count > prev_count) { + prev_count = curr_count; + esp_rom_printf("[mode: %d] Interrupt received (%d)\n", esp_cpu_get_curr_privilege_level(), curr_count); + } + if (curr_count >= ESP_TEE_TEST_INTR_ITER) { + break; + } + esp_rom_delay_us(1000U); + } + + mode = esp_cpu_get_curr_privilege_level(); + assert((mode == ESP_CPU_S_MODE) && "Incorrect privilege mode!"); + return 0; } diff --git a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_sec_srv.c b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_sec_srv.c index e90aef0119..6978a65780 100644 --- a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_sec_srv.c +++ b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_sec_srv.c @@ -12,37 +12,45 @@ static const char *TAG = "test_sec_srv"; /* Sample Trusted App */ -uint32_t NOINLINE_ATTR _ss_esp_tee_service_add(uint32_t a, uint32_t b) +uint32_t NOINLINE_ATTR _ss_esp_tee_test_service_add(uint32_t a, uint32_t b) { ESP_LOGD(TAG, "SS: %s", __func__); return (a + b); } -uint32_t NOINLINE_ATTR _ss_esp_tee_service_sub(uint32_t a, uint32_t b) +uint32_t NOINLINE_ATTR _ss_esp_tee_test_service_sub(uint32_t a, uint32_t b) { ESP_LOGD(TAG, "SS: %s", __func__); return (a - b); } -uint32_t NOINLINE_ATTR _ss_esp_tee_service_mul(uint32_t a, uint32_t b) +uint32_t NOINLINE_ATTR _ss_esp_tee_test_service_mul(uint32_t a, uint32_t b) { ESP_LOGD(TAG, "SS: %s", __func__); return (a * b); } -uint32_t NOINLINE_ATTR _ss_esp_tee_service_div(uint32_t a, uint32_t b) +uint32_t NOINLINE_ATTR _ss_esp_tee_test_service_div(uint32_t a, uint32_t b) { ESP_LOGD(TAG, "SS: %s", __func__); return (a / b); } -uint32_t _ss_add_in_loop(uint32_t a, uint32_t b, uint32_t iter) +uint32_t _ss_esp_tee_test_priv_mode_switch(uint32_t *a, uint32_t *b) { ESP_LOGD(TAG, "SS: %s", __func__); - for (int i = 0; i < iter; i++) { - a += b; - esp_rom_delay_us(1000000); - esp_rom_printf("[mode: %d] val: %d\n", esp_cpu_get_curr_privilege_level(), a); + + *a = 1; + *b = 1; + + uint32_t c = 0; + while (c < ESP_TEE_TEST_INTR_ITER * 2) { + c = *a + *b; + esp_rom_delay_us(500 * 1000U); + esp_rom_printf("[mode: %d] val: %d\n", esp_cpu_get_curr_privilege_level(), c); + *a += 1; + *b += 1; } - return a; + + return c; } diff --git a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_ctx_switch.c b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_ctx_switch.c index 6534cf712f..618717d709 100644 --- a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_ctx_switch.c +++ b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_ctx_switch.c @@ -4,32 +4,46 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "unity.h" -#include "esp_tee.h" -#include "secure_service_num.h" -#include "esp_tee_test.h" - #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "freertos/event_groups.h" + +#include "esp_cpu.h" +#include "esp_tee.h" +#include "esp_tee_test.h" +#include "secure_service_num.h" + +#include "unity.h" #include "sdkconfig.h" +#define TEST_TASK_1_DONE_BIT (BIT0) +#define TEST_TASK_2_DONE_BIT (BIT1) + +typedef struct { + uint32_t id; + uint32_t *val; + EventBits_t done_bit; +} test_task_args_t; + +static EventGroupHandle_t test_task_eg; + static void test_op(int sec_srv_num, uint32_t a, uint32_t b) { - esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS"); + esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); uint32_t lval = 0; switch (sec_srv_num) { - case SS_ESP_TEE_SERVICE_ADD: + case SS_ESP_TEE_TEST_SERVICE_ADD: lval = (a + b); break; - case SS_ESP_TEE_SERVICE_SUB: + case SS_ESP_TEE_TEST_SERVICE_SUB: lval = (a - b); break; - case SS_ESP_TEE_SERVICE_MUL: + case SS_ESP_TEE_TEST_SERVICE_MUL: lval = (a * b); break; - case SS_ESP_TEE_SERVICE_DIV: + case SS_ESP_TEE_TEST_SERVICE_DIV: lval = (a / b); break; default: @@ -40,60 +54,94 @@ static void test_op(int sec_srv_num, uint32_t a, uint32_t b) uint32_t val = esp_tee_service_call(3, sec_srv_num, a, b); TEST_ASSERT_EQUAL_UINT32(lval, val); - world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Sample app world switch failed"); + mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); } TEST_CASE("Test single calls to sample app (basic services)", "[basic]") { const uint32_t a = 200, b = 100; - test_op(SS_ESP_TEE_SERVICE_ADD, a, b); - test_op(SS_ESP_TEE_SERVICE_SUB, a, b); - test_op(SS_ESP_TEE_SERVICE_MUL, a, b); - test_op(SS_ESP_TEE_SERVICE_DIV, a, b); + test_op(SS_ESP_TEE_TEST_SERVICE_ADD, a, b); + test_op(SS_ESP_TEE_TEST_SERVICE_SUB, a, b); + test_op(SS_ESP_TEE_TEST_SERVICE_MUL, a, b); + test_op(SS_ESP_TEE_TEST_SERVICE_DIV, a, b); } TEST_CASE("Test multiple calls to sample app (basic services)", "[basic]") { - esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS"); + esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); for (int i = 0; i < 1024; i++) { - uint32_t val = esp_tee_service_call(3, SS_ESP_TEE_SERVICE_ADD, i, i + 1); + uint32_t val = esp_tee_service_call(3, SS_ESP_TEE_TEST_SERVICE_ADD, i, i + 1); TEST_ASSERT_EQUAL_UINT32((2 * i + 1), val); - world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Sample app world switch failed"); + mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); } } -TEST_CASE("Custom secure service call", "[basic]") +TEST_CASE("Test custom secure service call", "[basic]") { int res = -1; - dummy_secure_service(1, 2, 3, 4, 5, 6, 7, 8, &res); + esp_tee_test_dummy_sec_srv(1, 2, 3, 4, 5, 6, 7, 8, &res); TEST_ASSERT_EQUAL_UINT32(36, res); } -void test_task(void *pvParameters) +static void test_task(void *pvParameters) { - for (int i = 0; i < 8; i++) { - esp_rom_printf("[mode: %d] test_task - %d\n", esp_cpu_get_curr_privilege_level(), i); - vTaskDelay(pdMS_TO_TICKS(1000)); + test_task_args_t *args = (test_task_args_t *)pvParameters; + uint32_t *val = args->val; + uint32_t id = args->id; + + uint32_t prev_val = *val; + while (*val <= ESP_TEE_TEST_INTR_ITER) { + uint32_t curr_val = *val; + if (curr_val != prev_val) { + esp_rom_printf("[mode: %d] test_task - %d | val - %d\n", esp_cpu_get_curr_privilege_level(), id, curr_val); + prev_val = curr_val; + } + vTaskDelay(pdMS_TO_TICKS(100)); } + + xEventGroupSetBits(test_task_eg, args->done_bit); vTaskDelete(NULL); } -TEST_CASE("Task switching during secure service calls", "[basic]") +TEST_CASE("Test task switching during secure service calls", "[basic]") { - esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS"); + esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); - xTaskCreate(test_task, "test_task", 4096, NULL, CONFIG_UNITY_FREERTOS_PRIORITY + 3, NULL); + test_task_eg = xEventGroupCreate(); + TEST_ASSERT_NOT_NULL(test_task_eg); - const uint32_t a = 100, b = 200, iter = 8; - TEST_ASSERT_EQUAL_UINT32(a + b * iter, esp_tee_service_call(4, SS_ADD_IN_LOOP, a, b, iter)); + uint32_t a = 0, b = 0; - world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS"); + test_task_args_t task_args_1 = { + .id = 1, + .val = &a, + .done_bit = TEST_TASK_1_DONE_BIT + }; + + test_task_args_t task_args_2 = { + .id = 2, + .val = &b, + .done_bit = TEST_TASK_2_DONE_BIT + }; + + xTaskCreate(test_task, "test_task_1", 4096, (void *)&task_args_1, CONFIG_UNITY_FREERTOS_PRIORITY + 3, NULL); + xTaskCreate(test_task, "test_task_2", 4096, (void *)&task_args_2, CONFIG_UNITY_FREERTOS_PRIORITY + 3, NULL); + + uint32_t val = esp_tee_service_call(3, SS_ESP_TEE_TEST_PRIV_MODE_SWITCH, &a, &b); + TEST_ASSERT_EQUAL_UINT32(ESP_TEE_TEST_INTR_ITER * 2, val); + + EventBits_t bits = xEventGroupWaitBits(test_task_eg, TEST_TASK_1_DONE_BIT | TEST_TASK_2_DONE_BIT, pdTRUE, pdTRUE, portMAX_DELAY); + TEST_ASSERT_MESSAGE((bits & TEST_TASK_1_DONE_BIT), "Task 1 did not complete"); + TEST_ASSERT_MESSAGE((bits & TEST_TASK_2_DONE_BIT), "Task 2 did not complete"); + vEventGroupDelete(test_task_eg); + + mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); } TEST_CASE("Test TEE Heap: Malloc-write-free cycles", "[heap]") diff --git a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_interrupt.c b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_interrupt.c index 9b172c79e2..d8da5c75ba 100644 --- a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_interrupt.c +++ b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_interrupt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,90 +17,47 @@ #include "unity.h" -static const char *TAG = "test_esp_tee_intr"; +#define TEST_TIMER_RESOLUTION_HZ (1000000ULL) // 1MHz, 1 tick = 1us +#define TIMER_ALARM_PERIOD_S (0.25f) // 250ms @ resolution 1MHz + +static const char __attribute__((unused)) *TAG = "test_esp_tee_intr"; /* ---------------------------------------------------- Utility functions ---------------------------------------------------- */ -typedef struct { - uint64_t event_count; -} test_queue_element_t; - -static QueueHandle_t s_timer_queue; - static gptimer_handle_t gptimer = NULL; -static volatile uint32_t ns_int_count; - static bool IRAM_ATTR test_timer_on_alarm_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data) { - ESP_EARLY_LOGI(TAG, "Timer ISR Handler from World %d!", esp_cpu_get_curr_privilege_level()); - - BaseType_t high_task_awoken = pdFALSE; - QueueHandle_t queue = (QueueHandle_t)user_data; - // Retrieve count value and send to queue - test_queue_element_t ele = { - .event_count = edata->count_value - }; - ns_int_count += 1; - - xQueueSendFromISR(queue, &ele, &high_task_awoken); - // return whether we need to yield at the end of ISR - return (high_task_awoken == pdTRUE); + uint32_t *intr_count = (uint32_t *)user_data; + *intr_count = *intr_count + 1; + esp_rom_printf("[mode: %d] Interrupt triggered (%d)\n", esp_cpu_get_curr_privilege_level(), *intr_count); + return true; } -static void IRAM_ATTR timer_evt_task(void *arg) +static void test_timer_init(volatile uint32_t *arg) { - int record = 3; - while (1) { - test_queue_element_t ele; - if (xQueueReceive(s_timer_queue, &ele, pdMS_TO_TICKS(2000))) { - ESP_LOGI(TAG, "Timer reloaded, count=%llu", ele.event_count); - record--; - } else { - ESP_LOGW(TAG, "Missed one count event"); - } - if (!record) { - break; - } - } -} - -static void test_timer_init(bool for_ns_world) -{ - s_timer_queue = xQueueCreate(10, sizeof(test_queue_element_t)); - if (!s_timer_queue) { - ESP_LOGE(TAG, "Creating queue failed"); - return; - } - - ns_int_count = 0; - /* Select and initialize basic parameters of the timer */ gptimer_config_t timer_config = { .clk_src = GPTIMER_CLK_SRC_DEFAULT, .direction = GPTIMER_COUNT_UP, - .resolution_hz = 1000000, // 1MHz, 1 tick=1us + .resolution_hz = TEST_TIMER_RESOLUTION_HZ, }; ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer)); gptimer_event_callbacks_t cbs = { .on_alarm = test_timer_on_alarm_cb, }; - ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, s_timer_queue)); + ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, (void *)arg)); ESP_ERROR_CHECK(gptimer_enable(gptimer)); gptimer_alarm_config_t alarm_config2 = { .reload_count = 0, - .alarm_count = 250000, // Alarm target = 250ms @ resolution 1MHz + .alarm_count = TIMER_ALARM_PERIOD_S * TEST_TIMER_RESOLUTION_HZ, .flags.auto_reload_on_alarm = true, }; ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config2)); ESP_ERROR_CHECK(gptimer_start(gptimer)); - - if (for_ns_world) { - timer_evt_task(NULL); - } } static void test_timer_deinit(void) @@ -108,109 +65,80 @@ static void test_timer_deinit(void) ESP_ERROR_CHECK(gptimer_stop(gptimer)); ESP_ERROR_CHECK(gptimer_disable(gptimer)); ESP_ERROR_CHECK(gptimer_del_timer(gptimer)); - - if (s_timer_queue != NULL) { - vQueueDelete(s_timer_queue); - s_timer_queue = NULL; - } } /* ---------------------------------------------------- Test cases ---------------------------------------------------- */ -TEST_CASE("Test Secure interrupt in Non-Secure World", "[basic]") +TEST_CASE("Test TEE interrupt in TEE", "[basic]") { - esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS"); + esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); - volatile uint32_t lsecure_int_count = 0; + uint32_t val = esp_tee_service_call(1, SS_ESP_TEE_TEST_TEE_INTR_IN_TEE); + TEST_ASSERT_EQUAL_UINT32(ESP_TEE_TEST_INTR_ITER, val); - /* Pass the variable to secure world to record the interrupt count. */ - esp_tee_service_call(2, SS_ESP_TEE_TEST_INT_COUNT, &lsecure_int_count); - world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "World switch failed"); - - esp_tee_service_call(2, SS_ESP_TEE_TEST_TIMER_INIT, true); - world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "World switch failed"); - - /* Secure timer initialized. - * As secure timer interrupt will fire; CPU will switch to secure world. - * Secure world ISR handler will be called, Secure ISR log can be observed on console. - * After handling the secure interrupt, CPU will return to non-secure world - * and resume this loop and wait for the next secure timer interrupt. - * CPU will wait for TEE_TEST_INT_COUNT number of secure interrupts. - */ - while (lsecure_int_count < TEE_TEST_INT_COUNT); - - /* After waiting for TEE_TEST_INT_COUNT secure interrupt, - * disable the secure timer and assert the test status. - */ - esp_tee_service_call(2, SS_ESP_TEE_TEST_TIMER_INIT, false); - world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "World switch failed"); - - /* Assert the number of secure interrupt occurred again. */ - TEST_ASSERT_EQUAL_UINT32(TEE_TEST_INT_COUNT, lsecure_int_count); + mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); } -TEST_CASE("Test Secure interrupt in Secure World", "[basic]") +TEST_CASE("Test REE interrupt in REE", "[basic]") { - esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS"); + esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); - uint32_t cnt = esp_tee_service_call(1, SS_ESP_TEE_SECURE_INT_TEST); - TEST_ASSERT_EQUAL_UINT32(TEE_TEST_INT_COUNT, cnt); - - world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "World switch failed"); + volatile uint32_t ree_intr_count = 0; + test_timer_init(&ree_intr_count); + while (ree_intr_count < ESP_TEE_TEST_INTR_ITER) { + vTaskDelay(pdMS_TO_TICKS(250)); + } + test_timer_deinit(); } -static volatile uint32_t *get_ns_int_count(void) +TEST_CASE("Test REE interrupt in TEE", "[basic]") { - return &ns_int_count; -} + esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); -TEST_CASE("Test Non-secure interrupt in Secure World", "[basic]") -{ - esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not W1"); + volatile uint32_t ree_intr_count = 0; + volatile uint32_t *volatile ree_intr_count_ptr = &ree_intr_count; - /* Non-secure world timer initialization. */ - ESP_LOGI(TAG, "Enabling test timer from non-secure world"); - test_timer_init(false); + test_timer_init(ree_intr_count_ptr); - volatile uint32_t *volatile lns_int_count; - lns_int_count = get_ns_int_count(); - - /* After non-secure timer initialization, - * CPU will switch to secure world by using a service call to test API. - * CPU will wait in finite loop in secure world. - * And as non-secure timer interrupt fires, CPU will switch to non-secure world. - * Non-secure world ISR handler will be called, non-secure ISR log can be obsereved on console. - * After handling the interrupt in non-secure world, CPU will switch back to secure world - * and wait for the next timer interrupt. - * In secure world CPU will wait for TEE_TEST_INT_COUNT non-secure interrupts. - */ - uint32_t val = esp_tee_service_call(2, SS_ESP_TEE_NON_SECURE_INT_TEST, lns_int_count); + uint32_t val = esp_tee_service_call(2, SS_ESP_TEE_TEST_REE_INTR_IN_TEE, ree_intr_count_ptr); TEST_ASSERT_EQUAL_UINT32(0, val); - world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "World switch failed"); - - ESP_LOGI(TAG, "Disabling test timer from non-secure world"); test_timer_deinit(); + + mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); } -TEST_CASE("Test Non-secure interrupt in Non-Secure World", "[basic]") +TEST_CASE("Test TEE interrupt in REE", "[basic]") { - esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS"); + esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); - ESP_LOGI(TAG, "Enabling test timer from non-secure world"); - test_timer_init(true); + volatile uint32_t tee_intr_count = 0; + volatile uint32_t *volatile tee_intr_count_ptr = &tee_intr_count; + esp_tee_service_call(3, SS_ESP_TEE_TEST_TEE_INTR_IN_REE, 0, tee_intr_count_ptr); - vTaskDelay(pdMS_TO_TICKS(1000)); + uint32_t prev_count = 0; + while (true) { + uint32_t curr_count = *tee_intr_count_ptr; + if (curr_count > prev_count) { + prev_count = curr_count; + esp_rom_printf("[mode: %d] Interrupt received (%d)\n", esp_cpu_get_curr_privilege_level(), curr_count); + } + if (curr_count >= ESP_TEE_TEST_INTR_ITER) { + break; + } + vTaskDelay(pdMS_TO_TICKS(1)); + } - ESP_LOGI(TAG, "Disabling test timer from non-secure world"); - test_timer_deinit(); + esp_tee_service_call(3, SS_ESP_TEE_TEST_TEE_INTR_IN_REE, 1, NULL); + + TEST_ASSERT_EQUAL_UINT32(ESP_TEE_TEST_INTR_ITER, tee_intr_count); + + mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); } From bb55b0cefc4bb2230405f7890bc79a07054d4a3c Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Wed, 23 Jul 2025 14:34:15 +0530 Subject: [PATCH 4/4] ci(esp_tee): Enable the TEE test-apps for ESP32-C5 --- .../esp_tee/test_apps/.build-test-rules.yml | 8 +- .../esp_tee/test_apps/tee_cli_app/README.md | 4 +- .../test_apps/tee_cli_app/main/tee_srv_ota.c | 1 - .../test_apps/tee_cli_app/pytest_tee_cli.py | 52 ++++-------- .../test_apps/tee_cli_app/sdkconfig.defaults | 2 +- .../tee_cli_app/test_certs/server_cert.pem | 43 ++++++---- .../tee_cli_app/test_certs/server_key.pem | 64 ++++++++------ .../esp_tee/test_apps/tee_test_fw/README.md | 4 +- .../esp_tee/test_apps/tee_test_fw/conftest.py | 51 ++++++++++-- .../main/test_esp_tee_flash_prot.c | 50 +++++++++-- .../tee_test_fw/main/test_esp_tee_panic.c | 82 +++++++++--------- .../tee_test_fw/pytest_esp_tee_ut.py | 83 ++++++++++--------- .../test_apps/tee_test_fw/sdkconfig.defaults | 1 + 13 files changed, 267 insertions(+), 178 deletions(-) diff --git a/components/esp_tee/test_apps/.build-test-rules.yml b/components/esp_tee/test_apps/.build-test-rules.yml index 04999bc2f9..906c6b73c3 100644 --- a/components/esp_tee/test_apps/.build-test-rules.yml +++ b/components/esp_tee/test_apps/.build-test-rules.yml @@ -2,10 +2,10 @@ components/esp_tee/test_apps/tee_cli_app: disable: - - if: IDF_TARGET not in ["esp32c6"] - reason: only supported with esp32c6 for now + - if: IDF_TARGET not in ["esp32c6", "esp32c5"] + reason: only supported with c6 and c5 components/esp_tee/test_apps/tee_test_fw: disable: - - if: IDF_TARGET not in ["esp32c6", "esp32h2"] - reason: only supported with esp32c6 and esp32h2 for now + - if: IDF_TARGET not in ["esp32c6", "esp32h2", "esp32c5"] + reason: only supported with c6, h2 and c5 diff --git a/components/esp_tee/test_apps/tee_cli_app/README.md b/components/esp_tee/test_apps/tee_cli_app/README.md index 3b4ab26325..66cfc49649 100644 --- a/components/esp_tee/test_apps/tee_cli_app/README.md +++ b/components/esp_tee/test_apps/tee_cli_app/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C6 | -| ----------------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | +| ----------------- | -------- | -------- | # TEE CLI Application: Secure Services Demonstration diff --git a/components/esp_tee/test_apps/tee_cli_app/main/tee_srv_ota.c b/components/esp_tee/test_apps/tee_cli_app/main/tee_srv_ota.c index 42aacd3a37..aadabe9ff4 100644 --- a/components/esp_tee/test_apps/tee_cli_app/main/tee_srv_ota.c +++ b/components/esp_tee/test_apps/tee_cli_app/main/tee_srv_ota.c @@ -111,7 +111,6 @@ static void tee_ota_task(void *pvParameter) task_fatal_error(); } else if (data_read > 0) { if (image_header_was_checked == false) { - /* TODO: TEE image header is missing the `esp_app_desc_t` configuration structure */ if (data_read > sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)) { esp_image_header_t img_hdr; memcpy(&img_hdr, ota_write_data, sizeof(esp_image_header_t)); diff --git a/components/esp_tee/test_apps/tee_cli_app/pytest_tee_cli.py b/components/esp_tee/test_apps/tee_cli_app/pytest_tee_cli.py index 587c297c13..d749ee32a7 100644 --- a/components/esp_tee/test_apps/tee_cli_app/pytest_tee_cli.py +++ b/components/esp_tee/test_apps/tee_cli_app/pytest_tee_cli.py @@ -6,11 +6,9 @@ import json import logging import multiprocessing import os -import socket import ssl import time from typing import Any -from typing import Callable import pexpect import pytest @@ -22,7 +20,6 @@ from ecdsa.keys import VerifyingKey from ecdsa.util import sigdecode_der from pytest_embedded import Dut from pytest_embedded_idf.utils import idf_parametrize -from RangeHTTPServer import RangeRequestHandler TEST_MSG = 'hello world' @@ -36,12 +33,12 @@ key_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_certs/ @pytest.mark.generic -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_tee_cli_secure_storage(dut: Dut) -> None: # Dumping the REE binary size binary_file = os.path.join(dut.app.binary_path, 'tee_cli.bin') bin_size = os.path.getsize(binary_file) - logging.info('tee_cli_bin_size : {}KB'.format(bin_size // 1024)) + logging.info(f'tee_cli_bin_size : {bin_size // 1024}KB') # Starting the test dut.expect('ESP-TEE: Secure services demonstration', timeout=30) @@ -122,12 +119,12 @@ def verify_att_token_signature(att_tk: str) -> Any: @pytest.mark.generic -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_tee_cli_attestation(dut: Dut) -> None: # Dumping the REE binary size binary_file = os.path.join(dut.app.binary_path, 'tee_cli.bin') bin_size = os.path.getsize(binary_file) - logging.info('tee_cli_bin_size : {}KB'.format(bin_size // 1024)) + logging.info(f'tee_cli_bin_size : {bin_size // 1024}KB') # Starting the test dut.expect('ESP-TEE: Secure services demonstration', timeout=30) @@ -149,41 +146,22 @@ def test_tee_cli_attestation(dut: Dut) -> None: ####################################### -def https_request_handler() -> Callable[..., http.server.BaseHTTPRequestHandler]: - """ - Returns a request handler class that handles broken pipe exception - """ - - class RequestHandler(RangeRequestHandler): - def finish(self) -> None: - try: - if not self.wfile.closed: - self.wfile.flush() - self.wfile.close() - except socket.error: - pass - self.rfile.close() - - def handle(self) -> None: - try: - RangeRequestHandler.handle(self) - except socket.error: - pass - - return RequestHandler - - def start_https_server(ota_image_dir: str, server_ip: str, server_port: int) -> None: os.chdir(ota_image_dir) - requestHandler = https_request_handler() - httpd = http.server.HTTPServer((server_ip, server_port), requestHandler) + server_address = (server_ip, server_port) - httpd.socket = ssl.wrap_socket(httpd.socket, keyfile=key_file, certfile=server_file, server_side=True) + Handler = http.server.SimpleHTTPRequestHandler + httpd = http.server.HTTPServer(server_address, Handler) + + context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + context.load_cert_chain(certfile=server_file, keyfile=key_file) + + httpd.socket = context.wrap_socket(httpd.socket, server_side=True) httpd.serve_forever() @pytest.mark.wifi_high_traffic -@idf_parametrize('target', ['esp32c6'], indirect=['target']) +@idf_parametrize('target', ['supported_targets'], indirect=['target']) def test_tee_cli_secure_ota_wifi(dut: Dut) -> None: """ This is a positive test case, which downloads complete binary file multiple number of times. @@ -214,7 +192,7 @@ def test_tee_cli_secure_ota_wifi(dut: Dut) -> None: # Starting the test dut.expect('ESP-TEE: Secure services demonstration', timeout=30) - time.sleep(1) + time.sleep(2) # Connecting to Wi-Fi env_name = 'wifi_high_traffic' @@ -225,7 +203,7 @@ def test_tee_cli_secure_ota_wifi(dut: Dut) -> None: # Fetch the DUT IP address try: ip_address = dut.expect(r'got ip:(\d+\.\d+\.\d+\.\d+)[^\d]', timeout=30)[1].decode() - print('Connected to AP/Ethernet with IP: {}'.format(ip_address)) + print(f'Connected to AP/Ethernet with IP: {ip_address}') except pexpect.exceptions.TIMEOUT: raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP') diff --git a/components/esp_tee/test_apps/tee_cli_app/sdkconfig.defaults b/components/esp_tee/test_apps/tee_cli_app/sdkconfig.defaults index 2e0a48855a..c35d9943e4 100644 --- a/components/esp_tee/test_apps/tee_cli_app/sdkconfig.defaults +++ b/components/esp_tee/test_apps/tee_cli_app/sdkconfig.defaults @@ -14,7 +14,7 @@ CONFIG_FREERTOS_UNICORE=y # TEE: OTA-related CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y CONFIG_EXAMPLE_SKIP_COMMON_NAME_CHECK=y -CONFIG_EXAMPLE_OTA_RECV_TIMEOUT=45000 +CONFIG_EXAMPLE_OTA_RECV_TIMEOUT=30000 # Custom certificates for testing CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y diff --git a/components/esp_tee/test_apps/tee_cli_app/test_certs/server_cert.pem b/components/esp_tee/test_apps/tee_cli_app/test_certs/server_cert.pem index b29ba7ab1f..ff3cfba30a 100644 --- a/components/esp_tee/test_apps/tee_cli_app/test_certs/server_cert.pem +++ b/components/esp_tee/test_apps/tee_cli_app/test_certs/server_cert.pem @@ -1,20 +1,27 @@ -----BEGIN CERTIFICATE----- -MIIDWDCCAkACCQCbF4+gVh/MLjANBgkqhkiG9w0BAQsFADBuMQswCQYDVQQGEwJJ -TjELMAkGA1UECAwCTUgxDDAKBgNVBAcMA1BVTjEMMAoGA1UECgwDRVNQMQwwCgYD -VQQLDANFU1AxDDAKBgNVBAMMA0VTUDEaMBgGCSqGSIb3DQEJARYLZXNwQGVzcC5j -b20wHhcNMjEwNzEyMTIzNjI3WhcNNDEwNzA3MTIzNjI3WjBuMQswCQYDVQQGEwJJ -TjELMAkGA1UECAwCTUgxDDAKBgNVBAcMA1BVTjEMMAoGA1UECgwDRVNQMQwwCgYD -VQQLDANFU1AxDDAKBgNVBAMMA0VTUDEaMBgGCSqGSIb3DQEJARYLZXNwQGVzcC5j -b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDhxF/y7bygndxPwiWL -SwS9LY3uBMaJgup0ufNKVhx+FhGQOu44SghuJAaH3KkPUnt6SOM8jC97/yQuc32W -ukI7eBZoA12kargSnzdv5m5rZZpd+NznSSpoDArOAONKVlzr25A1+aZbix2mKRbQ -S5w9o1N2BriQuSzd8gL0Y0zEk3VkOWXEL+0yFUT144HnErnD+xnJtHe11yPO2fEz -YaGiilh0ddL26PXTugXMZN/8fRVHP50P2OG0SvFpC7vghlLp4VFM1/r3UJnvL6Oz -3ALc6dhxZEKQucqlpj8l1UegszQToopemtIj0qXTHw2+uUnkUyWIPjPC+wdOAoap -rFTRAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAItw24y565k3C/zENZlxyzto44ud -IYPQXN8Fa2pBlLe1zlSIyuaA/rWQ+i1daS8nPotkCbWZyf5N8DYaTE4B0OfvoUPk -B5uGDmbuk6akvlB5BGiYLfQjWHRsK9/4xjtIqN1H58yf3QNROuKsPAeywWS3Fn32 -3//OpbWaClQePx6udRYMqAitKR+QxL7/BKZQsX+UyShuq8hjphvXvk0BW8ONzuw9 -RcoORxM0FzySYjeQvm4LhzC/P3ZBhEq0xs55aL2a76SJhq5hJy7T/Xz6NFByvlrN -lFJJey33KFrAf5vnV9qcyWFIo7PYy2VsaaEjFeefr7q3sTFSMlJeadexW2Y= +MIIEmzCCAwOgAwIBAgIUCjRtb8JpjaUnUr1g2JJK8WxzXAkwDQYJKoZIhvcNAQEL +BQAwTDELMAkGA1UEBhMCSU4xCzAJBgNVBAgMAk1IMQswCQYDVQQHDAJQTjEMMAoG +A1UECgwDZXNwMRUwEwYDVQQDDAwxOTIuMTY4LjEuMzYwHhcNMjUwNzI0MTI0OTQw +WhcNMzUwNzIyMTI0OTQwWjBMMQswCQYDVQQGEwJJTjELMAkGA1UECAwCTUgxCzAJ +BgNVBAcMAlBOMQwwCgYDVQQKDANlc3AxFTATBgNVBAMMDDE5Mi4xNjguMS4zNjCC +AaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAK4nnofpHHPvvF4IuF1OhZvp +cTtScOV/h0eTFCpm+eq9NcsIUpEad1DMmKPGN9y1dp//qNZUJomZBnhG+NoHBLPX +Xu62fQ+n1EsJ8QtmEaNo+3fElM2joN6Vfi5/Pz6JyrYq5FYkZnI5agMlLPbrldZa +G3ZHh1vCAhbVrD6S0hLKNrTRt/PbKWfohz8swkl4DqOk0DQDKdkIB/WVLmFo3sMZ +wfTm04lfH9VMJXUrmxFI+WUycTqlpdupMPHdVAr4v85RsC8kRcIneJnc1lKDDHlX +ou0Loxjz3oLCtFNfiqARx7UQ0voAdLJlk7+NHM8D/ArcfMcKWE+aj/e8S6USf/9F +fkvqKJzdCQieEnI4uISAeHgj1Cy52nafD+eQRXcjjPCe3WZxYyD9kpeindoy0suM +EPgIMCTXKY/0iQxYNO9CxGqw5O3ROVPq/vWbRr/yOfJ8SRGnklztxrQiLB0kRtpO +hVCYmfk84l+98c9CPu1CY9VjlYqUOREjKc4edBeR9QIDAQABo3UwczAdBgNVHQ4E +FgQUAL1glrdORLboiLujugzLmArsLXowHwYDVR0jBBgwFoAUAL1glrdORLboiLuj +ugzLmArsLXowDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCBaAwEwYDVR0lBAww +CgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggGBAFiQgcPxNLK2Tan6Kw4Xyb2q +LdpEQXvxiF0f+tLAFJx1mc8aExaM0WinNehGZSwZl1DnH6sJlOiuitAewSjiaFVF +QXxS+8nkBGn0C0tAV4kc3/TxOpbNpTPZUDb3PNMhlGH1LJqZBpWrzbzHL8YSwXmT +aoiXV6/ubWk1yYjTLPChmavWaOAVhYK3GqRbDGDERXC8uXe7de5UuD8R+oaFS1oh +nC6x1wspGQbILjDwmqRE5GvPlTWSBAHw4bbWD4GnXMXAAkDj5Fjom+CzC5D7Q3wQ +C/JlVN1cHNLF6VlOlLDZyLDeWPOVkpm3OB5+IxPEW+8XtNfGrpB5cI/zf2Ba7kZU +jmZNrMqXXd3r7fYLTGjWfMMQb/XLTT2/qE/iOc/tCVLVkDu2hd5gtsIasnlwaBZ7 +dn1nRwrKaXwZnPql+Fx3KjuY6nA2+SDz9t57bIxkWhjE+Nn/zFZk7l84foyo3RhO +TAlCEC81uG9vZqL2fShbrTqpXs59KP3wlPVKuWro5Q== -----END CERTIFICATE----- diff --git a/components/esp_tee/test_apps/tee_cli_app/test_certs/server_key.pem b/components/esp_tee/test_apps/tee_cli_app/test_certs/server_key.pem index 20a4bdb624..77787dc494 100644 --- a/components/esp_tee/test_apps/tee_cli_app/test_certs/server_key.pem +++ b/components/esp_tee/test_apps/tee_cli_app/test_certs/server_key.pem @@ -1,28 +1,40 @@ -----BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDhxF/y7bygndxP -wiWLSwS9LY3uBMaJgup0ufNKVhx+FhGQOu44SghuJAaH3KkPUnt6SOM8jC97/yQu -c32WukI7eBZoA12kargSnzdv5m5rZZpd+NznSSpoDArOAONKVlzr25A1+aZbix2m -KRbQS5w9o1N2BriQuSzd8gL0Y0zEk3VkOWXEL+0yFUT144HnErnD+xnJtHe11yPO -2fEzYaGiilh0ddL26PXTugXMZN/8fRVHP50P2OG0SvFpC7vghlLp4VFM1/r3UJnv -L6Oz3ALc6dhxZEKQucqlpj8l1UegszQToopemtIj0qXTHw2+uUnkUyWIPjPC+wdO -AoaprFTRAgMBAAECggEAE0HCxV/N1Q1h+1OeDDGL5+74yjKSFKyb/vTVcaPCrmaH -fPvp0ddOvMZJ4FDMAsiQS6/n4gQ7EKKEnYmwTqj4eUYW8yxGUn3f0YbPHbZT+Mkj -z5woi3nMKi/MxCGDQZX4Ow3xUQlITUqibsfWcFHis8c4mTqdh4qj7xJzehD2PVYF -gNHZsvVj6MltjBDAVwV1IlGoHjuElm6vuzkfX7phxcA1B4ZqdYY17yCXUnvui46z -Xn2kUTOOUCEgfgvGa9E+l4OtdXi5IxjaSraU+dlg2KsE4TpCuN2MEVkeR5Ms3Y7Q -jgJl8vlNFJDQpbFukLcYwG7rO5N5dQ6WWfVia/5XgQKBgQD74at/bXAPrh9NxPmz -i1oqCHMDoM9sz8xIMZLF9YVu3Jf8ux4xVpRSnNy5RU1gl7ZXbpdgeIQ4v04zy5aw -8T4tu9K3XnR3UXOy25AK0q+cnnxZg3kFQm+PhtOCKEFjPHrgo2MUfnj+EDddod7N -JQr9q5rEFbqHupFPpWlqCa3QmQKBgQDldWUGokNaEpmgHDMnHxiibXV5LQhzf8Rq -gJIQXb7R9EsTSXEvsDyqTBb7PHp2Ko7rZ5YQfyf8OogGGjGElnPoU/a+Jij1gVFv -kZ064uXAAISBkwHdcuobqc5EbG3ceyH46F+FBFhqM8KcbxJxx08objmh58+83InN -P9Qr25Xw+QKBgEGXMHuMWgQbSZeM1aFFhoMvlBO7yogBTKb4Ecpu9wI5e3Kan3Al -pZYltuyf+VhP6XG3IMBEYdoNJyYhu+nzyEdMg8CwXg+8LC7FMis/Ve+o7aS5scgG -1to/N9DK/swCsdTRdzmc/ZDbVC+TuVsebFBGYZTyO5KgqLpezqaIQrTxAoGALFCU -10glO9MVyl9H3clap5v+MQ3qcOv/EhaMnw6L2N6WVT481tnxjW4ujgzrFcE4YuxZ -hgwYu9TOCmeqopGwBvGYWLbj+C4mfSahOAs0FfXDoYazuIIGBpuv03UhbpB1Si4O -rJDfRnuCnVWyOTkl54gKJ2OusinhjztBjcrV1XkCgYEA3qNi4uBsPdyz9BZGb/3G -rOMSw0CaT4pEMTLZqURmDP/0hxvTk1polP7O/FYwxVuJnBb6mzDa0xpLFPTpIAnJ -YXB8xpXU69QVh+EBbemdJWOd+zp5UCfXvb2shAeG3Tn/Dz4cBBMEUutbzP+or0nG -vSXnRLaxQhooWm+IuX9SuBQ= +MIIG/gIBADANBgkqhkiG9w0BAQEFAASCBugwggbkAgEAAoIBgQCuJ56H6Rxz77xe +CLhdToWb6XE7UnDlf4dHkxQqZvnqvTXLCFKRGndQzJijxjfctXaf/6jWVCaJmQZ4 +RvjaBwSz117utn0Pp9RLCfELZhGjaPt3xJTNo6DelX4ufz8+icq2KuRWJGZyOWoD +JSz265XWWht2R4dbwgIW1aw+ktISyja00bfz2yln6Ic/LMJJeA6jpNA0AynZCAf1 +lS5haN7DGcH05tOJXx/VTCV1K5sRSPllMnE6paXbqTDx3VQK+L/OUbAvJEXCJ3iZ +3NZSgwx5V6LtC6MY896CwrRTX4qgEce1ENL6AHSyZZO/jRzPA/wK3HzHClhPmo/3 +vEulEn//RX5L6iic3QkInhJyOLiEgHh4I9Qsudp2nw/nkEV3I4zwnt1mcWMg/ZKX +op3aMtLLjBD4CDAk1ymP9IkMWDTvQsRqsOTt0TlT6v71m0a/8jnyfEkRp5Jc7ca0 +IiwdJEbaToVQmJn5POJfvfHPQj7tQmPVY5WKlDkRIynOHnQXkfUCAwEAAQKCAYA4 +VJxUfbQ0U+Dr0YpAs/tHePSlKX9W3C8XmZ02MeS4ZscVivWZ9aOOQP9GSgEbpJ5g +FkO4P7PPYe3TzbEEZKzCtvD/6Yr+G1zxgJ+0/ijKYFSmYrF26mxIUrZjt8jvI4ar +8ae1rURtweBmcAnhPEZU9QRY973ykgg29pomCztj1IBpcEQ93i/AalgEuSeGuAyU +JeUqTbOlfZGFf+FmpJMZLCWuX1Mg5eHYDi83fQlFSANTFkPFonrJWCp6sQpUGiz2 +hFgGkH3jqLbA1KE5x/SwuQmWMbBHRPYhET2Py5mhkS5zddJS5YG3WSO/dv6o7tGP +Ek0G0RQzfKqraJRBM0ePb4texi5umIE+G3XpQApE8ZELJjVpEAQkKCH189np7oxv +tcWCQwPq5addMTPqVzaNjhC4JADhUeSiXYGlTmvSuSV/ZIXI7fffI1qDwrBVIX7N +T6ie4JQU+lc+hv8gPZqNdglHYUMj6i3bPPzQ8p/Tu5MdNcAoh455aXUilflJjukC +gcEA8EtvDE9k1zHgZFmcXkl+c+PgpGcp0nwoJ+uH2BCd5PI962IcDhQcKxCPNPa2 +GxV/6J/y6cLk99v3novIlZmEnIvMf/g2gYdW0XNKEljwtB6ms/Oq/OMMuGMP+Ix4 +0H9uW6LpYzYBuyKOt6RfYrgWsNsL2caojcu92aX4ug4kkf97OnsslrAqkp1hGJiN +okuiss63UVROalcNSWFLqkz7zcKy67eItuIBOEY+tKkdUt1b3/DURHFL4e5ZCdWo +UnjrAoHBALmJi3f9VGqsn2mFnetSeablRnvOyNMMblRgBLBVsc6hEl3Vxd0ejY8N +APWZ+W8/AXwpHj+Oqoap6wYiuXr1xcHBRNZu2gRB0evZUEzdu7m6dj28dc9ICymj +9CuFW+HVxidmBPfAum1+PU0WHkB4CwDpm5DtPymlNHJKKvDILawo4j2jh9K5YeCK +6/YdjmQVaBeHoB2v59UkEPZCcFarZa1Z6ZBlkNKCeCrKYB081RsEjYpwZUVd8eHw +49jl131onwKBwFHFec64ndpVUMUVcY7sd6m8XE/WA3drZMbg8eNnFDQ68zNMubtY +wJUvF2ywoBvrXxGsjJ9cAUsPgd5kNyghi+0x7a+GqhW+Fp9EGmrP9Wl2HMiUHRXd +thBxNZghRWO+WbG5aK6oTEKAagy4VPVlK+OXRxse7XEDamHMhy3Zbjx4slieXfgR +jwtBny8diuU10/IBQoTcqaqqYQ0dnQAhHndQ0E5CsLV7h2q9DM2x1xbB2WgFrlZ0 +L5x83bPpD1SxbQKBwQCjuKr4o/Qk+dTlwcGbkTjGPFWZFN0D11lYXS5mCAiSBHJ3 +mRczyy0xSVFKaKfCMf/2dzY48YSqtjAtRuETjuMF2a0L59+8l/RMwYPpgFSSTObg +DXiMA8/N296vtMtimkh0JcNGeKxJyHcBmf3x97wF/x6GocP11NFV9Pq1ZH9hBua1 +a6OEIJAtG4misWwgBv/Gm6h/6eSSoXPSSshkwnRDpy7Ce81y5Sxy3gg4ZKDMaZUY +z5udvYufS/lTQWaJRJMCgcEAzxLRrGW3Gz4ch1V+ZCNTNQJqUwHeIQF4mVNkeEk5 +wXE2NsW/DqStQiNkNDSMHiTXPfVoHDGhxxKhSYPe2O7JXkJL8EyzwMwEZJ4ypjuV +5/DadZh6cGu6UWVNAzzvcOMnEH8rHFfQlAd7MnFdJafXnEAX9UCfNFHOoNJhBbUj +kQPYVUEkEws0Feu0yUgyDRfDZcxeEC+ubvO0mGZEdGAuvu29AHnnGLhBTTdFb05H +Q4QjfIE8PkLbVa1oC3niOWdo -----END PRIVATE KEY----- diff --git a/components/esp_tee/test_apps/tee_test_fw/README.md b/components/esp_tee/test_apps/tee_test_fw/README.md index 5396aaf280..1488da3165 100644 --- a/components/esp_tee/test_apps/tee_test_fw/README.md +++ b/components/esp_tee/test_apps/tee_test_fw/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C6 | ESP32-H2 | -| ----------------- | -------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | -------- | ## ESP-TEE: Test Suite diff --git a/components/esp_tee/test_apps/tee_test_fw/conftest.py b/components/esp_tee/test_apps/tee_test_fw/conftest.py index d344c193f0..2a180f99b9 100644 --- a/components/esp_tee/test_apps/tee_test_fw/conftest.py +++ b/components/esp_tee/test_apps/tee_test_fw/conftest.py @@ -10,8 +10,6 @@ import sys import tempfile from pathlib import Path from typing import Any -from typing import Dict -from typing import List import espsecure import esptool @@ -104,7 +102,48 @@ esp_tee_empty_bin = { 0xDC, 0x60, 0x86, 0x6C, 0x37, 0x76, 0xAA, 0x30, 0x1F, 0x61, 0x48, 0x23, 0xEA, 0x34, 0xAA, 0x19, 0xE8, 0xDE, 0x04, 0x7D, 0x2A, 0x30, 0xC1, 0xDD, 0x61, 0x38, 0x9D, 0xB5, 0xCA, 0x13, 0x5A, 0x79 - ] + ], + 'esp32c5': [ + 0xE9, 0x04, 0x02, 0x1F, 0x00, 0x00, 0x80, 0x40, 0xEE, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x00, 0x64, 0x00, 0xC7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + # DROM segment + 0x20, 0x00, 0x00, 0x42, 0x00, 0x02, 0x00, 0x00, + # esp_app_desc structure + 0x32, 0x54, 0xCD, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0x35, 0x2E, 0x35, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x65, 0x73, 0x70, 0x5F, 0x74, 0x65, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x30, 0x3A, 0x30, 0x30, 0x3A, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x4E, 0x6F, 0x76, 0x20, 0x31, 0x31, 0x20, 0x32, + 0x30, 0x32, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x35, 0x2E, 0x35, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2D, 0x63, 0x66, 0x8B, 0x75, 0xFA, 0x59, 0x05, + 0x53, 0x34, 0x91, 0x71, 0x51, 0x33, 0x91, 0xDD, 0xF8, 0xB1, 0xFE, 0x83, + 0x06, 0xEB, 0x03, 0x80, 0x45, 0xC9, 0x18, 0x20, 0x83, 0x7E, 0x2E, 0x43, + *([0x00] * 0x58), + # Padding + *([0x00] * 0x100), + # IRAM segment + 0x00, 0x00, 0x80, 0x40, 0x20, 0x00, 0x00, 0x00, + *([0x00] * 0x20), + # PADDING segment + 0x00, 0x00, 0x00, 0x00, 0xC8, 0x7D, 0x00, 0x00, + *([0x00] * 0x7DC8), + # IROM segment + 0x20, 0x80, 0x00, 0x42, 0x00, 0x01, 0x00, 0x00, + *([0x00] * 0x100), + # Padding + *([0x00] * 0x0F), + # CRC8 checksum + 0x56, + # Image SHA256 + 0xCD, 0xCC, 0xF2, 0xE3, 0x52, 0x76, 0xE5, 0x6D, 0xF6, 0x32, 0x95, 0x27, + 0x5F, 0xF3, 0xD8, 0x90, 0xD7, 0x95, 0xA0, 0x95, 0xD5, 0xDA, 0xE7, 0xA4, + 0x58, 0x08, 0x84, 0xBB, 0x8F, 0x29, 0xAB, 0xE4 + ], } # fmt: on @@ -233,7 +272,7 @@ class TEESerial(IdfSerial): self.flash() self.custom_erase_partition('secure_storage') - KEY_DEFS: List[Dict[str, Any]] = [ + KEY_DEFS: list[dict[str, Any]] = [ {'key': 'aes256_key0', 'type': 'aes256', 'input': None, 'write_once': True}, { 'key': 'aes256_key1', @@ -264,7 +303,7 @@ class TEESerial(IdfSerial): NVS_CSV_PATH = TMP_DIR / 'tee_sec_stg_val.csv' NVS_BIN_PATH = TMP_DIR / 'tee_sec_stg_nvs.bin' - def run_command(self, command: List[str]) -> None: + def run_command(self, command: list[str]) -> None: try: subprocess.check_call(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) except subprocess.CalledProcessError: @@ -276,7 +315,7 @@ class TEESerial(IdfSerial): def create_tee_sec_stg_csv(self, tmp_dir: Path) -> Path: csv_path = self.NVS_CSV_PATH - rows: List[List[str]] = [ + rows: list[list[str]] = [ ['key', 'type', 'encoding', 'value'], ['tee_sec_stg_ns', 'namespace', '', ''], ] diff --git a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_flash_prot.c b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_flash_prot.c index 7c5d3cb9b9..bbde60b5c6 100644 --- a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_flash_prot.c +++ b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_flash_prot.c @@ -22,6 +22,7 @@ #include "unity.h" #include "ccomp_timer.h" +#include "sdkconfig.h" #define BOOT_COUNT_NAMESPACE "boot_count" #define TEST_PART_LABEL "custom" @@ -29,6 +30,30 @@ #define ESP_TEE_SEC_STG_PART_LABEL "secure_storage" +__attribute__((unused)) static const uint32_t mmu_op_fail_seq[8] = {[0 ... 7] = 0x0addbad0}; + +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 +#define SOC_TEE_FLASH_OP_FAIL_FAULT 1 +#else +#define SOC_TEE_FLASH_OP_FAIL_FAULT 0 +#endif + +#if SOC_TEE_FLASH_OP_FAIL_FAULT +#define CHECK_MMU_OP_FAIL(ptr_) do {} while (0) +#else +#define CHECK_MMU_OP_FAIL(ptr_) \ + do { \ + TEST_ASSERT_EQUAL_HEX8_ARRAY(mmu_op_fail_seq, (ptr_), 0x20); \ + esp_restart(); \ + } while (0) +#endif + +#if SOC_TEE_FLASH_OP_FAIL_FAULT +#define CHECK_FLASH_OP_FAIL(err) TEST_ESP_ERR(ESP_FAIL, err) +#else +#define CHECK_FLASH_OP_FAIL(err) do { (void)(err); esp_restart(); } while (0) +#endif + static const char *TAG = "test_esp_tee_flash_prot"; static void set_boot_count_in_nvs(uint8_t boot_count) @@ -77,6 +102,7 @@ static void test_esp_partition_mmap_api(void) part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_TEE_0, NULL); TEST_ASSERT_NOT_NULL(part); TEST_ESP_OK(esp_partition_mmap(part, 0, part->size, ESP_PARTITION_MMAP_DATA, &outptr, &out_handle)); + CHECK_MMU_OP_FAIL(outptr); ESP_LOG_BUFFER_HEXDUMP(TAG, outptr, 0x20, ESP_LOG_INFO); TEST_FAIL_MESSAGE("System fault should have been generated"); break; @@ -84,6 +110,7 @@ static void test_esp_partition_mmap_api(void) part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_TEE_1, NULL); TEST_ASSERT_NOT_NULL(part); TEST_ESP_OK(esp_partition_mmap(part, 0, part->size, ESP_PARTITION_MMAP_INST, &outptr, &out_handle)); + CHECK_MMU_OP_FAIL(outptr); ESP_LOG_BUFFER_HEXDUMP(TAG, outptr, 0x20, ESP_LOG_INFO); TEST_FAIL_MESSAGE("System fault should have been generated"); break; @@ -91,6 +118,7 @@ static void test_esp_partition_mmap_api(void) part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_TEE_OTA, NULL); TEST_ASSERT_NOT_NULL(part); TEST_ESP_OK(esp_partition_mmap(part, 0, part->size, ESP_PARTITION_MMAP_DATA, &outptr, &out_handle)); + CHECK_MMU_OP_FAIL(outptr); ESP_LOG_BUFFER_HEXDUMP(TAG, outptr, 0x20, ESP_LOG_INFO); TEST_FAIL_MESSAGE("System fault should have been generated"); break; @@ -98,6 +126,7 @@ static void test_esp_partition_mmap_api(void) part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, ESP_TEE_SEC_STG_PART_LABEL); TEST_ASSERT_NOT_NULL(part); TEST_ESP_OK(esp_partition_mmap(part, 0, part->size, ESP_PARTITION_MMAP_DATA, &outptr, &out_handle)); + CHECK_MMU_OP_FAIL(outptr); ESP_LOG_BUFFER_HEXDUMP(TAG, outptr, 0x20, ESP_LOG_INFO); TEST_FAIL_MESSAGE("System fault should have been generated"); break; @@ -117,7 +146,8 @@ static void test_esp_partition_api_r(const esp_partition_t *part) TEST_ASSERT_NOT_NULL(part); uint8_t buf_r[128]; memset(buf_r, 0x00, sizeof(buf_r)); - TEST_ESP_ERR(ESP_FAIL, esp_partition_read(part, 0x00, buf_r, sizeof(buf_r))); + esp_err_t err = esp_partition_read(part, 0x00, buf_r, sizeof(buf_r)); + CHECK_FLASH_OP_FAIL(err); } static void test_esp_partition_api_w(const esp_partition_t *part) @@ -125,13 +155,15 @@ static void test_esp_partition_api_w(const esp_partition_t *part) TEST_ASSERT_NOT_NULL(part); uint8_t buf_w[128]; memset(buf_w, 0xA5, sizeof(buf_w)); - TEST_ESP_ERR(ESP_FAIL, esp_partition_write(part, 0x00, buf_w, sizeof(buf_w))); + esp_err_t err = esp_partition_write(part, 0x00, buf_w, sizeof(buf_w)); + CHECK_FLASH_OP_FAIL(err); } static void test_esp_partition_api_e(const esp_partition_t *part) { TEST_ASSERT_NOT_NULL(part); - TEST_ESP_ERR(ESP_FAIL, esp_partition_erase_range(part, 0x00, SPI_FLASH_SEC_SIZE)); + esp_err_t err = esp_partition_erase_range(part, 0x00, SPI_FLASH_SEC_SIZE); + CHECK_FLASH_OP_FAIL(err); } static void test_esp_partition_api(void) @@ -188,6 +220,7 @@ static void test_spi_flash_mmap_api(void) part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_TEE_0, NULL); TEST_ASSERT_NOT_NULL(part); TEST_ESP_OK(spi_flash_mmap(part->address, part->size, SPI_FLASH_MMAP_DATA, &ptr, &handle)); + CHECK_MMU_OP_FAIL(ptr); ESP_LOG_BUFFER_HEXDUMP(TAG, ptr, 0x20, ESP_LOG_INFO); TEST_FAIL_MESSAGE("System fault should have been generated"); break; @@ -195,6 +228,7 @@ static void test_spi_flash_mmap_api(void) part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_TEE_1, NULL); TEST_ASSERT_NOT_NULL(part); TEST_ESP_OK(spi_flash_mmap(part->address, part->size, SPI_FLASH_MMAP_INST, &ptr, &handle)); + CHECK_MMU_OP_FAIL(ptr); ESP_LOG_BUFFER_HEXDUMP(TAG, ptr, 0x20, ESP_LOG_INFO); TEST_FAIL_MESSAGE("System fault should have been generated"); break; @@ -202,6 +236,7 @@ static void test_spi_flash_mmap_api(void) part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_TEE_OTA, NULL); TEST_ASSERT_NOT_NULL(part); TEST_ESP_OK(spi_flash_mmap(part->address, part->size, SPI_FLASH_MMAP_DATA, &ptr, &handle)); + CHECK_MMU_OP_FAIL(ptr); ESP_LOG_BUFFER_HEXDUMP(TAG, ptr, 0x20, ESP_LOG_INFO); TEST_FAIL_MESSAGE("System fault should have been generated"); break; @@ -222,19 +257,22 @@ static void test_esp_flash_api_r(uint32_t paddr) { uint8_t buf_r[128]; memset(buf_r, 0x00, sizeof(buf_r)); - TEST_ESP_ERR(ESP_FAIL, esp_flash_read(NULL, buf_r, paddr, sizeof(buf_r))); + esp_err_t err = esp_flash_read(NULL, buf_r, paddr, sizeof(buf_r)); + CHECK_FLASH_OP_FAIL(err); } static void test_esp_flash_api_w(uint32_t paddr) { uint8_t buf_w[128]; memset(buf_w, 0xA5, sizeof(buf_w)); - TEST_ESP_ERR(ESP_FAIL, esp_flash_write(NULL, buf_w, paddr, sizeof(buf_w))); + esp_err_t err = esp_flash_write(NULL, buf_w, paddr, sizeof(buf_w)); + CHECK_FLASH_OP_FAIL(err); } static void test_esp_flash_api_e(uint32_t paddr) { - TEST_ESP_ERR(ESP_FAIL, esp_flash_erase_region(NULL, paddr, SPI_FLASH_SEC_SIZE)); + esp_err_t err = esp_flash_erase_region(NULL, paddr, SPI_FLASH_SEC_SIZE); + CHECK_FLASH_OP_FAIL(err); } static void test_esp_flash_api(void) diff --git a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_panic.c b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_panic.c index 79c9acc1ff..115ed26010 100644 --- a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_panic.c +++ b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_panic.c @@ -35,102 +35,117 @@ extern uint32_t _instruction_reserved_start; #define TEST_APM_EFUSE_PROT_REG EFUSE_RD_KEY5_DATA0_REG #endif -TEST_CASE("Test APM violation interrupt: eFuse", "[apm_violation]") +TEST_CASE("Test APM violation: eFuse", "[apm_violation]") { uint32_t val = UINT32_MAX; val = REG_READ(TEST_APM_EFUSE_PROT_REG); TEST_ASSERT_EQUAL(0, val); - TEST_FAIL_MESSAGE("APM violation interrupt should have been generated"); + TEST_FAIL_MESSAGE("APM violation should have been generated"); } -TEST_CASE("Test APM violation interrupt: MMU", "[apm_violation]") +TEST_CASE("Test APM violation: MMU", "[apm_violation]") { uint32_t val = UINT32_MAX; REG_WRITE(SPI_MEM_MMU_ITEM_INDEX_REG(0), SOC_MMU_ENTRY_NUM - 2); val = REG_READ(SPI_MEM_MMU_ITEM_CONTENT_REG(0)); TEST_ASSERT_EQUAL(0, val); - TEST_FAIL_MESSAGE("APM violation interrupt should have been generated"); + TEST_FAIL_MESSAGE("APM violation should have been generated"); } -TEST_CASE("Test APM violation interrupt: AES", "[apm_violation]") +TEST_CASE("Test APM violation: AES", "[apm_violation]") { uint32_t val = UINT32_MAX; val = REG_READ(AES_KEY_2_REG); TEST_ASSERT_EQUAL(0, val); - TEST_FAIL_MESSAGE("APM violation interrupt should have been generated"); + TEST_FAIL_MESSAGE("APM violation should have been generated"); } -TEST_CASE("Test APM violation interrupt: HMAC", "[apm_violation]") +TEST_CASE("Test APM violation: HMAC", "[apm_violation]") { uint32_t val = UINT32_MAX; val = REG_READ(HMAC_SET_PARA_KEY_REG); TEST_ASSERT_EQUAL(0, val); - TEST_FAIL_MESSAGE("APM violation interrupt should have been generated"); + TEST_FAIL_MESSAGE("APM violation should have been generated"); } -TEST_CASE("Test APM violation interrupt: DS", "[apm_violation]") +TEST_CASE("Test APM violation: DS", "[apm_violation]") { uint32_t val = UINT32_MAX; val = REG_READ(DS_Z_MEM); TEST_ASSERT_EQUAL(0, val); - TEST_FAIL_MESSAGE("APM violation interrupt should have been generated"); + TEST_FAIL_MESSAGE("APM violation should have been generated"); } -TEST_CASE("Test APM violation interrupt: SHA PCR", "[apm_violation]") +TEST_CASE("Test APM violation: SHA PCR", "[apm_violation]") { uint32_t val = 0; REG_WRITE(PCR_SHA_CONF_REG, val); - TEST_FAIL_MESSAGE("APM violation interrupt should have been generated"); + TEST_FAIL_MESSAGE("APM violation should have been generated"); } -TEST_CASE("Test APM violation interrupt: ECC PCR", "[apm_violation]") +TEST_CASE("Test APM violation: ECC PCR", "[apm_violation]") { uint32_t val = 0; REG_WRITE(PCR_ECC_CONF_REG, val); - TEST_FAIL_MESSAGE("APM violation interrupt should have been generated"); + TEST_FAIL_MESSAGE("APM violation should have been generated"); } -/* TEE IRAM: Reserved/Vector-table boundary */ -TEST_CASE("Test TEE-TEE violation: IRAM (W1)", "[exception]") +// NOTE: For C6/H2, SWDT and BOD are protected using PMP, thus this test +// generates a store access fault instead of APM violation +TEST_CASE("Test APM violation: SWDT/BOD", "[exception]") { - esp_tee_service_call(1, SS_ESP_TEE_TEST_IRAM_REG1_WRITE_VIOLATION); +#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 + REG_WRITE(LP_ANALOG_PERI_LP_ANA_FIB_ENABLE_REG, 0); +#else + REG_WRITE(LP_ANA_FIB_ENABLE_REG, 0); +#endif TEST_FAIL_MESSAGE("Exception should have been generated"); } /* Illegal memory space: Write */ -TEST_CASE("Test TEE-TEE violation: Reserved (W1)", "[exception]") +TEST_CASE("Test TEE-TEE violation: Reserved-W1", "[exception]") { esp_tee_service_call(1, SS_ESP_TEE_TEST_RESV_REG1_WRITE_VIOLATION); TEST_FAIL_MESSAGE("Exception should have been generated"); } /* Illegal memory space: Execution */ -TEST_CASE("Test TEE-TEE violation: Reserved (X1)", "[exception]") +TEST_CASE("Test TEE-TEE violation: Reserved-X1", "[exception]") { esp_tee_service_call(1, SS_ESP_TEE_TEST_RESV_REG1_EXEC_VIOLATION); TEST_FAIL_MESSAGE("Exception should have been generated"); } +// TODO: [IDF-13827] Enable when TEE SRAM is partitioned as IRAM (RX) and DRAM (RW) +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C5) +/* TEE IRAM: Reserved/Vector-table boundary */ +TEST_CASE("Test TEE-TEE violation: IRAM-W1", "[exception]") +{ + esp_tee_service_call(1, SS_ESP_TEE_TEST_IRAM_REG1_WRITE_VIOLATION); + TEST_FAIL_MESSAGE("Exception should have been generated"); +} + /* TEE IRAM: Vector table region */ -TEST_CASE("Test TEE-TEE violation: IRAM (W2)", "[exception]") +TEST_CASE("Test TEE-TEE violation: IRAM-W2", "[exception]") { esp_tee_service_call(1, SS_ESP_TEE_TEST_IRAM_REG2_WRITE_VIOLATION); TEST_FAIL_MESSAGE("Exception should have been generated"); } /* TEE DRAM: Stack region */ -TEST_CASE("Test TEE-TEE violation: DRAM (X1)", "[exception]") +TEST_CASE("Test TEE-TEE violation: DRAM-X1", "[exception]") { esp_tee_service_call(1, SS_ESP_TEE_TEST_DRAM_REG1_EXEC_VIOLATION); TEST_FAIL_MESSAGE("Exception should have been generated"); } /* TEE DRAM: Heap region */ -TEST_CASE("Test TEE-TEE violation: DRAM (X2)", "[exception]") +TEST_CASE("Test TEE-TEE violation: DRAM-X2", "[exception]") { esp_tee_service_call(1, SS_ESP_TEE_TEST_DRAM_REG2_EXEC_VIOLATION); TEST_FAIL_MESSAGE("Exception should have been generated"); } +#endif /* Illegal Instruction */ TEST_CASE("Test TEE-TEE violation: Illegal Instruction", "[exception]") @@ -140,7 +155,7 @@ TEST_CASE("Test TEE-TEE violation: Illegal Instruction", "[exception]") } /* TEE DRAM -REE IRAM Boundary */ -TEST_CASE("Test REE-TEE isolation: DRAM (R1)", "[exception]") +TEST_CASE("Test REE-TEE isolation: DRAM-R1", "[exception]") { uint32_t* val = (uint32_t *)(&_iram_start - 0x04); TEST_ASSERT_EQUAL(0, *val); @@ -148,14 +163,14 @@ TEST_CASE("Test REE-TEE isolation: DRAM (R1)", "[exception]") } /* TEE DRAM -REE IRAM Boundary */ -TEST_CASE("Test REE-TEE isolation: DRAM (W1)", "[exception]") +TEST_CASE("Test REE-TEE isolation: DRAM-W1", "[exception]") { *(uint32_t *)(&_iram_start - 0x04) = 0xbadc0de; TEST_FAIL_MESSAGE("Exception should have been generated"); } /* TEE IRAM region */ -TEST_CASE("Test REE-TEE isolation: IRAM (R1)", "[exception]") +TEST_CASE("Test REE-TEE isolation: IRAM-R1", "[exception]") { uint32_t *val = (uint32_t *)(&_iram_start - (CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE) + 0x04); TEST_ASSERT_EQUAL(0, *val); @@ -163,14 +178,14 @@ TEST_CASE("Test REE-TEE isolation: IRAM (R1)", "[exception]") } /* TEE IRAM region */ -TEST_CASE("Test REE-TEE isolation: IRAM (W1)", "[exception]") +TEST_CASE("Test REE-TEE isolation: IRAM-W1", "[exception]") { *(uint32_t *)(&_iram_start - (CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE) + 0x04) = 0xbadc0de; TEST_FAIL_MESSAGE("Exception should have been generated"); } /* TEE IROM region */ -TEST_CASE("Test REE-TEE isolation: IROM (R1)", "[exception]") +TEST_CASE("Test REE-TEE isolation: IROM-R1", "[exception]") { uint32_t *val = (uint32_t *)(SOC_IROM_LOW + 0x04); TEST_ASSERT_EQUAL(0, *val); @@ -178,14 +193,14 @@ TEST_CASE("Test REE-TEE isolation: IROM (R1)", "[exception]") } /* TEE IROM region */ -TEST_CASE("Test REE-TEE isolation: IROM (W1)", "[exception]") +TEST_CASE("Test REE-TEE isolation: IROM-W1", "[exception]") { *(uint32_t *)(SOC_IROM_LOW + 0x04) = 0xbadc0de; TEST_FAIL_MESSAGE("Exception should have been generated"); } /* TEE DROM - REE IROM boundary */ -TEST_CASE("Test REE-TEE isolation: DROM (R1)", "[exception]") +TEST_CASE("Test REE-TEE isolation: DROM-R1", "[exception]") { const uint32_t test_addr = ALIGN_DOWN_TO_MMU_PAGE_SIZE((uint32_t)&_instruction_reserved_start); uint32_t *val = (uint32_t *)(test_addr - 0x04); @@ -194,16 +209,9 @@ TEST_CASE("Test REE-TEE isolation: DROM (R1)", "[exception]") } /* TEE DROM - REE IROM boundary */ -TEST_CASE("Test REE-TEE isolation: DROM (W1)", "[exception]") +TEST_CASE("Test REE-TEE isolation: DROM-W1", "[exception]") { const uint32_t test_addr = ALIGN_DOWN_TO_MMU_PAGE_SIZE((uint32_t)&_instruction_reserved_start); *(uint32_t *)(test_addr - 0x04) = 0xbadc0de; TEST_FAIL_MESSAGE("Exception should have been generated"); } - -/* SWDT/BOD Reset register */ -TEST_CASE("Test REE-TEE isolation: SWDT/BOD (W)", "[exception]") -{ - REG_WRITE(LP_ANALOG_PERI_LP_ANA_FIB_ENABLE_REG, 0); - TEST_FAIL_MESSAGE("Exception should have been generated"); -} diff --git a/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py b/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py index 409c0bdfc3..94c77c7da5 100644 --- a/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py +++ b/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py @@ -2,8 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 import re from enum import Enum -from typing import Dict -from typing import Tuple import pytest from pytest_embedded_idf import IdfDut @@ -11,7 +9,7 @@ from pytest_embedded_idf.utils import idf_parametrize # ---------------- Pytest build parameters ---------------- -SUPPORTED_TARGETS = ['esp32c6', 'esp32h2'] +SUPPORTED_TARGETS = ['esp32c6', 'esp32h2', 'esp32c5'] CONFIG_DEFAULT = [ # 'config, target, markers', @@ -34,28 +32,27 @@ CONFIG_ALL = [ # ---------------- Exception test-cases reasons ---------------- -TEE_VIOLATION_TEST_EXC_RSN: Dict[Tuple[str, str], str] = { - ('Reserved', 'W1'): 'Store access fault', - ('Reserved', 'X1'): 'Instruction access fault', - ('IRAM', 'W1'): 'Store access fault', - ('IRAM', 'W2'): 'Store access fault', - ('DRAM', 'X1'): 'Instruction access fault', - ('DRAM', 'X2'): 'Instruction access fault', +TEE_VIOLATION_TEST_EXC_RSN: dict[str, str] = { + ('Reserved-W1'): 'Store access fault', + ('Reserved-X1'): 'Instruction access fault', + ('IRAM-W1'): 'Store access fault', + ('IRAM-W2'): 'Store access fault', + ('DRAM-X1'): 'Instruction access fault', + ('DRAM-X2'): 'Instruction access fault', } -REE_ISOLATION_TEST_EXC_RSN: Dict[Tuple[str, str], str] = { - ('DRAM', 'R1'): 'Load access fault', - ('DRAM', 'W1'): 'Store access fault', - ('IRAM', 'R1'): 'Load access fault', - ('IRAM', 'W1'): 'Store access fault', - ('IROM', 'R1'): 'Load access fault', - ('IROM', 'W1'): 'Store access fault', - ('DROM', 'R1'): 'Load access fault', - ('DROM', 'W1'): 'Store access fault', - ('SWDT/BOD', 'W'): 'Store access fault', +REE_ISOLATION_TEST_EXC_RSN: dict[str, str] = { + ('DRAM-R1'): 'Load access fault', + ('DRAM-W1'): 'Store access fault', + ('IRAM-R1'): 'Load access fault', + ('IRAM-W1'): 'Store access fault', + ('IROM-R1'): 'Load access fault', + ('IROM-W1'): 'Store access fault', + ('DROM-R1'): 'Load access fault', + ('DROM-W1'): 'Store access fault', } -TEE_APM_VIOLATION_EXC_CHK = ['eFuse', 'MMU', 'AES', 'HMAC', 'DS', 'SHA PCR', 'ECC PCR'] +TEE_APM_VIOLATION_EXC_CHK = ['eFuse', 'MMU', 'AES', 'HMAC', 'DS', 'SHA PCR', 'ECC PCR', 'SWDT/BOD'] # ---------------- TEE default tests ---------------- @@ -118,10 +115,12 @@ def test_esp_tee_aes_perf(dut: IdfDut) -> None: def test_esp_tee_apm_violation(dut: IdfDut) -> None: for check in TEE_APM_VIOLATION_EXC_CHK: dut.expect_exact('Press ENTER to see the list of tests') - dut.write(f'"Test APM violation interrupt: {check}"') + dut.write(f'"Test APM violation: {check}"') exc = dut.expect(r'Core ([01]) panic\'ed \(([^)]+)\)', timeout=30).group(2).decode() - if dut.target == 'esp32h2' and check == 'eFuse': + if dut.target == 'esp32c5' or (dut.target == 'esp32h2' and check == 'eFuse'): exp_str = 'APM - Space exception' + elif check == 'SWDT/BOD': + exp_str = 'Store access fault' else: exp_str = 'APM - Authority exception' if exc != exp_str: @@ -148,13 +147,12 @@ def test_esp_tee_illegal_instruction(dut: IdfDut) -> None: ) def test_esp_tee_violation_checks(dut: IdfDut) -> None: checks_list = TEE_VIOLATION_TEST_EXC_RSN - for test in checks_list: - memory, access_type = test - expected_exc = checks_list[test] - if expected_exc is None: + for test, expected_exc in checks_list.items(): + if expected_exc is None or dut.target == 'esp32c5': + # TODO: Enable when TEE SRAM is partitioned as IRAM (RX) and DRAM (RW) continue dut.expect_exact('Press ENTER to see the list of tests') - dut.write(f'"Test TEE-TEE violation: {memory} ({access_type})"') + dut.write(f'"Test TEE-TEE violation: {test}"') actual_exc = dut.expect(r'Core ([01]) panic\'ed \(([^)]+)\)', timeout=30).group(2).decode() if actual_exc != expected_exc: raise RuntimeError('Incorrect exception received!') @@ -167,13 +165,11 @@ def test_esp_tee_violation_checks(dut: IdfDut) -> None: ) def test_esp_tee_isolation_checks(dut: IdfDut) -> None: checks_list = REE_ISOLATION_TEST_EXC_RSN - for test in checks_list: - memory, access_type = test - expected_exc = checks_list[test] + for test, expected_exc in checks_list.items(): if expected_exc is None: continue dut.expect_exact('Press ENTER to see the list of tests') - dut.write(f'"Test REE-TEE isolation: {memory} ({access_type})"') + dut.write(f'"Test REE-TEE isolation: {test}"') actual_exc = dut.expect(r'Core ([01]) panic\'ed \(([^)]+)\)', timeout=30).group(2).decode() if actual_exc != expected_exc: raise RuntimeError('Incorrect exception received!') @@ -215,6 +211,8 @@ def run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int, api: TeeFl flash_enc_enabled = dut.app.sdkconfig.get('SECURE_FLASH_ENC_ENABLED', True) + SOC_TEE_FLASH_OP_FAIL_FAULT = ['esp32c6', 'esp32h2'] + for stage in range(1, stages + 1): dut.write(str(test_case_num)) dut.expect(r'\s+\((\d+)\)\s+"([^"]+)"\r?\n', timeout=30) @@ -222,7 +220,10 @@ def run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int, api: TeeFl if stage > 1: if api in {TeeFlashAccessApi.ESP_PARTITION_MMAP, TeeFlashAccessApi.SPI_FLASH_MMAP}: - expect_panic_rsn(dut, 'Cache error') + if dut.target in SOC_TEE_FLASH_OP_FAIL_FAULT: + expect_panic_rsn(dut, 'Cache error') + else: + dut.expect(r'\[_ss_mmu_hal_map_region] Illegal flash access at\s+\S+\s*\|\s*\S+', timeout=10) elif api in {TeeFlashAccessApi.ESP_PARTITION, TeeFlashAccessApi.ESP_FLASH}: op_index = stage - 2 curr_op = expected_ops[api][op_index] @@ -230,7 +231,10 @@ def run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int, api: TeeFl # NOTE: The esp_partition_read API handles both decrypted # and plaintext reads. When flash encryption is enabled, # it uses the MMU HAL instead of the SPI flash HAL. - expect_panic_rsn(dut, 'Cache error') + if dut.target in SOC_TEE_FLASH_OP_FAIL_FAULT: + expect_panic_rsn(dut, 'Cache error') + else: + dut.expect(r'\[_ss_mmu_hal_map_region] Illegal flash access at\s+\S+\s*\|\s*\S+', timeout=10) else: match = dut.expect( r'\[_ss_spi_flash_hal_(\w+)\] Illegal flash access at \s*(0x[0-9a-fA-F]+)', timeout=10 @@ -239,7 +243,10 @@ def run_multiple_stages(dut: IdfDut, test_case_num: int, stages: int, api: TeeFl if not re.fullmatch(curr_op, actual_op): raise RuntimeError(f'Unexpected flash operation: {actual_op} (expected: {curr_op})') elif api == TeeFlashAccessApi.ESP_ROM_SPIFLASH: - expect_panic_rsn(dut, 'APM - Authority exception') + if dut.target in SOC_TEE_FLASH_OP_FAIL_FAULT: + expect_panic_rsn(dut, 'APM - Authority exception') + else: + expect_panic_rsn(dut, 'APM - Space exception') if stage != stages: dut.expect_exact('Press ENTER to see the list of tests.') @@ -340,7 +347,7 @@ def test_esp_tee_flash_prot_esp_flash(dut: IdfDut) -> None: @pytest.mark.generic @idf_parametrize('config', ['ota'], indirect=['config']) -@idf_parametrize('target', ['esp32c6', 'esp32h2'], indirect=['target']) +@idf_parametrize('target', SUPPORTED_TARGETS, indirect=['target']) def test_esp_tee_ota_negative(dut: IdfDut) -> None: # start test dut.expect_exact('Press ENTER to see the list of tests') @@ -474,8 +481,8 @@ def test_esp_tee_ota_rollback(dut: IdfDut) -> None: dut.expect('TEE otadata - Current image state: NEW', timeout=10) dut.expect('Loaded TEE app from partition at offset 0x40000', timeout=10) rst_rsn = dut.expect(r'rst:(0x[0-9A-Fa-f]+) \(([^)]+)\)', timeout=30).group(2).decode() - # NOTE: LP_WDT_SYS is for ESP32-C6 case as bootloader fails to load the dummy TEE app - if rst_rsn != 'LP_WDT_SYS': + # NOTE: LP_WDT_SYS (C6/H2) and RTC_WDT_SYS (C5) are expected as bootloader fails to load the dummy TEE app + if rst_rsn not in {'LP_WDT_SYS', 'RTC_WDT_SYS'}: raise RuntimeError('Incorrect reset reason observed after TEE image failure!') # after rollback diff --git a/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults b/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults index 9e3a863aba..4699b02915 100644 --- a/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults +++ b/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults @@ -9,6 +9,7 @@ CONFIG_SECURE_TEE_TEST_MODE=y # Setting partition table CONFIG_PARTITION_TABLE_SINGLE_APP_TEE=y +CONFIG_PARTITION_TABLE_OFFSET=0xF000 # TEE IRAM size CONFIG_SECURE_TEE_IRAM_SIZE=0x8400