xref: /linux/scripts/gdb/linux/cpus.py (revision 276d97d9)
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("&current_task")
139116b47b4SJan Kiszka        return per_cpu(var_ptr, cpu).dereference()
140116b47b4SJan Kiszka
141116b47b4SJan Kiszka
142116b47b4SJan KiszkaLxCurrentFunc()
143