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