[PATCH] lib: sbi_mpxy: Fix shared memory size rounding
Anup Patel
anup at brainfault.org
Mon Sep 28 05:26:46 PDT 2026
On Mon, Aug 17, 2026 at 9:25 PM Shibo Zhu <3499129952 at qq.com> wrote:
>
> 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.
The SBIUnit test for MPXY should be a separate patch. I will drop those changes
at the time of merging so send a separate patch.
Reviewed-by: Anup Patel <anup at brainfault.org>
Applied this patch to the riscv/opensbi repo.
Thanks,
Anup
>
> 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
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi
More information about the opensbi
mailing list