194575Sdes// SPDX-License-Identifier: GPL-2.0 294575Sdes/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */ 394575Sdes#include "vmlinux.h" 494575Sdes#include <bpf/bpf_helpers.h> 594575Sdes#include <bpf/bpf_tracing.h> 694575Sdes#include <bpf/bpf_core_read.h> 794575Sdes#include "bpf_misc.h" 894575Sdes 994575Sdeschar _license[] SEC("license") = "GPL"; 1094575Sdes 1194575Sdesstatic long stack[256]; 1294575Sdes 1394575Sdes/* 1494575Sdes * KPROBE contexts 1594575Sdes */ 1694575Sdes 1794575Sdes__weak int kprobe_typedef_ctx_subprog(bpf_user_pt_regs_t *ctx) 1894575Sdes{ 1994575Sdes return bpf_get_stack(ctx, &stack, sizeof(stack), 0); 2094575Sdes} 2194575Sdes 2294575SdesSEC("?kprobe") 2394575Sdes__success 2494575Sdesint kprobe_typedef_ctx(void *ctx) 2594575Sdes{ 2694575Sdes return kprobe_typedef_ctx_subprog(ctx); 2794575Sdes} 2894575Sdes 2994575Sdes/* s390x defines: 3094575Sdes * 3194575Sdes * typedef user_pt_regs bpf_user_pt_regs_t; 3294575Sdes * typedef struct { ... } user_pt_regs; 3394575Sdes * 3494575Sdes * And so "canonical" underlying struct type is anonymous. 3594575Sdes * So on s390x only valid ways to have PTR_TO_CTX argument in global subprogs 3694575Sdes * are: 3794577Sdes * - bpf_user_pt_regs_t *ctx (typedef); 3894577Sdes * - struct bpf_user_pt_regs_t *ctx (backwards compatible struct hack); 3994577Sdes * - void *ctx __arg_ctx (arg:ctx tag) 4094577Sdes * 4194575Sdes * Other architectures also allow using underlying struct types (e.g., 4294575Sdes * `struct pt_regs *ctx` for x86-64) 4394577Sdes */ 4494577Sdes#ifndef bpf_target_s390 4594575Sdes 4694575Sdes#define pt_regs_struct_t typeof(*(__PT_REGS_CAST((struct pt_regs *)NULL))) 4794575Sdes 4894577Sdes__weak int kprobe_struct_ctx_subprog(pt_regs_struct_t *ctx) 4994575Sdes{ 5094575Sdes return bpf_get_stack((void *)ctx, &stack, sizeof(stack), 0); 5194575Sdes} 5294575Sdes 5394575SdesSEC("?kprobe") 5494577Sdes__success 5594575Sdesint kprobe_resolved_ctx(void *ctx) 5694577Sdes{ 57116393Smbr return kprobe_struct_ctx_subprog(ctx); 5894577Sdes} 5996198Sdes 6096198Sdes#endif 6196198Sdes 6296198Sdes/* this is current hack to make this work on old kernels */ 6396198Sdesstruct bpf_user_pt_regs_t {}; 6494575Sdes 6596198Sdes__weak int kprobe_workaround_ctx_subprog(struct bpf_user_pt_regs_t *ctx) 6694575Sdes{ 67116393Smbr return bpf_get_stack(ctx, &stack, sizeof(stack), 0); 68116393Smbr} 69116393Smbr 70116393SmbrSEC("?kprobe") 7194575Sdes__success 72116393Smbrint kprobe_workaround_ctx(void *ctx) 7394575Sdes{ 7494575Sdes return kprobe_workaround_ctx_subprog(ctx); 7594575Sdes} 7694575Sdes 7794575Sdes/* 7894575Sdes * RAW_TRACEPOINT contexts 7994577Sdes */ 8094577Sdes 8196198Sdes__weak int raw_tp_ctx_subprog(struct bpf_raw_tracepoint_args *ctx) 8294577Sdes{ 83116393Smbr return bpf_get_stack(ctx, &stack, sizeof(stack), 0); 84116393Smbr} 85116393Smbr 86116393SmbrSEC("?raw_tp") 87116393Smbr__success 88116393Smbrint raw_tp_ctx(void *ctx) 8994577Sdes{ 90116393Smbr return raw_tp_ctx_subprog(ctx); 91116393Smbr} 92116393Smbr 93116393Smbr/* 94116393Smbr * RAW_TRACEPOINT_WRITABLE contexts 9594577Sdes */ 96116393Smbr 97116393Smbr__weak int raw_tp_writable_ctx_subprog(struct bpf_raw_tracepoint_args *ctx) 98116393Smbr{ 99116393Smbr return bpf_get_stack(ctx, &stack, sizeof(stack), 0); 100116393Smbr} 101116393Smbr 102116393SmbrSEC("?raw_tp") 103116393Smbr__success 104116393Smbrint raw_tp_writable_ctx(void *ctx) 105116393Smbr{ 106116393Smbr return raw_tp_writable_ctx_subprog(ctx); 107116393Smbr} 108116393Smbr 109116393Smbr/* 110116393Smbr * PERF_EVENT contexts 111116393Smbr */ 11294577Sdes 11394577Sdes__weak int perf_event_ctx_subprog(struct bpf_perf_event_data *ctx) 11494577Sdes{ 11596198Sdes return bpf_get_stack(ctx, &stack, sizeof(stack), 0); 11696198Sdes} 11796198Sdes 11896198SdesSEC("?perf_event") 11996198Sdes__success 12096198Sdesint perf_event_ctx(void *ctx) 12196198Sdes{ 12296198Sdes return perf_event_ctx_subprog(ctx); 12396198Sdes} 124116393Smbr 12596198Sdes/* this global subprog can be now called from many types of entry progs, each 12696198Sdes * with different context type 12796198Sdes */ 12896198Sdes__weak int subprog_ctx_tag(void *ctx __arg_ctx) 12996198Sdes{ 13096198Sdes return bpf_get_stack(ctx, stack, sizeof(stack), 0); 13194577Sdes} 13294577Sdes 13394577Sdesstruct my_struct { int x; }; 13494577Sdes 13594577Sdes__weak int subprog_multi_ctx_tags(void *ctx1 __arg_ctx, 13694577Sdes struct my_struct *mem, 137116393Smbr void *ctx2 __arg_ctx) 13894577Sdes{ 13994577Sdes if (!mem) 14094577Sdes return 0; 14194577Sdes 142116393Smbr return bpf_get_stack(ctx1, stack, sizeof(stack), 0) + 14394577Sdes mem->x + 14494577Sdes bpf_get_stack(ctx2, stack, sizeof(stack), 0); 14594577Sdes} 14694577Sdes 14794577SdesSEC("?raw_tp") 14894577Sdes__success __log_level(2) 14994577Sdesint arg_tag_ctx_raw_tp(void *ctx) 15094577Sdes{ 15194577Sdes struct my_struct x = { .x = 123 }; 15294577Sdes 153116393Smbr return subprog_ctx_tag(ctx) + subprog_multi_ctx_tags(ctx, &x, ctx); 154116393Smbr} 15594577Sdes 15694577SdesSEC("?perf_event") 15794577Sdes__success __log_level(2) 15894577Sdesint arg_tag_ctx_perf(void *ctx) 15994577Sdes{ 160116393Smbr struct my_struct x = { .x = 123 }; 16194577Sdes 16294577Sdes return subprog_ctx_tag(ctx) + subprog_multi_ctx_tags(ctx, &x, ctx); 16394577Sdes} 16494577Sdes 16594577SdesSEC("?kprobe") 16694577Sdes__success __log_level(2) 167116393Smbrint arg_tag_ctx_kprobe(void *ctx) 168116393Smbr{ 169116393Smbr struct my_struct x = { .x = 123 }; 170116393Smbr 171116393Smbr return subprog_ctx_tag(ctx) + subprog_multi_ctx_tags(ctx, &x, ctx); 172116393Smbr} 173116393Smbr