~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/scripts/gdb/linux/cpus.py

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /scripts/gdb/linux/cpus.py (Version linux-6.12-rc7) and /scripts/gdb/linux/cpus.py (Version linux-6.9.12)


  1 #                                                   1 #
  2 # gdb helper commands and functions for Linux       2 # gdb helper commands and functions for Linux kernel debugging
  3 #                                                   3 #
  4 #  per-cpu tools                                    4 #  per-cpu tools
  5 #                                                   5 #
  6 # Copyright (c) Siemens AG, 2011-2013               6 # Copyright (c) Siemens AG, 2011-2013
  7 #                                                   7 #
  8 # Authors:                                          8 # Authors:
  9 #  Jan Kiszka <jan.kiszka@siemens.com>               9 #  Jan Kiszka <jan.kiszka@siemens.com>
 10 #                                                  10 #
 11 # This work is licensed under the terms of the     11 # This work is licensed under the terms of the GNU GPL version 2.
 12 #                                                  12 #
 13                                                    13 
 14 import gdb                                         14 import gdb
 15                                                    15 
 16 from linux import tasks, utils                     16 from linux import tasks, utils
 17                                                    17 
 18                                                    18 
 19 task_type = utils.CachedType("struct task_stru     19 task_type = utils.CachedType("struct task_struct")
 20                                                    20 
 21                                                    21 
 22 MAX_CPUS = 4096                                    22 MAX_CPUS = 4096
 23                                                    23 
 24                                                    24 
 25 def get_current_cpu():                             25 def get_current_cpu():
 26     if utils.get_gdbserver_type() == utils.GDB     26     if utils.get_gdbserver_type() == utils.GDBSERVER_QEMU:
 27         return gdb.selected_thread().num - 1       27         return gdb.selected_thread().num - 1
 28     elif utils.get_gdbserver_type() == utils.G     28     elif utils.get_gdbserver_type() == utils.GDBSERVER_KGDB:
 29         return gdb.parse_and_eval("kgdb_active !!  29         tid = gdb.selected_thread().ptid[2]
                                                   >>  30         if tid > (0x100000000 - MAX_CPUS - 2):
                                                   >>  31             return 0x100000000 - tid - 2
                                                   >>  32         else:
                                                   >>  33             return tasks.get_thread_info(tasks.get_task_by_pid(tid))['cpu']
 30     else:                                          34     else:
 31         raise gdb.GdbError("Sorry, obtaining t     35         raise gdb.GdbError("Sorry, obtaining the current CPU is not yet "
 32                            "supported with thi     36                            "supported with this gdb server.")
 33                                                    37 
 34                                                    38 
 35 def per_cpu(var_ptr, cpu):                         39 def per_cpu(var_ptr, cpu):
 36     if cpu == -1:                                  40     if cpu == -1:
 37         cpu = get_current_cpu()                    41         cpu = get_current_cpu()
 38     if utils.is_target_arch("sparc:v9"):           42     if utils.is_target_arch("sparc:v9"):
 39         offset = gdb.parse_and_eval(               43         offset = gdb.parse_and_eval(
 40             "trap_block[{0}].__per_cpu_base".f     44             "trap_block[{0}].__per_cpu_base".format(str(cpu)))
 41     else:                                          45     else:
 42         try:                                       46         try:
 43             offset = gdb.parse_and_eval(           47             offset = gdb.parse_and_eval(
 44                 "__per_cpu_offset[{0}]".format     48                 "__per_cpu_offset[{0}]".format(str(cpu)))
 45         except gdb.error:                          49         except gdb.error:
 46             # !CONFIG_SMP case                     50             # !CONFIG_SMP case
 47             offset = 0                             51             offset = 0
 48     pointer = var_ptr.cast(utils.get_long_type     52     pointer = var_ptr.cast(utils.get_long_type()) + offset
 49     return pointer.cast(var_ptr.type).derefere     53     return pointer.cast(var_ptr.type).dereference()
 50                                                    54 
 51                                                    55 
 52 cpu_mask = {}                                      56 cpu_mask = {}
 53                                                    57 
 54                                                    58 
 55 def cpu_mask_invalidate(event):                    59 def cpu_mask_invalidate(event):
 56     global cpu_mask                                60     global cpu_mask
 57     cpu_mask = {}                                  61     cpu_mask = {}
 58     gdb.events.stop.disconnect(cpu_mask_invali     62     gdb.events.stop.disconnect(cpu_mask_invalidate)
 59     if hasattr(gdb.events, 'new_objfile'):         63     if hasattr(gdb.events, 'new_objfile'):
 60         gdb.events.new_objfile.disconnect(cpu_     64         gdb.events.new_objfile.disconnect(cpu_mask_invalidate)
 61                                                    65 
 62                                                    66 
 63 def cpu_list(mask_name):                           67 def cpu_list(mask_name):
 64     global cpu_mask                                68     global cpu_mask
 65     mask = None                                    69     mask = None
 66     if mask_name in cpu_mask:                      70     if mask_name in cpu_mask:
 67         mask = cpu_mask[mask_name]                 71         mask = cpu_mask[mask_name]
 68     if mask is None:                               72     if mask is None:
 69         mask = gdb.parse_and_eval(mask_name +      73         mask = gdb.parse_and_eval(mask_name + ".bits")
 70         if hasattr(gdb, 'events'):                 74         if hasattr(gdb, 'events'):
 71             cpu_mask[mask_name] = mask             75             cpu_mask[mask_name] = mask
 72             gdb.events.stop.connect(cpu_mask_i     76             gdb.events.stop.connect(cpu_mask_invalidate)
 73             if hasattr(gdb.events, 'new_objfil     77             if hasattr(gdb.events, 'new_objfile'):
 74                 gdb.events.new_objfile.connect     78                 gdb.events.new_objfile.connect(cpu_mask_invalidate)
 75     bits_per_entry = mask[0].type.sizeof * 8       79     bits_per_entry = mask[0].type.sizeof * 8
 76     num_entries = mask.type.sizeof * 8 / bits_     80     num_entries = mask.type.sizeof * 8 / bits_per_entry
 77     entry = -1                                     81     entry = -1
 78     bits = 0                                       82     bits = 0
 79                                                    83 
 80     while True:                                    84     while True:
 81         while bits == 0:                           85         while bits == 0:
 82             entry += 1                             86             entry += 1
 83             if entry == num_entries:               87             if entry == num_entries:
 84                 return                             88                 return
 85             bits = mask[entry]                     89             bits = mask[entry]
 86             if bits != 0:                          90             if bits != 0:
 87                 bit = 0                            91                 bit = 0
 88                 break                              92                 break
 89                                                    93 
 90         while bits & 1 == 0:                       94         while bits & 1 == 0:
 91             bits >>= 1                             95             bits >>= 1
 92             bit += 1                               96             bit += 1
 93                                                    97 
 94         cpu = entry * bits_per_entry + bit         98         cpu = entry * bits_per_entry + bit
 95                                                    99 
 96         bits >>= 1                                100         bits >>= 1
 97         bit += 1                                  101         bit += 1
 98                                                   102 
 99         yield int(cpu)                            103         yield int(cpu)
100                                                   104 
101                                                   105 
102 def each_online_cpu():                            106 def each_online_cpu():
103     for cpu in cpu_list("__cpu_online_mask"):     107     for cpu in cpu_list("__cpu_online_mask"):
104         yield cpu                                 108         yield cpu
105                                                   109 
106                                                   110 
107 def each_present_cpu():                           111 def each_present_cpu():
108     for cpu in cpu_list("__cpu_present_mask"):    112     for cpu in cpu_list("__cpu_present_mask"):
109         yield cpu                                 113         yield cpu
110                                                   114 
111                                                   115 
112 def each_possible_cpu():                          116 def each_possible_cpu():
113     for cpu in cpu_list("__cpu_possible_mask")    117     for cpu in cpu_list("__cpu_possible_mask"):
114         yield cpu                                 118         yield cpu
115                                                   119 
116                                                   120 
117 def each_active_cpu():                            121 def each_active_cpu():
118     for cpu in cpu_list("__cpu_active_mask"):     122     for cpu in cpu_list("__cpu_active_mask"):
119         yield cpu                                 123         yield cpu
120                                                   124 
121                                                   125 
122 class LxCpus(gdb.Command):                        126 class LxCpus(gdb.Command):
123     """List CPU status arrays                     127     """List CPU status arrays
124                                                   128 
125 Displays the known state of each CPU based on     129 Displays the known state of each CPU based on the kernel masks
126 and can help identify the state of hotplugged     130 and can help identify the state of hotplugged CPUs"""
127                                                   131 
128     def __init__(self):                           132     def __init__(self):
129         super(LxCpus, self).__init__("lx-cpus"    133         super(LxCpus, self).__init__("lx-cpus", gdb.COMMAND_DATA)
130                                                   134 
131     def invoke(self, arg, from_tty):              135     def invoke(self, arg, from_tty):
132         gdb.write("Possible CPUs : {}\n".forma    136         gdb.write("Possible CPUs : {}\n".format(list(each_possible_cpu())))
133         gdb.write("Present CPUs  : {}\n".forma    137         gdb.write("Present CPUs  : {}\n".format(list(each_present_cpu())))
134         gdb.write("Online CPUs   : {}\n".forma    138         gdb.write("Online CPUs   : {}\n".format(list(each_online_cpu())))
135         gdb.write("Active CPUs   : {}\n".forma    139         gdb.write("Active CPUs   : {}\n".format(list(each_active_cpu())))
136                                                   140 
137                                                   141 
138 LxCpus()                                          142 LxCpus()
139                                                   143 
140                                                   144 
141 class PerCpu(gdb.Function):                       145 class PerCpu(gdb.Function):
142     """Return per-cpu variable.                   146     """Return per-cpu variable.
143                                                   147 
144 $lx_per_cpu("VAR"[, CPU]): Return the per-cpu     148 $lx_per_cpu("VAR"[, CPU]): Return the per-cpu variable called VAR for the
145 given CPU number. If CPU is omitted, the CPU o    149 given CPU number. If CPU is omitted, the CPU of the current context is used.
146 Note that VAR has to be quoted as string."""      150 Note that VAR has to be quoted as string."""
147                                                   151 
148     def __init__(self):                           152     def __init__(self):
149         super(PerCpu, self).__init__("lx_per_c    153         super(PerCpu, self).__init__("lx_per_cpu")
150                                                   154 
151     def invoke(self, var, cpu=-1):             !! 155     def invoke(self, var_name, cpu=-1):
152         return per_cpu(var.address, cpu)       !! 156         var_ptr = gdb.parse_and_eval("&" + var_name.string())
                                                   >> 157         return per_cpu(var_ptr, cpu)
153                                                   158 
154                                                   159 
155 PerCpu()                                          160 PerCpu()
156                                                   161 
157 def get_current_task(cpu):                        162 def get_current_task(cpu):
158     task_ptr_type = task_type.get_type().point    163     task_ptr_type = task_type.get_type().pointer()
159                                                   164 
160     if utils.is_target_arch("x86"):               165     if utils.is_target_arch("x86"):
161         if gdb.lookup_global_symbol("cpu_tasks    166         if gdb.lookup_global_symbol("cpu_tasks"):
162             # This is a UML kernel, which stor    167             # This is a UML kernel, which stores the current task
163             # differently than other x86 sub a    168             # differently than other x86 sub architectures
164             var_ptr = gdb.parse_and_eval("(str    169             var_ptr = gdb.parse_and_eval("(struct task_struct *)cpu_tasks[0].task")
165             return var_ptr.dereference()          170             return var_ptr.dereference()
166         else:                                     171         else:
167             var_ptr = gdb.parse_and_eval("&pcp    172             var_ptr = gdb.parse_and_eval("&pcpu_hot.current_task")
168             return per_cpu(var_ptr, cpu).deref    173             return per_cpu(var_ptr, cpu).dereference()
169     elif utils.is_target_arch("aarch64"):         174     elif utils.is_target_arch("aarch64"):
170         current_task_addr = gdb.parse_and_eval    175         current_task_addr = gdb.parse_and_eval("$SP_EL0")
171         if (current_task_addr >> 63) != 0:        176         if (current_task_addr >> 63) != 0:
172             current_task = current_task_addr.c    177             current_task = current_task_addr.cast(task_ptr_type)
173             return current_task.dereference()     178             return current_task.dereference()
174         else:                                     179         else:
175             raise gdb.GdbError("Sorry, obtaini    180             raise gdb.GdbError("Sorry, obtaining the current task is not allowed "
176                                "while running     181                                "while running in userspace(EL0)")
177     elif utils.is_target_arch("riscv"):           182     elif utils.is_target_arch("riscv"):
178         current_tp = gdb.parse_and_eval("$tp")    183         current_tp = gdb.parse_and_eval("$tp")
179         scratch_reg = gdb.parse_and_eval("$ssc    184         scratch_reg = gdb.parse_and_eval("$sscratch")
180                                                   185 
181         # by default tp points to current task    186         # by default tp points to current task
182         current_task = current_tp.cast(task_pt    187         current_task = current_tp.cast(task_ptr_type)
183                                                   188 
184         # scratch register is set 0 in trap ha    189         # scratch register is set 0 in trap handler after entering kernel.
185         # When hart is in user mode, scratch r    190         # When hart is in user mode, scratch register is pointing to task_struct.
186         # and tp is used by user mode. So when    191         # and tp is used by user mode. So when scratch register holds larger value
187         # (negative address as ulong is larger    192         # (negative address as ulong is larger value) than tp, then use scratch register.
188         if (scratch_reg.cast(utils.get_ulong_t    193         if (scratch_reg.cast(utils.get_ulong_type()) > current_tp.cast(utils.get_ulong_type())):
189             current_task = scratch_reg.cast(ta    194             current_task = scratch_reg.cast(task_ptr_type)
190                                                   195 
191         return current_task.dereference()         196         return current_task.dereference()
192     else:                                         197     else:
193         raise gdb.GdbError("Sorry, obtaining t    198         raise gdb.GdbError("Sorry, obtaining the current task is not yet "
194                            "supported with thi    199                            "supported with this arch")
195                                                   200 
196 class LxCurrentFunc(gdb.Function):                201 class LxCurrentFunc(gdb.Function):
197     """Return current task.                       202     """Return current task.
198                                                   203 
199 $lx_current([CPU]): Return the per-cpu task va    204 $lx_current([CPU]): Return the per-cpu task variable for the given CPU
200 number. If CPU is omitted, the CPU of the curr    205 number. If CPU is omitted, the CPU of the current context is used."""
201                                                   206 
202     def __init__(self):                           207     def __init__(self):
203         super(LxCurrentFunc, self).__init__("l    208         super(LxCurrentFunc, self).__init__("lx_current")
204                                                   209 
205     def invoke(self, cpu=-1):                     210     def invoke(self, cpu=-1):
206         return get_current_task(cpu)              211         return get_current_task(cpu)
207                                                   212 
208                                                   213 
209 LxCurrentFunc()                                   214 LxCurrentFunc()
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php