Merge branch 'feat/esp_tee_mspi_tuning' into 'master'

change(esp_tee): Fix TEE SPI flash API issues on ESP32-C5

Closes IDF-13826

See merge request espressif/esp-idf!41952
This commit is contained in:
Mahavir Jain
2025-10-27 10:09:29 +05:30
18 changed files with 212 additions and 46 deletions

View File

@@ -217,13 +217,10 @@ static uint32_t current_mapped_size;
// Current bootloader mapping (ab)used for bootloader_read()
static uint32_t current_read_mapping = UINT32_MAX;
#if ESP_TEE_BUILD && CONFIG_IDF_TARGET_ESP32C6
extern void spi_common_set_dummy_output(esp_rom_spiflash_read_mode_t mode);
extern void spi_dummy_len_fix(uint8_t spi, uint8_t freqdiv);
/* TODO: [ESP-TEE] Workarounds for the ROM read API
*
* The esp_rom_spiflash_read API requires two workarounds on ESP32-C6 ECO0:
#if ESP_TEE_BUILD
/* [ESP-TEE] Workarounds for the ROM SPI flash APIs */
/*
* TODO: The esp_rom_spiflash_read API requires two workarounds on ESP32-C6 ECO0 -
*
* 1. [IDF-7199] Call esp_rom_spiflash_write API once before reading.
* Without this, reads return corrupted data.
@@ -231,10 +228,14 @@ extern void spi_dummy_len_fix(uint8_t spi, uint8_t freqdiv);
* 2. Configure ROM flash parameters before each read using the function below.
* Without this, the first byte read is corrupted.
*
* Note: These workarounds are not needed for ESP32-C6 ECO1 and later versions.
* NOTE: These workarounds are not needed for ESP32-C6 ECO1 and later versions.
*/
static void rom_read_api_workaround(void)
{
#if CONFIG_ESP32C6_REV_MIN_0
extern void spi_common_set_dummy_output(esp_rom_spiflash_read_mode_t mode);
extern void spi_dummy_len_fix(uint8_t spi, uint8_t freqdiv);
static bool is_first_call = true;
if (is_first_call) {
uint32_t dummy_val = UINT32_MAX;
@@ -268,6 +269,43 @@ static void rom_read_api_workaround(void)
spi_dummy_len_fix(1, freqdiv);
esp_rom_spiflash_config_readmode(read_mode);
spi_common_set_dummy_output(read_mode);
#endif
}
/*
* TODO: [IDF-13582]
*
* When `esp_flash_read()` is invoked from REE, it enables SPI1 WB (write-back) mode
* via `spi_flash_ll_wb_mode_enable()`. The ROM flash APIs used by TEE do not support
* WB mode, causing failures when TEE later accesses flash.
*
* Workaround applied in TEE flash layer:
* 1. Save the current WB mode state.
* 2. Temporarily disable WB mode before calling ROM flash APIs.
* 3. Restore WB mode state after the ROM API call completes.
*
* NOTE: This workaround will become removed once IDF-13582 is implemented.
*/
static inline bool spi1_wb_mode_save_and_disable(void)
{
#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL
if (REG_GET_BIT(SPI_MEM_RD_STATUS_REG(1), SPI_MEM_WB_MODE_EN)) {
REG_CLR_BIT(SPI_MEM_RD_STATUS_REG(1), SPI_MEM_WB_MODE_EN);
return true;
}
#endif
return false;
}
static inline void spi1_wb_mode_restore(bool saved_state)
{
#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL
if (saved_state) {
REG_SET_BIT(SPI_MEM_RD_STATUS_REG(1), SPI_MEM_WB_MODE_EN);
}
#else
(void)saved_state;
#endif
}
#endif
@@ -416,8 +454,9 @@ static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, s
#else
#if !ESP_TEE_BUILD
cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
#elif CONFIG_ESP32C6_REV_MIN_0
#else
rom_read_api_workaround();
bool is_wb_saved = spi1_wb_mode_save_and_disable();
#endif
#endif
@@ -428,6 +467,8 @@ static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, s
#else
#if !ESP_TEE_BUILD
cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
#else
spi1_wb_mode_restore(is_wb_saved);
#endif
#endif
@@ -550,6 +591,10 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool
return err;
}
#if ESP_TEE_BUILD
bool is_wb_saved = spi1_wb_mode_save_and_disable();
#endif
esp_rom_spiflash_result_t rc = ESP_ROM_SPIFLASH_RESULT_OK;
if (write_encrypted && !ENCRYPTION_IS_VIRTUAL) {
@@ -564,6 +609,7 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool
* from being read from already memory-mapped addresses that were modified.
*/
#if ESP_TEE_BUILD
spi1_wb_mode_restore(is_wb_saved);
spi_flash_check_and_flush_cache(dest_addr, size);
#endif

View File

@@ -6,7 +6,7 @@ set(includes "include" "${target}/include")
if(esp_tee_build)
if(CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1)
list(APPEND srcs "spi_flash_hal.c")
list(APPEND srcs "spi_flash_hal.c" "spi_flash_hal_iram.c")
endif()
elseif(NOT BOOTLOADER_BUILD)
if(NOT CONFIG_APP_BUILD_TYPE_PURE_RAM_APP)

View File

@@ -131,15 +131,7 @@ esp_err_t spi_flash_hal_configure_host_io_mode(
addr_bitlen += SPI_FLASH_LL_CONTINUOUS_MODE_BIT_NUMS;
#endif
spi_flash_ll_set_extra_address(dev, 0);
// TODO: [IDF-13582]
// Currently, REE and TEE use different sets of APIs for flash operations -
// REE uses the IDF SPI flash driver while TEE call the ROM APIs. This inconsistency
// leads to compatibility issues on ESP32-C5.
// One specific issue arises when esp_flash_read() is used in REE, which internally
// calls spi_flash_ll_wb_mode_enable(). This function enables the WB mode bit in
// the flash write operation. However, the ROM API does not support this
// feature, resulting in failures when TEE attempts to access flash after this call.
#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL && !CONFIG_SECURE_ENABLE_TEE
#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL
spi_flash_ll_wb_mode_enable(dev, true);
#endif
}
@@ -218,8 +210,7 @@ esp_err_t spi_flash_hal_common_command(spi_flash_host_inst_t *host, spi_flash_tr
if (trans->miso_len > 0) {
spi_flash_ll_get_buffer_data(dev, trans->miso_data, trans->miso_len);
}
// TODO: [IDF-13582]
#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL && !CONFIG_SECURE_ENABLE_TEE
#if SOC_SPI_MEM_SUPPORT_WB_MODE_INDEPENDENT_CONTROL
spi_flash_ll_wb_mode_enable(dev, false);
#endif
return ESP_OK;

View File

@@ -175,7 +175,20 @@ if(NOT non_os_build)
else()
if(ESP_TEE_BUILD)
list(APPEND srcs "esp_clk.c" "hw_random.c")
if(CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1)
list(APPEND srcs "mspi_timing_tuning/mspi_timing_tuning.c")
if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_MSPI_DELAY)
list(APPEND srcs "mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_mspi_delay.c")
endif()
if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_DQS)
list(APPEND srcs "mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_dqs.c")
endif()
if(CONFIG_SOC_MEMSPI_TIMING_TUNING_BY_FLASH_DELAY)
list(APPEND srcs "mspi_timing_tuning/tuning_scheme_impl/mspi_timing_by_flash_delay.c")
endif()
endif()
endif()
# Requires "_esp_error_check_failed()" function
list(APPEND priv_requires "esp_system")
endif()

