[PATCH 1/5] lib: utils/irqchip: Add RPMI system MSI helper library

Nick Hu nick.hu at sifive.com
Sun Nov 1 19:47:15 PST 2026


Move the RPMI system MSI initialization out of the MPXY RPMI sysmsi
driver and into a new irqchip helper library, rpmi_sysmsi. The helper
reads the P2A doorbell system MSI index from the mailbox channel,
queries the number of system MSIs and the attributes of each MSI from
the RPMI service group, and builds a bitmap of MSIs that must not be
exposed through MPXY: the P2A doorbell MSI and any MSI whose attributes
indicate it is preferred to be handled by privileged (M-mode) software.

rpmi_sysmsi_setup() and rpmi_sysmsi_cleanup() manage one reference
counted struct rpmi_sysmsi_data per mailbox channel. A setup call for a
channel that already has data returns the existing instance, so several
users of the same channel share a single denied bitmap. Convert the MPXY
RPMI sysmsi driver to use these functions instead of keeping its own
copy of the setup and cleanup logic.

Signed-off-by: Nick Hu <nick.hu at sifive.com>
---
 include/sbi_utils/irqchip/rpmi_sysmsi.h |  23 +++++++
 lib/utils/irqchip/Kconfig               |   5 ++
 lib/utils/irqchip/objects.mk            |   1 +
 lib/utils/irqchip/rpmi_sysmsi.c         | 117 ++++++++++++++++++++++++++++++++
 lib/utils/mpxy/Kconfig                  |   2 +
 lib/utils/mpxy/fdt_mpxy_rpmi_sysmsi.c   |  61 ++---------------
 6 files changed, 155 insertions(+), 54 deletions(-)

diff --git a/include/sbi_utils/irqchip/rpmi_sysmsi.h b/include/sbi_utils/irqchip/rpmi_sysmsi.h
new file mode 100644
index 00000000..90825557
--- /dev/null
+++ b/include/sbi_utils/irqchip/rpmi_sysmsi.h
@@ -0,0 +1,23 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 Ventana Micro Systems Inc.
+ */
+#ifndef __RPMI_SYSMSI_H__
+#define __RPMI_SYSMSI_H__
+
+#include <sbi/sbi_list.h>
+#include <sbi_utils/mailbox/mailbox.h>
+
+struct rpmi_sysmsi_data {
+	struct sbi_dlist node;
+	struct mbox_chan *chan;
+	unsigned long *sys_msi_denied_bmap;
+	u32 sys_num_msi;
+	u32 ref_cnt;
+};
+
+void rpmi_sysmsi_cleanup(struct rpmi_sysmsi_data *data);
+int rpmi_sysmsi_setup(struct mbox_chan *chan, struct rpmi_sysmsi_data **out_data);
+
+#endif
diff --git a/lib/utils/irqchip/Kconfig b/lib/utils/irqchip/Kconfig
index 7a71388c..03f297dc 100644
--- a/lib/utils/irqchip/Kconfig
+++ b/lib/utils/irqchip/Kconfig
@@ -38,4 +38,9 @@ config IRQCHIP_PLIC
 	bool "Platform Level Interrupt Controller (PLIC) support"
 	default n
 
+config RPMI_SYSMSI
+	bool "RPMI SYSTEM MSI support"
+	depends on RPMI_MAILBOX
+	default n
+
 endmenu
diff --git a/lib/utils/irqchip/objects.mk b/lib/utils/irqchip/objects.mk
index a13b384e..3195a273 100644
--- a/lib/utils/irqchip/objects.mk
+++ b/lib/utils/irqchip/objects.mk
@@ -22,3 +22,4 @@ libsbiutils-objs-$(CONFIG_FDT_IRQCHIP_PLIC) += irqchip/fdt_irqchip_plic.o
 libsbiutils-objs-$(CONFIG_IRQCHIP_APLIC) += irqchip/aplic.o
 libsbiutils-objs-$(CONFIG_IRQCHIP_IMSIC) += irqchip/imsic.o
 libsbiutils-objs-$(CONFIG_IRQCHIP_PLIC) += irqchip/plic.o
