Back to home page

OSCL-LXR

 
 

    


0001 /* Copyright (c) 2016 Facebook
0002  *
0003  * This program is free software; you can redistribute it and/or
0004  * modify it under the terms of version 2 of the GNU General Public
0005  * License as published by the Free Software Foundation.
0006  */
0007 #include <linux/ptrace.h>
0008 #include <uapi/linux/bpf.h>
0009 #include <uapi/linux/bpf_perf_event.h>
0010 #include <uapi/linux/perf_event.h>
0011 #include <bpf/bpf_helpers.h>
0012 #include <bpf/bpf_tracing.h>
0013 
0014 struct key_t {
0015     char comm[TASK_COMM_LEN];
0016     u32 kernstack;
0017     u32 userstack;
0018 };
0019 
0020 struct {
0021     __uint(type, BPF_MAP_TYPE_HASH);
0022     __type(key, struct key_t);
0023     __type(value, u64);
0024     __uint(max_entries, 10000);
0025 } counts SEC(".maps");
0026 
0027 struct {
0028     __uint(type, BPF_MAP_TYPE_STACK_TRACE);
0029     __uint(key_size, sizeof(u32));
0030     __uint(value_size, PERF_MAX_STACK_DEPTH * sizeof(u64));
0031     __uint(max_entries, 10000);
0032 } stackmap SEC(".maps");
0033 
0034 #define KERN_STACKID_FLAGS (0 | BPF_F_FAST_STACK_CMP)
0035 #define USER_STACKID_FLAGS (0 | BPF_F_FAST_STACK_CMP | BPF_F_USER_STACK)
0036 
0037 SEC("perf_event")
0038 int bpf_prog1(struct bpf_perf_event_data *ctx)
0039 {
0040     char time_fmt1[] = "Time Enabled: %llu, Time Running: %llu";
0041     char time_fmt2[] = "Get Time Failed, ErrCode: %d";
0042     char addr_fmt[] = "Address recorded on event: %llx";
0043     char fmt[] = "CPU-%d period %lld ip %llx";
0044     u32 cpu = bpf_get_smp_processor_id();
0045     struct bpf_perf_event_value value_buf;
0046     struct key_t key;
0047     u64 *val, one = 1;
0048     int ret;
0049 
0050     if (ctx->sample_period < 10000)
0051         /* ignore warmup */
0052         return 0;
0053     bpf_get_current_comm(&key.comm, sizeof(key.comm));
0054     key.kernstack = bpf_get_stackid(ctx, &stackmap, KERN_STACKID_FLAGS);
0055     key.userstack = bpf_get_stackid(ctx, &stackmap, USER_STACKID_FLAGS);
0056     if ((int)key.kernstack < 0 && (int)key.userstack < 0) {
0057         bpf_trace_printk(fmt, sizeof(fmt), cpu, ctx->sample_period,
0058                  PT_REGS_IP(&ctx->regs));
0059         return 0;
0060     }
0061 
0062     ret = bpf_perf_prog_read_value(ctx, (void *)&value_buf, sizeof(struct bpf_perf_event_value));
0063     if (!ret)
0064       bpf_trace_printk(time_fmt1, sizeof(time_fmt1), value_buf.enabled, value_buf.running);
0065     else
0066       bpf_trace_printk(time_fmt2, sizeof(time_fmt2), ret);
0067 
0068     if (ctx->addr != 0)
0069       bpf_trace_printk(addr_fmt, sizeof(addr_fmt), ctx->addr);
0070 
0071     val = bpf_map_lookup_elem(&counts, &key);
0072     if (val)
0073         (*val)++;
0074     else
0075         bpf_map_update_elem(&counts, &key, &one, BPF_NOEXIST);
0076     return 0;
0077 }
0078 
0079 char _license[] SEC("license") = "GPL";