Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8a3208a

Browse files
committed
bpf, arm32: Add JIT support for BPF line info
Update current JIT offsets to enable and set up BPF line info for better introspection and debugging. Offsets map each xlated insn to the start of its JITed code, as well as the epilogue. This also allows simplifying some code and dropping unneeded JIT ctx variables. Taking bpf_iter_udp4.bpf.o as an example using bpftool's JIT disassembly, before this change we see: 48: ldr lr, [fp, #-44] @ 0xffffffd4 4c: strd r2, [lr, #-40] @ 0xffffffd8 50: ldr r8, [fp, #-44] @ 0xffffffd4 54: ldr r8, [r8, #-40] @ 0xffffffd8 58: ldr r2, [r8] 5c: mov r7, r2 60: ldr r2, [r7] 64: mov r3, #0 68: ldr r8, [fp, #-44] @ 0xffffffd4 6c: ldr r8, [r8, #-40] @ 0xffffffd8 70: ldr r6, [r8, torvalds#8] 74: ldr r9, [fp, #-44] @ 0xffffffd4 78: strd r6, [r9, #-48] @ 0xffffffd0 While afterwards we have: 48: ldr lr, [fp, #-44] @ 0xffffffd4 4c: strd r2, [lr, #-40] @ 0xffffffd8 ; struct seq_file *seq = ctx->meta->seq; 50: ldr r8, [fp, #-44] @ 0xffffffd4 54: ldr r8, [r8, #-40] @ 0xffffffd8 58: ldr r2, [r8] ; struct seq_file *seq = ctx->meta->seq; 5c: mov r7, r2 60: ldr r2, [r7] 64: mov r3, #0 ; struct udp_sock *udp_sk = ctx->udp_sk; 68: ldr r8, [fp, #-44] @ 0xffffffd4 6c: ldr r8, [r8, #-40] @ 0xffffffd8 70: ldr r6, [r8, torvalds#8] 74: ldr r9, [fp, #-44] @ 0xffffffd4 78: strd r6, [r9, #-48] @ 0xffffffd0 which aligns with the original source code. Signed-off-by: Tony Ambardar <[email protected]>
1 parent 383aa43 commit 8a3208a

File tree

1 file changed

+31
-31
lines changed

1 file changed

+31
-31
lines changed

