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
1 change: 1 addition & 0 deletions arch/riscv/net/bpf_jit.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ struct rv_jit_context {
unsigned long flags;
int stack_size;
int tcc_offset;
u16 stack_arg_size;
u64 arena_vm_start;
u64 user_vm_start;
};
Expand Down
79 changes: 76 additions & 3 deletions arch/riscv/net/bpf_jit_comp64.c
Original file line number Diff line number Diff line change
Expand Up @@ -1815,19 +1815,44 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,

if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) {
const struct btf_func_model *fm;
int idx;
int idx, nargs;

fm = bpf_jit_find_kfunc_model(ctx->prog, insn);
if (!fm)
return -EINVAL;

for (idx = 0; idx < fm->nr_args; idx++) {
nargs = min_t(int, fm->nr_args, MAX_BPF_FUNC_REG_ARGS);
for (idx = 0; idx < nargs; idx++) {
u8 reg = bpf_to_rv_reg(BPF_REG_1 + idx, ctx);
bool sign = fm->arg_flags[idx] & BTF_FMODEL_SIGNED_ARG;

if (sign_extend(reg, reg, fm->arg_size[idx], sign, ctx))
return -EINVAL;
}

/* BPF stack args -> RISC-V ABI: args 6-8 in A5-A7, 9+ at SP+0 */
if (fm->nr_args > MAX_BPF_FUNC_REG_ARGS) {
int n_stack = fm->nr_args - MAX_BPF_FUNC_REG_ARGS;
int n_reg = min_t(int, n_stack,
RV_MAX_REG_ARGS - MAX_BPF_FUNC_REG_ARGS);

for (idx = 0; idx < n_reg; idx++) {
int sz = fm->arg_size[MAX_BPF_FUNC_REG_ARGS + idx];

emit_ld(RV_REG_A5 + idx, idx * 8, RV_REG_SP, ctx);
if (sz == sizeof(int))
emit_sextw(RV_REG_A5 + idx, RV_REG_A5 + idx, ctx);
}

for (idx = n_reg; idx < n_stack; idx++) {
int sz = fm->arg_size[MAX_BPF_FUNC_REG_ARGS + idx];

emit_ld(RV_REG_T1, idx * 8, RV_REG_SP, ctx);
if (sz == sizeof(int))
emit_sextw(RV_REG_T1, RV_REG_T1, ctx);
emit_sd(RV_REG_SP, (idx - n_reg) * 8, RV_REG_T1, ctx);
}
}
}

/* restore TCC to RV_REG_TCC before bpf2bpf call */
Expand Down Expand Up @@ -1892,6 +1917,21 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
case BPF_LDX | BPF_MEM | BPF_H:
case BPF_LDX | BPF_MEM | BPF_W:
case BPF_LDX | BPF_MEM | BPF_DW:
if (insn->src_reg == BPF_REG_PARAMS) {
int idx = off / 8 - 1;

if (is_12b_int(idx * 8)) {
emit_ldx_insn(rd, idx * 8, RV_REG_FP, BPF_SIZE(code), false, ctx);
} else {
emit_imm(RV_REG_T1, idx * 8, ctx);
emit_add(RV_REG_T1, RV_REG_T1, RV_REG_FP, ctx);
emit_ldx_insn(rd, 0, RV_REG_T1, BPF_SIZE(code), false, ctx);
}
if (BPF_SIZE(code) != BPF_DW && insn_is_zext(&insn[1]))
return 1;
break;
}
fallthrough;
case BPF_LDX | BPF_PROBE_MEM | BPF_B:
case BPF_LDX | BPF_PROBE_MEM | BPF_H:
case BPF_LDX | BPF_PROBE_MEM | BPF_W:
Expand Down Expand Up @@ -1939,6 +1979,20 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
case BPF_ST | BPF_MEM | BPF_H:
case BPF_ST | BPF_MEM | BPF_W:
case BPF_ST | BPF_MEM | BPF_DW:
if (insn->dst_reg == BPF_REG_PARAMS) {
int idx = -off / 8 - 1;

emit_imm(RV_REG_T1, imm, ctx);
if (is_12b_int(idx * 8)) {
emit_stx_insn(RV_REG_SP, idx * 8, RV_REG_T1, BPF_SIZE(code), ctx);
} else {
emit_imm(RV_REG_T2, idx * 8, ctx);
emit_add(RV_REG_T2, RV_REG_SP, RV_REG_T2, ctx);
emit_stx_insn(RV_REG_T2, 0, RV_REG_T1, BPF_SIZE(code), ctx);
}
break;
}
fallthrough;
/* ST | PROBE_MEM32: *(size *)(dst + RV_REG_ARENA + off) = imm */
case BPF_ST | BPF_PROBE_MEM32 | BPF_B:
case BPF_ST | BPF_PROBE_MEM32 | BPF_H:
Expand All @@ -1961,6 +2015,19 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
case BPF_STX | BPF_MEM | BPF_H:
case BPF_STX | BPF_MEM | BPF_W:
case BPF_STX | BPF_MEM | BPF_DW:
if (insn->dst_reg == BPF_REG_PARAMS) {
int idx = -off / 8 - 1;

if (is_12b_int(idx * 8)) {
emit_stx_insn(RV_REG_SP, idx * 8, rs, BPF_SIZE(code), ctx);
} else {
emit_imm(RV_REG_T1, idx * 8, ctx);
emit_add(RV_REG_T1, RV_REG_SP, RV_REG_T1, ctx);
emit_stx_insn(RV_REG_T1, 0, rs, BPF_SIZE(code), ctx);
}
break;
}
fallthrough;
/* STX | PROBE_MEM32: *(size *)(dst + RV_REG_ARENA + off) = src */
case BPF_STX | BPF_PROBE_MEM32 | BPF_B:
case BPF_STX | BPF_PROBE_MEM32 | BPF_H:
Expand Down Expand Up @@ -2046,6 +2113,7 @@ void bpf_jit_build_prologue(struct rv_jit_context *ctx, bool is_subprog)

stack_adjust = round_up(stack_adjust, STACK_ALIGN);
stack_adjust += bpf_stack_adjust;
stack_adjust += ctx->stack_arg_size;

store_offset = stack_adjust - 8;

Expand Down Expand Up @@ -2103,7 +2171,7 @@ void bpf_jit_build_prologue(struct rv_jit_context *ctx, bool is_subprog)
emit_addi(RV_REG_FP, RV_REG_SP, stack_adjust, ctx);

if (bpf_stack_adjust)
emit_addi(RV_REG_S5, RV_REG_SP, bpf_stack_adjust, ctx);
emit_addi(RV_REG_S5, RV_REG_SP, ctx->stack_arg_size + bpf_stack_adjust, ctx);

ctx->stack_size = stack_adjust;

Expand Down Expand Up @@ -2181,3 +2249,8 @@ bool bpf_jit_supports_timed_may_goto(void)
{
return true;
}

bool bpf_jit_supports_stack_args(void)
{
return true;
}
4 changes: 4 additions & 0 deletions arch/riscv/net/bpf_jit_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_pr
ctx->arena_vm_start = bpf_arena_get_kern_vm_start(prog->aux->arena);
ctx->user_vm_start = bpf_arena_get_user_vm_start(prog->aux->arena);
ctx->prog = prog;

ctx->stack_arg_size = round_up(bpf_out_stack_arg_cnt(env, prog) *
sizeof(u64), STACK_ALIGN);

ctx->offset = kvzalloc_objs(int, prog->len);
if (!ctx->offset)
goto out_offset;
Expand Down
3 changes: 2 additions & 1 deletion tools/testing/selftests/bpf/progs/btf__stack_arg_precision.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
#include <bpf/bpf_helpers.h>
#include "../test_kmods/bpf_testmod_kfunc.h"

#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64)) && \
#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64) || \
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) && \
defined(__BPF_FEATURE_STACK_ARGUMENT)

