From: Palmer Dabbelt <palmerdabbelt@google.com>
To: Bjorn Topel <bjorn.topel@gmail.com>
Cc: daniel@iogearbox.net, netdev@vger.kernel.org, ast@kernel.org,
Bjorn Topel <bjorn.topel@gmail.com>,
linux-riscv@lists.infradead.org, bpf@vger.kernel.org
Subject: Re: [PATCH bpf-next v2 7/9] riscv, bpf: optimize calls
Date: Mon, 23 Dec 2019 10:58:43 -0800 (PST) [thread overview]
Message-ID: <mhng-041b1051-f9ac-4cd8-95bf-731bb1bfbdb8@palmerdabbelt-glaptop> (raw)
In-Reply-To: <20191216091343.23260-8-bjorn.topel@gmail.com>
On Mon, 16 Dec 2019 01:13:41 PST (-0800), Bjorn Topel wrote:
> Instead of using emit_imm() and emit_jalr() which can expand to six
> instructions, start using jal or auipc+jalr.
>
> Signed-off-by: Björn Töpel <bjorn.topel@gmail.com>
> ---
> arch/riscv/net/bpf_jit_comp.c | 101 +++++++++++++++++++++-------------
> 1 file changed, 64 insertions(+), 37 deletions(-)
>
> diff --git a/arch/riscv/net/bpf_jit_comp.c b/arch/riscv/net/bpf_jit_comp.c
> index 46cff093f526..8d7e3343a08c 100644
> --- a/arch/riscv/net/bpf_jit_comp.c
> +++ b/arch/riscv/net/bpf_jit_comp.c
> @@ -811,11 +811,12 @@ static void emit_sext_32_rd(u8 *rd, struct rv_jit_context *ctx)
> *rd = RV_REG_T2;
> }
>
> -static void emit_jump_and_link(u8 rd, int rvoff, struct rv_jit_context *ctx)
> +static void emit_jump_and_link(u8 rd, s64 rvoff, bool force_jalr,
> + struct rv_jit_context *ctx)
> {
> s64 upper, lower;
>
> - if (is_21b_int(rvoff)) {
> + if (rvoff && is_21b_int(rvoff) && !force_jalr) {
> emit(rv_jal(rd, rvoff >> 1), ctx);
> return;
> }
> @@ -832,6 +833,28 @@ static bool is_signed_bpf_cond(u8 cond)
> cond == BPF_JSGE || cond == BPF_JSLE;
> }
>
> +static int emit_call(bool fixed, u64 addr, struct rv_jit_context *ctx)
> +{
> + s64 off = 0;
> + u64 ip;
> + u8 rd;
> +
> + if (addr && ctx->insns) {
> + ip = (u64)(long)(ctx->insns + ctx->ninsns);
> + off = addr - ip;
> + if (!is_32b_int(off)) {
> + pr_err("bpf-jit: target call addr %pK is out of range\n",
> + (void *)addr);
> + return -ERANGE;
> + }
> + }
> +
> + emit_jump_and_link(RV_REG_RA, off, !fixed, ctx);
> + rd = bpf_to_rv_reg(BPF_REG_0, ctx);
> + emit(rv_addi(rd, RV_REG_A0, 0), ctx);
Why are they out of order? It seems like it'd be better to just have the BPF
calling convention match the RISC-V calling convention, as that'd avoid
juggling the registers around.
> + return 0;
> +}
> +
> static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
> bool extra_pass)
> {
> @@ -1107,7 +1130,7 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
> /* JUMP off */
> case BPF_JMP | BPF_JA:
> rvoff = rv_offset(i, off, ctx);
> - emit_jump_and_link(RV_REG_ZERO, rvoff, ctx);
> + emit_jump_and_link(RV_REG_ZERO, rvoff, false, ctx);
> break;
>
> /* IF (dst COND src) JUMP off */
> @@ -1209,7 +1232,7 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
> case BPF_JMP | BPF_CALL:
> {
> bool fixed;
> - int i, ret;
> + int ret;
> u64 addr;
>
> mark_call(ctx);
> @@ -1217,20 +1240,9 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
> &fixed);
> if (ret < 0)
> return ret;
> - if (fixed) {
> - emit_imm(RV_REG_T1, addr, ctx);
> - } else {
> - i = ctx->ninsns;
> - emit_imm(RV_REG_T1, addr, ctx);
> - for (i = ctx->ninsns - i; i < 8; i++) {
> - /* nop */
> - emit(rv_addi(RV_REG_ZERO, RV_REG_ZERO, 0),
> - ctx);
> - }
> - }
> - emit(rv_jalr(RV_REG_RA, RV_REG_T1, 0), ctx);
> - rd = bpf_to_rv_reg(BPF_REG_0, ctx);
> - emit(rv_addi(rd, RV_REG_A0, 0), ctx);
> + ret = emit_call(fixed, addr, ctx);
> + if (ret)
> + return ret;
> break;
> }
> /* tail call */
> @@ -1245,7 +1257,7 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
> break;
>
> rvoff = epilogue_offset(ctx);
> - emit_jump_and_link(RV_REG_ZERO, rvoff, ctx);
> + emit_jump_and_link(RV_REG_ZERO, rvoff, false, ctx);
> break;
>
> /* dst = imm64 */
> @@ -1508,7 +1520,7 @@ static void build_epilogue(struct rv_jit_context *ctx)
> __build_epilogue(false, ctx);
> }
>
> -static int build_body(struct rv_jit_context *ctx, bool extra_pass)
> +static int build_body(struct rv_jit_context *ctx, bool extra_pass, int *offset)
> {
> const struct bpf_prog *prog = ctx->prog;
> int i;
> @@ -1520,12 +1532,12 @@ static int build_body(struct rv_jit_context *ctx, bool extra_pass)
> ret = emit_insn(insn, ctx, extra_pass);
> if (ret > 0) {
> i++;
> - if (ctx->insns == NULL)
> - ctx->offset[i] = ctx->ninsns;
> + if (offset)
> + offset[i] = ctx->ninsns;
> continue;
> }
> - if (ctx->insns == NULL)
> - ctx->offset[i] = ctx->ninsns;
> + if (offset)
> + offset[i] = ctx->ninsns;
> if (ret)
> return ret;
> }
> @@ -1553,8 +1565,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
> struct bpf_prog *tmp, *orig_prog = prog;
> int pass = 0, prev_ninsns = 0, i;
> struct rv_jit_data *jit_data;
> + unsigned int image_size = 0;
> struct rv_jit_context *ctx;
> - unsigned int image_size;
>
> if (!prog->jit_requested)
> return orig_prog;
> @@ -1599,36 +1611,51 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
> for (i = 0; i < 16; i++) {
> pass++;
> ctx->ninsns = 0;
> - if (build_body(ctx, extra_pass)) {
> + if (build_body(ctx, extra_pass, ctx->offset)) {
> prog = orig_prog;
> goto out_offset;
> }
> build_prologue(ctx);
> ctx->epilogue_offset = ctx->ninsns;
> build_epilogue(ctx);
> - if (ctx->ninsns == prev_ninsns)
> - break;
> +
> + if (ctx->ninsns == prev_ninsns) {
> + if (jit_data->header)
> + break;
> +
> + image_size = sizeof(u32) * ctx->ninsns;
> + jit_data->header =
> + bpf_jit_binary_alloc(image_size,
> + &jit_data->image,
> + sizeof(u32),
> + bpf_fill_ill_insns);
> + if (!jit_data->header) {
> + prog = orig_prog;
> + goto out_offset;
> + }
> +
> + ctx->insns = (u32 *)jit_data->image;
> + /* Now, when the image is allocated, the image
> + * can potentially shrink more (auipc/jalr ->
> + * jal).
> + */
> + }
It seems like these fragments should go along with patch #2 that introduces the
code, as I don't see anything above that makes this necessary here.
> prev_ninsns = ctx->ninsns;
> }
>
> - /* Allocate image, now that we know the size. */
> - image_size = sizeof(u32) * ctx->ninsns;
> - jit_data->header = bpf_jit_binary_alloc(image_size, &jit_data->image,
> - sizeof(u32),
> - bpf_fill_ill_insns);
> - if (!jit_data->header) {
> + if (i == 16) {
> + pr_err("bpf-jit: image did not converge in <%d passes!\n", i);
> + bpf_jit_binary_free(jit_data->header);
> prog = orig_prog;
> goto out_offset;
> }
>
> - /* Second, real pass, that acutally emits the image. */
> - ctx->insns = (u32 *)jit_data->image;
> skip_init_ctx:
> pass++;
> ctx->ninsns = 0;
>
> build_prologue(ctx);
> - if (build_body(ctx, extra_pass)) {
> + if (build_body(ctx, extra_pass, NULL)) {
> bpf_jit_binary_free(jit_data->header);
> prog = orig_prog;
> goto out_offset;
next prev parent reply other threads:[~2019-12-23 18:58 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-16 9:13 [PATCH bpf-next v2 0/9] riscv: BPF JIT fix, optimizations and far jumps support Björn Töpel
2019-12-16 9:13 ` [PATCH bpf-next v2 1/9] riscv, bpf: fix broken BPF tail calls Björn Töpel
2019-12-16 9:13 ` [PATCH bpf-next v2 2/9] riscv, bpf: add support for far branching Björn Töpel
2019-12-16 9:13 ` [PATCH bpf-next v2 3/9] riscv, bpf: add support for far branching when emitting tail call Björn Töpel
2019-12-16 9:13 ` [PATCH bpf-next v2 4/9] riscv, bpf: add support for far jumps and exits Björn Töpel
2019-12-16 9:13 ` [PATCH bpf-next v2 5/9] riscv, bpf: optimize BPF tail calls Björn Töpel
2019-12-16 9:13 ` [PATCH bpf-next v2 6/9] riscv, bpf: provide RISC-V specific JIT image alloc/free Björn Töpel
2019-12-16 15:09 ` Daniel Borkmann
2019-12-18 6:23 ` Björn Töpel
2020-01-04 1:32 ` Paul Walmsley
2020-01-07 10:24 ` Björn Töpel
2020-01-07 10:47 ` Paul Walmsley
2020-02-02 13:37 ` Alex Ghiti
2020-02-03 12:28 ` Björn Töpel
2020-02-03 20:57 ` Alex Ghiti
2019-12-16 9:13 ` [PATCH bpf-next v2 7/9] riscv, bpf: optimize calls Björn Töpel
2019-12-16 9:13 ` [PATCH bpf-next v2 8/9] riscv, bpf: add missing uapi header for BPF_PROG_TYPE_PERF_EVENT programs Björn Töpel
2019-12-16 9:13 ` [PATCH bpf-next v2 9/9] riscv, perf: add arch specific perf_arch_bpf_user_pt_regs Björn Töpel
2019-12-19 15:07 ` [PATCH bpf-next v2 0/9] riscv: BPF JIT fix, optimizations and far jumps support Daniel Borkmann
2019-12-19 22:02 ` [PATCH bpf-next v2 1/9] riscv, bpf: fix broken BPF tail calls Palmer Dabbelt
2019-12-23 18:03 ` [PATCH bpf-next v2 2/9] riscv, bpf: add support for far branching Palmer Dabbelt
2020-01-07 8:13 ` Björn Töpel
2020-01-23 2:08 ` Palmer Dabbelt
2019-12-23 18:18 ` [PATCH bpf-next v2 3/9] riscv, bpf: add support for far branching when emitting tail call Palmer Dabbelt
2019-12-23 18:18 ` [PATCH bpf-next v2 4/9] riscv, bpf: add support for far jumps and exits Palmer Dabbelt
2019-12-23 18:29 ` [PATCH bpf-next v2 5/9] riscv, bpf: optimize BPF tail calls Palmer Dabbelt
2019-12-23 18:30 ` [PATCH bpf-next v2 6/9] riscv, bpf: provide RISC-V specific JIT image alloc/free Palmer Dabbelt
2019-12-23 18:58 ` Palmer Dabbelt [this message]
2020-01-07 10:14 ` [PATCH bpf-next v2 7/9] riscv, bpf: optimize calls Björn Töpel
2020-01-28 2:15 ` Palmer Dabbelt
2020-02-03 12:11 ` Björn Töpel
2019-12-23 18:58 ` [PATCH bpf-next v2 8/9] riscv, bpf: add missing uapi header for BPF_PROG_TYPE_PERF_EVENT programs Palmer Dabbelt
2019-12-23 18:58 ` [PATCH bpf-next v2 9/9] riscv, perf: add arch specific perf_arch_bpf_user_pt_regs Palmer Dabbelt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=mhng-041b1051-f9ac-4cd8-95bf-731bb1bfbdb8@palmerdabbelt-glaptop \
--to=palmerdabbelt@google.com \
--cc=ast@kernel.org \
--cc=bjorn.topel@gmail.com \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=linux-riscv@lists.infradead.org \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).