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