Skip to content

Commit 13489e7

Browse files
hbathiniKernel Patches Daemon
authored and
Kernel Patches Daemon
committed
powerpc/bpf: fix JIT code size calculation of bpf trampoline
arch_bpf_trampoline_size() provides JIT size of the BPF trampoline before the buffer for JIT'ing it is allocated. The total number of instructions emitted for BPF trampoline JIT code depends on where the final image is located. So, the size arrived at with the dummy pass in arch_bpf_trampoline_size() can vary from the actual size needed in arch_prepare_bpf_trampoline(). When the instructions accounted in arch_bpf_trampoline_size() is less than the number of instructions emitted during the actual JIT compile of the trampoline, the below warning is produced: WARNING: CPU: 8 PID: 204190 at arch/powerpc/net/bpf_jit_comp.c:981 __arch_prepare_bpf_trampoline.isra.0+0xd2c/0xdcc which is: /* Make sure the trampoline generation logic doesn't overflow */ if (image && WARN_ON_ONCE(&image[ctx->idx] > (u32 *)rw_image_end - BPF_INSN_SAFETY)) { So, during the dummy pass, instead of providing some arbitrary image location, account for maximum possible instructions if and when there is a dependency with image location for JIT'ing. Fixes: d243b62 ("powerpc64/bpf: Add support for bpf trampolines") Reported-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com> Closes: https://lore.kernel.org/all/6168bfc8-659f-4b5a-a6fb-90a916dde3b3@linux.ibm.com/ Cc: stable@vger.kernel.org # v6.13+ Acked-by: Naveen N Rao (AMD) <naveen@kernel.org> Tested-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com> Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
1 parent 97831b9 commit 13489e7

File tree

4 files changed

+35
-39
lines changed

4 files changed

+35
-39
lines changed

arch/powerpc/net/bpf_jit.h

+17-3
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,32 @@
5151
EMIT(PPC_INST_BRANCH_COND | (((cond) & 0x3ff) << 16) | (offset & 0xfffc)); \
5252
} while (0)
5353

54-
/* Sign-extended 32-bit immediate load */
54+
/*
55+
* Sign-extended 32-bit immediate load
56+
*
57+
* If this is a dummy pass (!image), account for
58+
* maximum possible instructions.
59+
*/
5560
#define PPC_LI32(d, i) do { \
61+
if (!image) \
62+
ctx->idx += 2; \
63+
else { \
5664
if ((int)(uintptr_t)(i) >= -32768 && \
5765
(int)(uintptr_t)(i) < 32768) \
5866
EMIT(PPC_RAW_LI(d, i)); \
5967
else { \
6068
EMIT(PPC_RAW_LIS(d, IMM_H(i))); \
6169
if (IMM_L(i)) \
6270
EMIT(PPC_RAW_ORI(d, d, IMM_L(i))); \
63-
} } while(0)
71+
} \
72+
} } while (0)
6473

6574
#ifdef CONFIG_PPC64
75+
/* If dummy pass (!image), account for maximum possible instructions */
6676
#define PPC_LI64(d, i) do { \
77+
if (!image) \
78+
ctx->idx += 5; \
79+
else { \
6780
if ((long)(i) >= -2147483648 && \
6881
(long)(i) < 2147483648) \
6982
PPC_LI32(d, i); \
@@ -84,7 +97,8 @@
8497
if ((uintptr_t)(i) & 0x000000000000ffffULL) \
8598
EMIT(PPC_RAW_ORI(d, d, (uintptr_t)(i) & \
8699
0xffff)); \
87-
} } while (0)
100+
} \
101+
} } while (0)
88102
#define PPC_LI_ADDR PPC_LI64
89103

90104
#ifndef CONFIG_PPC_KERNEL_PCREL

arch/powerpc/net/bpf_jit_comp.c

