Skip to content

Commit 5c2c0ba

Browse files
Automatic merge of 'next' into merge (2026-04-07 07:47)
2 parents 6f9715a + e1f7a0e commit 5c2c0ba

10 files changed

Lines changed: 285 additions & 57 deletions

File tree

arch/powerpc/net/bpf_jit.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,14 @@ struct codegen_context {
178178
bool is_subprog;
179179
bool exception_boundary;
180180
bool exception_cb;
181+
void __percpu *priv_sp;
182+
unsigned int priv_stack_size;
181183
};
182184

185+
/* Memory size & magic-value to detect private stack overflow/underflow */
186+
#define PRIV_STACK_GUARD_SZ 16
187+
#define PRIV_STACK_GUARD_VAL 0xEB9F12345678eb9fULL
188+
183189
#define bpf_to_ppc(r) (ctx->b2p[r])
184190

185191
#ifdef CONFIG_PPC32
@@ -212,7 +218,9 @@ void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx);
212218
void bpf_jit_build_fentry_stubs(u32 *image, struct codegen_context *ctx);
213219
void bpf_jit_realloc_regs(struct codegen_context *ctx);
214220
int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg, long exit_addr);
215-
221+
void prepare_for_fsession_fentry(u32 *image, struct codegen_context *ctx, int cookie_cnt,
222+
int cookie_off, int retval_off);
223+
void store_func_meta(u32 *image, struct codegen_context *ctx, u64 func_meta, int func_meta_off);
216224
int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, u32 *fimage, int pass,
217225
struct codegen_context *ctx, int insn_idx,
218226
int jmp_off, int dst_reg, u32 code);

arch/powerpc/net/bpf_jit_comp.c

Lines changed: 164 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -129,25 +129,60 @@ bool bpf_jit_needs_zext(void)
129129
return true;
130130
}
131131

132+
static void priv_stack_init_guard(void __percpu *priv_stack_ptr, int alloc_size)
133+
{
134+
int cpu, underflow_idx = (alloc_size - PRIV_STACK_GUARD_SZ) >> 3;
135+
u64 *stack_ptr;
136+
137+
for_each_possible_cpu(cpu) {
138+
stack_ptr = per_cpu_ptr(priv_stack_ptr, cpu);
139+
stack_ptr[0] = PRIV_STACK_GUARD_VAL;
140+
stack_ptr[1] = PRIV_STACK_GUARD_VAL;
141+
stack_ptr[underflow_idx] = PRIV_STACK_GUARD_VAL;
142+
stack_ptr[underflow_idx + 1] = PRIV_STACK_GUARD_VAL;
143+
}
144+
}
145+
146+
static void priv_stack_check_guard(void __percpu *priv_stack_ptr, int alloc_size,
147+
struct bpf_prog *fp)
148+
{
149+
int cpu, underflow_idx = (alloc_size - PRIV_STACK_GUARD_SZ) >> 3;
150+
u64 *stack_ptr;
151+
152+
for_each_possible_cpu(cpu) {
153+
stack_ptr = per_cpu_ptr(priv_stack_ptr, cpu);
154+
if (stack_ptr[0] != PRIV_STACK_GUARD_VAL ||
155+
stack_ptr[1] != PRIV_STACK_GUARD_VAL ||
156+
stack_ptr[underflow_idx] != PRIV_STACK_GUARD_VAL ||
157+
stack_ptr[underflow_idx + 1] != PRIV_STACK_GUARD_VAL) {
158+
pr_err("BPF private stack overflow/underflow detected for prog %s\n",
159+
bpf_jit_get_prog_name(fp));
160+
break;
161+
}
162+
}
163+
}
164+
132165
struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
133166
{
134167
u32 proglen;
135168
u32 alloclen;
136169
u8 *image = NULL;
137-
u32 *code_base;
138-
u32 *addrs;
139-
struct powerpc_jit_data *jit_data;
170+
u32 *code_base = NULL;
171+
u32 *addrs = NULL;
172+
struct powerpc_jit_data *jit_data = NULL;
140173
struct codegen_context cgctx;
141174
int pass;
142175
int flen;
176+
int priv_stack_alloc_size;
177+
void __percpu *priv_stack_ptr = NULL;
143178
struct bpf_binary_header *fhdr = NULL;
144179
struct bpf_binary_header *hdr = NULL;
145180
struct bpf_prog *org_fp = fp;
146-
struct bpf_prog *tmp_fp;
181+
struct bpf_prog *tmp_fp = NULL;
147182
bool bpf_blinded = false;
148183
bool extra_pass = false;
149184
u8 *fimage = NULL;
150-
u32 *fcode_base;
185+
u32 *fcode_base = NULL;
151186
u32 extable_len;
152187
u32 fixup_len;
153188

@@ -173,6 +208,26 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
173208
fp->aux->jit_data = jit_data;
174209
}
175210

