179e7ec00SYonghong Song // SPDX-License-Identifier: GPL-2.0 279e7ec00SYonghong Song /* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */ 379e7ec00SYonghong Song 479e7ec00SYonghong Song #include <vmlinux.h> 579e7ec00SYonghong Song #include <bpf/bpf_helpers.h> 679e7ec00SYonghong Song #include "bpf_kfuncs.h" 779e7ec00SYonghong Song #include "../test_kmods/bpf_testmod_kfunc.h" 879e7ec00SYonghong Song 990e43f1bSPuranjay Mohan #if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64)) && \ 1090e43f1bSPuranjay Mohan defined(__BPF_FEATURE_STACK_ARGUMENT) 1179e7ec00SYonghong Song 1279e7ec00SYonghong Song const volatile bool has_stack_arg = true; 1379e7ec00SYonghong Song 1479e7ec00SYonghong Song struct bpf_iter_testmod_seq { 1579e7ec00SYonghong Song u64 :64; 1679e7ec00SYonghong Song u64 :64; 1779e7ec00SYonghong Song }; 1879e7ec00SYonghong Song 1979e7ec00SYonghong Song extern int bpf_iter_testmod_seq_new(struct bpf_iter_testmod_seq *it, s64 value, int cnt) __ksym; 2079e7ec00SYonghong Song extern void bpf_iter_testmod_seq_destroy(struct bpf_iter_testmod_seq *it) __ksym; 2179e7ec00SYonghong Song 2279e7ec00SYonghong Song struct timer_map_value { 2379e7ec00SYonghong Song struct bpf_timer timer; 2479e7ec00SYonghong Song }; 2579e7ec00SYonghong Song 2679e7ec00SYonghong Song struct { 2779e7ec00SYonghong Song __uint(type, BPF_MAP_TYPE_ARRAY); 2879e7ec00SYonghong Song __uint(max_entries, 1); 2979e7ec00SYonghong Song __type(key, int); 3079e7ec00SYonghong Song __type(value, struct timer_map_value); 3179e7ec00SYonghong Song } kfunc_timer_map SEC(".maps"); 3279e7ec00SYonghong Song 3379e7ec00SYonghong Song SEC("tc") 3479e7ec00SYonghong Song int test_stack_arg_scalar(struct __sk_buff *skb) 3579e7ec00SYonghong Song { 36*157317baSPuranjay Mohan return bpf_kfunc_call_stack_arg(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 3779e7ec00SYonghong Song } 3879e7ec00SYonghong Song 3979e7ec00SYonghong Song SEC("tc") 4079e7ec00SYonghong Song int test_stack_arg_ptr(struct __sk_buff *skb) 4179e7ec00SYonghong Song { 4279e7ec00SYonghong Song struct prog_test_pass1 p = { .x0 = 10, .x1 = 20 }; 4379e7ec00SYonghong Song 44*157317baSPuranjay Mohan return bpf_kfunc_call_stack_arg_ptr(1, 2, 3, 4, 5, 6, 7, 8, 9, &p); 4579e7ec00SYonghong Song } 4679e7ec00SYonghong Song 4779e7ec00SYonghong Song SEC("tc") 4879e7ec00SYonghong Song int test_stack_arg_mix(struct __sk_buff *skb) 4979e7ec00SYonghong Song { 5079e7ec00SYonghong Song struct prog_test_pass1 p = { .x0 = 10 }; 5179e7ec00SYonghong Song struct prog_test_pass1 q = { .x1 = 20 }; 5279e7ec00SYonghong Song 53*157317baSPuranjay Mohan return bpf_kfunc_call_stack_arg_mix(1, 2, 3, 4, 5, 6, 7, &p, 8, &q); 5479e7ec00SYonghong Song } 5579e7ec00SYonghong Song 56*157317baSPuranjay Mohan /* 1+2+3+4+5+6+7+8+9+sizeof(pkt_v4) = 45+54 = 99 */ 5779e7ec00SYonghong Song SEC("tc") 5879e7ec00SYonghong Song int test_stack_arg_dynptr(struct __sk_buff *skb) 5979e7ec00SYonghong Song { 6079e7ec00SYonghong Song struct bpf_dynptr ptr; 6179e7ec00SYonghong Song 6279e7ec00SYonghong Song bpf_dynptr_from_skb(skb, 0, &ptr); 63*157317baSPuranjay Mohan return bpf_kfunc_call_stack_arg_dynptr(1, 2, 3, 4, 5, 6, 7, 8, 9, &ptr); 6479e7ec00SYonghong Song } 6579e7ec00SYonghong Song 6679e7ec00SYonghong Song /* 1 + 2 + 3 + 4 + 5 + (1 + 2 + ... + 16) = 15 + 136 = 151 */ 6779e7ec00SYonghong Song SEC("tc") 6879e7ec00SYonghong Song int test_stack_arg_mem(struct __sk_buff *skb) 6979e7ec00SYonghong Song { 7079e7ec00SYonghong Song char buf[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; 7179e7ec00SYonghong Song 7279e7ec00SYonghong Song return bpf_kfunc_call_stack_arg_mem(1, 2, 3, 4, 5, buf, sizeof(buf)); 7379e7ec00SYonghong Song } 7479e7ec00SYonghong Song 75*157317baSPuranjay Mohan /* 1+2+3+4+5+6+7+8+9+100 = 145 */ 7679e7ec00SYonghong Song SEC("tc") 7779e7ec00SYonghong Song int test_stack_arg_iter(struct __sk_buff *skb) 7879e7ec00SYonghong Song { 7979e7ec00SYonghong Song struct bpf_iter_testmod_seq it; 8079e7ec00SYonghong Song u64 ret; 8179e7ec00SYonghong Song 8279e7ec00SYonghong Song bpf_iter_testmod_seq_new(&it, 100, 10); 83*157317baSPuranjay Mohan ret = bpf_kfunc_call_stack_arg_iter(1, 2, 3, 4, 5, 6, 7, 8, 9, &it); 8479e7ec00SYonghong Song bpf_iter_testmod_seq_destroy(&it); 8579e7ec00SYonghong Song return ret; 8679e7ec00SYonghong Song } 8779e7ec00SYonghong Song 8879e7ec00SYonghong Song const char cstr[] = "hello"; 8979e7ec00SYonghong Song 90*157317baSPuranjay Mohan /* 1+2+3+4+5+6+7+8+9 = 45 */ 9179e7ec00SYonghong Song SEC("tc") 9279e7ec00SYonghong Song int test_stack_arg_const_str(struct __sk_buff *skb) 9379e7ec00SYonghong Song { 94*157317baSPuranjay Mohan return bpf_kfunc_call_stack_arg_const_str(1, 2, 3, 4, 5, 6, 7, 8, 9, 95*157317baSPuranjay Mohan cstr); 9679e7ec00SYonghong Song } 9779e7ec00SYonghong Song 98*157317baSPuranjay Mohan /* 1+2+3+4+5+6+7+8+9 = 45 */ 9979e7ec00SYonghong Song SEC("tc") 10079e7ec00SYonghong Song int test_stack_arg_timer(struct __sk_buff *skb) 10179e7ec00SYonghong Song { 10279e7ec00SYonghong Song struct timer_map_value *val; 10379e7ec00SYonghong Song int key = 0; 10479e7ec00SYonghong Song 10579e7ec00SYonghong Song val = bpf_map_lookup_elem(&kfunc_timer_map, &key); 10679e7ec00SYonghong Song if (!val) 10779e7ec00SYonghong Song return 0; 108*157317baSPuranjay Mohan return bpf_kfunc_call_stack_arg_timer(1, 2, 3, 4, 5, 6, 7, 8, 9, 109*157317baSPuranjay Mohan &val->timer); 11079e7ec00SYonghong Song } 11179e7ec00SYonghong Song 11279e7ec00SYonghong Song #else 11379e7ec00SYonghong Song 11479e7ec00SYonghong Song const volatile bool has_stack_arg = false; 11579e7ec00SYonghong Song 11679e7ec00SYonghong Song SEC("tc") 11779e7ec00SYonghong Song int test_stack_arg_scalar(struct __sk_buff *skb) 11879e7ec00SYonghong Song { 11979e7ec00SYonghong Song return 0; 12079e7ec00SYonghong Song } 12179e7ec00SYonghong Song 12279e7ec00SYonghong Song SEC("tc") 12379e7ec00SYonghong Song int test_stack_arg_ptr(struct __sk_buff *skb) 12479e7ec00SYonghong Song { 12579e7ec00SYonghong Song return 0; 12679e7ec00SYonghong Song } 12779e7ec00SYonghong Song 12879e7ec00SYonghong Song SEC("tc") 12979e7ec00SYonghong Song int test_stack_arg_mix(struct __sk_buff *skb) 13079e7ec00SYonghong Song { 13179e7ec00SYonghong Song return 0; 13279e7ec00SYonghong Song } 13379e7ec00SYonghong Song 13479e7ec00SYonghong Song SEC("tc") 13579e7ec00SYonghong Song int test_stack_arg_dynptr(struct __sk_buff *skb) 13679e7ec00SYonghong Song { 13779e7ec00SYonghong Song return 0; 13879e7ec00SYonghong Song } 13979e7ec00SYonghong Song 14079e7ec00SYonghong Song SEC("tc") 14179e7ec00SYonghong Song int test_stack_arg_mem(struct __sk_buff *skb) 14279e7ec00SYonghong Song { 14379e7ec00SYonghong Song return 0; 14479e7ec00SYonghong Song } 14579e7ec00SYonghong Song 14679e7ec00SYonghong Song SEC("tc") 14779e7ec00SYonghong Song int test_stack_arg_iter(struct __sk_buff *skb) 14879e7ec00SYonghong Song { 14979e7ec00SYonghong Song return 0; 15079e7ec00SYonghong Song } 15179e7ec00SYonghong Song 15279e7ec00SYonghong Song SEC("tc") 15379e7ec00SYonghong Song int test_stack_arg_const_str(struct __sk_buff *skb) 15479e7ec00SYonghong Song { 15579e7ec00SYonghong Song return 0; 15679e7ec00SYonghong Song } 15779e7ec00SYonghong Song 15879e7ec00SYonghong Song SEC("tc") 15979e7ec00SYonghong Song int test_stack_arg_timer(struct __sk_buff *skb) 16079e7ec00SYonghong Song { 16179e7ec00SYonghong Song return 0; 16279e7ec00SYonghong Song } 16379e7ec00SYonghong Song 16479e7ec00SYonghong Song #endif 16579e7ec00SYonghong Song 16679e7ec00SYonghong Song char _license[] SEC("license") = "GPL"; 167