On Mon, Oct 26, 2026 at 12:38:51PM +0530, Subrahmanya Lingappa wrote:
> Charles,
> 
> On Wed, Oct 14, 2026 at 7:47 PM Charles Perry
> <[email protected]> wrote:
> >
> > This adds an RPMI transport driver for the Supervisor Binary Interface
> > (SBI) message proxy (MPXY) extension [1].
> >
> > This is for S-Mode U-Boot where some supervisor software (such as
> > OpenSBI) runs in M-Mode and handles the low level communication with the
> > PuC.
> >
> > [1]: https://github.com/riscv-non-isa/riscv-sbi-doc (chapter 20)
> >
> > Signed-off-by: Charles Perry <[email protected]>
> > ---
> > Changes in v4: None
> > Changes in v3: None
> >
> > Changes in v2: (from Yao Zi review)
> >  - Reorder headers
> >  - Remove struct sbi_mpxy_rpmi_channel_attrs and struct
> >    sbi_mpxy_channel_attrs for simpler u32 arrays
> >  - Don't null check pointers before free()
> > ---
> >  arch/riscv/include/asm/sbi.h          |  57 +++++
> >  drivers/firmware/rpmi/Kconfig         |   9 +
> >  drivers/firmware/rpmi/Makefile        |   1 +
> >  drivers/firmware/rpmi/rpmi-sbi-mpxy.c | 410 
> > ++++++++++++++++++++++++++++++++++
> >  4 files changed, 477 insertions(+)
> >
> > diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
> > index 47124dbaac84..10e03257d8e6 100644
> > --- a/arch/riscv/include/asm/sbi.h
> > +++ b/arch/riscv/include/asm/sbi.h
> > @@ -10,6 +10,7 @@
> >  #define _ASM_RISCV_SBI_H
> >
> >  #include <linux/types.h>
> > +#include <linux/errno.h>
> >
> >  enum sbi_ext_id {
> >         SBI_EXT_0_1_SET_TIMER = 0x0,
> > @@ -104,6 +105,17 @@ enum sbi_ext_dbcn_fid {
> >         SBI_EXT_DBCN_CONSOLE_WRITE_BYTE,
> >  };
> >
> > +enum sbi_ext_mpxy_fid {
> > +       SBI_EXT_MPXY_GET_SHMEM_SIZE = 0,
> > +       SBI_EXT_MPXY_SET_SHMEM,
> > +       SBI_EXT_MPXY_GET_CHANNEL_IDS,
> > +       SBI_EXT_MPXY_READ_ATTRS,
> > +       SBI_EXT_MPXY_WRITE_ATTRS,
> > +       SBI_EXT_MPXY_SEND_MSG_WITH_RESP,
> > +       SBI_EXT_MPXY_SEND_MSG_WITHOUT_RESP,
> > +       SBI_EXT_MPXY_GET_NOTIFICATION_EVENTS,
> > +};
> > +
> >  #ifdef CONFIG_SBI_V01
> >  #define SBI_EXT_SET_TIMER              SBI_EXT_0_1_SET_TIMER
> >  #define SBI_FID_SET_TIMER              0
> > @@ -132,6 +144,14 @@ enum sbi_ext_dbcn_fid {
> >  #define SBI_SPEC_VERSION_MAJOR_MASK    0x7f
> >  #define SBI_SPEC_VERSION_MINOR_MASK    0xffffff
> >
> > +static inline unsigned long sbi_mk_version(unsigned long major,
> > +                                          unsigned long minor)
> > +{
> > +       return ((major & SBI_SPEC_VERSION_MAJOR_MASK)
> > +               << SBI_SPEC_VERSION_MAJOR_SHIFT) |
> > +              (minor & SBI_SPEC_VERSION_MINOR_MASK);
> > +}
> > +
> >  /* SBI return error codes */
> >  #define SBI_SUCCESS                    0
> >  #define SBI_ERR_FAILURE                        -1
> > @@ -139,6 +159,43 @@ enum sbi_ext_dbcn_fid {
> >  #define SBI_ERR_INVALID_PARAM          -3
> >  #define SBI_ERR_DENIED                 -4
> >  #define SBI_ERR_INVALID_ADDRESS                -5
> > +#define SBI_ERR_ALREADY_AVAILABLE      -6
> > +#define SBI_ERR_ALREADY_STARTED                -7
> > +#define SBI_ERR_ALREADY_STOPPED                -8
> > +#define SBI_ERR_NO_SHMEM               -9
> > +#define SBI_ERR_INVALID_STATE          -10
> > +#define SBI_ERR_BAD_RANGE              -11
> > +#define SBI_ERR_TIMEOUT                        -12
> > +#define SBI_ERR_IO                     -13
> > +#define SBI_ERR_DENIED_LOCKED          -14
> > +
> > +static inline int sbi_to_linux_error(int err)
> > +{
> > +       switch (err) {
> > +       case SBI_SUCCESS:
> > +               return 0;
> > +       case SBI_ERR_DENIED:
> > +       case SBI_ERR_DENIED_LOCKED:
> > +               return -EPERM;
> > +       case SBI_ERR_INVALID_PARAM:
> > +       case SBI_ERR_INVALID_STATE:
> > +               return -EINVAL;
> > +       case SBI_ERR_BAD_RANGE:
> > +               return -ERANGE;
> > +       case SBI_ERR_INVALID_ADDRESS:
> > +               return -EFAULT;
> > +       case SBI_ERR_NO_SHMEM:
> > +               return -ENOMEM;
> > +       case SBI_ERR_TIMEOUT:
> > +               return -ETIMEDOUT;
> > +       case SBI_ERR_IO:
> > +               return -EIO;
> > +       case SBI_ERR_NOT_SUPPORTED:
> > +       case SBI_ERR_FAILURE:
> > +       default:
> > +               return -EOPNOTSUPP;
> > +       };
> > +}
> >
> >  struct sbiret {
> >         long error;
> > diff --git a/drivers/firmware/rpmi/Kconfig b/drivers/firmware/rpmi/Kconfig
> > index 54fd77ad8f48..708d931263ff 100644
> > --- a/drivers/firmware/rpmi/Kconfig
> > +++ b/drivers/firmware/rpmi/Kconfig
> > @@ -7,3 +7,12 @@ config RPMI_FIRMWARE
> >           protocol for communication between an Application Processor (AP) 
> > and a
> >           platform microcontroller (PuC). The RPMI specification is 
> > available
> >           at: https://github.com/riscv-non-isa/riscv-rpmi
> > +
> > +config RPMI_SBI_MPXY
> > +       bool "RPMI over SBI MPXY transport"
> > +       depends on RPMI_FIRMWARE && SBI
> > +       help
> > +         Enable support for transport of RPMI messages over the message 
> > proxy
> > +         (MPXY) extension of the supervisor binary interface (SBI). The
> > +         specification for the MPXY extension is available at:
> > +         https://github.com/riscv-non-isa/riscv-sbi-doc (chapter 20)
> > diff --git a/drivers/firmware/rpmi/Makefile b/drivers/firmware/rpmi/Makefile
> > index d69c718d150e..71c4aeaed910 100644
> > --- a/drivers/firmware/rpmi/Makefile
> > +++ b/drivers/firmware/rpmi/Makefile
> > @@ -1 +1,2 @@
> >  obj-y  += rpmi-uclass.o
> > +obj-$(CONFIG_RPMI_SBI_MPXY) += rpmi-sbi-mpxy.o
> > diff --git a/drivers/firmware/rpmi/rpmi-sbi-mpxy.c 
> > b/drivers/firmware/rpmi/rpmi-sbi-mpxy.c
> > new file mode 100644
> > index 000000000000..9ccca0eb59b2
> > --- /dev/null
> > +++ b/drivers/firmware/rpmi/rpmi-sbi-mpxy.c
> > @@ -0,0 +1,410 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2026 Microchip Technology Inc. All rights reserved.
> > + */
> > +
> > +#define LOG_CATEGORY UCLASS_RPMI
> > +
> > +#include <asm/io.h>
> > +#include <asm/sbi.h>
> > +#include <asm/types.h>
> > +#include <dm.h>
> > +#include <dm/device_compat.h>
> > +#include <linux/bitops.h>
> > +#include <linux/kernel.h>
> > +#include <log.h>
> > +#include <malloc.h>
> > +#include <rpmi-uclass.h>
> > +#include <string.h>
> > +
> > +/* SBI MPXY channel IDs data in shared memory */
> > +struct sbi_mpxy_channel_ids_data {
> > +       /* Remaining number of channel ids */
> > +       __le32 remaining;
> > +       /* Returned channel ids in current function call */
> > +       __le32 returned;
> > +       /* Returned channel id array */
> > +       __le32 channel_array[];
> > +};
> > +
> > +enum sbi_mpxy_attribute_id {
> > +       /* Standard channel attributes managed by MPXY framework */
> > +       SBI_MPXY_ATTR_MSG_PROT_ID = 0x00000000,
> > +       SBI_MPXY_ATTR_MSG_PROT_VER = 0x00000001,
> > +       SBI_MPXY_ATTR_MSG_MAX_LEN = 0x00000002,
> > +       SBI_MPXY_ATTR_MSG_SEND_TIMEOUT = 0x00000003,
> > +       SBI_MPXY_ATTR_MSG_COMPLETION_TIMEOUT = 0x00000004,
> > +       SBI_MPXY_ATTR_CHANNEL_CAPABILITY = 0x00000005,
> > +       SBI_MPXY_ATTR_SSE_EVENT_ID = 0x00000006,
> > +       SBI_MPXY_ATTR_MSI_CONTROL = 0x00000007,
> > +       SBI_MPXY_ATTR_MSI_ADDR_LO = 0x00000008,
> > +       SBI_MPXY_ATTR_MSI_ADDR_HI = 0x00000009,
> > +       SBI_MPXY_ATTR_MSI_DATA = 0x0000000A,
> > +       SBI_MPXY_ATTR_EVENTS_STATE_CONTROL = 0x0000000B,
> > +       SBI_MPXY_ATTR_STD_ATTR_MAX_IDX,
> > +       /*
> > +        * Message protocol specific attributes, managed by
> > +        * the message protocol specification.
> > +        */
> > +       SBI_MPXY_ATTR_MSGPROTO_ATTR_START = 0x80000000,
> > +       SBI_MPXY_ATTR_MSGPROTO_ATTR_END = 0xffffffff
> > +};
> > +
> > +/* SBI_MPXY_ATTR_CHANNEL_CAPABILITY bits */
> > +#define SBI_MPXY_CHAN_CAP_MSI BIT(0)
> > +#define SBI_MPXY_CHAN_CAP_SSE BIT(1)
> > +#define SBI_MPXY_CHAN_CAP_EVENTS_STATE BIT(2)
> > +#define SBI_MPXY_CHAN_CAP_SEND_WITH_RESP BIT(3)
> > +#define SBI_MPXY_CHAN_CAP_SEND_WITHOUT_RESP BIT(4)
> > +#define SBI_MPXY_CHAN_CAP_GET_NOTIFICATIONS BIT(5)
> > +
> > +/* RPMI message protocol specific MPXY attributes */
> > +enum sbi_mpxy_rpmi_attribute_id {
> > +       SBI_MPXY_RPMI_ATTR_SERVICEGROUP_ID,
> > +       SBI_MPXY_RPMI_ATTR_SERVICEGROUP_VERSION,
> > +       SBI_MPXY_RPMI_ATTR_IMPL_ID,
> > +       SBI_MPXY_RPMI_ATTR_IMPL_VERSION,
> > +       SBI_MPXY_RPMI_ATTR_MAX_ID
> > +};
> > +
> > +/* Possible values of MSG_PROT_ID attribute as-per SBI v3.0 (or higher) */
> > +enum sbi_mpxy_msgproto_id {
> > +       SBI_MPXY_MSGPROTO_RPMI_ID = 0x0,
> > +};
> > +
> > +struct sbi_mpxy_chan_desc {
> > +       u32 id;
> > +       u32 max_xfer_len;
> > +       u32 attrs[SBI_MPXY_ATTR_STD_ATTR_MAX_IDX];
> > +       u32 rpmi_attrs[SBI_MPXY_RPMI_ATTR_MAX_ID];
> > +};
> > +
> > +struct rpmi_sbi_mpxy {
> > +       struct udevice *dev;
> > +       void *shmem;
> > +       unsigned long shmem_size;
> > +       u32 channel_count;
> > +       struct sbi_mpxy_chan_desc *channel_descs;
> > +};
> > +
> > +static int rpmi_sbi_mpxy_read_attrs(struct rpmi_sbi_mpxy *mpxy, u32 
> > channel_id,
> > +                                   u32 base_attrid, u32 attr_count,
> > +                                   u32 *attrs_buf)
> > +{
> > +       struct sbiret sret;
> > +       int i;
> > +
> > +       sret = sbi_ecall(SBI_EXT_MPXY, SBI_EXT_MPXY_READ_ATTRS, channel_id,
> > +                        base_attrid, attr_count, 0, 0, 0);
> > +       if (sret.error)
> > +               return sbi_to_linux_error(sret.error);
> > +
> > +       for (i = 0; i < attr_count; i++)
> > +               attrs_buf[i] = le32_to_cpu(((__le32 *)mpxy->shmem)[i]);
> > +
> > +       return 0;
> > +}
> > +
> > +static int rpmi_sbi_mpxy_send_message(void *shmem, u32 mpxy_fid, u32 
> > channel_id,
> > +                                     u32 msg_id, const void *tx,
> > +                                     unsigned long tx_len, void *rx,
> > +                                     unsigned long max_rx_len,
> > +                                     unsigned long *rx_len)
> > +{
> > +       unsigned long rx_bytes;
> > +       struct sbiret sret;
> > +
> > +       if (tx)
> > +               memcpy(shmem, tx, tx_len);
> > +
> > +       sret = sbi_ecall(SBI_EXT_MPXY, mpxy_fid, channel_id, msg_id, 
> > tx_len, 0,
> > +                        0, 0);
> > +
> > +       if (rx && !sret.error) {
> > +               rx_bytes = sret.value;
> > +               if (rx_bytes > max_rx_len)
> > +                       return -ENOSPC;
> > +
> > +               memcpy(rx, shmem, rx_bytes);
>  `rx_bytes` is checked against the caller's buffer, but not against the
>  allocated MPXY shared-memory region. Current callers pass bounded response
>  buffers, so this is defensive hardening rather than a demonstrated overflow
>  in the current clients; however, the helper itself accepts an arbitrary
>  `max_rx_len` and trusts the SBI return value. Please bound the response by
>  both the shared-memory allocation and the channel's maximum transfer length
>  before copying.

Ok good point. I'll make this case return -EIO since this would be a bug in
the SBI.

Thanks,
Charles

> 
> Regards,
> Subrahmanya
> 

Reply via email to