1fe7f9ed9SJan Kiszka# 2fe7f9ed9SJan Kiszka# gdb helper commands and functions for Linux kernel debugging 3fe7f9ed9SJan Kiszka# 4fe7f9ed9SJan Kiszka# per-cpu tools 5fe7f9ed9SJan Kiszka# 6fe7f9ed9SJan Kiszka# Copyright (c) Siemens AG, 2011-2013 7fe7f9ed9SJan Kiszka# 8fe7f9ed9SJan Kiszka# Authors: 9fe7f9ed9SJan Kiszka# Jan Kiszka <jan.kiszka@siemens.com> 10fe7f9ed9SJan Kiszka# 11fe7f9ed9SJan Kiszka# This work is licensed under the terms of the GNU GPL version 2. 12fe7f9ed9SJan Kiszka# 13fe7f9ed9SJan Kiszka 14fe7f9ed9SJan Kiszkaimport gdb 15fe7f9ed9SJan Kiszka 16fe7f9ed9SJan Kiszkafrom linux import tasks, utils 17fe7f9ed9SJan Kiszka 18fe7f9ed9SJan Kiszka 19526940e3SBarry Songtask_type = utils.CachedType("struct task_struct") 20526940e3SBarry Song 21526940e3SBarry Song 22fe7f9ed9SJan KiszkaMAX_CPUS = 4096 23fe7f9ed9SJan Kiszka 24fe7f9ed9SJan Kiszka 25fe7f9ed9SJan Kiszkadef get_current_cpu(): 26fe7f9ed9SJan Kiszka if utils.get_gdbserver_type() == utils.GDBSERVER_QEMU: 27fe7f9ed9SJan Kiszka return gdb.selected_thread().num - 1 28fe7f9ed9SJan Kiszka elif utils.get_gdbserver_type() == utils.GDBSERVER_KGDB: 29fe7f9ed9SJan Kiszka tid = gdb.selected_thread().ptid[2] 30fe7f9ed9SJan Kiszka if tid > (0x100000000 - MAX_CPUS - 2): 31fe7f9ed9SJan Kiszka return 0x100000000 - tid - 2 32fe7f9ed9SJan Kiszka else: 33fe7f9ed9SJan Kiszka return tasks.get_thread_info(tasks.get_task_by_pid(tid))['cpu'] 34fe7f9ed9SJan Kiszka else: 35fe7f9ed9SJan Kiszka raise gdb.GdbError("Sorry, obtaining the current CPU is not yet " 36fe7f9ed9SJan Kiszka "supported with this gdb server.") 37fe7f9ed9SJan Kiszka 38fe7f9ed9SJan Kiszka 39fe7f9ed9SJan Kiszkadef per_cpu(var_ptr, cpu): 40fe7f9ed9SJan Kiszka if cpu == -1: 41fe7f9ed9SJan Kiszka cpu = get_current_cpu() 42fe7f9ed9SJan Kiszka if utils.is_target_arch("sparc:v9"): 43fe7f9ed9SJan Kiszka offset = gdb.parse_and_eval( 44fe7f9ed9SJan Kiszka "trap_block[{0}].__per_cpu_base".format(str(cpu))) 45fe7f9ed9SJan Kiszka else: 46fe7f9ed9SJan Kiszka try: 47fe7f9ed9SJan Kiszka offset = gdb.parse_and_eval( 48fe7f9ed9SJan Kiszka "__per_cpu_offset[{0}]".format(str(cpu))) 49fe7f9ed9SJan Kiszka except gdb.error: 50fe7f9ed9SJan Kiszka # !CONFIG_SMP case 51fe7f9ed9SJan Kiszka offset = 0 52fe7f9ed9SJan Kiszka pointer = var_ptr.cast(utils.get_long_type()) + offset 53fe7f9ed9SJan Kiszka return pointer.cast(var_ptr.type).dereference() 54fe7f9ed9SJan Kiszka 55fe7f9ed9SJan Kiszka 563d4cd9c9SJan Kiszkacpu_mask = {} 573d4cd9c9SJan Kiszka 583d4cd9c9SJan Kiszka 593d4cd9c9SJan Kiszkadef cpu_mask_invalidate(event): 603d4cd9c9SJan Kiszka global cpu_mask 613d4cd9c9SJan Kiszka cpu_mask = {} 623d4cd9c9SJan Kiszka gdb.events.stop.disconnect(cpu_mask_invalidate) 633d4cd9c9SJan Kiszka if hasattr(gdb.events, 'new_objfile'): 643d4cd9c9SJan Kiszka gdb.events.new_objfile.disconnect(cpu_mask_invalidate) 653d4cd9c9SJan Kiszka 663d4cd9c9SJan Kiszka 67a77e15e8SJan Kiszkadef cpu_list(mask_name): 683d4cd9c9SJan Kiszka global cpu_mask 69a77e15e8SJan Kiszka mask = None 703d4cd9c9SJan Kiszka if mask_name in cpu_mask: 71a77e15e8SJan Kiszka mask = cpu_mask[mask_name] 72a77e15e8SJan Kiszka if mask is None: 73a77e15e8SJan Kiszka mask = gdb.parse_and_eval(mask_name + ".bits") 743d4cd9c9SJan Kiszka if hasattr(gdb, 'events'): 75a77e15e8SJan Kiszka cpu_mask[mask_name] = mask 763d4cd9c9SJan Kiszka gdb.events.stop.connect(cpu_mask_invalidate) 773d4cd9c9SJan Kiszka if hasattr(gdb.events, 'new_objfile'): 783d4cd9c9SJan Kiszka gdb.events.new_objfile.connect(cpu_mask_invalidate) 79a77e15e8SJan Kiszka bits_per_entry = mask[0].type.sizeof * 8 80a77e15e8SJan Kiszka num_entries = mask.type.sizeof * 8 / bits_per_entry 81a77e15e8SJan Kiszka entry = -1 82a77e15e8SJan Kiszka bits = 0 833d4cd9c9SJan Kiszka 84a77e15e8SJan Kiszka while True: 85a77e15e8SJan Kiszka while bits == 0: 86a77e15e8SJan Kiszka entry += 1 87a77e15e8SJan Kiszka if entry == num_entries: 88a77e15e8SJan Kiszka return 89a77e15e8SJan Kiszka bits = mask[entry] 90a77e15e8SJan Kiszka if bits != 0: 91a77e15e8SJan Kiszka bit = 0 923d4cd9c9SJan Kiszka break 933d4cd9c9SJan Kiszka 94a77e15e8SJan Kiszka while bits & 1 == 0: 95a77e15e8SJan Kiszka bits >>= 1 96a77e15e8SJan Kiszka bit += 1 973d4cd9c9SJan Kiszka 98a77e15e8SJan Kiszka cpu = entry * bits_per_entry + bit 993d4cd9c9SJan Kiszka 100a77e15e8SJan Kiszka bits >>= 1 101a77e15e8SJan Kiszka bit += 1 1023d4cd9c9SJan Kiszka 1034bc393dbSJan Kiszka yield int(cpu) 104276d97d9SPantelis Koukousoulas 1053d4cd9c9SJan Kiszka 106b1503934SKieran Binghamdef each_online_cpu(): 107b1503934SKieran Bingham for cpu in cpu_list("__cpu_online_mask"): 108b1503934SKieran Bingham yield cpu 109b1503934SKieran Bingham 110b1503934SKieran Bingham 111b1503934SKieran Binghamdef each_present_cpu(): 112b1503934SKieran Bingham for cpu in cpu_list("__cpu_present_mask"): 113b1503934SKieran Bingham yield cpu 114b1503934SKieran Bingham 115b1503934SKieran Bingham 116b1503934SKieran Binghamdef each_possible_cpu(): 117b1503934SKieran Bingham for cpu in cpu_list("__cpu_possible_mask"): 118b1503934SKieran Bingham yield cpu 119b1503934SKieran Bingham 120b1503934SKieran Bingham 121b1503934SKieran Binghamdef each_active_cpu(): 122b1503934SKieran Bingham for cpu in cpu_list("__cpu_active_mask"): 123b1503934SKieran Bingham yield cpu 124b1503934SKieran Bingham 125b1503934SKieran Bingham 126b1503934SKieran Binghamclass LxCpus(gdb.Command): 127b1503934SKieran Bingham """List CPU status arrays 128b1503934SKieran Bingham 129b1503934SKieran BinghamDisplays the known state of each CPU based on the kernel masks 130b1503934SKieran Binghamand can help identify the state of hotplugged CPUs""" 131b1503934SKieran Bingham 132b1503934SKieran Bingham def __init__(self): 133b1503934SKieran Bingham super(LxCpus, self).__init__("lx-cpus", gdb.COMMAND_DATA) 134b1503934SKieran Bingham 135b1503934SKieran Bingham def invoke(self, arg, from_tty): 136b1503934SKieran Bingham gdb.write("Possible CPUs : {}\n".format(list(each_possible_cpu()))) 137b1503934SKieran Bingham gdb.write("Present CPUs : {}\n".format(list(each_present_cpu()))) 138b1503934SKieran Bingham gdb.write("Online CPUs : {}\n".format(list(each_online_cpu()))) 139b1503934SKieran Bingham gdb.write("Active CPUs : {}\n".format(list(each_active_cpu()))) 140b1503934SKieran Bingham 141494dbe02SStephen Boyd 142b1503934SKieran BinghamLxCpus() 143b1503934SKieran Bingham 144b1503934SKieran Bingham 145fe7f9ed9SJan Kiszkaclass PerCpu(gdb.Function): 146fe7f9ed9SJan Kiszka """Return per-cpu variable. 147fe7f9ed9SJan Kiszka 148fe7f9ed9SJan Kiszka$lx_per_cpu("VAR"[, CPU]): Return the per-cpu variable called VAR for the 149fe7f9ed9SJan Kiszkagiven CPU number. If CPU is omitted, the CPU of the current context is used. 150fe7f9ed9SJan KiszkaNote that VAR has to be quoted as string.""" 151fe7f9ed9SJan Kiszka 152fe7f9ed9SJan Kiszka def __init__(self): 153fe7f9ed9SJan Kiszka super(PerCpu, self).__init__("lx_per_cpu") 154fe7f9ed9SJan Kiszka 155fe7f9ed9SJan Kiszka def invoke(self, var_name, cpu=-1): 156fe7f9ed9SJan Kiszka var_ptr = gdb.parse_and_eval("&" + var_name.string()) 157fe7f9ed9SJan Kiszka return per_cpu(var_ptr, cpu) 158fe7f9ed9SJan Kiszka 159fe7f9ed9SJan Kiszka 160fe7f9ed9SJan KiszkaPerCpu() 161116b47b4SJan Kiszka 162dc958682SBarry Songdef get_current_task(cpu): 163526940e3SBarry Song task_ptr_type = task_type.get_type().pointer() 164526940e3SBarry Song 165dc958682SBarry Song if utils.is_target_arch("x86"): 1666d51363dSGlenn Washburn if gdb.lookup_global_symbol("cpu_tasks"): 1676d51363dSGlenn Washburn # This is a UML kernel, which stores the current task 1686d51363dSGlenn Washburn # differently than other x86 sub architectures 1696d51363dSGlenn Washburn var_ptr = gdb.parse_and_eval("(struct task_struct *)cpu_tasks[0].task") 1706d51363dSGlenn Washburn return var_ptr.dereference() 1716d51363dSGlenn Washburn else: 172c16a3b11SJeff Xie var_ptr = gdb.parse_and_eval("&pcpu_hot.current_task") 173dc958682SBarry Song return per_cpu(var_ptr, cpu).dereference() 174526940e3SBarry Song elif utils.is_target_arch("aarch64"): 175526940e3SBarry Song current_task_addr = gdb.parse_and_eval("$SP_EL0") 17656fe4870SGlenn Washburn if (current_task_addr >> 63) != 0: 177526940e3SBarry Song current_task = current_task_addr.cast(task_ptr_type) 178526940e3SBarry Song return current_task.dereference() 179526940e3SBarry Song else: 180526940e3SBarry Song raise gdb.GdbError("Sorry, obtaining the current task is not allowed " 181526940e3SBarry Song "while running in userspace(EL0)") 182*cd24f440SDeepak Gupta elif utils.is_target_arch("riscv"): 183*cd24f440SDeepak Gupta current_tp = gdb.parse_and_eval("$tp") 184*cd24f440SDeepak Gupta scratch_reg = gdb.parse_and_eval("$sscratch") 185*cd24f440SDeepak Gupta 186*cd24f440SDeepak Gupta # by default tp points to current task 187*cd24f440SDeepak Gupta current_task = current_tp.cast(task_ptr_type) 188*cd24f440SDeepak Gupta 189*cd24f440SDeepak Gupta # scratch register is set 0 in trap handler after entering kernel. 190*cd24f440SDeepak Gupta # When hart is in user mode, scratch register is pointing to task_struct. 191*cd24f440SDeepak Gupta # and tp is used by user mode. So when scratch register holds larger value 192*cd24f440SDeepak Gupta # (negative address as ulong is larger value) than tp, then use scratch register. 193*cd24f440SDeepak Gupta if (scratch_reg.cast(utils.get_ulong_type()) > current_tp.cast(utils.get_ulong_type())): 194*cd24f440SDeepak Gupta current_task = scratch_reg.cast(task_ptr_type) 195*cd24f440SDeepak Gupta 196*cd24f440SDeepak Gupta return current_task.dereference() 197dc958682SBarry Song else: 198dc958682SBarry Song raise gdb.GdbError("Sorry, obtaining the current task is not yet " 199dc958682SBarry Song "supported with this arch") 200116b47b4SJan Kiszka 201116b47b4SJan Kiszkaclass LxCurrentFunc(gdb.Function): 202116b47b4SJan Kiszka """Return current task. 203116b47b4SJan Kiszka 204116b47b4SJan Kiszka$lx_current([CPU]): Return the per-cpu task variable for the given CPU 205116b47b4SJan Kiszkanumber. If CPU is omitted, the CPU of the current context is used.""" 206116b47b4SJan Kiszka 207116b47b4SJan Kiszka def __init__(self): 208116b47b4SJan Kiszka super(LxCurrentFunc, self).__init__("lx_current") 209116b47b4SJan Kiszka 210116b47b4SJan Kiszka def invoke(self, cpu=-1): 211dc958682SBarry Song return get_current_task(cpu) 212116b47b4SJan Kiszka 213116b47b4SJan Kiszka 214116b47b4SJan KiszkaLxCurrentFunc() 215