+libsbiutils-objs-$(CONFIG_RPMI_SYSMSI) += irqchip/rpmi_sysmsi.o
diff --git a/lib/utils/irqchip/rpmi_sysmsi.c b/lib/utils/irqchip/rpmi_sysmsi.c
new file mode 100644
index 00000000..d403ce17
--- /dev/null
+++ b/lib/utils/irqchip/rpmi_sysmsi.c
@@ -0,0 +1,117 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 Ventana Micro Systems Inc.
+ */
+
+#include <sbi/sbi_bitmap.h>
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_heap.h>
+#include <sbi_utils/irqchip/rpmi_sysmsi.h>
+#include <sbi_utils/mailbox/rpmi_mailbox.h>
+
+static SBI_LIST_HEAD(rpmi_sysmsi_list);
+
+static struct rpmi_sysmsi_data *rpmi_sysmsi_find(struct mbox_chan *chan)
+{
+	struct rpmi_sysmsi_data *data;
+
+	if (!chan || sbi_list_empty(&rpmi_sysmsi_list))
+		return NULL;
+
+	sbi_list_for_each_entry(data, &rpmi_sysmsi_list, node) {
+		if (data->chan == chan)
+			return data;
+	}
+
+	return NULL;
+}
+
+void rpmi_sysmsi_cleanup(struct rpmi_sysmsi_data *data)
+{
+	if (!data || --data->ref_cnt)
+		return;
+
+	sbi_list_del(&data->node);
+	sbi_free(data->sys_msi_denied_bmap);
+	sbi_free(data);
+}
+
+int rpmi_sysmsi_setup(struct mbox_chan *chan, struct rpmi_sysmsi_data **out_data)
+{
+	struct rpmi_sysmsi_get_msi_attributes_resp gmaresp;
+	struct rpmi_sysmsi_get_msi_attributes_req gmareq;
+	struct rpmi_sysmsi_get_attributes_resp garesp;
+	struct rpmi_sysmsi_data *data;
+	u32 p2a_db_index, i;
+	int rc;
+
+	if (!out_data)
+		return SBI_EINVAL;
+
+	data = rpmi_sysmsi_find(chan);
+	if (data) {
+		*out_data = data;
+		data->ref_cnt++;
+		return SBI_OK;
+	}
+
+	rc = mbox_chan_get_attribute(chan, RPMI_CHANNEL_ATTR_P2A_DOORBELL_SYSMSI_INDEX,
+				     &p2a_db_index);
+	if (rc) {
+		sbi_printf("%s: mbox chan get attribute failed rc=%d\n", __func__, rc);
+		return rc;
+	}
+
+	rc = rpmi_normal_request_with_status(chan, RPMI_SYSMSI_SRV_GET_ATTRIBUTES,
+					     NULL, 0, 0, &garesp, rpmi_u32_count(garesp),
+					     rpmi_u32_count(garesp));
+	if (rc) {
+		sbi_printf("%s: SRV_GET_ATTRIBUTES failed rc=%d\n", __func__, rc);
+		return rc;
+	}
+
+	if (!garesp.sys_num_msi)
+		return SBI_ENODEV;
+
+	data = sbi_zalloc(sizeof(*data));
+	if (!data)
+		return SBI_ENOMEM;
+
+	data->ref_cnt = 1;
+	data->chan = chan;
+	data->sys_num_msi = garesp.sys_num_msi;
+	data->sys_msi_denied_bmap = sbi_zalloc(bitmap_estimate_size(data->sys_num_msi));
+	if (!data->sys_msi_denied_bmap) {
+		rc = SBI_ENOMEM;
+		goto free_data;
+	}
+
+	for (i = 0; i < data->sys_num_msi; i++) {
+		gmareq.sys_msi_index = i;
+		rc = rpmi_normal_request_with_status(chan,
+						     RPMI_SYSMSI_SRV_GET_MSI_ATTRIBUTES,
+						     &gmareq, rpmi_u32_count(gmareq),
+						     rpmi_u32_count(gmareq),
+						     &gmaresp, rpmi_u32_count(gmaresp),
+						     rpmi_u32_count(gmaresp));
+		if (rc) {
+			sbi_printf("%s: SRV_GET_MSI_ATTRIBUTES failed rc=%d\n", __func__, rc);
+			goto free_denied_bmap;
+		}
+
+		if (i == p2a_db_index || gmaresp.flag0 & RPMI_SYSMSI_MSI_ATTRIBUTES_FLAG0_PREF_PRIV)
+			bitmap_set(data->sys_msi_denied_bmap, i, 1);
+	}
+
+	*out_data = data;
+	sbi_list_add(&data->node, &rpmi_sysmsi_list);
+
+	return SBI_OK;
+free_denied_bmap:
+	sbi_free(data->sys_msi_denied_bmap);
+free_data:
+	sbi_free(data);
+	return rc;
+}
diff --git a/lib/utils/mpxy/Kconfig b/lib/utils/mpxy/Kconfig
index a3ed1c22..d53879d8 100644
--- a/lib/utils/mpxy/Kconfig
+++ b/lib/utils/mpxy/Kconfig
@@ -24,6 +24,8 @@ config FDT_MPXY_RPMI_LOGGING
 
 config FDT_MPXY_RPMI_SYSMSI
 	bool "MPXY driver for RPMI system MSI service group"
