Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
0002 // Copyright (c) 2020 Facebook
0003 #include "vmlinux.h"
0004 #include <bpf/bpf_helpers.h>
0005 #include <bpf/bpf_tracing.h>
0006 
0007 /* map of perf event fds, num_cpu * num_metric entries */
0008 struct {
0009     __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
0010     __uint(key_size, sizeof(__u32));
0011     __uint(value_size, sizeof(int));
0012 } events SEC(".maps");
0013 
0014 /* readings at fentry */
0015 struct {
0016     __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
0017     __uint(key_size, sizeof(__u32));
0018     __uint(value_size, sizeof(struct bpf_perf_event_value));
0019     __uint(max_entries, 1);
0020 } fentry_readings SEC(".maps");
0021 
0022 /* accumulated readings */
0023 struct {
0024     __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
0025     __uint(key_size, sizeof(__u32));
0026     __uint(value_size, sizeof(struct bpf_perf_event_value));
0027     __uint(max_entries, 1);
0028 } accum_readings SEC(".maps");
0029 
0030 const volatile __u32 num_cpu = 1;
0031 
0032 SEC("fentry/XXX")
0033 int BPF_PROG(fentry_XXX)
0034 {
0035     __u32 key = bpf_get_smp_processor_id();
0036     struct bpf_perf_event_value *ptr;
0037     __u32 zero = 0;
0038     long err;
0039 
0040     /* look up before reading, to reduce error */
0041     ptr = bpf_map_lookup_elem(&fentry_readings, &zero);
0042     if (!ptr)
0043         return 0;
0044 
0045     err = bpf_perf_event_read_value(&events, key, ptr, sizeof(*ptr));
0046     if (err)
0047         return 0;
0048 
0049     return 0;
0050 }
0051 
0052 static inline void
0053 fexit_update_maps(struct bpf_perf_event_value *after)
0054 {
0055     struct bpf_perf_event_value *before, diff;
0056     __u32 zero = 0;
0057 
0058     before = bpf_map_lookup_elem(&fentry_readings, &zero);
0059     /* only account samples with a valid fentry_reading */
0060     if (before && before->counter) {
0061         struct bpf_perf_event_value *accum;
0062 
0063         diff.counter = after->counter - before->counter;
0064         diff.enabled = after->enabled - before->enabled;
0065         diff.running = after->running - before->running;
0066 
0067         accum = bpf_map_lookup_elem(&accum_readings, &zero);
0068         if (accum) {
0069             accum->counter += diff.counter;
0070             accum->enabled += diff.enabled;
0071             accum->running += diff.running;
0072         }
0073     }
0074 }
0075 
0076 SEC("fexit/XXX")
0077 int BPF_PROG(fexit_XXX)
0078 {
0079     struct bpf_perf_event_value reading;
0080     __u32 cpu = bpf_get_smp_processor_id();
0081     int err;
0082 
0083     /* read all events before updating the maps, to reduce error */
0084     err = bpf_perf_event_read_value(&events, cpu, &reading, sizeof(reading));
0085     if (err)
0086         return 0;
0087 
0088     fexit_update_maps(&reading);
0089     return 0;
0090 }
0091 
0092 char LICENSE[] SEC("license") = "Dual BSD/GPL";