+10-23
Original file line numberDiff line numberDiff line change
@@ -504,10 +504,11 @@ static int invoke_bpf_prog(u32 *image, u32 *ro_image, struct codegen_context *ct
504504
EMIT(PPC_RAW_ADDI(_R3, _R1, regs_off));
505505
if (!p->jited)
506506
PPC_LI_ADDR(_R4, (unsigned long)p->insnsi);
507-
if (!create_branch(&branch_insn, (u32 *)&ro_image[ctx->idx], (unsigned long)p->bpf_func,
508-
BRANCH_SET_LINK)) {
509-
if (image)
510-
image[ctx->idx] = ppc_inst_val(branch_insn);
507+
/* Account for max possible instructions during dummy pass for size calculation */
508+
if (image && !create_branch(&branch_insn, (u32 *)&ro_image[ctx->idx],
509+
(unsigned long)p->bpf_func,
510+
BRANCH_SET_LINK)) {
511+
image[ctx->idx] = ppc_inst_val(branch_insn);
511512
ctx->idx++;
512513
} else {
513514
EMIT(PPC_RAW_LL(_R12, _R25, offsetof(struct bpf_prog, bpf_func)));
@@ -889,7 +890,8 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
889890
bpf_trampoline_restore_tail_call_cnt(image, ctx, func_frame_offset, r4_off);
890891

891892
/* Reserve space to patch branch instruction to skip fexit progs */
892-
im->ip_after_call = &((u32 *)ro_image)[ctx->idx];
893+
if (ro_image) /* image is NULL for dummy pass */
894+
im->ip_after_call = &((u32 *)ro_image)[ctx->idx];
893895
EMIT(PPC_RAW_NOP());
894896
}
895897

@@ -912,7 +914,8 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
912914
}
913915

914916
if (flags & BPF_TRAMP_F_CALL_ORIG) {
915-
im->ip_epilogue = &((u32 *)ro_image)[ctx->idx];
917+
if (ro_image) /* image is NULL for dummy pass */
918+
im->ip_epilogue = &((u32 *)ro_image)[ctx->idx];
916919
PPC_LI_ADDR(_R3, im);
917920
ret = bpf_jit_emit_func_call_rel(image, ro_image, ctx,
918921
(unsigned long)__bpf_tramp_exit);
@@ -973,25 +976,9 @@ int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
973976
struct bpf_tramp_links *tlinks, void *func_addr)
974977
{
975978
struct bpf_tramp_image im;
976-
void *image;
977979
int ret;
978980

979-
/*
980-
* Allocate a temporary buffer for __arch_prepare_bpf_trampoline().
981-
* This will NOT cause fragmentation in direct map, as we do not
982-
* call set_memory_*() on this buffer.
983-
*
984-
* We cannot use kvmalloc here, because we need image to be in
985-
* module memory range.
986-
*/
987-
image = bpf_jit_alloc_exec(PAGE_SIZE);
988-
if (!image)
989-
return -ENOMEM;
990-
991-
ret = __arch_prepare_bpf_trampoline(&im, image, image + PAGE_SIZE, image,
992-
m, flags, tlinks, func_addr);
993-
bpf_jit_free_exec(image);
994-
981+
ret = __arch_prepare_bpf_trampoline(&im, NULL, NULL, NULL, m, flags, tlinks, func_addr);
995982
return ret;
996983
}
997984

arch/powerpc/net/bpf_jit_comp32.c

-6
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,6 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code
313313
u64 func_addr;
314314
u32 true_cond;
315315
u32 tmp_idx;
316-
int j;
317316

318317
if (i && (BPF_CLASS(code) == BPF_ALU64 || BPF_CLASS(code) == BPF_ALU) &&
319318
(BPF_CLASS(prevcode) == BPF_ALU64 || BPF_CLASS(prevcode) == BPF_ALU) &&
@@ -1099,13 +1098,8 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code
10991098
* 16 byte instruction that uses two 'struct bpf_insn'
11001099
*/
11011100
case BPF_LD | BPF_IMM | BPF_DW: /* dst = (u64) imm */
1102-
tmp_idx = ctx->idx;
11031101
PPC_LI32(dst_reg_h, (u32)insn[i + 1].imm);
11041102
PPC_LI32(dst_reg, (u32)insn[i].imm);
1105-
/* padding to allow full 4 instructions for later patching */
1106-
if (!image)
1107-
for (j = ctx->idx - tmp_idx; j < 4; j++)
1108-
EMIT(PPC_RAW_NOP());
11091103
/* Adjust for two bpf instructions */
11101104
addrs[++i] = ctx->idx * 4;
11111105
break;

arch/powerpc/net/bpf_jit_comp64.c

+8-7
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,14 @@ int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *
227227
#ifdef CONFIG_PPC_KERNEL_PCREL
228228
reladdr = func_addr - local_paca->kernelbase;
229229

230-
if (reladdr < (long)SZ_8G && reladdr >= -(long)SZ_8G) {
230+
/*
231+
* If fimage is NULL (the initial pass to find image size),
232+
* account for the maximum no. of instructions possible.
233+
*/
234+
if (!fimage) {
235+
ctx->idx += 7;
236+
return 0;
237+
} else if (reladdr < (long)SZ_8G && reladdr >= -(long)SZ_8G) {
231238
EMIT(PPC_RAW_LD(_R12, _R13, offsetof(struct paca_struct, kernelbase)));
232239
/* Align for subsequent prefix instruction */
233240
if (!IS_ALIGNED((unsigned long)fimage + CTX_NIA(ctx), 8))
@@ -412,7 +419,6 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code
412419
u64 imm64;
413420
u32 true_cond;
414421
u32 tmp_idx;
415-
int j;
416422

417423
/*
418424
* addrs[] maps a BPF bytecode address into a real offset from
@@ -1046,12 +1052,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code
10461052
case BPF_LD | BPF_IMM | BPF_DW: /* dst = (u64) imm */
10471053
imm64 = ((u64)(u32) insn[i].imm) |
10481054
(((u64)(u32) insn[i+1].imm) << 32);
1049-
tmp_idx = ctx->idx;
10501055
PPC_LI64(dst_reg, imm64);
1051-
/* padding to allow full 5 instructions for later patching */
1052-
if (!image)
1053-
for (j = ctx->idx - tmp_idx; j < 5; j++)
1054-
EMIT(PPC_RAW_NOP());
10551056
/* Adjust for two bpf instructions */
10561057
addrs[++i] = ctx->idx * 4;
10571058
break;

0 commit comments

Comments
 (0)