lathist_kern.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com
  2. * Copyright (c) 2015 BMW Car IT GmbH
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of version 2 of the GNU General Public
  6. * License as published by the Free Software Foundation.
  7. */
  8. #include <linux/version.h>
  9. #include <linux/ptrace.h>
  10. #include <uapi/linux/bpf.h>
  11. #include <bpf/bpf_helpers.h>
  12. #define MAX_ENTRIES 20
  13. #define MAX_CPU 4
  14. /* We need to stick to static allocated memory (an array instead of
  15. * hash table) because managing dynamic memory from the
  16. * trace_preempt_[on|off] tracepoints hooks is not supported.
  17. */
  18. struct {
  19. __uint(type, BPF_MAP_TYPE_ARRAY);
  20. __type(key, int);
  21. __type(value, u64);
  22. __uint(max_entries, MAX_CPU);
  23. } my_map SEC(".maps");
  24. SEC("kprobe/trace_preempt_off")
  25. int bpf_prog1(struct pt_regs *ctx)
  26. {
  27. int cpu = bpf_get_smp_processor_id();
  28. u64 *ts = bpf_map_lookup_elem(&my_map, &cpu);
  29. if (ts)
  30. *ts = bpf_ktime_get_ns();
  31. return 0;
  32. }
  33. static unsigned int log2(unsigned int v)
  34. {
  35. unsigned int r;
  36. unsigned int shift;
  37. r = (v > 0xFFFF) << 4; v >>= r;
  38. shift = (v > 0xFF) << 3; v >>= shift; r |= shift;
  39. shift = (v > 0xF) << 2; v >>= shift; r |= shift;
  40. shift = (v > 0x3) << 1; v >>= shift; r |= shift;
  41. r |= (v >> 1);
  42. return r;
  43. }
  44. static unsigned int log2l(unsigned long v)
  45. {
  46. unsigned int hi = v >> 32;
  47. if (hi)
  48. return log2(hi) + 32;
  49. else
  50. return log2(v);
  51. }
  52. struct {
  53. __uint(type, BPF_MAP_TYPE_ARRAY);
  54. __type(key, int);
  55. __type(value, long);
  56. __uint(max_entries, MAX_CPU * MAX_ENTRIES);
  57. } my_lat SEC(".maps");
  58. SEC("kprobe/trace_preempt_on")
  59. int bpf_prog2(struct pt_regs *ctx)
  60. {
  61. u64 *ts, cur_ts, delta;
  62. int key, cpu;
  63. long *val;
  64. cpu = bpf_get_smp_processor_id();
  65. ts = bpf_map_lookup_elem(&my_map, &cpu);
  66. if (!ts)
  67. return 0;
  68. cur_ts = bpf_ktime_get_ns();
  69. delta = log2l(cur_ts - *ts);
  70. if (delta > MAX_ENTRIES - 1)
  71. delta = MAX_ENTRIES - 1;
  72. key = cpu * MAX_ENTRIES + delta;
  73. val = bpf_map_lookup_elem(&my_lat, &key);
  74. if (val)
  75. __sync_fetch_and_add((long *)val, 1);
  76. return 0;
  77. }
  78. char _license[] SEC("license") = "GPL";
  79. u32 _version SEC("version") = LINUX_VERSION_CODE;