mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-02 10:00:57 +02:00
feat(esp_tee): Support for ESP32-C5 - the esp_tee
component
This commit is contained in:
@@ -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()
|
||||
|
||||
|
@@ -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"
|
||||
|
@@ -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
|
||||
|
||||
|
332
components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml
Normal file
332
components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml
Normal 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
|
@@ -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 ------------------------------------------------- */
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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"
|
||||
|
@@ -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
|
@@ -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
|
@@ -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
|
@@ -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
|
@@ -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;
|
||||
|
@@ -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) {
|
||||
|
@@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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 ------------------------------------------------- */
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -3,4 +3,4 @@ dependencies:
|
||||
espressif/json_generator:
|
||||
version: "^1.1.2"
|
||||
rules:
|
||||
- if: "target in [esp32c6, esp32h2]"
|
||||
- if: "target in [esp32c6, esp32h2, esp32c5]"
|
||||
|
302
components/esp_tee/subproject/main/ld/esp32c5/esp_tee.ld.in
Normal file
302
components/esp_tee/subproject/main/ld/esp32c5/esp_tee.ld.in
Normal 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!");
|
@@ -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);
|
||||
}
|
@@ -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
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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
|
@@ -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
|
@@ -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));
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user