Skip to content

Commit c899e73

Browse files
author
Fox Snowpatch
committed
1 parent 5c2c0ba commit c899e73

7 files changed

Lines changed: 142 additions & 19 deletions

File tree

arch/powerpc/net/bpf_jit.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,8 @@ int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *
214214
int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct codegen_context *ctx,
215215
u32 *addrs, int pass, bool extra_pass);
216216
void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx);
217-
void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx);
218-
void bpf_jit_build_fentry_stubs(u32 *image, struct codegen_context *ctx);
217+
void bpf_jit_build_epilogue(u32 *image, u32 *fimage, struct codegen_context *ctx);
218+
void bpf_jit_build_fentry_stubs(u32 *image, u32 *fimage, struct codegen_context *ctx);
219219
void bpf_jit_realloc_regs(struct codegen_context *ctx);
220220
int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg, long exit_addr);
221221
void prepare_for_fsession_fentry(u32 *image, struct codegen_context *ctx, int cookie_cnt,

arch/powerpc/net/bpf_jit_comp.c

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,34 @@ asm (
4949
" .popsection ;"
5050
);
5151

52-
void bpf_jit_build_fentry_stubs(u32 *image, struct codegen_context *ctx)
52+
void bpf_jit_build_fentry_stubs(u32 *image, u32 *fimage, struct codegen_context *ctx)
5353
{
5454
int ool_stub_idx, long_branch_stub_idx;
5555

5656
/*
57+
* In the final pass, align the mis-aligned dummy tramp address
58+
* in the fimage. The alignment NOP must appear before OOL stub,
59+
* to make ool_stub_idx & long_branch_stub_idx constant from end.
60+
*
61+
* Need alignment NOP in following conditions:
62+
*
63+
* OOL stub aligned CONFIG_PPC_FTRACE_OUT_OF_LINE Alignment NOP
64+
* Y Y N
65+
* Y N Y
66+
* N Y Y
67+
* N N N
68+
*/
69+
#ifdef CONFIG_PPC64
70+
if (fimage && image) {
71+
unsigned long pc = (unsigned long)fimage + CTX_NIA(ctx);
72+
73+
if (IS_ALIGNED(pc, 8) ^
74+
IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE))
75+
EMIT(PPC_RAW_NOP());
76+
}
77+
#endif
78+
79+
/* nop // optional, for alignment of dummy_tramp_addr
5780
* Out-of-line stub:
5881
* mflr r0
5982
* [b|bl] tramp
@@ -70,26 +93,36 @@ void bpf_jit_build_fentry_stubs(u32 *image, struct codegen_context *ctx)
7093

7194
/*
7295
* Long branch stub:
73-
* .long <dummy_tramp_addr>
7496
* mflr r11
7597
* bcl 20,31,$+4
76-
* mflr r12
77-
* ld r12, -8-SZL(r12)
98+
* mflr r12 // lr/r12 stores current pc
99+
* ld r12, 20(r12) // offset(dummy_tramp_addr) from prev inst. is 20
78100
* mtctr r12
79-
* mtlr r11 // needed to retain ftrace ABI
101+
* mtlr r11 // needed to retain ftrace ABI
80102
* bctr
103+
* nop // for alignment of following address field
104+
* .long <dummy_tramp_addr> // 8-byte aligned
81105
*/
82-
if (image)
83-
*((unsigned long *)&image[ctx->idx]) = (unsigned long)dummy_tramp;
84-
ctx->idx += SZL / 4;
85106
long_branch_stub_idx = ctx->idx;
86107
EMIT(PPC_RAW_MFLR(_R11));
87108
EMIT(PPC_RAW_BCL4());
88109
EMIT(PPC_RAW_MFLR(_R12));
89-
EMIT(PPC_RAW_LL(_R12, _R12, -8-SZL));
110+
EMIT(PPC_RAW_LL(_R12, _R12, 20));
90111
EMIT(PPC_RAW_MTCTR(_R12));
91112
EMIT(PPC_RAW_MTLR(_R11));
92113
EMIT(PPC_RAW_BCTR());
114+
/*
115+
* The start of Long branch stub is guaranteed to be aligned as
116+
* result of optional NOP injection before OOL stub above.
117+
* Append tail NOP to re-gain 8-byte alignment disturbed by odd
118+
* instruction count in Long branch stub.
119+
*/
120+
EMIT(PPC_RAW_NOP());
121+
122+
if (image)
123+
*((unsigned long *)&image[ctx->idx]) = (unsigned long)dummy_tramp;
124+
125+
ctx->idx += SZL / 4;
93126

94127
if (!bpf_jit_ool_stub) {
95128
bpf_jit_ool_stub = (ctx->idx - ool_stub_idx) * 4;
@@ -107,7 +140,7 @@ int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg,
107140
PPC_JMP(ctx->alt_exit_addr);
108141
} else {
109142
ctx->alt_exit_addr = ctx->idx * 4;
110-
bpf_jit_build_epilogue(image, ctx);
143+
bpf_jit_build_epilogue(image, NULL, ctx);
111144
}
112145

113146
return 0;
@@ -308,7 +341,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
308341
*/
309342
bpf_jit_build_prologue(NULL, &cgctx);
310343
addrs[fp->len] = cgctx.idx * 4;
311-
bpf_jit_build_epilogue(NULL, &cgctx);
344+
bpf_jit_build_epilogue(NULL, NULL, &cgctx);
312345

313346
fixup_len = fp->aux->num_exentries * BPF_FIXUP_LEN * 4;
314347
extable_len = fp->aux->num_exentries * sizeof(struct exception_table_entry);
@@ -343,7 +376,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
343376
fp = org_fp;
344377
goto out_addrs;
345378
}
346-
bpf_jit_build_epilogue(code_base, &cgctx);
379+
bpf_jit_build_epilogue(code_base, fcode_base, &cgctx);
347380

