diff --git a/libbpf-tools/hardirqs.bpf.c b/libbpf-tools/hardirqs.bpf.c index cbcbd5c0515..11eb3f25c65 100644 --- a/libbpf-tools/hardirqs.bpf.c +++ b/libbpf-tools/hardirqs.bpf.c @@ -14,6 +14,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; +const volatile int targ_cpu = -1; struct { __uint(type, BPF_MAP_TYPE_CGROUP_ARRAY); @@ -38,10 +39,19 @@ struct { static struct info zero; +static __always_inline bool is_target_cpu() { + if (targ_cpu < 0) + return true; + + return targ_cpu == bpf_get_smp_processor_id(); +} + static int handle_entry(int irq, struct irqaction *action) { if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0)) return 0; + if (!is_target_cpu()) + return 0; if (do_count) { struct irq_key key = {}; @@ -76,6 +86,9 @@ static int handle_exit(int irq, struct irqaction *action) if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0)) return 0; + if (!is_target_cpu()) + return 0; + tsp = bpf_map_lookup_elem(&start, &key); if (!tsp) return 0; diff --git a/libbpf-tools/hardirqs.c b/libbpf-tools/hardirqs.c index b5257d95089..f783b9e5e2a 100644 --- a/libbpf-tools/hardirqs.c +++ b/libbpf-tools/hardirqs.c @@ -27,9 +27,11 @@ struct env { bool verbose; char *cgroupspath; bool cg; + int targ_cpu; } env = { .interval = 99999999, .times = 99999999, + .targ_cpu = -1, }; static volatile bool exiting; @@ -47,12 +49,14 @@ const char argp_program_doc[] = " hardirqs -d # show hard irq event time as histograms\n" " hardirqs 1 10 # print 1 second summaries, 10 times\n" " hardirqs -c CG # Trace process under cgroupsPath CG\n" +" hardirqs --cpu 1 # only stat irq on cpu 1\n" " hardirqs -NT 1 # 1s summaries, nanoseconds, and timestamps\n"; static const struct argp_option opts[] = { { "count", 'C', NULL, 0, "Show event counts instead of timing", 0 }, { "distributed", 'd', NULL, 0, "Show distributions as histograms", 0 }, { "cgroup", 'c', "/sys/fs/cgroup/unified", 0, "Trace process in cgroup path", 0 }, + { "cpu", 's', "CPU", 0, "Only stat irq on selected cpu", 0 }, { "timestamp", 'T', NULL, 0, "Include timestamp on output", 0 }, { "nanoseconds", 'N', NULL, 0, "Output in nanoseconds", 0 }, { "verbose", 'v', NULL, 0, "Verbose debug output", 0 }, @@ -77,6 +81,14 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) case 'C': env.count = true; break; + case 's': + errno = 0; + env.targ_cpu = atoi(arg); + if (errno || env.targ_cpu < 0) { + fprintf(stderr, "invalid cpu: %s\n", arg); + argp_usage(state); + } + break; case 'c': env.cgroupspath = arg; env.cg = true; @@ -218,6 +230,7 @@ int main(int argc, char **argv) obj->rodata->filter_cg = env.cg; obj->rodata->do_count = env.count; + obj->rodata->targ_cpu = env.targ_cpu; /* initialize global data (filtering options) */ if (!env.count) {