trace_event_kern.c 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /* Copyright (c) 2016 Facebook
  2. *
  3. * This program is free software; you can redistribute it and/or
  4. * modify it under the terms of version 2 of the GNU General Public
  5. * License as published by the Free Software Foundation.
  6. */
  7. #include <linux/ptrace.h>
  8. #include <linux/version.h>
  9. #include <uapi/linux/bpf.h>
  10. #include <uapi/linux/bpf_perf_event.h>
  11. #include <uapi/linux/perf_event.h>
  12. #include <bpf/bpf_helpers.h>
  13. #include <bpf/bpf_tracing.h>
  14. struct key_t {
  15. char comm[TASK_COMM_LEN];
  16. u32 kernstack;
  17. u32 userstack;
  18. };
  19. struct {
  20. __uint(type, BPF_MAP_TYPE_HASH);
  21. __type(key, struct key_t);
  22. __type(value, u64);
  23. __uint(max_entries, 10000);
  24. } counts SEC(".maps");
  25. struct {
  26. __uint(type, BPF_MAP_TYPE_STACK_TRACE);
  27. __uint(key_size, sizeof(u32));
  28. __uint(value_size, PERF_MAX_STACK_DEPTH * sizeof(u64));
  29. __uint(max_entries, 10000);
  30. } stackmap SEC(".maps");
  31. #define KERN_STACKID_FLAGS (0 | BPF_F_FAST_STACK_CMP)
  32. #define USER_STACKID_FLAGS (0 | BPF_F_FAST_STACK_CMP | BPF_F_USER_STACK)
  33. SEC("perf_event")
  34. int bpf_prog1(struct bpf_perf_event_data *ctx)
  35. {
  36. char time_fmt1[] = "Time Enabled: %llu, Time Running: %llu";
  37. char time_fmt2[] = "Get Time Failed, ErrCode: %d";
  38. char addr_fmt[] = "Address recorded on event: %llx";
  39. char fmt[] = "CPU-%d period %lld ip %llx";
  40. u32 cpu = bpf_get_smp_processor_id();
  41. struct bpf_perf_event_value value_buf;
  42. struct key_t key;
  43. u64 *val, one = 1;
  44. int ret;
  45. if (ctx->sample_period < 10000)
  46. /* ignore warmup */
  47. return 0;
  48. bpf_get_current_comm(&key.comm, sizeof(key.comm));
  49. key.kernstack = bpf_get_stackid(ctx, &stackmap, KERN_STACKID_FLAGS);
  50. key.userstack = bpf_get_stackid(ctx, &stackmap, USER_STACKID_FLAGS);
  51. if ((int)key.kernstack < 0 && (int)key.userstack < 0) {
  52. bpf_trace_printk(fmt, sizeof(fmt), cpu, ctx->sample_period,
  53. PT_REGS_IP(&ctx->regs));
  54. return 0;
  55. }
  56. ret = bpf_perf_prog_read_value(ctx, (void *)&value_buf, sizeof(struct bpf_perf_event_value));
  57. if (!ret)
  58. bpf_trace_printk(time_fmt1, sizeof(time_fmt1), value_buf.enabled, value_buf.running);
  59. else
  60. bpf_trace_printk(time_fmt2, sizeof(time_fmt2), ret);
  61. if (ctx->addr != 0)
  62. bpf_trace_printk(addr_fmt, sizeof(addr_fmt), ctx->addr);
  63. val = bpf_map_lookup_elem(&counts, &key);
  64. if (val)
  65. (*val)++;
  66. else
  67. bpf_map_update_elem(&counts, &key, &one, BPF_NOEXIST);
  68. return 0;
  69. }
  70. char _license[] SEC("license") = "GPL";