stdcalltest: Add secure timer Add an SMC that trusty-test can use to start a secure timer used by the FP tests to verify that the FP registers are correctly saved while handling secure interrupts. Bug: 284057071 Change-Id: Idd94114107a5020e85425679af405fa7c8c94da5
diff --git a/app/stdcalltest/stdcalltest.c b/app/stdcalltest/stdcalltest.c index e6cb6d3..5616a90 100644 --- a/app/stdcalltest/stdcalltest.c +++ b/app/stdcalltest/stdcalltest.c
@@ -27,11 +27,14 @@ */ #if WITH_LIB_SM +#define LOCAL_TRACE 0 + #include <arch/arch_ops.h> #include <arch/ops.h> #include <err.h> #include <inttypes.h> #include <kernel/thread.h> +#include <kernel/timer.h> #include <kernel/vm.h> #include <lib/sm.h> #include <lib/sm/sm_err.h> @@ -299,6 +302,43 @@ } #endif +/* 1ms x5000=5s should be long enough for the test to finish */ +#define FPSIMD_TIMER_PERIOD_NS (1000000) +#define FPSIMD_TIMER_TICKS (5000) + +static struct timer fpsimd_timers[SMP_MAX_CPUS]; +static uint fpsimd_timer_ticks[SMP_MAX_CPUS]; + +static enum handler_return fpsimd_timer_cb(struct timer* timer, + lk_time_ns_t now, + void* arg) { + uint cpu = arch_curr_cpu_num(); + + fpsimd_timer_ticks[cpu]--; + if (!fpsimd_timer_ticks[cpu]) { + LTRACEF("Disabling FP test timer on cpu %u\n", cpu); + timer_cancel(&fpsimd_timers[cpu]); + } + + return INT_NO_RESCHEDULE; +} + +static long stdcalltest_clobber_fpsimd_timer(struct smc32_args* args) { + uint cpu = arch_curr_cpu_num(); + bool start_timer = !fpsimd_timer_ticks[cpu]; + + DEBUG_ASSERT(arch_ints_disabled()); + + LTRACEF("Enabling FP test timer on cpu %u\n", cpu); + fpsimd_timer_ticks[cpu] = FPSIMD_TIMER_TICKS; + if (start_timer) { + timer_set_periodic_ns(&fpsimd_timers[cpu], FPSIMD_TIMER_PERIOD_NS, + fpsimd_timer_cb, NULL); + } + + return 1; +} + static long stdcalltest_stdcall(struct smc32_args* args) { switch (args->smc_nr) { case SMC_SC_TEST_VERSION: @@ -334,14 +374,28 @@ } } +static long stdcalltest_nopcall(struct smc32_args* args) { + switch (args->params[0]) { + case SMC_NC_TEST_CLOBBER_FPSIMD_TIMER: + return stdcalltest_clobber_fpsimd_timer(args); + default: + return SM_ERR_UNDEFINED_SMC; + } +} + static struct smc32_entity stdcalltest_sm_entity = { .stdcall_handler = stdcalltest_stdcall, .fastcall_handler = stdcalltest_fastcall, + .nopcall_handler = stdcalltest_nopcall, }; static void stdcalltest_init(uint level) { int err; + for (size_t i = 0; i < SMP_MAX_CPUS; i++) { + timer_initialize(&fpsimd_timers[i]); + } + err = sm_register_entity(SMC_ENTITY_TEST, &stdcalltest_sm_entity); if (err) { printf("trusty error register entity: %d\n", err);
diff --git a/app/stdcalltest/stdcalltest.h b/app/stdcalltest/stdcalltest.h index b30d72f..de37e08 100644 --- a/app/stdcalltest/stdcalltest.h +++ b/app/stdcalltest/stdcalltest.h
@@ -95,4 +95,17 @@ */ #define SMC_FC_TEST_CLOBBER_FPSIMD_CHECK SMC_FASTCALL_NR(SMC_ENTITY_TEST, 1) +/** + * SMC_NC_TEST_CLOBBER_FPSIMD_TIMER - Trigger the FP/SIMD test timer. + * + * Return: 1 on success, or one of the libsm errors otherwise. + * + * Trigger a secure timer that runs periodically a fixed number of + * times, then automatically disables itself. + * + * The timer is not strictly required for the test, so failing to + * start or stop the timer is not an error per se. + */ +#define SMC_NC_TEST_CLOBBER_FPSIMD_TIMER SMC_STDCALL_NR(SMC_ENTITY_TEST, 0) + #define TRUSTY_STDCALLTEST_API_VERSION 1