199 lines
7.0 KiB
Diff
199 lines
7.0 KiB
Diff
|
From 38d35bd1423ccafd0b8be0744155ce59ef3034ff Mon Sep 17 00:00:00 2001
|
||
|
From: Kazuhito Hagio <k-hagio-ab@nec.com>
|
||
|
Date: Wed, 12 Jul 2023 17:55:29 +0900
|
||
|
Subject: [PATCH 3/4] Fix "irq [-a|-s]" options on Linux 6.5-rc1 and later
|
||
|
|
||
|
Kernel commit 721255b982 ("genirq: Use a maple tree for interrupt
|
||
|
descriptor management"), which is contained in Linux 6.5-rc1 and later
|
||
|
kernels, replaced irq_desc_tree with a maple tree sparse_irqs.
|
||
|
|
||
|
Without the patch, "irq [-a|-s]" options fail with an error, e.g. the
|
||
|
following on x86_64, on kernels configured with CONFIG_SPARSE_IRQ=y.
|
||
|
|
||
|
crash> irq
|
||
|
irq: x86_64_dump_irq: irq_desc[] or irq_desc_tree do not exist?
|
||
|
|
||
|
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
|
||
|
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||
|
---
|
||
|
defs.h | 2 ++
|
||
|
ia64.c | 3 ++-
|
||
|
kernel.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++---
|
||
|
symbols.c | 1 +
|
||
|
x86_64.c | 9 ++++++---
|
||
|
5 files changed, 59 insertions(+), 7 deletions(-)
|
||
|
|
||
|
diff --git a/defs.h b/defs.h
|
||
|
index 26afe232cc3e..358f365585cf 100644
|
||
|
--- a/defs.h
|
||
|
+++ b/defs.h
|
||
|
@@ -676,6 +676,7 @@ struct new_utsname {
|
||
|
#define IRQ_DESC_TREE_XARRAY (0x80ULL)
|
||
|
#define KMOD_PAX (0x100ULL)
|
||
|
#define KMOD_MEMORY (0x200ULL)
|
||
|
+#define IRQ_DESC_TREE_MAPLE (0x400ULL)
|
||
|
|
||
|
#define XEN() (kt->flags & ARCH_XEN)
|
||
|
#define OPENVZ() (kt->flags & ARCH_OPENVZ)
|
||
|
@@ -2222,6 +2223,7 @@ struct offset_table { /* stash of commonly-used offsets */
|
||
|
long module_mem;
|
||
|
long module_memory_base;
|
||
|
long module_memory_size;
|
||
|
+ long irq_data_irq;
|
||
|
};
|
||
|
|
||
|
struct size_table { /* stash of commonly-used sizes */
|
||
|
diff --git a/ia64.c b/ia64.c
|
||
|
index 2e1d15fe6042..d3e0a3b01869 100644
|
||
|
--- a/ia64.c
|
||
|
+++ b/ia64.c
|
||
|
@@ -791,7 +791,8 @@ ia64_back_trace_cmd(struct bt_info *bt)
|
||
|
static void
|
||
|
ia64_dump_irq(int irq)
|
||
|
{
|
||
|
- if (symbol_exists("irq_desc") || symbol_exists("_irq_desc") ||
|
||
|
+ if (kernel_symbol_exists("sparse_irqs") ||
|
||
|
+ symbol_exists("irq_desc") || symbol_exists("_irq_desc") ||
|
||
|
kernel_symbol_exists("irq_desc_ptrs")) {
|
||
|
machdep->dump_irq = generic_dump_irq;
|
||
|
return(generic_dump_irq(irq));
|
||
|
diff --git a/kernel.c b/kernel.c
|
||
|
index 0fc77c19f12a..546eed95eebd 100644
|
||
|
--- a/kernel.c
|
||
|
+++ b/kernel.c
|
||
|
@@ -541,7 +541,10 @@ kernel_init()
|
||
|
MEMBER_OFFSET_INIT(irqaction_dev_id, "irqaction", "dev_id");
|
||
|
MEMBER_OFFSET_INIT(irqaction_next, "irqaction", "next");
|
||
|
|
||
|
- if (kernel_symbol_exists("irq_desc_tree")) {
|
||
|
+ /* 6.5 and later: CONFIG_SPARSE_IRQ */
|
||
|
+ if (kernel_symbol_exists("sparse_irqs"))
|
||
|
+ kt->flags2 |= IRQ_DESC_TREE_MAPLE;
|
||
|
+ else if (kernel_symbol_exists("irq_desc_tree")) {
|
||
|
get_symbol_type("irq_desc_tree", NULL, &req);
|
||
|
if (STREQ(req.type_tag_name, "xarray")) {
|
||
|
kt->flags2 |= IRQ_DESC_TREE_XARRAY;
|
||
|
@@ -554,6 +557,7 @@ kernel_init()
|
||
|
}
|
||
|
STRUCT_SIZE_INIT(irq_data, "irq_data");
|
||
|
if (VALID_STRUCT(irq_data)) {
|
||
|
+ MEMBER_OFFSET_INIT(irq_data_irq, "irq_data", "irq");
|
||
|
MEMBER_OFFSET_INIT(irq_data_chip, "irq_data", "chip");
|
||
|
MEMBER_OFFSET_INIT(irq_data_affinity, "irq_data", "affinity");
|
||
|
MEMBER_OFFSET_INIT(irq_desc_irq_data, "irq_desc", "irq_data");
|
||
|
@@ -6180,6 +6184,8 @@ dump_kernel_table(int verbose)
|
||
|
fprintf(fp, "%sIRQ_DESC_TREE_RADIX", others++ ? "|" : "");
|
||
|
if (kt->flags2 & IRQ_DESC_TREE_XARRAY)
|
||
|
fprintf(fp, "%sIRQ_DESC_TREE_XARRAY", others++ ? "|" : "");
|
||
|
+ if (kt->flags2 & IRQ_DESC_TREE_MAPLE)
|
||
|
+ fprintf(fp, "%sIRQ_DESC_TREE_MAPLE", others++ ? "|" : "");
|
||
|
if (kt->flags2 & KMOD_PAX)
|
||
|
fprintf(fp, "%sKMOD_PAX", others++ ? "|" : "");
|
||
|
if (kt->flags2 & KMOD_MEMORY)
|
||
|
@@ -6652,6 +6658,45 @@ get_irq_desc_addr(int irq)
|
||
|
readmem(ptr, KVADDR, &addr,
|
||
|
sizeof(void *), "irq_desc_ptrs entry",
|
||
|
FAULT_ON_ERROR);
|
||
|
+ } else if (kt->flags2 & IRQ_DESC_TREE_MAPLE) {
|
||
|
+ unsigned int i;
|
||
|
+
|
||
|
+ if (kt->highest_irq && (irq > kt->highest_irq))
|
||
|
+ return addr;
|
||
|
+
|
||
|
+ cnt = do_maple_tree(symbol_value("sparse_irqs"), MAPLE_TREE_COUNT, NULL);
|
||
|
+
|
||
|
+ len = sizeof(struct list_pair) * (cnt+1);
|
||
|
+ lp = (struct list_pair *)GETBUF(len);
|
||
|
+ lp[0].index = cnt; /* maxcount */
|
||
|
+
|
||
|
+ cnt = do_maple_tree(symbol_value("sparse_irqs"), MAPLE_TREE_GATHER, lp);
|
||
|
+
|
||
|
+ /*
|
||
|
+ * NOTE: We cannot use lp.index like Radix Tree or XArray because
|
||
|
+ * it's not an absolute index and just counter in Maple Tree.
|
||
|
+ */
|
||
|
+ if (kt->highest_irq == 0) {
|
||
|
+ readmem((ulong)lp[cnt-1].value +
|
||
|
+ OFFSET(irq_desc_irq_data) + OFFSET(irq_data_irq),
|
||
|
+ KVADDR, &kt->highest_irq, sizeof(int), "irq_data.irq",
|
||
|
+ FAULT_ON_ERROR);
|
||
|
+ }
|
||
|
+
|
||
|
+ for (c = 0; c < cnt; c++) {
|
||
|
+ readmem((ulong)lp[c].value +
|
||
|
+ OFFSET(irq_desc_irq_data) + OFFSET(irq_data_irq),
|
||
|
+ KVADDR, &i, sizeof(int), "irq_data.irq", FAULT_ON_ERROR);
|
||
|
+ if (i == irq) {
|
||
|
+ if (CRASHDEBUG(1))
|
||
|
+ fprintf(fp, "index: %d value: %lx\n",
|
||
|
+ i, (ulong)lp[c].value);
|
||
|
+ addr = (ulong)lp[c].value;
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ FREEBUF(lp);
|
||
|
+
|
||
|
} else if (kt->flags2 & (IRQ_DESC_TREE_RADIX|IRQ_DESC_TREE_XARRAY)) {
|
||
|
if (kt->highest_irq && (irq > kt->highest_irq))
|
||
|
return addr;
|
||
|
@@ -6700,8 +6745,8 @@ get_irq_desc_addr(int irq)
|
||
|
FREEBUF(lp);
|
||
|
} else {
|
||
|
error(FATAL,
|
||
|
- "neither irq_desc, _irq_desc, irq_desc_ptrs "
|
||
|
- "or irq_desc_tree symbols exist\n");
|
||
|
+ "neither irq_desc, _irq_desc, irq_desc_ptrs, "
|
||
|
+ "irq_desc_tree or sparse_irqs symbols exist\n");
|
||
|
}
|
||
|
|
||
|
return addr;
|
||
|
diff --git a/symbols.c b/symbols.c
|
||
|
index 82529a6785c9..876be7aea90e 100644
|
||
|
--- a/symbols.c
|
||
|
+++ b/symbols.c
|
||
|
@@ -10375,6 +10375,7 @@ dump_offset_table(char *spec, ulong makestruct)
|
||
|
OFFSET(irq_desc_t_kstat_irqs));
|
||
|
fprintf(fp, " irq_desc_t_affinity: %ld\n",
|
||
|
OFFSET(irq_desc_t_affinity));
|
||
|
+ fprintf(fp, " irq_data_irq: %ld\n", OFFSET(irq_data_irq));
|
||
|
fprintf(fp, " irq_data_chip: %ld\n",
|
||
|
OFFSET(irq_data_chip));
|
||
|
fprintf(fp, " irq_data_affinity: %ld\n",
|
||
|
diff --git a/x86_64.c b/x86_64.c
|
||
|
index 87e87ae6e1e8..42ade4817ad9 100644
|
||
|
--- a/x86_64.c
|
||
|
+++ b/x86_64.c
|
||
|
@@ -5391,7 +5391,8 @@ get_x86_64_frame(struct bt_info *bt, ulong *getpc, ulong *getsp)
|
||
|
static void
|
||
|
x86_64_dump_irq(int irq)
|
||
|
{
|
||
|
- if (symbol_exists("irq_desc") ||
|
||
|
+ if (kernel_symbol_exists("sparse_irqs") ||
|
||
|
+ symbol_exists("irq_desc") ||
|
||
|
kernel_symbol_exists("irq_desc_ptrs") ||
|
||
|
kernel_symbol_exists("irq_desc_tree")) {
|
||
|
machdep->dump_irq = generic_dump_irq;
|
||
|
@@ -5405,7 +5406,8 @@ x86_64_dump_irq(int irq)
|
||
|
static void
|
||
|
x86_64_get_irq_affinity(int irq)
|
||
|
{
|
||
|
- if (symbol_exists("irq_desc") ||
|
||
|
+ if (kernel_symbol_exists("sparse_irqs") ||
|
||
|
+ symbol_exists("irq_desc") ||
|
||
|
kernel_symbol_exists("irq_desc_ptrs") ||
|
||
|
kernel_symbol_exists("irq_desc_tree")) {
|
||
|
machdep->get_irq_affinity = generic_get_irq_affinity;
|
||
|
@@ -5419,7 +5421,8 @@ x86_64_get_irq_affinity(int irq)
|
||
|
static void
|
||
|
x86_64_show_interrupts(int irq, ulong *cpus)
|
||
|
{
|
||
|
- if (symbol_exists("irq_desc") ||
|
||
|
+ if (kernel_symbol_exists("sparse_irqs") ||
|
||
|
+ symbol_exists("irq_desc") ||
|
||
|
kernel_symbol_exists("irq_desc_ptrs") ||
|
||
|
kernel_symbol_exists("irq_desc_tree")) {
|
||
|
machdep->show_interrupts = generic_show_interrupts;
|
||
|
--
|
||
|
2.37.1
|
||
|
|