@@ -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
@@ -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
new file mode 100644
@@ -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);
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@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