1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 // Copyright (c) 2021 Facebook 3 #include "vmlinux.h" 4 #include <bpf/bpf_helpers.h> 5 #include <bpf/bpf_tracing.h> 6 7 struct { 8 __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); 9 __uint(key_size, sizeof(__u32)); 10 __uint(value_size, sizeof(int)); 11 __uint(map_flags, BPF_F_PRESERVE_ELEMS); 12 } events SEC(".maps"); 13 14 struct { 15 __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 16 __uint(key_size, sizeof(__u32)); 17 __uint(value_size, sizeof(struct bpf_perf_event_value)); 18 __uint(max_entries, 1); 19 } prev_readings SEC(".maps"); 20 21 struct { 22 __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 23 __uint(key_size, sizeof(__u32)); 24 __uint(value_size, sizeof(struct bpf_perf_event_value)); 25 __uint(max_entries, 1); 26 } diff_readings SEC(".maps"); 27 28 SEC("raw_tp/sched_switch") 29 int BPF_PROG(on_switch) 30 { 31 struct bpf_perf_event_value val, *prev_val, *diff_val; 32 __u32 key = bpf_get_smp_processor_id(); 33 __u32 zero = 0; 34 long err; 35 36 prev_val = bpf_map_lookup_elem(&prev_readings, &zero); 37 if (!prev_val) 38 return 0; 39 40 diff_val = bpf_map_lookup_elem(&diff_readings, &zero); 41 if (!diff_val) 42 return 0; 43 44 err = bpf_perf_event_read_value(&events, key, &val, sizeof(val)); 45 if (err) 46 return 0; 47 48 diff_val->counter = val.counter - prev_val->counter; 49 diff_val->enabled = val.enabled - prev_val->enabled; 50 diff_val->running = val.running - prev_val->running; 51 *prev_val = val; 52 return 0; 53 } 54 55 char LICENSE[] SEC("license") = "Dual BSD/GPL"; 56