Path: blob/master/tools/tracing/rtla/src/timerlat_bpf.c
26285 views
// SPDX-License-Identifier: GPL-2.01#ifdef HAVE_BPF_SKEL2#define _GNU_SOURCE3#include "timerlat.h"4#include "timerlat_bpf.h"5#include "timerlat.skel.h"67static struct timerlat_bpf *bpf;89/*10* timerlat_bpf_init - load and initialize BPF program to collect timerlat data11*/12int timerlat_bpf_init(struct timerlat_params *params)13{14int err;1516debug_msg("Loading BPF program\n");1718bpf = timerlat_bpf__open();19if (!bpf)20return 1;2122/* Pass common options */23bpf->rodata->output_divisor = params->output_divisor;24bpf->rodata->entries = params->entries;25bpf->rodata->irq_threshold = params->stop_us;26bpf->rodata->thread_threshold = params->stop_total_us;27bpf->rodata->aa_only = params->aa_only;2829if (params->entries != 0) {30/* Pass histogram options */31bpf->rodata->bucket_size = params->bucket_size;3233/* Set histogram array sizes */34bpf_map__set_max_entries(bpf->maps.hist_irq, params->entries);35bpf_map__set_max_entries(bpf->maps.hist_thread, params->entries);36bpf_map__set_max_entries(bpf->maps.hist_user, params->entries);37} else {38/* No entries, disable histogram */39bpf_map__set_autocreate(bpf->maps.hist_irq, false);40bpf_map__set_autocreate(bpf->maps.hist_thread, false);41bpf_map__set_autocreate(bpf->maps.hist_user, false);42}4344if (params->aa_only) {45/* Auto-analysis only, disable summary */46bpf_map__set_autocreate(bpf->maps.summary_irq, false);47bpf_map__set_autocreate(bpf->maps.summary_thread, false);48bpf_map__set_autocreate(bpf->maps.summary_user, false);49}5051/* Load and verify BPF program */52err = timerlat_bpf__load(bpf);53if (err) {54timerlat_bpf__destroy(bpf);55return err;56}5758return 0;59}6061/*62* timerlat_bpf_attach - attach BPF program to collect timerlat data63*/64int timerlat_bpf_attach(void)65{66debug_msg("Attaching BPF program\n");6768return timerlat_bpf__attach(bpf);69}7071/*72* timerlat_bpf_detach - detach BPF program to collect timerlat data73*/74void timerlat_bpf_detach(void)75{76timerlat_bpf__detach(bpf);77}7879/*80* timerlat_bpf_detach - destroy BPF program to collect timerlat data81*/82void timerlat_bpf_destroy(void)83{84timerlat_bpf__destroy(bpf);85}8687static int handle_rb_event(void *ctx, void *data, size_t data_sz)88{89return 0;90}9192/*93* timerlat_bpf_wait - wait until tracing is stopped or signal94*/95int timerlat_bpf_wait(int timeout)96{97struct ring_buffer *rb;98int retval;99100rb = ring_buffer__new(bpf_map__fd(bpf->maps.signal_stop_tracing),101handle_rb_event, NULL, NULL);102retval = ring_buffer__poll(rb, timeout * 1000);103ring_buffer__free(rb);104105return retval;106}107108/*109* timerlat_bpf_restart_tracing - restart stopped tracing110*/111int timerlat_bpf_restart_tracing(void)112{113unsigned int key = 0;114unsigned long long value = 0;115116return bpf_map__update_elem(bpf->maps.stop_tracing,117&key, sizeof(key),118&value, sizeof(value), BPF_ANY);119}120121static int get_value(struct bpf_map *map_irq,122struct bpf_map *map_thread,123struct bpf_map *map_user,124int key,125long long *value_irq,126long long *value_thread,127long long *value_user,128int cpus)129{130int err;131132err = bpf_map__lookup_elem(map_irq, &key,133sizeof(unsigned int), value_irq,134sizeof(long long) * cpus, 0);135if (err)136return err;137err = bpf_map__lookup_elem(map_thread, &key,138sizeof(unsigned int), value_thread,139sizeof(long long) * cpus, 0);140if (err)141return err;142err = bpf_map__lookup_elem(map_user, &key,143sizeof(unsigned int), value_user,144sizeof(long long) * cpus, 0);145if (err)146return err;147return 0;148}149150/*151* timerlat_bpf_get_hist_value - get value from BPF hist map152*/153int timerlat_bpf_get_hist_value(int key,154long long *value_irq,155long long *value_thread,156long long *value_user,157int cpus)158{159return get_value(bpf->maps.hist_irq,160bpf->maps.hist_thread,161bpf->maps.hist_user,162key, value_irq, value_thread, value_user, cpus);163}164165/*166* timerlat_bpf_get_summary_value - get value from BPF summary map167*/168int timerlat_bpf_get_summary_value(enum summary_field key,169long long *value_irq,170long long *value_thread,171long long *value_user,172int cpus)173{174return get_value(bpf->maps.summary_irq,175bpf->maps.summary_thread,176bpf->maps.summary_user,177key, value_irq, value_thread, value_user, cpus);178}179#endif /* HAVE_BPF_SKEL */180181182