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