long subprog_call_mem_kfunc(long a, long b, long c, long d, long e, long size)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
#include <vmlinux.h>
#include <bpf/bpf_helpers.h>

#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64)) && \
#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64) || \
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) && \
defined(__BPF_FEATURE_STACK_ARGUMENT)

int subprog_bad_order_6args(int a, int b, int c, int d, int e, int f)
Expand Down
3 changes: 2 additions & 1 deletion tools/testing/selftests/bpf/progs/stack_arg.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ struct {

int timer_result;

#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64)) && \
#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64) || \
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) && \
defined(__BPF_FEATURE_STACK_ARGUMENT)

const volatile bool has_stack_arg = true;
Expand Down
3 changes: 2 additions & 1 deletion tools/testing/selftests/bpf/progs/stack_arg_kfunc.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
#include "bpf_kfuncs.h"
#include "../test_kmods/bpf_testmod_kfunc.h"

#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64)) && \
#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64) || \
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) && \
defined(__BPF_FEATURE_STACK_ARGUMENT)

const volatile bool has_stack_arg = true;
Expand Down
3 changes: 2 additions & 1 deletion tools/testing/selftests/bpf/progs/stack_arg_precision.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
#include "../test_kmods/bpf_testmod_kfunc.h"
#include "bpf_misc.h"

#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64)) && \
#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64) || \
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) && \
defined(__BPF_FEATURE_STACK_ARGUMENT)

/* Force kfunc extern BTF generation for inline asm call below.
Expand Down
3 changes: 2 additions & 1 deletion tools/testing/selftests/bpf/progs/verifier_stack_arg.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ struct {
__type(value, long long);
} map_hash_8b SEC(".maps");

#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64)) && \
#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64) || \
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) && \
defined(__BPF_FEATURE_STACK_ARGUMENT)

__noinline __used
Expand Down
3 changes: 2 additions & 1 deletion tools/testing/selftests/bpf/progs/verifier_stack_arg_order.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
#include <bpf/bpf_helpers.h>
#include "bpf_misc.h"

#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64)) && \
#if (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64) || \
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) && \
defined(__BPF_FEATURE_STACK_ARGUMENT)

__noinline __used __naked
Expand Down
Loading