Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 77 additions & 20 deletions arch/riscv/net/bpf_jit_comp64.c
Original file line number Diff line number Diff line change
Expand Up @@ -926,19 +926,25 @@ static void restore_stack_args(int nr_stack_args, int args_off, int stk_arg_off,
}
}

static void emit_store_stack_imm64(u8 reg, int stack_off, u64 imm64,
struct rv_jit_context *ctx)
{
/* Load imm64 into reg and store it at [FP + stack_off]. */
emit_imm(reg, (s64)imm64, ctx);
emit_sd(RV_REG_FP, stack_off, reg, ctx);
}

static int invoke_bpf_prog(struct bpf_tramp_link *l, int args_off, int retval_off,
int run_ctx_off, bool save_ret, struct rv_jit_context *ctx)
{
int ret, branch_off;
struct bpf_prog *p = l->link.prog;
int cookie_off = offsetof(struct bpf_tramp_run_ctx, bpf_cookie);

if (l->cookie) {
emit_imm(RV_REG_T1, l->cookie, ctx);
emit_sd(RV_REG_FP, -run_ctx_off + cookie_off, RV_REG_T1, ctx);
} else {
if (l->cookie)
emit_store_stack_imm64(RV_REG_T1, -run_ctx_off + cookie_off, l->cookie, ctx);
else
emit_sd(RV_REG_FP, -run_ctx_off + cookie_off, RV_REG_ZERO, ctx);
}

/* arg1: prog */
emit_imm(RV_REG_A0, (const s64)p, ctx);
Expand Down Expand Up @@ -990,6 +996,29 @@ static int invoke_bpf_prog(struct bpf_tramp_link *l, int args_off, int retval_of
return ret;
}

static int invoke_bpf(struct bpf_tramp_links *tl, int args_off, int retval_off,
int run_ctx_off, int func_meta_off, bool save_ret, u64 func_meta,
int cookie_off, struct rv_jit_context *ctx)
{
int i, cur_cookie = (cookie_off - args_off) / 8;

for (i = 0; i < tl->nr_links; i++) {
int err;

if (tl->links[i]->link.prog->call_session_cookie) {
u64 meta = func_meta | ((u64)cur_cookie << BPF_TRAMP_COOKIE_INDEX_SHIFT);

emit_store_stack_imm64(RV_REG_T1, -func_meta_off, meta, ctx);
cur_cookie--;
}
err = invoke_bpf_prog(tl->links[i], args_off, retval_off, run_ctx_off,
save_ret, ctx);
if (err)
return err;
}
return 0;
}

static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
const struct btf_func_model *m,
struct bpf_tramp_links *tlinks,
Expand All @@ -999,13 +1028,15 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
int i, ret, offset;
int *branches_off = NULL;
int stack_size = 0, nr_arg_slots = 0;
int retval_off, args_off, nregs_off, ip_off, run_ctx_off, sreg_off, stk_arg_off;
int retval_off, args_off, func_meta_off, ip_off, run_ctx_off, sreg_off, stk_arg_off;
int cookie_off, cookie_cnt;
struct bpf_tramp_links *fentry = &tlinks[BPF_TRAMP_FENTRY];
struct bpf_tramp_links *fexit = &tlinks[BPF_TRAMP_FEXIT];
struct bpf_tramp_links *fmod_ret = &tlinks[BPF_TRAMP_MODIFY_RETURN];
bool is_struct_ops = flags & BPF_TRAMP_F_INDIRECT;
void *orig_call = func_addr;
bool save_ret;
u64 func_meta;
u32 insn;

/* Two types of generated trampoline stack layout:
Expand Down Expand Up @@ -1036,10 +1067,14 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
* [ ... ]
* FP - args_off [ arg1 ]
*
* FP - nregs_off [ regs count ]
* FP - func_meta_off [ regs count, etc ] always
*
* FP - ip_off [ traced func ] BPF_TRAMP_F_IP_ARG
*
* [ stack cookie N ]
* [ ... ]
* FP - cookie_off [ stack cookie 1 ]
*
* FP - run_ctx_off [ bpf_tramp_run_ctx ]
*
* FP - sreg_off [ callee saved reg ]
Expand Down Expand Up @@ -1071,14 +1106,20 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
stack_size += nr_arg_slots * 8;
args_off = stack_size;

/* function metadata, such as regs count */
stack_size += 8;
nregs_off = stack_size;
func_meta_off = stack_size;

if (flags & BPF_TRAMP_F_IP_ARG) {
stack_size += 8;
ip_off = stack_size;
}

cookie_cnt = bpf_fsession_cookie_cnt(tlinks);
/* room for session cookies */
stack_size += cookie_cnt * 8;
cookie_off = stack_size;

stack_size += round_up(sizeof(struct bpf_tramp_run_ctx), 8);
run_ctx_off = stack_size;

Expand Down Expand Up @@ -1123,26 +1164,32 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
emit_sd(RV_REG_FP, -sreg_off, RV_REG_S1, ctx);

/* store ip address of the traced function */
if (flags & BPF_TRAMP_F_IP_ARG) {
emit_imm(RV_REG_T1, (const s64)func_addr, ctx);
emit_sd(RV_REG_FP, -ip_off, RV_REG_T1, ctx);
}
if (flags & BPF_TRAMP_F_IP_ARG)
emit_store_stack_imm64(RV_REG_T1, -ip_off, (u64)func_addr, ctx);

emit_li(RV_REG_T1, nr_arg_slots, ctx);
emit_sd(RV_REG_FP, -nregs_off, RV_REG_T1, ctx);
func_meta = nr_arg_slots;
emit_store_stack_imm64(RV_REG_T1, -func_meta_off, func_meta, ctx);

store_args(nr_arg_slots, args_off, ctx);

if (bpf_fsession_cnt(tlinks)) {
/* clear all session cookies' value */
for (i = 0; i < cookie_cnt; i++)
emit_sd(RV_REG_FP, -cookie_off + 8 * i, RV_REG_ZERO, ctx);
/* clear return value to make sure fentry always get 0 */
emit_sd(RV_REG_FP, -retval_off, RV_REG_ZERO, ctx);
}

if (flags & BPF_TRAMP_F_CALL_ORIG) {
emit_imm(RV_REG_A0, ctx->insns ? (const s64)im : RV_MAX_COUNT_IMM, ctx);
ret = emit_call((const u64)__bpf_tramp_enter, true, ctx);
if (ret)
return ret;
}

for (i = 0; i < fentry->nr_links; i++) {
ret = invoke_bpf_prog(fentry->links[i], args_off, retval_off, run_ctx_off,
flags & BPF_TRAMP_F_RET_FENTRY_RET, ctx);
if (fentry->nr_links) {
ret = invoke_bpf(fentry, args_off, retval_off, run_ctx_off, func_meta_off,
flags & BPF_TRAMP_F_RET_FENTRY_RET, func_meta, cookie_off, ctx);
if (ret)
return ret;
}
Expand Down Expand Up @@ -1189,9 +1236,14 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
*(u32 *)(ctx->insns + branches_off[i]) = insn;
}

for (i = 0; i < fexit->nr_links; i++) {
ret = invoke_bpf_prog(fexit->links[i], args_off, retval_off,
run_ctx_off, false, ctx);
/* set "is_return" flag for fsession */
func_meta |= (1ULL << BPF_TRAMP_IS_RETURN_SHIFT);
if (bpf_fsession_cnt(tlinks))
emit_store_stack_imm64(RV_REG_T1, -func_meta_off, func_meta, ctx);

if (fexit->nr_links) {
ret = invoke_bpf(fexit, args_off, retval_off, run_ctx_off, func_meta_off,
false, func_meta, cookie_off, ctx);
if (ret)
goto out;
}
Expand Down Expand Up @@ -2091,3 +2143,8 @@ bool bpf_jit_inlines_helper_call(s32 imm)
return false;
}
}

bool bpf_jit_supports_fsession(void)
{
return true;
}
2 changes: 1 addition & 1 deletion tools/testing/selftests/bpf/progs/get_func_args_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ int BPF_PROG(tp_test2)
}

__u64 test7_result = 0;
#if defined(bpf_target_x86) || defined(bpf_target_arm64)
#if defined(bpf_target_x86) || defined(bpf_target_arm64) || defined(bpf_target_riscv)
SEC("fsession/bpf_fentry_test1")
int BPF_PROG(test7)
{
Expand Down
2 changes: 1 addition & 1 deletion tools/testing/selftests/bpf/progs/get_func_ip_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ int BPF_URETPROBE(test8, int ret)

__u64 test9_entry_result = 0;
__u64 test9_exit_result = 0;
#if defined(bpf_target_x86) || defined(bpf_target_arm64)
#if defined(bpf_target_x86) || defined(bpf_target_arm64) || defined(bpf_target_riscv)
SEC("fsession/bpf_fentry_test1")
int BPF_PROG(test9, int a)
{
Expand Down
Loading