diff options
Diffstat (limited to 'tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c')
-rw-r--r-- | tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c | 245 |
1 files changed, 204 insertions, 41 deletions
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c b/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c index 6008b7800..1f8e81c1e 100644 --- a/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c +++ b/tftf/tests/runtime_services/secure_service/test_ffa_direct_messaging.c @@ -1,45 +1,50 @@ /* - * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * Copyright (c) 2018-2022, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ -#include <arch_helpers.h> -#include <cactus_def.h> -#include <platform.h> +#include <debug.h> #include <smccc.h> -#include <ffa_helpers.h> + +#include <arch_helpers.h> +#include <cactus_test_cmds.h> +#include <ffa_endpoints.h> #include <ffa_svc.h> +#include <lib/events.h> +#include <lib/power_management.h> +#include <platform.h> +#include <spm_test_helpers.h> #include <test_helpers.h> -#define DIRECT_MSG_TEST_PATTERN1 (0xaaaa0000) -#define DIRECT_MSG_TEST_PATTERN2 (0xbbbb0000) -#define DIRECT_MSG_TEST_PATTERN3 (0xcccc0000) +#define ECHO_VAL1 U(0xa0a0a0a0) +#define ECHO_VAL2 U(0xb0b0b0b0) +#define ECHO_VAL3 U(0xc0c0c0c0) -static test_result_t send_receive_direct_msg(unsigned int sp_id, - unsigned int test_pattern) -{ - smc_ret_values ret_values; +static const struct ffa_uuid expected_sp_uuids[] = { + {PRIMARY_UUID}, {SECONDARY_UUID}, {TERTIARY_UUID} + }; - /* Send a message to SP through direct messaging */ - ret_values = ffa_msg_send_direct_req(HYP_ID, SP_ID(sp_id), - test_pattern); +static event_t cpu_booted[PLATFORM_CORE_COUNT]; + +static test_result_t send_cactus_echo_cmd(ffa_id_t sender, + ffa_id_t dest, + uint64_t value) +{ + struct ffa_value ret; + ret = cactus_echo_send_cmd(sender, dest, value); /* * Return responses may be FFA_MSG_SEND_DIRECT_RESP or FFA_INTERRUPT, * but only expect the former. Expect SMC32 convention from SP. */ - if (ret_values.ret0 != FFA_MSG_SEND_DIRECT_RESP_SMC32) { - tftf_testcase_printf("ffa_msg_send_direct_req returned %lx\n", - (u_register_t)ret_values.ret0); + if (!is_ffa_direct_response(ret)) { return TEST_RESULT_FAIL; } - /* - * Message loop in SP returns initial message with the running VM id - * into the lower 16 bits of initial message. - */ - if (ret_values.ret3 != (test_pattern | sp_id)) { + if (cactus_get_response(ret) != CACTUS_SUCCESS || + cactus_echo_get_val(ret) != value) { + ERROR("Echo Failed!\n"); return TEST_RESULT_FAIL; } @@ -51,26 +56,14 @@ test_result_t test_ffa_direct_messaging(void) test_result_t result; /********************************************************************** - * Verify that FFA is there and that it has the correct version. + * Check SPMC has ffa_version and expected FFA endpoints are deployed. **********************************************************************/ - SKIP_TEST_IF_FFA_VERSION_LESS_THAN(1, 0); - - /* Check if SPMC is OP-TEE at S-EL1 */ - if (check_spmc_execution_level()) { - /* Direct messaging is successfully verified for OP-TEE */ - return TEST_RESULT_SUCCESS; - } - - /* - * From this point assume SPMC runs at S-EL2 and two Cactus instances - * are loaded at S-EL1. - * - */ + CHECK_SPMC_TESTING_SETUP(1, 0, expected_sp_uuids); /********************************************************************** * Send a message to SP1 through direct messaging **********************************************************************/ - result = send_receive_direct_msg(1, DIRECT_MSG_TEST_PATTERN1); + result = send_cactus_echo_cmd(HYP_ID, SP_ID(1), ECHO_VAL1); if (result != TEST_RESULT_SUCCESS) { return result; } @@ -78,7 +71,7 @@ test_result_t test_ffa_direct_messaging(void) /********************************************************************** * Send a message to SP2 through direct messaging **********************************************************************/ - result = send_receive_direct_msg(2, DIRECT_MSG_TEST_PATTERN2); + result = send_cactus_echo_cmd(HYP_ID, SP_ID(2), ECHO_VAL2); if (result != TEST_RESULT_SUCCESS) { return result; } @@ -86,13 +79,183 @@ test_result_t test_ffa_direct_messaging(void) /********************************************************************** * Send a message to SP1 through direct messaging **********************************************************************/ - result = send_receive_direct_msg(1, DIRECT_MSG_TEST_PATTERN3); + result = send_cactus_echo_cmd(HYP_ID, SP_ID(1), ECHO_VAL3); + + return result; +} + +/** + * The 'send_cactus_req_echo_cmd' sends a CACTUS_REQ_ECHO_CMD to a cactus SP. + * Handling this command, cactus should then send CACTUS_ECHO_CMD to + * the specified SP according to 'echo_dest'. If the CACTUS_ECHO_CMD is resolved + * successfully, cactus will reply to tftf with CACTUS_SUCCESS, or CACTUS_ERROR + * otherwise. + * For the CACTUS_SUCCESS response, the test returns TEST_RESULT_SUCCESS. + */ +static test_result_t send_cactus_req_echo_cmd(ffa_id_t sender, + ffa_id_t dest, + ffa_id_t echo_dest, + uint64_t value) +{ + struct ffa_value ret; + + ret = cactus_req_echo_send_cmd(sender, dest, echo_dest, value); + + if (!is_ffa_direct_response(ret)) { + return TEST_RESULT_FAIL; + } + + if (cactus_get_response(ret) == CACTUS_ERROR) { + return TEST_RESULT_FAIL; + } + + return TEST_RESULT_SUCCESS; +} + +test_result_t test_ffa_sp_to_sp_direct_messaging(void) +{ + test_result_t result; + + CHECK_SPMC_TESTING_SETUP(1, 0, expected_sp_uuids); + + result = send_cactus_req_echo_cmd(HYP_ID, SP_ID(1), SP_ID(2), + ECHO_VAL1); + if (result != TEST_RESULT_SUCCESS) { + return result; + } + + /* + * The following the tests are intended to test the handling of a + * direct message request with a VM's ID as a the sender. + */ + result = send_cactus_req_echo_cmd(VM_ID(1), SP_ID(2), SP_ID(3), + ECHO_VAL2); if (result != TEST_RESULT_SUCCESS) { return result; } + result = send_cactus_req_echo_cmd(VM_ID(2), SP_ID(3), SP_ID(1), + ECHO_VAL3); + + return result; +} + +test_result_t test_ffa_sp_to_sp_deadlock(void) +{ + struct ffa_value ret; + /********************************************************************** - * All tests passed. + * Check SPMC has ffa_version and expected FFA endpoints are deployed. **********************************************************************/ + CHECK_SPMC_TESTING_SETUP(1, 0, expected_sp_uuids); + + ret = cactus_req_deadlock_send_cmd(HYP_ID, SP_ID(1), SP_ID(2), SP_ID(3)); + + if (is_ffa_direct_response(ret) == false) { + return TEST_RESULT_FAIL; + } + + if (cactus_get_response(ret) == CACTUS_ERROR) { + return TEST_RESULT_FAIL; + } + return TEST_RESULT_SUCCESS; } + +/** + * Handler that is passed during tftf_cpu_on to individual CPU cores. + * Runs a specific core and send a direct message request. + */ +static test_result_t cpu_on_handler(void) +{ + unsigned int core_pos = get_current_core_id(); + test_result_t ret = TEST_RESULT_SUCCESS; + struct ffa_value ffa_ret; + + /* + * Send a direct message request to SP1 (MP SP) from current physical + * CPU. Notice SP1 ECs are already woken as a result of the PSCI_CPU_ON + * invocation so they already reached the message loop. + * The SPMC uses the MP pinned context corresponding to the physical + * CPU emitting the request. + */ + ret = send_cactus_echo_cmd(HYP_ID, SP_ID(1), ECHO_VAL1); + if (ret != TEST_RESULT_SUCCESS) { + goto out; + } + + /* + * Secure Partitions beyond the first SP only have their first + * EC (or vCPU0) woken up at boot time by the SPMC. + * Other ECs need one round of ffa_run to reach the message loop. + */ + ffa_ret = ffa_run(SP_ID(2), core_pos); + if (ffa_func_id(ffa_ret) != FFA_MSG_WAIT) { + ERROR("Failed to run SP%x on core %u\n", SP_ID(2), + core_pos); + ret = TEST_RESULT_FAIL; + goto out; + } + + /* + * Send a direct message request to SP2 (MP SP) from current physical + * CPU. The SPMC uses the MP pinned context corresponding to the + * physical CPU emitting the request. + */ + ret = send_cactus_echo_cmd(HYP_ID, SP_ID(2), ECHO_VAL2); + if (ret != TEST_RESULT_SUCCESS) { + goto out; + } + + /* + * Send a direct message request to SP3 (UP SP) from current physical CPU. + * The SPMC uses the single vCPU migrated to the new physical core. + * The single SP vCPU may receive requests from multiple physical CPUs. + * Thus it is possible one message is being processed on one core while + * another (or multiple) cores attempt sending a new direct message + * request. In such case the cores attempting the new request receive + * a busy response from the SPMC. To handle this case a retry loop is + * implemented permitting some fairness. + */ + uint32_t trial_loop = 5U; + while (trial_loop--) { + ffa_ret = cactus_echo_send_cmd(HYP_ID, SP_ID(3), ECHO_VAL3); + if ((ffa_func_id(ffa_ret) == FFA_ERROR) && + (ffa_error_code(ffa_ret) == FFA_ERROR_BUSY)) { + VERBOSE("%s(%u) trial %u\n", __func__, core_pos, trial_loop); + waitms(1); + continue; + } + + if (is_ffa_direct_response(ffa_ret) == true) { + if (cactus_get_response(ffa_ret) != CACTUS_SUCCESS || + cactus_echo_get_val(ffa_ret) != ECHO_VAL3) { + ERROR("Echo Failed!\n"); + ret = TEST_RESULT_FAIL; + } + + goto out; + } + } + + ret = TEST_RESULT_FAIL; + +out: + /* Tell the lead CPU that the calling CPU has completed the test */ + tftf_send_event(&cpu_booted[core_pos]); + + return ret; +} + +/** + * Test direct messaging in multicore setup. Runs SPs on all the cores and sends + * direct messages to SPs. + */ +test_result_t test_ffa_secondary_core_direct_msg(void) +{ + /********************************************************************** + * Check SPMC has ffa_version and expected FFA endpoints are deployed. + **********************************************************************/ + CHECK_SPMC_TESTING_SETUP(1, 0, expected_sp_uuids); + return spm_run_multi_core_test((uintptr_t)cpu_on_handler, cpu_booted); +} |