Skip to content

Commit

Permalink
libbpf-tools: Allow hardirqs to run on old kernels
Browse files Browse the repository at this point in the history
This is part of efforts towards iovisor#4231. Fallback to raw tracepoints
if tp_btf is not available. With this patch, we also remove manual
attach and merge the two irq_handler_entry handlers into one.

Signed-off-by: Hengqi Chen <[email protected]>
  • Loading branch information
chenhengqi committed Sep 13, 2022
1 parent dfb0d98 commit fcd2187
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 50 deletions.
74 changes: 47 additions & 27 deletions libbpf-tools/hardirqs.bpf.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2020 Wenbo Zhang
#include <vmlinux.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include "hardirqs.h"
Expand All @@ -12,6 +13,7 @@
const volatile bool filter_cg = false;
const volatile bool targ_dist = false;
const volatile bool targ_ns = false;
const volatile bool do_count = false;

struct {
__uint(type, BPF_MAP_TYPE_CGROUP_ARRAY);
Expand All @@ -36,59 +38,53 @@ struct {

static struct info zero;

SEC("tracepoint/irq/irq_handler_entry")
int handle__irq_handler(struct trace_event_raw_irq_handler_entry *ctx)
static int handle_entry(int irq, struct irqaction *action)
{
struct irq_key key = {};
struct info *info;

if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
return 0;

bpf_probe_read_kernel_str(&key.name, sizeof(key.name), ctx->__data);
info = bpf_map_lookup_or_try_init(&infos, &key, &zero);
if (!info)
if (do_count) {
struct irq_key key = {};
struct info *info;

bpf_probe_read_kernel_str(&key.name, sizeof(key.name), BPF_CORE_READ(action, name));
info = bpf_map_lookup_or_try_init(&infos, &key, &zero);
if (!info)
return 0;
info->count += 1;
return 0;
info->count += 1;
return 0;
}
} else {
u64 ts = bpf_ktime_get_ns();
u32 key = 0;

SEC("tp_btf/irq_handler_entry")
int BPF_PROG(irq_handler_entry)
{
u64 ts = bpf_ktime_get_ns();
u32 key = 0;
if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
return 0;

if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
bpf_map_update_elem(&start, &key, &ts, BPF_ANY);
return 0;

bpf_map_update_elem(&start, &key, &ts, 0);
return 0;
}
}

SEC("tp_btf/irq_handler_exit")
int BPF_PROG(irq_handler_exit_exit, int irq, struct irqaction *action)
static int handle_exit(int irq, struct irqaction *action)
{
struct irq_key ikey = {};
struct info *info;
u32 key = 0;
s64 delta;
u64 delta;
u64 *tsp;

if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
return 0;

tsp = bpf_map_lookup_elem(&start, &key);
if (!tsp || !*tsp)
if (!tsp)
return 0;

delta = bpf_ktime_get_ns() - *tsp;
if (delta < 0)
return 0;
if (!targ_ns)
delta /= 1000U;

bpf_probe_read_kernel_str(&ikey.name, sizeof(ikey.name), action->name);
bpf_probe_read_kernel_str(&ikey.name, sizeof(ikey.name), BPF_CORE_READ(action, name));
info = bpf_map_lookup_or_try_init(&infos, &ikey, &zero);
if (!info)
return 0;
Expand All @@ -107,4 +103,28 @@ int BPF_PROG(irq_handler_exit_exit, int irq, struct irqaction *action)
return 0;
}

SEC("tp_btf/irq_handler_entry")
int BPF_PROG(irq_handler_entry_btf, int irq, struct irqaction *action)
{
return handle_entry(irq, action);
}

SEC("tp_btf/irq_handler_exit")
int BPF_PROG(irq_handler_exit_btf, int irq, struct irqaction *action)
{
return handle_exit(irq, action);
}

SEC("raw_tp/irq_handler_entry")
int BPF_PROG(irq_handler_entry, int irq, struct irqaction *action)
{
return handle_entry(irq, action);
}

SEC("raw_tp/irq_handler_exit")
int BPF_PROG(irq_handler_exit, int irq, struct irqaction *action)
{
return handle_exit(irq, action);
}

char LICENSE[] SEC("license") = "GPL";
40 changes: 17 additions & 23 deletions libbpf-tools/hardirqs.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,20 @@ int main(int argc, char **argv)
return 1;
}

if (probe_tp_btf("irq_handler_entry")) {
bpf_program__set_autoload(obj->progs.irq_handler_entry, false);
bpf_program__set_autoload(obj->progs.irq_handler_exit, false);
if (env.count)
bpf_program__set_autoload(obj->progs.irq_handler_exit_btf, false);
} else {
bpf_program__set_autoload(obj->progs.irq_handler_entry_btf, false);
bpf_program__set_autoload(obj->progs.irq_handler_exit_btf, false);
if (env.count)
bpf_program__set_autoload(obj->progs.irq_handler_exit, false);
}

obj->rodata->filter_cg = env.cg;
obj->rodata->do_count = env.count;

/* initialize global data (filtering options) */
if (!env.count) {
Expand Down Expand Up @@ -234,29 +247,10 @@ int main(int argc, char **argv)
}
}

if (env.count) {
obj->links.handle__irq_handler = bpf_program__attach(obj->progs.handle__irq_handler);
if (!obj->links.handle__irq_handler) {
err = -errno;
fprintf(stderr,
"failed to attach irq/irq_handler_entry: %s\n",
strerror(-err));
}
} else {
obj->links.irq_handler_entry = bpf_program__attach(obj->progs.irq_handler_entry);
if (!obj->links.irq_handler_entry) {
err = -errno;
fprintf(stderr,
"failed to attach irq_handler_entry: %s\n",
strerror(-err));
}
obj->links.irq_handler_exit_exit = bpf_program__attach(obj->progs.irq_handler_exit_exit);
if (!obj->links.irq_handler_exit_exit) {
err = -errno;
fprintf(stderr,
"failed to attach irq_handler_exit: %s\n",
strerror(-err));
}
err = hardirqs_bpf__attach(obj);
if (err) {
fprintf(stderr, "failed to attach BPF object: %d\n", err);
goto cleanup;
}

signal(SIGINT, sig_handler);
Expand Down

0 comments on commit fcd2187

Please sign in to comment.