From f254f93594f2b5fe6cfb97505f47058f33bf2959 Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Mon, 1 Jul 2024 16:26:06 +0530 Subject: [PATCH] feat(esp_tee): Support for ESP-TEE - `esp_hw_support` component --- components/esp_hw_support/CMakeLists.txt | 3 ++ components/esp_hw_support/esp_clk.c | 15 +++++++++- components/esp_hw_support/hw_random.c | 7 +++-- components/esp_hw_support/include/esp_cpu.h | 29 ++++++++++++++++++- .../include/esp_private/regi2c_ctrl.h | 6 ++-- components/esp_hw_support/intr_alloc.c | 4 +++ .../esp_hw_support/lowpower/CMakeLists.txt | 4 ++- .../port/esp32c6/CMakeLists.txt | 4 ++- .../port/esp32c6/cpu_region_protect.c | 12 ++++++++ .../port/esp32c6/esp_cpu_intr.c | 13 ++++++++- 10 files changed, 87 insertions(+), 10 deletions(-) diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 5652bcf140..e0ccdbce17 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -145,6 +145,9 @@ if(NOT non_os_build) list(APPEND srcs "esp_clock_output.c") endif() else() + if(ESP_TEE_BUILD) + list(APPEND srcs "esp_clk.c" "hw_random.c") + endif() # Requires "_esp_error_check_failed()" function list(APPEND priv_requires "esp_system") endif() diff --git a/components/esp_hw_support/esp_clk.c b/components/esp_hw_support/esp_clk.c index c4a2c0c207..2f5d1b7755 100644 --- a/components/esp_hw_support/esp_clk.c +++ b/components/esp_hw_support/esp_clk.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,7 +9,10 @@ #include #include +#if !NON_OS_BUILD #include "freertos/FreeRTOS.h" +#endif + #include "esp_attr.h" #include "soc/rtc.h" #include "soc/soc_caps.h" @@ -52,7 +55,11 @@ // g_ticks_us defined in ROMs for PRO and APP CPU extern uint32_t g_ticks_per_us_pro; +// Any code utilizing locks, which depend on FreeRTOS, should be omitted +// when building for Non-OS environments +#if !NON_OS_BUILD static portMUX_TYPE s_esp_rtc_time_lock = portMUX_INITIALIZER_UNLOCKED; +#endif #if SOC_RTC_MEM_SUPPORTED typedef struct { @@ -64,6 +71,7 @@ typedef struct { _Static_assert(sizeof(retain_mem_t) == 24, "retain_mem_t must be 24 bytes"); _Static_assert(offsetof(retain_mem_t, checksum) == sizeof(retain_mem_t) - sizeof(uint32_t), "Wrong offset for checksum field in retain_mem_t structure"); +#if !NON_OS_BUILD static __attribute__((section(".rtc_timer_data_in_rtc_mem"))) retain_mem_t s_rtc_timer_retain_mem; static uint32_t calc_checksum(void) @@ -77,6 +85,7 @@ static uint32_t calc_checksum(void) return checksum; } #define IS_RETAIN_MEM_VALID() (s_rtc_timer_retain_mem.checksum == calc_checksum()) +#endif // NON_OS_BUILD #endif // SOC_RTC_MEM_SUPPORTED inline static int IRAM_ATTR s_get_cpu_freq_mhz(void) @@ -108,6 +117,7 @@ int IRAM_ATTR esp_clk_xtal_freq(void) return rtc_clk_xtal_freq_get() * MHZ; } +#if !NON_OS_BUILD uint64_t esp_rtc_get_time_us(void) { portENTER_CRITICAL_SAFE(&s_esp_rtc_time_lock); @@ -161,6 +171,7 @@ uint64_t esp_rtc_get_time_us(void) return esp_rtc_time_us; #endif } +#endif void esp_clk_slowclk_cal_set(uint32_t new_cal) { @@ -214,6 +225,7 @@ uint64_t esp_clk_rtc_time(void) #endif } +#if !NON_OS_BUILD void esp_clk_private_lock(void) { portENTER_CRITICAL(&s_esp_rtc_time_lock); @@ -223,3 +235,4 @@ void esp_clk_private_unlock(void) { portEXIT_CRITICAL(&s_esp_rtc_time_lock); } +#endif diff --git a/components/esp_hw_support/hw_random.c b/components/esp_hw_support/hw_random.c index e83b767d96..4f43e39d53 100644 --- a/components/esp_hw_support/hw_random.c +++ b/components/esp_hw_support/hw_random.c @@ -13,9 +13,12 @@ #include "esp_cpu.h" #include "soc/wdev_reg.h" #include "esp_private/esp_clk.h" -#include "esp_private/startup_internal.h" #include "soc/soc_caps.h" +#if !ESP_TEE_BUILD +#include "esp_private/startup_internal.h" +#endif + #if SOC_LP_TIMER_SUPPORTED #include "hal/lp_timer_hal.h" #endif @@ -100,7 +103,7 @@ void esp_fill_random(void *buf, size_t len) } } -#if SOC_RNG_CLOCK_IS_INDEPENDENT +#if SOC_RNG_CLOCK_IS_INDEPENDENT && !ESP_TEE_BUILD ESP_SYSTEM_INIT_FN(init_rng_clock, SECONDARY, BIT(0), 102) { _lp_clkrst_ll_enable_rng_clock(true); diff --git a/components/esp_hw_support/include/esp_cpu.h b/components/esp_hw_support/include/esp_cpu.h index f0f441b713..b0f3e89ed5 100644 --- a/components/esp_hw_support/include/esp_cpu.h +++ b/components/esp_hw_support/include/esp_cpu.h @@ -15,6 +15,7 @@ #include "xtensa_api.h" #include "xt_utils.h" #elif __riscv +#include "riscv/csr.h" #include "riscv/rv_utils.h" #endif #include "esp_intr_alloc.h" @@ -129,6 +130,27 @@ FORCE_INLINE_ATTR __attribute__((pure)) int esp_cpu_get_core_id(void) return (int)rv_utils_get_core_id(); #endif } +/** + * @brief Get the current [RISC-V] CPU core's privilege level + * + * This function returns the current privilege level of the CPU core executing + * this function. + * + * @return The current CPU core's privilege level, -1 if not supported. + */ + +FORCE_INLINE_ATTR __attribute__((always_inline)) int esp_cpu_get_curr_privilege_level(void) +{ +#ifdef __XTENSA__ + return -1; +#else +#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 + return PRV_M; +#else + return RV_READ_CSR(CSR_PRV_MODE); +#endif +#endif +} /** * @brief Read the current stack pointer address @@ -229,7 +251,7 @@ FORCE_INLINE_ATTR void esp_cpu_intr_set_ivt_addr(const void *ivt_addr) #ifdef __XTENSA__ xt_utils_set_vecbase((uint32_t)ivt_addr); #else - rv_utils_set_mtvec((uint32_t)ivt_addr); + rv_utils_set_xtvec((uint32_t)ivt_addr); #endif } @@ -429,9 +451,14 @@ FORCE_INLINE_ATTR void esp_cpu_intr_edge_ack(int intr_num) assert(intr_num >= 0 && intr_num < SOC_CPU_INTR_NUM); #ifdef __XTENSA__ xthal_set_intclear((unsigned) (1 << intr_num)); +#else +#if CONFIG_SECURE_ENABLE_TEE && !ESP_TEE_BUILD + extern esprv_int_mgmt_t esp_tee_intr_sec_srv_cb; + esp_tee_intr_sec_srv_cb(2, TEE_INTR_EDGE_ACK_SRV_ID, intr_num); #else rv_utils_intr_edge_ack((unsigned) intr_num); #endif +#endif } /* -------------------------------------------------- Memory Ports ----------------------------------------------------- diff --git a/components/esp_hw_support/include/esp_private/regi2c_ctrl.h b/components/esp_hw_support/include/esp_private/regi2c_ctrl.h index 4be8502eaf..6be822733b 100644 --- a/components/esp_hw_support/include/esp_private/regi2c_ctrl.h +++ b/components/esp_hw_support/include/esp_private/regi2c_ctrl.h @@ -61,9 +61,9 @@ extern "C" { #define regi2c_write_reg_mask_raw esp_rom_regi2c_write_mask -#ifdef BOOTLOADER_BUILD +#if NON_OS_BUILD /** - * If compiling for the bootloader, ROM functions can be called directly, + * If compiling for the non-FreeRTOS builds (e.g. bootloader), ROM functions can be called directly, * without the need of a lock. */ #define regi2c_ctrl_read_reg regi2c_read_reg_raw @@ -83,7 +83,7 @@ void regi2c_ctrl_write_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, void regi2c_enter_critical(void); void regi2c_exit_critical(void); -#endif // BOOTLOADER_BUILD +#endif // NON_OS_BUILD /* Convenience macros for the above functions, these use register definitions * from regi2c_xxx.h header files. diff --git a/components/esp_hw_support/intr_alloc.c b/components/esp_hw_support/intr_alloc.c index dec1d1e24b..4365aa31a6 100644 --- a/components/esp_hw_support/intr_alloc.c +++ b/components/esp_hw_support/intr_alloc.c @@ -649,9 +649,13 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre } #endif +/* NOTE: ESP-TEE is responsible for all interrupt-related configurations + * when enabled. The following code is not applicable in that case */ +#if !CONFIG_SECURE_ENABLE_TEE #if SOC_INT_PLIC_SUPPORTED /* Make sure the interrupt is not delegated to user mode (IDF uses machine mode only) */ RV_CLEAR_CSR(mideleg, BIT(intr)); +#endif #endif portEXIT_CRITICAL(&spinlock); diff --git a/components/esp_hw_support/lowpower/CMakeLists.txt b/components/esp_hw_support/lowpower/CMakeLists.txt index 9525e68003..2d4124bb61 100644 --- a/components/esp_hw_support/lowpower/CMakeLists.txt +++ b/components/esp_hw_support/lowpower/CMakeLists.txt @@ -1,4 +1,6 @@ -if(BOOTLOADER_BUILD) +idf_build_get_property(non_os_build NON_OS_BUILD) + +if(non_os_build) return() endif() diff --git a/components/esp_hw_support/port/esp32c6/CMakeLists.txt b/components/esp_hw_support/port/esp32c6/CMakeLists.txt index d62fdf06eb..ed1586db48 100644 --- a/components/esp_hw_support/port/esp32c6/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32c6/CMakeLists.txt @@ -1,3 +1,5 @@ +idf_build_get_property(non_os_build NON_OS_BUILD) + set(srcs "rtc_clk_init.c" "rtc_clk.c" "pmu_param.c" @@ -8,7 +10,7 @@ set(srcs "rtc_clk_init.c" "ocode_init.c" ) -if(NOT BOOTLOADER_BUILD) +if(NOT non_os_build) list(APPEND srcs "sar_periph_ctrl.c") endif() diff --git a/components/esp_hw_support/port/esp32c6/cpu_region_protect.c b/components/esp_hw_support/port/esp32c6/cpu_region_protect.c index e385fb607d..512fe08ae2 100644 --- a/components/esp_hw_support/port/esp32c6/cpu_region_protect.c +++ b/components/esp_hw_support/port/esp32c6/cpu_region_protect.c @@ -62,6 +62,10 @@ static void esp_cpu_configure_invalid_regions(void) // 7. End of address space PMA_ENTRY_SET_TOR(11, SOC_PERIPHERAL_HIGH, PMA_NONE); PMA_ENTRY_SET_TOR(12, UINT32_MAX, PMA_TOR | PMA_NONE); + + PMA_ENTRY_CFG_RESET(13); + PMA_ENTRY_CFG_RESET(14); + PMA_ENTRY_CFG_RESET(15); } void esp_cpu_configure_region_protection(void) @@ -112,6 +116,14 @@ void esp_cpu_configure_region_protection(void) // esp_cpu_configure_invalid_regions(); + /* NOTE: When ESP-TEE is active, only configure invalid memory regions in bootloader + * to prevent errors before TEE initialization. TEE will handle all other + * memory protection. + */ +#if CONFIG_SECURE_ENABLE_TEE && BOOTLOADER_BUILD + return; +#endif + // // Configure all the valid address regions using PMP // diff --git a/components/esp_hw_support/port/esp32c6/esp_cpu_intr.c b/components/esp_hw_support/port/esp32c6/esp_cpu_intr.c index 38fdf890d8..2eb79bdd3a 100644 --- a/components/esp_hw_support/port/esp32c6/esp_cpu_intr.c +++ b/components/esp_hw_support/port/esp32c6/esp_cpu_intr.c @@ -6,6 +6,7 @@ #include "esp_cpu.h" #include "esp_riscv_intr.h" +#include "sdkconfig.h" void esp_cpu_intr_get_desc(int core_id, int intr_num, esp_cpu_intr_desc_t *intr_desc_ret) { @@ -16,7 +17,17 @@ void esp_cpu_intr_get_desc(int core_id, int intr_num, esp_cpu_intr_desc_t *intr_ * Interrupts 3, 4 and 7 are unavailable for PULP CPU as they are bound to Core-Local Interrupts (CLINT) */ // [TODO: IDF-2465] - const uint32_t rsvd_mask = BIT(1) | BIT(3) | BIT(4) | BIT(6) | BIT(7); + const uint32_t base_rsvd_mask = BIT(1) | BIT(3) | BIT(4) | BIT(6) | BIT(7); + + /* On the ESP32-C6, interrupt 14 is reserved for ESP-TEE + * for operations related to secure peripherals under its control + * (e.g. AES, SHA, APM) + */ +#if CONFIG_SECURE_ENABLE_TEE + const uint32_t rsvd_mask = base_rsvd_mask | BIT(14); +#else + const uint32_t rsvd_mask = base_rsvd_mask; +#endif intr_desc_ret->priority = 1; intr_desc_ret->type = ESP_CPU_INTR_TYPE_NA;