211+
priv_stack_ptr = fp->aux->priv_stack_ptr;
212+
if (!priv_stack_ptr && fp->aux->jits_use_priv_stack) {
213+
/*
214+
* Allocate private stack of size equivalent to
215+
* verifier-calculated stack size plus two memory
216+
* guard regions to detect private stack overflow
217+
* and underflow.
218+
*/
219+
priv_stack_alloc_size = round_up(fp->aux->stack_depth, 16) +
220+
2 * PRIV_STACK_GUARD_SZ;
221+
priv_stack_ptr = __alloc_percpu_gfp(priv_stack_alloc_size, 16, GFP_KERNEL);
222+
if (!priv_stack_ptr) {
223+
fp = org_fp;
224+
goto out_priv_stack;
225+
}
226+
227+
priv_stack_init_guard(priv_stack_ptr, priv_stack_alloc_size);
228+
fp->aux->priv_stack_ptr = priv_stack_ptr;
229+
}
230+
176231
flen = fp->len;
177232
addrs = jit_data->addrs;
178233
if (addrs) {
@@ -209,6 +264,19 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
209264
cgctx.is_subprog = bpf_is_subprog(fp);
210265
cgctx.exception_boundary = fp->aux->exception_boundary;
211266
cgctx.exception_cb = fp->aux->exception_cb;
267+
cgctx.priv_sp = priv_stack_ptr;
268+
cgctx.priv_stack_size = 0;
269+
if (priv_stack_ptr) {
270+
/*
271+
* priv_stack_size required for setting bpf FP inside
272+
* percpu allocation.
273+
* stack_size is marked 0 to prevent allocation on
274+
* general stack and offset calculation don't go for
275+
* a toss in bpf_jit_stack_offsetof() & bpf_jit_stack_local()
276+
*/
277+
cgctx.priv_stack_size = cgctx.stack_size;
278+
cgctx.stack_size = 0;
279+
}
212280

213281
/* Scouting faux-generate pass 0 */
214282
if (bpf_jit_build_body(fp, NULL, NULL, &cgctx, addrs, 0, false)) {
@@ -305,7 +373,19 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
305373
goto out_addrs;
306374
}
307375
bpf_prog_fill_jited_linfo(fp, addrs);
376+
/*
377+
* On ABI V1, executable code starts after the function
378+
* descriptor, so adjust base accordingly.
379+
*/
380+
bpf_prog_update_insn_ptrs(fp, addrs,
381+
(void *)fimage + FUNCTION_DESCR_SIZE);
382+
308383
out_addrs:
384+
if (!image && priv_stack_ptr) {
385+
fp->aux->priv_stack_ptr = NULL;
386+
free_percpu(priv_stack_ptr);
387+
}
388+
out_priv_stack:
309389
kfree(addrs);
310390
kfree(jit_data);
311391
fp->aux->jit_data = NULL;
@@ -419,6 +499,8 @@ void bpf_jit_free(struct bpf_prog *fp)
419499
if (fp->jited) {
420500
struct powerpc_jit_data *jit_data = fp->aux->jit_data;
421501
struct bpf_binary_header *hdr;
502+
void __percpu *priv_stack_ptr;
503+
int priv_stack_alloc_size;
422504

423505
/*
424506
* If we fail the final pass of JIT (from jit_subprogs),
@@ -432,6 +514,13 @@ void bpf_jit_free(struct bpf_prog *fp)
432514
}
433515
hdr = bpf_jit_binary_pack_hdr(fp);
434516
bpf_jit_binary_pack_free(hdr, NULL);
517+
priv_stack_ptr = fp->aux->priv_stack_ptr;
518+
if (priv_stack_ptr) {
519+
priv_stack_alloc_size = round_up(fp->aux->stack_depth, 16) +
520+
2 * PRIV_STACK_GUARD_SZ;
521+
priv_stack_check_guard(priv_stack_ptr, priv_stack_alloc_size, fp);
522+
free_percpu(priv_stack_ptr);
523+
}
435524
WARN_ON_ONCE(!bpf_prog_kallsyms_verify_off(fp));
436525
}
437526

@@ -453,6 +542,22 @@ bool bpf_jit_supports_kfunc_call(void)
453542
return IS_ENABLED(CONFIG_PPC64);
454543
}
455544

545+
bool bpf_jit_supports_private_stack(void)
546+
{
547+
return IS_ENABLED(CONFIG_PPC64);
548+
}
549+
550+
bool bpf_jit_supports_fsession(void)
551+
{
552+
/*
553+
* TODO: Remove after validating support
554+
* for fsession and trampoline on ppc32.
555+
*/
556+
if (IS_ENABLED(CONFIG_PPC32))
557+
return -EOPNOTSUPP;
558+
return true;
559+
}
560+
456561
bool bpf_jit_supports_arena(void)
457562
{
458563
return IS_ENABLED(CONFIG_PPC64);
@@ -725,12 +830,16 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
725830
struct bpf_tramp_links *tlinks,
726831
void *func_addr)
727832
{
728-
int regs_off, nregs_off, ip_off, run_ctx_off, retval_off, nvr_off, alt_lr_off, r4_off = 0;
833+
int regs_off, func_meta_off, ip_off, run_ctx_off, retval_off;
834+
int nvr_off, alt_lr_off, r4_off = 0;
729835
struct bpf_tramp_links *fmod_ret = &tlinks[BPF_TRAMP_MODIFY_RETURN];
730836
struct bpf_tramp_links *fentry = &tlinks[BPF_TRAMP_FENTRY];
731837
struct bpf_tramp_links *fexit = &tlinks[BPF_TRAMP_FEXIT];
732838
int i, ret, nr_regs, retaddr_off, bpf_frame_size = 0;
733839
struct codegen_context codegen_ctx, *ctx;
840+
int cookie_off, cookie_cnt, cookie_ctx_off;
841+
int fsession_cnt = bpf_fsession_cnt(tlinks);
842+
u64 func_meta;
734843
u32 *image = (u32 *)rw_image;
735844
ppc_inst_t branch_insn;
736845
u32 *branches = NULL;
@@ -766,9 +875,11 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
766875
* [ reg argN ]
767876
* [ ... ]
768877
* regs_off [ reg_arg1 ] prog_ctx
769-
* nregs_off [ args count ] ((u64 *)prog_ctx)[-1]
878+
* func_meta_off [ args count ] ((u64 *)prog_ctx)[-1]
770879
* ip_off [ traced function ] ((u64 *)prog_ctx)[-2]
880+
* [ stack cookieN ]
771881
* [ ... ]
882+
* cookie_off [ stack cookie1 ]
772883
* run_ctx_off [ bpf_tramp_run_ctx ]
773884
* [ reg argN ]
774885
* [ ... ]
@@ -800,16 +911,21 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
800911
run_ctx_off = bpf_frame_size;
801912
bpf_frame_size += round_up(sizeof(struct bpf_tramp_run_ctx), SZL);
802913

914+
/* room for session cookies */
915+
cookie_off = bpf_frame_size;
916+
cookie_cnt = bpf_fsession_cookie_cnt(tlinks);
917+
bpf_frame_size += cookie_cnt * 8;
918+
803919
/* Room for IP address argument */
804920
ip_off = bpf_frame_size;
805921
if (flags & BPF_TRAMP_F_IP_ARG)
806922
bpf_frame_size += SZL;
807923

808-
/* Room for args count */
809-
nregs_off = bpf_frame_size;
924+
/* Room for function metadata, arg regs count */
925+
func_meta_off = bpf_frame_size;
810926
bpf_frame_size += SZL;
811927

812-
/* Room for args */
928+
/* Room for arg regs */
813929
regs_off = bpf_frame_size;
814930
bpf_frame_size += nr_regs * SZL;
815931

@@ -908,9 +1024,9 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
9081024
EMIT(PPC_RAW_STL(_R3, _R1, retaddr_off));
9091025
}
9101026

911-
/* Save function arg count -- see bpf_get_func_arg_cnt() */
912-
EMIT(PPC_RAW_LI(_R3, nr_regs));
913-
EMIT(PPC_RAW_STL(_R3, _R1, nregs_off));
1027+
/* Save function arg regs count -- see bpf_get_func_arg_cnt() */
1028+
func_meta = nr_regs;
1029+
store_func_meta(image, ctx, func_meta, func_meta_off);
9141030

9151031
/* Save nv regs */
9161032
EMIT(PPC_RAW_STL(_R25, _R1, nvr_off));
@@ -924,10 +1040,28 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
9241040
return ret;
9251041
}
9261042

