1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include <vmlinux.h> |
3 | #include <bpf/bpf_helpers.h> |
4 | |
5 | #define TEST_STACK_DEPTH 2 |
6 | #define TEST_MAX_ENTRIES 16384 |
7 | |
8 | typedef __u64 stack_trace_t[TEST_STACK_DEPTH]; |
9 | |
10 | struct { |
11 | __uint(type, BPF_MAP_TYPE_STACK_TRACE); |
12 | __uint(max_entries, TEST_MAX_ENTRIES); |
13 | __type(key, __u32); |
14 | __type(value, stack_trace_t); |
15 | } stackmap SEC(".maps" ); |
16 | |
17 | struct { |
18 | __uint(type, BPF_MAP_TYPE_HASH); |
19 | __uint(max_entries, TEST_MAX_ENTRIES); |
20 | __type(key, __u32); |
21 | __type(value, __u32); |
22 | } stackid_hmap SEC(".maps" ); |
23 | |
24 | struct { |
25 | __uint(type, BPF_MAP_TYPE_ARRAY); |
26 | __uint(max_entries, TEST_MAX_ENTRIES); |
27 | __type(key, __u32); |
28 | __type(value, stack_trace_t); |
29 | } stack_amap SEC(".maps" ); |
30 | |
31 | int pid = 0; |
32 | int control = 0; |
33 | int failed = 0; |
34 | |
35 | SEC("tracepoint/sched/sched_switch" ) |
36 | int oncpu(struct trace_event_raw_sched_switch *ctx) |
37 | { |
38 | __u32 max_len = TEST_STACK_DEPTH * sizeof(__u64); |
39 | __u32 key = 0, val = 0; |
40 | __u64 *stack_p; |
41 | |
42 | if (pid != (bpf_get_current_pid_tgid() >> 32)) |
43 | return 0; |
44 | |
45 | if (control) |
46 | return 0; |
47 | |
48 | /* it should allow skipping whole buffer size entries */ |
49 | key = bpf_get_stackid(ctx, &stackmap, TEST_STACK_DEPTH); |
50 | if ((int)key >= 0) { |
51 | /* The size of stackmap and stack_amap should be the same */ |
52 | bpf_map_update_elem(&stackid_hmap, &key, &val, 0); |
53 | stack_p = bpf_map_lookup_elem(&stack_amap, &key); |
54 | if (stack_p) { |
55 | bpf_get_stack(ctx, stack_p, max_len, TEST_STACK_DEPTH); |
56 | /* it wrongly skipped all the entries and filled zero */ |
57 | if (stack_p[0] == 0) |
58 | failed = 1; |
59 | } |
60 | } else { |
61 | /* old kernel doesn't support skipping that many entries */ |
62 | failed = 2; |
63 | } |
64 | |
65 | return 0; |
66 | } |
67 | |
68 | char _license[] SEC("license" ) = "GPL" ; |
69 | |