[PATCH] lib: sbi_mpxy: Fix shared memory size rounding

Shibo Zhu 3499129952 at qq.com
Mon Aug 17 08:55:37 PDT 2026


sbi_mpxy_register_channel() currently performs ceiling division by
PAGE_SIZE but stores the resulting page count in mpxy_shmem_size. All
consumers interpret mpxy_shmem_size as a byte count, so channels requiring
more than one page produce an undersized shared memory value.

Use ROUNDUP() to keep the rounded value in bytes. Add SBIUnit coverage for
page boundaries and ensure smaller channels do not reduce the shared memory
size.

Fixes: ec09918426a5 ("lib: sbi: Update MPXY framework and SBI extension as per latest spec")
Signed-off-by: Shibo Zhu <3499129952 at qq.com>
---
 lib/sbi/sbi_mpxy.c            |  8 +++--
 lib/sbi/tests/objects.mk      |  2 ++
 lib/sbi/tests/sbi_mpxy_test.c | 64 +++++++++++++++++++++++++++++++++++
 3 files changed, 72 insertions(+), 2 deletions(-)
 create mode 100644 lib/sbi/tests/sbi_mpxy_test.c

diff --git a/lib/sbi/sbi_mpxy.c b/lib/sbi/sbi_mpxy.c
index 19f59f3a..ed0e7807 100644
--- a/lib/sbi/sbi_mpxy.c
+++ b/lib/sbi/sbi_mpxy.c
@@ -257,8 +257,8 @@ int sbi_mpxy_register_channel(struct sbi_mpxy_channel *channel)
 
 	/* Update shared memory size if required */
 	if (mpxy_shmem_size < channel->attrs.msg_data_maxlen) {
-		mpxy_shmem_size = channel->attrs.msg_data_maxlen;
-		mpxy_shmem_size = (mpxy_shmem_size + (PAGE_SIZE - 1)) / PAGE_SIZE;
+		mpxy_shmem_size = ROUNDUP(channel->attrs.msg_data_maxlen,
+					  PAGE_SIZE);
 	}
 
 	sbi_list_add_tail(&channel->head, &mpxy_channel_list);
@@ -803,3 +803,7 @@ int sbi_mpxy_get_notification_events(u32 channel_id, unsigned long *events_len)
 
 	return SBI_SUCCESS;
 }
+
+#ifdef CONFIG_SBIUNIT
+#include "tests/sbi_mpxy_test.c"
+#endif
diff --git a/lib/sbi/tests/objects.mk b/lib/sbi/tests/objects.mk
index 40c441e1..888b4412 100644
--- a/lib/sbi/tests/objects.mk
+++ b/lib/sbi/tests/objects.mk
@@ -19,6 +19,8 @@ libsbi-objs-$(CONFIG_SBIUNIT) += tests/sbi_math_test.o
 carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += ecall_test_suite
 libsbi-objs-$(CONFIG_SBIUNIT) += tests/sbi_ecall_test.o
 
+carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += mpxy_test_suite
+
 carray-sbi_unit_tests-$(CONFIG_SBIUNIT) += bitops_test_suite
 libsbi-objs-$(CONFIG_SBIUNIT) += tests/sbi_bitops_test.o
 
diff --git a/lib/sbi/tests/sbi_mpxy_test.c b/lib/sbi/tests/sbi_mpxy_test.c
new file mode 100644
index 00000000..d96975b4
--- /dev/null
+++ b/lib/sbi/tests/sbi_mpxy_test.c
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+#include <sbi/sbi_unit_test.h>
+
+static u32 mpxy_test_unused_channel_id(void)
+{
+	u32 channel_id = 0;
+
+	while (sbi_mpxy_find_channel_any(channel_id))
+		channel_id++;
+
+	return channel_id;
+}
+
+static void mpxy_shmem_size_test(struct sbiunit_test_case *test)
+{
+	static const struct {
+		u32 msg_data_maxlen;
+		unsigned long expected;
+	} cases[] = {
+		{ 4095, PAGE_SIZE },
+		{ 4096, PAGE_SIZE },
+		{ 4097, 2 * PAGE_SIZE },
+		{ 8192, 2 * PAGE_SIZE },
+		{ 8193, 3 * PAGE_SIZE },
+	};
+	struct sbi_mpxy_channel channels[array_size(cases) + 1] = { 0 };
+	unsigned long saved_size = mpxy_shmem_size;
+	unsigned long previous = PAGE_SIZE;
+	u32 i;
+
+	mpxy_shmem_size = PAGE_SIZE;
+
+	for (i = 0; i < array_size(cases); i++) {
+		channels[i].channel_id = mpxy_test_unused_channel_id();
+		channels[i].owner_domain = sbi_domain_thishart_ptr();
+		channels[i].attrs.msg_data_maxlen = cases[i].msg_data_maxlen;
+
+		SBIUNIT_ASSERT_EQ(test,
+				  sbi_mpxy_register_channel(&channels[i]), SBI_OK);
+		SBIUNIT_EXPECT_EQ(test, sbi_mpxy_get_shmem_size(),
+				  cases[i].expected);
+		SBIUNIT_EXPECT(test, sbi_mpxy_get_shmem_size() >= previous);
+		previous = sbi_mpxy_get_shmem_size();
+	}
+
+	/* Registering a smaller channel must not decrease the shared memory. */
+	channels[i].channel_id = mpxy_test_unused_channel_id();
+	channels[i].owner_domain = sbi_domain_thishart_ptr();
+	channels[i].attrs.msg_data_maxlen = 4095;
+	SBIUNIT_ASSERT_EQ(test, sbi_mpxy_register_channel(&channels[i]), SBI_OK);
+	SBIUNIT_EXPECT_EQ(test, sbi_mpxy_get_shmem_size(), previous);
+
+	for (i = 0; i < array_size(channels); i++)
+		sbi_list_del_init(&channels[i].head);
+	mpxy_shmem_size = saved_size;
+}
+
+static struct sbiunit_test_case mpxy_tests[] = {
+	SBIUNIT_TEST_CASE(mpxy_shmem_size_test),
+	SBIUNIT_END_CASE,
+};
+
+SBIUNIT_TEST_SUITE(mpxy_test_suite, mpxy_tests);
-- 
2.43.0




More information about the opensbi mailing list