Fix interrupted FFA_MSG_SEND_DIRECT_REQ handling
If a secure partition invokes another endpoint via
FFA_MSG_SEND_DIRECT_REQ the SPMC might return FFA_INTERRUPT if the
request was preempted by an interrupt. In this case the caller SP must
resume the request using FFA_RUN. Until now this case was mistakenly
treated as a secure interrupt targeting the caller.
Fix ffa_msg_send_direct_req function in libsp to follow the described
desired behavior.
Signed-off-by: Imre Kis <imre.kis@arm.com>
Change-Id: I848424a38698133006098f5ee4f89f610aa8c21c
diff --git a/components/messaging/ffa/libsp/ffa.c b/components/messaging/ffa/libsp/ffa.c
index 76f0eda..03431dd 100644
--- a/components/messaging/ffa/libsp/ffa.c
+++ b/components/messaging/ffa/libsp/ffa.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
- * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2025, Arm Limited and Contributors. All rights reserved.
*/
#include <assert.h> // for assert
@@ -312,8 +312,9 @@
dest, FFA_PARAM_MBZ, a0, a1, a2, a3, a4, &result);
while (result.a0 == FFA_INTERRUPT) {
- ffa_interrupt_handler(result.a2);
- ffa_return_from_interrupt(&result);
+ ffa_svc(FFA_RUN, result.a1, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+ FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+ &result);
}
if (result.a0 == FFA_ERROR) {
diff --git a/components/messaging/ffa/libsp/include/ffa_api_defines.h b/components/messaging/ffa/libsp/include/ffa_api_defines.h
index 23389a5..39cd0e8 100644
--- a/components/messaging/ffa/libsp/include/ffa_api_defines.h
+++ b/components/messaging/ffa/libsp/include/ffa_api_defines.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause */
/*
- * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2025, Arm Limited and Contributors. All rights reserved.
*/
#ifndef LIBSP_INCLUDE_FFA_API_DEFINES_H_
@@ -43,8 +43,8 @@
#define FFA_PARTITION_INFO_GET UINT32_C(0x84000068)
#define FFA_ID_GET UINT32_C(0x84000069)
#define FFA_MSG_WAIT UINT32_C(0x8400006B)
-#define FFA_MSG_YIELD UINT32_C(0x8400006C)
-#define FFA_MSG_RUN UINT32_C(0x8400006D)
+#define FFA_YIELD UINT32_C(0x8400006C)
+#define FFA_RUN UINT32_C(0x8400006D)
#define FFA_MSG_SEND UINT32_C(0x8400006E)
#define FFA_MSG_SEND_DIRECT_REQ_32 UINT32_C(0x8400006F)
#define FFA_MSG_SEND_DIRECT_REQ_64 UINT32_C(0xC400006F)
diff --git a/components/messaging/ffa/libsp/test/test_ffa_api.cpp b/components/messaging/ffa/libsp/test/test_ffa_api.cpp
index 9660599..03b5fe0 100644
--- a/components/messaging/ffa/libsp/test/test_ffa_api.cpp
+++ b/components/messaging/ffa/libsp/test/test_ffa_api.cpp
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
- * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2025, Arm Limited. All rights reserved.
*/
#include <CppUTest/TestHarness.h>
@@ -923,6 +923,7 @@
{
const uint16_t source_id = 0x1122;
const uint16_t dest_id = 0x3344;
+ const uint32_t target_info = ((uint32_t)dest_id << 16 | 0x5678);
const uint32_t arg0 = 0x01234567ULL;
const uint32_t arg1 = 0x12345678ULL;
const uint32_t arg2 = 0x23456789ULL;
@@ -932,13 +933,12 @@
struct ffa_params interrupt_params;
interrupt_params.a0 = 0x84000062;
- interrupt_params.a2 = interrupt_id;
+ interrupt_params.a1 = target_info;
expect_ffa_svc(0x8400006F, ((uint32_t)source_id << 16) | dest_id, 0,
arg0, arg1, arg2, arg3, arg4, &interrupt_params);
- expect_ffa_interrupt_handler(interrupt_id);
svc_result.a0 = 0x84000061;
- expect_ffa_svc(0x8400006B, 0, 0, 0, 0, 0, 0, 0, &svc_result);
+ expect_ffa_svc(0x8400006D, target_info, 0, 0, 0, 0, 0, 0, &svc_result);
ffa_result result = ffa_msg_send_direct_req_32(
source_id, dest_id, arg0, arg1, arg2, arg3, arg4, &msg);
LONGS_EQUAL(0, result);
@@ -949,6 +949,7 @@
{
const uint16_t source_id = 0x1122;
const uint16_t dest_id = 0x3344;
+ const uint32_t target_info = ((uint32_t)dest_id << 16 | 0x5678);
const uint32_t arg0 = 0x01234567ULL;
const uint32_t arg1 = 0x12345678ULL;
const uint32_t arg2 = 0x23456789ULL;
@@ -961,18 +962,16 @@
struct ffa_params interrupt_params1;
interrupt_params0.a0 = 0x84000062;
- interrupt_params0.a2 = interrupt_id0;
+ interrupt_params0.a1 = target_info;
expect_ffa_svc(0x8400006F, ((uint32_t)source_id << 16) | dest_id, 0,
arg0, arg1, arg2, arg3, arg4, &interrupt_params0);
- expect_ffa_interrupt_handler(interrupt_id0);
interrupt_params1.a0 = 0x84000062;
- interrupt_params1.a2 = interrupt_id1;
- expect_ffa_svc(0x8400006B, 0, 0, 0, 0, 0, 0, 0, &interrupt_params1);
- expect_ffa_interrupt_handler(interrupt_id1);
+ interrupt_params1.a1 = target_info;
+ expect_ffa_svc(0x8400006D, target_info, 0, 0, 0, 0, 0, 0, &interrupt_params1);
svc_result.a0 = 0x84000061;
- expect_ffa_svc(0x8400006B, 0, 0, 0, 0, 0, 0, 0, &svc_result);
+ expect_ffa_svc(0x8400006D, target_info, 0, 0, 0, 0, 0, 0, &svc_result);
ffa_result result = ffa_msg_send_direct_req_32(
source_id, dest_id, arg0, arg1, arg2, arg3, arg4, &msg);
LONGS_EQUAL(0, result);