diff --git a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/include/esp_tee_test.h b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/include/esp_tee_test.h index 4874ccc5c7..bb4eec7c45 100644 --- a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/include/esp_tee_test.h +++ b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/include/esp_tee_test.h @@ -9,36 +9,11 @@ extern "C" { #endif -#include #include "esp_attr.h" -#define TEE_TEST_INT_COUNT 3 +#define ESP_TEE_TEST_INTR_ITER (4) -uint32_t NOINLINE_ATTR esp_tee_service_add(uint32_t a, uint32_t b); - -uint32_t NOINLINE_ATTR esp_tee_service_sub(uint32_t a, uint32_t b); - -uint32_t NOINLINE_ATTR esp_tee_service_mul(uint32_t a, uint32_t b); - -uint32_t NOINLINE_ATTR esp_tee_service_div(uint32_t a, uint32_t b); - -int esp_tee_secure_int_test(void); - -int esp_tee_non_secure_int_test(volatile uint32_t* volatile ns_int_count); - -int esp_tee_test_int_count(uint32_t *secure_int_count); - -int esp_tee_test_store_prohibited(uint32_t type); - -int esp_tee_test_illegal_instr(void); - -int esp_tee_test_instr_fetch_prohibited(uint32_t type); - -void NOINLINE_ATTR dummy_secure_service(int a, int b, int c, int d, int e, int f, int g, int h, int *i); - -uint32_t add_in_loop(uint32_t a, uint32_t b, uint32_t iter); - -int _ss_esp_tee_test_heap_malloc_write_free(void); +void NOINLINE_ATTR esp_tee_test_dummy_sec_srv(int a, int b, int c, int d, int e, int f, int g, int h, int *i); #ifdef __cplusplus } diff --git a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/sec_srv_tbl_test.yml b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/sec_srv_tbl_test.yml index d62238944a..98d7001ffa 100644 --- a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/sec_srv_tbl_test.yml +++ b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/sec_srv_tbl_test.yml @@ -3,73 +3,69 @@ secure_services: entries: - id: 200 type: custom - function: esp_tee_service_add + function: esp_tee_test_service_add args: 2 - id: 201 type: custom - function: esp_tee_service_sub + function: esp_tee_test_service_sub args: 2 - id: 202 type: custom - function: esp_tee_service_mul + function: esp_tee_test_service_mul args: 2 - id: 203 type: custom - function: esp_tee_service_div + function: esp_tee_test_service_div args: 2 - id: 204 type: custom - function: esp_tee_test_timer_init - args: 1 + function: esp_tee_test_tee_intr_in_tee + args: 0 - id: 205 type: custom - function: esp_tee_secure_int_test - args: 0 + function: esp_tee_test_ree_intr_in_tee + args: 1 - id: 206 type: custom - function: esp_tee_non_secure_int_test - args: 1 + function: esp_tee_test_tee_intr_in_ree + args: 2 - id: 207 - type: custom - function: esp_tee_test_int_count - args: 1 - - id: 208 type: custom function: esp_tee_test_resv_reg1_write_violation args: 0 - - id: 209 + - id: 208 type: custom function: esp_tee_test_resv_reg1_exec_violation args: 0 - - id: 210 + - id: 209 type: custom function: esp_tee_test_iram_reg1_write_violation args: 0 - - id: 211 + - id: 210 type: custom function: esp_tee_test_iram_reg2_write_violation args: 0 - - id: 212 + - id: 211 type: custom function: esp_tee_test_dram_reg1_exec_violation args: 0 - - id: 213 + - id: 212 type: custom function: esp_tee_test_dram_reg2_exec_violation args: 0 - - id: 214 + - id: 213 type: custom function: esp_tee_test_illegal_instruction args: 0 + - id: 214 + type: custom + function: esp_tee_test_dummy_sec_srv + args: 9 - id: 215 type: custom - function: dummy_secure_service - args: 9 + function: esp_tee_test_priv_mode_switch + args: 2 - id: 216 - type: custom - function: add_in_loop - args: 3 - - id: 217 type: custom function: esp_tee_test_heap_malloc_write_free args: 0 diff --git a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_dummy_srv.c b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_dummy_srv.c index 049d59290c..585efc071c 100644 --- a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_dummy_srv.c +++ b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_dummy_srv.c @@ -9,7 +9,7 @@ #include "multi_heap.h" -void NOINLINE_ATTR _ss_dummy_secure_service(int a, int b, int c, int d, int e, int f, int g, int h, int *i) +void NOINLINE_ATTR _ss_esp_tee_test_dummy_sec_srv(int a, int b, int c, int d, int e, int f, int g, int h, int *i) { esp_rom_printf("Dummy secure service\n"); *i = a + b + c + d + e + f + g + h; diff --git a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_dummy_srv_wrapper.c b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_dummy_srv_wrapper.c index d31b968ce7..d9ca82e80e 100644 --- a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_dummy_srv_wrapper.c +++ b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_dummy_srv_wrapper.c @@ -1,14 +1,14 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include #include "secure_service_num.h" #include "esp_tee.h" -#include "esp_err.h" +#include "esp_attr.h" -void dummy_secure_service(int a, int b, int c, int d, int e, int f, int g, int h, int *i) +void NOINLINE_ATTR esp_tee_test_dummy_sec_srv(int a, int b, int c, int d, int e, int f, int g, int h, int *i) { - esp_tee_service_call(10, SS_DUMMY_SECURE_SERVICE, a, b, c, d, e, f, g, h, i); + esp_tee_service_call(10, SS_ESP_TEE_TEST_DUMMY_SEC_SRV, a, b, c, d, e, f, g, h, i); } diff --git a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_interrupt.c b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_interrupt.c index 760244c95b..17ce1321d4 100644 --- a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_interrupt.c +++ b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_interrupt.c @@ -4,174 +4,168 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + #include "esp_cpu.h" -#include "esp_log.h" -#include "riscv/csr.h" +#include "esp_rom_sys.h" -#include "hal/timer_ll.h" -#include "hal/clk_gate_ll.h" - -#include "soc/timer_group_reg.h" +#include "soc/soc.h" +#include "soc/interrupts.h" #include "soc/interrupt_matrix_reg.h" +#include "soc/pcr_reg.h" +#include "hal/timer_ll.h" #include "esp_tee.h" #include "esp_tee_intr.h" #include "esp_tee_test.h" -#define TIMER_DIVIDER 80 // Hardware timer clock divider -#define TIMER_RESOLUTION_HZ 1000000 // 1MHz resolution -#define TIMER_ALARM_PERIOD_S 0.10 // sample test interval for the first timer +static const char *TAG __attribute__((unused)) = "esp_tee_intr_test"; -/* TEE uses Group0 Timer0 */ -#define TEE_SECURE_GROUP 0 -#define TEE_SECURE_TIMER 0 +/* ---------------------------------------------------- Utility functions ---------------------------------------------------- */ -static const char *TAG = "esp_tee_intr_test"; +#define TEST_TIMER_GROUP (0) +#define TEST_TIMER_ID (0) +#define TEST_TIMER_DIVIDER (80) -static timg_dev_t *timg_hw = (&TIMERG0); +#define TEST_TIMER_RESOLUTION_HZ (1000000ULL) // 1MHz, 1 tick = 1us +#define TIMER_ALARM_PERIOD_S (0.25f) // 250ms @ resolution 1MHz -uint32_t *psecure_int_count = NULL; +static timg_dev_t *timg_dev = TIMER_LL_GET_HW(TEST_TIMER_GROUP); -static void IRAM_ATTR timer_group0_isr(void *arg) +static void IRAM_ATTR test_timer_isr(void *arg) { - ESP_LOGI(TAG, "Timer ISR Handler from World %d!", esp_cpu_get_curr_privilege_level()); + uint32_t *intr_count = (uint32_t *)arg; + *intr_count = *intr_count + 1; + esp_rom_printf("[mode: %d] Interrupt triggered (%d)\n", esp_cpu_get_curr_privilege_level(), *intr_count); - /* For interrupt test. */ - *psecure_int_count = *psecure_int_count + 1; - - /* Clear interrupt */ - timer_ll_clear_intr_status(timg_hw, TIMER_LL_EVENT_ALARM(TEE_SECURE_TIMER)); - - /* Re-enable the alarm. */ - timer_ll_enable_alarm(timg_hw, TEE_SECURE_TIMER, true); + /* Clear interrupt and re-enable the alarm */ + timer_ll_clear_intr_status(timg_dev, TIMER_LL_EVENT_ALARM(TEST_TIMER_ID)); + timer_ll_enable_alarm(timg_dev, TEST_TIMER_ID, true); } -static void tee_timer_enable(void) +static void test_timer_deinit(void) { - struct vector_desc_t timer_vd = { 0, NULL, NULL, NULL }; + const uint32_t timer_id = TEST_TIMER_ID; - // init timer_vc - timer_vd.source = ETS_TG0_T0_LEVEL_INTR_SOURCE; - timer_vd.isr = timer_group0_isr; + // Disable and clear timer state + timer_ll_enable_counter(timg_dev, timer_id, false); + timer_ll_enable_auto_reload(timg_dev, timer_id, false); + timer_ll_enable_alarm(timg_dev, timer_id, false); - ESP_LOGI(TAG, "Enabling test timer from secure world"); + timer_ll_enable_intr(timg_dev, TIMER_LL_EVENT_ALARM(timer_id), false); + timer_ll_clear_intr_status(timg_dev, TIMER_LL_EVENT_ALARM(timer_id)); - /* Enable TG0 peripheral module */ - _timer_ll_enable_bus_clock(TEE_SECURE_GROUP, true); - _timer_ll_reset_register(TEE_SECURE_GROUP); - - /* Stop counter, alarm, auto-reload at first place */ - timer_ll_enable_clock(TEE_SECURE_GROUP, TEE_SECURE_TIMER, true); - timer_ll_enable_counter(timg_hw, TEE_SECURE_TIMER, false); - timer_ll_enable_auto_reload(timg_hw, TEE_SECURE_TIMER, false); - timer_ll_enable_alarm(timg_hw, TEE_SECURE_TIMER, false); - - // Set clock source - timer_ll_set_clock_source(TEE_SECURE_GROUP, TEE_SECURE_TIMER, GPTIMER_CLK_SRC_DEFAULT); - timer_ll_set_clock_prescale(timg_hw, TEE_SECURE_TIMER, TIMER_DIVIDER); - - // Initialize counter value to zero - timer_ll_set_reload_value(timg_hw, TEE_SECURE_TIMER, 0); - timer_ll_trigger_soft_reload(timg_hw, TEE_SECURE_TIMER); - - // set counting direction - timer_ll_set_count_direction(timg_hw, TEE_SECURE_TIMER, GPTIMER_COUNT_UP); - - // disable interrupt - timer_ll_enable_intr(timg_hw, TIMER_LL_EVENT_ALARM(TEE_SECURE_TIMER), false); - // clear pending interrupt event - timer_ll_clear_intr_status(timg_hw, TIMER_LL_EVENT_ALARM(TEE_SECURE_TIMER)); - - esp_tee_intr_register((void *)&timer_vd); - timer_ll_enable_intr(timg_hw, TIMER_LL_EVENT_ALARM(TEE_SECURE_TIMER), true); - - timer_ll_set_reload_value(timg_hw, TEE_SECURE_TIMER, 0); - - // enable timer interrupt - timer_ll_enable_intr(timg_hw, TIMER_LL_EVENT_ALARM(TEE_SECURE_TIMER), true); - - // set timer alarm - uint64_t alarm_value = (TIMER_ALARM_PERIOD_S * TIMER_RESOLUTION_HZ); - timer_ll_set_alarm_value(timg_hw, TEE_SECURE_TIMER, alarm_value); - - timer_ll_enable_auto_reload(timg_hw, TEE_SECURE_TIMER, true); - timer_ll_enable_alarm(timg_hw, TEE_SECURE_TIMER, true); - timer_ll_enable_counter(timg_hw, TEE_SECURE_TIMER, true); -} - -static void tee_timer_disable(void) -{ - ESP_LOGI(TAG, "Disabling test timer from secure world"); - - /* Init timer interrupt vector descriptor */ - struct vector_desc_t timer_vd = { 0, NULL, NULL, NULL }; - timer_vd.source = ETS_TG0_T0_LEVEL_INTR_SOURCE; - timer_vd.isr = timer_group0_isr; + // Reset the counter + uint64_t prev_val = timer_ll_get_reload_value(timg_dev, timer_id); + timer_ll_set_reload_value(timg_dev, timer_id, 0); + timer_ll_trigger_soft_reload(timg_dev, timer_id); + timer_ll_set_reload_value(timg_dev, timer_id, prev_val); + // Deregister ISR + struct vector_desc_t timer_vd = { + .source = ETS_TG0_T0_LEVEL_INTR_SOURCE, + }; esp_tee_intr_deregister((void *)&timer_vd); - - /* Disable timer */ - timer_ll_enable_counter(timg_hw, TEE_SECURE_TIMER, false); - timer_ll_enable_auto_reload(timg_hw, TEE_SECURE_TIMER, false); - timer_ll_enable_alarm(timg_hw, TEE_SECURE_TIMER, false); - - /* Disable and clear interrupt */ - timer_ll_enable_intr(timg_hw, TIMER_LL_EVENT_ALARM(TEE_SECURE_TIMER), false); - timer_ll_clear_intr_status(timg_hw, TIMER_LL_EVENT_ALARM(TEE_SECURE_TIMER)); - - /* Disable TG0 peripheral module */ - // periph_ll_disable_clk_set_rst(PERIPH_TIMG0_MODULE); + timer_ll_enable_clock(TEST_TIMER_GROUP, timer_id, false); } -void _ss_esp_tee_test_timer_init(bool enable) +static void test_timer_init(volatile uint32_t *arg) { - if (enable) { - tee_timer_enable(); - } else { - tee_timer_disable(); - } + const uint32_t group_id = TEST_TIMER_GROUP; + const uint32_t timer_id = TEST_TIMER_ID; + + test_timer_deinit(); + + // Enable peripheral clock and reset hardware + _timer_ll_enable_bus_clock(group_id, true); + _timer_ll_reset_register(group_id); + + // Select clock source and enable module clock + // Enable the default clock source PLL_F80M + REG_SET_BIT(PCR_PLL_DIV_CLK_EN_REG, PCR_PLL_80M_CLK_EN); + timer_ll_set_clock_source(group_id, timer_id, GPTIMER_CLK_SRC_DEFAULT); + timer_ll_enable_clock(group_id, timer_id, true); + timer_ll_set_clock_prescale(timg_dev, timer_id, TEST_TIMER_DIVIDER); + timer_ll_set_count_direction(timg_dev, timer_id, GPTIMER_COUNT_UP); + + // Register ISR + struct vector_desc_t timer_vd = { + .source = ETS_TG0_T0_LEVEL_INTR_SOURCE, + .isr = test_timer_isr, + .arg = (void *)arg, + }; + esp_tee_intr_register((void *)&timer_vd); + timer_ll_enable_intr(timg_dev, TIMER_LL_EVENT_ALARM(timer_id), true); + + // Configure and enable timer alarm + timer_ll_set_alarm_value(timg_dev, timer_id, TIMER_ALARM_PERIOD_S * TEST_TIMER_RESOLUTION_HZ); + timer_ll_enable_auto_reload(timg_dev, timer_id, true); + timer_ll_enable_alarm(timg_dev, timer_id, true); + timer_ll_enable_counter(timg_dev, timer_id, true); } -/** - * Secure interrupt in secure world test. - */ -int _ss_esp_tee_secure_int_test(void) +/* ---------------------------------------------------- Test cases ---------------------------------------------------- */ + +uint32_t _ss_esp_tee_test_tee_intr_in_tee(void) { - ESP_LOGD(TAG, "In WORLD %d", esp_cpu_get_curr_privilege_level()); - volatile uint32_t secure_int_count = 0; - psecure_int_count = (uint32_t *)&secure_int_count; + esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level(); + assert((mode == ESP_CPU_S_MODE) && "Incorrect privilege mode!"); - _ss_esp_tee_test_timer_init(true); - while (secure_int_count < TEE_TEST_INT_COUNT); - _ss_esp_tee_test_timer_init(false); + volatile uint32_t tee_intr_count = 0; + test_timer_init(&tee_intr_count); - ESP_LOGD(TAG, "Exiting WORLD %d", esp_cpu_get_curr_privilege_level()); - return secure_int_count; -} - -/** - * Non-Secure interrupt in secure world test. - */ -int _ss_esp_tee_non_secure_int_test(volatile uint32_t *volatile ns_int_count) -{ - ESP_LOGD(TAG, "In WORLD %d", esp_cpu_get_curr_privilege_level()); - - uint32_t count = 0; - count = *ns_int_count; - - while ((*ns_int_count < TEE_TEST_INT_COUNT)) { - if (*ns_int_count > count) { - count = *ns_int_count; - ESP_LOGI(TAG, "Interrupt count %d", count); - } + while (tee_intr_count < ESP_TEE_TEST_INTR_ITER) { + esp_rom_delay_us(10 * 1000U); } - ESP_LOGD(TAG, "Exiting WORLD %d", esp_cpu_get_curr_privilege_level()); + test_timer_deinit(); + + mode = esp_cpu_get_curr_privilege_level(); + assert((mode == ESP_CPU_S_MODE) && "Incorrect privilege mode!"); + return tee_intr_count; +} + +uint32_t _ss_esp_tee_test_tee_intr_in_ree(int stage, volatile uint32_t *volatile intr_count) +{ + esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level(); + assert((mode == ESP_CPU_S_MODE) && "Incorrect privilege mode!"); + + switch (stage) { + case 0: + test_timer_init(intr_count); + break; + case 1: + test_timer_deinit(); + break; + default: + assert(false && "Invalid stage!"); + break; + } + + mode = esp_cpu_get_curr_privilege_level(); + assert((mode == ESP_CPU_S_MODE) && "Incorrect privilege mode!"); return 0; } -int _ss_esp_tee_test_int_count(uint32_t *secure_int_count) +uint32_t _ss_esp_tee_test_ree_intr_in_tee(volatile uint32_t *volatile intr_count) { - psecure_int_count = secure_int_count; - return (*psecure_int_count); + esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level(); + assert((mode == ESP_CPU_S_MODE) && "Incorrect privilege mode!"); + + uint32_t prev_count = 0; + while (true) { + uint32_t curr_count = *intr_count; + if (curr_count > prev_count) { + prev_count = curr_count; + esp_rom_printf("[mode: %d] Interrupt received (%d)\n", esp_cpu_get_curr_privilege_level(), curr_count); + } + if (curr_count >= ESP_TEE_TEST_INTR_ITER) { + break; + } + esp_rom_delay_us(1000U); + } + + mode = esp_cpu_get_curr_privilege_level(); + assert((mode == ESP_CPU_S_MODE) && "Incorrect privilege mode!"); + return 0; } diff --git a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_sec_srv.c b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_sec_srv.c index e90aef0119..6978a65780 100644 --- a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_sec_srv.c +++ b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_sec_srv.c @@ -12,37 +12,45 @@ static const char *TAG = "test_sec_srv"; /* Sample Trusted App */ -uint32_t NOINLINE_ATTR _ss_esp_tee_service_add(uint32_t a, uint32_t b) +uint32_t NOINLINE_ATTR _ss_esp_tee_test_service_add(uint32_t a, uint32_t b) { ESP_LOGD(TAG, "SS: %s", __func__); return (a + b); } -uint32_t NOINLINE_ATTR _ss_esp_tee_service_sub(uint32_t a, uint32_t b) +uint32_t NOINLINE_ATTR _ss_esp_tee_test_service_sub(uint32_t a, uint32_t b) { ESP_LOGD(TAG, "SS: %s", __func__); return (a - b); } -uint32_t NOINLINE_ATTR _ss_esp_tee_service_mul(uint32_t a, uint32_t b) +uint32_t NOINLINE_ATTR _ss_esp_tee_test_service_mul(uint32_t a, uint32_t b) { ESP_LOGD(TAG, "SS: %s", __func__); return (a * b); } -uint32_t NOINLINE_ATTR _ss_esp_tee_service_div(uint32_t a, uint32_t b) +uint32_t NOINLINE_ATTR _ss_esp_tee_test_service_div(uint32_t a, uint32_t b) { ESP_LOGD(TAG, "SS: %s", __func__); return (a / b); } -uint32_t _ss_add_in_loop(uint32_t a, uint32_t b, uint32_t iter) +uint32_t _ss_esp_tee_test_priv_mode_switch(uint32_t *a, uint32_t *b) { ESP_LOGD(TAG, "SS: %s", __func__); - for (int i = 0; i < iter; i++) { - a += b; - esp_rom_delay_us(1000000); - esp_rom_printf("[mode: %d] val: %d\n", esp_cpu_get_curr_privilege_level(), a); + + *a = 1; + *b = 1; + + uint32_t c = 0; + while (c < ESP_TEE_TEST_INTR_ITER * 2) { + c = *a + *b; + esp_rom_delay_us(500 * 1000U); + esp_rom_printf("[mode: %d] val: %d\n", esp_cpu_get_curr_privilege_level(), c); + *a += 1; + *b += 1; } - return a; + + return c; } 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 6534cf712f..618717d709 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 @@ -4,32 +4,46 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "unity.h" -#include "esp_tee.h" -#include "secure_service_num.h" -#include "esp_tee_test.h" - #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "freertos/event_groups.h" + +#include "esp_cpu.h" +#include "esp_tee.h" +#include "esp_tee_test.h" +#include "secure_service_num.h" + +#include "unity.h" #include "sdkconfig.h" +#define TEST_TASK_1_DONE_BIT (BIT0) +#define TEST_TASK_2_DONE_BIT (BIT1) + +typedef struct { + uint32_t id; + uint32_t *val; + EventBits_t done_bit; +} test_task_args_t; + +static EventGroupHandle_t test_task_eg; + static void test_op(int sec_srv_num, uint32_t a, uint32_t b) { - esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS"); + esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); uint32_t lval = 0; switch (sec_srv_num) { - case SS_ESP_TEE_SERVICE_ADD: + case SS_ESP_TEE_TEST_SERVICE_ADD: lval = (a + b); break; - case SS_ESP_TEE_SERVICE_SUB: + case SS_ESP_TEE_TEST_SERVICE_SUB: lval = (a - b); break; - case SS_ESP_TEE_SERVICE_MUL: + case SS_ESP_TEE_TEST_SERVICE_MUL: lval = (a * b); break; - case SS_ESP_TEE_SERVICE_DIV: + case SS_ESP_TEE_TEST_SERVICE_DIV: lval = (a / b); break; default: @@ -40,60 +54,94 @@ static void test_op(int sec_srv_num, uint32_t a, uint32_t b) uint32_t val = esp_tee_service_call(3, sec_srv_num, a, b); TEST_ASSERT_EQUAL_UINT32(lval, val); - world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Sample app world switch failed"); + mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); } TEST_CASE("Test single calls to sample app (basic services)", "[basic]") { const uint32_t a = 200, b = 100; - test_op(SS_ESP_TEE_SERVICE_ADD, a, b); - test_op(SS_ESP_TEE_SERVICE_SUB, a, b); - test_op(SS_ESP_TEE_SERVICE_MUL, a, b); - test_op(SS_ESP_TEE_SERVICE_DIV, a, b); + test_op(SS_ESP_TEE_TEST_SERVICE_ADD, a, b); + test_op(SS_ESP_TEE_TEST_SERVICE_SUB, a, b); + test_op(SS_ESP_TEE_TEST_SERVICE_MUL, a, b); + test_op(SS_ESP_TEE_TEST_SERVICE_DIV, a, b); } TEST_CASE("Test multiple calls to sample app (basic services)", "[basic]") { - esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS"); + esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); for (int i = 0; i < 1024; i++) { - uint32_t val = esp_tee_service_call(3, SS_ESP_TEE_SERVICE_ADD, i, i + 1); + uint32_t val = esp_tee_service_call(3, SS_ESP_TEE_TEST_SERVICE_ADD, i, i + 1); TEST_ASSERT_EQUAL_UINT32((2 * i + 1), val); - world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Sample app world switch failed"); + mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); } } -TEST_CASE("Custom secure service call", "[basic]") +TEST_CASE("Test custom secure service call", "[basic]") { int res = -1; - dummy_secure_service(1, 2, 3, 4, 5, 6, 7, 8, &res); + esp_tee_test_dummy_sec_srv(1, 2, 3, 4, 5, 6, 7, 8, &res); TEST_ASSERT_EQUAL_UINT32(36, res); } -void test_task(void *pvParameters) +static void test_task(void *pvParameters) { - for (int i = 0; i < 8; i++) { - esp_rom_printf("[mode: %d] test_task - %d\n", esp_cpu_get_curr_privilege_level(), i); - vTaskDelay(pdMS_TO_TICKS(1000)); + test_task_args_t *args = (test_task_args_t *)pvParameters; + uint32_t *val = args->val; + uint32_t id = args->id; + + uint32_t prev_val = *val; + 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); + prev_val = curr_val; + } + vTaskDelay(pdMS_TO_TICKS(100)); } + + xEventGroupSetBits(test_task_eg, args->done_bit); vTaskDelete(NULL); } -TEST_CASE("Task switching during secure service calls", "[basic]") +TEST_CASE("Test task switching during secure service calls", "[basic]") { - esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS"); + esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); - xTaskCreate(test_task, "test_task", 4096, NULL, CONFIG_UNITY_FREERTOS_PRIORITY + 3, NULL); + test_task_eg = xEventGroupCreate(); + TEST_ASSERT_NOT_NULL(test_task_eg); - const uint32_t a = 100, b = 200, iter = 8; - TEST_ASSERT_EQUAL_UINT32(a + b * iter, esp_tee_service_call(4, SS_ADD_IN_LOOP, a, b, iter)); + uint32_t a = 0, b = 0; - world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS"); + test_task_args_t task_args_1 = { + .id = 1, + .val = &a, + .done_bit = TEST_TASK_1_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); + + 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"); + vEventGroupDelete(test_task_eg); + + mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); } TEST_CASE("Test TEE Heap: Malloc-write-free cycles", "[heap]") diff --git a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_interrupt.c b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_interrupt.c index 9b172c79e2..d8da5c75ba 100644 --- a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_interrupt.c +++ b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_interrupt.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 */ @@ -17,90 +17,47 @@ #include "unity.h" -static const char *TAG = "test_esp_tee_intr"; +#define TEST_TIMER_RESOLUTION_HZ (1000000ULL) // 1MHz, 1 tick = 1us +#define TIMER_ALARM_PERIOD_S (0.25f) // 250ms @ resolution 1MHz + +static const char __attribute__((unused)) *TAG = "test_esp_tee_intr"; /* ---------------------------------------------------- Utility functions ---------------------------------------------------- */ -typedef struct { - uint64_t event_count; -} test_queue_element_t; - -static QueueHandle_t s_timer_queue; - static gptimer_handle_t gptimer = NULL; -static volatile uint32_t ns_int_count; - static bool IRAM_ATTR test_timer_on_alarm_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data) { - ESP_EARLY_LOGI(TAG, "Timer ISR Handler from World %d!", esp_cpu_get_curr_privilege_level()); - - BaseType_t high_task_awoken = pdFALSE; - QueueHandle_t queue = (QueueHandle_t)user_data; - // Retrieve count value and send to queue - test_queue_element_t ele = { - .event_count = edata->count_value - }; - ns_int_count += 1; - - xQueueSendFromISR(queue, &ele, &high_task_awoken); - // return whether we need to yield at the end of ISR - return (high_task_awoken == pdTRUE); + uint32_t *intr_count = (uint32_t *)user_data; + *intr_count = *intr_count + 1; + esp_rom_printf("[mode: %d] Interrupt triggered (%d)\n", esp_cpu_get_curr_privilege_level(), *intr_count); + return true; } -static void IRAM_ATTR timer_evt_task(void *arg) +static void test_timer_init(volatile uint32_t *arg) { - int record = 3; - while (1) { - test_queue_element_t ele; - if (xQueueReceive(s_timer_queue, &ele, pdMS_TO_TICKS(2000))) { - ESP_LOGI(TAG, "Timer reloaded, count=%llu", ele.event_count); - record--; - } else { - ESP_LOGW(TAG, "Missed one count event"); - } - if (!record) { - break; - } - } -} - -static void test_timer_init(bool for_ns_world) -{ - s_timer_queue = xQueueCreate(10, sizeof(test_queue_element_t)); - if (!s_timer_queue) { - ESP_LOGE(TAG, "Creating queue failed"); - return; - } - - ns_int_count = 0; - /* Select and initialize basic parameters of the timer */ gptimer_config_t timer_config = { .clk_src = GPTIMER_CLK_SRC_DEFAULT, .direction = GPTIMER_COUNT_UP, - .resolution_hz = 1000000, // 1MHz, 1 tick=1us + .resolution_hz = TEST_TIMER_RESOLUTION_HZ, }; ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer)); gptimer_event_callbacks_t cbs = { .on_alarm = test_timer_on_alarm_cb, }; - ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, s_timer_queue)); + ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, (void *)arg)); ESP_ERROR_CHECK(gptimer_enable(gptimer)); gptimer_alarm_config_t alarm_config2 = { .reload_count = 0, - .alarm_count = 250000, // Alarm target = 250ms @ resolution 1MHz + .alarm_count = TIMER_ALARM_PERIOD_S * TEST_TIMER_RESOLUTION_HZ, .flags.auto_reload_on_alarm = true, }; ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config2)); ESP_ERROR_CHECK(gptimer_start(gptimer)); - - if (for_ns_world) { - timer_evt_task(NULL); - } } static void test_timer_deinit(void) @@ -108,109 +65,80 @@ static void test_timer_deinit(void) ESP_ERROR_CHECK(gptimer_stop(gptimer)); ESP_ERROR_CHECK(gptimer_disable(gptimer)); ESP_ERROR_CHECK(gptimer_del_timer(gptimer)); - - if (s_timer_queue != NULL) { - vQueueDelete(s_timer_queue); - s_timer_queue = NULL; - } } /* ---------------------------------------------------- Test cases ---------------------------------------------------- */ -TEST_CASE("Test Secure interrupt in Non-Secure World", "[basic]") +TEST_CASE("Test TEE interrupt in TEE", "[basic]") { - esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS"); + esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); - volatile uint32_t lsecure_int_count = 0; + uint32_t val = esp_tee_service_call(1, SS_ESP_TEE_TEST_TEE_INTR_IN_TEE); + TEST_ASSERT_EQUAL_UINT32(ESP_TEE_TEST_INTR_ITER, val); - /* Pass the variable to secure world to record the interrupt count. */ - esp_tee_service_call(2, SS_ESP_TEE_TEST_INT_COUNT, &lsecure_int_count); - world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "World switch failed"); - - esp_tee_service_call(2, SS_ESP_TEE_TEST_TIMER_INIT, true); - world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "World switch failed"); - - /* Secure timer initialized. - * As secure timer interrupt will fire; CPU will switch to secure world. - * Secure world ISR handler will be called, Secure ISR log can be observed on console. - * After handling the secure interrupt, CPU will return to non-secure world - * and resume this loop and wait for the next secure timer interrupt. - * CPU will wait for TEE_TEST_INT_COUNT number of secure interrupts. - */ - while (lsecure_int_count < TEE_TEST_INT_COUNT); - - /* After waiting for TEE_TEST_INT_COUNT secure interrupt, - * disable the secure timer and assert the test status. - */ - esp_tee_service_call(2, SS_ESP_TEE_TEST_TIMER_INIT, false); - world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "World switch failed"); - - /* Assert the number of secure interrupt occurred again. */ - TEST_ASSERT_EQUAL_UINT32(TEE_TEST_INT_COUNT, lsecure_int_count); + mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); } -TEST_CASE("Test Secure interrupt in Secure World", "[basic]") +TEST_CASE("Test REE interrupt in REE", "[basic]") { - esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS"); + esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); - uint32_t cnt = esp_tee_service_call(1, SS_ESP_TEE_SECURE_INT_TEST); - TEST_ASSERT_EQUAL_UINT32(TEE_TEST_INT_COUNT, cnt); - - world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "World switch failed"); + volatile uint32_t ree_intr_count = 0; + test_timer_init(&ree_intr_count); + while (ree_intr_count < ESP_TEE_TEST_INTR_ITER) { + vTaskDelay(pdMS_TO_TICKS(250)); + } + test_timer_deinit(); } -static volatile uint32_t *get_ns_int_count(void) +TEST_CASE("Test REE interrupt in TEE", "[basic]") { - return &ns_int_count; -} + esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); -TEST_CASE("Test Non-secure interrupt in Secure World", "[basic]") -{ - esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not W1"); + volatile uint32_t ree_intr_count = 0; + volatile uint32_t *volatile ree_intr_count_ptr = &ree_intr_count; - /* Non-secure world timer initialization. */ - ESP_LOGI(TAG, "Enabling test timer from non-secure world"); - test_timer_init(false); + test_timer_init(ree_intr_count_ptr); - volatile uint32_t *volatile lns_int_count; - lns_int_count = get_ns_int_count(); - - /* After non-secure timer initialization, - * CPU will switch to secure world by using a service call to test API. - * CPU will wait in finite loop in secure world. - * And as non-secure timer interrupt fires, CPU will switch to non-secure world. - * Non-secure world ISR handler will be called, non-secure ISR log can be obsereved on console. - * After handling the interrupt in non-secure world, CPU will switch back to secure world - * and wait for the next timer interrupt. - * In secure world CPU will wait for TEE_TEST_INT_COUNT non-secure interrupts. - */ - uint32_t val = esp_tee_service_call(2, SS_ESP_TEE_NON_SECURE_INT_TEST, lns_int_count); + uint32_t val = esp_tee_service_call(2, SS_ESP_TEE_TEST_REE_INTR_IN_TEE, ree_intr_count_ptr); TEST_ASSERT_EQUAL_UINT32(0, val); - world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "World switch failed"); - - ESP_LOGI(TAG, "Disabling test timer from non-secure world"); test_timer_deinit(); + + mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); } -TEST_CASE("Test Non-secure interrupt in Non-Secure World", "[basic]") +TEST_CASE("Test TEE interrupt in REE", "[basic]") { - esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level(); - TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS"); + esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); - ESP_LOGI(TAG, "Enabling test timer from non-secure world"); - test_timer_init(true); + volatile uint32_t tee_intr_count = 0; + volatile uint32_t *volatile tee_intr_count_ptr = &tee_intr_count; + esp_tee_service_call(3, SS_ESP_TEE_TEST_TEE_INTR_IN_REE, 0, tee_intr_count_ptr); - vTaskDelay(pdMS_TO_TICKS(1000)); + uint32_t prev_count = 0; + while (true) { + uint32_t curr_count = *tee_intr_count_ptr; + if (curr_count > prev_count) { + prev_count = curr_count; + esp_rom_printf("[mode: %d] Interrupt received (%d)\n", esp_cpu_get_curr_privilege_level(), curr_count); + } + if (curr_count >= ESP_TEE_TEST_INTR_ITER) { + break; + } + vTaskDelay(pdMS_TO_TICKS(1)); + } - ESP_LOGI(TAG, "Disabling test timer from non-secure world"); - test_timer_deinit(); + esp_tee_service_call(3, SS_ESP_TEE_TEST_TEE_INTR_IN_REE, 1, NULL); + + TEST_ASSERT_EQUAL_UINT32(ESP_TEE_TEST_INTR_ITER, tee_intr_count); + + mode = esp_cpu_get_curr_privilege_level(); + TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!"); }