MEM: Release rx_buffer after retrieve request
Inside sp_memory_retrieve() ffa_rx_release() wasn't called after calling
ffa_mem_retrieve_req_rxtx(). This resulted in some later error as the
SPMC could not access the buffer afterwards.
Signed-off-by: Jelle Sels <jelle.sels@arm.com>
Change-Id: I0da6026c9bcb8ce64b2741474a4daaff896fb97c
diff --git a/components/messaging/ffa/libsp/sp_memory_management.c b/components/messaging/ffa/libsp/sp_memory_management.c
index 52d03ac..55c7764 100644
--- a/components/messaging/ffa/libsp/sp_memory_management.c
+++ b/components/messaging/ffa/libsp/sp_memory_management.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
*/
#include "sp_memory_management.h"
@@ -560,14 +560,23 @@
/* Fragmentation is not supported currently */
if (resp_total_length != resp_fragment_length) {
*out_region_count = UINT32_C(0);
- return SP_RESULT_INTERNAL_ERROR;
+ sp_res = SP_RESULT_INTERNAL_ERROR;
+ goto out;
}
rx_buffer.used = resp_total_length;
parse_descriptors(&rx_buffer, descriptor, acc_desc, 1, regions,
out_region_count);
- return SP_RESULT_OK;
+out:
+ ffa_res = ffa_rx_release();
+ if (ffa_res != FFA_OK) {
+ /* Keep original error when there was already an error.*/
+ if (sp_res == SP_RESULT_OK)
+ return SP_RESULT_FFA(ffa_res);
+ }
+
+ return sp_res;
}
sp_result
diff --git a/components/messaging/ffa/libsp/test/test_sp_memory_management.cpp b/components/messaging/ffa/libsp/test/test_sp_memory_management.cpp
index 16b6e80..80cfdf3 100644
--- a/components/messaging/ffa/libsp/test/test_sp_memory_management.cpp
+++ b/components/messaging/ffa/libsp/test/test_sp_memory_management.cpp
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
- * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
*/
#include <CppUTestExt/MockSupport.h>
@@ -1121,6 +1121,7 @@
expect_sp_rxtx_buffer_tx_get(&tx_buffer, &buffer_size, SP_RESULT_OK);
expect_sp_rxtx_buffer_rx_get(&rx_buffer, &buffer_size, SP_RESULT_OK);
+ expect_ffa_rx_release(FFA_OK);
expect_ffa_mem_retrieve_req_rxtx(expected_size, expected_size,
&resp_total_length,
&resp_fragment_length, result);
@@ -1131,6 +1132,40 @@
UNSIGNED_LONGS_EQUAL(0, out_region_count);
}
+TEST(sp_memory_management, sp_memory_retrieve_ffa_rx_release_error)
+{
+ struct sp_memory_descriptor desc = SP_MEM_DESC_C(sender_id, tag);
+ struct sp_memory_access_descriptor acc_desc = { .receiver_id =
+ receiver_id };
+ struct sp_memory_region regions = { .address = ptr,
+ .page_count = page_count };
+ uint32_t in_region_count = 1;
+ uint32_t out_region_count = 1;
+ ffa_result result = FFA_ABORTED;
+ const uint32_t expected_size = get_expected_size(in_region_count);
+ const uint32_t resp_total_length = expected_size;
+ const uint32_t resp_fragment_length = expected_size;
+
+ /* Filling RX buffer */
+ ffa_init_mem_transaction_desc(&rx_mem_transaction_buffer, sender_id + 1,
+ 0, 0, handle, tag);
+ ffa_add_mem_access_desc(&rx_mem_transaction_buffer, receiver_id + 1, 0,
+ 0);
+ ffa_add_memory_region(&rx_mem_transaction_buffer, ptr, page_count);
+
+ /* Exercising */
+ expect_sp_rxtx_buffer_tx_get(&tx_buffer, &buffer_size, SP_RESULT_OK);
+ expect_sp_rxtx_buffer_rx_get(&rx_buffer, &buffer_size, SP_RESULT_OK);
+ expect_ffa_rx_release(FFA_DENIED);
+ expect_ffa_mem_retrieve_req_rxtx(expected_size, expected_size,
+ &resp_total_length,
+ &resp_fragment_length, FFA_OK);
+ LONGS_EQUAL(SP_RESULT_FFA(FFA_DENIED),
+ sp_memory_retrieve(&desc, &acc_desc, ®ions,
+ in_region_count, &out_region_count,
+ handle));
+}
+
TEST(sp_memory_management, sp_memory_retrieve_fragmented_response)
{
struct sp_memory_descriptor desc = { 0 };
@@ -1144,6 +1179,7 @@
expect_sp_rxtx_buffer_tx_get(&tx_buffer, &buffer_size, SP_RESULT_OK);
expect_sp_rxtx_buffer_rx_get(&rx_buffer, &buffer_size, SP_RESULT_OK);
+ expect_ffa_rx_release(FFA_OK);
expect_ffa_mem_retrieve_req_rxtx(expected_size, expected_size,
&resp_total_length,
&resp_fragment_length, FFA_OK);
@@ -1178,6 +1214,7 @@
/* Exercising */
expect_sp_rxtx_buffer_tx_get(&tx_buffer, &buffer_size, SP_RESULT_OK);
expect_sp_rxtx_buffer_rx_get(&rx_buffer, &buffer_size, SP_RESULT_OK);
+ expect_ffa_rx_release(FFA_OK);
expect_ffa_mem_retrieve_req_rxtx(expected_size, expected_size,
&resp_total_length,
&resp_fragment_length, FFA_OK);