github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/gadgets/profile/cpu/tracer/bpf/profile.bpf.c (about) 1 /* SPDX-License-Identifier: BSD-2-Clause */ 2 /* Copyright (c) 2022 LG Electronics */ 3 #include <vmlinux.h> 4 #include <bpf/bpf_helpers.h> 5 #include <bpf/bpf_core_read.h> 6 #include <bpf/bpf_tracing.h> 7 #include "profile.h" 8 #include <gadget/maps.bpf.h> 9 #include <gadget/mntns_filter.h> 10 11 const volatile bool kernel_stacks_only = false; 12 const volatile bool user_stacks_only = false; 13 const volatile bool include_idle = false; 14 const volatile pid_t targ_pid = -1; 15 const volatile pid_t targ_tid = -1; 16 17 #define MAX_STACK_DEPTH 50 18 struct { 19 __uint(type, BPF_MAP_TYPE_STACK_TRACE); 20 __type(key, u32); 21 __uint(max_entries, 256); 22 __uint(value_size, MAX_STACK_DEPTH * sizeof(u64)); 23 } stackmap SEC(".maps"); 24 25 struct { 26 __uint(type, BPF_MAP_TYPE_HASH); 27 __type(key, struct key_t); 28 __type(value, sizeof(u64)); 29 __uint(max_entries, MAX_ENTRIES); 30 } counts SEC(".maps"); 31 32 /* 33 * If PAGE_OFFSET macro is not available in vmlinux.h, determine ip whose MSB 34 * (Most Significant Bit) is 1 as the kernel address. 35 * TODO: use end address of user space to determine the address space of ip 36 */ 37 #if defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) 38 #define BITS_PER_ADDR (64) 39 #define MSB_SET_ULONG (1UL << (BITS_PER_ADDR - 1)) 40 static __always_inline bool is_kernel_addr(u64 addr) 41 { 42 return !!(addr & MSB_SET_ULONG); 43 } 44 #else 45 static __always_inline bool is_kernel_addr(u64 addr) 46 { 47 return false; 48 } 49 #endif /* __TARGET_ARCH_arm64 || __TARGET_ARCH_x86 */ 50 51 SEC("perf_event") 52 int ig_prof_cpu(struct bpf_perf_event_data *ctx) 53 { 54 u64 id = bpf_get_current_pid_tgid(); 55 u32 pid = id >> 32; 56 u32 tid = id; 57 u64 *valp; 58 static const u64 zero; 59 struct key_t key = {}; 60 struct task_struct *task; 61 u64 mntns_id; 62 63 if (!include_idle && tid == 0) 64 return 0; 65 66 if (targ_pid != -1 && targ_pid != pid) 67 return 0; 68 if (targ_tid != -1 && targ_tid != tid) 69 return 0; 70 71 mntns_id = gadget_get_mntns_id(); 72 73 if (gadget_should_discard_mntns_id(mntns_id)) 74 return 0; 75 76 key.pid = pid; 77 key.mntns_id = mntns_id; 78 bpf_get_current_comm(&key.name, sizeof(key.name)); 79 80 if (user_stacks_only) 81 key.kern_stack_id = -1; 82 else 83 key.kern_stack_id = bpf_get_stackid(&ctx->regs, &stackmap, 0); 84 85 if (kernel_stacks_only) 86 key.user_stack_id = -1; 87 else 88 key.user_stack_id = bpf_get_stackid(&ctx->regs, &stackmap, 89 BPF_F_USER_STACK); 90 91 if (key.kern_stack_id >= 0) { 92 // populate extras to fix the kernel stack 93 u64 ip = PT_REGS_IP(&ctx->regs); 94 95 if (is_kernel_addr(ip)) { 96 key.kernel_ip = ip; 97 } 98 } 99 100 valp = bpf_map_lookup_or_try_init(&counts, &key, &zero); 101 if (valp) 102 __sync_fetch_and_add(valp, 1); 103 104 return 0; 105 } 106 107 char LICENSE[] SEC("license") = "GPL";