1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * List pending timers 4 * 5 * Copyright(C) 2006, Red Hat, Inc., Ingo Molnar 6 */ 7 8 #include <linux/proc_fs.h> 9 #include <linux/module.h> 10 #include <linux/spinlock.h> 11 #include <linux/sched.h> 12 #include <linux/seq_file.h> 13 #include <linux/kallsyms.h> 14 #include <linux/nmi.h> 15 16 #include <linux/uaccess.h> 17 18 #include "tick-internal.h" 19 20 struct timer_list_iter { 21 int cpu; 22 bool second_pass; 23 ktime_t now; 24 }; 25 26 /* 27 * This allows printing both to /proc/timer_list and 28 * to the console (on SysRq-Q): 29 */ 30 __printf(2, 3) 31 static void SEQ_printf(struct seq_file *m, const char *fmt, ...) 32 { 33 va_list args; 34 35 va_start(args, fmt); 36 37 if (m) 38 seq_vprintf(m, fmt, args); 39 else 40 vprintk(fmt, args); 41 42 va_end(args); 43 } 44 45 static void 46 print_timer(struct seq_file *m, struct hrtimer *taddr, struct hrtimer *timer, 47 int idx, ktime_t now) 48 { 49 SEQ_printf(m, " #%d: <%p>, %ps", idx, taddr, ACCESS_PRIVATE(timer, function)); 50 SEQ_printf(m, ", S:%02x", timer->is_queued); 51 SEQ_printf(m, "\n"); 52 SEQ_printf(m, " # expires at %lld-%lld nsecs [in %lld to %lld nsecs]\n", 53 (long long)hrtimer_get_softexpires(timer), 54 (long long)hrtimer_get_expires(timer), 55 (long long)ktime_sub(hrtimer_get_softexpires(timer), now), 56 (long long)ktime_sub(hrtimer_get_expires(timer), now)); 57 } 58 59 static void print_active_timers(struct seq_file *m, struct hrtimer_clock_base *base, ktime_t now) 60 { 61 struct timerqueue_linked_node *curr; 62 struct hrtimer *timer, tmp; 63 unsigned long next = 0, i; 64 unsigned long flags; 65 66 next_one: 67 i = 0; 68 69 touch_nmi_watchdog(); 70 71 raw_spin_lock_irqsave(&base->cpu_base->lock, flags); 72 73 curr = timerqueue_linked_first(&base->active); 74 /* 75 * Crude but we have to do this O(N*N) thing, because 76 * we have to unlock the base when printing: 77 */ 78 while (curr && i < next) { 79 curr = timerqueue_linked_next(curr); 80 i++; 81 } 82 83 if (curr) { 84 85 timer = container_of(curr, struct hrtimer, node); 86 tmp = *timer; 87 raw_spin_unlock_irqrestore(&base->cpu_base->lock, flags); 88 89 print_timer(m, timer, &tmp, i, now); 90 next++; 91 goto next_one; 92 } 93 raw_spin_unlock_irqrestore(&base->cpu_base->lock, flags); 94 } 95 96 static void 97 print_base(struct seq_file *m, struct hrtimer_clock_base *base, ktime_t now) 98 { 99 SEQ_printf(m, " .base: %p\n", base); 100 SEQ_printf(m, " .index: %d\n", base->index); 101 102 SEQ_printf(m, " .resolution: %u nsecs\n", hrtimer_resolution); 103 #ifdef CONFIG_HIGH_RES_TIMERS 104 SEQ_printf(m, " .offset: %lld nsecs\n", 105 (long long) base->offset); 106 #endif 107 SEQ_printf(m, "active timers:\n"); 108 print_active_timers(m, base, ktime_add(now, base->offset)); 109 } 110 111 static void print_cpu(struct seq_file *m, int cpu, ktime_t now) 112 { 113 struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu); 114 int i; 115 116 SEQ_printf(m, "cpu: %d\n", cpu); 117 for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) { 118 SEQ_printf(m, " clock %d:\n", i); 119 print_base(m, cpu_base->clock_base + i, now); 120 } 121 122 #define DIAG_READ(x) data_race(READ_ONCE(x)) 123 124 #define P(x) \ 125 SEQ_printf(m, " .%-15s: %llu\n", #x, \ 126 (unsigned long long)DIAG_READ(cpu_base->x)) 127 #define P_ktime(x) \ 128 SEQ_printf(m, " .%-15s: %lld nsecs\n", #x, (long long)DIAG_READ(cpu_base->x)) 129 130 #ifdef CONFIG_HIGH_RES_TIMERS 131 P_ktime(expires_next); 132 P(hres_active); 133 P(nr_events); 134 P(nr_retries); 135 P(nr_hangs); 136 P(max_hang_time); 137 #endif 138 #undef P 139 #undef P_ktime 140 141 #ifdef CONFIG_TICK_ONESHOT 142 # define P(x) \ 143 SEQ_printf(m, " .%-15s: %llu\n", #x, \ 144 (unsigned long long)DIAG_READ(ts->x)) 145 # define P_ktime(x) \ 146 SEQ_printf(m, " .%-15s: %lld nsecs\n", #x, (long long)DIAG_READ(ts->x)) 147 # define P_flag(x, f) \ 148 SEQ_printf(m, " .%-15s: %d\n", #x, !!(DIAG_READ(ts->flags) & (f))) 149 150 { 151 struct tick_sched *ts = tick_get_tick_sched(cpu); 152 P_flag(nohz, TS_FLAG_NOHZ); 153 P_flag(highres, TS_FLAG_HIGHRES); 154 P_ktime(last_tick); 155 P_flag(tick_stopped, TS_FLAG_STOPPED); 156 P(idle_calls); 157 P(idle_sleeps); 158 P_ktime(idle_entrytime); 159 P_ktime(idle_waketime); 160 P(last_jiffies); 161 P(next_timer); 162 P_ktime(idle_expires); 163 SEQ_printf(m, "jiffies: %llu\n", 164 (unsigned long long)jiffies); 165 } 166 #endif 167 168 #undef P 169 #undef P_ktime 170 #undef P_flag 171 #undef DIAG_READ 172 SEQ_printf(m, "\n"); 173 } 174 175 #ifdef CONFIG_GENERIC_CLOCKEVENTS 176 static void 177 print_tickdevice(struct seq_file *m, struct tick_device *td, int cpu) 178 { 179 struct clock_event_device *dev = td->evtdev; 180 181 touch_nmi_watchdog(); 182 183 SEQ_printf(m, "Tick Device: mode: %d\n", td->mode); 184 if (cpu < 0) 185 SEQ_printf(m, "Broadcast device\n"); 186 else 187 SEQ_printf(m, "Per CPU device: %d\n", cpu); 188 189 SEQ_printf(m, "Clock Event Device: "); 190 if (!dev) { 191 SEQ_printf(m, "<NULL>\n"); 192 return; 193 } 194 SEQ_printf(m, "%s\n", dev->name); 195 SEQ_printf(m, " max_delta_ns: %llu\n", 196 (unsigned long long) dev->max_delta_ns); 197 SEQ_printf(m, " min_delta_ns: %llu\n", 198 (unsigned long long) dev->min_delta_ns); 199 SEQ_printf(m, " mult: %u\n", dev->mult); 200 SEQ_printf(m, " shift: %u\n", dev->shift); 201 SEQ_printf(m, " mode: %d\n", clockevent_get_state(dev)); 202 SEQ_printf(m, " next_event: %lld nsecs\n", (long long)dev->next_event); 203 204 SEQ_printf(m, " set_next_event: %ps\n", dev->set_next_event); 205 206 if (dev->set_state_shutdown) 207 SEQ_printf(m, " shutdown: %ps\n", 208 dev->set_state_shutdown); 209 210 if (dev->set_state_periodic) 211 SEQ_printf(m, " periodic: %ps\n", 212 dev->set_state_periodic); 213 214 if (dev->set_state_oneshot) 215 SEQ_printf(m, " oneshot: %ps\n", 216 dev->set_state_oneshot); 217 218 if (dev->set_state_oneshot_stopped) 219 SEQ_printf(m, " oneshot stopped: %ps\n", 220 dev->set_state_oneshot_stopped); 221 222 if (dev->tick_resume) 223 SEQ_printf(m, " resume: %ps\n", 224 dev->tick_resume); 225 226 SEQ_printf(m, " event_handler: %ps\n", dev->event_handler); 227 SEQ_printf(m, "\n"); 228 SEQ_printf(m, " retries: %lu\n", dev->retries); 229 230 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST 231 if (cpu >= 0) { 232 const struct clock_event_device *wd = tick_get_wakeup_device(cpu); 233 234 SEQ_printf(m, "Wakeup Device: %s\n", wd ? wd->name : "<NULL>"); 235 } 236 #endif 237 SEQ_printf(m, "\n"); 238 } 239 240 static void timer_list_show_tickdevices_header(struct seq_file *m) 241 { 242 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST 243 print_tickdevice(m, tick_get_broadcast_device(), -1); 244 SEQ_printf(m, "tick_broadcast_mask: %*pb\n", 245 cpumask_pr_args(tick_get_broadcast_mask())); 246 #ifdef CONFIG_TICK_ONESHOT 247 SEQ_printf(m, "tick_broadcast_oneshot_mask: %*pb\n", 248 cpumask_pr_args(tick_get_broadcast_oneshot_mask())); 249 #endif 250 SEQ_printf(m, "\n"); 251 #endif 252 } 253 #endif 254 255 static inline void timer_list_header(struct seq_file *m, ktime_t now) 256 { 257 SEQ_printf(m, "Timer List Version: v0.11\n"); 258 SEQ_printf(m, "HRTIMER_MAX_CLOCK_BASES: %d\n", HRTIMER_MAX_CLOCK_BASES); 259 SEQ_printf(m, "now at %lld nsecs\n", (long long)now); 260 SEQ_printf(m, "\n"); 261 } 262 263 void sysrq_timer_list_show(void) 264 { 265 ktime_t now = ktime_get(); 266 int cpu; 267 268 timer_list_header(NULL, now); 269 270 for_each_online_cpu(cpu) 271 print_cpu(NULL, cpu, now); 272 273 #ifdef CONFIG_GENERIC_CLOCKEVENTS 274 timer_list_show_tickdevices_header(NULL); 275 for_each_online_cpu(cpu) 276 print_tickdevice(NULL, tick_get_device(cpu), cpu); 277 #endif 278 return; 279 } 280 281 #ifdef CONFIG_PROC_FS 282 static int timer_list_show(struct seq_file *m, void *v) 283 { 284 struct timer_list_iter *iter = v; 285 286 if (iter->cpu == -1 && !iter->second_pass) 287 timer_list_header(m, iter->now); 288 else if (!iter->second_pass) 289 print_cpu(m, iter->cpu, iter->now); 290 #ifdef CONFIG_GENERIC_CLOCKEVENTS 291 else if (iter->cpu == -1 && iter->second_pass) 292 timer_list_show_tickdevices_header(m); 293 else 294 print_tickdevice(m, tick_get_device(iter->cpu), iter->cpu); 295 #endif 296 return 0; 297 } 298 299 static void *move_iter(struct timer_list_iter *iter, loff_t offset) 300 { 301 for (; offset; offset--) { 302 iter->cpu = cpumask_next(iter->cpu, cpu_online_mask); 303 if (iter->cpu >= nr_cpu_ids) { 304 #ifdef CONFIG_GENERIC_CLOCKEVENTS 305 if (!iter->second_pass) { 306 iter->cpu = -1; 307 iter->second_pass = true; 308 } else 309 return NULL; 310 #else 311 return NULL; 312 #endif 313 } 314 } 315 return iter; 316 } 317 318 static void *timer_list_start(struct seq_file *file, loff_t *offset) 319 { 320 struct timer_list_iter *iter = file->private; 321 322 if (!*offset) 323 iter->now = ktime_get(); 324 iter->cpu = -1; 325 iter->second_pass = false; 326 return move_iter(iter, *offset); 327 } 328 329 static void *timer_list_next(struct seq_file *file, void *v, loff_t *offset) 330 { 331 struct timer_list_iter *iter = file->private; 332 ++*offset; 333 return move_iter(iter, 1); 334 } 335 336 static void timer_list_stop(struct seq_file *seq, void *v) 337 { 338 } 339 340 static const struct seq_operations timer_list_sops = { 341 .start = timer_list_start, 342 .next = timer_list_next, 343 .stop = timer_list_stop, 344 .show = timer_list_show, 345 }; 346 347 static int __init init_timer_list_procfs(void) 348 { 349 struct proc_dir_entry *pe; 350 351 pe = proc_create_seq_private("timer_list", 0400, NULL, &timer_list_sops, 352 sizeof(struct timer_list_iter), NULL); 353 if (!pe) 354 return -ENOMEM; 355 return 0; 356 } 357 __initcall(init_timer_list_procfs); 358 #endif 359