kernel/irq/msi.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
The debug_show() callback function is implemented in the MSI core code.
And assign it to the domain ops::debug_show() creation.
When debugging MSI-related hardware issues (e.g., interrupt delivery
failures), developers currently need to either:
1. Recompile kernel with dynamic debug for tracing msi_desc.
2. Manually read device registers through low-level tools.
Both approaches become challenging in production environments where
dynamic debugging is often disabled.
This patch proposes to expose MSI address_hi/address_lo and msg_data in
`/sys/kernel/debug/irq/irqs/<msi_irq_num>`. These fields are critical to:
- Verify if MSI configuration matches hardware programming
- Diagnose interrupt routing errors (e.g., mismatched destination ID)
- Validate remapping behavior in virtualized environments
The information is already maintained in msi_desc and irq_data structures.
By surfacing it through debugfs:
- We create a unified place for runtime IRQ diagnostics
- Enable debugging without kernel rebuilds or special tools
- Align with existing exposure of IRQ chip/type/affinity data
Sample output:
address_hi: 0x00000000
address_lo: 0xfe670040
msg_data: 0x00000001
Signed-off-by: Hans Zhang <18255117159@163.com>
---
Changes since v2-v3:
https://lore.kernel.org/linux-pci/20250301123953.291675-1-18255117159@163.com/
https://lore.kernel.org/linux-pci/20250302020328.296523-1-18255117159@163.com/
- Fix implicit declaration of function 'seq_printf'.
- Fix 'const struct irq_domain_ops' has no member named 'debug_show'.
- The patch commit message were modified.
- Removes the display that is not currently an MSI/MSIX interrupt.
Changes since v1:
https://lore.kernel.org/linux-pci/20250227162821.253020-1-18255117159@163.com/
- According to Thomas(tglx), the debug_show() callback should be added
to the MSI core code.
---
kernel/irq/msi.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index 396a067a8a56..adcc7c638295 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -15,6 +15,7 @@
#include <linux/mutex.h>
#include <linux/pci.h>
#include <linux/slab.h>
+#include <linux/seq_file.h>
#include <linux/sysfs.h>
#include <linux/types.h>
#include <linux/xarray.h>
@@ -756,12 +757,30 @@ static int msi_domain_translate(struct irq_domain *domain, struct irq_fwspec *fw
return info->ops->msi_translate(domain, fwspec, hwirq, type);
}
+#ifdef CONFIG_GENERIC_IRQ_DEBUGFS
+static void msi_domain_debug_show(struct seq_file *m, struct irq_domain *d,
+ struct irq_data *irqd, int ind)
+{
+ struct msi_desc *desc = irq_get_msi_desc(irqd->irq);
+
+ if (!desc)
+ return;
+
+ seq_printf(m, "\n%*saddress_hi: 0x%08x", ind + 1, "", desc->msg.address_hi);
+ seq_printf(m, "\n%*saddress_lo: 0x%08x", ind + 1, "", desc->msg.address_lo);
+ seq_printf(m, "\n%*smsg_data: 0x%08x\n", ind + 1, "", desc->msg.data);
+}
+#endif
+
static const struct irq_domain_ops msi_domain_ops = {
.alloc = msi_domain_alloc,
.free = msi_domain_free,
.activate = msi_domain_activate,
.deactivate = msi_domain_deactivate,
.translate = msi_domain_translate,
+#ifdef CONFIG_GENERIC_IRQ_DEBUGFS
+ .debug_show = msi_domain_debug_show,
+#endif
};
static irq_hw_number_t msi_domain_ops_get_hwirq(struct msi_domain_info *info,
base-commit: 76544811c850a1f4c055aa182b513b7a843868ea
--
2.25.1
The following commit has been merged into the irq/core branch of tip:
Commit-ID: 01499ae673dc66cf5e98589648848b520f6fdfe9
Gitweb: https://git.kernel.org/tip/01499ae673dc66cf5e98589648848b520f6fdfe9
Author: Hans Zhang <18255117159@163.com>
AuthorDate: Mon, 03 Mar 2025 20:10:08 +08:00
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Mon, 03 Mar 2025 22:16:03 +01:00
genirq/msi: Expose MSI message data in debugfs
When debugging MSI-related hardware issues (e.g. interrupt delivery
failures), developers currently need to either:
1. Recompile the kernel with dynamic debug for tracing msi_desc.
2. Manually read device registers through low-level tools.
Both approaches become challenging in production environments where
dynamic debugging is often disabled.
The interrupt core provides a debugfs interface for inspection of interrupt
related data, which contains the per interrupt information in the view of
the hierarchical interrupt domains. Though this interface does not expose
the MSI address/data pair, which is important information to:
- Verify whether the MSI configuration matches the hardware expectations
- Diagnose interrupt routing errors (e.g., mismatched destination ID)
- Validate remapping behavior in virtualized environments
Implement the debug_show() callback for the generic MSI interrupt domains,
and use it to expose the MSI address/data pair in the per interrupt
diagnostics.
Sample output:
address_hi: 0x00000000
address_lo: 0xfe670040
msg_data: 0x00000001
[ tglx: Massaged change log. Use irq_data_get_msi_desc() to avoid pointless
lookup. ]
Signed-off-by: Hans Zhang <18255117159@163.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/all/20250303121008.309265-1-18255117159@163.com
---
kernel/irq/msi.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index 396a067..fa92882 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -15,6 +15,7 @@
#include <linux/mutex.h>
#include <linux/pci.h>
#include <linux/slab.h>
+#include <linux/seq_file.h>
#include <linux/sysfs.h>
#include <linux/types.h>
#include <linux/xarray.h>
@@ -756,12 +757,30 @@ static int msi_domain_translate(struct irq_domain *domain, struct irq_fwspec *fw
return info->ops->msi_translate(domain, fwspec, hwirq, type);
}
+#ifdef CONFIG_GENERIC_IRQ_DEBUGFS
+static void msi_domain_debug_show(struct seq_file *m, struct irq_domain *d,
+ struct irq_data *irqd, int ind)
+{
+ struct msi_desc *desc = irq_data_get_msi_desc(irqd);
+
+ if (!desc)
+ return;
+
+ seq_printf(m, "\n%*saddress_hi: 0x%08x", ind + 1, "", desc->msg.address_hi);
+ seq_printf(m, "\n%*saddress_lo: 0x%08x", ind + 1, "", desc->msg.address_lo);
+ seq_printf(m, "\n%*smsg_data: 0x%08x\n", ind + 1, "", desc->msg.data);
+}
+#endif
+
static const struct irq_domain_ops msi_domain_ops = {
.alloc = msi_domain_alloc,
.free = msi_domain_free,
.activate = msi_domain_activate,
.deactivate = msi_domain_deactivate,
.translate = msi_domain_translate,
+#ifdef CONFIG_GENERIC_IRQ_DEBUGFS
+ .debug_show = msi_domain_debug_show,
+#endif
};
static irq_hw_number_t msi_domain_ops_get_hwirq(struct msi_domain_info *info,
© 2016 - 2025 Red Hat, Inc.