xref: /linux/scripts/gdb/linux/cpus.py (revision a77e15e8)
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
64*a77e15e8SJan Kiszkadef cpu_list(mask_name):
653d4cd9c9SJan Kiszka    global cpu_mask
66*a77e15e8SJan Kiszka    mask = None
673d4cd9c9SJan Kiszka    if mask_name in cpu_mask:
68*a77e15e8SJan Kiszka        mask = cpu_mask[mask_name]
69*a77e15e8SJan Kiszka    if mask is None:
70*a77e15e8SJan Kiszka        mask = gdb.parse_and_eval(mask_name + ".bits")
713d4cd9c9SJan Kiszka        if hasattr(gdb, 'events'):
72*a77e15e8SJan Kiszka            cpu_mask[mask_name] = mask
733d4cd9c9SJan Kiszka            gdb.events.stop.connect(cpu_mask_invalidate)
743d4cd9c9SJan Kiszka            if hasattr(gdb.events, 'new_objfile'):
753d4cd9c9SJan Kiszka                gdb.events.new_objfile.connect(cpu_mask_invalidate)
76*a77e15e8SJan Kiszka    bits_per_entry = mask[0].type.sizeof * 8
77*a77e15e8SJan Kiszka    num_entries = mask.type.sizeof * 8 / bits_per_entry
78*a77e15e8SJan Kiszka    entry = -1
79*a77e15e8SJan Kiszka    bits = 0
803d4cd9c9SJan Kiszka
81*a77e15e8SJan Kiszka    while True:
82*a77e15e8SJan Kiszka        while bits == 0:
83*a77e15e8SJan Kiszka            entry += 1
84*a77e15e8SJan Kiszka            if entry == num_entries:
85*a77e15e8SJan Kiszka                return
86*a77e15e8SJan Kiszka            bits = mask[entry]
87*a77e15e8SJan Kiszka            if bits != 0:
88*a77e15e8SJan Kiszka                bit = 0
893d4cd9c9SJan Kiszka                break
903d4cd9c9SJan Kiszka
91*a77e15e8SJan Kiszka        while bits & 1 == 0:
92*a77e15e8SJan Kiszka            bits >>= 1
93*a77e15e8SJan Kiszka            bit += 1
943d4cd9c9SJan Kiszka
95*a77e15e8SJan Kiszka        cpu = entry * bits_per_entry + bit
963d4cd9c9SJan Kiszka
97*a77e15e8SJan Kiszka        bits >>= 1
98*a77e15e8SJan Kiszka        bit += 1
993d4cd9c9SJan Kiszka
100*a77e15e8SJan Kiszka        yield cpu
101276d97d9SPantelis Koukousoulas
1023d4cd9c9SJan Kiszka
103fe7f9ed9SJan Kiszkaclass PerCpu(gdb.Function):
104fe7f9ed9SJan Kiszka    """Return per-cpu variable.
105fe7f9ed9SJan Kiszka
106fe7f9ed9SJan Kiszka$lx_per_cpu("VAR"[, CPU]): Return the per-cpu variable called VAR for the
107fe7f9ed9SJan Kiszkagiven CPU number. If CPU is omitted, the CPU of the current context is used.
108fe7f9ed9SJan KiszkaNote that VAR has to be quoted as string."""
109fe7f9ed9SJan Kiszka
110fe7f9ed9SJan Kiszka    def __init__(self):
111fe7f9ed9SJan Kiszka        super(PerCpu, self).__init__("lx_per_cpu")
112fe7f9ed9SJan Kiszka
113fe7f9ed9SJan Kiszka    def invoke(self, var_name, cpu=-1):
114fe7f9ed9SJan Kiszka        var_ptr = gdb.parse_and_eval("&" + var_name.string())
115fe7f9ed9SJan Kiszka        return per_cpu(var_ptr, cpu)
116fe7f9ed9SJan Kiszka
117fe7f9ed9SJan Kiszka
118fe7f9ed9SJan KiszkaPerCpu()
119116b47b4SJan Kiszka
120116b47b4SJan Kiszka
121116b47b4SJan Kiszkaclass LxCurrentFunc(gdb.Function):
122116b47b4SJan Kiszka    """Return current task.
123116b47b4SJan Kiszka
124116b47b4SJan Kiszka$lx_current([CPU]): Return the per-cpu task variable for the given CPU
125116b47b4SJan Kiszkanumber. If CPU is omitted, the CPU of the current context is used."""
126116b47b4SJan Kiszka
127116b47b4SJan Kiszka    def __init__(self):
128116b47b4SJan Kiszka        super(LxCurrentFunc, self).__init__("lx_current")
129116b47b4SJan Kiszka
130116b47b4SJan Kiszka    def invoke(self, cpu=-1):
131116b47b4SJan Kiszka        var_ptr = gdb.parse_and_eval("&current_task")
132116b47b4SJan Kiszka        return per_cpu(var_ptr, cpu).dereference()
133116b47b4SJan Kiszka
134116b47b4SJan Kiszka
135116b47b4SJan KiszkaLxCurrentFunc()
136