927-
for (i = 0; i < fentry->nr_links; i++)
1043+
if (fsession_cnt) {
1044+
/*
1045+
* Clear all the session cookies' values
1046+
* Clear the return value to make sure fentry always get 0
1047+
*/
1048+
prepare_for_fsession_fentry(image, ctx, cookie_cnt, cookie_off, retval_off);
1049+
}
1050+
1051+
cookie_ctx_off = (regs_off - cookie_off) / 8;
1052+
1053+
for (i = 0; i < fentry->nr_links; i++) {
1054+
if (bpf_prog_calls_session_cookie(fentry->links[i])) {
1055+
u64 meta = func_meta | (cookie_ctx_off << BPF_TRAMP_COOKIE_INDEX_SHIFT);
1056+
1057+
store_func_meta(image, ctx, meta, func_meta_off);
1058+
cookie_ctx_off--;
1059+
}
1060+
9281061
if (invoke_bpf_prog(image, ro_image, ctx, fentry->links[i], regs_off, retval_off,
9291062
run_ctx_off, flags & BPF_TRAMP_F_RET_FENTRY_RET))
9301063
return -EINVAL;
1064+
}
9311065

9321066
if (fmod_ret->nr_links) {
9331067
branches = kcalloc(fmod_ret->nr_links, sizeof(u32), GFP_KERNEL);
@@ -989,12 +1123,27 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
9891123
image[branches[i]] = ppc_inst_val(branch_insn);
9901124
}
9911125

