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']['next']['node']
47 curr
= curr
.address
.cast(rbtree
.rb_node_type
.get_type().pointer())
50 yield print_timer(curr
, idx
)
51 curr
= rbtree
.rb_next(curr
)
56 text
= " .base: {}\n".format(base
.address
)
57 text
+= " .index: {}\n".format(base
['index'])
59 text
+= " .resolution: {} nsecs\n".format(constants
.LX_hrtimer_resolution
)
61 text
+= " .get_time: {}\n".format(base
['get_time'])
62 if constants
.LX_CONFIG_HIGH_RES_TIMERS
:
63 text
+= " .offset: {} nsecs\n".format(base
['offset'])
64 text
+= "active timers:\n"
65 text
+= "".join([x
for x
in print_active_timers(base
)])
69 def print_cpu(hrtimer_bases
, cpu
, max_clock_bases
):
70 cpu_base
= cpus
.per_cpu(hrtimer_bases
, cpu
)
71 jiffies
= gdb
.parse_and_eval("jiffies_64")
72 tick_sched_ptr
= gdb
.parse_and_eval("&tick_cpu_sched")
73 ts
= cpus
.per_cpu(tick_sched_ptr
, cpu
)
75 text
= "cpu: {}\n".format(cpu
)
76 for i
in xrange(max_clock_bases
):
77 text
+= " clock {}:\n".format(i
)
78 text
+= print_base(cpu_base
['clock_base'][i
])
80 if constants
.LX_CONFIG_HIGH_RES_TIMERS
:
81 fmts
= [(" .{} : {} nsecs", 'expires_next'),
82 (" .{} : {}", 'hres_active'),
83 (" .{} : {}", 'nr_events'),
84 (" .{} : {}", 'nr_retries'),
85 (" .{} : {}", 'nr_hangs'),
86 (" .{} : {}", 'max_hang_time')]
87 text
+= "\n".join([s
.format(f
, cpu_base
[f
]) for s
, f
in fmts
])
90 if constants
.LX_CONFIG_TICK_ONESHOT
:
91 fmts
= [(" .{} : {}", 'nohz_mode'),
92 (" .{} : {} nsecs", 'last_tick'),
93 (" .{} : {}", 'tick_stopped'),
94 (" .{} : {}", 'idle_jiffies'),
95 (" .{} : {}", 'idle_calls'),
96 (" .{} : {}", 'idle_sleeps'),
97 (" .{} : {} nsecs", 'idle_entrytime'),
98 (" .{} : {} nsecs", 'idle_waketime'),
99 (" .{} : {} nsecs", 'idle_exittime'),
100 (" .{} : {} nsecs", 'idle_sleeptime'),
101 (" .{}: {} nsecs", 'iowait_sleeptime'),
102 (" .{} : {}", 'last_jiffies'),
103 (" .{} : {}", 'next_timer'),
104 (" .{} : {} nsecs", 'idle_expires')]
105 text
+= "\n".join([s
.format(f
, ts
[f
]) for s
, f
in fmts
])
106 text
+= "\njiffies: {}\n".format(jiffies
)
113 def print_tickdevice(td
, cpu
):
115 text
= "Tick Device: mode: {}\n".format(td
['mode'])
117 text
+= "Broadcast device\n"
119 text
+= "Per CPU device: {}\n".format(cpu
)
121 text
+= "Clock Event Device: "
126 text
+= "{}\n".format(dev
['name'])
127 text
+= " max_delta_ns: {}\n".format(dev
['max_delta_ns'])
128 text
+= " min_delta_ns: {}\n".format(dev
['min_delta_ns'])
129 text
+= " mult: {}\n".format(dev
['mult'])
130 text
+= " shift: {}\n".format(dev
['shift'])
131 text
+= " mode: {}\n".format(dev
['state_use_accessors'])
132 text
+= " next_event: {} nsecs\n".format(dev
['next_event'])
134 text
+= " set_next_event: {}\n".format(dev
['set_next_event'])
136 members
= [('set_state_shutdown', " shutdown: {}\n"),
137 ('set_state_periodic', " periodic: {}\n"),
138 ('set_state_oneshot', " oneshot: {}\n"),
139 ('set_state_oneshot_stopped', " oneshot stopped: {}\n"),
140 ('tick_resume', " resume: {}\n")]
141 for member
, fmt
in members
:
143 text
+= fmt
.format(dev
[member
])
145 text
+= " event_handler: {}\n".format(dev
['event_handler'])
146 text
+= " retries: {}\n".format(dev
['retries'])
151 def pr_cpumask(mask
):
153 if constants
.LX_NR_CPUS
> 1:
154 nr_cpu_ids
= gdb
.parse_and_eval("nr_cpu_ids")
156 inf
= gdb
.inferiors()[0]
158 num_bytes
= (nr_cpu_ids
+ 7) / 8
159 buf
= utils
.read_memoryview(inf
, bits
, num_bytes
).tobytes()
160 buf
= binascii
.b2a_hex(buf
)
168 chunks
.append(buf
[start
:end
])
169 if i
!= 0 and i
% 4 == 0:
172 extra
= nr_cpu_ids
% 8
174 chunks
[0] = chunks
[0][0] # Cut off the first 0
176 return "".join(chunks
)
179 class LxTimerList(gdb
.Command
):
180 """Print /proc/timer_list"""
183 super(LxTimerList
, self
).__init
__("lx-timerlist", gdb
.COMMAND_DATA
)
185 def invoke(self
, arg
, from_tty
):
186 hrtimer_bases
= gdb
.parse_and_eval("&hrtimer_bases")
187 max_clock_bases
= gdb
.parse_and_eval("HRTIMER_MAX_CLOCK_BASES")
189 text
= "Timer List Version: gdb scripts\n"
190 text
+= "HRTIMER_MAX_CLOCK_BASES: {}\n".format(max_clock_bases
)
191 text
+= "now at {} nsecs\n".format(ktime_get())
193 for cpu
in cpus
.each_online_cpu():
194 text
+= print_cpu(hrtimer_bases
, cpu
, max_clock_bases
)
196 if constants
.LX_CONFIG_GENERIC_CLOCKEVENTS
:
197 if constants
.LX_CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
:
198 bc_dev
= gdb
.parse_and_eval("&tick_broadcast_device")
199 text
+= print_tickdevice(bc_dev
, -1)
201 mask
= gdb
.parse_and_eval("tick_broadcast_mask")
202 mask
= pr_cpumask(mask
)
203 text
+= "tick_broadcast_mask: {}\n".format(mask
)
204 if constants
.LX_CONFIG_TICK_ONESHOT
:
205 mask
= gdb
.parse_and_eval("tick_broadcast_oneshot_mask")
206 mask
= pr_cpumask(mask
)
207 text
+= "tick_broadcast_oneshot_mask: {}\n".format(mask
)
210 tick_cpu_devices
= gdb
.parse_and_eval("&tick_cpu_device")
211 for cpu
in cpus
.each_online_cpu():
212 tick_dev
= cpus
.per_cpu(tick_cpu_devices
, cpu
)
213 text
+= print_tickdevice(tick_dev
, cpu
)