xref: /OK3568_Linux_fs/kernel/scripts/gdb/linux/cpus.py (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#
2*4882a593Smuzhiyun# gdb helper commands and functions for Linux kernel debugging
3*4882a593Smuzhiyun#
4*4882a593Smuzhiyun#  per-cpu tools
5*4882a593Smuzhiyun#
6*4882a593Smuzhiyun# Copyright (c) Siemens AG, 2011-2013
7*4882a593Smuzhiyun#
8*4882a593Smuzhiyun# Authors:
9*4882a593Smuzhiyun#  Jan Kiszka <jan.kiszka@siemens.com>
10*4882a593Smuzhiyun#
11*4882a593Smuzhiyun# This work is licensed under the terms of the GNU GPL version 2.
12*4882a593Smuzhiyun#
13*4882a593Smuzhiyun
14*4882a593Smuzhiyunimport gdb
15*4882a593Smuzhiyun
16*4882a593Smuzhiyunfrom linux import tasks, utils
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun
19*4882a593SmuzhiyunMAX_CPUS = 4096
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun
22*4882a593Smuzhiyundef get_current_cpu():
23*4882a593Smuzhiyun    if utils.get_gdbserver_type() == utils.GDBSERVER_QEMU:
24*4882a593Smuzhiyun        return gdb.selected_thread().num - 1
25*4882a593Smuzhiyun    elif utils.get_gdbserver_type() == utils.GDBSERVER_KGDB:
26*4882a593Smuzhiyun        tid = gdb.selected_thread().ptid[2]
27*4882a593Smuzhiyun        if tid > (0x100000000 - MAX_CPUS - 2):
28*4882a593Smuzhiyun            return 0x100000000 - tid - 2
29*4882a593Smuzhiyun        else:
30*4882a593Smuzhiyun            return tasks.get_thread_info(tasks.get_task_by_pid(tid))['cpu']
31*4882a593Smuzhiyun    else:
32*4882a593Smuzhiyun        raise gdb.GdbError("Sorry, obtaining the current CPU is not yet "
33*4882a593Smuzhiyun                           "supported with this gdb server.")
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun
36*4882a593Smuzhiyundef per_cpu(var_ptr, cpu):
37*4882a593Smuzhiyun    if cpu == -1:
38*4882a593Smuzhiyun        cpu = get_current_cpu()
39*4882a593Smuzhiyun    if utils.is_target_arch("sparc:v9"):
40*4882a593Smuzhiyun        offset = gdb.parse_and_eval(
41*4882a593Smuzhiyun            "trap_block[{0}].__per_cpu_base".format(str(cpu)))
42*4882a593Smuzhiyun    else:
43*4882a593Smuzhiyun        try:
44*4882a593Smuzhiyun            offset = gdb.parse_and_eval(
45*4882a593Smuzhiyun                "__per_cpu_offset[{0}]".format(str(cpu)))
46*4882a593Smuzhiyun        except gdb.error:
47*4882a593Smuzhiyun            # !CONFIG_SMP case
48*4882a593Smuzhiyun            offset = 0
49*4882a593Smuzhiyun    pointer = var_ptr.cast(utils.get_long_type()) + offset
50*4882a593Smuzhiyun    return pointer.cast(var_ptr.type).dereference()
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun
53*4882a593Smuzhiyuncpu_mask = {}
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun
56*4882a593Smuzhiyundef cpu_mask_invalidate(event):
57*4882a593Smuzhiyun    global cpu_mask
58*4882a593Smuzhiyun    cpu_mask = {}
59*4882a593Smuzhiyun    gdb.events.stop.disconnect(cpu_mask_invalidate)
60*4882a593Smuzhiyun    if hasattr(gdb.events, 'new_objfile'):
61*4882a593Smuzhiyun        gdb.events.new_objfile.disconnect(cpu_mask_invalidate)
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun
64*4882a593Smuzhiyundef cpu_list(mask_name):
65*4882a593Smuzhiyun    global cpu_mask
66*4882a593Smuzhiyun    mask = None
67*4882a593Smuzhiyun    if mask_name in cpu_mask:
68*4882a593Smuzhiyun        mask = cpu_mask[mask_name]
69*4882a593Smuzhiyun    if mask is None:
70*4882a593Smuzhiyun        mask = gdb.parse_and_eval(mask_name + ".bits")
71*4882a593Smuzhiyun        if hasattr(gdb, 'events'):
72*4882a593Smuzhiyun            cpu_mask[mask_name] = mask
73*4882a593Smuzhiyun            gdb.events.stop.connect(cpu_mask_invalidate)
74*4882a593Smuzhiyun            if hasattr(gdb.events, 'new_objfile'):
75*4882a593Smuzhiyun                gdb.events.new_objfile.connect(cpu_mask_invalidate)
76*4882a593Smuzhiyun    bits_per_entry = mask[0].type.sizeof * 8
77*4882a593Smuzhiyun    num_entries = mask.type.sizeof * 8 / bits_per_entry
78*4882a593Smuzhiyun    entry = -1
79*4882a593Smuzhiyun    bits = 0
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun    while True:
82*4882a593Smuzhiyun        while bits == 0:
83*4882a593Smuzhiyun            entry += 1
84*4882a593Smuzhiyun            if entry == num_entries:
85*4882a593Smuzhiyun                return
86*4882a593Smuzhiyun            bits = mask[entry]
87*4882a593Smuzhiyun            if bits != 0:
88*4882a593Smuzhiyun                bit = 0
89*4882a593Smuzhiyun                break
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun        while bits & 1 == 0:
92*4882a593Smuzhiyun            bits >>= 1
93*4882a593Smuzhiyun            bit += 1
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun        cpu = entry * bits_per_entry + bit
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun        bits >>= 1
98*4882a593Smuzhiyun        bit += 1
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun        yield int(cpu)
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun
103*4882a593Smuzhiyundef each_online_cpu():
104*4882a593Smuzhiyun    for cpu in cpu_list("__cpu_online_mask"):
105*4882a593Smuzhiyun        yield cpu
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun
108*4882a593Smuzhiyundef each_present_cpu():
109*4882a593Smuzhiyun    for cpu in cpu_list("__cpu_present_mask"):
110*4882a593Smuzhiyun        yield cpu
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun
113*4882a593Smuzhiyundef each_possible_cpu():
114*4882a593Smuzhiyun    for cpu in cpu_list("__cpu_possible_mask"):
115*4882a593Smuzhiyun        yield cpu
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun
118*4882a593Smuzhiyundef each_active_cpu():
119*4882a593Smuzhiyun    for cpu in cpu_list("__cpu_active_mask"):
120*4882a593Smuzhiyun        yield cpu
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun
123*4882a593Smuzhiyunclass LxCpus(gdb.Command):
124*4882a593Smuzhiyun    """List CPU status arrays
125*4882a593Smuzhiyun
126*4882a593SmuzhiyunDisplays the known state of each CPU based on the kernel masks
127*4882a593Smuzhiyunand can help identify the state of hotplugged CPUs"""
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun    def __init__(self):
130*4882a593Smuzhiyun        super(LxCpus, self).__init__("lx-cpus", gdb.COMMAND_DATA)
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun    def invoke(self, arg, from_tty):
133*4882a593Smuzhiyun        gdb.write("Possible CPUs : {}\n".format(list(each_possible_cpu())))
134*4882a593Smuzhiyun        gdb.write("Present CPUs  : {}\n".format(list(each_present_cpu())))
135*4882a593Smuzhiyun        gdb.write("Online CPUs   : {}\n".format(list(each_online_cpu())))
136*4882a593Smuzhiyun        gdb.write("Active CPUs   : {}\n".format(list(each_active_cpu())))
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun
139*4882a593SmuzhiyunLxCpus()
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun
142*4882a593Smuzhiyunclass PerCpu(gdb.Function):
143*4882a593Smuzhiyun    """Return per-cpu variable.
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun$lx_per_cpu("VAR"[, CPU]): Return the per-cpu variable called VAR for the
146*4882a593Smuzhiyungiven CPU number. If CPU is omitted, the CPU of the current context is used.
147*4882a593SmuzhiyunNote that VAR has to be quoted as string."""
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun    def __init__(self):
150*4882a593Smuzhiyun        super(PerCpu, self).__init__("lx_per_cpu")
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun    def invoke(self, var_name, cpu=-1):
153*4882a593Smuzhiyun        var_ptr = gdb.parse_and_eval("&" + var_name.string())
154*4882a593Smuzhiyun        return per_cpu(var_ptr, cpu)
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun
157*4882a593SmuzhiyunPerCpu()
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun
160*4882a593Smuzhiyunclass LxCurrentFunc(gdb.Function):
161*4882a593Smuzhiyun    """Return current task.
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun$lx_current([CPU]): Return the per-cpu task variable for the given CPU
164*4882a593Smuzhiyunnumber. If CPU is omitted, the CPU of the current context is used."""
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun    def __init__(self):
167*4882a593Smuzhiyun        super(LxCurrentFunc, self).__init__("lx_current")
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun    def invoke(self, cpu=-1):
170*4882a593Smuzhiyun        var_ptr = gdb.parse_and_eval("&current_task")
171*4882a593Smuzhiyun        return per_cpu(var_ptr, cpu).dereference()
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun
174*4882a593SmuzhiyunLxCurrentFunc()
175