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 >
