diff options
43 files changed, 483 insertions, 254 deletions
@@ -133,7 +133,6 @@ $(eval $(call assert_boolean,ENABLE_ASSERTIONS)) $(eval $(call assert_boolean,FIRMWARE_UPDATE)) $(eval $(call assert_boolean,FWU_BL_TEST)) $(eval $(call assert_boolean,NEW_TEST_SESSION)) -$(eval $(call assert_boolean,SHELL_COLOR)) $(eval $(call assert_boolean,USE_NVM)) ################################################################################ @@ -148,7 +147,6 @@ $(eval $(call add_define,TFTF_DEFINES,ENABLE_ASSERTIONS)) $(eval $(call add_define,TFTF_DEFINES,LOG_LEVEL)) $(eval $(call add_define,TFTF_DEFINES,NEW_TEST_SESSION)) $(eval $(call add_define,TFTF_DEFINES,PLAT_${PLAT})) -$(eval $(call add_define,TFTF_DEFINES,SHELL_COLOR)) $(eval $(call add_define,TFTF_DEFINES,USE_NVM)) ifeq (${ARCH},aarch32) diff --git a/defaults.mk b/defaults.mk index 63c1b2e1c..0f7465268 100644 --- a/defaults.mk +++ b/defaults.mk @@ -37,9 +37,6 @@ FWU_BL_TEST := 1 # framework should try to resume a previous one if it was interrupted NEW_TEST_SESSION := 1 -# Use of shell colors -SHELL_COLOR := 0 - # Use non volatile memory for storing results USE_NVM := 0 diff --git a/docs/user-guide.rst b/docs/user-guide.rst index 397b4c2c9..e11a6bfa0 100644 --- a/docs/user-guide.rst +++ b/docs/user-guide.rst @@ -367,11 +367,6 @@ TFTF build options session was interrupted and resume it. It can take either 1 (always start new session) or 0 (resume session as appropriate). 1 is the default. -- ``SHELL_COLOR``: Choose whether text messages should use shell's color escape - sequences to ease identifying which CPU displays it. If enabled, this makes - each CPU write part of the message in a different color. It can take either - 0 (disabled) or 1 (enabled) as values. 0 is the default. - - ``TESTS``: Set of tests to run. Use the following command to list all possible sets of tests: diff --git a/drivers/io/vexpress_nor/io_vexpress_nor_hw.c b/drivers/io/vexpress_nor/io_vexpress_nor_hw.c index de7b4ceff..6e563c9f0 100644 --- a/drivers/io/vexpress_nor/io_vexpress_nor_hw.c +++ b/drivers/io/vexpress_nor/io_vexpress_nor_hw.c @@ -159,7 +159,6 @@ static int flash_erase_block(const io_nor_flash_spec_t *device, int err = IO_SUCCESS; uint32_t status_register; - VERBOSE("%s : 0x%x\n", __func__, block_offset); /* Request a block erase and then confirm it */ nor_send_cmd(block_offset, NOR_CMD_BLOCK_ERASE); nor_send_cmd(block_offset, NOR_CMD_BLOCK_ERASE_ACK); @@ -359,7 +358,6 @@ int flash_block_write(file_state_t *fp, uint32_t offset, /* address passed should be block aligned */ assert(!(offset % fp->block_spec->block_size)); - VERBOSE("%s : 0x%x\n", __func__, flash_pos); /* Unlock block */ flash_unlock_block_if_necessary(fp->block_spec, block_offset); @@ -398,7 +396,6 @@ int flash_block_write(file_state_t *fp, uint32_t offset, *written = fp->block_spec->block_size; lock_block: - VERBOSE("%s : 0x%x\n", __func__, block_offset); /* Lock the block once done */ flash_perform_lock_operation(fp->block_spec, block_offset, diff --git a/fwu/ns_bl1u/ns_bl1u.mk b/fwu/ns_bl1u/ns_bl1u.mk index 0d7efcce0..d5c78069e 100644 --- a/fwu/ns_bl1u/ns_bl1u.mk +++ b/fwu/ns_bl1u/ns_bl1u.mk @@ -28,7 +28,6 @@ NS_BL1U_INCLUDES := \ NS_BL1U_SOURCES := $(addprefix tftf/framework/, \ ${ARCH}/arch.c \ ${ARCH}/asm_debug.S \ - ${ARCH}/exceptions.S \ debug.c \ ) diff --git a/fwu/ns_bl2u/ns_bl2u.mk b/fwu/ns_bl2u/ns_bl2u.mk index 0605c3c2d..abd5ac555 100644 --- a/fwu/ns_bl2u/ns_bl2u.mk +++ b/fwu/ns_bl2u/ns_bl2u.mk @@ -28,7 +28,6 @@ NS_BL2U_INCLUDES := \ NS_BL2U_SOURCES := $(addprefix tftf/framework/, \ ${ARCH}/arch.c \ ${ARCH}/asm_debug.S \ - ${ARCH}/exceptions.S \ debug.c \ ) diff --git a/fwu/ns_bl2u/ns_bl2u_main.c b/fwu/ns_bl2u/ns_bl2u_main.c index babcf93e0..5b1373f64 100644 --- a/fwu/ns_bl2u/ns_bl2u_main.c +++ b/fwu/ns_bl2u/ns_bl2u_main.c @@ -52,7 +52,7 @@ void ns_bl2u_main(void) /* Call FWU_SMC_UPDATE_DONE to indicate image update done. */ INFO("NS_BL2U: Calling FWU_SMC_UPDATE_DONE\n"); - fwu_params.arg0 = FWU_SMC_UPDATE_DONE; + fwu_params.fid = FWU_SMC_UPDATE_DONE; fwu_result = tftf_smc(&fwu_params); ERROR("NS_BL2U: Unexpected return from FWU process (%d)\n", (int)fwu_result.ret0); diff --git a/include/common/debug.h b/include/common/debug.h index bfbff093d..216c53d9b 100644 --- a/include/common/debug.h +++ b/include/common/debug.h @@ -9,34 +9,15 @@ #include <stdio.h> -/* TODO: Deal with per-image printf functions in a cleaner way. */ - -#if defined(IMAGE_CACTUS) || defined(IMAGE_IVY) -/* - * The register MPIDR_EL1 can't be read from EL0, which means that mp_printf() - * can't be used. - */ -#define mp_printf printf -#else /* * Print a formatted string on the UART. * * Does the same thing as the standard libc's printf() function but in a MP-safe * manner, i.e. it can be called from several CPUs simultaneously without * getting interleaved messages. - * - * The messages printed using mp_printf() won't be saved in the test results - * (use tftf_testcase_output() instead for that). mp_printf() is meant to be - * used for debug traces only. Unlike messages stored in the tests output which - * appear only at the end of the test session in the test report, messages - * printed using mp_printf() will be displayed straight away. - * - * Messaged will be prefixed by the CPU MPID issuing the call, like that: - * [cpu 0x0002] Sending SGI #1 to cpu 0 */ __attribute__((format(printf, 1, 2))) void mp_printf(const char *fmt, ...); -#endif /* * The log output macros print output to the console. These macros produce @@ -44,8 +25,8 @@ void mp_printf(const char *fmt, ...); * make command line) is greater or equal than the level required for that * type of log output. * The format expected is similar to printf(). For example: - * INFO("Info %s.\n", "message") -> [cpu 0xxx] INFO: Info message. - * WARN("Warning %s.\n", "message") -> [cpu 0xxx] WARNING: Warning message. + * INFO("Info %s.\n", "message") -> INFO: Info message. + * WARN("Warning %s.\n", "message") -> WARNING: Warning message. */ #define LOG_LEVEL_NONE 0 #define LOG_LEVEL_ERROR 10 diff --git a/include/lib/aarch32/arch_helpers.h b/include/lib/aarch32/arch_helpers.h index ee7ed3145..3e6e6f9cc 100644 --- a/include/lib/aarch32/arch_helpers.h +++ b/include/lib/aarch32/arch_helpers.h @@ -442,4 +442,16 @@ static inline void disable_fiq(void) void disable_mmu_icache(void); +/* Read the count value of the system counter. */ +static inline uint64_t syscounter_read(void) +{ + /* + * The instruction barrier is needed to guarantee that we read an + * accurate value. Otherwise, the CPU might speculatively read it and + * return a stale value. + */ + isb(); + return read64_cntpct(); +} + #endif /* ARCH_HELPERS_H */ diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h index 1d9202d04..053f8ba67 100644 --- a/include/lib/aarch64/arch_helpers.h +++ b/include/lib/aarch64/arch_helpers.h @@ -468,4 +468,16 @@ static inline uint64_t el_implemented(unsigned int el) } } +/* Read the count value of the system counter. */ +static inline uint64_t syscounter_read(void) +{ + /* + * The instruction barrier is needed to guarantee that we read an + * accurate value. Otherwise, the CPU might speculatively read it and + * return a stale value. + */ + isb(); + return read_cntpct_el0(); +} + #endif /* ARCH_HELPERS_H */ diff --git a/include/lib/stdlib/stdio.h b/include/lib/stdlib/stdio.h index 80110a8b4..55d8fe2c1 100644 --- a/include/lib/stdlib/stdio.h +++ b/include/lib/stdlib/stdio.h @@ -59,6 +59,8 @@ typedef __ssize_t ssize_t; #define EOF (-1) int printf(const char * __restrict, ...) __printflike(1, 2); +int vprintf(const char * __restrict, __va_list); + int putchar(int); int puts(const char *); int sprintf(char * __restrict, const char * __restrict, ...) diff --git a/include/lib/tftf_lib.h b/include/lib/tftf_lib.h index 97b6f411d..58112b4b6 100644 --- a/include/lib/tftf_lib.h +++ b/include/lib/tftf_lib.h @@ -36,8 +36,6 @@ typedef enum { TEST_RESULT_MAX } test_result_t; -const char *test_result_to_string(test_result_t result); - #define TEST_RESULT_IS_VALID(result) \ ((result >= TEST_RESULT_MIN) && (result < TEST_RESULT_MAX)) @@ -133,7 +131,7 @@ void waitus(uint64_t us); */ typedef struct { /* Function identifier. Identifies which function is being invoked. */ - uint32_t arg0; + uint32_t fid; u_register_t arg1; u_register_t arg2; diff --git a/lib/delay/delay.c b/lib/delay/delay.c index d88e500c6..f6b29d1e8 100644 --- a/lib/delay/delay.c +++ b/lib/delay/delay.c @@ -5,22 +5,14 @@ */ #include <arch_helpers.h> -#include <tftf.h> void waitus(uint64_t us) { - uint64_t cntp_ct_val_base; - uint32_t cnt_frq; - uint64_t wait_cycles; + uint64_t start_count_val = syscounter_read(); + uint64_t wait_cycles = (us * read_cntfrq_el0()) / 1000000; - cnt_frq = read_cntfrq_el0(); - cntp_ct_val_base = read_cntpct_el0(); - - /* Waitms in terms of counter freq */ - wait_cycles = (us * cnt_frq) / 1000000; - - while (read_cntpct_el0() - cntp_ct_val_base < wait_cycles) - ; + while ((syscounter_read() - start_count_val) < wait_cycles) + /* Busy wait... */; } void waitms(uint64_t ms) diff --git a/lib/power_management/suspend/tftf_suspend.c b/lib/power_management/suspend/tftf_suspend.c index 75c2ade06..d6c989afe 100644 --- a/lib/power_management/suspend/tftf_suspend.c +++ b/lib/power_management/suspend/tftf_suspend.c @@ -6,6 +6,7 @@ #include <arch_helpers.h> #include <arm_gic.h> +#include <console.h> #include <debug.h> #include <platform.h> #include <power_management.h> @@ -51,6 +52,9 @@ int32_t tftf_enter_suspend(const suspend_info_t *info, */ flush_dcache_range((u_register_t)ctx, sizeof(*ctx)); + /* Make sure any outstanding message is printed. */ + console_flush(); + if (info->psci_api == SMC_PSCI_CPU_SUSPEND) rc = tftf_smc(&cpu_suspend_args); else diff --git a/lib/sdei/sdei.c b/lib/sdei/sdei.c index 846b96eb4..264da28ae 100644 --- a/lib/sdei/sdei.c +++ b/lib/sdei/sdei.c @@ -32,7 +32,7 @@ int64_t sdei_interrupt_bind(int intr, struct sdei_intr_ctx *intr_ctx) intr_ctx->enabled = arm_gic_intr_enabled(intr); arm_gic_intr_disable(intr); - args.arg0 = SDEI_INTERRUPT_BIND; + args.fid = SDEI_INTERRUPT_BIND; args.arg1 = intr; ret = tftf_smc(&args); if (ret.ret0 < 0) { @@ -51,7 +51,7 @@ int64_t sdei_interrupt_release(int ev, const struct sdei_intr_ctx *intr_ctx) assert(intr_ctx); - args.arg0 = SDEI_INTERRUPT_RELEASE; + args.fid = SDEI_INTERRUPT_RELEASE; args.arg1 = ev; ret = tftf_smc(&args); if (ret.ret0 == 0) { @@ -69,7 +69,7 @@ int64_t sdei_event_register(int ev, sdei_handler_t *ep, smc_args args = { 0 }; smc_ret_values ret; - args.arg0 = SDEI_EVENT_REGISTER; + args.fid = SDEI_EVENT_REGISTER; args.arg1 = ev; args.arg2 = (u_register_t)ep; args.arg3 = ep_arg; @@ -84,7 +84,7 @@ int64_t sdei_event_unregister(int ev) smc_args args = { 0 }; smc_ret_values ret; - args.arg0 = SDEI_EVENT_UNREGISTER; + args.fid = SDEI_EVENT_UNREGISTER; args.arg1 = ev; ret = tftf_smc(&args); return ret.ret0; @@ -95,7 +95,7 @@ int64_t sdei_event_enable(int ev) smc_args args = { 0 }; smc_ret_values ret; - args.arg0 = SDEI_EVENT_ENABLE; + args.fid = SDEI_EVENT_ENABLE; args.arg1 = ev; ret = tftf_smc(&args); return ret.ret0; @@ -106,7 +106,7 @@ int64_t sdei_event_disable(int ev) smc_args args = { 0 }; smc_ret_values ret; - args.arg0 = SDEI_EVENT_DISABLE; + args.fid = SDEI_EVENT_DISABLE; args.arg1 = ev; ret = tftf_smc(&args); return ret.ret0; @@ -117,7 +117,7 @@ int64_t sdei_pe_mask(void) smc_args args = { 0 }; smc_ret_values ret; - args.arg0 = SDEI_PE_MASK; + args.fid = SDEI_PE_MASK; ret = tftf_smc(&args); return ret.ret0; } @@ -127,7 +127,7 @@ int64_t sdei_pe_unmask(void) smc_args args = { 0 }; smc_ret_values ret; - args.arg0 = SDEI_PE_UNMASK; + args.fid = SDEI_PE_UNMASK; ret = tftf_smc(&args); return ret.ret0; } @@ -137,7 +137,7 @@ int64_t sdei_private_reset(void) smc_args args = { 0 }; smc_ret_values ret; - args.arg0 = SDEI_PRIVATE_RESET; + args.fid = SDEI_PRIVATE_RESET; ret = tftf_smc(&args); return ret.ret0; } @@ -147,7 +147,7 @@ int64_t sdei_shared_reset(void) smc_args args = { 0 }; smc_ret_values ret; - args.arg0 = SDEI_SHARED_RESET; + args.fid = SDEI_SHARED_RESET; ret = tftf_smc(&args); return ret.ret0; } @@ -157,7 +157,7 @@ int64_t sdei_event_signal(uint64_t mpidr) smc_args args = { 0 }; smc_ret_values ret; - args.arg0 = SDEI_EVENT_SIGNAL; + args.fid = SDEI_EVENT_SIGNAL; args.arg1 = 0; /* must be event 0 */ args.arg2 = mpidr; ret = tftf_smc(&args); @@ -169,7 +169,7 @@ int64_t sdei_event_status(int32_t ev) smc_args args = { 0 }; smc_ret_values ret; - args.arg0 = SDEI_EVENT_STATUS; + args.fid = SDEI_EVENT_STATUS; args.arg1 = ev; ret = tftf_smc(&args); return ret.ret0; @@ -180,7 +180,7 @@ int64_t sdei_event_routing_set(int32_t ev, uint64_t flags) smc_args args = { 0 }; smc_ret_values ret; - args.arg0 = SDEI_EVENT_ROUTING_SET; + args.fid = SDEI_EVENT_ROUTING_SET; args.arg1 = ev; args.arg2 = flags; ret = tftf_smc(&args); @@ -192,7 +192,7 @@ int64_t sdei_event_context(uint32_t param) smc_args args = { 0 }; smc_ret_values ret; - args.arg0 = SDEI_EVENT_CONTEXT; + args.fid = SDEI_EVENT_CONTEXT; args.arg1 = param; ret = tftf_smc(&args); return ret.ret0; @@ -203,7 +203,7 @@ int64_t sdei_event_complete(uint32_t flags) smc_args args = { 0 }; smc_ret_values ret; - args.arg0 = SDEI_EVENT_COMPLETE; + args.fid = SDEI_EVENT_COMPLETE; args.arg1 = flags; ret = tftf_smc(&args); return ret.ret0; @@ -214,7 +214,7 @@ int64_t sdei_event_complete_and_resume(uint64_t addr) smc_args args = { 0 }; smc_ret_values ret; - args.arg0 = SDEI_EVENT_COMPLETE_AND_RESUME; + args.fid = SDEI_EVENT_COMPLETE_AND_RESUME; args.arg1 = addr; ret = tftf_smc(&args); return ret.ret0; diff --git a/lib/smc/aarch64/asm_smc.S b/lib/smc/aarch64/asm_smc.S index 48a80a3f7..1180f518e 100644 --- a/lib/smc/aarch64/asm_smc.S +++ b/lib/smc/aarch64/asm_smc.S @@ -12,7 +12,7 @@ /* --------------------------------------------------------------------------- - * smc_ret_values asm_tftf_smc64(uint32_t arg0, + * smc_ret_values asm_tftf_smc64(uint32_t fid, * u_register_t arg1, * u_register_t arg2, * u_register_t arg3, diff --git a/lib/smc/aarch64/smc.c b/lib/smc/aarch64/smc.c index cbe4bb9fd..6667ee7be 100644 --- a/lib/smc/aarch64/smc.c +++ b/lib/smc/aarch64/smc.c @@ -7,7 +7,7 @@ #include <stdint.h> #include <tftf.h> -smc_ret_values asm_tftf_smc64(uint32_t arg0, +smc_ret_values asm_tftf_smc64(uint32_t fid, u_register_t arg1, u_register_t arg2, u_register_t arg3, @@ -18,7 +18,7 @@ smc_ret_values asm_tftf_smc64(uint32_t arg0, smc_ret_values tftf_smc(const smc_args *args) { - return asm_tftf_smc64(args->arg0, + return asm_tftf_smc64(args->fid, args->arg1, args->arg2, args->arg3, diff --git a/lib/stdlib/printf.c b/lib/stdlib/printf.c index 6329157d0..8ae7c2635 100644 --- a/lib/stdlib/printf.c +++ b/lib/stdlib/printf.c @@ -9,28 +9,34 @@ /* Choose max of 512 chars for now. */ #define PRINT_BUFFER_SIZE 512 -int printf(const char *fmt, ...) + +int vprintf(const char *fmt, va_list args) { - va_list args; char buf[PRINT_BUFFER_SIZE]; int count; - va_start(args, fmt); vsnprintf(buf, sizeof(buf) - 1, fmt, args); - va_end(args); + buf[PRINT_BUFFER_SIZE - 1] = '\0'; /* Use putchar directly as 'puts()' adds a newline. */ - buf[PRINT_BUFFER_SIZE - 1] = '\0'; count = 0; - while (buf[count]) - { - if (putchar(buf[count]) != EOF) { - count++; - } else { - count = EOF; - break; + while (buf[count] != 0) { + if (putchar(buf[count]) == EOF) { + return EOF; } + count++; } return count; } + +int printf(const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + int count = vprintf(fmt, args); + va_end(args); + + return count; +} diff --git a/lib/utils/mp_printf.c b/lib/utils/mp_printf.c index d1eb780ea..777c736ad 100644 --- a/lib/utils/mp_printf.c +++ b/lib/utils/mp_printf.c @@ -4,8 +4,6 @@ * SPDX-License-Identifier: BSD-3-Clause */ -#include <arch_helpers.h> -#include <platform.h> #include <spinlock.h> #include <stdarg.h> #include <stdio.h> @@ -13,60 +11,14 @@ /* Lock to avoid concurrent accesses to the serial console */ static spinlock_t printf_lock; -/* - * Print the MPID header, e.g.: [cpu 0x0100] - * - * If SHELL_COLOR == 1, this also prints shell's color escape sequences to ease - * identifying which CPU displays the message. There are 8 standard colors so - * if the platform has more than 8 CPUs, some colors will be reused. - */ -#if SHELL_COLOR -#define PRINT_MPID_HDR(_mpid) \ - do { \ - unsigned int linear_id = platform_get_core_pos(_mpid); \ - printf("\033[1;%u;40m", 30 + (linear_id & 0x7)); \ - printf("[cpu 0x%.4x] ", _mpid); \ - printf("\033[0m"); \ - } while (0) -#else -#define PRINT_MPID_HDR(_mpid) \ - printf("[cpu 0x%.4x] ", _mpid) -#endif /* SHELL_COLOR */ - void mp_printf(const char *fmt, ...) { - va_list ap; - char str[256]; - /* - * As part of testing Firmware Update feature on Cortex-A57 CPU, an - * issue was discovered while printing in NS_BL1U stage. The issue - * appears when the second call to `NOTICE()` is made in the - * `ns_bl1u_main()`. As a result of this issue the CPU hangs and the - * debugger is also not able to connect anymore. - * - * After further debugging and experiments it was found that if - * `read_mpidr_el1()` is avoided or volatile qualifier is used for - * reading the mpidr, this issue gets resolved. - * - * NOTE: The actual/real reason why this happens is still not known. - * Moreover this problem is not encountered on Cortex-A53 CPU. - */ - volatile unsigned int mpid = read_mpidr_el1() & 0xFFFF; - - /* - * TODO: It would be simpler to use vprintf() instead of - * vsnprintf() + printf(), we wouldn't need to declare a static buffer - * for storing the product of vsnprintf(). Unfortunately our C library - * doesn't provide vprintf() at the moment. - * Import vprintf() code from FreeBSD C library to our local C library. - */ - va_start(ap, fmt); - vsnprintf(str, sizeof(str), fmt, ap); - str[sizeof(str) - 1] = 0; - va_end(ap); + va_list args; + va_start(args, fmt); spin_lock(&printf_lock); - PRINT_MPID_HDR(mpid); - printf("%s", str); + vprintf(fmt, args); spin_unlock(&printf_lock); + + va_end(args); } diff --git a/spm/cactus/cactus.mk b/spm/cactus/cactus.mk index 1ebc6927b..03d809d10 100644 --- a/spm/cactus/cactus.mk +++ b/spm/cactus/cactus.mk @@ -58,6 +58,8 @@ CACTUS_SOURCES += \ CACTUS_SOURCES += drivers/arm/pl011/${ARCH}/pl011_console.S \ lib/${ARCH}/cache_helpers.S \ lib/${ARCH}/misc_helpers.S \ + lib/locks/${ARCH}/spinlock.S \ + lib/utils/mp_printf.c \ ${STDLIB_SOURCES} \ ${SPRT_LIB_SOURCES} diff --git a/spm/common/sp_helpers.h b/spm/common/sp_helpers.h index fb2d8ac94..1bd4425ff 100644 --- a/spm/common/sp_helpers.h +++ b/spm/common/sp_helpers.h @@ -11,7 +11,7 @@ #include <sys/types.h> typedef struct { - u_register_t arg0; + u_register_t fid; u_register_t arg1; u_register_t arg2; u_register_t arg3; @@ -28,7 +28,7 @@ typedef struct { * structure. The return values of the SVC call will be stored in the same * structure (overriding the input arguments). * - * Return the first return value. It is equivalent to args.arg0 but is also + * Return the first return value. It is equivalent to args.fid but is also * provided as the return value for convenience. */ u_register_t sp_svc(svc_args *args); diff --git a/spm/ivy/ivy.mk b/spm/ivy/ivy.mk index 89fd92d47..c7726f4fd 100644 --- a/spm/ivy/ivy.mk +++ b/spm/ivy/ivy.mk @@ -55,6 +55,8 @@ IVY_SOURCES += \ IVY_SOURCES += drivers/arm/pl011/${ARCH}/pl011_console.S \ lib/${ARCH}/cache_helpers.S \ lib/${ARCH}/misc_helpers.S \ + lib/locks/${ARCH}/spinlock.S \ + lib/utils/mp_printf.c \ ${STDLIB_SOURCES} \ ${SPRT_LIB_SOURCES} diff --git a/tftf/framework/include/tftf.h b/tftf/framework/include/tftf.h index 8231e284a..43f1e7ea5 100644 --- a/tftf/framework/include/tftf.h +++ b/tftf/framework/include/tftf.h @@ -130,7 +130,10 @@ STATUS tftf_testcase_set_result(const test_case_t *testcase, */ STATUS tftf_testcase_get_result(const test_case_t *testcase, TESTCASE_RESULT *result, char *test_output); -void tftf_report_generate(void); +void print_testsuite_start(const test_suite_t *testsuite); +void print_test_start(const test_case_t *test); +void print_test_end(const test_case_t *test); +void print_tests_summary(void); /* * Exit the TFTF. diff --git a/tftf/framework/main.c b/tftf/framework/main.c index 3f94dc94a..02b54386e 100644 --- a/tftf/framework/main.c +++ b/tftf/framework/main.c @@ -148,8 +148,14 @@ static void prepare_next_test(void) for (unsigned int i = 0; i < PLATFORM_CORE_COUNT; ++i) test_results[i] = TEST_RESULT_NA; - NOTICE("Starting unittest '%s - %s'\n", - current_testsuite()->name, current_testcase()->name); + /* If we're starting a new testsuite, announce it. */ + test_ref_t test_to_run; + tftf_get_test_to_run(&test_to_run); + if (test_to_run.testcase_idx == 0) { + print_testsuite_start(current_testsuite()); + } + + print_test_start(current_testcase()); /* Program the watchdog */ tftf_platform_watchdog_set(); @@ -176,7 +182,6 @@ static test_result_t get_overall_test_result(void) switch (test_results[core_pos]) { case TEST_RESULT_NA: - VERBOSE("CPU%u not involved in the test\n", core_pos); /* Ignoring */ break; @@ -185,7 +190,6 @@ static test_result_t get_overall_test_result(void) * If at least one CPU skipped the test, consider the * whole test as skipped as well. */ - NOTICE("CPU%u skipped the test\n", core_pos); return TEST_RESULT_SKIPPED; case TEST_RESULT_SUCCESS: @@ -193,7 +197,6 @@ static test_result_t get_overall_test_result(void) break; case TEST_RESULT_FAIL: - ERROR("CPU%u failed the test\n", core_pos); return TEST_RESULT_FAIL; case TEST_RESULT_CRASHED: @@ -205,7 +208,6 @@ static test_result_t get_overall_test_result(void) * If at least one CPU crashed, consider the whole test * as crashed as well. */ - ERROR("CPU%u never returned from the test!\n", core_pos); return TEST_RESULT_CRASHED; default: @@ -263,21 +265,18 @@ static unsigned int close_test(void) assert(tftf_get_ref_cnt() == 0); /* Save test result in NVM */ - test_result_t overall_test_result = get_overall_test_result(); tftf_testcase_set_result(current_testcase(), - overall_test_result, + get_overall_test_result(), 0); - NOTICE("Unittest '%s - %s' complete. Result: %s\n", - current_testsuite()->name, current_testcase()->name, - test_result_to_string(overall_test_result)); + print_test_end(current_testcase()); /* The test is finished, let's move to the next one (if any) */ next_test = advance_to_next_test(); /* If this was the last test then report all results */ if (!next_test) { - tftf_report_generate(); + print_tests_summary(); tftf_clean_nvm(); return 1; } else { @@ -551,7 +550,7 @@ void __dead2 tftf_cold_boot_main(void) NOTICE("Resuming interrupted test session\n"); rc = resume_test_session(); if (rc < 0) { - tftf_report_generate(); + print_tests_summary(); tftf_clean_nvm(); tftf_exit(); } diff --git a/tftf/framework/report.c b/tftf/framework/report.c index faae34b87..663caf365 100644 --- a/tftf/framework/report.c +++ b/tftf/framework/report.c @@ -6,70 +6,97 @@ #include <assert.h> #include <debug.h> -#include <platform_def.h> /* For TESTCASE_OUTPUT_MAX_SIZE */ #include <stdio.h> -#include <string.h> +#include <stdbool.h> #include <tftf.h> -static unsigned int total_tests; -static unsigned int tests_stats[TEST_RESULT_MAX]; - -static void tftf_update_tests_statistics(test_result_t result) -{ - assert(TEST_RESULT_IS_VALID(result)); - total_tests++; - tests_stats[result]++; -} - static const char *test_result_strings[TEST_RESULT_MAX] = { "Skipped", "Passed", "Failed", "Crashed", }; -const char *test_result_to_string(test_result_t result) +static const char *test_result_to_string(test_result_t result) { assert(TEST_RESULT_IS_VALID(result)); return test_result_strings[result]; } -void tftf_report_generate(void) +void print_testsuite_start(const test_suite_t *testsuite) { - unsigned i, j; - const test_case_t *testcases; - TESTCASE_RESULT testcase_result; - char test_output[TESTCASE_OUTPUT_MAX_SIZE]; - STATUS status; - - /* Extract the result of all the testcases */ - printf("========== TEST REPORT ==========\n"); - for (i = 0; testsuites[i].name != NULL; i++) { - printf("# Test suite '%s':\n", testsuites[i].name); - testcases = testsuites[i].testcases; - - for (j = 0; testcases[j].name != NULL; j++) { - status = tftf_testcase_get_result(&testcases[j], &testcase_result, test_output); - if (status != STATUS_SUCCESS) { - printf("Failed to get test result.\n"); + mp_printf("--\n"); + mp_printf("Running test suite '%s'\n", testsuite->name); + mp_printf("Description: %s\n", testsuite->description); + mp_printf("\n"); +} + +void print_test_start(const test_case_t *test) +{ + mp_printf("> Executing '%s'\n", test->name); +} + +void print_test_end(const test_case_t *test) +{ + TESTCASE_RESULT result; + char output[TESTCASE_OUTPUT_MAX_SIZE]; + + tftf_testcase_get_result(test, &result, output); + + mp_printf(" TEST COMPLETE %54s\n", + test_result_to_string(result.result)); + if (strlen(output) != 0) { + mp_printf("%s", output); + } + mp_printf("\n"); +} + +void print_tests_summary(void) +{ + int total_tests = 0; + int tests_stats[TEST_RESULT_MAX] = { 0 }; + + mp_printf("******************************* Summary *******************************\n"); + + /* Go through the list of test suites. */ + for (int i = 0; testsuites[i].name != NULL; i++) { + bool passed = true; + + mp_printf("> Test suite '%s'\n", testsuites[i].name); + + const test_case_t *testcases = testsuites[i].testcases; + + /* Go through the list of tests inside this test suite. */ + for (int j = 0; testcases[j].name != NULL; j++) { + TESTCASE_RESULT result; + char output[TESTCASE_OUTPUT_MAX_SIZE]; + + if (tftf_testcase_get_result(&testcases[j], &result, + output) != STATUS_SUCCESS) { + mp_printf("Failed to get test result.\n"); continue; } - tftf_update_tests_statistics(testcase_result.result); - /* TODO: print test duration */ - printf("\t - %s: %s\n", testcases[j].name, - test_result_to_string(testcase_result.result)); + assert(TEST_RESULT_IS_VALID(result.result)); - if (strlen(test_output) != 0) { - printf("--- output ---\n"); - printf("%s", test_output); - printf("--------------\n"); + /* + * Consider that a test suite passed if all of its + * tests passed or were skipped. + */ + if ((result.result != TEST_RESULT_SUCCESS) && + (result.result != TEST_RESULT_SKIPPED)) { + passed = false; } + + total_tests++; + tests_stats[result.result]++; } + mp_printf("%70s\n", passed ? "Passed" : "Failed"); } - printf("=================================\n"); - for (i = TEST_RESULT_MIN; i < TEST_RESULT_MAX; i++) { - printf("Tests %-8s: %d\n", + mp_printf("=================================\n"); + + for (int i = TEST_RESULT_MIN; i < TEST_RESULT_MAX; i++) { + mp_printf("Tests %-8s: %d\n", test_result_to_string(i), tests_stats[i]); } - printf("%-14s: %d\n", "Total tests", total_tests); - printf("=================================\n"); + mp_printf("%-14s: %d\n", "Total tests", total_tests); + mp_printf("=================================\n"); } diff --git a/tftf/framework/timer/timer_framework.c b/tftf/framework/timer/timer_framework.c index e5e9a0f86..0b0a7a53a 100644 --- a/tftf/framework/timer/timer_framework.c +++ b/tftf/framework/timer/timer_framework.c @@ -71,15 +71,11 @@ static inline unsigned long long get_current_prog_time(void) int tftf_initialise_timer(void) { - int rc; - unsigned int i; - /* * Get platform specific timer information */ - rc = plat_initialise_timer_ops(&plat_timer_info); - if (rc) { - ERROR("%s %d: No timer data found\n", __func__, __LINE__); + int rc = plat_initialise_timer_ops(&plat_timer_info); + if (rc != 0) { return rc; } @@ -87,7 +83,7 @@ int tftf_initialise_timer(void) assert(TIMER_STEP_VALUE); /* Initialise the array to max possible time */ - for (i = 0; i < PLATFORM_CORE_COUNT; i++) + for (unsigned int i = 0; i < PLATFORM_CORE_COUNT; i++) interrupt_req_time[i] = INVALID_TIME; tftf_irq_register_handler(TIMER_IRQ, tftf_timer_framework_handler); diff --git a/tftf/tests/performance_tests/smc_latencies.c b/tftf/tests/performance_tests/smc_latencies.c index fe226790e..49733cfb6 100644 --- a/tftf/tests/performance_tests/smc_latencies.c +++ b/tftf/tests/performance_tests/smc_latencies.c @@ -143,7 +143,7 @@ test_result_t smc_arch_workaround_1(void) /* Check if SMCCC version is at least v1.1 */ expected_ver = MAKE_SMCCC_VERSION(1, 1); memset(&args, 0, sizeof(args)); - args.arg0 = SMCCC_VERSION; + args.fid = SMCCC_VERSION; ret = tftf_smc(&args); if ((int32_t)ret.ret0 < expected_ver) { printf("Unexpected SMCCC version: 0x%x\n", @@ -153,7 +153,7 @@ test_result_t smc_arch_workaround_1(void) /* Check if SMCCC_ARCH_WORKAROUND_1 is implemented */ memset(&args, 0, sizeof(args)); - args.arg0 = SMCCC_ARCH_FEATURES; + args.fid = SMCCC_ARCH_FEATURES; args.arg1 = SMCCC_ARCH_WORKAROUND_1; ret = tftf_smc(&args); if ((int)ret.ret0 == -1) { @@ -162,7 +162,7 @@ test_result_t smc_arch_workaround_1(void) } memset(&args, 0, sizeof(args)); - args.arg0 = SMCCC_ARCH_WORKAROUND_1; + args.fid = SMCCC_ARCH_WORKAROUND_1; test_measure_smc_latency(&args, &latency); tftf_testcase_printf( diff --git a/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_1.c b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_1.c index 4a45ad4d8..90a43f33b 100644 --- a/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_1.c +++ b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_1.c @@ -60,7 +60,7 @@ static test_result_t test_smccc_entrypoint(void) /* Check if SMCCC version is at least v1.1 */ expected_ver = MAKE_SMCCC_VERSION(1, 1); memset(&args, 0, sizeof(args)); - args.arg0 = SMCCC_VERSION; + args.fid = SMCCC_VERSION; ret = tftf_smc(&args); if ((int32_t)ret.ret0 < expected_ver) { tftf_testcase_printf("Unexpected SMCCC version: 0x%x\n", @@ -70,7 +70,7 @@ static test_result_t test_smccc_entrypoint(void) /* Check if SMCCC_ARCH_WORKAROUND_1 is required or not */ memset(&args, 0, sizeof(args)); - args.arg0 = SMCCC_ARCH_FEATURES; + args.fid = SMCCC_ARCH_FEATURES; args.arg1 = SMCCC_ARCH_WORKAROUND_1; ret = tftf_smc(&args); if ((int)ret.ret0 == -1) { @@ -104,7 +104,7 @@ static test_result_t test_smccc_entrypoint(void) /* Invoke the workaround to make sure nothing nasty happens */ memset(&args, 0, sizeof(args)); - args.arg0 = SMCCC_ARCH_WORKAROUND_1; + args.fid = SMCCC_ARCH_WORKAROUND_1; tftf_smc(&args); return TEST_RESULT_SUCCESS; } diff --git a/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_2.c b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_2.c index dd0542ca3..a09087411 100644 --- a/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_2.c +++ b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_2.c @@ -43,7 +43,7 @@ static test_result_t test_smccc_entrypoint(void) /* Check if SMCCC version is at least v1.1 */ expected_ver = MAKE_SMCCC_VERSION(1, 1); memset(&args, 0, sizeof(args)); - args.arg0 = SMCCC_VERSION; + args.fid = SMCCC_VERSION; ret = tftf_smc(&args); if ((int32_t)ret.ret0 < expected_ver) { tftf_testcase_printf("Unexpected SMCCC version: 0x%x\n", @@ -53,7 +53,7 @@ static test_result_t test_smccc_entrypoint(void) /* Check if SMCCC_ARCH_WORKAROUND_2 is required or not */ memset(&args, 0, sizeof(args)); - args.arg0 = SMCCC_ARCH_FEATURES; + args.fid = SMCCC_ARCH_FEATURES; args.arg1 = SMCCC_ARCH_WORKAROUND_2; ret = tftf_smc(&args); if ((int)ret.ret0 == -1) { @@ -87,7 +87,7 @@ static test_result_t test_smccc_entrypoint(void) /* Invoke the workaround to make sure nothing nasty happens */ memset(&args, 0, sizeof(args)); - args.arg0 = SMCCC_ARCH_WORKAROUND_2; + args.fid = SMCCC_ARCH_WORKAROUND_2; tftf_smc(&args); return TEST_RESULT_SUCCESS; } diff --git a/tftf/tests/runtime_services/generic/generic_smc.c b/tftf/tests/runtime_services/generic/generic_smc.c new file mode 100644 index 000000000..901b44812 --- /dev/null +++ b/tftf/tests/runtime_services/generic/generic_smc.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2018, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <psci.h> +#include <smccc.h> +#include <std_svc.h> +#include <string.h> +#include <tftf_lib.h> +#include <tsp.h> +#include <utils_def.h> + +/* An invalid SMC function number. */ +#define INVALID_FN 0x666 + +/* PSCI version returned by TF-A. */ +static const uint32_t psci_version = PSCI_VERSION(PSCI_MAJOR_VER, + PSCI_MINOR_VER); + +/* UUID of the standard service in TF-A. */ +static const smc_ret_values std_svc_uuid = { + 0x108d905b, 0x47e8f863, 0xfbc02dae, 0xe2f64156 +}; + +/* + * Build an SMC function ID given its type (fast/yielding), calling convention, + * owning entity number and function number. + */ +static inline uint32_t make_smc_fid(unsigned int type, unsigned int cc, + unsigned int oen, unsigned int func_num) +{ + return (type << FUNCID_TYPE_SHIFT) | (cc << FUNCID_CC_SHIFT) + | (oen << FUNCID_OEN_SHIFT) | (func_num << FUNCID_NUM_SHIFT); +} + +/* Exit the test if the specified condition holds true. */ +#define FAIL_IF(_cond) \ + do { \ + if ((_cond)) { \ + return TEST_RESULT_FAIL; \ + } \ + } while (0) + +/* + * Send an SMC with the specified arguments. + * Check that the values it returns match the expected ones. If not, write an + * error message in the test report. + */ +static bool smc_check_eq(const smc_args *args, const smc_ret_values *expect) +{ + smc_ret_values ret = tftf_smc(args); + + if (memcmp(&ret, expect, sizeof(smc_ret_values)) == 0) { + return true; + } else { + tftf_testcase_printf( + "Got {0x%lx,0x%lx,0x%lx,0x%lx}, expected {0x%lx,0x%lx,0x%lx,0x%lx}.\n", + ret.ret0, ret.ret1, ret.ret2, ret.ret3, + expect->ret0, expect->ret1, expect->ret2, expect->ret3); + return false; + } +} + +/* Exercise SMC32 calling convention with fast SMC calls. */ +test_result_t smc32_fast(void) +{ + /* Valid Fast SMC32 using all 4 return values. */ + const smc_args args1 = { .fid = SMC_STD_SVC_UID }; + FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid)); + + /* Invalid Fast SMC32. */ + const smc_args args2 = { + make_smc_fid(SMC_TYPE_FAST, SMC_32, OEN_ARM_START, INVALID_FN), + 0x11111111, 0x22222222, 0x33333333 }; + const smc_ret_values ret2 + = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333 }; + FAIL_IF(!smc_check_eq(&args2, &ret2)); + + /* Valid Fast SMC32 using 1 return value. */ + const smc_args args3 + = { SMC_PSCI_VERSION, 0x44444444, 0x55555555, 0x66666666 }; + const smc_ret_values ret3 + = { psci_version, 0x44444444, 0x55555555, 0x66666666 }; + FAIL_IF(!smc_check_eq(&args3, &ret3)); + + return TEST_RESULT_SUCCESS; +} + +/* Exercise SMC64 calling convention with yielding SMC calls. */ +test_result_t smc64_yielding(void) +{ + /* Valid Fast SMC32 using all 4 return values. */ + const smc_args args1 = { .fid = SMC_STD_SVC_UID }; + FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid)); + + /* Invalid function number, SMC64 Yielding. */ + const smc_args args2 = { + make_smc_fid(SMC_TYPE_STD, SMC_64, OEN_ARM_START, INVALID_FN), + 0x11111111, 0x22222222, 0x33333333 }; + const smc_ret_values ret2 + = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333 }; + FAIL_IF(!smc_check_eq(&args2, &ret2)); + + /* + * Valid[1] yielding SMC64 using 1 return value. + * + * [1] Valid from the point of view of the generic SMC handler if the + * TSPd is present. In this case, the SMC request gets passed to the + * TSPd handler code. The fact that it then gets rejected by the TSPd is + * irrelevant here, as we are not trying to test the TSPd nor the TSP. + * + * In other cases (i.e. AArch64 BL31 with no TSPd support or AArch32 + * SP_MIN) this test should still fail in the same way, although it + * doesn't exercise the same code path in TF-A. + */ + const smc_args args3 = { + make_smc_fid(SMC_TYPE_STD, SMC_64, OEN_TOS_START, INVALID_FN), + 0x44444444, 0x55555555, 0x66666666 }; + const smc_ret_values ret3 + = { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666 }; + FAIL_IF(!smc_check_eq(&args3, &ret3)); + + return TEST_RESULT_SUCCESS; +} + +#ifdef AARCH32 +static test_result_t smc64_fast_caller32(void) +{ + /* Valid Fast SMC32 using all 4 return values. */ + smc_args args1 = { .fid = SMC_STD_SVC_UID }; + FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid)); + + /* Invalid SMC function number, Fast SMC64. */ + const smc_args args2 = { + make_smc_fid(SMC_TYPE_FAST, SMC_64, OEN_ARM_START, INVALID_FN), + 0x11111111, 0x22222222, 0x33333333 }; + const smc_ret_values ret2 + = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333 }; + FAIL_IF(!smc_check_eq(&args2, &ret2)); + + /* + * Valid SMC function number, Fast SMC64. However, 32-bit callers are + * forbidden to use the SMC64 calling convention. + */ + const smc_args args3 = { SMC_PSCI_AFFINITY_INFO_AARCH64, + 0x44444444, 0x55555555, 0x66666666 }; + const smc_ret_values ret3 + = { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666 }; + FAIL_IF(!smc_check_eq(&args3, &ret3)); + + return TEST_RESULT_SUCCESS; +} +#else +static test_result_t smc64_fast_caller64(void) +{ + /* Valid Fast SMC32 using all 4 return values. */ + smc_args args1 = { .fid = SMC_STD_SVC_UID }; + FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid)); + + /* Invalid function number, Fast SMC64. */ + const smc_args args2 = { + make_smc_fid(SMC_TYPE_FAST, SMC_64, OEN_ARM_START, INVALID_FN), + 0x11111111, 0x22222222, 0x33333333 }; + const smc_ret_values ret2 + = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333 }; + FAIL_IF(!smc_check_eq(&args2, &ret2)); + + /* Valid Fast SMC64 using 1 return value. */ + const smc_args args3 = { SMC_PSCI_AFFINITY_INFO_AARCH64, + 0x44444444, 0x55555555, 0x66666666 }; + const smc_ret_values ret3 + = { PSCI_E_INVALID_PARAMS, 0x44444444, 0x55555555, 0x66666666 }; + FAIL_IF(!smc_check_eq(&args3, &ret3)); + + return TEST_RESULT_SUCCESS; +} +#endif /* AARCH32 */ + +/* Exercise SMC64 calling convention with fast SMC calls. */ +test_result_t smc64_fast(void) +{ +#ifdef AARCH32 + return smc64_fast_caller32(); +#else + return smc64_fast_caller64(); +#endif +} + +/* Exercise SMC32 calling convention with yielding SMC calls. */ +test_result_t smc32_yielding(void) +{ + /* Valid Fast SMC32 using all 4 return values. */ + const smc_args args1 = { .fid = SMC_STD_SVC_UID }; + FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid)); + + /* Invalid function number, SMC32 Yielding. */ + const smc_args args2 = { + make_smc_fid(SMC_TYPE_STD, SMC_32, OEN_ARM_START, INVALID_FN), + 0x11111111, 0x22222222, 0x33333333 }; + const smc_ret_values ret2 + = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333 }; + FAIL_IF(!smc_check_eq(&args2, &ret2)); + + /* + * Valid[1] yielding SMC32 using 1 return value. + * + * [1] Valid from the point of view of the generic SMC handler if a + * secure payload dispatcher handling this SMC range is present. In this + * case, the SMC request gets passed to the dispatcher handler code. The + * fact that it then gets rejected by the dispatcher is irrelevant here, + * as we are not trying to test the dispatcher nor the secure payload. + * + * In BL31 has no SPD support, this test should still fail in the same + * way, although it doesn't exercise the same code path in TF-A. + */ + const smc_args args3 = { + make_smc_fid(SMC_TYPE_STD, SMC_32, OEN_TOS_START, INVALID_FN), + 0x44444444, 0x55555555, 0x66666666 }; + const smc_ret_values ret3 + = { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666 }; + FAIL_IF(!smc_check_eq(&args3, &ret3)); + + return TEST_RESULT_SUCCESS; +} + diff --git a/tftf/tests/runtime_services/sip_service/test_exec_state_switch.c b/tftf/tests/runtime_services/sip_service/test_exec_state_switch.c index 120a99ee0..713c8196e 100644 --- a/tftf/tests/runtime_services/sip_service/test_exec_state_switch.c +++ b/tftf/tests/runtime_services/sip_service/test_exec_state_switch.c @@ -130,7 +130,7 @@ test_result_t test_exec_state_switch_invalid_pc(void) int ret; smc_args args = { - .arg0 = ARM_SIP_SVC_EXE_STATE_SWITCH, + .fid = ARM_SIP_SVC_EXE_STATE_SWITCH, .arg1 = (u_register_t) -1, .arg2 = LO32(&state_switch_a32_entry), .arg3 = HI32(&state_switch_cookie), @@ -163,7 +163,7 @@ test_result_t test_exec_state_switch_invalid_ctx(void) int ret; smc_args args = { - .arg0 = ARM_SIP_SVC_EXE_STATE_SWITCH, + .fid = ARM_SIP_SVC_EXE_STATE_SWITCH, .arg1 = HI32(&state_switch_a32_entry), .arg2 = LO32(&state_switch_a32_entry), .arg3 = -1, @@ -195,7 +195,7 @@ test_result_t test_exec_state_switch_valid(void) int ret; smc_args args = { - .arg0 = ARM_SIP_SVC_EXE_STATE_SWITCH, + .fid = ARM_SIP_SVC_EXE_STATE_SWITCH, .arg1 = HI32(&state_switch_a32_entry), .arg2 = LO32(&state_switch_a32_entry), .arg3 = HI32(&state_switch_cookie), @@ -259,7 +259,7 @@ test_result_t test_exec_state_switch_after_cpu_on(void) int ret; smc_args args = { - .arg0 = ARM_SIP_SVC_EXE_STATE_SWITCH, + .fid = ARM_SIP_SVC_EXE_STATE_SWITCH, .arg1 = HI32(&state_switch_a32_entry), .arg2 = LO32(&state_switch_a32_entry), .arg3 = HI32(&state_switch_cookie), diff --git a/tftf/tests/runtime_services/standard_service/pmf/api_tests/runtime_instr/test_pmf_rt_instr.c b/tftf/tests/runtime_services/standard_service/pmf/api_tests/runtime_instr/test_pmf_rt_instr.c index ac811e209..3a3701e92 100644 --- a/tftf/tests/runtime_services/standard_service/pmf/api_tests/runtime_instr/test_pmf_rt_instr.c +++ b/tftf/tests/runtime_services/standard_service/pmf/api_tests/runtime_instr/test_pmf_rt_instr.c @@ -55,7 +55,7 @@ static u_register_t pmf_get_ts(u_register_t tid, u_register_t *v) smc_args args = { 0 }; smc_ret_values ret; - args.arg0 = PMF_SMC_GET_TIMESTAMP; + args.fid = PMF_SMC_GET_TIMESTAMP; args.arg1 = tid; args.arg2 = read_mpidr_el1(); ret = tftf_smc(&args); diff --git a/tftf/tests/runtime_services/standard_service/psci/api_tests/migrate_info_type/test_migrate_info_type.c b/tftf/tests/runtime_services/standard_service/psci/api_tests/migrate_info_type/test_migrate_info_type.c index 73a10489f..50462d7fd 100644 --- a/tftf/tests/runtime_services/standard_service/psci/api_tests/migrate_info_type/test_migrate_info_type.c +++ b/tftf/tests/runtime_services/standard_service/psci/api_tests/migrate_info_type/test_migrate_info_type.c @@ -43,7 +43,7 @@ test_result_t test_migrate_info_type(void) int32_t migrate_ret; /* Identify the level of multicore support present in the Trusted OS */ - args.arg0 = SMC_PSCI_MIG_INFO_TYPE; + args.fid = SMC_PSCI_MIG_INFO_TYPE; ret = tftf_smc(&args); mp_support = (int32_t) ret.ret0; @@ -84,7 +84,7 @@ test_result_t test_migrate_info_type(void) * Either there is no Trusted OS or the Trusted OS is the TSP. * In both cases, the MIGRATE call should not be supported. */ - args.arg0 = SMC_PSCI_MIG; + args.fid = SMC_PSCI_MIG; /* * Pass a valid MPID so that the MIGRATE call doesn't fail because of * invalid parameters diff --git a/tftf/tests/runtime_services/standard_service/query_std_svc.c b/tftf/tests/runtime_services/standard_service/query_std_svc.c index e96d4ae13..34141d2b8 100644 --- a/tftf/tests/runtime_services/standard_service/query_std_svc.c +++ b/tftf/tests/runtime_services/standard_service/query_std_svc.c @@ -41,7 +41,7 @@ test_result_t test_query_std_svc(void) test_result_t test_result = TEST_RESULT_SUCCESS; /* Standard Service Call UID */ - std_svc_args.arg0 = SMC_STD_SVC_UID; + std_svc_args.fid = SMC_STD_SVC_UID; ret = tftf_smc(&std_svc_args); make_uuid_from_4words(&std_svc_uuid, @@ -55,7 +55,7 @@ test_result_t test_query_std_svc(void) } /* Standard Service Call Count */ - std_svc_args.arg0 = SMC_STD_SVC_CALL_COUNT; + std_svc_args.fid = SMC_STD_SVC_CALL_COUNT; ret = tftf_smc(&std_svc_args); if (ret.ret0 == SMC_UNKNOWN) { @@ -68,7 +68,7 @@ test_result_t test_query_std_svc(void) } /* Standard Service Call Revision details */ - std_svc_args.arg0 = SMC_STD_SVC_REVISION; + std_svc_args.fid = SMC_STD_SVC_REVISION; ret = tftf_smc(&std_svc_args); if ((ret.ret0 != STD_SVC_REVISION_MAJOR) || diff --git a/tftf/tests/runtime_services/standard_service/unknown_smc.c b/tftf/tests/runtime_services/standard_service/unknown_smc.c index 70175e3d1..d2a81ca62 100644 --- a/tftf/tests/runtime_services/standard_service/unknown_smc.c +++ b/tftf/tests/runtime_services/standard_service/unknown_smc.c @@ -20,7 +20,7 @@ test_result_t test_unknown_smc(void) smc_args unk_smc; smc_ret_values ret; - unk_smc.arg0 = INVALID_FID; + unk_smc.fid = INVALID_FID; ret = tftf_smc(&unk_smc); if (ret.ret0 != SMC_UNKNOWN) { diff --git a/tftf/tests/runtime_services/trusted_os/tsp/test_irq_preempted_std_smc.c b/tftf/tests/runtime_services/trusted_os/tsp/test_irq_preempted_std_smc.c index 22e35dbc1..b8bfcfe5e 100644 --- a/tftf/tests/runtime_services/trusted_os/tsp/test_irq_preempted_std_smc.c +++ b/tftf/tests/runtime_services/trusted_os/tsp/test_irq_preempted_std_smc.c @@ -125,7 +125,7 @@ static int preempt_std_smc_on_this_cpu(void) * Invoke an STD SMC. Should be pre-empted because of the SGI * that is waiting. */ - std_smc_args.arg0 = TSP_STD_FID(TSP_ADD); + std_smc_args.fid = TSP_STD_FID(TSP_ADD); std_smc_args.arg1 = TEST_VALUE_1; std_smc_args.arg2 = TEST_VALUE_2; smc_ret = tftf_smc(&std_smc_args); @@ -163,7 +163,7 @@ static int resume_std_smc_on_this_cpu(void) unsigned int core_pos = platform_get_core_pos(core_mpid); /* Resume the STD SMC. Verify result. */ - std_smc_args.arg0 = TSP_FID_RESUME; + std_smc_args.fid = TSP_FID_RESUME; smc_ret = tftf_smc(&std_smc_args); if ((smc_ret.ret0 != 0) || (smc_ret.ret1 != TEST_VALUE_1 * 2) || (smc_ret.ret2 != TEST_VALUE_2 * 2)) { @@ -191,7 +191,7 @@ static int resume_fail_std_smc_on_this_cpu(void) unsigned int core_pos = platform_get_core_pos(core_mpid); /* Resume the STD SMC. Verify result. */ - std_smc_args.arg0 = TSP_FID_RESUME; + std_smc_args.fid = TSP_FID_RESUME; smc_ret = tftf_smc(&std_smc_args); if (smc_ret.ret0 != SMC_UNKNOWN) { tftf_testcase_printf( @@ -304,7 +304,7 @@ static test_result_t test_resume_preempted_std_smc_other_cpus_non_lead_fn(void) */ smc_args std_smc_args; - std_smc_args.arg0 = TSP_FID_RESUME; + std_smc_args.fid = TSP_FID_RESUME; smc_ret_values smc_ret = tftf_smc(&std_smc_args); if (smc_ret.ret0 != SMC_UNKNOWN) { tftf_testcase_printf( @@ -427,7 +427,7 @@ static test_result_t test_resume_different_cpu_preempted_std_smc_non_lead_fn(voi * waiting. It has to be different than the one invoked from the lead * CPU. */ - std_smc_args.arg0 = TSP_STD_FID(TSP_MUL); + std_smc_args.fid = TSP_STD_FID(TSP_MUL); std_smc_args.arg1 = TEST_VALUE_1; std_smc_args.arg2 = TEST_VALUE_2; smc_ret = tftf_smc(&std_smc_args); @@ -458,7 +458,7 @@ static test_result_t test_resume_different_cpu_preempted_std_smc_non_lead_fn(voi } /* Resume the STD SMC. Verify result. */ - std_smc_args.arg0 = TSP_FID_RESUME; + std_smc_args.fid = TSP_FID_RESUME; smc_ret = tftf_smc(&std_smc_args); if ((smc_ret.ret0 != 0) || (smc_ret.ret1 != TEST_VALUE_1*TEST_VALUE_1) || (smc_ret.ret2 != TEST_VALUE_2*TEST_VALUE_2)) { @@ -474,7 +474,7 @@ static test_result_t test_resume_different_cpu_preempted_std_smc_non_lead_fn(voi } /* Try to resume the lead CPU STD SMC. Verify result. */ - std_smc_args.arg0 = TSP_FID_RESUME; + std_smc_args.fid = TSP_FID_RESUME; smc_ret = tftf_smc(&std_smc_args); if (smc_ret.ret0 != SMC_UNKNOWN) { tftf_testcase_printf( @@ -536,7 +536,7 @@ test_result_t test_resume_different_cpu_preempted_std_smc(void) * Invoke an STD SMC. Should be pre-empted because of the SGI that is * waiting. */ - std_smc_args.arg0 = TSP_STD_FID(TSP_ADD); + std_smc_args.fid = TSP_STD_FID(TSP_ADD); std_smc_args.arg1 = TEST_VALUE_1; std_smc_args.arg2 = TEST_VALUE_2; smc_ret = tftf_smc(&std_smc_args); @@ -589,7 +589,7 @@ test_result_t test_resume_different_cpu_preempted_std_smc(void) * Try to resume the STD SMC from the lead CPU. It should be able resume * the one it generated before and to return the correct result. */ - std_smc_args.arg0 = TSP_FID_RESUME; + std_smc_args.fid = TSP_FID_RESUME; smc_ret = tftf_smc(&std_smc_args); if ((smc_ret.ret0 != 0) || (smc_ret.ret1 != TEST_VALUE_1 * 2) || (smc_ret.ret2 != TEST_VALUE_2 * 2)) { diff --git a/tftf/tests/runtime_services/trusted_os/tsp/test_irq_spurious_gicv2.c b/tftf/tests/runtime_services/trusted_os/tsp/test_irq_spurious_gicv2.c index 767484014..6eaf0465a 100644 --- a/tftf/tests/runtime_services/trusted_os/tsp/test_irq_spurious_gicv2.c +++ b/tftf/tests/runtime_services/trusted_os/tsp/test_irq_spurious_gicv2.c @@ -70,7 +70,7 @@ static test_result_t test_multicore_spurious_interrupt_non_lead_fn(void) smc_ret_values smc_ret; /* Invoke an STD SMC. */ - std_smc_args.arg0 = TSP_STD_FID(TSP_ADD); + std_smc_args.fid = TSP_STD_FID(TSP_ADD); std_smc_args.arg1 = TEST_VALUE_1; std_smc_args.arg2 = TEST_VALUE_2; smc_ret = tftf_smc(&std_smc_args); @@ -93,7 +93,7 @@ static test_result_t test_multicore_spurious_interrupt_non_lead_fn(void) } } else if (smc_ret.ret0 == TSP_SMC_PREEMPTED) { /* Resume the STD SMC. */ - std_smc_args.arg0 = TSP_FID_RESUME; + std_smc_args.fid = TSP_FID_RESUME; smc_ret = tftf_smc(&std_smc_args); preempted_count[core_pos]++; } else { diff --git a/tftf/tests/runtime_services/trusted_os/tsp/test_normal_int_switch.c b/tftf/tests/runtime_services/trusted_os/tsp/test_normal_int_switch.c index c2223894c..0128ffae8 100644 --- a/tftf/tests/runtime_services/trusted_os/tsp/test_normal_int_switch.c +++ b/tftf/tests/runtime_services/trusted_os/tsp/test_normal_int_switch.c @@ -129,7 +129,7 @@ test_result_t tsp_int_and_resume(void) SKIP_TEST_IF_TSP_NOT_PRESENT(); /* Standard SMC */ - tsp_svc_params.arg0 = TSP_STD_FID(TSP_ADD); + tsp_svc_params.fid = TSP_STD_FID(TSP_ADD); tsp_svc_params.arg1 = 4; tsp_svc_params.arg2 = 6; res = preempt_tsp_via_SGI(&tsp_svc_params, 0); @@ -137,7 +137,7 @@ test_result_t tsp_int_and_resume(void) return res; /* Now that we have ensured preemption, issue RESUME */ - tsp_svc_params.arg0 = TSP_FID_RESUME; + tsp_svc_params.fid = TSP_FID_RESUME; tsp_result = tftf_smc(&tsp_svc_params); /* Check the result of the addition */ @@ -153,7 +153,7 @@ test_result_t tsp_int_and_resume(void) } /* Standard SMC */ - tsp_svc_params.arg0 = TSP_STD_FID(TSP_SUB); + tsp_svc_params.fid = TSP_STD_FID(TSP_SUB); tsp_svc_params.arg1 = 4; tsp_svc_params.arg2 = 6; res = preempt_tsp_via_SGI(&tsp_svc_params, 0); @@ -161,7 +161,7 @@ test_result_t tsp_int_and_resume(void) return res; /* Now that we have ensured preemption, issue RESUME */ - tsp_svc_params.arg0 = TSP_FID_RESUME; + tsp_svc_params.fid = TSP_FID_RESUME; tsp_result = tftf_smc(&tsp_svc_params); /* Check the result of the substraction */ @@ -176,7 +176,7 @@ test_result_t tsp_int_and_resume(void) } /* Standard SMC */ - tsp_svc_params.arg0 = TSP_STD_FID(TSP_MUL); + tsp_svc_params.fid = TSP_STD_FID(TSP_MUL); tsp_svc_params.arg1 = 4; tsp_svc_params.arg2 = 6; res = preempt_tsp_via_SGI(&tsp_svc_params, 0); @@ -184,7 +184,7 @@ test_result_t tsp_int_and_resume(void) return res; /* Now that we have ensured preemption, issue RESUME */ - tsp_svc_params.arg0 = TSP_FID_RESUME; + tsp_svc_params.fid = TSP_FID_RESUME; tsp_result = tftf_smc(&tsp_svc_params); /* Check the result of the multiplication */ @@ -199,7 +199,7 @@ test_result_t tsp_int_and_resume(void) } /* Standard SMC */ - tsp_svc_params.arg0 = TSP_STD_FID(TSP_DIV); + tsp_svc_params.fid = TSP_STD_FID(TSP_DIV); tsp_svc_params.arg1 = 4; tsp_svc_params.arg2 = 6; res = preempt_tsp_via_SGI(&tsp_svc_params, 0); @@ -207,7 +207,7 @@ test_result_t tsp_int_and_resume(void) return res; /* Now that we have ensured preemption, issue RESUME */ - tsp_svc_params.arg0 = TSP_FID_RESUME; + tsp_svc_params.fid = TSP_FID_RESUME; tsp_result = tftf_smc(&tsp_svc_params); /* Check the result of the division */ @@ -241,7 +241,7 @@ test_result_t test_fast_smc_when_tsp_preempted(void) SKIP_TEST_IF_TSP_NOT_PRESENT(); /* Standard SMC */ - tsp_svc_params.arg0 = TSP_STD_FID(TSP_ADD); + tsp_svc_params.fid = TSP_STD_FID(TSP_ADD); tsp_svc_params.arg1 = 4; tsp_svc_params.arg2 = 6; res = preempt_tsp_via_SGI(&tsp_svc_params, 0); @@ -249,7 +249,7 @@ test_result_t test_fast_smc_when_tsp_preempted(void) return res; /* Now that we have ensured preemption, issue Fast SMC */ - tsp_svc_params.arg0 = TSP_FAST_FID(TSP_ADD); + tsp_svc_params.fid = TSP_FAST_FID(TSP_ADD); tsp_svc_params.arg1 = 4; tsp_svc_params.arg2 = 6; @@ -262,7 +262,7 @@ test_result_t test_fast_smc_when_tsp_preempted(void) } /* Issue RESUME */ - tsp_svc_params.arg0 = TSP_FID_RESUME; + tsp_svc_params.fid = TSP_FID_RESUME; tsp_result = tftf_smc(&tsp_svc_params); /* Check the result of the addition */ @@ -302,7 +302,7 @@ static test_result_t test_std_smc_when_tsp_preempted(int abort_smc) SKIP_TEST_IF_TSP_NOT_PRESENT(); /* Standard SMC */ - tsp_svc_params.arg0 = TSP_STD_FID(TSP_ADD); + tsp_svc_params.fid = TSP_STD_FID(TSP_ADD); tsp_svc_params.arg1 = 4; tsp_svc_params.arg2 = 6; res = preempt_tsp_via_SGI(&tsp_svc_params, 0); @@ -310,7 +310,7 @@ static test_result_t test_std_smc_when_tsp_preempted(int abort_smc) return res; /* Now that we have ensured preemption, issue Standard SMC */ - tsp_svc_params.arg0 = TSP_STD_FID(TSP_ADD); + tsp_svc_params.fid = TSP_STD_FID(TSP_ADD); tsp_svc_params.arg1 = 4; tsp_svc_params.arg2 = 6; @@ -322,7 +322,7 @@ static test_result_t test_std_smc_when_tsp_preempted(int abort_smc) } /* Issue ABORT or RESUME */ - tsp_svc_params.arg0 = abort_smc ? TSP_FID_ABORT : TSP_FID_RESUME; + tsp_svc_params.fid = abort_smc ? TSP_FID_ABORT : TSP_FID_RESUME; tsp_result = tftf_smc(&tsp_svc_params); /* @@ -370,7 +370,7 @@ test_result_t test_resume_smc_without_preemption(void) SKIP_TEST_IF_TSP_NOT_PRESENT(); /* Issue RESUME */ - tsp_svc_params.arg0 = TSP_FID_RESUME; + tsp_svc_params.fid = TSP_FID_RESUME; tsp_result = tftf_smc(&tsp_svc_params); if (tsp_result.ret0 != SMC_UNKNOWN) { @@ -403,7 +403,7 @@ test_result_t tsp_int_and_resume_stress(void) while ((count < STRESS_COUNT) && (res == TEST_RESULT_SUCCESS)) { /* Standard SMC */ - tsp_svc_params.arg0 = TSP_STD_FID(TSP_ADD); + tsp_svc_params.fid = TSP_STD_FID(TSP_ADD); tsp_svc_params.arg1 = 4; tsp_svc_params.arg2 = 6; /* Try to preempt TSP via IRQ */ @@ -412,7 +412,7 @@ test_result_t tsp_int_and_resume_stress(void) return res; /* Issue RESUME */ - tsp_svc_params.arg0 = TSP_FID_RESUME; + tsp_svc_params.fid = TSP_FID_RESUME; tsp_result = tftf_smc(&tsp_svc_params); /* Check the result of the addition */ @@ -454,7 +454,7 @@ test_result_t tsp_fiq_while_int(void) SKIP_TEST_IF_TSP_NOT_PRESENT(); /* Standard SMC */ - tsp_svc_params.arg0 = TSP_STD_FID(TSP_ADD); + tsp_svc_params.fid = TSP_STD_FID(TSP_ADD); tsp_svc_params.arg1 = 4; tsp_svc_params.arg2 = 6; res = preempt_tsp_via_SGI(&tsp_svc_params, 1); @@ -462,7 +462,7 @@ test_result_t tsp_fiq_while_int(void) return res; /* Now that we have ensured preemption, issue RESUME */ - tsp_svc_params.arg0 = TSP_FID_RESUME; + tsp_svc_params.fid = TSP_FID_RESUME; tsp_result = tftf_smc(&tsp_svc_params); /* Check the result of the addition */ diff --git a/tftf/tests/runtime_services/trusted_os/tsp/test_smc_tsp_std_fn_call.c b/tftf/tests/runtime_services/trusted_os/tsp/test_smc_tsp_std_fn_call.c index 836367667..6e99309bd 100644 --- a/tftf/tests/runtime_services/trusted_os/tsp/test_smc_tsp_std_fn_call.c +++ b/tftf/tests/runtime_services/trusted_os/tsp/test_smc_tsp_std_fn_call.c @@ -29,7 +29,7 @@ test_result_t test_smc_tsp_std_fns_call(void) SKIP_TEST_IF_TSP_NOT_PRESENT(); /* TrustedOS Service Call Count */ - std_svc_args.arg0 = SMC_TOS_CALL_COUNT; + std_svc_args.fid = SMC_TOS_CALL_COUNT; ret = tftf_smc(&std_svc_args); if (ret.ret0 != TSP_NUM_FID) { tftf_testcase_printf("Wrong Call Count: expected %u,\n" @@ -39,7 +39,7 @@ test_result_t test_smc_tsp_std_fns_call(void) } /* TrustedOS Service Call Revision details */ - std_svc_args.arg0 = SMC_TOS_REVISION; + std_svc_args.fid = SMC_TOS_REVISION; ret = tftf_smc(&std_svc_args); if ((ret.ret0 != TSP_REVISION_MAJOR) || ret.ret1 != TSP_REVISION_MINOR) { diff --git a/tftf/tests/tests-smc.mk b/tftf/tests/tests-smc.mk new file mode 100644 index 000000000..8496cd1de --- /dev/null +++ b/tftf/tests/tests-smc.mk @@ -0,0 +1,7 @@ +# +# Copyright (c) 2018, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +TESTS_SOURCES += tftf/tests/runtime_services/generic/generic_smc.c diff --git a/tftf/tests/tests-smc.xml b/tftf/tests/tests-smc.xml new file mode 100644 index 000000000..56f987dd9 --- /dev/null +++ b/tftf/tests/tests-smc.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + Copyright (c) 2018, Arm Limited. All rights reserved. + + SPDX-License-Identifier: BSD-3-Clause +--> + +<testsuites> + + <testsuite name="SMC calling convention" + description="Test different flavours of the SMC calling convention"> + <testcase name="Fast SMC32" function="smc32_fast" /> + <testcase name="Fast SMC64" function="smc64_fast" /> + <testcase name="Yielding SMC32" function="smc32_yielding" /> + <testcase name="Yielding SMC64" function="smc64_yielding" /> + </testsuite> + +</testsuites> diff --git a/tftf/tests/tests-standard.mk b/tftf/tests/tests-standard.mk index c4d35c609..72c2ec0d0 100644 --- a/tftf/tests/tests-standard.mk +++ b/tftf/tests/tests-standard.mk @@ -16,6 +16,7 @@ TESTS_MAKEFILE := $(addprefix tftf/tests/, \ tests-runtime-instrumentation.mk \ tests-sdei.mk \ tests-single-fault.mk \ + tests-smc.mk \ tests-spm.mk \ tests-template.mk \ tests-tftf-validation.mk \ diff --git a/tftf/tests/tests-standard.xml b/tftf/tests/tests-standard.xml index e2a1a2bd8..a1323d555 100644 --- a/tftf/tests/tests-standard.xml +++ b/tftf/tests/tests-standard.xml @@ -19,6 +19,7 @@ <!ENTITY tests-state-switch SYSTEM "tests-arm-state-switch.xml"> <!ENTITY tests-cpu-extensions SYSTEM "tests-cpu-extensions.xml"> <!ENTITY tests-performance SYSTEM "tests-performance.xml"> + <!ENTITY tests-smc SYSTEM "tests-smc.xml"> ]> <testsuites> @@ -33,5 +34,6 @@ &tests-state-switch; &tests-cpu-extensions; &tests-performance; + &tests-smc; </testsuites> |