arch/arm/net/bpf_jit_32.c

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,6 @@ static const s8 bpf2a32[][2] = {
179179
*
180180
* prog : bpf_prog
181181
* idx : index of current last JITed instruction.
182-
* prologue_bytes : bytes used in prologue.
183-
* epilogue_offset : offset of epilogue starting.
184182
* offsets : array of BPF instruction offsets in
185183
* JITed code.
186184
* target : final JITed code.
@@ -193,8 +191,6 @@ static const s8 bpf2a32[][2] = {
193191
struct jit_ctx {
194192
const struct bpf_prog *prog;
195193
unsigned int idx;
196-
unsigned int prologue_bytes;
197-
unsigned int epilogue_offset;
198194
unsigned int cpu_architecture;
199195
u32 flags;
200196
u32 *offsets;
@@ -417,8 +413,7 @@ static u16 imm_offset(u32 k, struct jit_ctx *ctx)
417413
ctx->imms[i] = k;
418414

419415
/* constants go just after the epilogue */
420-
offset = ctx->offsets[ctx->prog->len - 1] * 4;
421-
offset += ctx->prologue_bytes;
416+
offset = ctx->offsets[ctx->prog->len] * 4; /* epilogue start */
422417
offset += ctx->epilogue_bytes;
423418
offset += i * 4;
424419

@@ -447,8 +442,8 @@ static inline int bpf2a32_offset(int bpf_to, int bpf_from,
447442

448443
if (ctx->target == NULL)
449444
return 0;
450-
to = ctx->offsets[bpf_to];
451-
from = ctx->offsets[bpf_from];
445+
to = ctx->offsets[bpf_to + 1];
446+
from = ctx->offsets[bpf_from + 1];
452447

453448
return to - from - 1;
454449
}
@@ -499,7 +494,7 @@ static inline int epilogue_offset(const struct jit_ctx *ctx)
499494
/* No need for 1st dummy run */
500495
if (ctx->target == NULL)
501496
return 0;
502-
to = ctx->epilogue_offset;
497+
to = ctx->offsets[ctx->prog->len]; /* epilogue start */
503498
from = ctx->idx;
504499

505500
return to - from - 2;
@@ -2710,23 +2705,26 @@ static int build_body(struct jit_ctx *ctx, bool extra_pass)
27102705
const struct bpf_insn *insn = &(prog->insnsi[i]);
27112706
int ret;
27122707

2708+
/* Save start offset of each JITed insn. */
2709+
if (ctx->target == NULL)
2710+
ctx->offsets[i] = ctx->idx;
2711+
27132712
ret = build_insn(insn, ctx, extra_pass);
27142713

27152714
/* It's used with loading the 64 bit immediate value. */
27162715
if (ret > 0) {
27172716
i++;
2718-
if (ctx->target == NULL)
2719-
ctx->offsets[i] = ctx->idx;
27202717
continue;
27212718
}
27222719

2723-
if (ctx->target == NULL)
2724-
ctx->offsets[i] = ctx->idx;
2725-
27262720
/* If unsuccessful, return with error code */
27272721
if (ret)
27282722
return ret;
27292723
}
2724+
/* Finally save epilogue offset. */
2725+
if (ctx->target == NULL)
2726+
ctx->offsets[i] = ctx->idx;
2727+
27302728
return 0;
27312729
}
27322730

@@ -2766,7 +2764,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
27662764
bool tmp_blinded = false;
27672765
bool extra_pass = false;
27682766
struct jit_ctx ctx;
2769-
unsigned int tmp_idx;
27702767
unsigned int image_size;
27712768
u8 *image_ptr;
27722769

@@ -2812,10 +2809,10 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
28122809
ctx.cpu_architecture = cpu_architecture();
28132810
ctx.stack_size = JIT_ALIGN(prog->aux->stack_depth);
28142811

2815-
/* Not able to allocate memory for offsets[] , then
2812+
/* Not able to allocate memory for offsets[], then
28162813
* we must fall back to the interpreter
28172814
*/
2818-
ctx.offsets = kcalloc(prog->len, sizeof(int), GFP_KERNEL);
2815+
ctx.offsets = kcalloc(prog->len + 1, sizeof(int), GFP_KERNEL);
28192816
if (ctx.offsets == NULL) {
28202817
prog = orig_prog;
28212818
goto out_off;
@@ -2831,21 +2828,18 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
28312828
* being successful in the second pass, so just fall back
28322829
* to the interpreter.
28332830
*/
2831+
build_prologue(&ctx);
2832+
28342833
if (build_body(&ctx, extra_pass)) {
28352834
prog = orig_prog;
28362835
goto out_off;
28372836
}
28382837

2839-
tmp_idx = ctx.idx;
2840-
build_prologue(&ctx);
2841-
ctx.prologue_bytes = (ctx.idx - tmp_idx) * 4;
2842-
2843-
ctx.epilogue_offset = ctx.idx;
2838+
build_epilogue(&ctx);
28442839

2840+
/* On pre-ARMv7 append a literal pool of 32-bit imm constants. */
28452841
#if __LINUX_ARM_ARCH__ < 7
2846-
tmp_idx = ctx.idx;
2847-
build_epilogue(&ctx);
2848-
ctx.epilogue_bytes = (ctx.idx - tmp_idx) * 4;
2842+
ctx.epilogue_bytes = (ctx.idx - ctx.offsets[prog->len]) * 4;
28492843

28502844
ctx.idx += ctx.imm_count;
28512845
if (ctx.imm_count) {
@@ -2855,9 +2849,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
28552849
goto out_off;
28562850
}
28572851
}
2858-
#else
2859-
/* there's nothing about the epilogue on ARMv7 */
2860-
build_epilogue(&ctx);
28612852
#endif
28622853
/* Now we can get the actual image size of the JITed arm code.
28632854
* Currently, we are not considering the THUMB-2 instructions
@@ -2931,12 +2922,21 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
29312922

29322923
DEBUG_PASS(3);
29332924

2925+
if (!prog->is_func || extra_pass) {
2926+
int i;
2927+
/* BPF line info expects array of byte-offsets mapping each
2928+
* xlated insn to the end of its JITed insn (following byte),
2929+
* so convert to bytes and drop the first array elem mapping
2930+
* the proglogue.
2931+
*/
2932+
for (i = 0; i <= prog->len; i++)
2933+
ctx.offsets[i] *= 4;
2934+
bpf_prog_fill_jited_linfo(prog, ctx.offsets + 1);
29342935
out_imms:
29352936
#if __LINUX_ARM_ARCH__ < 7
2936-
if (ctx.imm_count)
2937-
kfree(ctx.imms);
2937+
if (ctx.imm_count)
2938+
kfree(ctx.imms);
29382939
#endif
2939-
if (!prog->is_func || extra_pass) {
29402940
out_off:
29412941
kfree(ctx.offsets);
29422942
kfree(jit_data);

0 commit comments

Comments
 (0)