+	depends on RPMI_MAILBOX
+	select RPMI_SYSMSI
 	default n
 
 config FDT_MPXY_RPMI_VOLTAGE
diff --git a/lib/utils/mpxy/fdt_mpxy_rpmi_sysmsi.c b/lib/utils/mpxy/fdt_mpxy_rpmi_sysmsi.c
index 1dcc049e..f9ed5de4 100644
--- a/lib/utils/mpxy/fdt_mpxy_rpmi_sysmsi.c
+++ b/lib/utils/mpxy/fdt_mpxy_rpmi_sysmsi.c
@@ -7,20 +7,14 @@
 #include <sbi/sbi_bitmap.h>
 #include <sbi/sbi_domain.h>
 #include <sbi/sbi_byteorder.h>
-#include <sbi/sbi_heap.h>
-#include <sbi_utils/mailbox/rpmi_mailbox.h>
+#include <sbi_utils/irqchip/rpmi_sysmsi.h>
 #include <sbi_utils/mpxy/fdt_mpxy_rpmi_mbox.h>
 
-struct mpxy_rpmi_sysmsi {
-	u32 sys_num_msi;
-	unsigned long *sys_msi_denied_bmap;
-};
-
 static int mpxy_rpmi_sysmis_xfer(void *context, struct mbox_chan *chan,
 				 struct mbox_xfer *xfer)
 {
 	struct rpmi_message_args *args = xfer->args;
-	struct mpxy_rpmi_sysmsi *smg = context;
+	struct rpmi_sysmsi_data *smg = context;
 	u64 sys_msi_address;
 	u32 sys_msi_index;
 	int rc = 0;
@@ -77,62 +71,21 @@ static int mpxy_rpmi_sysmis_xfer(void *context, struct mbox_chan *chan,
 
 static void mpxy_rpmi_sysmsi_cleanup(void *context)
 {
-	struct mpxy_rpmi_sysmsi *smg = context;
+	struct rpmi_sysmsi_data *smg = context;
 
-	sbi_free(smg->sys_msi_denied_bmap);
-	sbi_free(smg);
+	rpmi_sysmsi_cleanup(smg);
 }
 
 static int mpxy_rpmi_sysmsi_setup(void **context, struct mbox_chan *chan,
 				  const struct mpxy_rpmi_mbox_data *data)
 {
-	struct rpmi_sysmsi_get_msi_attributes_resp gmaresp;
-	struct rpmi_sysmsi_get_msi_attributes_req gmareq;
-	struct rpmi_sysmsi_get_attributes_resp garesp;
-	struct mpxy_rpmi_sysmsi *smg;
-	u32 p2a_db_index;
-	int rc, i;
-
-	rc = mbox_chan_get_attribute(chan, RPMI_CHANNEL_ATTR_P2A_DOORBELL_SYSMSI_INDEX,
-				     &p2a_db_index);
-	if (rc)
-		return rc;
+	struct rpmi_sysmsi_data *smg;
+	int rc;
 
-	rc = rpmi_normal_request_with_status(chan, RPMI_SYSMSI_SRV_GET_ATTRIBUTES,
-					     NULL, 0, 0, &garesp, rpmi_u32_count(garesp),
-					     rpmi_u32_count(garesp));
+	rc = rpmi_sysmsi_setup(chan, &smg);
 	if (rc)
 		return rc;
 
-	smg = sbi_zalloc(sizeof(*smg));
-	if (!smg)
-		return SBI_ENOMEM;
-
-	smg->sys_num_msi = garesp.sys_num_msi;
-	smg->sys_msi_denied_bmap = sbi_zalloc(bitmap_estimate_size(smg->sys_num_msi));
-	if (!smg->sys_msi_denied_bmap) {
-		sbi_free(smg);
-		return SBI_ENOMEM;
-	}
-
-	for (i = 0; i < smg->sys_num_msi; i++) {
-		gmareq.sys_msi_index = i;
-		rc = rpmi_normal_request_with_status(chan,
-						     RPMI_SYSMSI_SRV_GET_MSI_ATTRIBUTES,
-						     &gmareq, rpmi_u32_count(gmareq),
-						     rpmi_u32_count(gmareq),
-						     &gmaresp, rpmi_u32_count(gmaresp),
-						     rpmi_u32_count(gmaresp));
-		if (rc) {
-			mpxy_rpmi_sysmsi_cleanup(smg);
-			return rc;
-		}
-
-		if (p2a_db_index == i ||
-		    (gmaresp.flag0 & RPMI_SYSMSI_MSI_ATTRIBUTES_FLAG0_PREF_PRIV))
-			bitmap_set(smg->sys_msi_denied_bmap, i, 1);
-	}
-
 	*context = smg;
 	return 0;
 }

-- 
2.43.7




More information about the opensbi mailing list