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 } fentry_readings SEC(".maps");
0020 
0021 /* accumulated readings */
0022 struct {
0023     __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
0024     __uint(key_size, sizeof(u32));
0025     __uint(value_size, sizeof(struct bpf_perf_event_value));
0026 } accum_readings SEC(".maps");
0027 
0028 /* sample counts, one per cpu */
0029 struct {
0030     __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
0031     __uint(key_size, sizeof(u32));
0032     __uint(value_size, sizeof(u64));
0033 } counts SEC(".maps");
0034 
0035 const volatile __u32 num_cpu = 1;
0036 const volatile __u32 num_metric = 1;
0037 #define MAX_NUM_MATRICS 4
0038 
0039 SEC("fentry/XXX")
0040 int BPF_PROG(fentry_XXX)
0041 {
0042     struct bpf_perf_event_value *ptrs[MAX_NUM_MATRICS];
0043     u32 key = bpf_get_smp_processor_id();
0044     u32 i;
0045 
0046     /* look up before reading, to reduce error */
0047     for (i = 0; i < num_metric && i < MAX_NUM_MATRICS; i++) {
0048         u32 flag = i;
0049 
0050         ptrs[i] = bpf_map_lookup_elem(&fentry_readings, &flag);
0051         if (!ptrs[i])
0052             return 0;
0053     }
0054 
0055     for (i = 0; i < num_metric && i < MAX_NUM_MATRICS; i++) {
0056         struct bpf_perf_event_value reading;
0057         int err;
0058 
0059         err = bpf_perf_event_read_value(&events, key, &reading,
0060                         sizeof(reading));
0061         if (err)
0062             return 0;
0063         *(ptrs[i]) = reading;
0064         key += num_cpu;
0065     }
0066 
0067     return 0;
0068 }
0069 
0070 static inline void
0071 fexit_update_maps(u32 id, struct bpf_perf_event_value *after)
0072 {
0073     struct bpf_perf_event_value *before, diff;
0074 
0075     before = bpf_map_lookup_elem(&fentry_readings, &id);
0076     /* only account samples with a valid fentry_reading */
0077     if (before && before->counter) {
0078         struct bpf_perf_event_value *accum;
0079 
0080         diff.counter = after->counter - before->counter;
0081         diff.enabled = after->enabled - before->enabled;
0082         diff.running = after->running - before->running;
0083 
0084         accum = bpf_map_lookup_elem(&accum_readings, &id);
0085         if (accum) {
0086             accum->counter += diff.counter;
0087             accum->enabled += diff.enabled;
0088             accum->running += diff.running;
0089         }
0090     }
0091 }
0092 
0093 SEC("fexit/XXX")
0094 int BPF_PROG(fexit_XXX)
0095 {
0096     struct bpf_perf_event_value readings[MAX_NUM_MATRICS];
0097     u32 cpu = bpf_get_smp_processor_id();
0098     u32 i, zero = 0;
0099     int err;
0100     u64 *count;
0101 
0102     /* read all events before updating the maps, to reduce error */
0103     for (i = 0; i < num_metric && i < MAX_NUM_MATRICS; i++) {
0104         err = bpf_perf_event_read_value(&events, cpu + i * num_cpu,
0105                         readings + i, sizeof(*readings));
0106         if (err)
0107             return 0;
0108     }
0109     count = bpf_map_lookup_elem(&counts, &zero);
0110     if (count) {
0111         *count += 1;
0112         for (i = 0; i < num_metric && i < MAX_NUM_MATRICS; i++)
0113             fexit_update_maps(i, &readings[i]);
0114     }
0115     return 0;
0116 }
0117 
0118 char LICENSE[] SEC("license") = "Dual BSD/GPL";