perf kwork: Add IRQ trace BPF support

Implements irq trace bpf function.

Test cases:
Trace irq without filter:

  # perf kwork -k irq rep -b
  Starting trace, Hit <Ctrl+C> to stop and report
  ^C
    Kwork Name                     | Cpu  | Total Runtime | Count     | Max runtime   | Max runtime start   | Max runtime end     |
   --------------------------------------------------------------------------------------------------------------------------------
    virtio0-requests:25            | 0000 |     31.026 ms |       285 |      1.493 ms |     110326.049963 s |     110326.051456 s |
    eth0:10                        | 0002 |      7.875 ms |        96 |      1.429 ms |     110313.916835 s |     110313.918264 s |
    ata_piix:14                    | 0002 |      2.510 ms |        28 |      0.396 ms |     110331.367987 s |     110331.368383 s |
   --------------------------------------------------------------------------------------------------------------------------------

Trace irq with cpu filter:

  # perf kwork -k irq rep -b -C 0
  Starting trace, Hit <Ctrl+C> to stop and report
  ^C
    Kwork Name                     | Cpu  | Total Runtime | Count     | Max runtime   | Max runtime start   | Max runtime end     |
   --------------------------------------------------------------------------------------------------------------------------------
    virtio0-requests:25            | 0000 |     34.288 ms |       282 |      2.061 ms |     110358.078968 s |     110358.081029 s |
   --------------------------------------------------------------------------------------------------------------------------------

Trace irq with name filter:

  # perf kwork -k irq rep -b -n eth0
  Starting trace, Hit <Ctrl+C> to stop and report
  ^C
    Kwork Name                     | Cpu  | Total Runtime | Count     | Max runtime   | Max runtime start   | Max runtime end     |
   --------------------------------------------------------------------------------------------------------------------------------
    eth0:10                        | 0002 |      2.184 ms |        21 |      0.572 ms |     110386.541699 s |     110386.542271 s |
   --------------------------------------------------------------------------------------------------------------------------------

Trace irq with summary:

  # perf kwork -k irq rep -b -S
  Starting trace, Hit <Ctrl+C> to stop and report
  ^C
    Kwork Name                     | Cpu  | Total Runtime | Count     | Max runtime   | Max runtime start   | Max runtime end     |
   --------------------------------------------------------------------------------------------------------------------------------
    virtio0-requests:25            | 0000 |     42.923 ms |       285 |      1.181 ms |     110418.128867 s |     110418.130049 s |
    eth0:10                        | 0002 |      2.085 ms |        20 |      0.668 ms |     110416.002935 s |     110416.003603 s |
    ata_piix:14                    | 0002 |      0.970 ms |         4 |      0.656 ms |     110424.034482 s |     110424.035138 s |
   --------------------------------------------------------------------------------------------------------------------------------
    Total count            :       309
    Total runtime   (msec) :    45.977 (0.003% load average)
    Total time span (msec) : 17017.655
   --------------------------------------------------------------------------------------------------------------------------------

