mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-02 10:00:57 +02:00
ci(esp_tee): Refactor the ESP-TEE test-cases
- Improve the interrupt-related test cases - Fix potential issues in the task-switching test during secure service calls
This commit is contained in:
@@ -9,36 +9,11 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "esp_attr.h"
|
#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);
|
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);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@@ -3,73 +3,69 @@ secure_services:
|
|||||||
entries:
|
entries:
|
||||||
- id: 200
|
- id: 200
|
||||||
type: custom
|
type: custom
|
||||||
function: esp_tee_service_add
|
function: esp_tee_test_service_add
|
||||||
args: 2
|
args: 2
|
||||||
- id: 201
|
- id: 201
|
||||||
type: custom
|
type: custom
|
||||||
function: esp_tee_service_sub
|
function: esp_tee_test_service_sub
|
||||||
args: 2
|
args: 2
|
||||||
- id: 202
|
- id: 202
|
||||||
type: custom
|
type: custom
|
||||||
function: esp_tee_service_mul
|
function: esp_tee_test_service_mul
|
||||||
args: 2
|
args: 2
|
||||||
- id: 203
|
- id: 203
|
||||||
type: custom
|
type: custom
|
||||||
function: esp_tee_service_div
|
function: esp_tee_test_service_div
|
||||||
args: 2
|
args: 2
|
||||||
- id: 204
|
- id: 204
|
||||||
type: custom
|
type: custom
|
||||||
function: esp_tee_test_timer_init
|
function: esp_tee_test_tee_intr_in_tee
|
||||||
args: 1
|
args: 0
|
||||||
- id: 205
|
- id: 205
|
||||||
type: custom
|
type: custom
|
||||||
function: esp_tee_secure_int_test
|
function: esp_tee_test_ree_intr_in_tee
|
||||||
args: 0
|
args: 1
|
||||||
- id: 206
|
- id: 206
|
||||||
type: custom
|
type: custom
|
||||||
function: esp_tee_non_secure_int_test
|
function: esp_tee_test_tee_intr_in_ree
|
||||||
args: 1
|
args: 2
|
||||||
- id: 207
|
- id: 207
|
||||||
type: custom
|
|
||||||
function: esp_tee_test_int_count
|
|
||||||
args: 1
|
|
||||||
- id: 208
|
|
||||||
type: custom
|
type: custom
|
||||||
function: esp_tee_test_resv_reg1_write_violation
|
function: esp_tee_test_resv_reg1_write_violation
|
||||||
args: 0
|
args: 0
|
||||||
- id: 209
|
- id: 208
|
||||||
type: custom
|
type: custom
|
||||||
function: esp_tee_test_resv_reg1_exec_violation
|
function: esp_tee_test_resv_reg1_exec_violation
|
||||||
args: 0
|
args: 0
|
||||||
- id: 210
|
- id: 209
|
||||||
type: custom
|
type: custom
|
||||||
function: esp_tee_test_iram_reg1_write_violation
|
function: esp_tee_test_iram_reg1_write_violation
|
||||||
args: 0
|
args: 0
|
||||||
- id: 211
|
- id: 210
|
||||||
type: custom
|
type: custom
|
||||||
function: esp_tee_test_iram_reg2_write_violation
|
function: esp_tee_test_iram_reg2_write_violation
|
||||||
args: 0
|
args: 0
|
||||||
- id: 212
|
- id: 211
|
||||||
type: custom
|
type: custom
|
||||||
function: esp_tee_test_dram_reg1_exec_violation
|
function: esp_tee_test_dram_reg1_exec_violation
|
||||||
args: 0
|
args: 0
|
||||||
- id: 213
|
- id: 212
|
||||||
type: custom
|
type: custom
|
||||||
function: esp_tee_test_dram_reg2_exec_violation
|
function: esp_tee_test_dram_reg2_exec_violation
|
||||||
args: 0
|
args: 0
|
||||||
- id: 214
|
- id: 213
|
||||||
type: custom
|
type: custom
|
||||||
function: esp_tee_test_illegal_instruction
|
function: esp_tee_test_illegal_instruction
|
||||||
args: 0
|
args: 0
|
||||||
|
- id: 214
|
||||||
|
type: custom
|
||||||
|
function: esp_tee_test_dummy_sec_srv
|
||||||
|
args: 9
|
||||||
- id: 215
|
- id: 215
|
||||||
type: custom
|
type: custom
|
||||||
function: dummy_secure_service
|
function: esp_tee_test_priv_mode_switch
|
||||||
args: 9
|
args: 2
|
||||||
- id: 216
|
- id: 216
|
||||||
type: custom
|
|
||||||
function: add_in_loop
|
|
||||||
args: 3
|
|
||||||
- id: 217
|
|
||||||
type: custom
|
type: custom
|
||||||
function: esp_tee_test_heap_malloc_write_free
|
function: esp_tee_test_heap_malloc_write_free
|
||||||
args: 0
|
args: 0
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#include "multi_heap.h"
|
#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");
|
esp_rom_printf("Dummy secure service\n");
|
||||||
*i = a + b + c + d + e + f + g + h;
|
*i = a + b + c + d + e + f + g + h;
|
||||||
|
@@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include "secure_service_num.h"
|
#include "secure_service_num.h"
|
||||||
#include "esp_tee.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);
|
||||||
}
|
}
|
||||||
|
@@ -4,174 +4,168 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "esp_cpu.h"
|
#include "esp_cpu.h"
|
||||||
#include "esp_log.h"
|
#include "esp_rom_sys.h"
|
||||||
#include "riscv/csr.h"
|
|
||||||
|
|
||||||
#include "hal/timer_ll.h"
|
#include "soc/soc.h"
|
||||||
#include "hal/clk_gate_ll.h"
|
#include "soc/interrupts.h"
|
||||||
|
|
||||||
#include "soc/timer_group_reg.h"
|
|
||||||
#include "soc/interrupt_matrix_reg.h"
|
#include "soc/interrupt_matrix_reg.h"
|
||||||
|
#include "soc/pcr_reg.h"
|
||||||
|
#include "hal/timer_ll.h"
|
||||||
|
|
||||||
#include "esp_tee.h"
|
#include "esp_tee.h"
|
||||||
#include "esp_tee_intr.h"
|
#include "esp_tee_intr.h"
|
||||||
#include "esp_tee_test.h"
|
#include "esp_tee_test.h"
|
||||||
|
|
||||||
#define TIMER_DIVIDER 80 // Hardware timer clock divider
|
static const char *TAG __attribute__((unused)) = "esp_tee_intr_test";
|
||||||
#define TIMER_RESOLUTION_HZ 1000000 // 1MHz resolution
|
|
||||||
#define TIMER_ALARM_PERIOD_S 0.10 // sample test interval for the first timer
|
|
||||||
|
|
||||||
/* TEE uses Group0 Timer0 */
|
/* ---------------------------------------------------- Utility functions ---------------------------------------------------- */
|
||||||
#define TEE_SECURE_GROUP 0
|
|
||||||
#define TEE_SECURE_TIMER 0
|
|
||||||
|
|
||||||
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. */
|
/* Clear interrupt and re-enable the alarm */
|
||||||
*psecure_int_count = *psecure_int_count + 1;
|
timer_ll_clear_intr_status(timg_dev, TIMER_LL_EVENT_ALARM(TEST_TIMER_ID));
|
||||||
|
timer_ll_enable_alarm(timg_dev, TEST_TIMER_ID, true);
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// Disable and clear timer state
|
||||||
timer_vd.source = ETS_TG0_T0_LEVEL_INTR_SOURCE;
|
timer_ll_enable_counter(timg_dev, timer_id, false);
|
||||||
timer_vd.isr = timer_group0_isr;
|
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 */
|
// Reset the counter
|
||||||
_timer_ll_enable_bus_clock(TEE_SECURE_GROUP, true);
|
uint64_t prev_val = timer_ll_get_reload_value(timg_dev, timer_id);
|
||||||
_timer_ll_reset_register(TEE_SECURE_GROUP);
|
timer_ll_set_reload_value(timg_dev, timer_id, 0);
|
||||||
|
timer_ll_trigger_soft_reload(timg_dev, timer_id);
|
||||||
/* Stop counter, alarm, auto-reload at first place */
|
timer_ll_set_reload_value(timg_dev, timer_id, prev_val);
|
||||||
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;
|
|
||||||
|
|
||||||
|
// Deregister ISR
|
||||||
|
struct vector_desc_t timer_vd = {
|
||||||
|
.source = ETS_TG0_T0_LEVEL_INTR_SOURCE,
|
||||||
|
};
|
||||||
esp_tee_intr_deregister((void *)&timer_vd);
|
esp_tee_intr_deregister((void *)&timer_vd);
|
||||||
|
timer_ll_enable_clock(TEST_TIMER_GROUP, timer_id, false);
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _ss_esp_tee_test_timer_init(bool enable)
|
static void test_timer_init(volatile uint32_t *arg)
|
||||||
{
|
{
|
||||||
if (enable) {
|
const uint32_t group_id = TEST_TIMER_GROUP;
|
||||||
tee_timer_enable();
|
const uint32_t timer_id = TEST_TIMER_ID;
|
||||||
} else {
|
|
||||||
tee_timer_disable();
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/* ---------------------------------------------------- Test cases ---------------------------------------------------- */
|
||||||
* Secure interrupt in secure world test.
|
|
||||||
*/
|
uint32_t _ss_esp_tee_test_tee_intr_in_tee(void)
|
||||||
int _ss_esp_tee_secure_int_test(void)
|
|
||||||
{
|
{
|
||||||
ESP_LOGD(TAG, "In WORLD %d", esp_cpu_get_curr_privilege_level());
|
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
|
||||||
volatile uint32_t secure_int_count = 0;
|
assert((mode == ESP_CPU_S_MODE) && "Incorrect privilege mode!");
|
||||||
psecure_int_count = (uint32_t *)&secure_int_count;
|
|
||||||
|
|
||||||
_ss_esp_tee_test_timer_init(true);
|
volatile uint32_t tee_intr_count = 0;
|
||||||
while (secure_int_count < TEE_TEST_INT_COUNT);
|
test_timer_init(&tee_intr_count);
|
||||||
_ss_esp_tee_test_timer_init(false);
|
|
||||||
|
|
||||||
ESP_LOGD(TAG, "Exiting WORLD %d", esp_cpu_get_curr_privilege_level());
|
while (tee_intr_count < ESP_TEE_TEST_INTR_ITER) {
|
||||||
return secure_int_count;
|
esp_rom_delay_us(10 * 1000U);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
* 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());
|
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
|
||||||
|
assert((mode == ESP_CPU_S_MODE) && "Incorrect privilege mode!");
|
||||||
|
|
||||||
uint32_t count = 0;
|
switch (stage) {
|
||||||
count = *ns_int_count;
|
case 0:
|
||||||
|
test_timer_init(intr_count);
|
||||||
while ((*ns_int_count < TEE_TEST_INT_COUNT)) {
|
break;
|
||||||
if (*ns_int_count > count) {
|
case 1:
|
||||||
count = *ns_int_count;
|
test_timer_deinit();
|
||||||
ESP_LOGI(TAG, "Interrupt count %d", count);
|
break;
|
||||||
}
|
default:
|
||||||
|
assert(false && "Invalid stage!");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGD(TAG, "Exiting WORLD %d", esp_cpu_get_curr_privilege_level());
|
mode = esp_cpu_get_curr_privilege_level();
|
||||||
|
assert((mode == ESP_CPU_S_MODE) && "Incorrect privilege mode!");
|
||||||
return 0;
|
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;
|
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
|
||||||
return (*psecure_int_count);
|
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;
|
||||||
}
|
}
|
||||||
|
@@ -12,37 +12,45 @@ static const char *TAG = "test_sec_srv";
|
|||||||
|
|
||||||
/* Sample Trusted App */
|
/* 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__);
|
ESP_LOGD(TAG, "SS: %s", __func__);
|
||||||
return (a + b);
|
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__);
|
ESP_LOGD(TAG, "SS: %s", __func__);
|
||||||
return (a - b);
|
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__);
|
ESP_LOGD(TAG, "SS: %s", __func__);
|
||||||
return (a * b);
|
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__);
|
ESP_LOGD(TAG, "SS: %s", __func__);
|
||||||
return (a / b);
|
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__);
|
ESP_LOGD(TAG, "SS: %s", __func__);
|
||||||
for (int i = 0; i < iter; i++) {
|
|
||||||
a += b;
|
*a = 1;
|
||||||
esp_rom_delay_us(1000000);
|
*b = 1;
|
||||||
esp_rom_printf("[mode: %d] val: %d\n", esp_cpu_get_curr_privilege_level(), a);
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
@@ -4,32 +4,46 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* 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/FreeRTOS.h"
|
||||||
#include "freertos/task.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"
|
#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)
|
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();
|
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
|
||||||
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS");
|
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
|
||||||
|
|
||||||
uint32_t lval = 0;
|
uint32_t lval = 0;
|
||||||
switch (sec_srv_num) {
|
switch (sec_srv_num) {
|
||||||
case SS_ESP_TEE_SERVICE_ADD:
|
case SS_ESP_TEE_TEST_SERVICE_ADD:
|
||||||
lval = (a + b);
|
lval = (a + b);
|
||||||
break;
|
break;
|
||||||
case SS_ESP_TEE_SERVICE_SUB:
|
case SS_ESP_TEE_TEST_SERVICE_SUB:
|
||||||
lval = (a - b);
|
lval = (a - b);
|
||||||
break;
|
break;
|
||||||
case SS_ESP_TEE_SERVICE_MUL:
|
case SS_ESP_TEE_TEST_SERVICE_MUL:
|
||||||
lval = (a * b);
|
lval = (a * b);
|
||||||
break;
|
break;
|
||||||
case SS_ESP_TEE_SERVICE_DIV:
|
case SS_ESP_TEE_TEST_SERVICE_DIV:
|
||||||
lval = (a / b);
|
lval = (a / b);
|
||||||
break;
|
break;
|
||||||
default:
|
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);
|
uint32_t val = esp_tee_service_call(3, sec_srv_num, a, b);
|
||||||
TEST_ASSERT_EQUAL_UINT32(lval, val);
|
TEST_ASSERT_EQUAL_UINT32(lval, val);
|
||||||
|
|
||||||
world = esp_cpu_get_curr_privilege_level();
|
mode = esp_cpu_get_curr_privilege_level();
|
||||||
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Sample app world switch failed");
|
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Test single calls to sample app (basic services)", "[basic]")
|
TEST_CASE("Test single calls to sample app (basic services)", "[basic]")
|
||||||
{
|
{
|
||||||
const uint32_t a = 200, b = 100;
|
const uint32_t a = 200, b = 100;
|
||||||
test_op(SS_ESP_TEE_SERVICE_ADD, a, b);
|
test_op(SS_ESP_TEE_TEST_SERVICE_ADD, a, b);
|
||||||
test_op(SS_ESP_TEE_SERVICE_SUB, a, b);
|
test_op(SS_ESP_TEE_TEST_SERVICE_SUB, a, b);
|
||||||
test_op(SS_ESP_TEE_SERVICE_MUL, a, b);
|
test_op(SS_ESP_TEE_TEST_SERVICE_MUL, a, b);
|
||||||
test_op(SS_ESP_TEE_SERVICE_DIV, a, b);
|
test_op(SS_ESP_TEE_TEST_SERVICE_DIV, a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Test multiple calls to sample app (basic services)", "[basic]")
|
TEST_CASE("Test multiple calls to sample app (basic services)", "[basic]")
|
||||||
{
|
{
|
||||||
esp_cpu_priv_mode_t world = esp_cpu_get_curr_privilege_level();
|
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
|
||||||
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS");
|
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
|
||||||
|
|
||||||
for (int i = 0; i < 1024; i++) {
|
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);
|
TEST_ASSERT_EQUAL_UINT32((2 * i + 1), val);
|
||||||
world = esp_cpu_get_curr_privilege_level();
|
mode = esp_cpu_get_curr_privilege_level();
|
||||||
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Sample app world switch failed");
|
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;
|
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);
|
TEST_ASSERT_EQUAL_UINT32(36, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_task(void *pvParameters)
|
static void test_task(void *pvParameters)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 8; i++) {
|
test_task_args_t *args = (test_task_args_t *)pvParameters;
|
||||||
esp_rom_printf("[mode: %d] test_task - %d\n", esp_cpu_get_curr_privilege_level(), i);
|
uint32_t *val = args->val;
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
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);
|
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();
|
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
|
||||||
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS");
|
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;
|
uint32_t a = 0, b = 0;
|
||||||
TEST_ASSERT_EQUAL_UINT32(a + b * iter, esp_tee_service_call(4, SS_ADD_IN_LOOP, a, b, iter));
|
|
||||||
|
|
||||||
world = esp_cpu_get_curr_privilege_level();
|
test_task_args_t task_args_1 = {
|
||||||
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS");
|
.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]")
|
TEST_CASE("Test TEE Heap: Malloc-write-free cycles", "[heap]")
|
||||||
|
@@ -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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -17,90 +17,47 @@
|
|||||||
|
|
||||||
#include "unity.h"
|
#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 ---------------------------------------------------- */
|
/* ---------------------------------------------------- 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 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)
|
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());
|
uint32_t *intr_count = (uint32_t *)user_data;
|
||||||
|
*intr_count = *intr_count + 1;
|
||||||
BaseType_t high_task_awoken = pdFALSE;
|
esp_rom_printf("[mode: %d] Interrupt triggered (%d)\n", esp_cpu_get_curr_privilege_level(), *intr_count);
|
||||||
QueueHandle_t queue = (QueueHandle_t)user_data;
|
return true;
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 */
|
/* Select and initialize basic parameters of the timer */
|
||||||
gptimer_config_t timer_config = {
|
gptimer_config_t timer_config = {
|
||||||
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
|
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
|
||||||
.direction = GPTIMER_COUNT_UP,
|
.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));
|
ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer));
|
||||||
|
|
||||||
gptimer_event_callbacks_t cbs = {
|
gptimer_event_callbacks_t cbs = {
|
||||||
.on_alarm = test_timer_on_alarm_cb,
|
.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));
|
ESP_ERROR_CHECK(gptimer_enable(gptimer));
|
||||||
|
|
||||||
gptimer_alarm_config_t alarm_config2 = {
|
gptimer_alarm_config_t alarm_config2 = {
|
||||||
.reload_count = 0,
|
.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,
|
.flags.auto_reload_on_alarm = true,
|
||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config2));
|
ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config2));
|
||||||
ESP_ERROR_CHECK(gptimer_start(gptimer));
|
ESP_ERROR_CHECK(gptimer_start(gptimer));
|
||||||
|
|
||||||
if (for_ns_world) {
|
|
||||||
timer_evt_task(NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_timer_deinit(void)
|
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_stop(gptimer));
|
||||||
ESP_ERROR_CHECK(gptimer_disable(gptimer));
|
ESP_ERROR_CHECK(gptimer_disable(gptimer));
|
||||||
ESP_ERROR_CHECK(gptimer_del_timer(gptimer));
|
ESP_ERROR_CHECK(gptimer_del_timer(gptimer));
|
||||||
|
|
||||||
if (s_timer_queue != NULL) {
|
|
||||||
vQueueDelete(s_timer_queue);
|
|
||||||
s_timer_queue = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------- Test cases ---------------------------------------------------- */
|
/* ---------------------------------------------------- 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();
|
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
|
||||||
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS");
|
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. */
|
mode = esp_cpu_get_curr_privilege_level();
|
||||||
esp_tee_service_call(2, SS_ESP_TEE_TEST_INT_COUNT, &lsecure_int_count);
|
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
|
||||||
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS");
|
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);
|
volatile uint32_t ree_intr_count = 0;
|
||||||
TEST_ASSERT_EQUAL_UINT32(TEE_TEST_INT_COUNT, cnt);
|
test_timer_init(&ree_intr_count);
|
||||||
|
while (ree_intr_count < ESP_TEE_TEST_INTR_ITER) {
|
||||||
world = esp_cpu_get_curr_privilege_level();
|
vTaskDelay(pdMS_TO_TICKS(250));
|
||||||
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "World switch failed");
|
}
|
||||||
|
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]")
|
volatile uint32_t ree_intr_count = 0;
|
||||||
{
|
volatile uint32_t *volatile ree_intr_count_ptr = &ree_intr_count;
|
||||||
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");
|
|
||||||
|
|
||||||
/* Non-secure world timer initialization. */
|
test_timer_init(ree_intr_count_ptr);
|
||||||
ESP_LOGI(TAG, "Enabling test timer from non-secure world");
|
|
||||||
test_timer_init(false);
|
|
||||||
|
|
||||||
volatile uint32_t *volatile lns_int_count;
|
uint32_t val = esp_tee_service_call(2, SS_ESP_TEE_TEST_REE_INTR_IN_TEE, ree_intr_count_ptr);
|
||||||
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);
|
|
||||||
TEST_ASSERT_EQUAL_UINT32(0, val);
|
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();
|
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();
|
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
|
||||||
TEST_ASSERT_MESSAGE((world == ESP_CPU_NS_MODE), "Current world is not NS");
|
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Enabling test timer from non-secure world");
|
volatile uint32_t tee_intr_count = 0;
|
||||||
test_timer_init(true);
|
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");
|
esp_tee_service_call(3, SS_ESP_TEE_TEST_TEE_INTR_IN_REE, 1, NULL);
|
||||||
test_timer_deinit();
|
|
||||||
|
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!");
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user