Skip to content

Commit 873409d

Browse files
committed
refactor(esp_tee): Simplify service call ASM routine
- Remove `mret` for jumping to the service call dispatcher; instead, enable interrupts and execute directly - Fix potential corruption of the `t3` register when returning from a service call - Simplify the secure service dispatcher function
1 parent 5c4a527 commit 873409d

File tree

13 files changed

+95
-137
lines changed

13 files changed

+95
-137
lines changed

components/esp_tee/include/esp_tee.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,8 @@ typedef struct {
4343
uint32_t magic_word;
4444
uint32_t api_major_version;
4545
uint32_t api_minor_version;
46-
uint32_t reserved[2];
46+
uint32_t reserved[3];
4747
/* TEE-related fields */
48-
void *s_entry_addr;
4948
void *s_int_handler;
5049
/* REE-related fields */
5150
void *ns_entry_addr;
@@ -85,14 +84,12 @@ uint32_t esp_tee_service_call_with_noniram_intr_disabled(int argc, ...);
8584

8685
#if !(__DOXYGEN__)
8786
/* Offsets of some values in esp_tee_config_t that are used by assembly code */
88-
#define ESP_TEE_CFG_OFFS_S_ENTRY_ADDR 0x14
8987
#define ESP_TEE_CFG_OFFS_S_INTR_HANDLER 0x18
9088
#define ESP_TEE_CFG_OFFS_NS_ENTRY_ADDR 0x1C
9189
#define ESP_TEE_CFG_OFFS_NS_INTR_HANDLER 0x20
9290

9391
#if !defined(__ASSEMBLER__)
9492
/* Check the offsets are correct using the C compiler */
95-
ESP_STATIC_ASSERT(offsetof(esp_tee_config_t, s_entry_addr) == ESP_TEE_CFG_OFFS_S_ENTRY_ADDR, "offset macro is wrong");
9693
ESP_STATIC_ASSERT(offsetof(esp_tee_config_t, s_int_handler) == ESP_TEE_CFG_OFFS_S_INTR_HANDLER, "offset macro is wrong");
9794
ESP_STATIC_ASSERT(offsetof(esp_tee_config_t, ns_entry_addr) == ESP_TEE_CFG_OFFS_NS_ENTRY_ADDR, "offset macro is wrong");
9895
ESP_STATIC_ASSERT(offsetof(esp_tee_config_t, ns_int_handler) == ESP_TEE_CFG_OFFS_NS_INTR_HANDLER, "offset macro is wrong");

components/esp_tee/src/esp_tee_config.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -25,9 +25,9 @@ esp_tee_config_t esp_tee_app_config __attribute__((section(".esp_tee_app_cfg")))
2525
.api_major_version = ESP_TEE_API_MAJOR_VER,
2626
.api_minor_version = ESP_TEE_API_MINOR_VER,
2727

28-
/* .s_entry_addr and .s_intr_handler are NULL in the
29-
app binary, but will be written by the TEE before it loads the binary
30-
*/
28+
/* s_intr_handler is NULL in the REE image, but will be written by
29+
* the TEE before it loads the binary
30+
*/
3131

3232
.ns_int_handler = &_tee_interrupt_handler,
3333
.ns_entry_addr = &_u2m_switch,

components/esp_tee/subproject/main/CMakeLists.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ set(srcs "core/esp_tee_init.c"
2020

2121
# Arch specific implementation for TEE
2222
list(APPEND srcs "arch/${arch}/esp_tee_vectors.S"
23-
"arch/${arch}/esp_tee_vector_table.S"
24-
"arch/${arch}/esp_tee_secure_entry.S")
23+
"arch/${arch}/esp_tee_vector_table.S")
2524

2625
# SoC specific implementation for TEE
2726
list(APPEND srcs "soc/${target}/esp_tee_secure_sys_cfg.c"
@@ -78,7 +77,9 @@ list(APPEND srcs "common/esp_app_desc_tee.c")
7877
idf_component_register(SRCS ${srcs}
7978
INCLUDE_DIRS ${include})
8079

81-
set_source_files_properties("core/esp_secure_services.c" PROPERTIES COMPILE_FLAGS -Wno-deprecated)
80+
# TODO: Currently only -Og optimization level works correctly at runtime
81+
set_source_files_properties("core/esp_secure_dispatcher.c" PROPERTIES COMPILE_FLAGS "-Og")
82+
8283
include(${CMAKE_CURRENT_LIST_DIR}/ld/esp_tee_ld.cmake)
8384

8485
# esp_app_desc_t configuration structure for TEE: Linking symbol and trimming project version and name

components/esp_tee/subproject/main/arch/riscv/esp_tee_secure_entry.S

Lines changed: 0 additions & 33 deletions
This file was deleted.

components/esp_tee/subproject/main/arch/riscv/esp_tee_vectors.S

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "riscv/encoding.h"
1414
#include "riscv/rvruntime-frames.h"
15+
#include "esp_private/vectors_const.h"
1516

1617
#include "esp_tee.h"
1718
#include "sdkconfig.h"
@@ -25,9 +26,12 @@
2526
.equ ECALL_U_MODE, 0x8
2627
.equ ECALL_M_MODE, 0xb
2728
.equ TEE_APM_INTR_MASK_0, 0x00300000
28-
.equ TEE_APM_INTR_MASK_1, 0x000000F8
29+
.equ TEE_APM_INTR_MASK_1, 0x000000f8
30+
.equ TEE_INTR_DELEG_MASK, 0xffffbfff
2931

3032
.global esp_tee_global_interrupt_handler
33+
.global esp_tee_service_dispatcher
34+
3135

3236
.section .data
3337
.align 4
@@ -179,6 +183,8 @@ _panic_handler:
179183

180184
/* Read mcause */
181185
csrr t0, mcause
186+
li t1, VECTORS_MCAUSE_INTBIT_MASK | VECTORS_MCAUSE_REASON_MASK
187+
and t0, t0, t1
182188

183189
/* Check whether the exception is an M-mode ecall */
184190
li t1, ECALL_M_MODE
@@ -291,28 +297,34 @@ _user_ecall:
291297
lw t0, 0(sp)
292298
addi sp, sp, 16
293299

294-
/* This point is reached when a service call is issued from the REE */
300+
/* This point is reached when a secure service call is issued from the REE */
295301
/* Save register context and mepc */
296302
save_general_regs RV_STK_FRMSZ
297303
save_mepc
298304

299-
/* Saving the U-mode (i.e. REE) stack pointer */
305+
/* Save the U-mode (i.e. REE) stack pointer */
300306
la t0, _ns_sp
301307
sw sp, 0(t0)
302308

303-
/* Switching to the M-mode (i.e. TEE) stack */
309+
/* Switch to the M-mode (i.e. TEE) stack */
304310
la sp, _tee_stack
305311

306-
/* Load the TEE entry point (see sec_world_entry) in the mepc */
307-
la t2, esp_tee_app_config
308-
lw t2, ESP_TEE_CFG_OFFS_S_ENTRY_ADDR(t2)
309-
csrw mepc, t2
312+
/* Disable the U-mode delegation of all interrupts */
313+
csrwi mideleg, 0
310314

311-
/* Set the privilege mode to transition to after mret to M-mode */
312-
li t3, MSTATUS_MPP
313-
csrs mstatus, t3
315+
/* Enable interrupts */
316+
csrsi mstatus, MSTATUS_MIE
314317

315-
mret
318+
/* Jump to the secure service dispatcher */
319+
jal esp_tee_service_dispatcher
320+
321+
/* Enable the U-mode delegation of all interrupts (except the TEE secure interrupt) */
322+
li t0, TEE_INTR_DELEG_MASK
323+
csrs mideleg, t0
324+
325+
/* Fire an M-ecall */
326+
mv a1, zero
327+
ecall
316328

317329
/* This point is reached after servicing a U-mode interrupt occurred
318330
* while executing a secure service */
@@ -333,7 +345,7 @@ _rtn_from_ns_int:
333345

334346
/* Restore register context and resume the secure service */
335347
restore_mepc
336-
restore_general_regs
348+
restore_general_regs RV_STK_FRMSZ
337349

338350
mret
339351

@@ -347,7 +359,7 @@ _rtn_from_ns_int:
347359
_tee_ns_intr_handler:
348360
/* Start by saving the general purpose registers and the PC value before
349361
* the interrupt happened. */
350-
save_general_regs
362+
save_general_regs RV_STK_FRMSZ
351363
save_mepc
352364

353365
/* Though it is not necessary we save GP and SP here.
@@ -357,7 +369,7 @@ _tee_ns_intr_handler:
357369
/* As gp register is not saved by the macro, save it here */
358370
sw gp, RV_STK_GP(sp)
359371
/* Same goes for the SP value before trapping */
360-
addi t0, sp, CONTEXT_SIZE /* restore sp with the value when interrupt happened */
372+
addi t0, sp, RV_STK_FRMSZ /* restore sp with the value when interrupt happened */
361373
/* Save SP */
362374
sw t0, RV_STK_SP(sp)
363375

@@ -395,8 +407,8 @@ _tee_ns_intr_handler:
395407
csrw mscratch, t0
396408

397409
/* Enable the U-mode interrupt delegation (except for the TEE secure interrupt) */
398-
li t0, 0xffffbfff
399-
csrw mideleg, t0
410+
li t0, TEE_INTR_DELEG_MASK
411+
csrs mideleg, t0
400412

401413
/* Place magic bytes in all the general registers */
402414
store_magic_general_regs
@@ -413,7 +425,7 @@ _tee_ns_intr_handler:
413425
_tee_s_intr_handler:
414426
/* Start by saving the general purpose registers and the PC value before
415427
* the interrupt happened. */
416-
save_general_regs
428+
save_general_regs RV_STK_FRMSZ
417429
save_mepc
418430

419431
/* Though it is not necessary we save GP and SP here.
@@ -423,7 +435,7 @@ _tee_s_intr_handler:
423435
/* As gp register is not saved by the macro, save it here */
424436
sw gp, RV_STK_GP(sp)
425437
/* Same goes for the SP value before trapping */
426-
addi t0, sp, CONTEXT_SIZE /* restore sp with the value when interrupt happened */
438+
addi t0, sp, RV_STK_FRMSZ /* restore sp with the value when interrupt happened */
427439
/* Save SP */
428440
sw t0, RV_STK_SP(sp)
429441

@@ -457,7 +469,7 @@ _save_reg_ctx:
457469
_continue:
458470
/* Before doing anything preserve the stack pointer */
459471
mv s11, sp
460-
/* Switching to the TEE interrupt stack */
472+
/* Switch to the TEE interrupt stack */
461473
la sp, _tee_intr_stack
462474
/* If this is a non-nested interrupt, SP now points to the interrupt stack */
463475

@@ -527,7 +539,7 @@ _intr_hdlr_exec:
527539
mv sp, s11
528540

529541
restore_mepc
530-
restore_general_regs
542+
restore_general_regs RV_STK_FRMSZ
531543
/* exit, this will also re-enable the interrupts */
532544
mret
533545

components/esp_tee/subproject/main/core/esp_secure_dispatcher.c

Lines changed: 30 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
6-
6+
#include <string.h>
77
#include <stdarg.h>
88
#include "esp_log.h"
99
#include "esp_tee.h"
@@ -34,13 +34,10 @@ static const secure_service_entry_t *find_service_by_id(uint32_t id)
3434
}
3535

3636
/**
37-
* @brief Entry point to the TEE binary during secure service call. It decipher the call and dispatch it
38-
* to corresponding Secure Service API in secure world.
39-
* TODO: Fix the assembly routine here for compatibility with all levels of compiler optimizations
37+
* @brief Handles incoming secure service requests to the TEE.
38+
* Validates and routes each request to the appropriate
39+
* secure service implementation.
4040
*/
41-
#pragma GCC push_options
42-
#pragma GCC optimize ("Og")
43-
4441
int esp_tee_service_dispatcher(int argc, va_list ap)
4542
{
4643
if (argc > ESP_TEE_MAX_INPUT_ARG) {
@@ -50,21 +47,19 @@ int esp_tee_service_dispatcher(int argc, va_list ap)
5047
}
5148

5249
int ret = -1;
53-
uint32_t argv[ESP_TEE_MAX_INPUT_ARG], *argp;
50+
uint32_t argv[ESP_TEE_MAX_INPUT_ARG] = {0};
5451

5552
uint32_t sid = va_arg(ap, uint32_t);
5653
argc--;
5754

5855
const secure_service_entry_t *service = find_service_by_id(sid);
5956
if (service == NULL) {
6057
ESP_LOGE(TAG, "Invalid service ID!");
61-
va_end(ap);
6258
return ret;
6359
}
6460

6561
if (argc != service->nargs) {
6662
ESP_LOGE(TAG, "Invalid number of arguments for service %d!", sid);
67-
va_end(ap);
6863
return ret;
6964
}
7065

@@ -73,65 +68,47 @@ int esp_tee_service_dispatcher(int argc, va_list ap)
7368
for (int i = 0; i < argc; i++) {
7469
argv[i] = va_arg(ap, uint32_t);
7570
}
76-
argp = &argv[0];
77-
va_end(ap);
71+
uint32_t *argp = &argv[0];
7872

7973
asm volatile(
80-
"mv t0, %1 \n"
81-
"beqz t0, service_call \n"
74+
"mv t0, %1 \n" // t0 = argc
75+
"mv t1, %3 \n" // t1 = argp
8276

83-
"lw a0, 0(%3) \n"
84-
"addi t0, t0, -1 \n"
85-
"beqz t0, service_call \n"
77+
"li t2, 8 \n" // t2 = 8 (max register args)
78+
"ble t0, t2, load_regs \n" // If argc <= 8 (a0-a7), skip stack routine
8679

87-
"lw a1, 4(%3) \n"
88-
"addi t0, t0, -1 \n"
89-
"beqz t0, service_call \n"
80+
// Store extra args (argc > 8) on stack
81+
"mv t3, sp \n"
82+
"addi t1, t1, 32 \n"
9083

91-
"lw a2, 8(%3) \n"
84+
"stack_loop: \n"
85+
"lw t4, 0(t1) \n"
86+
"sw t4, 0(t3) \n"
87+
"addi t1, t1, 4 \n"
88+
"addi t3, t3, 4 \n"
9289
"addi t0, t0, -1 \n"
93-
"beqz t0, service_call \n"
90+
"bge t0, t2, stack_loop \n"
9491

92+
// Load the first 8 arguments into a0-a7
93+
"load_regs: \n"
94+
"lw a0, 0(%3) \n"
95+
"lw a1, 4(%3) \n"
96+
"lw a2, 8(%3) \n"
9597
"lw a3, 12(%3) \n"
96-
"addi t0, t0, -1 \n"
97-
"beqz t0, service_call \n"
98-
9998
"lw a4, 16(%3) \n"
100-
"addi t0, t0, -1 \n"
101-
"beqz t0, service_call \n"
102-
10399
"lw a5, 20(%3) \n"
104-
"addi t0, t0, -1 \n"
105-
"beqz t0, service_call \n"
106-
107100
"lw a6, 24(%3) \n"
108-
"addi t0, t0, -1 \n"
109-
"beqz t0, service_call \n"
110-
111101
"lw a7, 28(%3) \n"
112-
"addi t0, t0, -1 \n"
113-
"beqz t0, service_call \n"
102+
"fence \n"
114103

115-
"addi %3, %3, 32 \n"
116-
"mv t2, sp \n"
117-
"loop: \n"
118-
"lw t1, 0(%3) \n"
119-
"sw t1, 0(t2) \n"
120-
"addi t0, t0, -1 \n"
121-
"addi t2, t2, 4 \n"
122-
"addi %3, %3, 4 \n"
123-
"bnez t0, loop \n"
124-
125-
"service_call: \n"
126-
"mv t1, %2 \n"
127-
"jalr 0(t1) \n"
128-
"mv %0, a0 \n"
104+
"mv t1, %2 \n" // Load function pointer
105+
"jalr 0(t1) \n" // Call function
106+
"mv %0, a0 \n" // Store return value
129107
: "=r"(ret)
130108
: "r"(argc), "r"(fp_secure_service), "r"(argp)
131-
: "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "t0", "t1", "t2"
109+
: "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
110+
"t0", "t1", "t2", "t3", "t4"
132111
);
133112

134113
return ret;
135114
}
136-
137-
#pragma GCC pop_options

components/esp_tee/subproject/main/core/esp_tee_init.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ static void tee_init_app_config(void)
5959
esp_tee_app_config.api_minor_version = ESP_TEE_API_MINOR_VER;
6060

6161
/* Set the TEE-related fields (from the TEE binary) that the REE will use to interface with TEE */
62-
esp_tee_app_config.s_entry_addr = &_sec_world_entry;
6362
esp_tee_app_config.s_int_handler = &_tee_s_intr_handler;
6463
}
6564

0 commit comments

Comments
 (0)