^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) // Copyright (c) 2020 Facebook
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <vmlinux.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <bpf/bpf_helpers.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <bpf/bpf_tracing.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) /* map of perf event fds, num_cpu * num_metric entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) __uint(key_size, sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) __uint(value_size, sizeof(int));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) } events SEC(".maps");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) /* readings at fentry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) __uint(key_size, sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) __uint(value_size, sizeof(struct bpf_perf_event_value));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) } fentry_readings SEC(".maps");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /* accumulated readings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) __uint(key_size, sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) __uint(value_size, sizeof(struct bpf_perf_event_value));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) } accum_readings SEC(".maps");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /* sample counts, one per cpu */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) __uint(key_size, sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) __uint(value_size, sizeof(u64));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) } counts SEC(".maps");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) const volatile __u32 num_cpu = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) const volatile __u32 num_metric = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define MAX_NUM_MATRICS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) SEC("fentry/XXX")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) int BPF_PROG(fentry_XXX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct bpf_perf_event_value *ptrs[MAX_NUM_MATRICS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) u32 key = bpf_get_smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) u32 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* look up before reading, to reduce error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) for (i = 0; i < num_metric && i < MAX_NUM_MATRICS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) u32 flag = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) ptrs[i] = bpf_map_lookup_elem(&fentry_readings, &flag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (!ptrs[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) for (i = 0; i < num_metric && i < MAX_NUM_MATRICS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct bpf_perf_event_value reading;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) err = bpf_perf_event_read_value(&events, key, &reading,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) sizeof(reading));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) *(ptrs[i]) = reading;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) key += num_cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) fexit_update_maps(u32 id, struct bpf_perf_event_value *after)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct bpf_perf_event_value *before, diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) before = bpf_map_lookup_elem(&fentry_readings, &id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* only account samples with a valid fentry_reading */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (before && before->counter) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct bpf_perf_event_value *accum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) diff.counter = after->counter - before->counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) diff.enabled = after->enabled - before->enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) diff.running = after->running - before->running;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) accum = bpf_map_lookup_elem(&accum_readings, &id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (accum) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) accum->counter += diff.counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) accum->enabled += diff.enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) accum->running += diff.running;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) SEC("fexit/XXX")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) int BPF_PROG(fexit_XXX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct bpf_perf_event_value readings[MAX_NUM_MATRICS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) u32 cpu = bpf_get_smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) u32 i, zero = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) u64 *count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* read all events before updating the maps, to reduce error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) for (i = 0; i < num_metric && i < MAX_NUM_MATRICS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) err = bpf_perf_event_read_value(&events, cpu + i * num_cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) readings + i, sizeof(*readings));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) count = bpf_map_lookup_elem(&counts, &zero);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) *count += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) for (i = 0; i < num_metric && i < MAX_NUM_MATRICS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) fexit_update_maps(i, &readings[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) char LICENSE[] SEC("license") = "Dual BSD/GPL";