From d49055e307e9941bef3a7dfaf37620669c052a87 Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Wed, 3 Sep 2025 12:07:39 +0530 Subject: [PATCH] fix(esp_tee): Skip taking the service call mutex when in critical sections - Fixes INT_WDT timeouts with mmap operations - Add test-case for verifying parallel service calls --- components/esp_tee/src/esp_tee.c | 7 +- .../main/test_esp_tee_ctx_switch.c | 72 +++++++++++++------ 2 files changed, 55 insertions(+), 24 deletions(-) diff --git a/components/esp_tee/src/esp_tee.c b/components/esp_tee/src/esp_tee.c index 3079c5ae9e..e1a55449f7 100644 --- a/components/esp_tee/src/esp_tee.c +++ b/components/esp_tee/src/esp_tee.c @@ -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 */ @@ -10,6 +10,7 @@ #include "esp_private/cache_utils.h" #include "freertos/FreeRTOS.h" +#include "freertos/portmacro.h" #include "freertos/semphr.h" #include "freertos/task.h" @@ -43,7 +44,9 @@ uint32_t IRAM_ATTR esp_tee_service_call(int argc, ...) va_list ap; va_start(ap, argc); - if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) { + /* NOTE: Cannot take the mutex if the scheduler is suspended or + * service call is requested from a critical section */ + if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING && xPortCanYield()) { if (xSemaphoreTake(s_tee_mutex, portMAX_DELAY) == pdTRUE) { val = _u2m_switch(argc, ap); xSemaphoreGive(s_tee_mutex); diff --git a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_ctx_switch.c b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_ctx_switch.c index 618717d709..e3e122ae70 100644 --- a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_ctx_switch.c +++ b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_ctx_switch.c @@ -5,6 +5,7 @@ */ #include "freertos/FreeRTOS.h" +#include "freertos/portmacro.h" #include "freertos/task.h" #include "freertos/event_groups.h" @@ -18,6 +19,7 @@ #define TEST_TASK_1_DONE_BIT (BIT0) #define TEST_TASK_2_DONE_BIT (BIT1) +#define TEST_TASK_DONE_BITS (TEST_TASK_1_DONE_BIT | TEST_TASK_2_DONE_BIT) typedef struct { uint32_t id; @@ -87,7 +89,7 @@ TEST_CASE("Test custom secure service call", "[basic]") TEST_ASSERT_EQUAL_UINT32(36, res); } -static void test_task(void *pvParameters) +static void test_task_basic(void *pvParameters) { test_task_args_t *args = (test_task_args_t *)pvParameters; uint32_t *val = args->val; @@ -97,7 +99,7 @@ static void test_task(void *pvParameters) while (*val <= ESP_TEE_TEST_INTR_ITER) { uint32_t curr_val = *val; if (curr_val != prev_val) { - esp_rom_printf("[mode: %d] test_task - %d | val - %d\n", esp_cpu_get_curr_privilege_level(), id, curr_val); + esp_rom_printf("[mode: %d] test_task - %lu | val - %lu\n", esp_cpu_get_curr_privilege_level(), id, curr_val); prev_val = curr_val; } vTaskDelay(pdMS_TO_TICKS(100)); @@ -109,39 +111,65 @@ static void test_task(void *pvParameters) TEST_CASE("Test task switching during secure service calls", "[basic]") { - esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); + TEST_ASSERT_EQUAL(ESP_CPU_NS_MODE, esp_cpu_get_curr_privilege_level()); test_task_eg = xEventGroupCreate(); TEST_ASSERT_NOT_NULL(test_task_eg); uint32_t a = 0, b = 0; - - test_task_args_t task_args_1 = { - .id = 1, - .val = &a, - .done_bit = TEST_TASK_1_DONE_BIT + test_task_args_t task_args[] = { + { .id = 1, .val = &a, .done_bit = TEST_TASK_1_DONE_BIT }, + { .id = 2, .val = &b, .done_bit = TEST_TASK_2_DONE_BIT } }; - test_task_args_t task_args_2 = { - .id = 2, - .val = &b, - .done_bit = TEST_TASK_2_DONE_BIT - }; - - xTaskCreate(test_task, "test_task_1", 4096, (void *)&task_args_1, CONFIG_UNITY_FREERTOS_PRIORITY + 3, NULL); - xTaskCreate(test_task, "test_task_2", 4096, (void *)&task_args_2, CONFIG_UNITY_FREERTOS_PRIORITY + 3, NULL); + xTaskCreate(test_task_basic, "test_task_1", 4096, (void *)&task_args[0], CONFIG_UNITY_FREERTOS_PRIORITY + 3, NULL); + xTaskCreate(test_task_basic, "test_task_2", 4096, (void *)&task_args[1], CONFIG_UNITY_FREERTOS_PRIORITY + 3, NULL); uint32_t val = esp_tee_service_call(3, SS_ESP_TEE_TEST_PRIV_MODE_SWITCH, &a, &b); TEST_ASSERT_EQUAL_UINT32(ESP_TEE_TEST_INTR_ITER * 2, val); - EventBits_t bits = xEventGroupWaitBits(test_task_eg, TEST_TASK_1_DONE_BIT | TEST_TASK_2_DONE_BIT, pdTRUE, pdTRUE, portMAX_DELAY); - TEST_ASSERT_MESSAGE((bits & TEST_TASK_1_DONE_BIT), "Task 1 did not complete"); - TEST_ASSERT_MESSAGE((bits & TEST_TASK_2_DONE_BIT), "Task 2 did not complete"); + EventBits_t bits = xEventGroupWaitBits(test_task_eg, TEST_TASK_DONE_BITS, pdTRUE, pdTRUE, portMAX_DELAY); + TEST_ASSERT(bits & TEST_TASK_DONE_BITS); vEventGroupDelete(test_task_eg); - mode = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); + TEST_ASSERT_EQUAL(ESP_CPU_NS_MODE, esp_cpu_get_curr_privilege_level()); +} + +static void test_task_w_sec_srv(void *pvParameters) +{ + test_task_args_t *args = (test_task_args_t *)pvParameters; + uint32_t id = args->id; + + esp_rom_printf("[task: %lu] Running...\n", id); + + uint32_t a = 0, b = 0; + uint32_t res = esp_tee_service_call(3, SS_ESP_TEE_TEST_PRIV_MODE_SWITCH, &a, &b); + + vTaskDelay(pdMS_TO_TICKS(100)); + TEST_ASSERT_EQUAL_UINT32(ESP_TEE_TEST_INTR_ITER * 2, res); + + esp_rom_printf("[task: %lu] Exiting...\n", id); + + xEventGroupSetBits(test_task_eg, args->done_bit); + vTaskDelete(NULL); +} + +TEST_CASE("Test parallel secure service calls", "[basic]") +{ + test_task_eg = xEventGroupCreate(); + TEST_ASSERT_NOT_NULL(test_task_eg); + + test_task_args_t task_args[] = { + { .id = 1, .done_bit = TEST_TASK_1_DONE_BIT }, + { .id = 2, .done_bit = TEST_TASK_2_DONE_BIT } + }; + + xTaskCreate(test_task_w_sec_srv, "test_task1", 4096, (void *)&task_args[0], CONFIG_UNITY_FREERTOS_PRIORITY, NULL); + xTaskCreate(test_task_w_sec_srv, "test_task2", 4096, (void *)&task_args[1], CONFIG_UNITY_FREERTOS_PRIORITY, NULL); + + EventBits_t bits = xEventGroupWaitBits(test_task_eg, TEST_TASK_DONE_BITS, pdTRUE, pdTRUE, portMAX_DELAY); + TEST_ASSERT(bits & TEST_TASK_DONE_BITS); + vEventGroupDelete(test_task_eg); } TEST_CASE("Test TEE Heap: Malloc-write-free cycles", "[heap]")