Committer testing:

  # perf kwork -k irq rep -b
  Starting trace, Hit <Ctrl+C> to stop and report
  ^C
    Kwork Name                     | Cpu  | Total Runtime | Count     | Max runtime   | Max runtime start   | Max runtime end     |
   --------------------------------------------------------------------------------------------------------------------------------
    nvme0q20:145                   | 0019 |      0.570 ms |        28 |      0.064 ms |      26966.635102 s |      26966.635167 s |
    amdgpu:162                     | 0002 |      0.568 ms |        29 |      0.068 ms |      26966.644346 s |      26966.644414 s |
    nvme0q4:129                    | 0003 |      0.565 ms |        31 |      0.037 ms |      26966.614830 s |      26966.614866 s |
    nvme0q16:141                   | 0015 |      0.205 ms |        66 |      0.012 ms |      26967.145161 s |      26967.145174 s |
    nvme0q29:154                   | 0028 |      0.154 ms |        44 |      0.014 ms |      26967.078970 s |      26967.078984 s |
    nvme0q10:135                   | 0009 |      0.134 ms |        43 |      0.011 ms |      26967.132093 s |      26967.132104 s |
    nvme0q2:127                    | 0001 |      0.132 ms |        26 |      0.011 ms |      26966.883584 s |      26966.883595 s |
    nvme0q25:150                   | 0024 |      0.127 ms |        32 |      0.014 ms |      26966.631419 s |      26966.631433 s |
    nvme0q14:139                   | 0013 |      0.110 ms |        21 |      0.017 ms |      26966.760843 s |      26966.760861 s |
    nvme0q30:155                   | 0029 |      0.102 ms |        30 |      0.022 ms |      26966.677171 s |      26966.677193 s |
    nvme0q13:138                   | 0012 |      0.088 ms |        20 |      0.015 ms |      26966.738733 s |      26966.738748 s |
    nvme0q6:131                    | 0005 |      0.087 ms |        13 |      0.020 ms |      26966.648445 s |      26966.648465 s |
    nvme0q28:153                   | 0027 |      0.066 ms |        12 |      0.015 ms |      26966.771431 s |      26966.771447 s |
    nvme0q26:151                   | 0025 |      0.060 ms |        13 |      0.012 ms |      26966.704266 s |      26966.704278 s |
    nvme0q21:146                   | 0020 |      0.054 ms |        20 |      0.011 ms |      26967.322082 s |      26967.322094 s |
    nvme0q1:126                    | 0000 |      0.046 ms |        11 |      0.013 ms |      26966.859754 s |      26966.859767 s |
    nvme0q17:142                   | 0016 |      0.046 ms |        10 |      0.011 ms |      26967.114513 s |      26967.114524 s |
    xhci_hcd:74                    | 0015 |      0.041 ms |         3 |      0.016 ms |      26967.086004 s |      26967.086020 s |
    nvme0q8:133                    | 0007 |      0.039 ms |        12 |      0.008 ms |      26966.712056 s |      26966.712063 s |
    nvme0q32:157                   | 0031 |      0.036 ms |        10 |      0.014 ms |      26966.627054 s |      26966.627068 s |
    nvme0q9:134                    | 0008 |      0.036 ms |        11 |      0.011 ms |      26967.258452 s |      26967.258462 s |
    nvme0q7:132                    | 0006 |      0.024 ms |         3 |      0.014 ms |      26966.767404 s |      26966.767418 s |
    nvme0q11:136                   | 0010 |      0.023 ms |         5 |      0.006 ms |      26966.935455 s |      26966.935461 s |
    nvme0q31:156                   | 0030 |      0.018 ms |         5 |      0.006 ms |      26966.627517 s |      26966.627524 s |
    nvme0q12:137                   | 0011 |      0.015 ms |         2 |      0.014 ms |      26966.799588 s |      26966.799602 s |
    enp5s0-rx-0:164                | 0006 |      0.009 ms |         2 |      0.005 ms |      26966.742024 s |      26966.742028 s |
    enp5s0-rx-1:165                | 0007 |      0.006 ms |         2 |      0.004 ms |      26966.939486 s |      26966.939490 s |
    enp5s0-tx-0:166                | 0008 |      0.005 ms |         1 |      0.005 ms |      26966.939484 s |      26966.939489 s |
    enp5s0-tx-1:167                | 0009 |      0.005 ms |         1 |      0.005 ms |      26966.939484 s |      26966.939489 s |
   --------------------------------------------------------------------------------------------------------------------------------

  #t

Signed-off-by: Yang Jihong <yangjihong1@huawei.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Clarke <pc@us.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20220709015033.38326-16-yangjihong1@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Yang Jihong 2022-07-09 09:50:31 +08:00 коммит произвёл Arnaldo Carvalho de Melo
Родитель daf07d2207
Коммит 420298aefe
2 изменённых файлов: 187 добавлений и 1 удалений

Просмотреть файл

@ -62,9 +62,45 @@ void perf_kwork__trace_finish(void)
skel->bss->enabled = 0;
}
static int get_work_name_from_map(struct work_key *key, char **ret_name)
{
char name[MAX_KWORKNAME] = { 0 };
int fd = bpf_map__fd(skel->maps.perf_kwork_names);
*ret_name = NULL;
if (fd < 0) {
pr_debug("Invalid names map fd\n");
return 0;
}
if ((bpf_map_lookup_elem(fd, key, name) == 0) && (strlen(name) != 0)) {
*ret_name = strdup(name);
if (*ret_name == NULL) {
pr_err("Failed to copy work name\n");
return -1;
}
}
return 0;
}
static void irq_load_prepare(struct perf_kwork *kwork)
{
if (kwork->report == KWORK_REPORT_RUNTIME) {
bpf_program__set_autoload(skel->progs.report_irq_handler_entry, true);
bpf_program__set_autoload(skel->progs.report_irq_handler_exit, true);
}
}
static struct kwork_class_bpf kwork_irq_bpf = {
.load_prepare = irq_load_prepare,
.get_work_name = get_work_name_from_map,
};
static struct kwork_class_bpf *
kwork_class_bpf_supported_list[KWORK_CLASS_MAX] = {
[KWORK_CLASS_IRQ] = NULL,
[KWORK_CLASS_IRQ] = &kwork_irq_bpf,
[KWORK_CLASS_SOFTIRQ] = NULL,
[KWORK_CLASS_WORKQUEUE] = NULL,
};

