feat(esp_tee): Support for ESP32-C5 - the esp_tee component

This commit is contained in:
Laukik Hase
2025-04-30 19:32:05 +05:30
parent 056e4a4162
commit 11d3a2480f
27 changed files with 2261 additions and 46 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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) },
{ "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]);
}
}

View File

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

View File

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

View File

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

View File

@@ -3,4 +3,4 @@ dependencies:
espressif/json_generator:
version: "^1.1.2"
rules:
- if: "target in [esp32c6, esp32h2]"
- if: "target in [esp32c6, esp32h2, esp32c5]"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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