1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */ 3 4 #include <vmlinux.h> 5 #include <bpf/bpf_helpers.h> 6 #include "bpf_kfuncs.h" 7 #include "../test_kmods/bpf_testmod_kfunc.h" 8 9 #if defined(__TARGET_ARCH_x86) && defined(__BPF_FEATURE_STACK_ARGUMENT) 10 11 const volatile bool has_stack_arg = true; 12 13 struct bpf_iter_testmod_seq { 14 u64 :64; 15 u64 :64; 16 }; 17 18 extern int bpf_iter_testmod_seq_new(struct bpf_iter_testmod_seq *it, s64 value, int cnt) __ksym; 19 extern void bpf_iter_testmod_seq_destroy(struct bpf_iter_testmod_seq *it) __ksym; 20 21 struct timer_map_value { 22 struct bpf_timer timer; 23 }; 24 25 struct { 26 __uint(type, BPF_MAP_TYPE_ARRAY); 27 __uint(max_entries, 1); 28 __type(key, int); 29 __type(value, struct timer_map_value); 30 } kfunc_timer_map SEC(".maps"); 31 32 SEC("tc") 33 int test_stack_arg_scalar(struct __sk_buff *skb) 34 { 35 return bpf_kfunc_call_stack_arg(1, 2, 3, 4, 5, 6, 7, 8); 36 } 37 38 SEC("tc") 39 int test_stack_arg_ptr(struct __sk_buff *skb) 40 { 41 struct prog_test_pass1 p = { .x0 = 10, .x1 = 20 }; 42 43 return bpf_kfunc_call_stack_arg_ptr(1, 2, 3, 4, 5, &p); 44 } 45 46 SEC("tc") 47 int test_stack_arg_mix(struct __sk_buff *skb) 48 { 49 struct prog_test_pass1 p = { .x0 = 10 }; 50 struct prog_test_pass1 q = { .x1 = 20 }; 51 52 return bpf_kfunc_call_stack_arg_mix(1, 2, 3, 4, 5, &p, 6, &q); 53 } 54 55 /* 1 + 2 + 3 + 4 + 5 + sizeof(pkt_v4) = 15 + 54 = 69 */ 56 SEC("tc") 57 int test_stack_arg_dynptr(struct __sk_buff *skb) 58 { 59 struct bpf_dynptr ptr; 60 61 bpf_dynptr_from_skb(skb, 0, &ptr); 62 return bpf_kfunc_call_stack_arg_dynptr(1, 2, 3, 4, 5, &ptr); 63 } 64 65 /* 1 + 2 + 3 + 4 + 5 + (1 + 2 + ... + 16) = 15 + 136 = 151 */ 66 SEC("tc") 67 int test_stack_arg_mem(struct __sk_buff *skb) 68 { 69 char buf[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; 70 71 return bpf_kfunc_call_stack_arg_mem(1, 2, 3, 4, 5, buf, sizeof(buf)); 72 } 73 74 /* 1 + 2 + 3 + 4 + 5 + 100 = 115 */ 75 SEC("tc") 76 int test_stack_arg_iter(struct __sk_buff *skb) 77 { 78 struct bpf_iter_testmod_seq it; 79 u64 ret; 80 81 bpf_iter_testmod_seq_new(&it, 100, 10); 82 ret = bpf_kfunc_call_stack_arg_iter(1, 2, 3, 4, 5, &it); 83 bpf_iter_testmod_seq_destroy(&it); 84 return ret; 85 } 86 87 const char cstr[] = "hello"; 88 89 /* 1 + 2 + 3 + 4 + 5 = 15 */ 90 SEC("tc") 91 int test_stack_arg_const_str(struct __sk_buff *skb) 92 { 93 return bpf_kfunc_call_stack_arg_const_str(1, 2, 3, 4, 5, cstr); 94 } 95 96 /* 1 + 2 + 3 + 4 + 5 = 15 */ 97 SEC("tc") 98 int test_stack_arg_timer(struct __sk_buff *skb) 99 { 100 struct timer_map_value *val; 101 int key = 0; 102 103 val = bpf_map_lookup_elem(&kfunc_timer_map, &key); 104 if (!val) 105 return 0; 106 return bpf_kfunc_call_stack_arg_timer(1, 2, 3, 4, 5, &val->timer); 107 } 108 109 #else 110 111 const volatile bool has_stack_arg = false; 112 113 SEC("tc") 114 int test_stack_arg_scalar(struct __sk_buff *skb) 115 { 116 return 0; 117 } 118 119 SEC("tc") 120 int test_stack_arg_ptr(struct __sk_buff *skb) 121 { 122 return 0; 123 } 124 125 SEC("tc") 126 int test_stack_arg_mix(struct __sk_buff *skb) 127 { 128 return 0; 129 } 130 131 SEC("tc") 132 int test_stack_arg_dynptr(struct __sk_buff *skb) 133 { 134 return 0; 135 } 136 137 SEC("tc") 138 int test_stack_arg_mem(struct __sk_buff *skb) 139 { 140 return 0; 141 } 142 143 SEC("tc") 144 int test_stack_arg_iter(struct __sk_buff *skb) 145 { 146 return 0; 147 } 148 149 SEC("tc") 150 int test_stack_arg_const_str(struct __sk_buff *skb) 151 { 152 return 0; 153 } 154 155 SEC("tc") 156 int test_stack_arg_timer(struct __sk_buff *skb) 157 { 158 return 0; 159 } 160 161 #endif 162 163 char _license[] SEC("license") = "GPL"; 164