diff options
author | Imre Kis <imre.kis@arm.com> | 2021-02-25 17:56:19 +0100 |
---|---|---|
committer | György Szing <gyorgy.szing@arm.com> | 2021-07-02 13:58:01 +0200 |
commit | be97e77f3b1737f2dddbf21f84eff5f8d14edd20 (patch) | |
tree | f78713c8d6fc7c8e40f40278368357a4c855858a | |
parent | c674b5b698d149b5d042ea8f4aa46c303f55df83 (diff) | |
download | trusted-services-be97e77f3b1737f2dddbf21f84eff5f8d14edd20.tar.gz |
libsp: Add FF-A direct message routing extension
The routing extension is a layer on top of FF-A which enables SPs to
send direct messages to the normal world component while maintaining
the state of the SPs in the call chain.
Change-Id: Ic4d6d5cbbccbe1adb534e7b8d2502b78b3d9cb04
Signed-off-by: Imre Kis <imre.kis@arm.com>
7 files changed, 1174 insertions, 0 deletions
diff --git a/components/messaging/ffa/libsp/component.cmake b/components/messaging/ffa/libsp/component.cmake index 2fec443c9..a21c6309c 100644 --- a/components/messaging/ffa/libsp/component.cmake +++ b/components/messaging/ffa/libsp/component.cmake @@ -8,6 +8,8 @@ if (NOT DEFINED TGT) message(FATAL_ERROR "mandatory parameter TGT is not defined.") endif() +set(FFA_DIRECT_MSG_ROUTING_EXTENSION ON CACHE BOOL "Enable FF-A direct message routing extension") + target_sources(${TGT} PRIVATE "${CMAKE_CURRENT_LIST_DIR}/aarch64/ffa_syscalls_a64.S" "${CMAKE_CURRENT_LIST_DIR}/ffa.c" @@ -34,6 +36,15 @@ set_property(TARGET ${TGT} PROPERTY PUBLIC_HEADER ${CMAKE_CURRENT_LIST_DIR}/include/sp_rxtx.h ) +if (FFA_DIRECT_MSG_ROUTING_EXTENSION) + target_sources(${TGT} PRIVATE + "${CMAKE_CURRENT_LIST_DIR}/ffa_direct_msg_routing_extension.c" + ) + + target_compile_options(${TGT} PUBLIC + -DFFA_DIRECT_MSG_ROUTING_EXTENSION=1 + ) +endif() target_include_directories(${TGT} PUBLIC diff --git a/components/messaging/ffa/libsp/ffa_direct_msg_routing_extension.c b/components/messaging/ffa/libsp/ffa_direct_msg_routing_extension.c new file mode 100644 index 000000000..681357304 --- /dev/null +++ b/components/messaging/ffa/libsp/ffa_direct_msg_routing_extension.c @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved. + */ + +#include "ffa_direct_msg_routing_extension.h" +#include "ffa_api.h" +#include <stdbool.h> + +#define SP_ID_INVALID FFA_ID_GET_ID_MASK +#define FFA_ROUTING_EXT_RC_BIT BIT(0) +#define FFA_ROUTING_EXT_ERROR_BIT BIT(1) + +enum sp_rc_state { idle = 0, root, leaf, rc_root, internal, forwarding }; + +enum sp_rc_state state = idle; +static uint16_t own_id = SP_ID_INVALID; +static uint16_t caller_id = SP_ID_INVALID; +static uint16_t callee_id = SP_ID_INVALID; + +static bool is_rc_message(const struct ffa_direct_msg *msg) +{ + return msg->args[0] & FFA_ROUTING_EXT_RC_BIT; +} + +static bool is_error_message(const struct ffa_direct_msg *msg) +{ + return msg->args[0] & FFA_ROUTING_EXT_ERROR_BIT; +} + +static ffa_result get_error_code_from_message(const struct ffa_direct_msg *msg) +{ + return (ffa_result)msg->args[1]; +} + +static ffa_result send_rc_error_message(struct ffa_direct_msg *req, + ffa_result error_code) +{ + return ffa_msg_send_direct_resp(req->destination_id, req->source_id, + (FFA_ROUTING_EXT_ERROR_BIT | + FFA_ROUTING_EXT_RC_BIT), + error_code, 0, 0, 0, req); +} + +static ffa_result send_rc_error_message_to_rc_root(struct ffa_direct_msg *resp, + ffa_result error_code) +{ + return ffa_msg_send_direct_req(own_id, callee_id, + (FFA_ROUTING_EXT_RC_BIT | + FFA_ROUTING_EXT_ERROR_BIT), + error_code, 0, 0, 0, resp); +} + +static ffa_result deny_unexpected_rc_responses(struct ffa_direct_msg *req) +{ + ffa_result ffa_res = FFA_OK; + + while (is_rc_message(req)) { + ffa_res = send_rc_error_message(req, FFA_DENIED); + if (ffa_res != FFA_OK) + return ffa_res; + } + + return FFA_OK; +} + +static ffa_result deny_unexpected_requests(struct ffa_direct_msg *req) +{ + ffa_result ffa_res = FFA_OK; + + while (!is_rc_message(req) || req->source_id != caller_id) { + ffa_res = send_rc_error_message(req, FFA_BUSY); + if (ffa_res != FFA_OK) { + /* Sending error message as a response to an invalid + * request has failed. Sending and FFA_MSG_WAIT to have + * a chance for receiving a valid message. + */ + ffa_res = ffa_msg_wait(req); + if (ffa_res != FFA_OK) { + /* Even the FFA_MSG_WAIT failed so return. */ + return ffa_res; + } + } + } + + return FFA_OK; +} + +static ffa_result request_received_hook(struct ffa_direct_msg *req) +{ + ffa_result ffa_res = FFA_OK; + + ffa_res = deny_unexpected_rc_responses(req); + if (ffa_res != FFA_OK) + return ffa_res; + + state = leaf; + own_id = req->destination_id; + caller_id = req->source_id; + callee_id = SP_ID_INVALID; + + return FFA_OK; +} + +ffa_result ffa_direct_msg_routing_ext_wait_post_hook(struct ffa_direct_msg *req) +{ + return request_received_hook(req); +} + +void ffa_direct_msg_routing_ext_req_pre_hook(struct ffa_direct_msg *req) +{ + state = internal; + callee_id = req->destination_id; +} + +ffa_result ffa_direct_msg_routing_ext_req_post_hook(struct ffa_direct_msg *resp) +{ + ffa_result ffa_res = FFA_OK; + struct ffa_direct_msg rc_resp = { 0 }; + + while (is_rc_message(resp)) { + if (is_error_message(resp)) { + /* The callee returned an error in an RC message. */ + ffa_res = get_error_code_from_message(resp); + break; + } + + /* Forwarding RC request towards the root (normal world) */ + state = forwarding; + + ffa_res = ffa_msg_send_direct_resp(own_id, caller_id, + resp->args[0], resp->args[1], + resp->args[2], resp->args[3], + resp->args[4], &rc_resp); + if (ffa_res != FFA_OK) + goto forward_ffa_error_to_rc_root; + + /* + * Denying messages which are not RC responses or came from a + * different endpoint than the original caller. + */ + ffa_res = deny_unexpected_requests(&rc_resp); + if (ffa_res != FFA_OK) + goto forward_ffa_error_to_rc_root; + + /* Forwarding RC response towards the RC root. */ + state = internal; + ffa_res = ffa_msg_send_direct_req( + own_id, callee_id, rc_resp.args[0], rc_resp.args[1], + rc_resp.args[2], rc_resp.args[3], rc_resp.args[4], + resp); + + goto break_on_ffa_error; + + /* + * At this point an FF-A error message was received while it was + * trying to forward the RC message. Forwarding erro to RC root. + */ +forward_ffa_error_to_rc_root: + ffa_res = send_rc_error_message_to_rc_root(resp, ffa_res); + +break_on_ffa_error: + if (ffa_res != FFA_OK) { + /* Exit loop, set leaf state and return with error. */ + break; + } + } + + /* Non-RC message was received or a non-recoverable error happened. */ + state = leaf; + callee_id = SP_ID_INVALID; + + return ffa_res; +} + +void ffa_direct_msg_routing_ext_req_error_hook(void) +{ + state = leaf; + callee_id = SP_ID_INVALID; +} + +void ffa_direct_msg_routing_ext_resp_pre_hook(struct ffa_direct_msg *resp) +{ + state = idle; + caller_id = SP_ID_INVALID; + callee_id = SP_ID_INVALID; +} + +ffa_result ffa_direct_msg_routing_ext_resp_post_hook(struct ffa_direct_msg *req) +{ + return request_received_hook(req); +} + +void ffa_direct_msg_routing_ext_resp_error_hook(void) +{ +} + +void ffa_direct_msg_routing_ext_rc_req_pre_hook(struct ffa_direct_msg *req) +{ + req->args[0] = FFA_ROUTING_EXT_RC_BIT; + state = rc_root; +} + +ffa_result +ffa_direct_msg_routing_ext_rc_req_post_hook(struct ffa_direct_msg *resp) +{ + ffa_result ffa_res = FFA_OK; + + ffa_res = deny_unexpected_requests(resp); + state = leaf; + + if (is_error_message(resp)) + ffa_res = get_error_code_from_message(resp); + + return ffa_res; +} + +void ffa_direct_msg_routing_ext_rc_req_error_hook(void) +{ + state = leaf; +} diff --git a/components/messaging/ffa/libsp/include/ffa_direct_msg_routing_extension.h b/components/messaging/ffa/libsp/include/ffa_direct_msg_routing_extension.h new file mode 100644 index 000000000..3715f50f5 --- /dev/null +++ b/components/messaging/ffa/libsp/include/ffa_direct_msg_routing_extension.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + */ + +#ifndef LIBSP_INCLUDE_FFA_DIRECT_MSG_ROUTING_EXTENSION_H_ +#define LIBSP_INCLUDE_FFA_DIRECT_MSG_ROUTING_EXTENSION_H_ + +#include "ffa_api_types.h" +#include "sp_api_defines.h" +#include "sp_api_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +ffa_result +ffa_direct_msg_routing_ext_wait_post_hook(struct ffa_direct_msg *req); + +void ffa_direct_msg_routing_ext_req_pre_hook(struct ffa_direct_msg *req); +ffa_result +ffa_direct_msg_routing_ext_req_post_hook(struct ffa_direct_msg *resp); +void ffa_direct_msg_routing_ext_req_error_hook(void); + +void ffa_direct_msg_routing_ext_resp_pre_hook(struct ffa_direct_msg *resp); +ffa_result +ffa_direct_msg_routing_ext_resp_post_hook(struct ffa_direct_msg *req); +void ffa_direct_msg_routing_ext_resp_error_hook(void); + +void ffa_direct_msg_routing_ext_rc_req_pre_hook(struct ffa_direct_msg *req); +ffa_result +ffa_direct_msg_routing_ext_rc_req_post_hook(struct ffa_direct_msg *resp); +void ffa_direct_msg_routing_ext_rc_req_error_hook(void); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBSP_INCLUDE_FFA_DIRECT_MSG_ROUTING_EXTENSION_H_ */ diff --git a/components/messaging/ffa/libsp/include/sp_messaging.h b/components/messaging/ffa/libsp/include/sp_messaging.h index 3ee5aae83..4bb45f767 100644 --- a/components/messaging/ffa/libsp/include/sp_messaging.h +++ b/components/messaging/ffa/libsp/include/sp_messaging.h @@ -57,6 +57,18 @@ sp_result sp_msg_send_direct_req(const struct sp_msg *req, struct sp_msg *resp); sp_result sp_msg_send_direct_resp(const struct sp_msg *resp, struct sp_msg *req); +#if FFA_DIRECT_MSG_ROUTING_EXTENSION +/** + * @brief Sends a request on the return channel and waits for the response + * message which it returns then. + * + * @param[in] req The request message + * @param[out] resp The response message + * @return The SP API result + */ +sp_result sp_msg_send_rc_req(const struct sp_msg *req, struct sp_msg *resp); +#endif /* FFA_DIRECT_MSG_ROUTING_EXTENSION */ + #ifdef __cplusplus } #endif diff --git a/components/messaging/ffa/libsp/sp_messaging.c b/components/messaging/ffa/libsp/sp_messaging.c index 9e2938454..ba07ce158 100644 --- a/components/messaging/ffa/libsp/sp_messaging.c +++ b/components/messaging/ffa/libsp/sp_messaging.c @@ -6,6 +6,9 @@ #include "ffa_api.h" #include "sp_api_defines.h" #include "sp_messaging.h" +#if FFA_DIRECT_MSG_ROUTING_EXTENSION +#include "ffa_direct_msg_routing_extension.h" +#endif #include <string.h> @@ -57,6 +60,14 @@ sp_result sp_msg_wait(struct sp_msg *msg) return SP_RESULT_FFA(ffa_res); } +#if FFA_DIRECT_MSG_ROUTING_EXTENSION + ffa_res = ffa_direct_msg_routing_ext_wait_post_hook(&ffa_msg); + if (ffa_res != FFA_OK) { + *msg = (struct sp_msg){ 0 }; + return SP_RESULT_FFA(ffa_res); + } +#endif + unpack_ffa_direct_msg(&ffa_msg, msg); return SP_RESULT_OK; @@ -78,6 +89,10 @@ sp_result sp_msg_send_direct_req(const struct sp_msg *req, struct sp_msg *resp) pack_ffa_direct_msg(req, &ffa_req); +#if FFA_DIRECT_MSG_ROUTING_EXTENSION + ffa_direct_msg_routing_ext_req_pre_hook(&ffa_req); +#endif + ffa_res = ffa_msg_send_direct_req(ffa_req.source_id, ffa_req.destination_id, ffa_req.args[0], ffa_req.args[1], @@ -85,10 +100,21 @@ sp_result sp_msg_send_direct_req(const struct sp_msg *req, struct sp_msg *resp) ffa_req.args[4], &ffa_resp); if (ffa_res != FFA_OK) { +#if FFA_DIRECT_MSG_ROUTING_EXTENSION + ffa_direct_msg_routing_ext_req_error_hook(); +#endif *resp = (struct sp_msg){ 0 }; return SP_RESULT_FFA(ffa_res); } +#if FFA_DIRECT_MSG_ROUTING_EXTENSION + ffa_res = ffa_direct_msg_routing_ext_req_post_hook(&ffa_resp); + if (ffa_res != SP_RESULT_OK) { + *resp = (struct sp_msg){ 0 }; + return SP_RESULT_FFA(ffa_res); + } +#endif + unpack_ffa_direct_msg(&ffa_resp, resp); return SP_RESULT_OK; @@ -110,6 +136,10 @@ sp_result sp_msg_send_direct_resp(const struct sp_msg *resp, struct sp_msg *req) pack_ffa_direct_msg(resp, &ffa_resp); +#if FFA_DIRECT_MSG_ROUTING_EXTENSION + ffa_direct_msg_routing_ext_resp_pre_hook(&ffa_resp); +#endif + ffa_res = ffa_msg_send_direct_resp(ffa_resp.source_id, ffa_resp.destination_id, ffa_resp.args[0], ffa_resp.args[1], @@ -117,11 +147,65 @@ sp_result sp_msg_send_direct_resp(const struct sp_msg *resp, struct sp_msg *req) ffa_resp.args[4], &ffa_req); if (ffa_res != FFA_OK) { +#if FFA_DIRECT_MSG_ROUTING_EXTENSION + ffa_direct_msg_routing_ext_resp_error_hook(); +#endif *req = (struct sp_msg){ 0 }; return SP_RESULT_FFA(ffa_res); } +#if FFA_DIRECT_MSG_ROUTING_EXTENSION + ffa_res = ffa_direct_msg_routing_ext_resp_post_hook(&ffa_req); + if (ffa_res != SP_RESULT_OK) { + *req = (struct sp_msg){ 0 }; + return SP_RESULT_FFA(ffa_res); + } +#endif + unpack_ffa_direct_msg(&ffa_req, req); return SP_RESULT_OK; } + +#if FFA_DIRECT_MSG_ROUTING_EXTENSION +sp_result sp_msg_send_rc_req(const struct sp_msg *req, struct sp_msg *resp) +{ + ffa_result ffa_res = FFA_OK; + struct ffa_direct_msg ffa_req = { 0 }; + struct ffa_direct_msg ffa_resp = { 0 }; + + if (!resp) + return SP_RESULT_INVALID_PARAMETERS; + + if (!req) { + *resp = (struct sp_msg){ 0 }; + return SP_RESULT_INVALID_PARAMETERS; + } + + pack_ffa_direct_msg(req, &ffa_req); + + ffa_direct_msg_routing_ext_rc_req_pre_hook(&ffa_req); + + ffa_res = ffa_msg_send_direct_resp(ffa_req.source_id, + ffa_req.destination_id, + ffa_req.args[0], ffa_req.args[1], + ffa_req.args[2], ffa_req.args[3], + ffa_req.args[4], &ffa_resp); + + if (ffa_res != FFA_OK) { + ffa_direct_msg_routing_ext_rc_req_error_hook(); + *resp = (struct sp_msg){ 0 }; + return SP_RESULT_FFA(ffa_res); + } + + ffa_res = ffa_direct_msg_routing_ext_rc_req_post_hook(&ffa_resp); + if (ffa_res != SP_RESULT_OK) { + *resp = (struct sp_msg){ 0 }; + return SP_RESULT_FFA(ffa_res); + } + + unpack_ffa_direct_msg(&ffa_resp, resp); + + return SP_RESULT_OK; +} +#endif diff --git a/components/messaging/ffa/libsp/test/test_sp_messaging.cpp b/components/messaging/ffa/libsp/test/test_sp_messaging.cpp index 2ddf1ab62..78bf8bf47 100644 --- a/components/messaging/ffa/libsp/test/test_sp_messaging.cpp +++ b/components/messaging/ffa/libsp/test/test_sp_messaging.cpp @@ -12,6 +12,11 @@ #define SP_MSG_ARG_OFFSET (1) +#if FFA_DIRECT_MSG_ROUTING_EXTENSION +#define ROUTING_EXT_RC_BIT BIT(0) +#define ROUTING_EXT_ERR_BIT BIT(1) +#endif + TEST_GROUP(sp_messaging) { TEST_SETUP() @@ -76,6 +81,22 @@ TEST_GROUP(sp_messaging) } } +#if FFA_DIRECT_MSG_ROUTING_EXTENSION + void wait_and_receive_request(uint16_t source_id, uint16_t dest_id) + { + struct ffa_direct_msg expected_ffa_req = { 0 }; + struct sp_msg req = { 0 }; + + fill_ffa_msg(&expected_ffa_req); + expected_ffa_req.source_id = source_id; + expected_ffa_req.destination_id = dest_id; + expect_ffa_msg_wait(&expected_ffa_req, FFA_OK); + + LONGS_EQUAL(SP_RESULT_OK, sp_msg_wait(&req)); + ffa_and_sp_msg_equal(&expected_ffa_req, &req); + } +#endif + struct sp_msg req; struct sp_msg resp; struct ffa_direct_msg ffa_msg; @@ -112,6 +133,45 @@ TEST(sp_messaging, sp_msg_wait) ffa_and_sp_msg_equal(&ffa_msg, &req); } +#if FFA_DIRECT_MSG_ROUTING_EXTENSION +TEST(sp_messaging, sp_msg_wait_deny_rc_failure) +{ + struct ffa_direct_msg rc_msg = { 0 }; + ffa_result result = FFA_ABORTED; + + fill_ffa_msg(&rc_msg); + rc_msg.args[0] = ROUTING_EXT_RC_BIT; + expect_ffa_msg_wait(&rc_msg, FFA_OK); + + fill_ffa_msg(&ffa_msg); + expect_ffa_msg_send_direct_resp( + rc_msg.destination_id, rc_msg.source_id, + ROUTING_EXT_RC_BIT | ROUTING_EXT_ERR_BIT, + SP_RESULT_FFA(FFA_DENIED), 0, 0, 0, &ffa_msg, result); + + LONGS_EQUAL(SP_RESULT_FFA(result), sp_msg_wait(&req)); + MEMCMP_EQUAL(&empty_sp_msg, &req, sizeof(empty_sp_msg)); +} + +TEST(sp_messaging, sp_msg_wait_deny_rc) +{ + struct ffa_direct_msg rc_msg = { 0 }; + + fill_ffa_msg(&rc_msg); + rc_msg.args[0] = ROUTING_EXT_RC_BIT; + expect_ffa_msg_wait(&rc_msg, FFA_OK); + + fill_ffa_msg(&ffa_msg); + expect_ffa_msg_send_direct_resp( + rc_msg.destination_id, rc_msg.source_id, + ROUTING_EXT_RC_BIT | ROUTING_EXT_ERR_BIT, + SP_RESULT_FFA(FFA_DENIED), 0, 0, 0, &ffa_msg, FFA_OK); + + LONGS_EQUAL(SP_RESULT_OK, sp_msg_wait(&req)); + ffa_and_sp_msg_equal(&ffa_msg, &req); +} +#endif + TEST(sp_messaging, sp_msg_send_direct_req_resp_null) { LONGS_EQUAL(SP_RESULT_INVALID_PARAMETERS, @@ -175,6 +235,564 @@ TEST(sp_messaging, sp_msg_send_direct_req_success) MEMCMP_EQUAL(&empty_sp_msg, &resp, sizeof(empty_sp_msg)); } +#if FFA_DIRECT_MSG_ROUTING_EXTENSION +TEST(sp_messaging, sp_msg_send_direct_req_rc_forwarding_success) +{ + const uint16_t root_id = 1; + const uint16_t own_id = 2; + const uint16_t rc_root_id = 3; + ffa_direct_msg req = { 0 }; + ffa_direct_msg rc_req = { 0 }; + ffa_direct_msg rc_resp = { 0 }; + ffa_direct_msg resp = { 0 }; + sp_msg sp_req = { 0 }; + sp_msg sp_resp = { 0 }; + + fill_sp_msg(&sp_req); + sp_req.source_id = own_id; + sp_req.destination_id = rc_root_id; + + req.function_id = FFA_MSG_SEND_DIRECT_REQ_32; + req.source_id = own_id; + req.destination_id = rc_root_id; + copy_sp_to_ffa_args(sp_req.args, req.args); + + fill_ffa_msg(&rc_req); + rc_req.function_id = FFA_MSG_SEND_DIRECT_RESP_32; + rc_req.source_id = rc_root_id; + rc_req.destination_id = own_id; + rc_req.args[0] = ROUTING_EXT_RC_BIT; + + fill_ffa_msg(&rc_resp); + rc_resp.function_id = FFA_MSG_SEND_DIRECT_REQ_32; + rc_resp.source_id = root_id; + rc_resp.destination_id = own_id; + rc_resp.args[0] = ROUTING_EXT_RC_BIT; + + fill_sp_msg(&sp_resp); + sp_resp.source_id = rc_root_id; + sp_resp.destination_id = own_id; + + resp.function_id = FFA_MSG_SEND_DIRECT_RESP_32; + resp.source_id = rc_root_id; + resp.destination_id = own_id; + copy_sp_to_ffa_args(sp_resp.args, resp.args); + + /* Initial request to current SP to set own_id */ + wait_and_receive_request(root_id, own_id); + + /* Sending request and receiving RC request from RC root */ + expect_ffa_msg_send_direct_req(own_id, rc_root_id, 0, req.args[1], + req.args[2], req.args[3], req.args[4], + &rc_req, FFA_OK); + + /* Forwarding RC request to root and receiving RC response */ + expect_ffa_msg_send_direct_resp(own_id, root_id, rc_req.args[0], + rc_req.args[1], rc_req.args[2], + rc_req.args[3], rc_req.args[4], + &rc_resp, FFA_OK); + + /* Fowarding RC response to RC root and receiving response */ + expect_ffa_msg_send_direct_req(own_id, rc_root_id, rc_resp.args[0], + rc_resp.args[1], rc_resp.args[2], + rc_resp.args[3], rc_resp.args[4], &resp, + FFA_OK); + + LONGS_EQUAL(SP_RESULT_OK, sp_msg_send_direct_req(&sp_req, &sp_resp)); + ffa_and_sp_msg_equal(&resp, &sp_resp); +} + +TEST(sp_messaging, sp_msg_send_direct_req_rc_error) +{ + const uint16_t root_id = 1; + const uint16_t own_id = 2; + const uint16_t rc_root_id = 3; + ffa_direct_msg req = { 0 }; + ffa_direct_msg rc_err = { 0 }; + sp_msg sp_req = { 0 }; + sp_msg sp_resp = { 0 }; + + fill_sp_msg(&sp_req); + sp_req.source_id = own_id; + sp_req.destination_id = rc_root_id; + + req.function_id = FFA_MSG_SEND_DIRECT_REQ_32; + req.source_id = own_id; + req.destination_id = rc_root_id; + copy_sp_to_ffa_args(sp_req.args, req.args); + + fill_ffa_msg(&rc_err); + rc_err.function_id = FFA_MSG_SEND_DIRECT_RESP_32; + rc_err.source_id = rc_root_id; + rc_err.destination_id = own_id; + rc_err.args[0] = ROUTING_EXT_RC_BIT | ROUTING_EXT_ERR_BIT; + rc_err.args[1] = result; + + /* Initial request to current SP to set own_id */ + wait_and_receive_request(root_id, own_id); + + /* Sending request and receiving RC request from RC root */ + expect_ffa_msg_send_direct_req(own_id, rc_root_id, 0, req.args[1], + req.args[2], req.args[3], req.args[4], + &rc_err, FFA_OK); + + LONGS_EQUAL(SP_RESULT_FFA(result), + sp_msg_send_direct_req(&sp_req, &sp_resp)); + MEMCMP_EQUAL(&empty_sp_msg, &sp_resp, sizeof(empty_sp_msg)); +} + +TEST(sp_messaging, sp_msg_send_direct_req_rc_forwarding_success_deny_request) +{ + const uint16_t root_id = 1; + const uint16_t own_id = 2; + const uint16_t rc_root_id = 3; + ffa_direct_msg req = { 0 }; + ffa_direct_msg rc_req = { 0 }; + ffa_direct_msg request_to_deny = { 0 }; + ffa_direct_msg rc_resp = { 0 }; + ffa_direct_msg resp = { 0 }; + sp_msg sp_req = { 0 }; + sp_msg sp_resp = { 0 }; + + fill_sp_msg(&sp_req); + sp_req.source_id = own_id; + sp_req.destination_id = rc_root_id; + + req.function_id = FFA_MSG_SEND_DIRECT_REQ_32; + req.source_id = own_id; + req.destination_id = rc_root_id; + copy_sp_to_ffa_args(sp_req.args, req.args); + + fill_ffa_msg(&rc_req); + rc_req.function_id = FFA_MSG_SEND_DIRECT_RESP_32; + rc_req.source_id = rc_root_id; + rc_req.destination_id = own_id; + rc_req.args[0] = ROUTING_EXT_RC_BIT; + + request_to_deny.function_id = FFA_MSG_SEND_DIRECT_REQ_32; + request_to_deny.source_id = root_id; + request_to_deny.destination_id = own_id; + request_to_deny.args[0] = 0; + + fill_ffa_msg(&rc_resp); + rc_resp.function_id = FFA_MSG_SEND_DIRECT_REQ_32; + rc_resp.source_id = root_id; + rc_resp.destination_id = own_id; + rc_resp.args[0] = ROUTING_EXT_RC_BIT; + + fill_sp_msg(&sp_resp); + sp_resp.source_id = rc_root_id; + sp_resp.destination_id = own_id; + + resp.function_id = FFA_MSG_SEND_DIRECT_RESP_32; + resp.source_id = rc_root_id; + resp.destination_id = own_id; + copy_sp_to_ffa_args(sp_resp.args, resp.args); + + /* Initial request to current SP to set own_id */ + wait_and_receive_request(root_id, own_id); + + /* Sending request and receiving RC request from RC root */ + expect_ffa_msg_send_direct_req(own_id, rc_root_id, 0, req.args[1], + req.args[2], req.args[3], req.args[4], + &rc_req, FFA_OK); + + /* Forwarding RC request to root and receiving a request to deny */ + expect_ffa_msg_send_direct_resp(own_id, root_id, rc_req.args[0], + rc_req.args[1], rc_req.args[2], + rc_req.args[3], rc_req.args[4], + &request_to_deny, FFA_OK); + + /* Sending error to root and receiving RC response */ + expect_ffa_msg_send_direct_resp( + own_id, root_id, ROUTING_EXT_RC_BIT | ROUTING_EXT_ERR_BIT, + SP_RESULT_FFA(FFA_BUSY), 0, 0, 0, &rc_resp, FFA_OK); + + /* Fowarding RC response to RC root and receiving response */ + expect_ffa_msg_send_direct_req(own_id, rc_root_id, rc_resp.args[0], + rc_resp.args[1], rc_resp.args[2], + rc_resp.args[3], rc_resp.args[4], &resp, + FFA_OK); + + LONGS_EQUAL(SP_RESULT_OK, sp_msg_send_direct_req(&sp_req, &sp_resp)); + ffa_and_sp_msg_equal(&resp, &sp_resp); +} + +TEST(sp_messaging, sp_msg_send_direct_req_rc_forwarding_success_invalid_req_src) +{ + const uint16_t root_id = 1; + const uint16_t own_id = 2; + const uint16_t rc_root_id = 3; + ffa_direct_msg req = { 0 }; + ffa_direct_msg rc_req = { 0 }; + ffa_direct_msg request_to_deny = { 0 }; + ffa_direct_msg rc_resp = { 0 }; + ffa_direct_msg resp = { 0 }; + sp_msg sp_req = { 0 }; + sp_msg sp_resp = { 0 }; + + fill_sp_msg(&sp_req); + sp_req.source_id = own_id; + sp_req.destination_id = rc_root_id; + + req.function_id = FFA_MSG_SEND_DIRECT_REQ_32; + req.source_id = own_id; + req.destination_id = rc_root_id; + copy_sp_to_ffa_args(sp_req.args, req.args); + + fill_ffa_msg(&rc_req); + rc_req.function_id = FFA_MSG_SEND_DIRECT_RESP_32; + rc_req.source_id = rc_root_id; + rc_req.destination_id = own_id; + rc_req.args[0] = ROUTING_EXT_RC_BIT; + + request_to_deny.function_id = FFA_MSG_SEND_DIRECT_REQ_32; + /* This source ID should be denied in the current state. */ + request_to_deny.source_id = rc_root_id; + request_to_deny.destination_id = own_id; + request_to_deny.args[0] = ROUTING_EXT_RC_BIT; + + fill_ffa_msg(&rc_resp); + rc_resp.function_id = FFA_MSG_SEND_DIRECT_REQ_32; + rc_resp.source_id = root_id; + rc_resp.destination_id = own_id; + rc_resp.args[0] = ROUTING_EXT_RC_BIT; + + fill_sp_msg(&sp_resp); + sp_resp.source_id = rc_root_id; + sp_resp.destination_id = own_id; + + resp.function_id = FFA_MSG_SEND_DIRECT_RESP_32; + resp.source_id = rc_root_id; + resp.destination_id = own_id; + copy_sp_to_ffa_args(sp_resp.args, resp.args); + + /* Initial request to current SP to set own_id */ + wait_and_receive_request(root_id, own_id); + + /* Sending request and receiving RC request from RC root */ + expect_ffa_msg_send_direct_req(own_id, rc_root_id, 0, req.args[1], + req.args[2], req.args[3], req.args[4], + &rc_req, FFA_OK); + + /* Forwarding RC request to root and receiving RC response */ + expect_ffa_msg_send_direct_resp(own_id, root_id, rc_req.args[0], + rc_req.args[1], rc_req.args[2], + rc_req.args[3], rc_req.args[4], + &request_to_deny, FFA_OK); + + /* Sending error to root and receiving RC response */ + expect_ffa_msg_send_direct_resp( + own_id, rc_root_id, ROUTING_EXT_ERR_BIT | ROUTING_EXT_RC_BIT, + SP_RESULT_FFA(FFA_BUSY), 0, 0, 0, &rc_resp, FFA_OK); + + /* Fowarding RC response to RC root and receiving response */ + expect_ffa_msg_send_direct_req(own_id, rc_root_id, rc_resp.args[0], + rc_resp.args[1], rc_resp.args[2], + rc_resp.args[3], rc_resp.args[4], &resp, + FFA_OK); + + LONGS_EQUAL(SP_RESULT_OK, sp_msg_send_direct_req(&sp_req, &sp_resp)); + ffa_and_sp_msg_equal(&resp, &sp_resp); +} + +TEST(sp_messaging, sp_msg_send_direct_req_deny_fail_wait_success) +{ + const uint16_t root_id = 1; + const uint16_t own_id = 2; + const uint16_t rc_root_id = 3; + ffa_direct_msg req = { 0 }; + ffa_direct_msg rc_req = { 0 }; + ffa_direct_msg request_to_deny = { 0 }; + ffa_direct_msg rc_resp = { 0 }; + ffa_direct_msg resp = { 0 }; + sp_msg sp_req = { 0 }; + sp_msg sp_resp = { 0 }; + + fill_sp_msg(&sp_req); + sp_req.source_id = own_id; + sp_req.destination_id = rc_root_id; + + req.function_id = FFA_MSG_SEND_DIRECT_REQ_32; + req.source_id = own_id; + req.destination_id = rc_root_id; + copy_sp_to_ffa_args(sp_req.args, req.args); + + fill_ffa_msg(&rc_req); + rc_req.function_id = FFA_MSG_SEND_DIRECT_RESP_32; + rc_req.source_id = rc_root_id; + rc_req.destination_id = own_id; + rc_req.args[0] = ROUTING_EXT_RC_BIT; + + request_to_deny.function_id = FFA_MSG_SEND_DIRECT_REQ_32; + /* This source ID should be denied in the current state. */ + request_to_deny.source_id = rc_root_id; + request_to_deny.destination_id = own_id; + request_to_deny.args[0] = ROUTING_EXT_RC_BIT; + + fill_ffa_msg(&rc_resp); + rc_resp.function_id = FFA_MSG_SEND_DIRECT_REQ_32; + rc_resp.source_id = root_id; + rc_resp.destination_id = own_id; + rc_resp.args[0] = ROUTING_EXT_RC_BIT; + + fill_sp_msg(&sp_resp); + sp_resp.source_id = rc_root_id; + sp_resp.destination_id = own_id; + + resp.function_id = FFA_MSG_SEND_DIRECT_RESP_32; + resp.source_id = rc_root_id; + resp.destination_id = own_id; + copy_sp_to_ffa_args(sp_resp.args, resp.args); + + /* Initial request to current SP to set own_id */ + wait_and_receive_request(root_id, own_id); + + /* Sending request and receiving RC request from RC root */ + expect_ffa_msg_send_direct_req(own_id, rc_root_id, 0, req.args[1], + req.args[2], req.args[3], req.args[4], + &rc_req, FFA_OK); + + /* Forwarding RC request to root and receiving RC response */ + expect_ffa_msg_send_direct_resp(own_id, root_id, rc_req.args[0], + rc_req.args[1], rc_req.args[2], + rc_req.args[3], rc_req.args[4], + &request_to_deny, FFA_OK); + + /* Sending error to root which fails */ + expect_ffa_msg_send_direct_resp( + own_id, rc_root_id, (ROUTING_EXT_ERR_BIT | ROUTING_EXT_RC_BIT), + SP_RESULT_FFA(FFA_BUSY), 0, 0, 0, &rc_resp, FFA_DENIED); + + /* Sending FFA_MSG_WAIT as we are still waiting for the RC response */ + expect_ffa_msg_wait(&rc_resp, FFA_OK); + + /* Fowarding RC response to RC root and receiving response */ + expect_ffa_msg_send_direct_req(own_id, rc_root_id, rc_resp.args[0], + rc_resp.args[1], rc_resp.args[2], + rc_resp.args[3], rc_resp.args[4], &resp, + FFA_OK); + + LONGS_EQUAL(SP_RESULT_OK, sp_msg_send_direct_req(&sp_req, &sp_resp)); + ffa_and_sp_msg_equal(&resp, &sp_resp); +} + +TEST(sp_messaging, sp_msg_send_direct_req_deny_fail_wait_fail_forwarding) +{ + const uint16_t root_id = 1; + const uint16_t own_id = 2; + const uint16_t rc_root_id = 3; + ffa_direct_msg req = { 0 }; + ffa_direct_msg rc_req = { 0 }; + ffa_direct_msg request_to_deny = { 0 }; + ffa_direct_msg rc_resp = { 0 }; + ffa_direct_msg resp = { 0 }; + sp_msg sp_req = { 0 }; + sp_msg sp_resp = { 0 }; + + fill_sp_msg(&sp_req); + sp_req.source_id = own_id; + sp_req.destination_id = rc_root_id; + + req.function_id = FFA_MSG_SEND_DIRECT_REQ_32; + req.source_id = own_id; + req.destination_id = rc_root_id; + copy_sp_to_ffa_args(sp_req.args, req.args); + + fill_ffa_msg(&rc_req); + rc_req.function_id = FFA_MSG_SEND_DIRECT_RESP_32; + rc_req.source_id = rc_root_id; + rc_req.destination_id = own_id; + rc_req.args[0] = ROUTING_EXT_RC_BIT; + + request_to_deny.function_id = FFA_MSG_SEND_DIRECT_REQ_32; + /* This source ID should be denied in the current state. */ + request_to_deny.source_id = rc_root_id; + request_to_deny.destination_id = own_id; + request_to_deny.args[0] = ROUTING_EXT_RC_BIT; + + fill_ffa_msg(&rc_resp); + rc_resp.function_id = FFA_MSG_SEND_DIRECT_REQ_32; + rc_resp.source_id = root_id; + rc_resp.destination_id = own_id; + rc_resp.args[0] = ROUTING_EXT_RC_BIT; + + fill_sp_msg(&sp_resp); + sp_resp.source_id = rc_root_id; + sp_resp.destination_id = own_id; + + resp.function_id = FFA_MSG_SEND_DIRECT_RESP_32; + resp.source_id = rc_root_id; + resp.destination_id = own_id; + copy_sp_to_ffa_args(sp_resp.args, resp.args); + + /* Initial request to current SP to set own_id */ + wait_and_receive_request(root_id, own_id); + + /* Sending request and receiving RC request from RC root */ + expect_ffa_msg_send_direct_req(own_id, rc_root_id, 0, req.args[1], + req.args[2], req.args[3], req.args[4], + &rc_req, FFA_OK); + + /* Forwarding RC request to root and receiving RC response */ + expect_ffa_msg_send_direct_resp(own_id, root_id, rc_req.args[0], + rc_req.args[1], rc_req.args[2], + rc_req.args[3], rc_req.args[4], + &request_to_deny, FFA_OK); + + /* Sending error to root which fails */ + expect_ffa_msg_send_direct_resp( + own_id, rc_root_id, ROUTING_EXT_ERR_BIT | ROUTING_EXT_RC_BIT, + SP_RESULT_FFA(FFA_BUSY), 0, 0, 0, &rc_resp, FFA_DENIED); + + /* Sending FFA_MSG_WAIT as we are still waiting for the RC response */ + expect_ffa_msg_wait(&rc_resp, result); + + /* Fowarding RC error as FFA_MSG_WAIT failed */ + expect_ffa_msg_send_direct_req( + own_id, rc_root_id, (ROUTING_EXT_RC_BIT | ROUTING_EXT_ERR_BIT), + result, 0, 0, 0, &resp, FFA_OK); + + LONGS_EQUAL(SP_RESULT_OK, sp_msg_send_direct_req(&sp_req, &sp_resp)); + ffa_and_sp_msg_equal(&resp, &sp_resp); +} + +TEST(sp_messaging, sp_msg_send_direct_req_rc_return_rc_error_msg) +{ + const uint16_t root_id = 1; + const uint16_t own_id = 2; + const uint16_t rc_root_id = 3; + ffa_direct_msg req = { 0 }; + ffa_direct_msg rc_req = { 0 }; + ffa_direct_msg rc_resp = { 0 }; + ffa_direct_msg resp = { 0 }; + sp_msg sp_req = { 0 }; + sp_msg sp_resp = { 0 }; + ffa_result result = FFA_ABORTED; + + fill_sp_msg(&sp_req); + sp_req.source_id = own_id; + sp_req.destination_id = rc_root_id; + + req.function_id = FFA_MSG_SEND_DIRECT_REQ_32; + req.source_id = own_id; + req.destination_id = rc_root_id; + copy_sp_to_ffa_args(sp_req.args, req.args); + + fill_ffa_msg(&rc_req); + rc_req.function_id = FFA_MSG_SEND_DIRECT_RESP_32; + rc_req.source_id = rc_root_id; + rc_req.destination_id = own_id; + rc_req.args[0] = ROUTING_EXT_RC_BIT; + + fill_ffa_msg(&rc_resp); + rc_resp.function_id = FFA_MSG_SEND_DIRECT_REQ_32; + rc_resp.source_id = root_id; + rc_resp.destination_id = own_id; + rc_resp.args[0] = ROUTING_EXT_RC_BIT; + + fill_sp_msg(&sp_resp); + sp_resp.source_id = rc_root_id; + sp_resp.destination_id = own_id; + + resp.function_id = FFA_MSG_SEND_DIRECT_RESP_32; + resp.source_id = rc_root_id; + resp.destination_id = own_id; + copy_sp_to_ffa_args(sp_resp.args, resp.args); + + /* Initial request to current SP to set own_id */ + wait_and_receive_request(root_id, own_id); + + /* Sending request and receiving RC request from RC root */ + expect_ffa_msg_send_direct_req(own_id, rc_root_id, 0, req.args[1], + req.args[2], req.args[3], req.args[4], + &rc_req, FFA_OK); + + /* Forwarding RC request to root and receiving RC response */ + expect_ffa_msg_send_direct_resp(own_id, root_id, rc_req.args[0], + rc_req.args[1], rc_req.args[2], + rc_req.args[3], rc_req.args[4], + &rc_resp, result); + + /* Fowarding RC error to RC root and receiving response */ + expect_ffa_msg_send_direct_req(own_id, rc_root_id, + ROUTING_EXT_RC_BIT | ROUTING_EXT_ERR_BIT, + SP_RESULT_FFA(result), 0, 0, 0, &resp, + FFA_OK); + + LONGS_EQUAL(SP_RESULT_OK, sp_msg_send_direct_req(&sp_req, &sp_resp)); + ffa_and_sp_msg_equal(&resp, &sp_resp); +} + +TEST(sp_messaging, sp_msg_send_direct_req_rc_return_resp_fail) +{ + const uint16_t root_id = 1; + const uint16_t own_id = 2; + const uint16_t rc_root_id = 3; + ffa_direct_msg req = { 0 }; + ffa_direct_msg rc_req = { 0 }; + ffa_direct_msg rc_resp = { 0 }; + ffa_direct_msg resp = { 0 }; + sp_msg sp_req = { 0 }; + sp_msg sp_resp = { 0 }; + ffa_result result = FFA_ABORTED; + + fill_sp_msg(&sp_req); + sp_req.source_id = own_id; + sp_req.destination_id = rc_root_id; + + req.function_id = FFA_MSG_SEND_DIRECT_REQ_32; + req.source_id = own_id; + req.destination_id = rc_root_id; + copy_sp_to_ffa_args(sp_req.args, req.args); + + fill_ffa_msg(&rc_req); + rc_req.function_id = FFA_MSG_SEND_DIRECT_RESP_32; + rc_req.source_id = rc_root_id; + rc_req.destination_id = own_id; + rc_req.args[0] = ROUTING_EXT_RC_BIT; + + fill_ffa_msg(&rc_resp); + rc_resp.function_id = FFA_MSG_SEND_DIRECT_REQ_32; + rc_resp.source_id = root_id; + rc_resp.destination_id = own_id; + rc_resp.args[0] = ROUTING_EXT_RC_BIT; + + fill_sp_msg(&sp_resp); + sp_resp.source_id = rc_root_id; + sp_resp.destination_id = own_id; + + resp.function_id = FFA_MSG_SEND_DIRECT_RESP_32; + resp.source_id = rc_root_id; + resp.destination_id = own_id; + copy_sp_to_ffa_args(sp_resp.args, resp.args); + + /* Initial request to current SP to set own_id */ + wait_and_receive_request(root_id, own_id); + + /* Sending request and receiving RC request from RC root */ + expect_ffa_msg_send_direct_req(own_id, rc_root_id, 0, req.args[1], + req.args[2], req.args[3], req.args[4], + &rc_req, FFA_OK); + + /* Forwarding RC request to root and receiving RC response */ + expect_ffa_msg_send_direct_resp(own_id, root_id, rc_req.args[0], + rc_req.args[1], rc_req.args[2], + rc_req.args[3], rc_req.args[4], + &rc_resp, FFA_OK); + + /* Fowarding RC response to RC root and receiving response */ + expect_ffa_msg_send_direct_req(own_id, rc_root_id, rc_resp.args[0], + rc_resp.args[1], rc_resp.args[2], + rc_resp.args[3], rc_resp.args[4], &resp, + result); + + LONGS_EQUAL(SP_RESULT_FFA(result), + sp_msg_send_direct_req(&sp_req, &sp_resp)); + MEMCMP_EQUAL(&empty_sp_msg, &sp_resp, sizeof(empty_sp_msg)); +} +#endif + TEST(sp_messaging, sp_msg_send_direct_resp_req_null) { LONGS_EQUAL(SP_RESULT_INVALID_PARAMETERS, @@ -239,3 +857,177 @@ TEST(sp_messaging, sp_msg_send_direct_resp_success) LONGS_EQUAL(SP_RESULT_OK, sp_msg_send_direct_resp(&resp, &req)); MEMCMP_EQUAL(&empty_sp_msg, &req, sizeof(empty_sp_msg)); } + +#if FFA_DIRECT_MSG_ROUTING_EXTENSION +TEST(sp_messaging, sp_msg_send_direct_resp_deny_rc_failure) +{ + uint32_t expected_ffa_args[5] = { 0 }; + struct ffa_direct_msg rc_msg = { 0 }; + + fill_sp_msg(&resp); + + fill_ffa_msg(&rc_msg); + rc_msg.args[0] = ROUTING_EXT_RC_BIT; + + fill_ffa_msg(&ffa_msg); + copy_sp_to_ffa_args(resp.args, expected_ffa_args); + + expect_ffa_msg_send_direct_resp( + resp.source_id, resp.destination_id, expected_ffa_args[0], + expected_ffa_args[1], expected_ffa_args[2], + expected_ffa_args[3], expected_ffa_args[4], &rc_msg, FFA_OK); + + expect_ffa_msg_send_direct_resp( + rc_msg.destination_id, rc_msg.source_id, + ROUTING_EXT_RC_BIT | ROUTING_EXT_ERR_BIT, + SP_RESULT_FFA(FFA_DENIED), 0, 0, 0, &ffa_msg, result); + + LONGS_EQUAL(SP_RESULT_FFA(result), + sp_msg_send_direct_resp(&resp, &req)); + MEMCMP_EQUAL(&empty_sp_msg, &req, sizeof(empty_sp_msg)); +} + +TEST(sp_messaging, sp_msg_send_direct_resp_deny_rc) +{ + uint32_t expected_ffa_args[5] = { 0 }; + struct ffa_direct_msg rc_msg = { 0 }; + + fill_sp_msg(&resp); + + fill_ffa_msg(&rc_msg); + rc_msg.args[0] = ROUTING_EXT_RC_BIT; + + fill_ffa_msg(&ffa_msg); + copy_sp_to_ffa_args(resp.args, expected_ffa_args); + + expect_ffa_msg_send_direct_resp(resp.source_id, resp.destination_id, 0, + expected_ffa_args[1], + expected_ffa_args[2], + expected_ffa_args[3], + expected_ffa_args[4], &rc_msg, FFA_OK); + + expect_ffa_msg_send_direct_resp( + rc_msg.destination_id, rc_msg.source_id, + ROUTING_EXT_RC_BIT | ROUTING_EXT_ERR_BIT, + SP_RESULT_FFA(FFA_DENIED), 0, 0, 0, &ffa_msg, FFA_OK); + + LONGS_EQUAL(SP_RESULT_OK, sp_msg_send_direct_resp(&resp, &req)); + ffa_and_sp_msg_equal(&ffa_msg, &req); +} + +TEST(sp_messaging, sp_msg_send_rc_req_req_null) +{ + LONGS_EQUAL(SP_RESULT_INVALID_PARAMETERS, + sp_msg_send_rc_req(&req, NULL)); +} + +TEST(sp_messaging, sp_msg_send_rc_req_resp_null) +{ + memset(&resp, 0x5a, sizeof(resp)); + LONGS_EQUAL(SP_RESULT_INVALID_PARAMETERS, + sp_msg_send_rc_req(NULL, &resp)); + MEMCMP_EQUAL(&empty_sp_msg, &resp, sizeof(empty_sp_msg)); +} + +TEST(sp_messaging, sp_msg_send_rc_req_ffa_error) +{ + ffa_result result = FFA_ABORTED; + + fill_sp_msg(&resp); + memset(&req, 0x5a, sizeof(req)); + fill_ffa_msg(&ffa_msg); + + expect_ffa_msg_send_direct_resp(req.source_id, req.destination_id, + ROUTING_EXT_RC_BIT, req.args[0], + req.args[1], req.args[2], req.args[3], + &ffa_msg, result); + + LONGS_EQUAL(SP_RESULT_FFA(result), sp_msg_send_rc_req(&req, &resp)); + MEMCMP_EQUAL(&empty_sp_msg, &resp, sizeof(empty_sp_msg)); +} + +TEST(sp_messaging, sp_msg_send_rc_req_deny_fail_wait_fail) +{ + const uint16_t root_id = 1; + const uint16_t own_id = 2; + + wait_and_receive_request(root_id, own_id); + + fill_sp_msg(&req); + req.source_id = own_id; + req.destination_id = root_id; + + fill_ffa_msg(&ffa_msg); + ffa_msg.source_id = root_id; + ffa_msg.destination_id = own_id; + /* Should be RC message so it will be denied */ + ffa_msg.args[0] = 0; + + expect_ffa_msg_send_direct_resp(req.source_id, req.destination_id, + ROUTING_EXT_RC_BIT, req.args[0], + req.args[1], req.args[2], req.args[3], + &ffa_msg, FFA_OK); + + expect_ffa_msg_send_direct_resp( + req.source_id, req.destination_id, + ROUTING_EXT_RC_BIT | ROUTING_EXT_ERR_BIT, + SP_RESULT_FFA(FFA_BUSY), 0, 0, 0, &ffa_msg, result); + + expect_ffa_msg_wait(&ffa_msg, result); + + LONGS_EQUAL(SP_RESULT_FFA(result), sp_msg_send_rc_req(&req, &resp)); + MEMCMP_EQUAL(&empty_sp_msg, &resp, sizeof(empty_sp_msg)); +} + +TEST(sp_messaging, sp_msg_send_rc_req_rc_error) +{ + const uint16_t root_id = 1; + const uint16_t own_id = 2; + sp_result sp_err = SP_RESULT_NOT_FOUND; + + wait_and_receive_request(root_id, own_id); + + fill_sp_msg(&req); + req.source_id = own_id; + req.destination_id = root_id; + + fill_ffa_msg(&ffa_msg); + ffa_msg.source_id = root_id; + ffa_msg.destination_id = own_id; + ffa_msg.args[0] = ROUTING_EXT_RC_BIT | ROUTING_EXT_ERR_BIT; + ffa_msg.args[1] = sp_err; + + expect_ffa_msg_send_direct_resp(req.source_id, req.destination_id, + ROUTING_EXT_RC_BIT, req.args[0], + req.args[1], req.args[2], req.args[3], + &ffa_msg, FFA_OK); + + LONGS_EQUAL(sp_err, sp_msg_send_rc_req(&req, &resp)); + MEMCMP_EQUAL(&empty_sp_msg, &resp, sizeof(empty_sp_msg)); +} + +TEST(sp_messaging, sp_msg_send_rc_req_success) +{ + const uint16_t root_id = 1; + const uint16_t own_id = 2; + + wait_and_receive_request(root_id, own_id); + + fill_sp_msg(&req); + req.source_id = own_id; + req.destination_id = root_id; + + fill_ffa_msg(&ffa_msg); + ffa_msg.source_id = root_id; + ffa_msg.destination_id = own_id; + ffa_msg.args[0] = ROUTING_EXT_RC_BIT; + + expect_ffa_msg_send_direct_resp(req.source_id, req.destination_id, + ROUTING_EXT_RC_BIT, req.args[0], + req.args[1], req.args[2], req.args[3], + &ffa_msg, FFA_OK); + + LONGS_EQUAL(SP_RESULT_OK, sp_msg_send_rc_req(&req, &resp)); + ffa_and_sp_msg_equal(&ffa_msg, &resp); +} +#endif diff --git a/components/messaging/ffa/libsp/tests.cmake b/components/messaging/ffa/libsp/tests.cmake index 092aceff3..d851442d5 100644 --- a/components/messaging/ffa/libsp/tests.cmake +++ b/components/messaging/ffa/libsp/tests.cmake @@ -138,4 +138,19 @@ unit_test_add_suite( ${UNIT_TEST_PROJECT_PATH}/components/common/utils/include COMPILE_DEFINITIONS -DARM64 +) + +unit_test_add_suite( + NAME libsp_sp_messaging_with_routing_extension + SOURCES + ${CMAKE_CURRENT_LIST_DIR}/test/test_sp_messaging.cpp + ${CMAKE_CURRENT_LIST_DIR}/test/mock_ffa_api.cpp + ${CMAKE_CURRENT_LIST_DIR}/sp_messaging.c + ${CMAKE_CURRENT_LIST_DIR}/ffa_direct_msg_routing_extension.c + INCLUDE_DIRECTORIES + ${CMAKE_CURRENT_LIST_DIR}/include/ + ${UNIT_TEST_PROJECT_PATH}/components/common/utils/include + COMPILE_DEFINITIONS + -DARM64 + -DFFA_DIRECT_MSG_ROUTING_EXTENSION=1 )
\ No newline at end of file |