1*363b17e2STao Chen // SPDX-License-Identifier: GPL-2.0 2*363b17e2STao Chen // Copyright (c) 2018 Facebook 3*363b17e2STao Chen 4*363b17e2STao Chen #include <vmlinux.h> 5*363b17e2STao Chen #include <bpf/bpf_helpers.h> 6*363b17e2STao Chen 7*363b17e2STao Chen #ifndef PERF_MAX_STACK_DEPTH 8*363b17e2STao Chen #define PERF_MAX_STACK_DEPTH 127 9*363b17e2STao Chen #endif 10*363b17e2STao Chen 11*363b17e2STao Chen struct { 12*363b17e2STao Chen __uint(type, BPF_MAP_TYPE_ARRAY); 13*363b17e2STao Chen __uint(max_entries, 1); 14*363b17e2STao Chen __type(key, __u32); 15*363b17e2STao Chen __type(value, __u32); 16*363b17e2STao Chen } control_map SEC(".maps"); 17*363b17e2STao Chen 18*363b17e2STao Chen struct { 19*363b17e2STao Chen __uint(type, BPF_MAP_TYPE_HASH); 20*363b17e2STao Chen __uint(max_entries, 16384); 21*363b17e2STao Chen __type(key, __u32); 22*363b17e2STao Chen __type(value, __u32); 23*363b17e2STao Chen } stackid_hmap SEC(".maps"); 24*363b17e2STao Chen 25*363b17e2STao Chen typedef __u64 stack_trace_t[PERF_MAX_STACK_DEPTH]; 26*363b17e2STao Chen 27*363b17e2STao Chen struct { 28*363b17e2STao Chen __uint(type, BPF_MAP_TYPE_STACK_TRACE); 29*363b17e2STao Chen __uint(max_entries, 16384); 30*363b17e2STao Chen __type(key, __u32); 31*363b17e2STao Chen __type(value, stack_trace_t); 32*363b17e2STao Chen } stackmap SEC(".maps"); 33*363b17e2STao Chen 34*363b17e2STao Chen struct { 35*363b17e2STao Chen __uint(type, BPF_MAP_TYPE_ARRAY); 36*363b17e2STao Chen __uint(max_entries, 16384); 37*363b17e2STao Chen __type(key, __u32); 38*363b17e2STao Chen __type(value, stack_trace_t); 39*363b17e2STao Chen } stack_amap SEC(".maps"); 40*363b17e2STao Chen 41*363b17e2STao Chen /* taken from /sys/kernel/tracing/events/sched/sched_switch/format */ 42*363b17e2STao Chen struct sched_switch_args { 43*363b17e2STao Chen unsigned long long pad; 44*363b17e2STao Chen char prev_comm[TASK_COMM_LEN]; 45*363b17e2STao Chen int prev_pid; 46*363b17e2STao Chen int prev_prio; 47*363b17e2STao Chen long long prev_state; 48*363b17e2STao Chen char next_comm[TASK_COMM_LEN]; 49*363b17e2STao Chen int next_pid; 50*363b17e2STao Chen int next_prio; 51*363b17e2STao Chen }; 52*363b17e2STao Chen 53*363b17e2STao Chen SEC("tracepoint/sched/sched_switch") 54*363b17e2STao Chen int oncpu(struct sched_switch_args *ctx) 55*363b17e2STao Chen { 56*363b17e2STao Chen __u32 max_len = PERF_MAX_STACK_DEPTH * sizeof(__u64); 57*363b17e2STao Chen __u32 key = 0, val = 0, *value_p; 58*363b17e2STao Chen void *stack_p; 59*363b17e2STao Chen 60*363b17e2STao Chen value_p = bpf_map_lookup_elem(&control_map, &key); 61*363b17e2STao Chen if (value_p && *value_p) 62*363b17e2STao Chen return 0; /* skip if non-zero *value_p */ 63*363b17e2STao Chen 64*363b17e2STao Chen /* The size of stackmap and stackid_hmap should be the same */ 65*363b17e2STao Chen key = bpf_get_stackid(ctx, &stackmap, 0); 66*363b17e2STao Chen if ((int)key >= 0) { 67*363b17e2STao Chen bpf_map_update_elem(&stackid_hmap, &key, &val, 0); 68*363b17e2STao Chen stack_p = bpf_map_lookup_elem(&stack_amap, &key); 69*363b17e2STao Chen if (stack_p) 70*363b17e2STao Chen bpf_get_stack(ctx, stack_p, max_len, 0); 71*363b17e2STao Chen } 72*363b17e2STao Chen 73*363b17e2STao Chen return 0; 74*363b17e2STao Chen } 75*363b17e2STao Chen 76*363b17e2STao Chen char _license[] SEC("license") = "GPL"; 77