History

scripts/gdb: print interrupts

This GDB script prints the interrupts in the system in the same way that /proc/interrupts does. This does include the architecture specific part done by arch_show_interrupts() for x86, ARM, ARM64 and MIPS. Example output from an ARM64 system: (gdb) lx-interruptlist CPU0 CPU1 CPU2 CPU3 10: 3167 1225 1276 2629 GICv2 30 Level arch_timer 13: 0 0 0 0 GICv2 36 Level arm-pmu 14: 0 0 0 0 GICv2 37 Level arm-pmu 15: 0 0 0 0 GICv2 38 Level arm-pmu 16: 0 0 0 0 GICv2 39 Level arm-pmu 28: 0 0 0 0 interrupt-controller@8410640 5 Edge brcmstb-gpio-wake 30: 125 0 0 0 GICv2 128 Level ttyS0 31: 0 0 0 0 interrupt-controller@8416000 0 Level mspi_done 32: 0 0 0 0 interrupt-controller@8410640 3 Edge brcmstb-waketimer 33: 0 0 0 0 interrupt-controller@8418580 8 Edge brcmstb-waketimer-rtc 34: 872 0 0 0 GICv2 230 Level brcm_scmi@0 35: 0 0 0 0 interrupt-controller@8410640 10 Edge 8d0f200.usb-phy 37: 0 0 0 0 GICv2 97 Level PCIe PME 42: 0 0 0 0 GICv2 145 Level xhci-hcd:usb1 43: 94 0 0 0 GICv2 71 Level mmc1 44: 0 0 0 0 GICv2 70 Level mmc0 IPI0: 23 666 154 98 Rescheduling interrupts IPI1: 247 1053 1701 634 Function call interrupts IPI2: 0 0 0 0 CPU stop interrupts IPI3: 0 0 0 0 CPU stop (for crash dump) interrupts IPI4: 0 0 0 0 Timer broadcast interrupts IPI5: 7 9 5 0 IRQ work interrupts IPI6: 0 0 0 0 CPU wake-up interrupts ERR: 0

Florian Fainelli committed 3 years ago

Commit b0969d71 parent 8af055a3 files · +247 −0Browse files

Unified · Split

3 files
  1. scripts/gdb/linux/constants.py.in +14 −0
  2. scripts/gdb/linux/interrupts.py +232 −0
  3. scripts/gdb/vmlinux-gdb.py +1 −0
