Skip to content

Commit d49055e

Browse files
committed
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
1 parent 26014bb commit d49055e

File tree

2 files changed

+55
-24
lines changed

2 files changed

+55
-24
lines changed

components/esp_tee/src/esp_tee.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -10,6 +10,7 @@
1010
#include "esp_private/cache_utils.h"
1111

1212
#include "freertos/FreeRTOS.h"
13+
#include "freertos/portmacro.h"
1314
#include "freertos/semphr.h"
1415
#include "freertos/task.h"
1516

@@ -43,7 +44,9 @@ uint32_t IRAM_ATTR esp_tee_service_call(int argc, ...)
4344
va_list ap;
4445
va_start(ap, argc);
4546

46-
if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) {
47+
/* NOTE: Cannot take the mutex if the scheduler is suspended or
48+
* service call is requested from a critical section */
49+
if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING && xPortCanYield()) {
4750
if (xSemaphoreTake(s_tee_mutex, portMAX_DELAY) == pdTRUE) {
4851
val = _u2m_switch(argc, ap);
4952
xSemaphoreGive(s_tee_mutex);

components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_ctx_switch.c

Lines changed: 50 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
#include "freertos/FreeRTOS.h"
8+
#include "freertos/portmacro.h"
89
#include "freertos/task.h"
910
#include "freertos/event_groups.h"
1011

@@ -18,6 +19,7 @@
1819

1920
#define TEST_TASK_1_DONE_BIT (BIT0)
2021
#define TEST_TASK_2_DONE_BIT (BIT1)
22+
#define TEST_TASK_DONE_BITS (TEST_TASK_1_DONE_BIT | TEST_TASK_2_DONE_BIT)
2123

2224
typedef struct {
2325
uint32_t id;
@@ -87,7 +89,7 @@ TEST_CASE("Test custom secure service call", "[basic]")
8789
TEST_ASSERT_EQUAL_UINT32(36, res);
8890
}
8991

90-
static void test_task(void *pvParameters)
92+
static void test_task_basic(void *pvParameters)
9193
{
9294
test_task_args_t *args = (test_task_args_t *)pvParameters;
9395
uint32_t *val = args->val;
@@ -97,7 +99,7 @@ static void test_task(void *pvParameters)
9799
while (*val <= ESP_TEE_TEST_INTR_ITER) {
98100
uint32_t curr_val = *val;
99101
if (curr_val != prev_val) {
100-
esp_rom_printf("[mode: %d] test_task - %d | val - %d\n", esp_cpu_get_curr_privilege_level(), id, curr_val);
102+
esp_rom_printf("[mode: %d] test_task - %lu | val - %lu\n", esp_cpu_get_curr_privilege_level(), id, curr_val);
101103
prev_val = curr_val;
102104
}
103105
vTaskDelay(pdMS_TO_TICKS(100));
@@ -109,39 +111,65 @@ static void test_task(void *pvParameters)
109111

110112
TEST_CASE("Test task switching during secure service calls", "[basic]")
111113
{
112-
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
113-
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
114+
TEST_ASSERT_EQUAL(ESP_CPU_NS_MODE, esp_cpu_get_curr_privilege_level());
114115

115116
test_task_eg = xEventGroupCreate();
116117
TEST_ASSERT_NOT_NULL(test_task_eg);
117118

118119
uint32_t a = 0, b = 0;
119-
120-
test_task_args_t task_args_1 = {
121-
.id = 1,
122-
.val = &a,
123-
.done_bit = TEST_TASK_1_DONE_BIT
124-
};
125-
126-
test_task_args_t task_args_2 = {
127-
.id = 2,
128-
.val = &b,
129-
.done_bit = TEST_TASK_2_DONE_BIT
120+
test_task_args_t task_args[] = {
121+
{ .id = 1, .val = &a, .done_bit = TEST_TASK_1_DONE_BIT },
122+
{ .id = 2, .val = &b, .done_bit = TEST_TASK_2_DONE_BIT }
130123
};
131124

132-
xTaskCreate(test_task, "test_task_1", 4096, (void *)&task_args_1, CONFIG_UNITY_FREERTOS_PRIORITY + 3, NULL);
133-
xTaskCreate(test_task, "test_task_2", 4096, (void *)&task_args_2, CONFIG_UNITY_FREERTOS_PRIORITY + 3, NULL);
125+
xTaskCreate(test_task_basic, "test_task_1", 4096, (void *)&task_args[0], CONFIG_UNITY_FREERTOS_PRIORITY + 3, NULL);
126+
xTaskCreate(test_task_basic, "test_task_2", 4096, (void *)&task_args[1], CONFIG_UNITY_FREERTOS_PRIORITY + 3, NULL);
134127

135128
uint32_t val = esp_tee_service_call(3, SS_ESP_TEE_TEST_PRIV_MODE_SWITCH, &a, &b);
136129
TEST_ASSERT_EQUAL_UINT32(ESP_TEE_TEST_INTR_ITER * 2, val);
137130

138-
EventBits_t bits = xEventGroupWaitBits(test_task_eg, TEST_TASK_1_DONE_BIT | TEST_TASK_2_DONE_BIT, pdTRUE, pdTRUE, portMAX_DELAY);
139-
TEST_ASSERT_MESSAGE((bits & TEST_TASK_1_DONE_BIT), "Task 1 did not complete");
140-
TEST_ASSERT_MESSAGE((bits & TEST_TASK_2_DONE_BIT), "Task 2 did not complete");
131+
EventBits_t bits = xEventGroupWaitBits(test_task_eg, TEST_TASK_DONE_BITS, pdTRUE, pdTRUE, portMAX_DELAY);
132+
TEST_ASSERT(bits & TEST_TASK_DONE_BITS);
141133
vEventGroupDelete(test_task_eg);
142134

143-
mode = esp_cpu_get_curr_privilege_level();
144-
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
135+
TEST_ASSERT_EQUAL(ESP_CPU_NS_MODE, esp_cpu_get_curr_privilege_level());
136+
}
137+
138+
static void test_task_w_sec_srv(void *pvParameters)
139+
{
140+
test_task_args_t *args = (test_task_args_t *)pvParameters;
141+
uint32_t id = args->id;
142+
143+
esp_rom_printf("[task: %lu] Running...\n", id);
144+
145+
uint32_t a = 0, b = 0;
146+
uint32_t res = esp_tee_service_call(3, SS_ESP_TEE_TEST_PRIV_MODE_SWITCH, &a, &b);
147+
148+
vTaskDelay(pdMS_TO_TICKS(100));
149+
TEST_ASSERT_EQUAL_UINT32(ESP_TEE_TEST_INTR_ITER * 2, res);
150+
151+
esp_rom_printf("[task: %lu] Exiting...\n", id);
152+
153+
xEventGroupSetBits(test_task_eg, args->done_bit);
154+
vTaskDelete(NULL);
155+
}
156+
157+
TEST_CASE("Test parallel secure service calls", "[basic]")
158+
{
159+
test_task_eg = xEventGroupCreate();
160+
TEST_ASSERT_NOT_NULL(test_task_eg);
161+
162+
test_task_args_t task_args[] = {
163+
{ .id = 1, .done_bit = TEST_TASK_1_DONE_BIT },
164+
{ .id = 2, .done_bit = TEST_TASK_2_DONE_BIT }
165+
};
166+
167+
xTaskCreate(test_task_w_sec_srv, "test_task1", 4096, (void *)&task_args[0], CONFIG_UNITY_FREERTOS_PRIORITY, NULL);
168+
xTaskCreate(test_task_w_sec_srv, "test_task2", 4096, (void *)&task_args[1], CONFIG_UNITY_FREERTOS_PRIORITY, NULL);
169+
170+
EventBits_t bits = xEventGroupWaitBits(test_task_eg, TEST_TASK_DONE_BITS, pdTRUE, pdTRUE, portMAX_DELAY);
171+
TEST_ASSERT(bits & TEST_TASK_DONE_BITS);
172+
vEventGroupDelete(test_task_eg);
145173
}
146174

147175
TEST_CASE("Test TEE Heap: Malloc-write-free cycles", "[heap]")

0 commit comments

Comments
 (0)