-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Eunseon Lee <[email protected]>
- Loading branch information
Showing
4 changed files
with
590 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
// Copyright (c) 2021 Wenbo Zhang | ||
#include <vmlinux.h> | ||
#include <bpf/bpf_helpers.h> | ||
#include <bpf/bpf_core_read.h> | ||
#include <bpf/bpf_tracing.h> | ||
#include "profile.h" | ||
|
||
#define PF_KTHREAD 0x00200000 /* I am a kernel thread */ | ||
#define MAX_ENTRIES 10240 | ||
|
||
const volatile bool kernel_stacks_only = false; | ||
const volatile bool user_stacks_only = false; | ||
const volatile bool include_idle = false; | ||
const volatile pid_t targ_tgid = -1; | ||
const volatile pid_t targ_pid = -1; | ||
|
||
struct { | ||
__uint(type, BPF_MAP_TYPE_STACK_TRACE); | ||
__uint(key_size, sizeof(u32)); | ||
} stackmap SEC(".maps"); | ||
|
||
struct { | ||
__uint(type, BPF_MAP_TYPE_HASH); | ||
__type(key, struct key_t); | ||
__type(value, sizeof(u64)); | ||
__uint(max_entries, MAX_ENTRIES); | ||
} counts SEC(".maps"); | ||
|
||
SEC("perf_event") | ||
int do_perf_event(struct bpf_perf_event_data *ctx) { | ||
u64 id = bpf_get_current_pid_tgid(); | ||
u32 tgid = id >> 32; | ||
u32 pid = id; | ||
u32 *valp, val; | ||
|
||
if (include_idle == false && pid == 0) | ||
return 0; | ||
|
||
if (targ_tgid != -1 && targ_tgid != tgid) | ||
return 0; | ||
if (targ_pid != -1 && targ_pid != pid) | ||
return 0; | ||
|
||
if (container_should_be_filtered()) { | ||
return 0; | ||
} | ||
|
||
// create map key | ||
struct key_t key = {.pid = tgid}; | ||
bpf_get_current_comm(&key.name, sizeof(key.name)); | ||
|
||
if (user_stacks_only) | ||
key.kern_stack_id = -1; | ||
else | ||
key.kern_stack_id = bpf_get_stackid(ctx, &stackmap, 0); | ||
|
||
if (kernel_stacks_only) | ||
key.user_stack_id = -1; | ||
else | ||
key.user_stack_id = bpf_get_stackid(ctx, &stackmap, BPF_F_USER_STACK); | ||
|
||
if (key.kern_stack_id >= 0) { | ||
// populate extras to fix the kernel stack | ||
u64 ip = PT_REGS_IP(&ctx->regs); | ||
u64 page_offset; | ||
|
||
// if ip isn't sane, leave key ips as zero for later checking | ||
#if defined(CONFIG_X86_64) && defined(__PAGE_OFFSET_BASE) | ||
// x64, 4.16, ..., 4.11, etc., but some earlier kernel didn't have it | ||
page_offset = __PAGE_OFFSET_BASE; | ||
#elif defined(CONFIG_X86_64) && defined(__PAGE_OFFSET_BASE_L4) | ||
// x64, 4.17, and later | ||
#if defined(CONFIG_DYNAMIC_MEMORY_LAYOUT) && defined(CONFIG_X86_5LEVEL) | ||
page_offset = __PAGE_OFFSET_BASE_L5; | ||
#else | ||
page_offset = __PAGE_OFFSET_BASE_L4; | ||
#endif | ||
#else | ||
// earlier x86_64 kernels, e.g., 4.6, comes here | ||
// arm64, s390, powerpc, x86_32 | ||
|
||
page_offset = PAGE_OFFSET; | ||
#endif | ||
|
||
if (ip > page_offset) { | ||
key.kernel_ip = ip; | ||
} | ||
} | ||
|
||
valp = bpf_map_lookup_elem(&counts, &key); | ||
val = 1; | ||
if (!valp) | ||
bpf_map_update_elem(&counts, &key, &val, BPF_OK); | ||
else | ||
__sync_fetch_and_add(&valp, &val); | ||
return 0; | ||
} | ||
|
||
char LICENSE[] SEC("license") = "GPL"; |
Oops, something went wrong.