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
+)