Просмотреть файл

@ -71,4 +71,154 @@ int enabled = 0;
int has_cpu_filter = 0;
int has_name_filter = 0;
static __always_inline int local_strncmp(const char *s1,
unsigned int sz, const char *s2)
{
int ret = 0;
unsigned int i;
for (i = 0; i < sz; i++) {
ret = (unsigned char)s1[i] - (unsigned char)s2[i];
if (ret || !s1[i] || !s2[i])
break;
}
return ret;
}
static __always_inline int trace_event_match(struct work_key *key, char *name)
{
__u8 *cpu_val;
char *name_val;
__u32 zero = 0;
__u32 cpu = bpf_get_smp_processor_id();
if (!enabled)
return 0;
if (has_cpu_filter) {
cpu_val = bpf_map_lookup_elem(&perf_kwork_cpu_filter, &cpu);
if (!cpu_val)
return 0;
}
if (has_name_filter && (name != NULL)) {
name_val = bpf_map_lookup_elem(&perf_kwork_name_filter, &zero);
if (name_val &&
(local_strncmp(name_val, MAX_KWORKNAME, name) != 0)) {
return 0;
}
}
return 1;
}
static __always_inline void do_update_time(void *map, struct work_key *key,
__u64 time_start, __u64 time_end)
{
struct report_data zero, *data;
__s64 delta = time_end - time_start;
if (delta < 0)
return;
data = bpf_map_lookup_elem(map, key);
if (!data) {
__builtin_memset(&zero, 0, sizeof(zero));
bpf_map_update_elem(map, key, &zero, BPF_NOEXIST);
data = bpf_map_lookup_elem(map, key);
if (!data)
return;
}
if ((delta > data->max_time) ||
(data->max_time == 0)) {
data->max_time = delta;
data->max_time_start = time_start;
data->max_time_end = time_end;
}
data->total_time += delta;
data->nr++;
}
static __always_inline void do_update_timestart(void *map, struct work_key *key)
{
__u64 ts = bpf_ktime_get_ns();
bpf_map_update_elem(map, key, &ts, BPF_ANY);
}
static __always_inline void do_update_timeend(void *report_map, void *time_map,
struct work_key *key)
{
__u64 *time = bpf_map_lookup_elem(time_map, key);
if (time) {
bpf_map_delete_elem(time_map, key);
do_update_time(report_map, key, *time, bpf_ktime_get_ns());
}
}
static __always_inline void do_update_name(void *map,
struct work_key *key, char *name)
{
if (!bpf_map_lookup_elem(map, key))
bpf_map_update_elem(map, key, name, BPF_ANY);
}
static __always_inline int update_timestart_and_name(void *time_map,
void *names_map,
struct work_key *key,
char *name)
{
if (!trace_event_match(key, name))
return 0;
do_update_timestart(time_map, key);
do_update_name(names_map, key, name);
return 0;
}
static __always_inline int update_timeend(void *report_map,
void *time_map, struct work_key *key)
{
if (!trace_event_match(key, NULL))
return 0;
do_update_timeend(report_map, time_map, key);
return 0;
}
SEC("tracepoint/irq/irq_handler_entry")
int report_irq_handler_entry(struct trace_event_raw_irq_handler_entry *ctx)
{
char name[MAX_KWORKNAME];
struct work_key key = {
.type = KWORK_CLASS_IRQ,
.cpu = bpf_get_smp_processor_id(),
.id = (__u64)ctx->irq,
};
void *name_addr = (void *)ctx + (ctx->__data_loc_name & 0xffff);
bpf_probe_read_kernel_str(name, sizeof(name), name_addr);
return update_timestart_and_name(&perf_kwork_time,
&perf_kwork_names, &key, name);
}
SEC("tracepoint/irq/irq_handler_exit")
int report_irq_handler_exit(struct trace_event_raw_irq_handler_exit *ctx)
{
struct work_key key = {
.type = KWORK_CLASS_IRQ,
.cpu = bpf_get_smp_processor_id(),
.id = (__u64)ctx->irq,
};
return update_timeend(&perf_kwork_report, &perf_kwork_time, &key);
}
char LICENSE[] SEC("license") = "Dual BSD/GPL";