diff --git a/tools/ebpf/lcore_monitor.c b/tools/ebpf/lcore_monitor.c index 2f7060d21..3bebbaabf 100644 --- a/tools/ebpf/lcore_monitor.c +++ b/tools/ebpf/lcore_monitor.c @@ -22,7 +22,8 @@ struct lcore_monitor_ctx { char bpf_prog[64]; struct lcore_tid_cfg cfg; - struct lcore_tid_event out; + struct lcore_tid_event sched_out; + struct lcore_tid_event irq_entry; }; enum lm_args_cmd { @@ -132,19 +133,30 @@ static int lm_event_handler(void* pri, void* data, size_t data_sz) { dbg("%s: type %d, ns %" PRIu64 "\n", __func__, e->type, e->ns); if (e->type == LCORE_SCHED_OUT) { - memcpy(&ctx->out, e, sizeof(ctx->out)); - dbg("%s: out ns %" PRIu64 "\n", __func__, ctx->out.ns); + memcpy(&ctx->sched_out, e, sizeof(ctx->sched_out)); + dbg("%s: out ns %" PRIu64 "\n", __func__, ctx->sched_out.ns); return 0; } if (e->type == LCORE_SCHED_IN) { - float ns = e->ns - ctx->out.ns; - int next_pid = ctx->out.next_pid; + float ns = e->ns - ctx->sched_out.ns; + int next_pid = ctx->sched_out.next_pid; char process_name[64]; get_process_name_by_pid(next_pid, process_name, sizeof(process_name)); info("%s: sched out %.3fus as comm: %s\n", __func__, ns / 1000, process_name); } + if (e->type == LCORE_IRQ_ENTRY) { + memcpy(&ctx->irq_entry, e, sizeof(ctx->irq_entry)); + dbg("%s: irq_entry ns %" PRIu64 "\n", __func__, ctx->irq_entry.ns); + return 0; + } + + if (e->type == LCORE_IRQ_EXIT) { + float ns = e->ns - ctx->irq_entry.ns; + info("%s: sched out %.3fus as irq: %d\n", __func__, ns / 1000, ctx->irq_entry.irq); + } + return 0; } @@ -194,15 +206,39 @@ int main(int argc, char** argv) { return -1; } + /* attach bpf_prog_sched_switch */ prog = bpf_object__find_program_by_name(obj, "bpf_prog_sched_switch"); if (!prog) { - err("%s, finding BPF program failed\n", __func__); + err("%s, finding bpf_prog_sched_switch failed\n", __func__); return -1; } - link = bpf_program__attach_tracepoint(prog, "sched", "sched_switch"); if (libbpf_get_error(link)) { - err("%s, attaching BPF program to tracepoint failed\n", __func__); + err("%s, attaching bpf_prog_sched_switch to tracepoint failed\n", __func__); + return -1; + } + + /* attach bpf_prog_irq_handler_entry */ + prog = bpf_object__find_program_by_name(obj, "bpf_prog_irq_handler_entry"); + if (!prog) { + err("%s, finding bpf_prog_irq_handler_entry failed\n", __func__); + return -1; + } + link = bpf_program__attach_tracepoint(prog, "irq", "irq_handler_entry"); + if (libbpf_get_error(link)) { + err("%s, attaching bpf_prog_irq_handler_entry to tracepoint failed\n", __func__); + return -1; + } + + /* attach bpf_prog_irq_handler_exit */ + prog = bpf_object__find_program_by_name(obj, "bpf_prog_irq_handler_exit"); + if (!prog) { + err("%s, finding bpf_prog_irq_handler_exit failed\n", __func__); + return -1; + } + link = bpf_program__attach_tracepoint(prog, "irq", "irq_handler_exit"); + if (libbpf_get_error(link)) { + err("%s, attaching bpf_prog_irq_handler_exit to tracepoint failed\n", __func__); return -1; } diff --git a/tools/ebpf/lcore_monitor.h b/tools/ebpf/lcore_monitor.h index 308fd4d40..7ebd76382 100644 --- a/tools/ebpf/lcore_monitor.h +++ b/tools/ebpf/lcore_monitor.h @@ -12,14 +12,23 @@ struct lcore_tid_cfg { }; enum lcore_tid_event_type { - LCORE_SCHED_IN, - LCORE_SCHED_OUT, + /* hook on tracepoint/sched/sched_switch */ + LCORE_SCHED_IN, /* the t_pid was scheduled in */ + LCORE_SCHED_OUT, /* the t_pid was scheduled out */ + /* note: irq hook is only for io interrupt, not for system irq like timer */ + /* hook on tracepoint/irq/irq_handler_entry */ + LCORE_IRQ_ENTRY, + /* hook on tracepoint/irq/irq_handler_exit */ + LCORE_IRQ_EXIT, }; struct lcore_tid_event { enum lcore_tid_event_type type; uint64_t ns; - int next_pid; + union { + int next_pid; /* for LCORE_SCHED_IN/LCORE_SCHED_OUT */ + int irq; /* for LCORE_IRQ_ENTRY/LCORE_IRQ_EXIT */ + }; }; #endif \ No newline at end of file diff --git a/tools/ebpf/lcore_monitor_kern.c b/tools/ebpf/lcore_monitor_kern.c index ab10c96aa..793a2f883 100644 --- a/tools/ebpf/lcore_monitor_kern.c +++ b/tools/ebpf/lcore_monitor_kern.c @@ -23,8 +23,15 @@ struct { __uint(max_entries, 512 * 1024); } lm_events_map SEC(".maps"); -static int lm_event_submit(enum lcore_tid_event_type type, - struct trace_event_raw_sched_switch* args) { +static struct lcore_tid_cfg* lm_get_cfg(void) { + struct lcore_tid_cfg* cfg; + uint32_t key = 0; + cfg = bpf_map_lookup_elem(&lm_cfg_map, &key); + return cfg; +} + +static int lm_switch_event_submit(enum lcore_tid_event_type type, + struct trace_event_raw_sched_switch* args) { struct lcore_tid_event* e; e = bpf_ringbuf_reserve(&lm_events_map, sizeof(*e), 0); @@ -44,26 +51,80 @@ static int lm_event_submit(enum lcore_tid_event_type type, SEC("tracepoint/sched/sched_switch") int bpf_prog_sched_switch(struct trace_event_raw_sched_switch* args) { - uint32_t key = 0; - struct lcore_tid_cfg* cfg = bpf_map_lookup_elem(&lm_cfg_map, &key); + struct lcore_tid_cfg* cfg = lm_get_cfg(); if (!cfg) return 0; /* core id check */ if (bpf_get_smp_processor_id() != cfg->core_id) return 0; if (cfg->bpf_trace) { - char fmt[] = "prev_pid %d next_pid in\n"; + char fmt[] = "sched_switch: prev_pid %d next_pid in\n"; bpf_trace_printk(fmt, sizeof(fmt), args->prev_pid, args->next_pid); } if (args->prev_pid == cfg->t_pid) { - lm_event_submit(LCORE_SCHED_OUT, args); + lm_switch_event_submit(LCORE_SCHED_OUT, args); } if (args->next_pid == cfg->t_pid) { - lm_event_submit(LCORE_SCHED_IN, args); + lm_switch_event_submit(LCORE_SCHED_IN, args); + } + + return 0; +} + +static int lm_irq_event_submit(enum lcore_tid_event_type type, + struct trace_event_raw_irq_handler_entry* args) { + struct lcore_tid_event* e; + + e = bpf_ringbuf_reserve(&lm_events_map, sizeof(*e), 0); + if (!e) { + char fmt[] = "lm event ringbuf reserve fail\n"; + bpf_trace_printk(fmt, sizeof(fmt)); + return 0; + } + + e->type = type; + e->ns = bpf_ktime_get_ns(); + e->irq = args->irq; + + bpf_ringbuf_submit(e, 0); + return 0; +} + +SEC("tracepoint/irq/irq_handler_entry") +int bpf_prog_irq_handler_entry(struct trace_event_raw_irq_handler_entry* args) { + struct lcore_tid_cfg* cfg = lm_get_cfg(); + if (!cfg) return 0; + + /* core id check */ + if (bpf_get_smp_processor_id() != cfg->core_id) return 0; + + if (cfg->bpf_trace) { + char fmt[] = "irq_handler_entry, irq %d\n"; + bpf_trace_printk(fmt, sizeof(fmt), args->irq); + } + + lm_irq_event_submit(LCORE_IRQ_ENTRY, args); + + return 0; +} + +SEC("tracepoint/irq/irq_handler_exit") +int bpf_prog_irq_handler_exit(struct trace_event_raw_irq_handler_entry* args) { + struct lcore_tid_cfg* cfg = lm_get_cfg(); + if (!cfg) return 0; + + /* core id check */ + if (bpf_get_smp_processor_id() != cfg->core_id) return 0; + + if (cfg->bpf_trace) { + char fmt[] = "irq_handler_exit, irq %d\n"; + bpf_trace_printk(fmt, sizeof(fmt), args->irq); } + lm_irq_event_submit(LCORE_IRQ_EXIT, args); + return 0; }