Back to home page

OSCL-LXR

 
 

    


0001 #include <stdio.h>
0002 #include <fcntl.h>
0003 #include <stdint.h>
0004 #include <stdlib.h>
0005 
0006 #include <linux/err.h>
0007 
0008 #include "util/ftrace.h"
0009 #include "util/cpumap.h"
0010 #include "util/thread_map.h"
0011 #include "util/debug.h"
0012 #include "util/evlist.h"
0013 #include "util/bpf_counter.h"
0014 
0015 #include "util/bpf_skel/func_latency.skel.h"
0016 
0017 static struct func_latency_bpf *skel;
0018 
0019 int perf_ftrace__latency_prepare_bpf(struct perf_ftrace *ftrace)
0020 {
0021     int fd, err;
0022     int i, ncpus = 1, ntasks = 1;
0023     struct filter_entry *func;
0024 
0025     if (!list_is_singular(&ftrace->filters)) {
0026         pr_err("ERROR: %s target function(s).\n",
0027                list_empty(&ftrace->filters) ? "No" : "Too many");
0028         return -1;
0029     }
0030 
0031     func = list_first_entry(&ftrace->filters, struct filter_entry, list);
0032 
0033     skel = func_latency_bpf__open();
0034     if (!skel) {
0035         pr_err("Failed to open func latency skeleton\n");
0036         return -1;
0037     }
0038 
0039     /* don't need to set cpu filter for system-wide mode */
0040     if (ftrace->target.cpu_list) {
0041         ncpus = perf_cpu_map__nr(ftrace->evlist->core.user_requested_cpus);
0042         bpf_map__set_max_entries(skel->maps.cpu_filter, ncpus);
0043     }
0044 
0045     if (target__has_task(&ftrace->target) || target__none(&ftrace->target)) {
0046         ntasks = perf_thread_map__nr(ftrace->evlist->core.threads);
0047         bpf_map__set_max_entries(skel->maps.task_filter, ntasks);
0048     }
0049 
0050     set_max_rlimit();
0051 
0052     err = func_latency_bpf__load(skel);
0053     if (err) {
0054         pr_err("Failed to load func latency skeleton\n");
0055         goto out;
0056     }
0057 
0058     if (ftrace->target.cpu_list) {
0059         u32 cpu;
0060         u8 val = 1;
0061 
0062         skel->bss->has_cpu = 1;
0063         fd = bpf_map__fd(skel->maps.cpu_filter);
0064 
0065         for (i = 0; i < ncpus; i++) {
0066             cpu = perf_cpu_map__cpu(ftrace->evlist->core.user_requested_cpus, i).cpu;
0067             bpf_map_update_elem(fd, &cpu, &val, BPF_ANY);
0068         }
0069     }
0070 
0071     if (target__has_task(&ftrace->target) || target__none(&ftrace->target)) {
0072         u32 pid;
0073         u8 val = 1;
0074 
0075         skel->bss->has_task = 1;
0076         fd = bpf_map__fd(skel->maps.task_filter);
0077 
0078         for (i = 0; i < ntasks; i++) {
0079             pid = perf_thread_map__pid(ftrace->evlist->core.threads, i);
0080             bpf_map_update_elem(fd, &pid, &val, BPF_ANY);
0081         }
0082     }
0083 
0084     skel->bss->use_nsec = ftrace->use_nsec;
0085 
0086     skel->links.func_begin = bpf_program__attach_kprobe(skel->progs.func_begin,
0087                                 false, func->name);
0088     if (IS_ERR(skel->links.func_begin)) {
0089         pr_err("Failed to attach fentry program\n");
0090         err = PTR_ERR(skel->links.func_begin);
0091         goto out;
0092     }
0093 
0094     skel->links.func_end = bpf_program__attach_kprobe(skel->progs.func_end,
0095                               true, func->name);
0096     if (IS_ERR(skel->links.func_end)) {
0097         pr_err("Failed to attach fexit program\n");
0098         err = PTR_ERR(skel->links.func_end);
0099         goto out;
0100     }
0101 
0102     /* XXX: we don't actually use this fd - just for poll() */
0103     return open("/dev/null", O_RDONLY);
0104 
0105 out:
0106     return err;
0107 }
0108 
0109 int perf_ftrace__latency_start_bpf(struct perf_ftrace *ftrace __maybe_unused)
0110 {
0111     skel->bss->enabled = 1;
0112     return 0;
0113 }
0114 
0115 int perf_ftrace__latency_stop_bpf(struct perf_ftrace *ftrace __maybe_unused)
0116 {
0117     skel->bss->enabled = 0;
0118     return 0;
0119 }
0120 
0121 int perf_ftrace__latency_read_bpf(struct perf_ftrace *ftrace __maybe_unused,
0122                   int buckets[])
0123 {
0124     int i, fd, err;
0125     u32 idx;
0126     u64 *hist;
0127     int ncpus = cpu__max_cpu().cpu;
0128 
0129     fd = bpf_map__fd(skel->maps.latency);
0130 
0131     hist = calloc(ncpus, sizeof(*hist));
0132     if (hist == NULL)
0133         return -ENOMEM;
0134 
0135     for (idx = 0; idx < NUM_BUCKET; idx++) {
0136         err = bpf_map_lookup_elem(fd, &idx, hist);
0137         if (err) {
0138             buckets[idx] = 0;
0139             continue;
0140         }
0141 
0142         for (i = 0; i < ncpus; i++)
0143             buckets[idx] += hist[i];
0144     }
0145 
0146     free(hist);
0147     return 0;
0148 }
0149 
0150 int perf_ftrace__latency_cleanup_bpf(struct perf_ftrace *ftrace __maybe_unused)
0151 {
0152     func_latency_bpf__destroy(skel);
0153     return 0;
0154 }