[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