992-
for (i = 0; i < fexit->nr_links; i++)
1126+
/* set the "is_return" flag for fsession */
1127+
func_meta |= (1ULL << BPF_TRAMP_IS_RETURN_SHIFT);
1128+
if (fsession_cnt)
1129+
store_func_meta(image, ctx, func_meta, func_meta_off);
1130+
1131+
cookie_ctx_off = (regs_off - cookie_off) / 8;
1132+
1133+
for (i = 0; i < fexit->nr_links; i++) {
1134+
if (bpf_prog_calls_session_cookie(fexit->links[i])) {
1135+
u64 meta = func_meta | (cookie_ctx_off << BPF_TRAMP_COOKIE_INDEX_SHIFT);
1136+
1137+
store_func_meta(image, ctx, meta, func_meta_off);
1138+
cookie_ctx_off--;
1139+
}
1140+
9931141
if (invoke_bpf_prog(image, ro_image, ctx, fexit->links[i], regs_off, retval_off,
9941142
run_ctx_off, false)) {
9951143
ret = -EINVAL;
9961144
goto cleanup;
9971145
}
1146+
}
9981147

9991148
if (flags & BPF_TRAMP_F_CALL_ORIG) {
10001149
if (ro_image) /* image is NULL for dummy pass */

arch/powerpc/net/bpf_jit_comp32.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,41 @@ void bpf_jit_realloc_regs(struct codegen_context *ctx)
123123
}
124124
}
125125

126+
void prepare_for_fsession_fentry(u32 *image, struct codegen_context *ctx, int cookie_cnt,
127+
int cookie_off, int retval_off)
128+
{
129+
/*
130+
* Set session cookies value
131+
* Clear cookies field on stack
132+
* Ensure retval to be cleared on fentry
133+
*/
134+
EMIT(PPC_RAW_LI(bpf_to_ppc(TMP_REG), 0));
135+
136+
for (int i = 0; i < cookie_cnt; i++) {
137+
EMIT(PPC_RAW_STW(bpf_to_ppc(TMP_REG), _R1, cookie_off + 4 * i));
138+
EMIT(PPC_RAW_STW(bpf_to_ppc(TMP_REG), _R1, cookie_off + 4 * i + 4));
139+
}
140+
141+
EMIT(PPC_RAW_STW(bpf_to_ppc(TMP_REG), _R1, retval_off));
142+
EMIT(PPC_RAW_STW(bpf_to_ppc(TMP_REG), _R1, retval_off + 4));
143+
}
144+
145+
void store_func_meta(u32 *image, struct codegen_context *ctx,
146+
u64 func_meta, int func_meta_off)
147+
{
148+
/*
149+
* Store func_meta to stack: [R1 + func_meta_off] = func_meta
150+
* func_meta := argument count in first byte + cookie value
151+
*/
152+
/* Store lower word */
153+
EMIT(PPC_RAW_LI32(bpf_to_ppc(TMP_REG), (u32)func_meta));
154+
EMIT(PPC_RAW_STW(bpf_to_ppc(TMP_REG), _R1, func_meta_off));
155+
156+
/* Store upper word */
157+
EMIT(PPC_RAW_LI32(bpf_to_ppc(TMP_REG), (u32)(func_meta >> 32)));
158+
EMIT(PPC_RAW_STW(bpf_to_ppc(TMP_REG), _R1, func_meta_off + 4));
159+
}
160+
126161
void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx)
127162
{
128163
int i;

0 commit comments

Comments
 (0)