scripts/gdb/linux/constants.py.in+14−0
@@ -15,6 +15,7 @@ · 14 unmodified lines
1515 #include <linux/clk-provider.h>
1616 #include <linux/fs.h>
1717 #include <linux/hrtimer.h>
18+#include <linux/irq.h>
1819 #include <linux/mount.h>
1920 #include <linux/of_fdt.h>
2021 #include <linux/radix-tree.h>
@@ -57,6 +58,10 @@ LX_VALUE(SB_NODIRATIME) · 36 unmodified lines
5758 /* linux/htimer.h */
5859 LX_GDBPARSED(hrtimer_resolution)
5960
61+/* linux/irq.h */
62+LX_GDBPARSED(IRQD_LEVEL)
63+LX_GDBPARSED(IRQ_HIDDEN)
64+
6065 /* linux/mount.h */
6166 LX_VALUE(MNT_NOSUID)
6267 LX_VALUE(MNT_NODEV)
@@ -85,3 +90,12 @@ LX_CONFIG(CONFIG_HIGH_RES_TIMERS) · 22 unmodified lines
8590 LX_CONFIG(CONFIG_NR_CPUS)
8691 LX_CONFIG(CONFIG_OF)
8792 LX_CONFIG(CONFIG_TICK_ONESHOT)
93+LX_CONFIG(CONFIG_GENERIC_IRQ_SHOW_LEVEL)
94+LX_CONFIG(CONFIG_X86_LOCAL_APIC)
95+LX_CONFIG(CONFIG_SMP)
96+LX_CONFIG(CONFIG_X86_THERMAL_VECTOR)
97+LX_CONFIG(CONFIG_X86_MCE_THRESHOLD)
98+LX_CONFIG(CONFIG_X86_MCE_AMD)
99+LX_CONFIG(CONFIG_X86_MCE)
100+LX_CONFIG(CONFIG_X86_IO_APIC)
101+LX_CONFIG(CONFIG_HAVE_KVM)
scripts/gdb/linux/interrupts.py+232−0
@@ -0,0 +1,232 @@
1+# SPDX-License-Identifier: GPL-2.0
2+#
3+# Copyright 2023 Broadcom
4+
5+import gdb
6+
7+from linux import constants
8+from linux import cpus
9+from linux import utils
10+from linux import radixtree
11+
12+irq_desc_type = utils.CachedType("struct irq_desc")
13+
14+def irq_settings_is_hidden(desc):
15+ return desc['status_use_accessors'] & constants.LX_IRQ_HIDDEN
16+
17+def irq_desc_is_chained(desc):
18+ return desc['action'] and desc['action'] == gdb.parse_and_eval("&chained_action")
19+
20+def irqd_is_level(desc):
21+ return desc['irq_data']['common']['state_use_accessors'] & constants.LX_IRQD_LEVEL
22+
23+def show_irq_desc(prec, irq):
24+ text = ""
25+
26+ desc = radixtree.lookup(gdb.parse_and_eval("&irq_desc_tree"), irq)
27+ if desc is None:
28+ return text
29+
30+ desc = desc.cast(irq_desc_type.get_type())
31+ if desc is None:
32+ return text
33+
34+ if irq_settings_is_hidden(desc):
35+ return text
36+
37+ any_count = 0
38+ if desc['kstat_irqs']:
39+ for cpu in cpus.each_online_cpu():
40+ any_count += cpus.per_cpu(desc['kstat_irqs'], cpu)
41+
42+ if (desc['action'] == 0 or irq_desc_is_chained(desc)) and any_count == 0:
43+ return text;
44+
45+ text += "%*d: " % (prec, irq)
46+ for cpu in cpus.each_online_cpu():
47+ if desc['kstat_irqs']:
48+ count = cpus.per_cpu(desc['kstat_irqs'], cpu)
49+ else:
50+ count = 0
51+ text += "%10u" % (count)
52+
53+ name = "None"
54+ if desc['irq_data']['chip']:
55+ chip = desc['irq_data']['chip']
56+ if chip['name']:
57+ name = chip['name'].string()
58+ else:
59+ name = "-"
60+
61+ text += " %8s" % (name)
62+
63+ if desc['irq_data']['domain']:
64+ text += " %*lu" % (prec, desc['irq_data']['hwirq'])
65+ else:
66+ text += " %*s" % (prec, "")
67+
68+ if constants.LX_CONFIG_GENERIC_IRQ_SHOW_LEVEL:
69+ text += " %-8s" % ("Level" if irqd_is_level(desc) else "Edge")
70+
71+ if desc['name']:
72+ text += "-%-8s" % (desc['name'].string())
73+
74+ """ Some toolchains may not be able to provide information about irqaction """
75+ try:
76+ gdb.lookup_type("struct irqaction")
77+ action = desc['action']
78+ if action is not None:
79+ text += " %s" % (action['name'].string())
80+ while True:
81+ action = action['next']
82+ if action is not None:
83+ break
84+ if action['name']:
85+ text += ", %s" % (action['name'].string())
86+ except:
87+ pass
88+
89+ text += "\n"
90+
91+ return text
92+
93+def show_irq_err_count(prec):
94+ cnt = utils.gdb_eval_or_none("irq_err_count")
95+ text = ""
96+ if cnt is not None:
97+ text += "%*s: %10u\n" % (prec, "ERR", cnt['counter'])
98+ return text
99+
100+def x86_show_irqstat(prec, pfx, field, desc):
101+ irq_stat = gdb.parse_and_eval("&irq_stat")
102+ text = "%*s: " % (prec, pfx)
103+ for cpu in cpus.each_online_cpu():
104+ stat = cpus.per_cpu(irq_stat, cpu)
105+ text += "%10u " % (stat[field])
106+ text += " %s\n" % (desc)
107+ return text
108+
109+def x86_show_mce(prec, var, pfx, desc):
110+ pvar = gdb.parse_and_eval(var)
111+ text = "%*s: " % (prec, pfx)
112+ for cpu in cpus.each_online_cpu():
113+ text += "%10u " % (cpus.per_cpu(pvar, cpu))
114+ text += " %s\n" % (desc)
115+ return text
116+
117+def x86_show_interupts(prec):
118+ text = x86_show_irqstat(prec, "NMI", '__nmi_count', 'Non-maskable interrupts')
119+
120+ if constants.LX_CONFIG_X86_LOCAL_APIC:
121+ text += x86_show_irqstat(prec, "LOC", 'apic_timer_irqs', "Local timer interrupts")
122+ text += x86_show_irqstat(prec, "SPU", 'irq_spurious_count', "Spurious interrupts")
123+ text += x86_show_irqstat(prec, "PMI", 'apic_perf_irqs', "Performance monitoring interrupts")
124+ text += x86_show_irqstat(prec, "IWI", 'apic_irq_work_irqs', "IRQ work interrupts")
125+ text += x86_show_irqstat(prec, "RTR", 'icr_read_retry_count', "APIC ICR read retries")
126+ if utils.gdb_eval_or_none("x86_platform_ipi_callback") is not None:
127+ text += x86_show_irqstat(prec, "PLT", 'x86_platform_ipis', "Platform interrupts")
128+
129+ if constants.LX_CONFIG_SMP:
130+ text += x86_show_irqstat(prec, "RES", 'irq_resched_count', "Rescheduling interrupts")
131+ text += x86_show_irqstat(prec, "CAL", 'irq_call_count', "Function call interrupts")
132+ text += x86_show_irqstat(prec, "TLB", 'irq_tlb_count', "TLB shootdowns")
133+
134+ if constants.LX_CONFIG_X86_THERMAL_VECTOR:
135+ text += x86_show_irqstat(prec, "TRM", 'irq_thermal_count', "Thermal events interrupts")
136+
137+ if constants.LX_CONFIG_X86_MCE_THRESHOLD:
138+ text += x86_show_irqstat(prec, "THR", 'irq_threshold_count', "Threshold APIC interrupts")
139+
140+ if constants.LX_CONFIG_X86_MCE_AMD:
141+ text += x86_show_irqstat(prec, "DFR", 'irq_deferred_error_count', "Deferred Error APIC interrupts")
142+
143+ if constants.LX_CONFIG_X86_MCE:
144+ text += x86_show_mce(prec, "&mce_exception_count", "MCE", "Machine check exceptions")
145+ text == x86_show_mce(prec, "&mce_poll_count", "MCP", "Machine check polls")
146+
147+ text += show_irq_err_count(prec)
148+
149+ if constants.LX_CONFIG_X86_IO_APIC:
150+ cnt = utils.gdb_eval_or_none("irq_mis_count")
151+ if cnt is not None:
152+ text += "%*s: %10u\n" % (prec, "MIS", cnt['counter'])
153+
154+ if constants.LX_CONFIG_HAVE_KVM:
155+ text += x86_show_irqstat(prec, "PIN", 'kvm_posted_intr_ipis', 'Posted-interrupt notification event')
156+ text += x86_show_irqstat(prec, "NPI", 'kvm_posted_intr_nested_ipis', 'Nested posted-interrupt event')
157+ text += x86_show_irqstat(prec, "PIW", 'kvm_posted_intr_wakeup_ipis', 'Posted-interrupt wakeup event')
158+
159+ return text
160+
161+def arm_common_show_interrupts(prec):
162+ text = ""
163+ nr_ipi = utils.gdb_eval_or_none("nr_ipi")
164+ ipi_desc = utils.gdb_eval_or_none("ipi_desc")
165+ ipi_types = utils.gdb_eval_or_none("ipi_types")
166+ if nr_ipi is None or ipi_desc is None or ipi_types is None:
167+ return text
168+
169+ if prec >= 4:
170+ sep = " "
171+ else:
172+ sep = ""
173+
174+ for ipi in range(nr_ipi):
175+ text += "%*s%u:%s" % (prec - 1, "IPI", ipi, sep)
176+ desc = ipi_desc[ipi].cast(irq_desc_type.get_type().pointer())
177+ if desc == 0:
178+ continue
179+ for cpu in cpus.each_online_cpu():
180+ text += "%10u" % (cpus.per_cpu(desc['kstat_irqs'], cpu))
181+ text += " %s" % (ipi_types[ipi].string())
182+ text += "\n"
183+ return text
184+
185+def aarch64_show_interrupts(prec):
186+ text = arm_common_show_interrupts(prec)
187+ text += "%*s: %10lu\n" % (prec, "ERR", gdb.parse_and_eval("irq_err_count"))
188+ return text
189+
190+def arch_show_interrupts(prec):
191+ text = ""
192+ if utils.is_target_arch("x86"):
193+ text += x86_show_interupts(prec)
194+ elif utils.is_target_arch("aarch64"):
195+ text += aarch64_show_interrupts(prec)
196+ elif utils.is_target_arch("arm"):
197+ text += arm_common_show_interrupts(prec)
198+ elif utils.is_target_arch("mips"):
199+ text += show_irq_err_count(prec)
200+ else:
201+ raise gdb.GdbError("Unsupported architecture: {}".format(target_arch))
202+
203+ return text
204+
205+class LxInterruptList(gdb.Command):
206+ """Print /proc/interrupts"""
207+
208+ def __init__(self):
209+ super(LxInterruptList, self).__init__("lx-interruptlist", gdb.COMMAND_DATA)
210+
211+ def invoke(self, arg, from_tty):
212+ nr_irqs = gdb.parse_and_eval("nr_irqs")
213+ prec = 3
214+ j = 1000
215+ while prec < 10 and j <= nr_irqs:
216+ prec += 1
217+ j *= 10
218+
219+ gdb.write("%*s" % (prec + 8, ""))
220+ for cpu in cpus.each_online_cpu():
221+ gdb.write("CPU%-8d" % cpu)
222+ gdb.write("\n")
223+
224+ if utils.gdb_eval_or_none("&irq_desc_tree") is None:
225+ return
226+
227+ for irq in range(nr_irqs):
228+ gdb.write(show_irq_desc(prec, irq))
229+ gdb.write(arch_show_interrupts(prec))
230+
231+
232+LxInterruptList()
scripts/gdb/vmlinux-gdb.py+1−0
@@ -42,3 +42,4 @@ else: · 41 unmodified lines
4242 import linux.device
4343 import linux.mm
4444 import linux.radixtree
45+ import linux.interrupts

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t