167ee5ad2SAlexei Starovoitov // SPDX-License-Identifier: GPL-2.0 267ee5ad2SAlexei Starovoitov /* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */ 367ee5ad2SAlexei Starovoitov #include <vmlinux.h> 467ee5ad2SAlexei Starovoitov #include <bpf/bpf_helpers.h> 567ee5ad2SAlexei Starovoitov #include <bpf/bpf_tracing.h> 667ee5ad2SAlexei Starovoitov 767ee5ad2SAlexei Starovoitov #define CLOCK_MONOTONIC 1 867ee5ad2SAlexei Starovoitov 967ee5ad2SAlexei Starovoitov char _license[] SEC("license") = "GPL"; 1067ee5ad2SAlexei Starovoitov 1167ee5ad2SAlexei Starovoitov struct elem { 1267ee5ad2SAlexei Starovoitov struct bpf_timer timer; 1367ee5ad2SAlexei Starovoitov }; 1467ee5ad2SAlexei Starovoitov 1567ee5ad2SAlexei Starovoitov struct { 1667ee5ad2SAlexei Starovoitov __uint(type, BPF_MAP_TYPE_ARRAY); 1767ee5ad2SAlexei Starovoitov __uint(max_entries, 1); 1867ee5ad2SAlexei Starovoitov __type(key, int); 1967ee5ad2SAlexei Starovoitov __type(value, struct elem); 2067ee5ad2SAlexei Starovoitov } timer_map SEC(".maps"); 2167ee5ad2SAlexei Starovoitov 2267ee5ad2SAlexei Starovoitov volatile int in_timer_start; 2367ee5ad2SAlexei Starovoitov volatile int tp_called; 2467ee5ad2SAlexei Starovoitov 2567ee5ad2SAlexei Starovoitov static int timer_cb(void *map, int *key, struct elem *value) 2667ee5ad2SAlexei Starovoitov { 2767ee5ad2SAlexei Starovoitov return 0; 2867ee5ad2SAlexei Starovoitov } 2967ee5ad2SAlexei Starovoitov 3067ee5ad2SAlexei Starovoitov SEC("tp_btf/hrtimer_cancel") 3167ee5ad2SAlexei Starovoitov int BPF_PROG(tp_hrtimer_cancel, struct hrtimer *hrtimer) 3267ee5ad2SAlexei Starovoitov { 3367ee5ad2SAlexei Starovoitov struct bpf_timer *timer; 3467ee5ad2SAlexei Starovoitov int key = 0; 3567ee5ad2SAlexei Starovoitov 3667ee5ad2SAlexei Starovoitov if (!in_timer_start) 3767ee5ad2SAlexei Starovoitov return 0; 3867ee5ad2SAlexei Starovoitov 3967ee5ad2SAlexei Starovoitov tp_called = 1; 4067ee5ad2SAlexei Starovoitov timer = bpf_map_lookup_elem(&timer_map, &key); 4167ee5ad2SAlexei Starovoitov 4267ee5ad2SAlexei Starovoitov /* 4367ee5ad2SAlexei Starovoitov * Call bpf_timer_start() from the tracepoint within hrtimer logic 44*6e65cf81SAlexei Starovoitov * on the same timer to make sure it doesn't deadlock. 4567ee5ad2SAlexei Starovoitov */ 4667ee5ad2SAlexei Starovoitov bpf_timer_start(timer, 1000000000, 0); 4767ee5ad2SAlexei Starovoitov return 0; 4867ee5ad2SAlexei Starovoitov } 4967ee5ad2SAlexei Starovoitov 5067ee5ad2SAlexei Starovoitov SEC("syscall") 5167ee5ad2SAlexei Starovoitov int start_timer(void *ctx) 5267ee5ad2SAlexei Starovoitov { 5367ee5ad2SAlexei Starovoitov struct bpf_timer *timer; 5467ee5ad2SAlexei Starovoitov int key = 0; 5567ee5ad2SAlexei Starovoitov 5667ee5ad2SAlexei Starovoitov timer = bpf_map_lookup_elem(&timer_map, &key); 5767ee5ad2SAlexei Starovoitov /* claude may complain here that there is no NULL check. Ignoring it. */ 5867ee5ad2SAlexei Starovoitov bpf_timer_init(timer, &timer_map, CLOCK_MONOTONIC); 5967ee5ad2SAlexei Starovoitov bpf_timer_set_callback(timer, timer_cb); 6067ee5ad2SAlexei Starovoitov 6167ee5ad2SAlexei Starovoitov /* 6267ee5ad2SAlexei Starovoitov * call hrtimer_start() twice, so that 2nd call does 6367ee5ad2SAlexei Starovoitov * remove_hrtimer() and trace_hrtimer_cancel() tracepoint. 6467ee5ad2SAlexei Starovoitov */ 6567ee5ad2SAlexei Starovoitov in_timer_start = 1; 6667ee5ad2SAlexei Starovoitov bpf_timer_start(timer, 1000000000, 0); 6767ee5ad2SAlexei Starovoitov bpf_timer_start(timer, 1000000000, 0); 6867ee5ad2SAlexei Starovoitov in_timer_start = 0; 6967ee5ad2SAlexei Starovoitov return 0; 7067ee5ad2SAlexei Starovoitov } 71