1 # SPDX-License-Identifier: GPL-2.0
3 # Copyright 2019 Google LLC.
8 from linux import constants
10 from linux import rbtree
11 from linux import utils
13 timerqueue_node_type = utils.CachedType("struct timerqueue_node").get_type()
14 hrtimer_type = utils.CachedType("struct hrtimer").get_type()
18 """Returns the current time, but not very accurately
20 We can't read the hardware timer itself to add any nanoseconds
21 that need to be added since we last stored the time in the
22 timekeeper. But this is probably good enough for debug purposes."""
23 tk_core = gdb.parse_and_eval("&tk_core")
25 return tk_core['timekeeper']['tkr_mono']['base']
28 def print_timer(rb_node, idx):
29 timerqueue = utils.container_of(rb_node, timerqueue_node_type.pointer(),
31 timer = utils.container_of(timerqueue, hrtimer_type.pointer(), "node")
33 function = str(timer['function']).split(" ")[1].strip("<>")
34 softexpires = timer['_softexpires']
35 expires = timer['node']['expires']
38 text = " #{}: <{}>, {}, ".format(idx, timer, function)
39 text += "S:{:02x}\n".format(int(timer['state']))
40 text += " # expires at {}-{} nsecs [in {} to {} nsecs]\n".format(
41 softexpires, expires, softexpires - now, expires - now)
45 def print_active_timers(base):
46 curr = base['active']['rb_root']['rb_leftmost']
49 yield print_timer(curr, idx)
50 curr = rbtree.rb_next(curr)
55 text = " .base: {}\n".format(base.address)
56 text += " .index: {}\n".format(base['index'])
58 text += " .resolution: {} nsecs\n".format(constants.LX_hrtimer_resolution)
60 text += " .get_time: {}\n".format(base['get_time'])
61 if constants.LX_CONFIG_HIGH_RES_TIMERS:
62 text += " .offset: {} nsecs\n".format(base['offset'])
63 text += "active timers:\n"
64 text += "".join([x for x in print_active_timers(base)])
68 def print_cpu(hrtimer_bases, cpu, max_clock_bases):
69 cpu_base = cpus.per_cpu(hrtimer_bases, cpu)
70 jiffies = gdb.parse_and_eval("jiffies_64")
71 tick_sched_ptr = gdb.parse_and_eval("&tick_cpu_sched")
72 ts = cpus.per_cpu(tick_sched_ptr, cpu)
74 text = "cpu: {}\n".format(cpu)
75 for i in xrange(max_clock_bases):
76 text += " clock {}:\n".format(i)
77 text += print_base(cpu_base['clock_base'][i])
79 if constants.LX_CONFIG_HIGH_RES_TIMERS:
80 fmts = [(" .{} : {} nsecs", 'expires_next'),
81 (" .{} : {}", 'hres_active'),
82 (" .{} : {}", 'nr_events'),
83 (" .{} : {}", 'nr_retries'),
84 (" .{} : {}", 'nr_hangs'),
85 (" .{} : {}", 'max_hang_time')]
86 text += "\n".join([s.format(f, cpu_base[f]) for s, f in fmts])
89 if constants.LX_CONFIG_TICK_ONESHOT:
90 fmts = [(" .{} : {}", 'nohz_mode'),
91 (" .{} : {} nsecs", 'last_tick'),
92 (" .{} : {}", 'tick_stopped'),
93 (" .{} : {}", 'idle_jiffies'),
94 (" .{} : {}", 'idle_calls'),
95 (" .{} : {}", 'idle_sleeps'),
96 (" .{} : {} nsecs", 'idle_entrytime'),
97 (" .{} : {} nsecs", 'idle_waketime'),
98 (" .{} : {} nsecs", 'idle_exittime'),
99 (" .{} : {} nsecs", 'idle_sleeptime'),
100 (" .{}: {} nsecs", 'iowait_sleeptime'),
101 (" .{} : {}", 'last_jiffies'),
102 (" .{} : {}", 'next_timer'),
103 (" .{} : {} nsecs", 'idle_expires')]
104 text += "\n".join([s.format(f, ts[f]) for s, f in fmts])
105 text += "\njiffies: {}\n".format(jiffies)
112 def print_tickdevice(td, cpu):
114 text = "Tick Device: mode: {}\n".format(td['mode'])
116 text += "Broadcast device\n"
118 text += "Per CPU device: {}\n".format(cpu)
120 text += "Clock Event Device: "
125 text += "{}\n".format(dev['name'])
126 text += " max_delta_ns: {}\n".format(dev['max_delta_ns'])
127 text += " min_delta_ns: {}\n".format(dev['min_delta_ns'])
128 text += " mult: {}\n".format(dev['mult'])
129 text += " shift: {}\n".format(dev['shift'])
130 text += " mode: {}\n".format(dev['state_use_accessors'])
131 text += " next_event: {} nsecs\n".format(dev['next_event'])
133 text += " set_next_event: {}\n".format(dev['set_next_event'])
135 members = [('set_state_shutdown', " shutdown: {}\n"),
136 ('set_state_periodic', " periodic: {}\n"),
137 ('set_state_oneshot', " oneshot: {}\n"),
138 ('set_state_oneshot_stopped', " oneshot stopped: {}\n"),
139 ('tick_resume', " resume: {}\n")]
140 for member, fmt in members:
142 text += fmt.format(dev[member])
144 text += " event_handler: {}\n".format(dev['event_handler'])
145 text += " retries: {}\n".format(dev['retries'])
150 def pr_cpumask(mask):
152 if constants.LX_NR_CPUS > 1:
153 nr_cpu_ids = gdb.parse_and_eval("nr_cpu_ids")
155 inf = gdb.inferiors()[0]
157 num_bytes = (nr_cpu_ids + 7) / 8
158 buf = utils.read_memoryview(inf, bits, num_bytes).tobytes()
159 buf = binascii.b2a_hex(buf)
167 chunks.append(buf[start:end])
168 if i != 0 and i % 4 == 0:
171 extra = nr_cpu_ids % 8
173 chunks[0] = chunks[0][0] # Cut off the first 0
175 return "".join(chunks)
178 class LxTimerList(gdb.Command):
179 """Print /proc/timer_list"""
182 super(LxTimerList, self).__init__("lx-timerlist", gdb.COMMAND_DATA)
184 def invoke(self, arg, from_tty):
185 hrtimer_bases = gdb.parse_and_eval("&hrtimer_bases")
186 max_clock_bases = gdb.parse_and_eval("HRTIMER_MAX_CLOCK_BASES")
188 text = "Timer List Version: gdb scripts\n"
189 text += "HRTIMER_MAX_CLOCK_BASES: {}\n".format(max_clock_bases)
190 text += "now at {} nsecs\n".format(ktime_get())
192 for cpu in cpus.each_online_cpu():
193 text += print_cpu(hrtimer_bases, cpu, max_clock_bases)
195 if constants.LX_CONFIG_GENERIC_CLOCKEVENTS:
196 if constants.LX_CONFIG_GENERIC_CLOCKEVENTS_BROADCAST:
197 bc_dev = gdb.parse_and_eval("&tick_broadcast_device")
198 text += print_tickdevice(bc_dev, -1)
200 mask = gdb.parse_and_eval("tick_broadcast_mask")
201 mask = pr_cpumask(mask)
202 text += "tick_broadcast_mask: {}\n".format(mask)
203 if constants.LX_CONFIG_TICK_ONESHOT:
204 mask = gdb.parse_and_eval("tick_broadcast_oneshot_mask")
205 mask = pr_cpumask(mask)
206 text += "tick_broadcast_oneshot_mask: {}\n".format(mask)
209 tick_cpu_devices = gdb.parse_and_eval("&tick_cpu_device")
210 for cpu in cpus.each_online_cpu():
211 tick_dev = cpus.per_cpu(tick_cpu_devices, cpu)
212 text += print_tickdevice(tick_dev, cpu)