diff options
-rw-r--r-- | include/lib/extensions/fpu.h | 53 | ||||
-rw-r--r-- | include/runtime_services/cactus_test_cmds.h | 16 | ||||
-rw-r--r-- | include/runtime_services/spm_common.h | 14 | ||||
-rw-r--r-- | lib/extensions/fpu/fpu.c | 134 | ||||
-rw-r--r-- | spm/cactus/cactus.mk | 4 | ||||
-rw-r--r-- | spm/cactus/cactus_tests/cactus_test_cpu_features.c | 38 | ||||
-rw-r--r-- | tftf/tests/aarch32_tests_to_skip.txt | 2 | ||||
-rw-r--r-- | tftf/tests/runtime_services/secure_service/spm_common.c | 63 | ||||
-rw-r--r-- | tftf/tests/runtime_services/secure_service/test_spm_cpu_features.c | 47 | ||||
-rw-r--r-- | tftf/tests/tests-spm.mk | 14 |
10 files changed, 266 insertions, 119 deletions
diff --git a/include/lib/extensions/fpu.h b/include/lib/extensions/fpu.h new file mode 100644 index 0000000..c803081 --- /dev/null +++ b/include/lib/extensions/fpu.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FPU_H +#define FPU_H + +/* The FPU and SIMD register bank is 32 quadword (128 bits) Q registers. */ +#define FPU_Q_SIZE 16U +#define FPU_Q_COUNT 32U + +/* These defines are needed by assembly code to access FPU registers. */ +#define FPU_OFFSET_Q 0U +#define FPU_OFFSET_FPSR (FPU_Q_SIZE * FPU_Q_COUNT) +#define FPU_OFFSET_FPCR (FPU_OFFSET_FPSR + 8) + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + +typedef struct fpu_reg_state { + uint8_t q[FPU_Q_COUNT][FPU_Q_SIZE]; + unsigned long fpsr; + unsigned long fpcr; +} fpu_reg_state_t; + +/* + * Read and compare FPU state registers with provided template values in parameters. + */ +bool fpu_state_compare_template(fpu_reg_state_t *fpu); + +/* + * Fill the template with random values and copy it to + * FPU state registers(SIMD vectors, FPCR, FPSR). + */ +void fpu_state_fill_regs_and_template(fpu_reg_state_t *fpu); + +/* + * This function populates the provided FPU structure with the provided template + * regs_val for all the 32 FPU/SMID registers, and the status registers FPCR/FPSR + */ +void fpu_state_set(fpu_reg_state_t *vec, + uint8_t regs_val); + +/* + * This function prints the content of the provided FPU structure + */ +void fpu_state_print(fpu_reg_state_t *vec); + +#endif /* __ASSEMBLER__ */ +#endif /* FPU_H */ diff --git a/include/runtime_services/cactus_test_cmds.h b/include/runtime_services/cactus_test_cmds.h index e52f333..9dc0d90 100644 --- a/include/runtime_services/cactus_test_cmds.h +++ b/include/runtime_services/cactus_test_cmds.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * Copyright (c) 2021-2023, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -283,6 +283,20 @@ static inline struct ffa_value cactus_req_simd_fill_send_cmd( } /** + * Request to compare FPU state(SIMD vectors, FPCR, FPSR) content + * with previous template values to check a save/restore routine during the + * context switches between secure world and normal world. + */ +#define CACTUS_CMP_SIMD_VALUE_CMD (CACTUS_REQ_SIMD_FILL_CMD + 1) + +static inline struct ffa_value cactus_req_simd_compare_send_cmd( + ffa_id_t source, ffa_id_t dest) +{ + return cactus_send_cmd(source, dest, CACTUS_CMP_SIMD_VALUE_CMD, 0, 0, 0, + 0); +} + +/** * Command to request cactus to sleep for the given time in ms * * The command id is the hex representation of string "sleep" diff --git a/include/runtime_services/spm_common.h b/include/runtime_services/spm_common.h index 6fe445a..7f47dc7 100644 --- a/include/runtime_services/spm_common.h +++ b/include/runtime_services/spm_common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * Copyright (c) 2021-2023, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -97,27 +97,15 @@ bool is_expected_cactus_response(struct ffa_value ret, uint32_t expected_resp, void dump_ffa_value(struct ffa_value ret); /* - * Max. vector length: - * SIMD: 128 bits = 16 bytes - */ -#define SIMD_VECTOR_LEN_BYTES 16 - -#define SIMD_NUM_VECTORS 32 - -typedef uint8_t simd_vector_t[SIMD_VECTOR_LEN_BYTES]; - -/* * Fills SIMD/SVE registers with the content of the container v. * Number of vectors is assumed to be SIMD/SVE_NUM_VECTORS. */ -void fill_simd_vector_regs(const simd_vector_t v[SIMD_NUM_VECTORS]); void fill_sve_vector_regs(const sve_vector_t v[SVE_NUM_VECTORS]); /* * Reads contents of SIMD/SVE registers into the provided container v. * Number of vectors is assumed to be SIMD/SVE_NUM_VECTORS. */ -void read_simd_vector_regs(simd_vector_t v[SIMD_NUM_VECTORS]); void read_sve_vector_regs(sve_vector_t v[SVE_NUM_VECTORS]); bool check_spmc_execution_level(void); diff --git a/lib/extensions/fpu/fpu.c b/lib/extensions/fpu/fpu.c new file mode 100644 index 0000000..da887b3 --- /dev/null +++ b/lib/extensions/fpu/fpu.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2023, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + +#include <debug.h> +#include <lib/extensions/fpu.h> + +#define __STR(x) #x +#define STR(x) __STR(x) + +#define fill_simd_helper(num1, num2) "ldp q"#num1", q"#num2",\ + [%0], #"STR(2 * FPU_Q_SIZE)";" +#define read_simd_helper(num1, num2) "stp q"#num1", q"#num2",\ + [%0], #"STR(2 * FPU_Q_SIZE)";" + +static fpu_reg_state_t g_fpu_read; + +static void read_fpu_state_registers(fpu_reg_state_t *fpu_template_in) +{ +#ifdef __aarch64__ + + u_register_t fpsr; + u_register_t fpcr; + + /* Read current FPCR FPSR and write to template. */ + __asm__ volatile ("mrs %0, fpsr\n" : "=r" (fpsr)); + __asm__ volatile ("mrs %0, fpcr\n" : "=r" (fpcr)); + fpu_template_in->fpsr = fpsr; + fpu_template_in->fpcr = fpcr; + + __asm__ volatile( + read_simd_helper(0, 1) + read_simd_helper(2, 3) + read_simd_helper(4, 5) + read_simd_helper(6, 7) + read_simd_helper(8, 9) + read_simd_helper(10, 11) + read_simd_helper(12, 13) + read_simd_helper(14, 15) + read_simd_helper(16, 17) + read_simd_helper(18, 19) + read_simd_helper(20, 21) + read_simd_helper(22, 23) + read_simd_helper(24, 25) + read_simd_helper(26, 27) + read_simd_helper(28, 29) + read_simd_helper(30, 31) + "sub %0, %0, #" STR(FPU_Q_COUNT * FPU_Q_SIZE) ";" + : : "r" (fpu_template_in->q)); +#endif +} + +void fpu_state_fill_regs_and_template(fpu_reg_state_t *fpu_template_in) +{ + u_register_t fpsr; + u_register_t fpcr; + u_register_t temp; + + temp = rand(); + (void)memset((void *)fpu_template_in, 0, sizeof(fpu_reg_state_t)); + + /* + * Write random value to FPCR FPSR. + * Note write will be ignored for reserved bits. + */ + __asm__ volatile ("mrs %0, fpsr\n" : "=r" (temp)); + __asm__ volatile ("mrs %0, fpcr\n" : "=r" (temp)); + + /* + * Read back current FPCR FPSR and write to template, + */ + __asm__ volatile ("mrs %0, fpsr\n" : "=r" (fpsr)); + __asm__ volatile ("mrs %0, fpcr\n" : "=r" (fpcr)); + fpu_template_in->fpsr = fpsr; + fpu_template_in->fpcr = fpcr; + + for (unsigned int num = 0U; num < FPU_Q_COUNT; num++) { + memset((uint8_t *)fpu_template_in->q[num], temp * num, + sizeof(fpu_template_in->q[0])); + } + __asm__ volatile( + fill_simd_helper(0, 1) + fill_simd_helper(2, 3) + fill_simd_helper(4, 5) + fill_simd_helper(6, 7) + fill_simd_helper(8, 9) + fill_simd_helper(10, 11) + fill_simd_helper(12, 13) + fill_simd_helper(14, 15) + fill_simd_helper(16, 17) + fill_simd_helper(18, 19) + fill_simd_helper(20, 21) + fill_simd_helper(22, 23) + fill_simd_helper(24, 25) + fill_simd_helper(26, 27) + fill_simd_helper(28, 29) + fill_simd_helper(30, 31) + "sub %0, %0, #" STR(FPU_Q_COUNT * FPU_Q_SIZE) ";" + : : "r" (fpu_template_in->q)); +} + +void fpu_state_print(fpu_reg_state_t *vec) +{ + INFO("dumping FPU registers :\n"); + for (unsigned int num = 0U; num < FPU_Q_COUNT; num++) { + INFO("Q[%u]=0x%llx%llx\n", num, (uint64_t)vec->q[num * FPU_Q_SIZE], + (uint64_t)(vec->q[num * FPU_Q_SIZE + 1])); + } + INFO("FPCR=0x%lx FPSR=0x%lx\n", vec->fpcr, vec->fpsr); +} + +bool fpu_state_compare_template(fpu_reg_state_t *fpu_template_in) +{ + (void)memset((void *)&g_fpu_read, 0, sizeof(fpu_reg_state_t)); + read_fpu_state_registers(&g_fpu_read); + + if (memcmp((uint8_t *)fpu_template_in, + (uint8_t *)&g_fpu_read, + sizeof(fpu_reg_state_t)) != 0U) { + ERROR("%s failed\n", __func__); + ERROR("Read values\n"); + fpu_state_print(&g_fpu_read); + ERROR("Template values\n"); + fpu_state_print(fpu_template_in); + return false; + } else { + return true; + } +} diff --git a/spm/cactus/cactus.mk b/spm/cactus/cactus.mk index c3bbe59..be8997e 100644 --- a/spm/cactus/cactus.mk +++ b/spm/cactus/cactus.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2018-2022, Arm Limited. All rights reserved. +# Copyright (c) 2018-2023, Arm Limited. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -22,6 +22,7 @@ CACTUS_INCLUDES := \ -Iinclude/common \ -Iinclude/common/${ARCH} \ -Iinclude/lib \ + -Iinclude/lib/extensions \ -Iinclude/lib/${ARCH} \ -Iinclude/lib/utils \ -Iinclude/lib/xlat_tables \ @@ -75,6 +76,7 @@ CACTUS_SOURCES += drivers/arm/pl011/${ARCH}/pl011_console.S \ lib/exceptions/${ARCH}/sync.c \ lib/locks/${ARCH}/spinlock.S \ lib/utils/mp_printf.c \ + lib/extensions/fpu/fpu.c \ ${XLAT_TABLES_LIB_SRCS} CACTUS_LINKERFILE := spm/cactus/cactus.ld.S diff --git a/spm/cactus/cactus_tests/cactus_test_cpu_features.c b/spm/cactus/cactus_tests/cactus_test_cpu_features.c index 7bf6e83..78b89ac 100644 --- a/spm/cactus/cactus_tests/cactus_test_cpu_features.c +++ b/spm/cactus/cactus_tests/cactus_test_cpu_features.c @@ -1,29 +1,45 @@ /* - * Copyright (c) 2021, Arm Limited. All rights reserved. + * Copyright (c) 2023, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include "cactus_message_loop.h" #include "cactus_test_cmds.h" +#include <fpu.h> #include "spm_common.h" /* + * Note Test must exercise FILL and COMPARE command in + * sequence and on same CPU. + */ +static fpu_reg_state_t g_fpu_temp; +static unsigned int core_pos; +/* * Fill SIMD vectors from secure world side with a unique value. - * 0x22 is just a dummy value to be distinguished from the value - * in the normal world. */ CACTUS_CMD_HANDLER(req_simd_fill, CACTUS_REQ_SIMD_FILL_CMD) { - simd_vector_t simd_vectors[SIMD_NUM_VECTORS]; - - for (unsigned int num = 0U; num < SIMD_NUM_VECTORS; num++) { - memset(simd_vectors[num], 0x22 * num, sizeof(simd_vector_t)); - } - - fill_simd_vector_regs(simd_vectors); - + core_pos = platform_get_core_pos(read_mpidr_el1()); + fpu_state_fill_regs_and_template(&g_fpu_temp); return cactus_response(ffa_dir_msg_dest(*args), ffa_dir_msg_source(*args), CACTUS_SUCCESS); } + +/* + * compare FPU state(SIMD vectors, FPCR, FPSR) from secure world side with the previous + * SIMD_SECURE_VALUE unique value. + */ +CACTUS_CMD_HANDLER(req_simd_compare, CACTUS_CMP_SIMD_VALUE_CMD) +{ + bool test_succeed = false; + + unsigned int core_pos1 = platform_get_core_pos(read_mpidr_el1()); + if (core_pos1 == core_pos) { + test_succeed = fpu_state_compare_template(&g_fpu_temp); + } + return cactus_response(ffa_dir_msg_dest(*args), + ffa_dir_msg_source(*args), + test_succeed ? CACTUS_SUCCESS : CACTUS_ERROR); +} diff --git a/tftf/tests/aarch32_tests_to_skip.txt b/tftf/tests/aarch32_tests_to_skip.txt index cdc298d..9ccc1b5 100644 --- a/tftf/tests/aarch32_tests_to_skip.txt +++ b/tftf/tests/aarch32_tests_to_skip.txt @@ -4,4 +4,4 @@ # SPDX-License-Identifier: BSD-3-Clause # Realm payload at EL1 - +SIMD,SVE Registers context diff --git a/tftf/tests/runtime_services/secure_service/spm_common.c b/tftf/tests/runtime_services/secure_service/spm_common.c index ae30ebc..60b77b8 100644 --- a/tftf/tests/runtime_services/secure_service/spm_common.c +++ b/tftf/tests/runtime_services/secure_service/spm_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * Copyright (c) 2021-2023, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -12,14 +12,6 @@ #include <spm_common.h> #include <xlat_tables_v2.h> -#define __STR(x) #x -#define STR(x) __STR(x) - -#define fill_simd_helper(num1, num2) "ldp q"#num1", q"#num2",\ - [%0], #"STR(2 * SIMD_VECTOR_LEN_BYTES)";" -#define read_simd_helper(num1, num2) "stp q"#num1", q"#num2",\ - [%0], #"STR(2 * SIMD_VECTOR_LEN_BYTES)";" - /** * Helper to log errors after FF-A calls. */ @@ -111,57 +103,6 @@ void dump_ffa_value(struct ffa_value ret) ret.arg7); } -void fill_simd_vector_regs(const simd_vector_t v[SIMD_NUM_VECTORS]) -{ -#ifdef __aarch64__ - __asm__ volatile( - fill_simd_helper(0, 1) - fill_simd_helper(2, 3) - fill_simd_helper(4, 5) - fill_simd_helper(6, 7) - fill_simd_helper(8, 9) - fill_simd_helper(10, 11) - fill_simd_helper(12, 13) - fill_simd_helper(14, 15) - fill_simd_helper(16, 17) - fill_simd_helper(18, 19) - fill_simd_helper(20, 21) - fill_simd_helper(22, 23) - fill_simd_helper(24, 25) - fill_simd_helper(26, 27) - fill_simd_helper(28, 29) - fill_simd_helper(30, 31) - "sub %0, %0, #" STR(SIMD_NUM_VECTORS * SIMD_VECTOR_LEN_BYTES) ";" - : : "r" (v)); -#endif -} - -void read_simd_vector_regs(simd_vector_t v[SIMD_NUM_VECTORS]) -{ -#ifdef __aarch64__ - memset(v, 0, sizeof(simd_vector_t) * SIMD_NUM_VECTORS); - __asm__ volatile( - read_simd_helper(0, 1) - read_simd_helper(2, 3) - read_simd_helper(4, 5) - read_simd_helper(6, 7) - read_simd_helper(8, 9) - read_simd_helper(10, 11) - read_simd_helper(12, 13) - read_simd_helper(14, 15) - read_simd_helper(16, 17) - read_simd_helper(18, 19) - read_simd_helper(20, 21) - read_simd_helper(22, 23) - read_simd_helper(24, 25) - read_simd_helper(26, 27) - read_simd_helper(28, 29) - read_simd_helper(30, 31) - "sub %0, %0, #" STR(SIMD_NUM_VECTORS * SIMD_VECTOR_LEN_BYTES) ";" - : : "r" (v)); -#endif -} - void fill_sve_vector_regs(const sve_vector_t v[SVE_NUM_VECTORS]) { #ifdef __aarch64__ @@ -642,4 +583,4 @@ bool enable_trusted_wdog_interrupt(ffa_id_t source, ffa_id_t dest) bool disable_trusted_wdog_interrupt(ffa_id_t source, ffa_id_t dest) { return configure_trusted_wdog_interrupt(source, dest, false); -}
\ No newline at end of file +} diff --git a/tftf/tests/runtime_services/secure_service/test_spm_cpu_features.c b/tftf/tests/runtime_services/secure_service/test_spm_cpu_features.c index a230d56..8cb54f7 100644 --- a/tftf/tests/runtime_services/secure_service/test_spm_cpu_features.c +++ b/tftf/tests/runtime_services/secure_service/test_spm_cpu_features.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * Copyright (c) 2021-2023, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,6 +7,7 @@ #include <cactus_test_cmds.h> #include <ffa_endpoints.h> #include <ffa_helpers.h> +#include <fpu.h> #include <test_helpers.h> #define SENDER HYP_ID @@ -28,18 +29,18 @@ static test_result_t fp_vector_compare(uint8_t *a, uint8_t *b, return TEST_RESULT_SUCCESS; } -#ifdef __aarch64__ static sve_vector_t sve_vectors_input[SVE_NUM_VECTORS] __aligned(16); static sve_vector_t sve_vectors_output[SVE_NUM_VECTORS] __aligned(16); static int sve_op_1[SVE_ARRAYSIZE]; static int sve_op_2[SVE_ARRAYSIZE]; -#endif +static fpu_reg_state_t g_fpu_template; /* - * Tests that SIMD vectors are preserved during the context switches between + * Tests that SIMD vectors and FPU state are preserved during the context switches between * normal world and the secure world. - * Fills the SIMD vectors with known values, requests SP to fill the vectors - * with a different values, checks that the context is restored on return. + * Fills the SIMD vectors, FPCR and FPSR with random values, requests SP to fill the vectors + * with a different values, request SP to check if secure SIMD context is restored. + * Checks that the NS context is restored on return. */ test_result_t test_simd_vectors_preserved(void) { @@ -48,16 +49,7 @@ test_result_t test_simd_vectors_preserved(void) **********************************************************************/ CHECK_SPMC_TESTING_SETUP(1, 1, expected_sp_uuids); - simd_vector_t simd_vectors_send[SIMD_NUM_VECTORS], - simd_vectors_receive[SIMD_NUM_VECTORS]; - - /* 0x11 is just a dummy value to be distinguished from the value in the - * secure world. */ - for (unsigned int num = 0U; num < SIMD_NUM_VECTORS; num++) { - memset(simd_vectors_send[num], 0x11 * (num+1), sizeof(simd_vector_t)); - } - fill_simd_vector_regs(simd_vectors_send); - + fpu_state_fill_regs_and_template(&g_fpu_template); struct ffa_value ret = cactus_req_simd_fill_send_cmd(SENDER, RECEIVER); if (!is_ffa_direct_response(ret)) { @@ -68,11 +60,18 @@ test_result_t test_simd_vectors_preserved(void) return TEST_RESULT_FAIL; } - read_simd_vector_regs(simd_vectors_receive); + ret = cactus_req_simd_compare_send_cmd(SENDER, RECEIVER); - return fp_vector_compare((uint8_t *)simd_vectors_send, - (uint8_t *)simd_vectors_receive, - sizeof(simd_vector_t), SIMD_NUM_VECTORS); + if (!is_ffa_direct_response(ret)) { + return TEST_RESULT_FAIL; + } + + if (cactus_get_response(ret) == CACTUS_ERROR) { + return TEST_RESULT_FAIL; + } + /* Normal world verify its FPU/SIMD state registers data */ + return fpu_state_compare_template(&g_fpu_template) ? TEST_RESULT_SUCCESS : + TEST_RESULT_FAIL; } /* @@ -83,7 +82,6 @@ test_result_t test_simd_vectors_preserved(void) */ test_result_t test_sve_vectors_preserved(void) { -#ifdef __aarch64__ uint64_t vl; uint8_t *sve_vector; @@ -139,9 +137,6 @@ test_result_t test_sve_vectors_preserved(void) return fp_vector_compare((uint8_t *)sve_vectors_input, (uint8_t *)sve_vectors_output, vl, SVE_NUM_VECTORS); -#else - return TEST_RESULT_SKIPPED; -#endif /* __aarch64__ */ } /* @@ -150,7 +145,6 @@ test_result_t test_sve_vectors_preserved(void) */ test_result_t test_sve_vectors_operations(void) { -#ifdef __aarch64__ unsigned int val; SKIP_TEST_IF_SVE_NOT_SUPPORTED(); @@ -184,7 +178,4 @@ test_result_t test_sve_vectors_operations(void) } return TEST_RESULT_SUCCESS; -#else - return TEST_RESULT_SKIPPED; -#endif /* __aarch64__ */ } diff --git a/tftf/tests/tests-spm.mk b/tftf/tests/tests-spm.mk index 8f44f14..fccddb4 100644 --- a/tftf/tests/tests-spm.mk +++ b/tftf/tests/tests-spm.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2018-2022, Arm Limited. All rights reserved. +# Copyright (c) 2018-2023, Arm Limited. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -18,14 +18,22 @@ TESTS_SOURCES += \ test_ffa_memory_sharing.c \ test_ffa_setup_and_discovery.c \ test_ffa_notifications.c \ - test_spm_cpu_features.c \ test_spm_smmu.c \ test_ffa_exceptions.c \ - sve_operations_cactus.S \ ) +ifeq (${ARCH},aarch64) +TESTS_SOURCES += \ + $(addprefix tftf/tests/runtime_services/secure_service/, \ + test_spm_cpu_features.c \ + sve_operations_cactus.S \ + ) + TESTS_SOURCES += \ $(addprefix tftf/tests/runtime_services/host_realm_managment/, \ host_realm_rmi.c \ host_realm_helper.c \ ) + +TESTS_SOURCES += lib/extensions/fpu/fpu.c +endif |