Skip to content

Commit

Permalink
riscv, bpf: Use bpf_prog_pack for RV64 bpf trampoline
Browse files Browse the repository at this point in the history
We used bpf_prog_pack to aggregate bpf programs into huge page to
relieve the iTLB pressure on the system. We can apply it to bpf
trampoline, as Song had been implemented it in core and x86 [0]. This
patch is going to use bpf_prog_pack to RV64 bpf trampoline. Since Song
and Puranjay have done a lot of work for bpf_prog_pack on RV64,
implementing this function will be easy.

Link: https://lore.kernel.org/all/20231206224054.492250-1-song@kernel.org [0]
Signed-off-by: Pu Lehui <pulehui@huawei.com>
Tested-by: Björn Töpel <bjorn@rivosinc.com> #riscv
  • Loading branch information
Pu Lehui authored and Kernel Patches Daemon committed May 24, 2024
1 parent 33a352e commit 85ce4f7
Showing 1 changed file with 29 additions and 14 deletions.
43 changes: 29 additions & 14 deletions arch/riscv/net/bpf_jit_comp64.c
Original file line number Diff line number Diff line change
Expand Up @@ -956,7 +956,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
goto out;
emit_sd(RV_REG_FP, -retval_off, RV_REG_A0, ctx);
emit_sd(RV_REG_FP, -(retval_off - 8), regmap[BPF_REG_0], ctx);
im->ip_after_call = ctx->insns + ctx->ninsns;
im->ip_after_call = ctx->ro_insns + ctx->ninsns;
/* 2 nops reserved for auipc+jalr pair */
emit(rv_nop(), ctx);
emit(rv_nop(), ctx);
Expand All @@ -977,7 +977,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
}

if (flags & BPF_TRAMP_F_CALL_ORIG) {
im->ip_epilogue = ctx->insns + ctx->ninsns;
im->ip_epilogue = ctx->ro_insns + ctx->ninsns;
emit_imm(RV_REG_A0, ctx->insns ? (const s64)im : RV_MAX_COUNT_IMM, ctx);
ret = emit_call((const u64)__bpf_tramp_exit, true, ctx);
if (ret)
Expand Down Expand Up @@ -1040,25 +1040,33 @@ int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
return ret < 0 ? ret : ninsns_rvoff(ctx.ninsns);
}

int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image,
void *image_end, const struct btf_func_model *m,
void *arch_alloc_bpf_trampoline(unsigned int size)
{
return bpf_prog_pack_alloc(size, bpf_fill_ill_insns);
}

void arch_free_bpf_trampoline(void *image, unsigned int size)
{
bpf_prog_pack_free(image, size);
}

int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *ro_image,
void *ro_image_end, const struct btf_func_model *m,
u32 flags, struct bpf_tramp_links *tlinks,
void *func_addr)
{
int ret;
void *image, *res;
struct rv_jit_context ctx;
u32 size = image_end - image;
u32 size = ro_image_end - ro_image;

image = kvmalloc(size, GFP_KERNEL);
if (!image)
return -ENOMEM;

ctx.ninsns = 0;
/*
* The bpf_int_jit_compile() uses a RW buffer (ctx.insns) to write the
* JITed instructions and later copies it to a RX region (ctx.ro_insns).
* It also uses ctx.ro_insns to calculate offsets for jumps etc. As the
* trampoline image uses the same memory area for writing and execution,
* both ctx.insns and ctx.ro_insns can be set to image.
*/
ctx.insns = image;
ctx.ro_insns = image;
ctx.ro_insns = ro_image;
ret = __arch_prepare_bpf_trampoline(im, m, tlinks, func_addr, flags, &ctx);
if (ret < 0)
goto out;
Expand All @@ -1068,8 +1076,15 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image,
goto out;
}

bpf_flush_icache(image, image_end);
res = bpf_arch_text_copy(ro_image, image, size);
if (IS_ERR(res)) {
ret = PTR_ERR(res);
goto out;
}

bpf_flush_icache(ro_image, ro_image_end);
out:
kvfree(image);
return ret < 0 ? ret : size;
}

Expand Down

0 comments on commit 85ce4f7

Please sign in to comment.