View File

@@ -15,7 +15,12 @@
#include "soc/soc.h"
#include "hal/spi_flash_hal.h"
#include "hal/mspi_ll.h"
#if !ESP_TEE_BUILD
#include "esp_private/esp_cache_private.h"
#else
#include "hal/cache_ll.h"
#include "hal/cache_hal.h"
#endif
#include "esp_private/mspi_timing_tuning.h"
#include "esp_private/mspi_timing_config.h"
#include "esp_private/mspi_timing_by_mspi_delay.h"
@@ -553,7 +558,12 @@ void mspi_timing_change_speed_mode_cache_safe(bool switch_down)
* for preventing concurrent from MSPI to external memory
*/
#if SOC_CACHE_FREEZE_SUPPORTED
#if !ESP_TEE_BUILD
esp_cache_freeze_ext_mem_cache();
#else
/* NOTE: [ESP-TEE] Check implementation when SoCs with 2-level cache are supported */
cache_hal_freeze(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
#endif
#endif //#if SOC_CACHE_FREEZE_SUPPORTED
if (switch_down) {
@@ -565,7 +575,11 @@ void mspi_timing_change_speed_mode_cache_safe(bool switch_down)
}
#if SOC_CACHE_FREEZE_SUPPORTED
#if !ESP_TEE_BUILD
esp_cache_unfreeze_ext_mem_cache();
#else
cache_hal_unfreeze(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
#endif
#endif //#if SOC_CACHE_FREEZE_SUPPORTED
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE && !CONFIG_FREERTOS_UNICORE

View File

@@ -28,10 +28,7 @@
#define MSPI_TIMING_FLASH_MODULE_CLOCK 120
#endif
//------------------------------------FLASH Needs Tuning or not-------------------------------------//
/* TODO: [ESP-TEE | IDF-10425] The SPI1 controller is protected by APM when ESP-TEE is enabled.
* MSPI tuning requires access to this controller, so it is currently disabled.
*/
#if MSPI_TIMING_FLASH_STR_MODE && !CONFIG_SECURE_ENABLE_TEE
#if MSPI_TIMING_FLASH_STR_MODE
#define MSPI_TIMING_FLASH_NEEDS_TUNING (MSPI_TIMING_FLASH_MODULE_CLOCK > 40)
#endif
@@ -48,8 +45,7 @@
#define MSPI_TIMING_PSRAM_MODULE_CLOCK 10 //Define this to 10MHz
#endif
//------------------------------------PSRAM Needs Tuning or not-------------------------------------//
/* TODO: [ESP-TEE | IDF-10425] */
#if MSPI_TIMING_PSRAM_STR_MODE && !CONFIG_SECURE_ENABLE_TEE
#if MSPI_TIMING_PSRAM_STR_MODE
#define MSPI_TIMING_PSRAM_NEEDS_TUNING (MSPI_TIMING_PSRAM_MODULE_CLOCK > 40)
#endif

View File

@@ -152,21 +152,12 @@ if(CONFIG_ESP_ROM_HAS_VERSION)
endif()
if(ESP_TEE_BUILD)
if(CONFIG_IDF_TARGET_ESP32H4 AND NOT CONFIG_ESP32H4_SELECTS_REV_MP) # TODO: ESP32H4 IDF-13835
rom_linker_script("beta5.heap")
rom_linker_script("beta5.spiflash")
if(CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT)
rom_linker_script("beta5.newlib-nano")
endif()
else()
rom_linker_script("heap")
rom_linker_script("spiflash")
if(CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT)
rom_linker_script("newlib-nano")
endif()
rom_linker_script("heap")
if(CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT)
rom_linker_script("newlib-nano")
endif()
rom_linker_script("libc")
if(CONFIG_ESP_ROM_HAS_SUBOPTIMAL_NEWLIB_ON_MISALIGNED_MEMORY) # TODO IDF-13852: use optimized memcpy for TEE ?
if(CONFIG_ESP_ROM_HAS_SUBOPTIMAL_NEWLIB_ON_MISALIGNED_MEMORY)
rom_linker_script("libc-suboptimal_for_misaligned_mem")
endif()
endif()

View File

@@ -96,6 +96,30 @@ secure_services:
type: IDF
function: spi_flash_chip_generic_config_host_io_mode
args: 2
- id: 23
type: IDF
function: mspi_timing_flash_tuning
args: 0
- id: 24
type: IDF
function: mspi_timing_psram_tuning
args: 0
- id: 25
type: IDF
function: mspi_timing_enter_low_speed_mode
args: 1
- id: 26
type: IDF
function: mspi_timing_enter_high_speed_mode
args: 1
- id: 27
type: IDF
function: mspi_timing_change_speed_mode_cache_safe
args: 1
- id: 28
type: IDF
function: spi_timing_get_flash_timing_param
args: 1
# ID: 30-53 (24) - Interrupt Handling
- family: interrupt_handling
entries:

View File

@@ -13,7 +13,9 @@
#include "rom/digital_signature.h"
#include "hal/mmu_types.h"
#include "hal/wdt_hal.h"
#include "hal/spi_flash_hal.h"
#include "hal/spi_flash_types.h"
#include "esp_private/mspi_timing_tuning.h"
#include "esp_hmac.h"
#include "esp_ds.h"
#include "esp_crypto_lock.h"
@@ -490,4 +492,36 @@ esp_err_t IRAM_ATTR __wrap_spi_flash_chip_generic_config_host_io_mode(esp_flash_
{
return esp_tee_service_call(3, SS_SPI_FLASH_CHIP_GENERIC_CONFIG_HOST_IO_MODE, chip, flags);
}
#if CONFIG_IDF_TARGET_ESP32C5
void IRAM_ATTR __wrap_mspi_timing_flash_tuning(void)
{
esp_tee_service_call(1, SS_MSPI_TIMING_FLASH_TUNING);
}
void IRAM_ATTR __wrap_mspi_timing_psram_tuning(void)
{
esp_tee_service_call(1, SS_MSPI_TIMING_PSRAM_TUNING);
}
void IRAM_ATTR __wrap_mspi_timing_enter_low_speed_mode(bool control_spi1)
{
esp_tee_service_call(2, SS_MSPI_TIMING_ENTER_LOW_SPEED_MODE, control_spi1);
}
void IRAM_ATTR __wrap_mspi_timing_enter_high_speed_mode(bool control_spi1)
{
esp_tee_service_call(2, SS_MSPI_TIMING_ENTER_HIGH_SPEED_MODE, control_spi1);
}
void IRAM_ATTR __wrap_mspi_timing_change_speed_mode_cache_safe(bool switch_down)
{
esp_tee_service_call(2, SS_MSPI_TIMING_CHANGE_SPEED_MODE_CACHE_SAFE, switch_down);
}
void IRAM_ATTR __wrap_spi_timing_get_flash_timing_param(spi_flash_hal_timing_config_t *out_timing_config)
{
esp_tee_service_call(2, SS_SPI_TIMING_GET_FLASH_TIMING_PARAM, out_timing_config);
}
#endif
#endif

View File

@@ -25,7 +25,7 @@ set(ESP_TEE_BUILD 1)
set(NON_OS_BUILD 1)
# Additional components
list(APPEND COMPONENTS bootloader_support efuse esp_security mbedtls esp_stdio)
list(APPEND COMPONENTS bootloader_support efuse esp_hal_mspi esp_security mbedtls esp_stdio)
# TEE-specific components
list(APPEND COMPONENTS tee_flash_mgr tee_ota_ops tee_sec_storage tee_attestation)

View File

@@ -18,6 +18,7 @@
#include "hal/spi_flash_types.h"
#include "spi_flash_chip_generic.h"
#include "memspi_host_driver.h"
#include "esp_private/mspi_timing_tuning.h"
#include "esp_flash.h"
#include "riscv/rv_utils.h"
@@ -417,4 +418,36 @@ esp_err_t _ss_spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip, uint
{
return spi_flash_chip_generic_config_host_io_mode(chip, flags);
}
#if CONFIG_IDF_TARGET_ESP32C5
void _ss_mspi_timing_psram_tuning(void)
{
mspi_timing_psram_tuning();
}
void _ss_mspi_timing_flash_tuning(void)
{
mspi_timing_flash_tuning();
}
void _ss_mspi_timing_enter_low_speed_mode(bool control_spi1)
{
mspi_timing_enter_low_speed_mode(control_spi1);
}
void _ss_mspi_timing_enter_high_speed_mode(bool control_spi1)
{
mspi_timing_enter_high_speed_mode(control_spi1);
}
void _ss_mspi_timing_change_speed_mode_cache_safe(bool switch_down)
{
mspi_timing_change_speed_mode_cache_safe(switch_down);
}
void _ss_spi_timing_get_flash_timing_param(spi_flash_hal_timing_config_t *out_timing_config)
{
spi_timing_get_flash_timing_param(out_timing_config);
}
#endif
#endif

View File

@@ -40,6 +40,11 @@ PROVIDE ( esp_tee_app_config = SRAM_REE_SEG_START + 0x2b0 );
PROVIDE ( GDMA = 0x60080000 );
/* SPI Flash functions required from the ROM (refer esp32c5.rom.spiflash.ld) */
PROVIDE ( spi_flash_check_and_flush_cache = 0x40000230 );
PROVIDE ( spi_flash_chip_generic_config_host_io_mode = 0x400002d4 );
PROVIDE ( memspi_host_flush_cache = 0x40000318 );
/* Default entry point: */
ENTRY(esp_tee_init);
@@ -98,6 +103,7 @@ SECTIONS
*libhal.a:cache_hal.c*(.literal .text .literal.* .text.*)
*libhal.a:wdt_hal_iram.c*(.literal .text .literal.* .text.*)
*libhal.a:apm_hal.c*(.literal .text .literal.* .text.*)
*libesp_hal_mspi.a:*(.literal .text .literal.* .text.*)
/* IDF components */
*libbootloader_support.a:*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:*(.literal .text .literal.* .text.*)
@@ -146,6 +152,7 @@ SECTIONS
/* HAL (noflash) */
*libhal.a:mmu_hal.c*(.rodata .srodata .rodata.* .srodata.*)
*libhal.a:cache_hal.c*(.rodata .srodata .rodata.* .srodata.*)
*libesp_hal_mspi.a:*(.rodata .srodata .rodata.* .srodata.*)
_tee_rodata_end = ABSOLUTE(.);
_tee_dram_end = ABSOLUTE(.);
} > sram_tee_seg

View File

@@ -40,6 +40,11 @@ PROVIDE ( esp_tee_app_config = SRAM_REE_SEG_START + 0x2e0 );
PROVIDE ( GDMA = 0x60080000 );
/* SPI Flash functions required from the ROM (refer esp32c6.rom.spiflash.ld) */
PROVIDE ( spi_flash_check_and_flush_cache = 0x4000021c );
PROVIDE ( spi_flash_chip_generic_config_host_io_mode = 0x400002c4 );
PROVIDE ( memspi_host_flush_cache = 0x40000308 );
/* Default entry point: */
ENTRY(esp_tee_init);
@@ -98,6 +103,7 @@ SECTIONS
*libhal.a:cache_hal.c*(.literal .text .literal.* .text.*)
*libhal.a:wdt_hal_iram.c*(.literal .text .literal.* .text.*)
*libhal.a:apm_hal.c*(.literal .text .literal.* .text.*)
*libesp_hal_mspi.a:*(.literal .text .literal.* .text.*)
/* IDF components */
*libbootloader_support.a:*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:*(.literal .text .literal.* .text.*)
@@ -146,6 +152,7 @@ SECTIONS
/* HAL (noflash) */
*libhal.a:mmu_hal.c*(.rodata .srodata .rodata.* .srodata.*)
*libhal.a:cache_hal.c*(.rodata .srodata .rodata.* .srodata.*)
*libesp_hal_mspi.a:*(.rodata .srodata .rodata.* .srodata.*)
_tee_rodata_end = ABSOLUTE(.);
_tee_dram_end = ABSOLUTE(.);
} > sram_tee_seg

View File

@@ -40,6 +40,11 @@ PROVIDE ( esp_tee_app_config = SRAM_REE_SEG_START + 0x2e0 );
PROVIDE ( GDMA = 0x60080000 );
/* SPI Flash functions required from the ROM (refer esp32h2.rom.spiflash.ld) */
PROVIDE ( spi_flash_check_and_flush_cache = 0x40000214 );
PROVIDE ( spi_flash_chip_generic_config_host_io_mode = 0x400002bc );
PROVIDE ( memspi_host_flush_cache = 0x40000300 );
/* Default entry point: */
ENTRY(esp_tee_init);
@@ -98,6 +103,7 @@ SECTIONS
*libhal.a:cache_hal.c*(.literal .text .literal.* .text.*)
*libhal.a:wdt_hal_iram.c*(.literal .text .literal.* .text.*)
*libhal.a:apm_hal.c*(.literal .text .literal.* .text.*)
*libesp_hal_mspi.a:*(.literal .text .literal.* .text.*)
/* IDF components */
*libbootloader_support.a:*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:*(.literal .text .literal.* .text.*)
@@ -146,6 +152,7 @@ SECTIONS
/* HAL (noflash) */
*libhal.a:mmu_hal.c*(.rodata .srodata .rodata.* .srodata.*)
*libhal.a:cache_hal.c*(.rodata .srodata .rodata.* .srodata.*)
*libesp_hal_mspi.a:*(.rodata .srodata .rodata.* .srodata.*)
_tee_rodata_end = ABSOLUTE(.);
_tee_dram_end = ABSOLUTE(.);
} > sram_tee_seg

