feat(esp_tee): Support for ESP-TEE - esp_system component

This commit is contained in:
Laukik Hase
2024-07-01 14:42:08 +05:30
parent 54c3f1bae4
commit 733741bbac
8 changed files with 105 additions and 9 deletions

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -10,15 +10,40 @@
#include "../ext_mem_layout.h" #include "../ext_mem_layout.h"
#include "hal/mmu_types.h" #include "hal/mmu_types.h"
/* NOTE: With ESP-TEE enabled:
* - The start address is moved by the size of TEE IDROM segments since these
* segments are placed at the start of the linear address space
* - TEE IROM and DROM segments are both 64KB (CONFIG_SECURE_TEE_IROM_SIZE,
* CONFIG_SECURE_TEE_DROM_SIZE) for now. Thus, the number of reserved entries
* from the start would be (64KB + 64KB)/MMU_PAGE_SIZE
* - The last few MMU entries are reserved for TEE flash operations. The number
* of reserved entries matches the size of TEE IDROM segments (IROM + DROM)
* plus one additional entry, i.e. (64KB + 64KB)/MMU_PAGE_SIZE + 1
*/
#if CONFIG_SECURE_ENABLE_TEE
#define TEE_MMU_MEM_REG_START_OFFS (CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE)
#define TEE_MMU_RESV_PAGES ((CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE) / CONFIG_MMU_PAGE_SIZE)
#define TEE_MMU_MEM_REG_END_OFFS ((TEE_MMU_RESV_PAGES + 1) * CONFIG_MMU_PAGE_SIZE)
#define MMU_MEM_REG_START_ADDR_W_TEE (SOC_MMU_IRAM0_LINEAR_ADDRESS_LOW + TEE_MMU_MEM_REG_START_OFFS)
#define MMU_MEM_REG_END_ADDR_W_TEE (SOC_MMU_IRAM0_LINEAR_ADDRESS_HIGH - TEE_MMU_MEM_REG_END_OFFS)
#define MMU_IRAM0_LINEAR_ADDRESS_LOW MMU_MEM_REG_START_ADDR_W_TEE
#define MMU_IRAM0_LINEAR_ADDRESS_HIGH MMU_MEM_REG_END_ADDR_W_TEE
#else
#define MMU_IRAM0_LINEAR_ADDRESS_LOW SOC_MMU_IRAM0_LINEAR_ADDRESS_LOW
#define MMU_IRAM0_LINEAR_ADDRESS_HIGH SOC_MMU_IRAM0_LINEAR_ADDRESS_HIGH
#endif
/** /**
* The start addresses in this list should always be sorted from low to high, as MMU driver will need to * The start addresses in this list should always be sorted from low to high, as MMU driver will need to
* coalesce adjacent regions * coalesce adjacent regions
*/ */
const mmu_mem_region_t g_mmu_mem_regions[SOC_MMU_LINEAR_ADDRESS_REGION_NUM] = { const mmu_mem_region_t g_mmu_mem_regions[SOC_MMU_LINEAR_ADDRESS_REGION_NUM] = {
[0] = { [0] = {
.start = SOC_MMU_IRAM0_LINEAR_ADDRESS_LOW, .start = MMU_IRAM0_LINEAR_ADDRESS_LOW,
.end = SOC_MMU_IRAM0_LINEAR_ADDRESS_HIGH, .end = MMU_IRAM0_LINEAR_ADDRESS_HIGH,
.size = SOC_BUS_SIZE(SOC_MMU_IRAM0_LINEAR), .size = MMU_IRAM0_LINEAR_ADDRESS_HIGH - MMU_IRAM0_LINEAR_ADDRESS_LOW,
.bus_id = CACHE_BUS_IBUS0 | CACHE_BUS_DBUS0, .bus_id = CACHE_BUS_IBUS0 | CACHE_BUS_DBUS0,
.targets = MMU_TARGET_FLASH0, .targets = MMU_TARGET_FLASH0,
.caps = MMU_MEM_CAP_EXEC | MMU_MEM_CAP_READ | MMU_MEM_CAP_32BIT | MMU_MEM_CAP_8BIT, .caps = MMU_MEM_CAP_EXEC | MMU_MEM_CAP_READ | MMU_MEM_CAP_32BIT | MMU_MEM_CAP_8BIT,

View File

@@ -1,4 +1,5 @@
idf_build_get_property(target IDF_TARGET) idf_build_get_property(target IDF_TARGET)
idf_build_get_property(esp_tee_build ESP_TEE_BUILD)
# On Linux, we only support a few features, hence this simple component registration # On Linux, we only support a few features, hence this simple component registration
if(${target} STREQUAL "linux") if(${target} STREQUAL "linux")
@@ -22,7 +23,7 @@ if(CONFIG_IDF_ENV_FPGA OR CONFIG_ESP_BRINGUP_BYPASS_RANDOM_SETTING)
list(APPEND srcs "fpga_overrides_rng.c") list(APPEND srcs "fpga_overrides_rng.c")
endif() endif()
if(BOOTLOADER_BUILD) if(BOOTLOADER_BUILD OR esp_tee_build)
# "_esp_error_check_failed()" requires spi_flash module # "_esp_error_check_failed()" requires spi_flash module
# Bootloader relies on some Kconfig options defined in esp_system. # Bootloader relies on some Kconfig options defined in esp_system.
idf_component_register(SRCS "${srcs}" REQUIRES spi_flash) idf_component_register(SRCS "${srcs}" REQUIRES spi_flash)

View File

@@ -121,7 +121,7 @@ menu "ESP System Settings"
config ESP_SYSTEM_PMP_IDRAM_SPLIT config ESP_SYSTEM_PMP_IDRAM_SPLIT
bool "Enable IRAM/DRAM split protection" bool "Enable IRAM/DRAM split protection"
depends on SOC_CPU_IDRAM_SPLIT_USING_PMP depends on SOC_CPU_IDRAM_SPLIT_USING_PMP && !SECURE_ENABLE_TEE
default "y" default "y"
help help
If enabled, the CPU watches all the memory access and raises an exception in case If enabled, the CPU watches all the memory access and raises an exception in case
@@ -141,6 +141,13 @@ menu "ESP System Settings"
Warning: on ESP32-P4 this will also mark the memory area used for BOOTLOADER_RESERVE_RTC_MEM Warning: on ESP32-P4 this will also mark the memory area used for BOOTLOADER_RESERVE_RTC_MEM
as executable. If you consider this a security risk then do not activate this option. as executable. If you consider this a security risk then do not activate this option.
config ESP_SYSTEM_MEMPROT_FEATURE_VIA_TEE
bool "Enable memory protection (via TEE)"
depends on SECURE_ENABLE_TEE
default "y"
help
This option enables the default memory protection provided by TEE.
config ESP_SYSTEM_MEMPROT_FEATURE config ESP_SYSTEM_MEMPROT_FEATURE
bool "Enable memory protection" bool "Enable memory protection"
depends on SOC_MEMPROT_SUPPORTED depends on SOC_MEMPROT_SUPPORTED
@@ -592,7 +599,8 @@ menu "ESP System Settings"
config ESP_SYSTEM_HW_STACK_GUARD config ESP_SYSTEM_HW_STACK_GUARD
bool "Hardware stack guard" bool "Hardware stack guard"
depends on SOC_ASSIST_DEBUG_SUPPORTED # TODO: [ESP-TEE] IDF-10770
depends on SOC_ASSIST_DEBUG_SUPPORTED && !SECURE_ENABLE_TEE
default y default y
help help
This config allows to trigger a panic interrupt when Stack Pointer register goes out of allocated stack This config allows to trigger a panic interrupt when Stack Pointer register goes out of allocated stack

View File

@@ -15,7 +15,13 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#include "ld.common" #include "ld.common"
#define SRAM_SEG_START 0x40800000 #if !CONFIG_SECURE_ENABLE_TEE
#define SRAM_SEG_START (0x40800000)
#else
#define SRAM_SEG_START (0x40800000 + CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE)
#define FLASH_SEG_OFFSET (CONFIG_SECURE_TEE_IROM_SIZE + CONFIG_SECURE_TEE_DROM_SIZE)
#endif // CONFIG_SECURE_ENABLE_TEE
#define SRAM_SEG_END 0x4086E610 /* 2nd stage bootloader iram_loader_seg start address */ #define SRAM_SEG_END 0x4086E610 /* 2nd stage bootloader iram_loader_seg start address */
#define SRAM_SEG_SIZE SRAM_SEG_END - SRAM_SEG_START #define SRAM_SEG_SIZE SRAM_SEG_END - SRAM_SEG_START
@@ -35,8 +41,14 @@ MEMORY
*/ */
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS #if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
#if CONFIG_SECURE_ENABLE_TEE
/* Flash mapped instruction data */
irom_seg (RX) : org = 0x42000020 + FLASH_SEG_OFFSET,
len = IDRAM0_2_SEG_SIZE - FLASH_SEG_OFFSET - 0x20
#else
/* Flash mapped instruction data */ /* Flash mapped instruction data */
irom_seg (RX) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20 irom_seg (RX) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20
#endif
/** /**
* (0x20 offset above is a convenience for the app binary image generation. * (0x20 offset above is a convenience for the app binary image generation.
@@ -54,8 +66,14 @@ MEMORY
sram_seg (RWX) : org = SRAM_SEG_START, len = SRAM_SEG_SIZE sram_seg (RWX) : org = SRAM_SEG_START, len = SRAM_SEG_SIZE
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS #if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
#if CONFIG_SECURE_ENABLE_TEE
/* Flash mapped constant data */ /* Flash mapped constant data */
drom_seg (R) : org = 0x42000020 + FLASH_SEG_OFFSET,
len = IDRAM0_2_SEG_SIZE - FLASH_SEG_OFFSET - 0x20
#else
/* Flash mapped instruction data */
drom_seg (R) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20 drom_seg (R) : org = 0x42000020, len = IDRAM0_2_SEG_SIZE - 0x20
#endif
/* (See irom_seg for meaning of 0x20 offset in the above.) */ /* (See irom_seg for meaning of 0x20 offset in the above.) */
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS #endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS

View File

@@ -173,11 +173,22 @@ SECTIONS
/* Vectors go to start of IRAM */ /* Vectors go to start of IRAM */
ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned");
_vector_table_start = ABSOLUTE(.);
KEEP(*(.exception_vectors_table.text)); KEEP(*(.exception_vectors_table.text));
KEEP(*(.exception_vectors.text)); KEEP(*(.exception_vectors.text));
ALIGNED_SYMBOL(4, _invalid_pc_placeholder) ALIGNED_SYMBOL(4, _invalid_pc_placeholder)
/* esp_tee_config_t structure: used to share information between the TEE and REE
* (e.g. interrupt handler addresses, REE flash text-rodata boundaries, etc.)
* This symbol is expected by the TEE at an offset of 0x300 from the vector table start.
*/
#if CONFIG_SECURE_ENABLE_TEE
ALIGNED_SYMBOL(0x10, _esp_tee_app_cfg)
ASSERT(ABSOLUTE(.) == _vector_table_start + 0x2e0, "esp_tee_app_cfg must be at an offset 0x2e0 from the vector table start");
*libesp_tee.a:(.esp_tee_app_cfg);
#endif
/* Code marked as running out of IRAM */ /* Code marked as running out of IRAM */
_iram_text_start = ABSOLUTE(.); _iram_text_start = ABSOLUTE(.);

View File

@@ -419,6 +419,15 @@ void IRAM_ATTR call_start_cpu0(void)
esp_cpu_intr_set_mtvt_addr(&_mtvt_table); esp_cpu_intr_set_mtvt_addr(&_mtvt_table);
#endif #endif
/* NOTE: When ESP-TEE is enabled, this sets up the callback function
* which redirects all the interrupt management for the REE (user app)
* to the TEE by raising the appropriate service calls.
*/
#if CONFIG_SECURE_ENABLE_TEE
extern uint32_t esp_tee_service_call(int argc, ...);
esprv_int_setup_mgmt_cb((void *)esp_tee_service_call);
#endif
rst_reas[0] = esp_rom_get_reset_reason(0); rst_reas[0] = esp_rom_get_reset_reason(0);
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
rst_reas[1] = esp_rom_get_reset_reason(1); rst_reas[1] = esp_rom_get_reset_reason(1);
@@ -606,8 +615,12 @@ void IRAM_ATTR call_start_cpu0(void)
#else #else
ESP_EARLY_LOGI(TAG, "Multicore app"); ESP_EARLY_LOGI(TAG, "Multicore app");
#endif #endif
/* NOTE: When ESP-TEE is enabled, it configures its own memory protection
* scheme using the CPU-inherent features PMP and PMA and the APM peripheral.
*/
#if !CONFIG_SECURE_ENABLE_TEE
bootloader_init_mem(); bootloader_init_mem();
#endif
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
s_cpu_up[0] = true; s_cpu_up[0] = true;

View File

@@ -63,6 +63,12 @@ ESP_SYSTEM_INIT_FN(init_show_cpu_freq, CORE, BIT(0), 10)
return ESP_OK; return ESP_OK;
} }
/* NOTE: When ESP-TEE is enabled, the Brownout Detection module is part
* of the TEE and is initialized in the TEE startup routine itself.
* It is protected from all REE accesses through memory protection mechanisms,
* as it is a critical module for device functioning.
*/
#if !CONFIG_SECURE_ENABLE_TEE
ESP_SYSTEM_INIT_FN(init_brownout, CORE, BIT(0), 104) ESP_SYSTEM_INIT_FN(init_brownout, CORE, BIT(0), 104)
{ {
// [refactor-todo] leads to call chain rtc_is_register (driver) -> esp_intr_alloc (esp32/esp32s2) -> // [refactor-todo] leads to call chain rtc_is_register (driver) -> esp_intr_alloc (esp32/esp32s2) ->
@@ -76,6 +82,7 @@ ESP_SYSTEM_INIT_FN(init_brownout, CORE, BIT(0), 104)
#endif // CONFIG_ESP_BROWNOUT_DET #endif // CONFIG_ESP_BROWNOUT_DET
return ESP_OK; return ESP_OK;
} }
#endif
ESP_SYSTEM_INIT_FN(init_newlib_time, CORE, BIT(0), 105) ESP_SYSTEM_INIT_FN(init_newlib_time, CORE, BIT(0), 105)
{ {

View File

@@ -12,6 +12,11 @@
#include "heap_memory_layout.h" #include "heap_memory_layout.h"
#include "esp_heap_caps.h" #include "esp_heap_caps.h"
#if CONFIG_SECURE_ENABLE_TEE
#define SRAM_DIRAM_TEE_ORG (SOC_DIRAM_IRAM_LOW)
#define SRAM_DIRAM_TEE_END (SRAM_DIRAM_TEE_ORG + CONFIG_SECURE_TEE_IRAM_SIZE + CONFIG_SECURE_TEE_DRAM_SIZE)
#endif
/** /**
* @brief Memory type descriptors. These describe the capabilities of a type of memory in the SoC. * @brief Memory type descriptors. These describe the capabilities of a type of memory in the SoC.
* Each type of memory map consists of one or more regions in the address space. * Each type of memory map consists of one or more regions in the address space.
@@ -95,6 +100,14 @@ SOC_RESERVE_MEMORY_REGION((intptr_t)&_data_start, (intptr_t)&_heap_start, dram_d
// Target has a shared D/IRAM virtual address, no need to calculate I_D_OFFSET like previous chips // Target has a shared D/IRAM virtual address, no need to calculate I_D_OFFSET like previous chips
SOC_RESERVE_MEMORY_REGION((intptr_t)&_iram_start, (intptr_t)&_iram_end, iram_code); SOC_RESERVE_MEMORY_REGION((intptr_t)&_iram_start, (intptr_t)&_iram_end, iram_code);
/* NOTE: When ESP-TEE is enabled, the start of the internal SRAM
* is used by the TEE and is protected from any REE access using
* memory protection mechanisms employed by ESP-TEE.
*/
#if CONFIG_SECURE_ENABLE_TEE
SOC_RESERVE_MEMORY_REGION((intptr_t)SRAM_DIRAM_TEE_ORG, (intptr_t)(SRAM_DIRAM_TEE_END), tee_diram);
#endif
#ifdef CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP #ifdef CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
SOC_RESERVE_MEMORY_REGION(SOC_RTC_DRAM_LOW, (intptr_t)&_rtc_force_slow_end, rtcram_data); SOC_RESERVE_MEMORY_REGION(SOC_RTC_DRAM_LOW, (intptr_t)&_rtc_force_slow_end, rtcram_data);
#endif #endif