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 19fe7f9ed9SJan KiszkaMAX_CPUS = 4096 20fe7f9ed9SJan Kiszka 21fe7f9ed9SJan Kiszka 22fe7f9ed9SJan Kiszkadef get_current_cpu(): 23fe7f9ed9SJan Kiszka if utils.get_gdbserver_type() == utils.GDBSERVER_QEMU: 24fe7f9ed9SJan Kiszka return gdb.selected_thread().num - 1 25fe7f9ed9SJan Kiszka elif utils.get_gdbserver_type() == utils.GDBSERVER_KGDB: 26fe7f9ed9SJan Kiszka tid = gdb.selected_thread().ptid[2] 27fe7f9ed9SJan Kiszka if tid > (0x100000000 - MAX_CPUS - 2): 28fe7f9ed9SJan Kiszka return 0x100000000 - tid - 2 29fe7f9ed9SJan Kiszka else: 30fe7f9ed9SJan Kiszka return tasks.get_thread_info(tasks.get_task_by_pid(tid))['cpu'] 31fe7f9ed9SJan Kiszka else: 32fe7f9ed9SJan Kiszka raise gdb.GdbError("Sorry, obtaining the current CPU is not yet " 33fe7f9ed9SJan Kiszka "supported with this gdb server.") 34fe7f9ed9SJan Kiszka 35fe7f9ed9SJan Kiszka 36fe7f9ed9SJan Kiszkadef per_cpu(var_ptr, cpu): 37fe7f9ed9SJan Kiszka if cpu == -1: 38fe7f9ed9SJan Kiszka cpu = get_current_cpu() 39fe7f9ed9SJan Kiszka if utils.is_target_arch("sparc:v9"): 40fe7f9ed9SJan Kiszka offset = gdb.parse_and_eval( 41fe7f9ed9SJan Kiszka "trap_block[{0}].__per_cpu_base".format(str(cpu))) 42fe7f9ed9SJan Kiszka else: 43fe7f9ed9SJan Kiszka try: 44fe7f9ed9SJan Kiszka offset = gdb.parse_and_eval( 45fe7f9ed9SJan Kiszka "__per_cpu_offset[{0}]".format(str(cpu))) 46fe7f9ed9SJan Kiszka except gdb.error: 47fe7f9ed9SJan Kiszka # !CONFIG_SMP case 48fe7f9ed9SJan Kiszka offset = 0 49fe7f9ed9SJan Kiszka pointer = var_ptr.cast(utils.get_long_type()) + offset 50fe7f9ed9SJan Kiszka return pointer.cast(var_ptr.type).dereference() 51fe7f9ed9SJan Kiszka 52fe7f9ed9SJan Kiszka 533d4cd9c9SJan Kiszkacpu_mask = {} 543d4cd9c9SJan Kiszka 553d4cd9c9SJan Kiszka 563d4cd9c9SJan Kiszkadef cpu_mask_invalidate(event): 573d4cd9c9SJan Kiszka global cpu_mask 583d4cd9c9SJan Kiszka cpu_mask = {} 593d4cd9c9SJan Kiszka gdb.events.stop.disconnect(cpu_mask_invalidate) 603d4cd9c9SJan Kiszka if hasattr(gdb.events, 'new_objfile'): 613d4cd9c9SJan Kiszka gdb.events.new_objfile.disconnect(cpu_mask_invalidate) 623d4cd9c9SJan Kiszka 633d4cd9c9SJan Kiszka 643d4cd9c9SJan Kiszkaclass CpuList(): 653d4cd9c9SJan Kiszka def __init__(self, mask_name): 663d4cd9c9SJan Kiszka global cpu_mask 673d4cd9c9SJan Kiszka self.mask = None 683d4cd9c9SJan Kiszka if mask_name in cpu_mask: 693d4cd9c9SJan Kiszka self.mask = cpu_mask[mask_name] 703d4cd9c9SJan Kiszka if self.mask is None: 713d4cd9c9SJan Kiszka self.mask = gdb.parse_and_eval(mask_name + ".bits") 723d4cd9c9SJan Kiszka if hasattr(gdb, 'events'): 733d4cd9c9SJan Kiszka cpu_mask[mask_name] = self.mask 743d4cd9c9SJan Kiszka gdb.events.stop.connect(cpu_mask_invalidate) 753d4cd9c9SJan Kiszka if hasattr(gdb.events, 'new_objfile'): 763d4cd9c9SJan Kiszka gdb.events.new_objfile.connect(cpu_mask_invalidate) 773d4cd9c9SJan Kiszka self.bits_per_entry = self.mask[0].type.sizeof * 8 783d4cd9c9SJan Kiszka self.num_entries = self.mask.type.sizeof * 8 / self.bits_per_entry 793d4cd9c9SJan Kiszka self.entry = -1 803d4cd9c9SJan Kiszka self.bits = 0 813d4cd9c9SJan Kiszka 823d4cd9c9SJan Kiszka def __iter__(self): 833d4cd9c9SJan Kiszka return self 843d4cd9c9SJan Kiszka 85*276d97d9SPantelis Koukousoulas def __next__(self): 863d4cd9c9SJan Kiszka while self.bits == 0: 873d4cd9c9SJan Kiszka self.entry += 1 883d4cd9c9SJan Kiszka if self.entry == self.num_entries: 893d4cd9c9SJan Kiszka raise StopIteration 903d4cd9c9SJan Kiszka self.bits = self.mask[self.entry] 913d4cd9c9SJan Kiszka if self.bits != 0: 923d4cd9c9SJan Kiszka self.bit = 0 933d4cd9c9SJan Kiszka break 943d4cd9c9SJan Kiszka 953d4cd9c9SJan Kiszka while self.bits & 1 == 0: 963d4cd9c9SJan Kiszka self.bits >>= 1 973d4cd9c9SJan Kiszka self.bit += 1 983d4cd9c9SJan Kiszka 993d4cd9c9SJan Kiszka cpu = self.entry * self.bits_per_entry + self.bit 1003d4cd9c9SJan Kiszka 1013d4cd9c9SJan Kiszka self.bits >>= 1 1023d4cd9c9SJan Kiszka self.bit += 1 1033d4cd9c9SJan Kiszka 1043d4cd9c9SJan Kiszka return cpu 1053d4cd9c9SJan Kiszka 106*276d97d9SPantelis Koukousoulas def next(self): 107*276d97d9SPantelis Koukousoulas return self.__next__() 108*276d97d9SPantelis Koukousoulas 1093d4cd9c9SJan Kiszka 110fe7f9ed9SJan Kiszkaclass PerCpu(gdb.Function): 111fe7f9ed9SJan Kiszka """Return per-cpu variable. 112fe7f9ed9SJan Kiszka 113fe7f9ed9SJan Kiszka$lx_per_cpu("VAR"[, CPU]): Return the per-cpu variable called VAR for the 114fe7f9ed9SJan Kiszkagiven CPU number. If CPU is omitted, the CPU of the current context is used. 115fe7f9ed9SJan KiszkaNote that VAR has to be quoted as string.""" 116fe7f9ed9SJan Kiszka 117fe7f9ed9SJan Kiszka def __init__(self): 118fe7f9ed9SJan Kiszka super(PerCpu, self).__init__("lx_per_cpu") 119fe7f9ed9SJan Kiszka 120fe7f9ed9SJan Kiszka def invoke(self, var_name, cpu=-1): 121fe7f9ed9SJan Kiszka var_ptr = gdb.parse_and_eval("&" + var_name.string()) 122fe7f9ed9SJan Kiszka return per_cpu(var_ptr, cpu) 123fe7f9ed9SJan Kiszka 124fe7f9ed9SJan Kiszka 125fe7f9ed9SJan KiszkaPerCpu() 126116b47b4SJan Kiszka 127116b47b4SJan Kiszka 128116b47b4SJan Kiszkaclass LxCurrentFunc(gdb.Function): 129116b47b4SJan Kiszka """Return current task. 130116b47b4SJan Kiszka 131116b47b4SJan Kiszka$lx_current([CPU]): Return the per-cpu task variable for the given CPU 132116b47b4SJan Kiszkanumber. If CPU is omitted, the CPU of the current context is used.""" 133116b47b4SJan Kiszka 134116b47b4SJan Kiszka def __init__(self): 135116b47b4SJan Kiszka super(LxCurrentFunc, self).__init__("lx_current") 136116b47b4SJan Kiszka 137116b47b4SJan Kiszka def invoke(self, cpu=-1): 138116b47b4SJan Kiszka var_ptr = gdb.parse_and_eval("¤t_task") 139116b47b4SJan Kiszka return per_cpu(var_ptr, cpu).dereference() 140116b47b4SJan Kiszka 141116b47b4SJan Kiszka 142116b47b4SJan KiszkaLxCurrentFunc() 143