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";