Path: blob/master/tools/tracing/rtla/src/timerlat_bpf.c
54335 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/* BPF object and program for action program */10static struct bpf_object *obj;11static struct bpf_program *prog;1213/*14* timerlat_bpf_init - load and initialize BPF program to collect timerlat data15*/16int timerlat_bpf_init(struct timerlat_params *params)17{18int err;1920debug_msg("Loading BPF program\n");2122bpf = timerlat_bpf__open();23if (!bpf)24return 1;2526/* Pass common options */27bpf->rodata->output_divisor = params->common.output_divisor;28bpf->rodata->entries = params->common.hist.entries;29bpf->rodata->irq_threshold = params->common.stop_us;30bpf->rodata->thread_threshold = params->common.stop_total_us;31bpf->rodata->aa_only = params->common.aa_only;3233if (params->common.hist.entries != 0) {34/* Pass histogram options */35bpf->rodata->bucket_size = params->common.hist.bucket_size;3637/* Set histogram array sizes */38bpf_map__set_max_entries(bpf->maps.hist_irq, params->common.hist.entries);39bpf_map__set_max_entries(bpf->maps.hist_thread, params->common.hist.entries);40bpf_map__set_max_entries(bpf->maps.hist_user, params->common.hist.entries);41} else {42/* No entries, disable histogram */43bpf_map__set_autocreate(bpf->maps.hist_irq, false);44bpf_map__set_autocreate(bpf->maps.hist_thread, false);45bpf_map__set_autocreate(bpf->maps.hist_user, false);46}4748if (params->common.aa_only) {49/* Auto-analysis only, disable summary */50bpf_map__set_autocreate(bpf->maps.summary_irq, false);51bpf_map__set_autocreate(bpf->maps.summary_thread, false);52bpf_map__set_autocreate(bpf->maps.summary_user, false);53}5455/* Load and verify BPF program */56err = timerlat_bpf__load(bpf);57if (err) {58timerlat_bpf__destroy(bpf);59return err;60}6162return 0;63}6465/*66* timerlat_bpf_set_action - set action on threshold executed on BPF side67*/68static int timerlat_bpf_set_action(struct bpf_program *prog)69{70unsigned int key = 0, value = bpf_program__fd(prog);7172return bpf_map__update_elem(bpf->maps.bpf_action,73&key, sizeof(key),74&value, sizeof(value),75BPF_ANY);76}7778/*79* timerlat_bpf_attach - attach BPF program to collect timerlat data80*/81int timerlat_bpf_attach(void)82{83debug_msg("Attaching BPF program\n");8485return timerlat_bpf__attach(bpf);86}8788/*89* timerlat_bpf_detach - detach BPF program to collect timerlat data90*/91void timerlat_bpf_detach(void)92{93timerlat_bpf__detach(bpf);94}9596/*97* timerlat_bpf_detach - destroy BPF program to collect timerlat data98*/99void timerlat_bpf_destroy(void)100{101timerlat_bpf__destroy(bpf);102bpf = NULL;103if (obj)104bpf_object__close(obj);105obj = NULL;106prog = NULL;107}108109static int handle_rb_event(void *ctx, void *data, size_t data_sz)110{111return 0;112}113114/*115* timerlat_bpf_wait - wait until tracing is stopped or signal116*/117int timerlat_bpf_wait(int timeout)118{119struct ring_buffer *rb;120int retval;121122rb = ring_buffer__new(bpf_map__fd(bpf->maps.signal_stop_tracing),123handle_rb_event, NULL, NULL);124retval = ring_buffer__poll(rb, timeout * 1000);125ring_buffer__free(rb);126127return retval;128}129130/*131* timerlat_bpf_restart_tracing - restart stopped tracing132*/133int timerlat_bpf_restart_tracing(void)134{135unsigned int key = 0;136unsigned long long value = 0;137138return bpf_map__update_elem(bpf->maps.stop_tracing,139&key, sizeof(key),140&value, sizeof(value), BPF_ANY);141}142143static int get_value(struct bpf_map *map_irq,144struct bpf_map *map_thread,145struct bpf_map *map_user,146int key,147long long *value_irq,148long long *value_thread,149long long *value_user,150int cpus)151{152int err;153154err = bpf_map__lookup_elem(map_irq, &key,155sizeof(unsigned int), value_irq,156sizeof(long long) * cpus, 0);157if (err)158return err;159err = bpf_map__lookup_elem(map_thread, &key,160sizeof(unsigned int), value_thread,161sizeof(long long) * cpus, 0);162if (err)163return err;164err = bpf_map__lookup_elem(map_user, &key,165sizeof(unsigned int), value_user,166sizeof(long long) * cpus, 0);167if (err)168return err;169return 0;170}171172/*173* timerlat_bpf_get_hist_value - get value from BPF hist map174*/175int timerlat_bpf_get_hist_value(int key,176long long *value_irq,177long long *value_thread,178long long *value_user,179int cpus)180{181return get_value(bpf->maps.hist_irq,182bpf->maps.hist_thread,183bpf->maps.hist_user,184key, value_irq, value_thread, value_user, cpus);185}186187/*188* timerlat_bpf_get_summary_value - get value from BPF summary map189*/190int timerlat_bpf_get_summary_value(enum summary_field key,191long long *value_irq,192long long *value_thread,193long long *value_user,194int cpus)195{196return get_value(bpf->maps.summary_irq,197bpf->maps.summary_thread,198bpf->maps.summary_user,199key, value_irq, value_thread, value_user, cpus);200}201202/*203* timerlat_load_bpf_action_program - load and register a BPF action program204*/205int timerlat_load_bpf_action_program(const char *program_path)206{207int err;208209obj = bpf_object__open_file(program_path, NULL);210if (!obj) {211err_msg("Failed to open BPF action program: %s\n", program_path);212goto out_err;213}214215err = bpf_object__load(obj);216if (err) {217err_msg("Failed to load BPF action program: %s\n", program_path);218goto out_obj_err;219}220221prog = bpf_object__find_program_by_name(obj, "action_handler");222if (!prog) {223err_msg("BPF action program must have 'action_handler' function: %s\n",224program_path);225goto out_obj_err;226}227228err = timerlat_bpf_set_action(prog);229if (err) {230err_msg("Failed to register BPF action program: %s\n", program_path);231goto out_prog_err;232}233234return 0;235236out_prog_err:237prog = NULL;238out_obj_err:239bpf_object__close(obj);240obj = NULL;241out_err:242return 1;243}244245#endif /* HAVE_BPF_SKEL */246247248