View File

@@ -1,8 +1,6 @@
# Reducing TEE I/DRAM sizes
# 28KB
CONFIG_SECURE_TEE_IRAM_SIZE=0x7000
# 16KB
CONFIG_SECURE_TEE_DRAM_SIZE=0x4000
# TEE Secure Storage: Release mode
CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE=y

View File

@@ -15,3 +15,7 @@ CONFIG_NVS_SEC_KEY_PROTECT_USING_FLASH_ENC=y
# TEE Secure Storage: Release mode
CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE=y
CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID=5
# Increasing TEE DRAM size
# 18KB
CONFIG_SECURE_TEE_DRAM_SIZE=0x4800

View File

@@ -15,3 +15,7 @@ CONFIG_SECURE_TEE_ATT_KEY_STR_ID="tee_att_keyN"
# Enabling flash protection over SPI1
CONFIG_SECURE_TEE_EXT_FLASH_MEMPROT_SPI1=y
# Increasing TEE DRAM size
# 19KB
CONFIG_SECURE_TEE_DRAM_SIZE=0x4c00

View File

@@ -11,6 +11,3 @@ CONFIG_SECURE_TEE_TEST_MODE=y
# Setting partition table
CONFIG_PARTITION_TABLE_SINGLE_APP_TEE=y
CONFIG_PARTITION_TABLE_OFFSET=0xF000
# TEE IRAM size
CONFIG_SECURE_TEE_IRAM_SIZE=0x8400