Path: blob/master/tools/tracing/rtla/src/timerlat.bpf.c
26285 views
// SPDX-License-Identifier: GPL-2.01#include <linux/bpf.h>2#include <bpf/bpf_tracing.h>3#include <stdbool.h>4#include "timerlat_bpf.h"56#define nosubprog __always_inline7#define MAX_ENTRIES_DEFAULT 409689char LICENSE[] SEC("license") = "GPL";1011struct trace_event_raw_timerlat_sample {12unsigned long long timer_latency;13int context;14} __attribute__((preserve_access_index));1516struct {17__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);18__uint(max_entries, MAX_ENTRIES_DEFAULT);19__type(key, unsigned int);20__type(value, unsigned long long);21} hist_irq SEC(".maps"), hist_thread SEC(".maps"), hist_user SEC(".maps");2223struct {24__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);25__uint(max_entries, SUMMARY_FIELD_N);26__type(key, unsigned int);27__type(value, unsigned long long);28} summary_irq SEC(".maps"), summary_thread SEC(".maps"), summary_user SEC(".maps");2930struct {31__uint(type, BPF_MAP_TYPE_ARRAY);32__uint(max_entries, 1);33__type(key, unsigned int);34__type(value, unsigned long long);35} stop_tracing SEC(".maps");3637struct {38__uint(type, BPF_MAP_TYPE_RINGBUF);39__uint(max_entries, 1);40} signal_stop_tracing SEC(".maps");4142/* Params to be set by rtla */43const volatile int bucket_size = 1;44const volatile int output_divisor = 1000;45const volatile int entries = 256;46const volatile int irq_threshold;47const volatile int thread_threshold;48const volatile bool aa_only;4950nosubprog unsigned long long map_get(void *map,51unsigned int key)52{53unsigned long long *value_ptr;5455value_ptr = bpf_map_lookup_elem(map, &key);5657return !value_ptr ? 0 : *value_ptr;58}5960nosubprog void map_set(void *map,61unsigned int key,62unsigned long long value)63{64bpf_map_update_elem(map, &key, &value, BPF_ANY);65}6667nosubprog void map_increment(void *map,68unsigned int key)69{70map_set(map, key, map_get(map, key) + 1);71}7273nosubprog void update_main_hist(void *map,74int bucket)75{76if (entries == 0)77/* No histogram */78return;7980if (bucket >= entries)81/* Overflow */82return;8384map_increment(map, bucket);85}8687nosubprog void update_summary(void *map,88unsigned long long latency,89int bucket)90{91if (aa_only)92/* Auto-analysis only, nothing to be done here */93return;9495map_set(map, SUMMARY_CURRENT, latency);9697if (bucket >= entries)98/* Overflow */99map_increment(map, SUMMARY_OVERFLOW);100101if (latency > map_get(map, SUMMARY_MAX))102map_set(map, SUMMARY_MAX, latency);103104if (latency < map_get(map, SUMMARY_MIN) || map_get(map, SUMMARY_COUNT) == 0)105map_set(map, SUMMARY_MIN, latency);106107map_increment(map, SUMMARY_COUNT);108map_set(map, SUMMARY_SUM, map_get(map, SUMMARY_SUM) + latency);109}110111nosubprog void set_stop_tracing(void)112{113int value = 0;114115/* Suppress further sample processing */116map_set(&stop_tracing, 0, 1);117118/* Signal to userspace */119bpf_ringbuf_output(&signal_stop_tracing, &value, sizeof(value), 0);120}121122SEC("tp/osnoise/timerlat_sample")123int handle_timerlat_sample(struct trace_event_raw_timerlat_sample *tp_args)124{125unsigned long long latency, latency_us;126int bucket;127128if (map_get(&stop_tracing, 0))129return 0;130131latency = tp_args->timer_latency / output_divisor;132latency_us = tp_args->timer_latency / 1000;133bucket = latency / bucket_size;134135if (tp_args->context == 0) {136update_main_hist(&hist_irq, bucket);137update_summary(&summary_irq, latency, bucket);138139if (irq_threshold != 0 && latency_us >= irq_threshold)140set_stop_tracing();141} else if (tp_args->context == 1) {142update_main_hist(&hist_thread, bucket);143update_summary(&summary_thread, latency, bucket);144145if (thread_threshold != 0 && latency_us >= thread_threshold)146set_stop_tracing();147} else {148update_main_hist(&hist_user, bucket);149update_summary(&summary_user, latency, bucket);150}151152return 0;153}154155156