Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

Link: https://lkml.kernel.org/r/20230406220451.1583239-1-f.fainelli@gmail.com
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Cc: Jan Kiszka <jan.kiszka@siemens.com>
Cc: Kieran Bingham <kbingham@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Florian Fainelli and committed by
Andrew Morton
b0969d76 8af055ae

+247
+14
scripts/gdb/linux/constants.py.in
··· 15 15 #include <linux/clk-provider.h> 16 16 #include <linux/fs.h> 17 17 #include <linux/hrtimer.h> 18 + #include <linux/irq.h> 18 19 #include <linux/mount.h> 19 20 #include <linux/of_fdt.h> 20 21 #include <linux/radix-tree.h> ··· 58 57 /* linux/htimer.h */ 59 58 LX_GDBPARSED(hrtimer_resolution) 60 59 60 + /* linux/irq.h */ 61 + LX_GDBPARSED(IRQD_LEVEL) 62 + LX_GDBPARSED(IRQ_HIDDEN) 63 + 61 64 /* linux/mount.h */ 62 65 LX_VALUE(MNT_NOSUID) 63 66 LX_VALUE(MNT_NODEV) ··· 90 85 LX_CONFIG(CONFIG_NR_CPUS) 91 86 LX_CONFIG(CONFIG_OF) 92 87 LX_CONFIG(CONFIG_TICK_ONESHOT) 88 + LX_CONFIG(CONFIG_GENERIC_IRQ_SHOW_LEVEL) 89 + LX_CONFIG(CONFIG_X86_LOCAL_APIC) 90 + LX_CONFIG(CONFIG_SMP) 91 + LX_CONFIG(CONFIG_X86_THERMAL_VECTOR) 92 + LX_CONFIG(CONFIG_X86_MCE_THRESHOLD) 93 + LX_CONFIG(CONFIG_X86_MCE_AMD) 94 + LX_CONFIG(CONFIG_X86_MCE) 95 + LX_CONFIG(CONFIG_X86_IO_APIC) 96 + LX_CONFIG(CONFIG_HAVE_KVM)
+232
scripts/gdb/linux/interrupts.py
··· 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()
+1
scripts/gdb/vmlinux-gdb.py
··· 42 42 import linux.device 43 43 import linux.mm 44 44 import linux.radixtree 45 + import linux.interrupts