348381
if (bpf_jit_enable > 1)
349382
pr_info("Pass %d: shrink = %d, seen = 0x%x\n", pass,
@@ -1280,21 +1313,23 @@ static void do_isync(void *info __maybe_unused)
12801313
* bpf_func:
12811314
* [nop|b] ool_stub
12821315
* 2. Out-of-line stub:
1316+
* nop // optional nop for alignment
12831317
* ool_stub:
12841318
* mflr r0
12851319
* [b|bl] <bpf_prog>/<long_branch_stub>
12861320
* mtlr r0 // CONFIG_PPC_FTRACE_OUT_OF_LINE only
12871321
* b bpf_func + 4
12881322
* 3. Long branch stub:
12891323
* long_branch_stub:
1290-
* .long <branch_addr>/<dummy_tramp>
12911324
* mflr r11
12921325
* bcl 20,31,$+4
12931326
* mflr r12
12941327
* ld r12, -16(r12)
12951328
* mtctr r12
12961329
* mtlr r11 // needed to retain ftrace ABI
12971330
* bctr
1331+
* nop // nop for mem alignment of dummy_tramp_addr
1332+
* .long <branch_addr>/<dummy_tramp>
12981333
*
12991334
* dummy_tramp is used to reduce synchronization requirements.
13001335
*
@@ -1396,10 +1431,12 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
13961431
* 1. Update the address in the long branch stub:
13971432
* If new_addr is out of range, we will have to use the long branch stub, so patch new_addr
13981433
* here. Otherwise, revert to dummy_tramp, but only if we had patched old_addr here.
1434+
*
1435+
* dummy_tramp_addr moved to bottom of long branch stub.
13991436
*/
14001437
if ((new_addr && !is_offset_in_branch_range(new_addr - ip)) ||
14011438
(old_addr && !is_offset_in_branch_range(old_addr - ip)))
1402-
ret = patch_ulong((void *)(bpf_func_end - bpf_jit_long_branch_stub - SZL),
1439+
ret = patch_ulong((void *)(bpf_func_end - SZL), /* SZL: dummy_tramp_addr offset */
14031440
(new_addr && !is_offset_in_branch_range(new_addr - ip)) ?
14041441
(unsigned long)new_addr : (unsigned long)dummy_tramp);
14051442
if (ret)

arch/powerpc/net/bpf_jit_comp64.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ static void bpf_jit_emit_common_epilogue(u32 *image, struct codegen_context *ctx
398398
}
399399
}
400400

401-
void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
401+
void bpf_jit_build_epilogue(u32 *image, u32 *fimage, struct codegen_context *ctx)
402402
{
403403
bpf_jit_emit_common_epilogue(image, ctx);
404404

@@ -407,7 +407,7 @@ void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
407407

408408
EMIT(PPC_RAW_BLR());
409409

410-
bpf_jit_build_fentry_stubs(image, ctx);
410+
bpf_jit_build_fentry_stubs(image, fimage, ctx);
411411
}
412412

413413
/*

tools/testing/selftests/bpf/jit_disasm_helpers.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,11 @@ int get_jited_program_text(int fd, char *text, size_t text_sz)
170170
struct bpf_prog_info info = {};
171171
__u32 info_len = sizeof(info);
172172
__u32 jited_funcs, len, pc;
173+
__u32 trunc_len = 0;
173174
__u32 *func_lens = NULL;
174175
FILE *text_out = NULL;
175176
uint8_t *image = NULL;
177+
char *triple = NULL;
176178
int i, err = 0;
177179

178180
if (!llvm_initialized) {
@@ -216,9 +218,18 @@ int get_jited_program_text(int fd, char *text, size_t text_sz)
216218
if (!ASSERT_OK(err, "bpf_prog_get_info_by_fd #2"))
217219
goto out;
218220

221+
/*
222+
* last 8 bytes contains dummy_trampoline address in JIT
223+
* output for 64-bit and 32-bit powerpc, which can't
224+
* disassemble a to valid instruction.
225+
*/
226+
triple = LLVMGetDefaultTargetTriple();
227+
if (strstr(triple, "powerpc"))
228+
trunc_len = 8;
229+
219230
for (pc = 0, i = 0; i < jited_funcs; ++i) {
220231
fprintf(text_out, "func #%d:\n", i);
221-
disasm_one_func(text_out, image + pc, func_lens[i]);
232+
disasm_one_func(text_out, image + pc, func_lens[i] - trunc_len);
222233
fprintf(text_out, "\n");
223234
pc += func_lens[i];
224235
}

tools/testing/selftests/bpf/progs/bpf_misc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@
155155
#define __arch_arm64 __arch("ARM64")
156156
#define __arch_riscv64 __arch("RISCV64")
157157
#define __arch_s390x __arch("s390x")
158+
#define __arch_powerpc64 __arch("POWERPC64")
158159
#define __caps_unpriv(caps) __attribute__((btf_decl_tag("comment:test_caps_unpriv=" EXPAND_QUOTE(caps))))
159160
#define __load_if_JITed() __attribute__((btf_decl_tag("comment:load_mode=jited")))
160161
#define __load_if_no_JITed() __attribute__((btf_decl_tag("comment:load_mode=no_jited")))

tools/testing/selftests/bpf/progs/verifier_tailcall_jit.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,75 @@ __jited(" popq %rax")
9090
__jited(" jmp {{.*}}") /* jump to tail call tgt */
9191
__jited("L0: leave")
9292
__jited(" {{(retq|jmp 0x)}}") /* return or jump to rethunk */
93+
__arch_powerpc64
94+
/* program entry for main(), regular function prologue */
95+
__jited(" nop")
96+
__jited(" ld 2, 16(13)")
97+
__jited(" li 9, 0")
98+
__jited(" std 9, -8(1)")
99+
__jited(" mflr 0")
100+
__jited(" std 0, 16(1)")
101+
__jited(" stdu 1, {{.*}}(1)")
102+
/* load address and call sub() via count register */
103+
__jited(" lis 12, {{.*}}")
104+
__jited(" sldi 12, 12, 32")
105+
__jited(" oris 12, 12, {{.*}}")
106+
__jited(" ori 12, 12, {{.*}}")
107+
__jited(" mtctr 12")
108+
__jited(" bctrl")
109+
__jited(" mr 8, 3")
110+
__jited(" li 8, 0")
111+
__jited(" addi 1, 1, {{.*}}")
112+
__jited(" ld 0, 16(1)")
113+
__jited(" mtlr 0")
114+
__jited(" mr 3, 8")
115+
__jited(" blr")
116+
__jited("...")
117+
__jited("func #1")
118+
/* subprogram entry for sub() */
119+
__jited(" nop")
120+
__jited(" ld 2, 16(13)")
121+
/* tail call prologue for subprogram */
122+
__jited(" ld 10, 0(1)")
123+
__jited(" ld 9, -8(10)")
124+
__jited(" cmplwi 9, 33")
125+
__jited(" bt {{.*}}, {{.*}}")
126+
__jited(" addi 9, 10, -8")
127+
__jited(" std 9, -8(1)")
128+
__jited(" lis {{.*}}, {{.*}}")
129+
__jited(" sldi {{.*}}, {{.*}}, 32")
130+
__jited(" oris {{.*}}, {{.*}}, {{.*}}")
131+
__jited(" ori {{.*}}, {{.*}}, {{.*}}")
132+
__jited(" li {{.*}}, 0")
133+
__jited(" lwz 9, {{.*}}({{.*}})")
134+
__jited(" slwi {{.*}}, {{.*}}, 0")
135+
__jited(" cmplw {{.*}}, 9")
136+
__jited(" bf 0, {{.*}}")
137+
/* bpf_tail_call implementation */
138+
__jited(" ld 9, -8(1)")
139+
__jited(" cmplwi 9, 33")
140+
__jited(" bf {{.*}}, {{.*}}")
141+
__jited(" ld 9, 0(9)")
142+
__jited(" cmplwi 9, 33")
143+
__jited(" bt {{.*}}, {{.*}}")
144+
__jited(" addi 9, 9, 1")
145+
__jited(" mulli 10, {{.*}}, 8")
146+
__jited(" add 10, 10, {{.*}}")
147+
__jited(" ld 10, {{.*}}(10)")
148+
__jited(" cmpldi 10, 0")
149+
__jited(" bt {{.*}}, {{.*}}")
150+
__jited(" ld 10, {{.*}}(10)")
151+
__jited(" addi 10, 10, 16")
152+
__jited(" mtctr 10")
153+
__jited(" ld 10, -8(1)")
154+
__jited(" cmplwi 10, 33")
155+
__jited(" bt {{.*}}, {{.*}}")
156+
__jited(" addi 10, 1, -8")
157+
__jited(" std 9, 0(10)")
158+
__jited(" bctr")
159+
__jited(" mr 3, 8")
160+
__jited(" blr")
161+
93162
SEC("tc")
94163
__naked int main(void)
95164
{

tools/testing/selftests/bpf/test_loader.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ enum arch {
378378
ARCH_ARM64 = 0x4,
379379
ARCH_RISCV64 = 0x8,
380380
ARCH_S390X = 0x10,
381+
ARCH_POWERPC64 = 0x20,
381382
};
382383

383384
static int get_current_arch(void)
@@ -390,6 +391,8 @@ static int get_current_arch(void)
390391
return ARCH_RISCV64;
391392
#elif defined(__s390x__)
392393
return ARCH_S390X;
394+
#elif defined(__powerpc64__)
395+
return ARCH_POWERPC64;
393396
#endif
394397
return ARCH_UNKNOWN;
395398
}
@@ -587,6 +590,8 @@ static int parse_test_spec(struct test_loader *tester,
587590
arch = ARCH_RISCV64;
588591
} else if (strcmp(val, "s390x") == 0) {
589592
arch = ARCH_S390X;
593+
} else if (strcmp(val, "POWERPC64") == 0) {
594+
arch = ARCH_POWERPC64;
590595
} else {
591596
PRINT_FAIL("bad arch spec: '%s'\n", val);
592597
err = -EINVAL;

0 commit comments

Comments
 (0)