diff options
-rw-r--r-- | include/common/test_helpers.h | 11 | ||||
-rw-r--r-- | include/runtime_services/spci_helpers.h | 32 | ||||
-rw-r--r-- | tftf/tests/runtime_services/secure_service/spci_helpers.c | 227 | ||||
-rw-r--r-- | tftf/tests/runtime_services/secure_service/test_spci_direct_messaging.c | 107 | ||||
-rw-r--r-- | tftf/tests/tests-spm.mk | 9 | ||||
-rw-r--r-- | tftf/tests/tests-spm.xml | 22 |
6 files changed, 203 insertions, 205 deletions
diff --git a/include/common/test_helpers.h b/include/common/test_helpers.h index a90fd715f..5c0f090e5 100644 --- a/include/common/test_helpers.h +++ b/include/common/test_helpers.h @@ -147,14 +147,19 @@ typedef test_result_t (*test_function_arg_t)(void *arg); do { \ smc_args version_smc = { SPCI_VERSION }; \ smc_ret_values smc_ret = tftf_smc(&version_smc); \ - uint32_t version = smc_ret.ret0; \ + uint32_t version = smc_ret.ret2; \ \ - if (version == SMC_UNKNOWN) { \ + if (smc_ret.ret0 != SPCI_SUCCESS_SMC32) { \ tftf_testcase_printf("SPM not detected.\n"); \ return TEST_RESULT_SKIPPED; \ } \ + \ + if ((version & SPCI_VERSION_BIT31_MASK) != 0) { \ + tftf_testcase_printf("SPCI_VERSION bad response.\n"); \ + return TEST_RESULT_SKIPPED; \ + } \ \ - if (version < SPCI_VERSION_FORM(major, minor)) { \ + if (version < MAKE_SPCI_VERSION(major, minor)) { \ tftf_testcase_printf("SPCI_VERSION returned %d.%d\n" \ "The required version is %d.%d\n", \ version >> SPCI_VERSION_MAJOR_SHIFT,\ diff --git a/include/runtime_services/spci_helpers.h b/include/runtime_services/spci_helpers.h index a64591e71..cfc3a5ff4 100644 --- a/include/runtime_services/spci_helpers.h +++ b/include/runtime_services/spci_helpers.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Arm Limited. All rights reserved. + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,41 +7,19 @@ #ifndef SPCI_HELPERS_H #define SPCI_HELPERS_H +#include <tftf_lib.h> #include <utils_def.h> /* This error code must be different to the ones used by SPCI */ #define SPCI_TFTF_ERROR -42 -/* Client ID used for SPCI calls */ -#define TFTF_SPCI_CLIENT_ID U(0x00007F7F) - #ifndef __ASSEMBLY__ #include <stdint.h> -int spci_service_handle_open(uint16_t client_id, uint16_t *handle, - uint32_t uuid1, uint32_t uuid2, - uint32_t uuid3, uint32_t uuid4); -int spci_service_handle_close(uint16_t client_id, uint16_t handle); - -int spci_service_request_start(u_register_t x1, u_register_t x2, - u_register_t x3, u_register_t x4, - u_register_t x5, u_register_t x6, - uint16_t client_id, uint16_t handle, - uint32_t *token); -int spci_service_request_resume(uint16_t client_id, uint16_t handle, - uint32_t token, u_register_t *x1, - u_register_t *x2, u_register_t *x3); -int spci_service_get_response(uint16_t client_id, uint16_t handle, - uint32_t token, u_register_t *x1, - u_register_t *x2, u_register_t *x3); - -int spci_service_request_blocking(u_register_t x1, u_register_t x2, - u_register_t x3, u_register_t x4, - u_register_t x5, u_register_t x6, - uint16_t client_id, uint16_t handle, - u_register_t *rx1, u_register_t *rx2, - u_register_t *rx3); +smc_ret_values spci_msg_send_direct_req(uint32_t source_id, uint32_t dest_id, uint32_t message); +smc_ret_values spci_msg_send_direct_req64(uint32_t source_id, uint32_t dest_id, uint64_t message); +smc_ret_values spci_run(uint32_t dest_id, uint32_t vcpu_id); #endif /* __ASSEMBLY__ */ diff --git a/tftf/tests/runtime_services/secure_service/spci_helpers.c b/tftf/tests/runtime_services/secure_service/spci_helpers.c index 268c26f6f..1370a3877 100644 --- a/tftf/tests/runtime_services/secure_service/spci_helpers.c +++ b/tftf/tests/runtime_services/secure_service/spci_helpers.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Arm Limited. All rights reserved. + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -8,172 +8,101 @@ #include <smccc.h> #include <spci_helpers.h> #include <spci_svc.h> -#include <tftf_lib.h> -/* Returns a SPCI error code. On success, it also returns a 16 bit handle. */ -int spci_service_handle_open(uint16_t client_id, uint16_t *handle, - uint32_t uuid1, uint32_t uuid2, - uint32_t uuid3, uint32_t uuid4) -{ - int32_t ret; - - smc_args get_handle_smc_args = { - SPCI_SERVICE_HANDLE_OPEN, - uuid1, uuid2, uuid3, uuid4, - 0, 0, /* Reserved - MBZ */ - client_id - }; - - smc_ret_values smc_ret = tftf_smc(&get_handle_smc_args); - - ret = smc_ret.ret0; - if (ret != SPCI_SUCCESS) - return ret; - - uint32_t x1 = smc_ret.ret1; - - if ((x1 & 0x0000FFFF) != 0) { - tftf_testcase_printf("SPCI_SERVICE_HANDLE_OPEN returned x1 = 0x%08x\n", x1); - return SPCI_TFTF_ERROR; - } - - /* The handle is returned in the top 16 bits */ - *handle = (x1 >> 16) & 0xFFFF; - - return SPCI_SUCCESS; -} - -/* Invokes SPCI_SERVICE_HANDLE_CLOSE. Returns a SPCI error code. */ -int spci_service_handle_close(uint16_t client_id, uint16_t handle) +/*----------------------------------------------------------------------------- + * SPCI_RUN + * + * Parameters + * uint32 Function ID (w0): 0x8400006D + * uint32 Target information (w1): Information to identify target SP/VM + * -Bits[31:16]: ID of SP/VM. + * -Bits[15:0]: ID of vCPU of SP/VM to run. + * Other Parameter registers w2-w7/x2-x7: Reserved (MBZ) + * + * On failure, returns SPCI_ERROR in w0 and error code in w2: + * -INVALID_PARAMETERS: Unrecognized endpoint or vCPU ID + * -NOT_SUPPORTED: This function is not implemented at this SPCI instance + * -DENIED: Callee is not in a state to handle this request + * -BUSY: vCPU is busy and caller must retry later + * -ABORTED: vCPU or VM ran into an unexpected error and has aborted + */ +smc_ret_values spci_run(uint32_t dest_id, uint32_t vcpu_id) { - smc_args close_handle_smc_args = { - SPCI_SERVICE_HANDLE_CLOSE, - client_id | (handle << 16) + smc_args args = { + SPCI_MSG_RUN, + (dest_id << 16) | vcpu_id, + 0, 0, 0, 0, 0, 0 }; - smc_ret_values smc_ret = tftf_smc(&close_handle_smc_args); - - return (int32_t)(uint32_t)smc_ret.ret0; + return tftf_smc(&args); } -/* Returns a SPCI error code. On success, it also returns a token. */ -int spci_service_request_start(u_register_t x1, u_register_t x2, - u_register_t x3, u_register_t x4, - u_register_t x5, u_register_t x6, - uint16_t client_id, uint16_t handle, - uint32_t *token) +/*----------------------------------------------------------------------------- + * SPCI_MSG_SEND_DIRECT_REQ + * + * Parameters + * uint32 Function ID (w0): 0x8400006F / 0xC400006F + * uint32 Source/Destination IDs (w1): Source and destination endpoint IDs + * -Bit[31:16]: Source endpoint ID + * -Bit[15:0]: Destination endpoint ID + * uint32/uint64 (w2/x2) - RFU MBZ + * w3-w7 - Implementation defined + * + * On failure, returns SPCI_ERROR in w0 and error code in w2: + * -INVALID_PARAMETERS: Invalid endpoint ID or non-zero reserved register + * -DENIED: Callee is not in a state to handle this request + * -NOT_SUPPORTED: This function is not implemented at this SPCI instance + * -BUSY: Message target is busy + * -ABORTED: Message target ran into an unexpected error and has aborted + */ +static smc_ret_values __spci_msg_send_direct_req32_5(uint32_t source_id, + uint32_t dest_id, + uint32_t arg0, + uint32_t arg1, + uint32_t arg2, + uint32_t arg3, + uint32_t arg4) { - int32_t ret; - - smc_args request_smc_args = { - SPCI_SERVICE_REQUEST_START_AARCH64, - x1, x2, x3, x4, x5, x6, - client_id | (handle << 16) + smc_args args = { + SPCI_MSG_SEND_DIRECT_REQ_SMC32, + (source_id << 16) | dest_id, + 0, + arg0, arg1, arg2, arg3, arg4 }; - smc_ret_values smc_ret = tftf_smc(&request_smc_args); - - ret = (int32_t)(uint32_t)smc_ret.ret0; - if (ret != SPCI_SUCCESS) - return ret; - - *token = smc_ret.ret1; - - return SPCI_SUCCESS; + return tftf_smc(&args); } -/* - * Returns a SPCI error code. On success, it also returns x1-x3. Any of the - * pointers x1-x3 may be NULL in case the caller doesn't need that value. - */ -int spci_service_request_resume(uint16_t client_id, uint16_t handle, - uint32_t token, u_register_t *x1, - u_register_t *x2, u_register_t *x3) +/* Direct message send helper accepting a single 32b message argument */ +smc_ret_values spci_msg_send_direct_req(uint32_t source_id, uint32_t dest_id, + uint32_t message) { - int32_t ret; - - smc_args request_resume_smc = { - SPCI_SERVICE_REQUEST_RESUME_AARCH64, - token, 0, 0, 0, 0, 0, - client_id | (handle << 16) - }; - - smc_ret_values smc_ret = tftf_smc(&request_resume_smc); - - ret = (int32_t)(uint32_t)smc_ret.ret0; - if (ret != SPCI_SUCCESS) - return ret; - - if (x1 != NULL) - *x1 = smc_ret.ret1; - if (x2 != NULL) - *x2 = smc_ret.ret2; - if (x3 != NULL) - *x3 = smc_ret.ret3; - - return SPCI_SUCCESS; + return __spci_msg_send_direct_req32_5(source_id, dest_id, + message, 0, 0, 0, 0); } -/* - * Returns a SPCI error code. On success, it also returns x1-x3. Any of the - * pointers x1-x3 may be NULL in case the caller doesn't need that value. - */ -int spci_service_get_response(uint16_t client_id, uint16_t handle, - uint32_t token, u_register_t *x1, - u_register_t *x2, u_register_t *x3) +static smc_ret_values __spci_msg_send_direct_req64_5(uint32_t source_id, + uint32_t dest_id, + uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4) { - int32_t ret; - - smc_args get_response_smc = { - SPCI_SERVICE_GET_RESPONSE_AARCH64, - token, 0, 0, 0, 0, 0, - client_id | (handle << 16) + smc_args args = { + SPCI_MSG_SEND_DIRECT_REQ_SMC64, + (source_id << 16) | dest_id, + 0, + arg0, arg1, arg2, arg3, arg4 }; - smc_ret_values smc_ret = tftf_smc(&get_response_smc); - - ret = (int32_t)(uint32_t)smc_ret.ret0; - if (ret != SPCI_SUCCESS) - return ret; - - if (x1 != NULL) - *x1 = smc_ret.ret1; - if (x2 != NULL) - *x2 = smc_ret.ret2; - if (x3 != NULL) - *x3 = smc_ret.ret3; - - return SPCI_SUCCESS; + return tftf_smc(&args); } -/* Returns a SPCI error code. On success, it also returns the returned values. */ -int spci_service_request_blocking(u_register_t x1, u_register_t x2, - u_register_t x3, u_register_t x4, - u_register_t x5, u_register_t x6, - uint16_t client_id, uint16_t handle, - u_register_t *rx1, u_register_t *rx2, - u_register_t *rx3) +/* Direct message send helper accepting a single 64b message argument */ +smc_ret_values spci_msg_send_direct_req64(uint32_t source_id, uint32_t dest_id, + uint64_t message) { - int32_t ret; - - smc_args request_smc_args = { - SPCI_SERVICE_REQUEST_BLOCKING_AARCH64, - x1, x2, x3, x4, x5, x6, - client_id | (handle << 16) - }; - - smc_ret_values smc_ret = tftf_smc(&request_smc_args); - - ret = (int32_t)(uint32_t)smc_ret.ret0; - if (ret != SPCI_SUCCESS) - return ret; - - if (rx1 != NULL) - *rx1 = smc_ret.ret1; - if (rx2 != NULL) - *rx2 = smc_ret.ret2; - if (rx3 != NULL) - *rx3 = smc_ret.ret3; - - return SPCI_SUCCESS; + return __spci_msg_send_direct_req64_5(source_id, dest_id, + message, 0, 0, 0, 0); } diff --git a/tftf/tests/runtime_services/secure_service/test_spci_direct_messaging.c b/tftf/tests/runtime_services/secure_service/test_spci_direct_messaging.c new file mode 100644 index 000000000..7c0e97380 --- /dev/null +++ b/tftf/tests/runtime_services/secure_service/test_spci_direct_messaging.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <cactus_def.h> +#include <platform.h> +#include <smccc.h> +#include <spci_helpers.h> +#include <spci_svc.h> +#include <test_helpers.h> + +/* Hypervisor ID at physical SPCI instance */ +#define HYP_ID (0) + +/* By convention, SP IDs (as opposed to VM IDs) have bit 15 set */ +#define SP_ID(x) (x | (1 << 15)) + +#define DIRECT_MSG_TEST_PATTERN1 (0xaaaa0000) +#define DIRECT_MSG_TEST_PATTERN2 (0xbbbb0000) +#define DIRECT_MSG_TEST_PATTERN3 (0xcccc0000) + +static test_result_t send_receive_direct_msg(unsigned int sp_id, + unsigned int test_pattern) +{ + smc_ret_values ret_values; + + /* Send a message to SP through direct messaging */ + ret_values = spci_msg_send_direct_req(HYP_ID, SP_ID(sp_id), + test_pattern); + + /* + * Return responses may be SPCI_MSG_SEND_DIRECT_RESP or SPCI_INTERRUPT, + * but only expect the former. Expect SMC32 convention from SP. + */ + if (ret_values.ret0 != SPCI_MSG_SEND_DIRECT_RESP_SMC32) { + tftf_testcase_printf("spci_msg_send_direct_req returned %lx\n", + (u_register_t)ret_values.ret0); + 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)) { + return TEST_RESULT_FAIL; + } + + return TEST_RESULT_SUCCESS; +} + +test_result_t test_spci_direct_messaging(void) +{ + smc_ret_values ret_values; + test_result_t result; + + /********************************************************************** + * Verify that SPCI is there and that it has the correct version. + **********************************************************************/ + SKIP_TEST_IF_SPCI_VERSION_LESS_THAN(0, 9); + + /********************************************************************** + * Send a message to SP1 through direct messaging + **********************************************************************/ + result = send_receive_direct_msg(1, DIRECT_MSG_TEST_PATTERN1); + if (result != TEST_RESULT_SUCCESS) { + return result; + } + + /********************************************************************** + * Send a message to SP2 through direct messaging + **********************************************************************/ + /* + * NOTICE: for now, the SPM does not initially run each SP sequentially + * on boot up so we explicitely run the SP once by invoking SPCI_RUN so + * it reaches spci_msg_wait in the message loop function. + */ + + /* Request running SP2 on VCPU0 */ + ret_values = spci_run(2, 0); + if (ret_values.ret0 != SPCI_MSG_WAIT) { + tftf_testcase_printf("spci_run returned %lx\n", + (u_register_t)ret_values.ret0); + return TEST_RESULT_FAIL; + } + + result = send_receive_direct_msg(2, DIRECT_MSG_TEST_PATTERN2); + if (result != TEST_RESULT_SUCCESS) { + return result; + } + + /********************************************************************** + * Send a message to SP1 through direct messaging + **********************************************************************/ + result = send_receive_direct_msg(1, DIRECT_MSG_TEST_PATTERN3); + if (result != TEST_RESULT_SUCCESS) { + return result; + } + + /********************************************************************** + * All tests passed. + **********************************************************************/ + return TEST_RESULT_SUCCESS; +} diff --git a/tftf/tests/tests-spm.mk b/tftf/tests/tests-spm.mk index c4876879f..40c9b87d7 100644 --- a/tftf/tests/tests-spm.mk +++ b/tftf/tests/tests-spm.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, Arm Limited. All rights reserved. +# Copyright (c) 2018-2020, Arm Limited. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -7,10 +7,5 @@ TESTS_SOURCES += \ $(addprefix tftf/tests/runtime_services/secure_service/, \ spci_helpers.c \ - test_spci_handle_open.c \ - test_spci_blocking_request.c \ - test_spci_non_blocking_request.c \ - test_spci_blocking_while_busy.c \ - test_spci_blocking_interrupt.c \ - test_spci_non_blocking_interrupt.c \ + test_spci_direct_messaging.c \ ) diff --git a/tftf/tests/tests-spm.xml b/tftf/tests/tests-spm.xml index 9afc6afd2..beac7dd69 100644 --- a/tftf/tests/tests-spm.xml +++ b/tftf/tests/tests-spm.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - Copyright (c) 2018, Arm Limited. All rights reserved. + Copyright (c) 2018-2020, Arm Limited. All rights reserved. SPDX-License-Identifier: BSD-3-Clause --> @@ -11,24 +11,8 @@ <testsuite name="Secure Partition Manager" description="Test SPM APIs"> - <testcase name="SPCI handle open and close" - function="test_spci_handle_open" /> - - <testcase name="SPCI non-blocking requests" - function="test_spci_request" /> - - <testcase name="SPCI blocking requests multicore" - function="test_spci_blocking_request_multicore" /> - <testcase name="SPCI non-blocking requests multicore" - function="test_spci_request_multicore" /> - - <testcase name="SPCI blocking request while busy" - function="test_spci_blocking_while_busy" /> - - <testcase name="SPCI blocking request fail to preempt" - function="test_spci_blocking_interrupt_by_ns" /> - <testcase name="SPCI non-blocking request succeed to preempt" - function="test_spci_non_blocking_interrupt_by_ns" /> + <testcase name="SPCI direct messaging API" + function="test_spci_direct_messaging" /> </testsuite> |