mirror of https://gitee.com/openkylin/linux.git
bpf: powerpc64: optimize JIT passes for bpf function calls
Once the JITed images for each function in a multi-function program are generated after the first three JIT passes, we only need to fix the target address for the branch instruction corresponding to each bpf-to-bpf function call. This introduces the following optimizations for reducing the work done by the JIT compiler when handling multi-function programs: [1] Instead of doing two extra passes to fix the bpf function calls, do just one as that would be sufficient. [2] During the extra pass, only overwrite the instruction sequences for the bpf-to-bpf function calls as everything else would still remain exactly the same. This also reduces the number of writes to the JITed image. [3] Do not regenerate the prologue and the epilogue during the extra pass as that would be redundant. Signed-off-by: Sandipan Das <sandipan@linux.ibm.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
parent
dcb40590e6
commit
025dceb0fa
|
@ -891,6 +891,55 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fix the branch target addresses for subprog calls */
|
||||||
|
static int bpf_jit_fixup_subprog_calls(struct bpf_prog *fp, u32 *image,
|
||||||
|
struct codegen_context *ctx, u32 *addrs)
|
||||||
|
{
|
||||||
|
const struct bpf_insn *insn = fp->insnsi;
|
||||||
|
bool func_addr_fixed;
|
||||||
|
u64 func_addr;
|
||||||
|
u32 tmp_idx;
|
||||||
|
int i, ret;
|
||||||
|
|
||||||
|
for (i = 0; i < fp->len; i++) {
|
||||||
|
/*
|
||||||
|
* During the extra pass, only the branch target addresses for
|
||||||
|
* the subprog calls need to be fixed. All other instructions
|
||||||
|
* can left untouched.
|
||||||
|
*
|
||||||
|
* The JITed image length does not change because we already
|
||||||
|
* ensure that the JITed instruction sequence for these calls
|
||||||
|
* are of fixed length by padding them with NOPs.
|
||||||
|
*/
|
||||||
|
if (insn[i].code == (BPF_JMP | BPF_CALL) &&
|
||||||
|
insn[i].src_reg == BPF_PSEUDO_CALL) {
|
||||||
|
ret = bpf_jit_get_func_addr(fp, &insn[i], true,
|
||||||
|
&func_addr,
|
||||||
|
&func_addr_fixed);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save ctx->idx as this would currently point to the
|
||||||
|
* end of the JITed image and set it to the offset of
|
||||||
|
* the instruction sequence corresponding to the
|
||||||
|
* subprog call temporarily.
|
||||||
|
*/
|
||||||
|
tmp_idx = ctx->idx;
|
||||||
|
ctx->idx = addrs[i] / 4;
|
||||||
|
bpf_jit_emit_func_call_rel(image, ctx, func_addr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Restore ctx->idx here. This is safe as the length
|
||||||
|
* of the JITed sequence remains unchanged.
|
||||||
|
*/
|
||||||
|
ctx->idx = tmp_idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct powerpc64_jit_data {
|
struct powerpc64_jit_data {
|
||||||
struct bpf_binary_header *header;
|
struct bpf_binary_header *header;
|
||||||
u32 *addrs;
|
u32 *addrs;
|
||||||
|
@ -989,6 +1038,22 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
|
||||||
skip_init_ctx:
|
skip_init_ctx:
|
||||||
code_base = (u32 *)(image + FUNCTION_DESCR_SIZE);
|
code_base = (u32 *)(image + FUNCTION_DESCR_SIZE);
|
||||||
|
|
||||||
|
if (extra_pass) {
|
||||||
|
/*
|
||||||
|
* Do not touch the prologue and epilogue as they will remain
|
||||||
|
* unchanged. Only fix the branch target address for subprog
|
||||||
|
* calls in the body.
|
||||||
|
*
|
||||||
|
* This does not change the offsets and lengths of the subprog
|
||||||
|
* call instruction sequences and hence, the size of the JITed
|
||||||
|
* image as well.
|
||||||
|
*/
|
||||||
|
bpf_jit_fixup_subprog_calls(fp, code_base, &cgctx, addrs);
|
||||||
|
|
||||||
|
/* There is no need to perform the usual passes. */
|
||||||
|
goto skip_codegen_passes;
|
||||||
|
}
|
||||||
|
|
||||||
/* Code generation passes 1-2 */
|
/* Code generation passes 1-2 */
|
||||||
for (pass = 1; pass < 3; pass++) {
|
for (pass = 1; pass < 3; pass++) {
|
||||||
/* Now build the prologue, body code & epilogue for real. */
|
/* Now build the prologue, body code & epilogue for real. */
|
||||||
|
@ -1002,6 +1067,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
|
||||||
proglen - (cgctx.idx * 4), cgctx.seen);
|
proglen - (cgctx.idx * 4), cgctx.seen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skip_codegen_passes:
|
||||||
if (bpf_jit_enable > 1)
|
if (bpf_jit_enable > 1)
|
||||||
/*
|
/*
|
||||||
* Note that we output the base address of the code_base
|
* Note that we output the base address of the code_base
|
||||||
|
|
Loading…
Reference in New Issue