Skip to content

Commit 38d35bd

Browse files
committed
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 <[email protected]>
1 parent d17d51a commit 38d35bd

File tree

5 files changed

+59
-7
lines changed

5 files changed

+59
-7
lines changed

defs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,7 @@ struct new_utsname {
676676
#define IRQ_DESC_TREE_XARRAY (0x80ULL)
677677
#define KMOD_PAX (0x100ULL)
678678
#define KMOD_MEMORY (0x200ULL)
679+
#define IRQ_DESC_TREE_MAPLE (0x400ULL)
679680

680681
#define XEN() (kt->flags & ARCH_XEN)
681682
#define OPENVZ() (kt->flags & ARCH_OPENVZ)
@@ -2222,6 +2223,7 @@ struct offset_table { /* stash of commonly-used offsets */
22222223
long module_mem;
22232224
long module_memory_base;
22242225
long module_memory_size;
2226+
long irq_data_irq;
22252227
};
22262228

22272229
struct size_table { /* stash of commonly-used sizes */

ia64.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -791,7 +791,8 @@ ia64_back_trace_cmd(struct bt_info *bt)
791791
static void
792792
ia64_dump_irq(int irq)
793793
{
794-
if (symbol_exists("irq_desc") || symbol_exists("_irq_desc") ||
794+
if (kernel_symbol_exists("sparse_irqs") ||
795+
symbol_exists("irq_desc") || symbol_exists("_irq_desc") ||
795796
kernel_symbol_exists("irq_desc_ptrs")) {
796797
machdep->dump_irq = generic_dump_irq;
797798
return(generic_dump_irq(irq));

kernel.c

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,10 @@ kernel_init()
541541
MEMBER_OFFSET_INIT(irqaction_dev_id, "irqaction", "dev_id");
542542
MEMBER_OFFSET_INIT(irqaction_next, "irqaction", "next");
543543

544-
if (kernel_symbol_exists("irq_desc_tree")) {
544+
/* 6.5 and later: CONFIG_SPARSE_IRQ */
545+
if (kernel_symbol_exists("sparse_irqs"))
546+
kt->flags2 |= IRQ_DESC_TREE_MAPLE;
547+
else if (kernel_symbol_exists("irq_desc_tree")) {
545548
get_symbol_type("irq_desc_tree", NULL, &req);
546549
if (STREQ(req.type_tag_name, "xarray")) {
547550
kt->flags2 |= IRQ_DESC_TREE_XARRAY;
@@ -554,6 +557,7 @@ kernel_init()
554557
}
555558
STRUCT_SIZE_INIT(irq_data, "irq_data");
556559
if (VALID_STRUCT(irq_data)) {
560+
MEMBER_OFFSET_INIT(irq_data_irq, "irq_data", "irq");
557561
MEMBER_OFFSET_INIT(irq_data_chip, "irq_data", "chip");
558562
MEMBER_OFFSET_INIT(irq_data_affinity, "irq_data", "affinity");
559563
MEMBER_OFFSET_INIT(irq_desc_irq_data, "irq_desc", "irq_data");
@@ -6180,6 +6184,8 @@ dump_kernel_table(int verbose)
61806184
fprintf(fp, "%sIRQ_DESC_TREE_RADIX", others++ ? "|" : "");
61816185
if (kt->flags2 & IRQ_DESC_TREE_XARRAY)
61826186
fprintf(fp, "%sIRQ_DESC_TREE_XARRAY", others++ ? "|" : "");
6187+
if (kt->flags2 & IRQ_DESC_TREE_MAPLE)
6188+
fprintf(fp, "%sIRQ_DESC_TREE_MAPLE", others++ ? "|" : "");
61836189
if (kt->flags2 & KMOD_PAX)
61846190
fprintf(fp, "%sKMOD_PAX", others++ ? "|" : "");
61856191
if (kt->flags2 & KMOD_MEMORY)
@@ -6652,6 +6658,45 @@ get_irq_desc_addr(int irq)
66526658
readmem(ptr, KVADDR, &addr,
66536659
sizeof(void *), "irq_desc_ptrs entry",
66546660
FAULT_ON_ERROR);
6661+
} else if (kt->flags2 & IRQ_DESC_TREE_MAPLE) {
6662+
unsigned int i;
6663+
6664+
if (kt->highest_irq && (irq > kt->highest_irq))
6665+
return addr;
6666+
6667+
cnt = do_maple_tree(symbol_value("sparse_irqs"), MAPLE_TREE_COUNT, NULL);
6668+
6669+
len = sizeof(struct list_pair) * (cnt+1);
6670+
lp = (struct list_pair *)GETBUF(len);
6671+
lp[0].index = cnt; /* maxcount */
6672+
6673+
cnt = do_maple_tree(symbol_value("sparse_irqs"), MAPLE_TREE_GATHER, lp);
6674+
6675+
/*
6676+
* NOTE: We cannot use lp.index like Radix Tree or XArray because
6677+
* it's not an absolute index and just counter in Maple Tree.
6678+
*/
6679+
if (kt->highest_irq == 0) {
6680+
readmem((ulong)lp[cnt-1].value +
6681+
OFFSET(irq_desc_irq_data) + OFFSET(irq_data_irq),
6682+
KVADDR, &kt->highest_irq, sizeof(int), "irq_data.irq",
6683+
FAULT_ON_ERROR);
6684+
}
6685+
6686+
for (c = 0; c < cnt; c++) {
6687+
readmem((ulong)lp[c].value +
6688+
OFFSET(irq_desc_irq_data) + OFFSET(irq_data_irq),
6689+
KVADDR, &i, sizeof(int), "irq_data.irq", FAULT_ON_ERROR);
6690+
if (i == irq) {
6691+
if (CRASHDEBUG(1))
6692+
fprintf(fp, "index: %d value: %lx\n",
6693+
i, (ulong)lp[c].value);
6694+
addr = (ulong)lp[c].value;
6695+
break;
6696+
}
6697+
}
6698+
FREEBUF(lp);
6699+
66556700
} else if (kt->flags2 & (IRQ_DESC_TREE_RADIX|IRQ_DESC_TREE_XARRAY)) {
66566701
if (kt->highest_irq && (irq > kt->highest_irq))
66576702
return addr;
@@ -6700,8 +6745,8 @@ get_irq_desc_addr(int irq)
67006745
FREEBUF(lp);
67016746
} else {
67026747
error(FATAL,
6703-
"neither irq_desc, _irq_desc, irq_desc_ptrs "
6704-
"or irq_desc_tree symbols exist\n");
6748+
"neither irq_desc, _irq_desc, irq_desc_ptrs, "
6749+
"irq_desc_tree or sparse_irqs symbols exist\n");
67056750
}
67066751

67076752
return addr;

symbols.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10375,6 +10375,7 @@ dump_offset_table(char *spec, ulong makestruct)
1037510375
OFFSET(irq_desc_t_kstat_irqs));
1037610376
fprintf(fp, " irq_desc_t_affinity: %ld\n",
1037710377
OFFSET(irq_desc_t_affinity));
10378+
fprintf(fp, " irq_data_irq: %ld\n", OFFSET(irq_data_irq));
1037810379
fprintf(fp, " irq_data_chip: %ld\n",
1037910380
OFFSET(irq_data_chip));
1038010381
fprintf(fp, " irq_data_affinity: %ld\n",

x86_64.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5391,7 +5391,8 @@ get_x86_64_frame(struct bt_info *bt, ulong *getpc, ulong *getsp)
53915391
static void
53925392
x86_64_dump_irq(int irq)
53935393
{
5394-
if (symbol_exists("irq_desc") ||
5394+
if (kernel_symbol_exists("sparse_irqs") ||
5395+
symbol_exists("irq_desc") ||
53955396
kernel_symbol_exists("irq_desc_ptrs") ||
53965397
kernel_symbol_exists("irq_desc_tree")) {
53975398
machdep->dump_irq = generic_dump_irq;
@@ -5405,7 +5406,8 @@ x86_64_dump_irq(int irq)
54055406
static void
54065407
x86_64_get_irq_affinity(int irq)
54075408
{
5408-
if (symbol_exists("irq_desc") ||
5409+
if (kernel_symbol_exists("sparse_irqs") ||
5410+
symbol_exists("irq_desc") ||
54095411
kernel_symbol_exists("irq_desc_ptrs") ||
54105412
kernel_symbol_exists("irq_desc_tree")) {
54115413
machdep->get_irq_affinity = generic_get_irq_affinity;
@@ -5419,7 +5421,8 @@ x86_64_get_irq_affinity(int irq)
54195421
static void
54205422
x86_64_show_interrupts(int irq, ulong *cpus)
54215423
{
5422-
if (symbol_exists("irq_desc") ||
5424+
if (kernel_symbol_exists("sparse_irqs") ||
5425+
symbol_exists("irq_desc") ||
54235426
kernel_symbol_exists("irq_desc_ptrs") ||
54245427
kernel_symbol_exists("irq_desc_tree")) {
54255428
machdep->show_interrupts = generic_show_interrupts;

0 commit comments

Comments
 (0)