Unit-test FFA ABI-s for notification handling
This change implements unit-tests for the listed FFA ABI-s:
- FFA_NOTIFICATION_BIND
- FFA_NOTIFICATION_UNBIND
- FFA_NOTIFICATION_SET
- FFA_NOTIFICATION_GET
Change-Id: I2faa440a408f1846ffd8f4c1f6528292e49ced4c
Signed-off-by: Gabor Toth <gabor.toth2@arm.com>
diff --git a/components/messaging/ffa/libsp/mock/component.cmake b/components/messaging/ffa/libsp/mock/component.cmake
index 101a56f..a3c3c65 100644
--- a/components/messaging/ffa/libsp/mock/component.cmake
+++ b/components/messaging/ffa/libsp/mock/component.cmake
@@ -17,6 +17,7 @@
"${CMAKE_CURRENT_LIST_DIR}/mock_sp_discovery.cpp"
"${CMAKE_CURRENT_LIST_DIR}/mock_sp_memory_management.cpp"
"${CMAKE_CURRENT_LIST_DIR}/mock_sp_messaging.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/mock_sp_notification.cpp"
"${CMAKE_CURRENT_LIST_DIR}/mock_sp_rxtx.cpp"
)
diff --git a/components/messaging/ffa/libsp/mock/mock_ffa_api.cpp b/components/messaging/ffa/libsp/mock/mock_ffa_api.cpp
index b18731d..aa277f9 100644
--- a/components/messaging/ffa/libsp/mock/mock_ffa_api.cpp
+++ b/components/messaging/ffa/libsp/mock/mock_ffa_api.cpp
@@ -636,3 +636,102 @@
.withUnsignedIntParameter("length", length)
.returnIntValue();
}
+
+void expect_ffa_notification_bind(uint16_t sender, uint16_t receiver, uint32_t flags,
+ uint64_t notification_bitmap, ffa_result result)
+{
+ mock().expectOneCall("ffa_notification_bind")
+ .withUnsignedIntParameter("sender", sender)
+ .withUnsignedIntParameter("receiver", receiver)
+ .withUnsignedIntParameter("flags", flags)
+ .withUnsignedIntParameter("notification_bitmap", notification_bitmap)
+ .andReturnValue(result);
+}
+
+ffa_result ffa_notification_bind(uint16_t sender, uint16_t receiver, uint32_t flags,
+ uint64_t notification_bitmap)
+{
+ return mock()
+ .actualCall("ffa_notification_bind")
+ .withUnsignedIntParameter("sender", sender)
+ .withUnsignedIntParameter("receiver", receiver)
+ .withUnsignedIntParameter("flags", flags)
+ .withUnsignedIntParameter("notification_bitmap", notification_bitmap)
+ .returnIntValue();
+}
+
+void expect_ffa_notification_unbind(uint16_t sender, uint16_t receiver,
+ uint64_t notification_bitmap, ffa_result result)
+{
+ mock().expectOneCall("ffa_notification_unbind")
+ .withUnsignedIntParameter("sender", sender)
+ .withUnsignedIntParameter("receiver", receiver)
+ .withUnsignedIntParameter("notification_bitmap", notification_bitmap)
+ .andReturnValue(result);
+}
+
+ffa_result ffa_notification_unbind(uint16_t sender, uint16_t receiver, uint64_t notification_bitmap)
+{
+ return mock()
+ .actualCall("ffa_notification_unbind")
+ .withUnsignedIntParameter("sender", sender)
+ .withUnsignedIntParameter("receiver", receiver)
+ .withUnsignedIntParameter("notification_bitmap", notification_bitmap)
+ .returnIntValue();
+}
+
+void expect_ffa_notification_set(uint16_t sender, uint16_t receiver, uint32_t flags,
+ uint64_t notification_bitmap, ffa_result result)
+{
+ mock().expectOneCall("ffa_notification_set")
+ .withUnsignedIntParameter("sender", sender)
+ .withUnsignedIntParameter("receiver", receiver)
+ .withUnsignedIntParameter("flags", flags)
+ .withUnsignedIntParameter("notification_bitmap", notification_bitmap)
+ .andReturnValue(result);
+}
+
+ffa_result ffa_notification_set(uint16_t sender, uint16_t receiver, uint32_t flags,
+ uint64_t notification_bitmap)
+{
+ return mock()
+ .actualCall("ffa_notification_set")
+ .withUnsignedIntParameter("sender", sender)
+ .withUnsignedIntParameter("receiver", receiver)
+ .withUnsignedIntParameter("flags", flags)
+ .withUnsignedIntParameter("notification_bitmap", notification_bitmap)
+ .returnIntValue();
+}
+
+void expect_ffa_notification_get(uint16_t sender, uint16_t receiver, uint32_t flags,
+ uint64_t *sp_notification_bitmap, uint64_t *vm_notification_bitmap,
+ uint64_t *framework_notification_bitmap, ffa_result result)
+{
+ mock().expectOneCall("ffa_notification_get")
+ .withUnsignedIntParameter("sender", sender)
+ .withUnsignedIntParameter("receiver", receiver)
+ .withUnsignedIntParameter("flags", flags)
+ .withOutputParameterReturning("sp_notification_bitmap", sp_notification_bitmap,
+ sizeof(*sp_notification_bitmap))
+ .withOutputParameterReturning("vm_notification_bitmap", vm_notification_bitmap,
+ sizeof(*vm_notification_bitmap))
+ .withOutputParameterReturning("framework_notification_bitmap",
+ framework_notification_bitmap,
+ sizeof(*framework_notification_bitmap))
+ .andReturnValue(result);
+}
+
+ffa_result ffa_notification_get(uint16_t sender, uint16_t receiver, uint32_t flags,
+ uint64_t *sp_notification_bitmap, uint64_t *vm_notification_bitmap,
+ uint64_t *framework_notification_bitmap)
+{
+ return mock()
+ .actualCall("ffa_notification_get")
+ .withUnsignedIntParameter("sender", sender)
+ .withUnsignedIntParameter("receiver", receiver)
+ .withUnsignedIntParameter("flags", flags)
+ .withOutputParameter("sp_notification_bitmap", sp_notification_bitmap)
+ .withOutputParameter("vm_notification_bitmap", vm_notification_bitmap)
+ .withOutputParameter("framework_notification_bitmap", framework_notification_bitmap)
+ .returnIntValue();
+}
diff --git a/components/messaging/ffa/libsp/mock/mock_ffa_api.h b/components/messaging/ffa/libsp/mock/mock_ffa_api.h
index 9e43c13..4aad6f5 100644
--- a/components/messaging/ffa/libsp/mock/mock_ffa_api.h
+++ b/components/messaging/ffa/libsp/mock/mock_ffa_api.h
@@ -112,4 +112,17 @@
void expect_ffa_console_log_64(const char *message, size_t length,
ffa_result result);
+void expect_ffa_notification_bind(uint16_t sender, uint16_t receiver, uint32_t flags,
+ uint64_t notification_bitmap, ffa_result result);
+
+void expect_ffa_notification_unbind(uint16_t sender, uint16_t receiver,
+ uint64_t notification_bitmap, ffa_result result);
+
+void expect_ffa_notification_set(uint16_t sender, uint16_t receiver, uint32_t flags,
+ uint64_t notification_bitmap, ffa_result result);
+
+void expect_ffa_notification_get(uint16_t sender, uint16_t receiver, uint32_t flags,
+ uint64_t *sp_notification_bitmap, uint64_t *vm_notification_bitmap,
+ uint64_t *framework_notification_bitmap, ffa_result result);
+
#endif /* FFA_LIBSP_TEST_MOCK_FFA_API_H_ */
diff --git a/components/messaging/ffa/libsp/mock/mock_sp_notification.cpp b/components/messaging/ffa/libsp/mock/mock_sp_notification.cpp
new file mode 100644
index 0000000..fef2840
--- /dev/null
+++ b/components/messaging/ffa/libsp/mock/mock_sp_notification.cpp
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ */
+
+#include <CppUTestExt/MockSupport.h>
+#include "mock_sp_notification.h"
+
+void expect_sp_notification_bind(uint16_t sender, uint16_t receiver,
+ struct sp_notif_bind_flags *flags, uint64_t notification_bitmap,
+ sp_result result)
+{
+ mock().expectOneCall("sp_notification_bind")
+ .withUnsignedIntParameter("sender", sender)
+ .withUnsignedIntParameter("receiver", receiver)
+ .withMemoryBufferParameter("flags", (const uint8_t *)flags, sizeof(*flags))
+ .withUnsignedIntParameter("notification_bitmap", notification_bitmap)
+ .andReturnValue(result);
+}
+
+sp_result sp_notification_bind(uint16_t sender, uint16_t receiver,
+ struct sp_notif_bind_flags *flags, uint64_t notification_bitmap)
+{
+ return mock()
+ .actualCall("sp_notification_bind")
+ .withUnsignedIntParameter("sender", sender)
+ .withUnsignedIntParameter("receiver", receiver)
+ .withMemoryBufferParameter("flags", (const uint8_t *)flags, sizeof(*flags))
+ .withUnsignedIntParameter("notification_bitmap", notification_bitmap)
+ .returnIntValue();
+}
+
+void expect_sp_notification_unbind(uint16_t sender, uint16_t receiver, uint64_t notification_bitmap,
+ sp_result result)
+{
+ mock().expectOneCall("sp_notification_unbind")
+ .withUnsignedIntParameter("sender", sender)
+ .withUnsignedIntParameter("receiver", receiver)
+ .withUnsignedIntParameter("notification_bitmap", notification_bitmap)
+ .andReturnValue(result);
+}
+
+sp_result sp_notification_unbind(uint16_t sender, uint16_t receiver, uint64_t notification_bitmap)
+{
+ return mock()
+ .actualCall("sp_notification_unbind")
+ .withUnsignedIntParameter("sender", sender)
+ .withUnsignedIntParameter("receiver", receiver)
+ .withUnsignedIntParameter("notification_bitmap", notification_bitmap)
+ .returnIntValue();
+}
+
+void expect_sp_notification_set(uint16_t sender, uint16_t receiver,
+ struct sp_notif_set_flags *flags, uint64_t notification_bitmap,
+ sp_result result)
+{
+ mock().expectOneCall("sp_notification_set")
+ .withUnsignedIntParameter("sender", sender)
+ .withUnsignedIntParameter("receiver", receiver)
+ .withMemoryBufferParameter("flags", (const uint8_t *)flags, sizeof(*flags))
+ .withUnsignedIntParameter("notification_bitmap", notification_bitmap)
+ .andReturnValue(result);
+}
+
+sp_result sp_notification_set(uint16_t sender, uint16_t receiver, struct sp_notif_set_flags *flags,
+ uint64_t notification_bitmap)
+{
+ return mock()
+ .actualCall("sp_notification_set")
+ .withUnsignedIntParameter("sender", sender)
+ .withUnsignedIntParameter("receiver", receiver)
+ .withMemoryBufferParameter("flags", (const uint8_t *)flags, sizeof(*flags))
+ .withUnsignedIntParameter("notification_bitmap", notification_bitmap)
+ .returnIntValue();
+}
+
+void expect_sp_notification_get(uint16_t sender, uint16_t receiver,
+ uint64_t *sp_notification_bitmap, uint64_t *vm_notification_bitmap,
+ uint32_t *spm_notification_bitmap, uint32_t *hv_notification_bitmap,
+ sp_result result)
+{
+ mock().expectOneCall("sp_notification_get")
+ .withUnsignedIntParameter("sender", sender)
+ .withUnsignedIntParameter("receiver", receiver)
+ .withOutputParameterReturning("sp_notification_bitmap", sp_notification_bitmap,
+ sizeof(*sp_notification_bitmap))
+ .withOutputParameterReturning("vm_notification_bitmap", vm_notification_bitmap,
+ sizeof(*vm_notification_bitmap))
+ .withOutputParameterReturning("spm_notification_bitmap", spm_notification_bitmap,
+ sizeof(*spm_notification_bitmap))
+ .withOutputParameterReturning("hv_notification_bitmap", hv_notification_bitmap,
+ sizeof(*hv_notification_bitmap))
+ .andReturnValue(result);
+}
+
+sp_result sp_notification_get(uint16_t sender, uint16_t receiver, uint64_t *sp_notification_bitmap,
+ uint64_t *vm_notification_bitmap, uint32_t *spm_notification_bitmap,
+ uint32_t *hv_notification_bitmap)
+{
+ return mock()
+ .actualCall("sp_notification_get")
+ .withUnsignedIntParameter("sender", sender)
+ .withUnsignedIntParameter("receiver", receiver)
+ .withOutputParameter("sp_notification_bitmap", sp_notification_bitmap)
+ .withOutputParameter("vm_notification_bitmap", vm_notification_bitmap)
+ .withOutputParameter("spm_notification_bitmap", spm_notification_bitmap)
+ .withOutputParameter("hv_notification_bitmap", hv_notification_bitmap)
+ .returnIntValue();
+}
diff --git a/components/messaging/ffa/libsp/mock/mock_sp_notification.h b/components/messaging/ffa/libsp/mock/mock_sp_notification.h
new file mode 100644
index 0000000..3e9bcc2
--- /dev/null
+++ b/components/messaging/ffa/libsp/mock/mock_sp_notification.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ */
+
+#ifndef LIBSP_MOCK_MOCK_SP_NOTIFICATION_H_
+#define LIBSP_MOCK_MOCK_SP_NOTIFICATION_H_
+
+#include "../include/sp_notification.h"
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void expect_sp_notification_bind(uint16_t sender, uint16_t receiver,
+ struct sp_notif_bind_flags *flags, uint64_t notification_bitmap,
+ sp_result result);
+void expect_sp_notification_unbind(uint16_t sender, uint16_t receiver, uint64_t notification_bitmap,
+ sp_result result);
+void expect_sp_notification_set(uint16_t sender, uint16_t receiver,
+ struct sp_notif_set_flags *flags, uint64_t notification_bitmap,
+ sp_result result);
+void expect_sp_notification_get(uint16_t sender, uint16_t receiver,
+ uint64_t *sp_notification_bitmap, uint64_t *vm_notification_bitmap,
+ uint32_t *spm_notification_bitmap, uint32_t *hv_notification_bitmap,
+ sp_result result);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBSP_MOCK_MOCK_SP_NOTIFICATION_H_ */
diff --git a/components/messaging/ffa/libsp/mock/test/test_mock_ffa_api.cpp b/components/messaging/ffa/libsp/mock/test/test_mock_ffa_api.cpp
index 4405712..7be80c8 100644
--- a/components/messaging/ffa/libsp/mock/test/test_mock_ffa_api.cpp
+++ b/components/messaging/ffa/libsp/mock/test/test_mock_ffa_api.cpp
@@ -388,3 +388,56 @@
expect_ffa_console_log_64(message, length, result);
LONGS_EQUAL(result, ffa_console_log_64(message, length));
}
+
+TEST(mock_ffa_api, ffa_notification_bind)
+{
+ const uint16_t sender = 1;
+ const uint16_t receiver = 2;
+ const uint32_t flags = 0xAAAA;
+ const uint64_t notification_bitmap = 0x55555555;
+
+ expect_ffa_notification_bind(sender, receiver, flags, notification_bitmap, result);
+ LONGS_EQUAL(result, ffa_notification_bind(sender, receiver, flags, notification_bitmap));
+}
+
+TEST(mock_ffa_api, ffa_notification_unbind)
+{
+ const uint16_t sender = 1;
+ const uint16_t receiver = 2;
+ const uint64_t notification_bitmap = 0x55555555;
+
+ expect_ffa_notification_unbind(sender, receiver, notification_bitmap, result);
+ LONGS_EQUAL(result, ffa_notification_unbind(sender, receiver, notification_bitmap));
+}
+
+TEST(mock_ffa_api, ffa_notification_set)
+{
+ const uint16_t sender = 1;
+ const uint16_t receiver = 2;
+ const uint32_t flags = 0xAAAA;
+ const uint64_t notification_bitmap = 0x55555555;
+
+ expect_ffa_notification_set(sender, receiver, flags, notification_bitmap, result);
+ LONGS_EQUAL(result, ffa_notification_set(sender, receiver, flags, notification_bitmap));
+}
+
+TEST(mock_ffa_api, ffa_notification_get)
+{
+ const uint16_t sender = 1;
+ const uint16_t receiver = 2;
+ const uint32_t flags = 0xAAAA;
+ uint64_t expected_notification_bitmap = 0x55555555;
+ uint64_t sp_notification_bitmap = 0;
+ uint64_t vm_notification_bitmap = 0;
+ uint64_t framework_notification_bitmap = 0;
+
+ expect_ffa_notification_get(sender, receiver, flags, &expected_notification_bitmap,
+ &expected_notification_bitmap, &expected_notification_bitmap,
+ result);
+ LONGS_EQUAL(result,
+ ffa_notification_get(sender, receiver, flags, &sp_notification_bitmap,
+ &vm_notification_bitmap, &framework_notification_bitmap));
+ LONGS_EQUAL(sp_notification_bitmap, expected_notification_bitmap);
+ LONGS_EQUAL(vm_notification_bitmap, expected_notification_bitmap);
+ LONGS_EQUAL(framework_notification_bitmap, expected_notification_bitmap);
+}
diff --git a/components/messaging/ffa/libsp/mock/test/test_mock_sp_notification.cpp b/components/messaging/ffa/libsp/mock/test/test_mock_sp_notification.cpp
new file mode 100644
index 0000000..3eac96d
--- /dev/null
+++ b/components/messaging/ffa/libsp/mock/test/test_mock_sp_notification.cpp
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ */
+
+#include <CppUTestExt/MockSupport.h>
+#include <CppUTest/TestHarness.h>
+#include "mock_sp_notification.h"
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+TEST_GROUP(mock_sp_notification)
+{
+ TEST_TEARDOWN()
+ {
+ mock().checkExpectations();
+ mock().clear();
+ }
+
+ static const sp_result result = -1;
+ struct sp_notif_bind_flags bind_flags = { .per_cpu = 1 };
+ struct sp_notif_set_flags set_flags = { .per_cpu = 1,
+ .delay_sched_rec_intr = 0,
+ .receiver_vcpu_id = 42 };
+};
+
+TEST(mock_sp_notification, sp_notification_bind)
+{
+ const uint16_t sender = 1;
+ const uint16_t receiver = 2;
+ const uint64_t notification_bitmap = 0x55555555;
+
+ expect_sp_notification_bind(sender, receiver, &bind_flags, notification_bitmap, result);
+ LONGS_EQUAL(result,
+ sp_notification_bind(sender, receiver, &bind_flags, notification_bitmap));
+}
+
+TEST(mock_sp_notification, sp_notification_unbind)
+{
+ const uint16_t sender = 1;
+ const uint16_t receiver = 2;
+ const uint64_t notification_bitmap = 0x55555555;
+
+ expect_sp_notification_unbind(sender, receiver, notification_bitmap, result);
+ LONGS_EQUAL(result, sp_notification_unbind(sender, receiver, notification_bitmap));
+}
+
+TEST(mock_sp_notification, sp_notification_set)
+{
+ const uint16_t sender = 1;
+ const uint16_t receiver = 2;
+ const uint64_t notification_bitmap = 0x55555555;
+
+ expect_sp_notification_set(sender, receiver, &set_flags, notification_bitmap, result);
+ LONGS_EQUAL(result, sp_notification_set(sender, receiver, &set_flags, notification_bitmap));
+}
+
+TEST(mock_sp_notification, sp_notification_get)
+{
+ const uint16_t sender = 1;
+ const uint16_t receiver = 2;
+ uint64_t expected_notification_bitmap = 0x55555555;
+ uint64_t sp_notification_bitmap = 0;
+ uint64_t vm_notification_bitmap = 0;
+ uint32_t spm_notification_bitmap = 0;
+ uint32_t hv_notification_bitmap = 0;
+
+ expect_sp_notification_get(sender, receiver, &expected_notification_bitmap,
+ &expected_notification_bitmap,
+ (uint32_t *)&expected_notification_bitmap,
+ (uint32_t *)&expected_notification_bitmap, result);
+ LONGS_EQUAL(result, sp_notification_get(sender, receiver, &sp_notification_bitmap,
+ &vm_notification_bitmap, &spm_notification_bitmap,
+ &hv_notification_bitmap));
+ LONGS_EQUAL(sp_notification_bitmap, expected_notification_bitmap);
+ LONGS_EQUAL(vm_notification_bitmap, expected_notification_bitmap);
+ LONGS_EQUAL(spm_notification_bitmap, expected_notification_bitmap);
+ LONGS_EQUAL(hv_notification_bitmap, expected_notification_bitmap);
+}
diff --git a/components/messaging/ffa/libsp/test/sp_notification_internals.yml b/components/messaging/ffa/libsp/test/sp_notification_internals.yml
new file mode 100644
index 0000000..74ee84b
--- /dev/null
+++ b/components/messaging/ffa/libsp/test/sp_notification_internals.yml
@@ -0,0 +1,17 @@
+#
+# Copyright (c) 2025, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+elements:
+- file: components/messaging/ffa/libsp/sp_notification.c
+ type: include
+- file: components/messaging/ffa/libsp/sp_notification.c
+ type: function
+ name: build_notif_bind_flags
+ options: [remove_static]
+- file: components/messaging/ffa/libsp/sp_notification.c
+ type: function
+ name: build_notif_set_flags
+ options: [remove_static]
diff --git a/components/messaging/ffa/libsp/test/test_ffa_api.cpp b/components/messaging/ffa/libsp/test/test_ffa_api.cpp
index c7c26fe..9ea4889 100644
--- a/components/messaging/ffa/libsp/test/test_ffa_api.cpp
+++ b/components/messaging/ffa/libsp/test/test_ffa_api.cpp
@@ -1912,3 +1912,148 @@
0x6261393837363534, &svc_result);
ffa_console_log_64(message, length);
}
+
+TEST(ffa_api, ffa_notification_bind_success)
+{
+ const uint16_t sender = 0x1234;
+ const uint16_t receiver = 0x5678;
+ const uint32_t flags = 0xAAAAAAAA;
+ const uint64_t notification_bitmap = 0x55555555AAAAAAAA;
+
+ svc_result.a0 = 0x84000061;
+ expect_ffa_svc(0x8400007F, sender << 16 | receiver, flags, notification_bitmap & 0xFFFFFFFF,
+ (notification_bitmap >> 32) & 0xFFFFFFFF, 0, 0, 0, &svc_result);
+ ffa_result result = ffa_notification_bind(sender, receiver, flags, notification_bitmap);
+
+ LONGS_EQUAL(0, result);
+}
+
+TEST(ffa_api, ffa_notification_bind_error)
+{
+ const uint16_t sender = 0x1234;
+ const uint16_t receiver = 0x5678;
+ const uint32_t flags = 0xAAAAAAAA;
+ const uint64_t notification_bitmap = 0x55555555AAAAAAAA;
+
+ setup_error_response(-1);
+ expect_ffa_svc(0x8400007F, sender << 16 | receiver, flags, notification_bitmap & 0xFFFFFFFF,
+ (notification_bitmap >> 32) & 0xFFFFFFFF, 0, 0, 0, &svc_result);
+ ffa_result result = ffa_notification_bind(sender, receiver, flags, notification_bitmap);
+
+ LONGS_EQUAL(-1, result);
+}
+
+TEST(ffa_api, ffa_notification_unbind_success)
+{
+ const uint16_t sender = 0x1234;
+ const uint16_t receiver = 0x5678;
+ const uint64_t notification_bitmap = 0x55555555AAAAAAAA;
+
+ svc_result.a0 = 0x84000061;
+ expect_ffa_svc(0x84000080, sender << 16 | receiver, 0, notification_bitmap & 0xFFFFFFFF,
+ (notification_bitmap >> 32) & 0xFFFFFFFF, 0, 0, 0, &svc_result);
+ ffa_result result = ffa_notification_unbind(sender, receiver, notification_bitmap);
+
+ LONGS_EQUAL(0, result);
+}
+
+TEST(ffa_api, ffa_notification_unbind_error)
+{
+ const uint16_t sender = 0x1234;
+ const uint16_t receiver = 0x5678;
+ const uint64_t notification_bitmap = 0x55555555AAAAAAAA;
+
+ setup_error_response(-1);
+ expect_ffa_svc(0x84000080, sender << 16 | receiver, 0, notification_bitmap & 0xFFFFFFFF,
+ (notification_bitmap >> 32) & 0xFFFFFFFF, 0, 0, 0, &svc_result);
+ ffa_result result = ffa_notification_unbind(sender, receiver, notification_bitmap);
+
+ LONGS_EQUAL(-1, result);
+}
+
+TEST(ffa_api, ffa_notification_set_success)
+{
+ const uint16_t sender = 0x1234;
+ const uint16_t receiver = 0x5678;
+ const uint32_t flags = 0xF;
+ const uint64_t notification_bitmap = 0x55555555AAAAAAAA;
+
+ svc_result.a0 = 0x84000061;
+ expect_ffa_svc(0x84000081, sender << 16 | receiver, flags, notification_bitmap & 0xFFFFFFFF,
+ (notification_bitmap >> 32) & 0xFFFFFFFF, 0, 0, 0, &svc_result);
+ ffa_result result = ffa_notification_set(sender, receiver, flags, notification_bitmap);
+
+ LONGS_EQUAL(0, result);
+}
+
+TEST(ffa_api, ffa_notification_set_error)
+{
+ const uint16_t sender = 0x1234;
+ const uint16_t receiver = 0x5678;
+ const uint32_t flags = 0xF;
+ const uint64_t notification_bitmap = 0x55555555AAAAAAAA;
+
+ setup_error_response(-1);
+ expect_ffa_svc(0x84000081, sender << 16 | receiver, flags, notification_bitmap & 0xFFFFFFFF,
+ (notification_bitmap >> 32) & 0xFFFFFFFF, 0, 0, 0, &svc_result);
+ ffa_result result = ffa_notification_set(sender, receiver, flags, notification_bitmap);
+
+ LONGS_EQUAL(-1, result);
+}
+
+TEST(ffa_api, ffa_notification_set_invalid_flag)
+{
+ const uint16_t sender = 0x1234;
+ const uint16_t receiver = 0x5678;
+ const uint32_t flags = 0xAAAAAAAA;
+ const uint64_t notification_bitmap = 0x55555555AAAAAAAA;
+
+ ffa_result result = ffa_notification_set(sender, receiver, flags, notification_bitmap);
+
+ LONGS_EQUAL(FFA_INVALID_PARAMETERS, result);
+}
+
+TEST(ffa_api, ffa_notification_get_success)
+{
+ const uint16_t sender = 0x1234;
+ const uint16_t receiver = 0x5678;
+ const uint32_t flags = 0xF;
+ uint64_t sp_notification_bitmap = 0;
+ uint64_t vm_notification_bitmap = 0;
+ uint64_t framework_notification_bitmap = 0;
+
+ svc_result.a0 = 0x84000061;
+ svc_result.a2 = 0xAAAAAAAA;
+ svc_result.a3 = 0xBBBBBBBB;
+ svc_result.a4 = 0xCCCCCCCC;
+ svc_result.a5 = 0xDDDDDDDD;
+ svc_result.a6 = 0xEEEEEEEE;
+ svc_result.a7 = 0xFFFFFFFF;
+ expect_ffa_svc(0x84000082, sender << 16 | receiver, flags, 0, 0, 0, 0, 0, &svc_result);
+ ffa_result result = ffa_notification_get(sender, receiver, flags, &sp_notification_bitmap,
+ &vm_notification_bitmap,
+ &framework_notification_bitmap);
+
+ LONGS_EQUAL(0, result);
+ LONGS_EQUAL(sp_notification_bitmap, 0xBBBBBBBBAAAAAAAA);
+ LONGS_EQUAL(vm_notification_bitmap, 0xDDDDDDDDCCCCCCCC);
+ LONGS_EQUAL(framework_notification_bitmap, 0xFFFFFFFFEEEEEEEE);
+}
+
+TEST(ffa_api, ffa_notification_get_error)
+{
+ const uint16_t sender = 0x1234;
+ const uint16_t receiver = 0x5678;
+ const uint32_t flags = 0xF;
+ uint64_t sp_notification_bitmap = 0;
+ uint64_t vm_notification_bitmap = 0;
+ uint64_t framework_notification_bitmap = 0;
+
+ setup_error_response(-1);
+ expect_ffa_svc(0x84000082, sender << 16 | receiver, flags, 0, 0, 0, 0, 0, &svc_result);
+ ffa_result result = ffa_notification_get(sender, receiver, flags, &sp_notification_bitmap,
+ &vm_notification_bitmap,
+ &framework_notification_bitmap);
+
+ LONGS_EQUAL(-1, result);
+}
diff --git a/components/messaging/ffa/libsp/test/test_sp_notification.cpp b/components/messaging/ffa/libsp/test/test_sp_notification.cpp
new file mode 100644
index 0000000..38b9fce
--- /dev/null
+++ b/components/messaging/ffa/libsp/test/test_sp_notification.cpp
@@ -0,0 +1,187 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ */
+
+#include <CppUTest/TestHarness.h>
+#include <CppUTestExt/MockSupport.h>
+#include <stdint.h>
+#include <string.h>
+#include "mock_ffa_api.h"
+#include "../include/sp_notification.h"
+
+/* Picked functions */
+extern "C" {
+uint32_t build_notif_bind_flags(struct sp_notif_bind_flags *flags);
+uint32_t build_notif_set_flags(struct sp_notif_set_flags *flags);
+}
+
+TEST_GROUP(sp_notification)
+{
+ TEST_TEARDOWN()
+ {
+ mock().checkExpectations();
+ mock().clear();
+ }
+
+ const uint16_t sender = 1;
+ const uint16_t receiver = 2;
+ struct sp_notif_bind_flags bind_flags_percpu = { .per_cpu = 1 };
+ struct sp_notif_bind_flags bind_flags_global = { .per_cpu = 0 };
+ struct sp_notif_set_flags set_flags = { .per_cpu = 1,
+ .delay_sched_rec_intr = 0,
+ .receiver_vcpu_id = 42 };
+ struct sp_notif_set_flags set_flags_invalid = { .per_cpu = 0,
+ .delay_sched_rec_intr = 1,
+ .receiver_vcpu_id = 42 };
+ uint64_t test_sp_notification_bitmap = 0xAAAAAAAABBBBBBBB;
+ uint64_t test_vm_notification_bitmap = 0xCCCCCCCCDDDDDDDD;
+ uint64_t test_fw_notification_bitmap = 0xEEEEEEEEFFFFFFFF;
+};
+
+TEST(sp_notification, build_notif_bind_flags_global)
+{
+ uint32_t result = 0;
+
+ result = build_notif_bind_flags(&bind_flags_global);
+ UNSIGNED_LONGS_EQUAL(0, result);
+}
+
+TEST(sp_notification, build_notif_bind_flags_percpu)
+{
+ uint32_t expected_result = bind_flags_global.per_cpu;
+ uint32_t result = 0;
+
+ result = build_notif_bind_flags(&bind_flags_global);
+ UNSIGNED_LONGS_EQUAL(expected_result, result);
+}
+
+TEST(sp_notification, build_notif_set_flags)
+{
+ uint32_t expected_result = set_flags.receiver_vcpu_id
+ << FFA_NOTIF_SET_FLAGS_RECEIVER_VCPU_SHIFT |
+ FFA_NOTIF_SET_FLAGS_PER_VCPU_NOTIFICATIONS;
+ uint32_t result = 0;
+
+ result = build_notif_set_flags(&set_flags);
+ UNSIGNED_LONGS_EQUAL(expected_result, result);
+}
+
+TEST(sp_notification, build_notif_set_flags_invalid)
+{
+ uint32_t expected_result = FFA_NOTIF_SET_FLAGS_DELAY_SCHEDULE_RECEIVER;
+ uint32_t result = 0;
+
+ result = build_notif_set_flags(&set_flags_invalid);
+ UNSIGNED_LONGS_EQUAL(expected_result, result);
+}
+
+TEST(sp_notification, sp_notification_bind_error)
+{
+ ffa_result result = FFA_ABORTED;
+ expect_ffa_notification_bind(sender, receiver, build_notif_bind_flags(&bind_flags_percpu),
+ test_sp_notification_bitmap, result);
+ LONGS_EQUAL(SP_RESULT_FFA(result),
+ sp_notification_bind(sender, receiver, &bind_flags_percpu,
+ test_sp_notification_bitmap));
+}
+
+TEST(sp_notification, sp_notification_bind)
+{
+ ffa_result result = FFA_OK;
+ expect_ffa_notification_bind(sender, receiver, build_notif_bind_flags(&bind_flags_percpu),
+ test_sp_notification_bitmap, result);
+ LONGS_EQUAL(SP_RESULT_FFA(result),
+ sp_notification_bind(sender, receiver, &bind_flags_percpu,
+ test_sp_notification_bitmap));
+}
+
+TEST(sp_notification, sp_notification_unbind_error)
+{
+ ffa_result result = FFA_ABORTED;
+ expect_ffa_notification_unbind(sender, receiver, test_sp_notification_bitmap, result);
+ LONGS_EQUAL(SP_RESULT_FFA(result),
+ sp_notification_unbind(sender, receiver, test_sp_notification_bitmap));
+}
+
+TEST(sp_notification, sp_notification_unbind)
+{
+ ffa_result result = FFA_OK;
+ expect_ffa_notification_unbind(sender, receiver, test_sp_notification_bitmap, result);
+ LONGS_EQUAL(SP_RESULT_FFA(result),
+ sp_notification_unbind(sender, receiver, test_sp_notification_bitmap));
+}
+
+TEST(sp_notification, sp_notification_set_error)
+{
+ ffa_result result = FFA_ABORTED;
+ expect_ffa_notification_set(sender, receiver, build_notif_set_flags(&set_flags),
+ test_sp_notification_bitmap, result);
+ LONGS_EQUAL(SP_RESULT_FFA(result),
+ sp_notification_set(sender, receiver, &set_flags, test_sp_notification_bitmap));
+}
+
+TEST(sp_notification, sp_notification_set_invalid_flag)
+{
+ LONGS_EQUAL(SP_RESULT_INVALID_PARAMETERS,
+ sp_notification_set(sender, receiver, &set_flags_invalid,
+ test_sp_notification_bitmap));
+}
+
+TEST(sp_notification, sp_notification_set)
+{
+ ffa_result result = FFA_OK;
+ expect_ffa_notification_set(sender, receiver, build_notif_set_flags(&set_flags),
+ test_sp_notification_bitmap, result);
+ LONGS_EQUAL(SP_RESULT_FFA(result),
+ sp_notification_set(sender, receiver, &set_flags, test_sp_notification_bitmap));
+}
+
+TEST(sp_notification, sp_notification_get_error)
+{
+ ffa_result result = FFA_ABORTED;
+ uint64_t sp_notification_bitmap = 0;
+ uint64_t vm_notification_bitmap = 0;
+ uint32_t spm_notification_bitmap = 0;
+ uint32_t hv_notification_bitmap = 0;
+
+ expect_ffa_notification_get(sender, receiver, 0xF, &test_sp_notification_bitmap,
+ &test_vm_notification_bitmap, &test_fw_notification_bitmap,
+ result);
+ LONGS_EQUAL(SP_RESULT_FFA(result),
+ sp_notification_get(sender, receiver, &sp_notification_bitmap,
+ &vm_notification_bitmap, &spm_notification_bitmap,
+ &hv_notification_bitmap));
+}
+
+TEST(sp_notification, sp_notification_get_null_param)
+{
+ ffa_result result = FFA_OK;
+ uint64_t dummy = 0;
+
+ expect_ffa_notification_get(sender, receiver, 0, &dummy, &dummy, &dummy, result);
+
+ LONGS_EQUAL(SP_RESULT_FFA(result),
+ sp_notification_get(sender, receiver, NULL, NULL, NULL, NULL));
+}
+
+TEST(sp_notification, sp_notification_get)
+{
+ ffa_result result = FFA_OK;
+ uint64_t sp_notification_bitmap = 0;
+ uint64_t vm_notification_bitmap = 0;
+ uint32_t spm_notification_bitmap = 0;
+ uint32_t hv_notification_bitmap = 0;
+
+ expect_ffa_notification_get(sender, receiver, 0xF, &test_sp_notification_bitmap,
+ &test_vm_notification_bitmap, &test_fw_notification_bitmap,
+ result);
+ LONGS_EQUAL(SP_RESULT_FFA(result),
+ sp_notification_get(sender, receiver, &sp_notification_bitmap,
+ &vm_notification_bitmap, &spm_notification_bitmap,
+ &hv_notification_bitmap));
+ LONGS_EQUAL(sp_notification_bitmap, test_sp_notification_bitmap);
+ LONGS_EQUAL(vm_notification_bitmap, test_vm_notification_bitmap);
+ LONGS_EQUAL(spm_notification_bitmap, test_fw_notification_bitmap & 0xFFFFFFFF);
+ LONGS_EQUAL(hv_notification_bitmap, test_fw_notification_bitmap >> 32 & 0xFFFFFFFF);
+}
diff --git a/components/messaging/ffa/libsp/tests.cmake b/components/messaging/ffa/libsp/tests.cmake
index 80df5cd..c118d98 100644
--- a/components/messaging/ffa/libsp/tests.cmake
+++ b/components/messaging/ffa/libsp/tests.cmake
@@ -249,4 +249,34 @@
-DARM64
-DFFA_DIRECT_MSG_ROUTING_EXTENSION=1
-DCFG_FFA_VERSION=0x00010000
-)
\ No newline at end of file
+)
+
+unit_test_add_suite(
+ NAME libsp_sp_notification
+ SOURCES
+ ${CMAKE_CURRENT_LIST_DIR}/test/test_sp_notification.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/test/sp_notification_internals.yml
+ ${CMAKE_CURRENT_LIST_DIR}/mock/mock_ffa_api.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/sp_notification.c
+ INCLUDE_DIRECTORIES
+ ${CMAKE_CURRENT_LIST_DIR}/include/
+ ${CMAKE_CURRENT_LIST_DIR}/mock
+ ${UNIT_TEST_PROJECT_PATH}/components/common/utils/include
+ COMPILE_DEFINITIONS
+ -DARM64
+ -DCFG_FFA_VERSION=0x00010000
+)
+
+unit_test_add_suite(
+ NAME libsp_mock_sp_notification
+ SOURCES
+ ${CMAKE_CURRENT_LIST_DIR}/mock/test/test_mock_sp_notification.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/mock/mock_sp_notification.cpp
+ INCLUDE_DIRECTORIES
+ ${CMAKE_CURRENT_LIST_DIR}/include/
+ ${CMAKE_CURRENT_LIST_DIR}/mock
+ ${UNIT_TEST_PROJECT_PATH}/components/common/utils/include
+ COMPILE_DEFINITIONS
+ -DARM64
+ -DCFG_FFA_VERSION=0x00010000
+)