@@ -325,6 +325,22 @@ struct jit_context {
325325/* Number of bytes that will be skipped on tailcall */
326326#define X86_TAIL_CALL_OFFSET (12 + ENDBR_INSN_SIZE)
327327
328+ static void push_r9 (u8 * * pprog )
329+ {
330+ u8 * prog = * pprog ;
331+
332+ EMIT2 (0x41 , 0x51 ); /* push r9 */
333+ * pprog = prog ;
334+ }
335+
336+ static void pop_r9 (u8 * * pprog )
337+ {
338+ u8 * prog = * pprog ;
339+
340+ EMIT2 (0x41 , 0x59 ); /* pop r9 */
341+ * pprog = prog ;
342+ }
343+
328344static void push_r12 (u8 * * pprog )
329345{
330346 u8 * prog = * pprog ;
@@ -1404,6 +1420,24 @@ static void emit_shiftx(u8 **pprog, u32 dst_reg, u8 src_reg, bool is64, u8 op)
14041420 * pprog = prog ;
14051421}
14061422
1423+ static void emit_priv_frame_ptr (u8 * * pprog , void __percpu * priv_frame_ptr )
1424+ {
1425+ u8 * prog = * pprog ;
1426+
1427+ /* movabs r9, priv_frame_ptr */
1428+ emit_mov_imm64 (& prog , X86_REG_R9 , (__force long ) priv_frame_ptr >> 32 ,
1429+ (u32 ) (__force long ) priv_frame_ptr );
1430+
1431+ #ifdef CONFIG_SMP
1432+ /* add <r9>, gs:[<off>] */
1433+ EMIT2 (0x65 , 0x4c );
1434+ EMIT3 (0x03 , 0x0c , 0x25 );
1435+ EMIT ((u32 )(unsigned long )& this_cpu_off , 4 );
1436+ #endif
1437+
1438+ * pprog = prog ;
1439+ }
1440+
14071441#define INSN_SZ_DIFF (((addrs[i] - addrs[i - 1]) - (prog - temp)))
14081442
14091443#define __LOAD_TCC_PTR (off ) \
@@ -1421,6 +1455,7 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image
14211455 int insn_cnt = bpf_prog -> len ;
14221456 bool seen_exit = false;
14231457 u8 temp [BPF_MAX_INSN_SIZE + BPF_INSN_SAFETY ];
1458+ void __percpu * priv_frame_ptr = NULL ;
14241459 u64 arena_vm_start , user_vm_start ;
14251460 int i , excnt = 0 ;
14261461 int ilen , proglen = 0 ;
@@ -1429,6 +1464,10 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image
14291464 int err ;
14301465
14311466 stack_depth = bpf_prog -> aux -> stack_depth ;
1467+ if (bpf_prog -> aux -> priv_stack_ptr ) {
1468+ priv_frame_ptr = bpf_prog -> aux -> priv_stack_ptr + round_up (stack_depth , 16 );
1469+ stack_depth = 0 ;
1470+ }
14321471
14331472 arena_vm_start = bpf_arena_get_kern_vm_start (bpf_prog -> aux -> arena );
14341473 user_vm_start = bpf_arena_get_user_vm_start (bpf_prog -> aux -> arena );
@@ -1457,6 +1496,9 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image
14571496 emit_mov_imm64 (& prog , X86_REG_R12 ,
14581497 arena_vm_start >> 32 , (u32 ) arena_vm_start );
14591498
1499+ if (priv_frame_ptr )
1500+ emit_priv_frame_ptr (& prog , priv_frame_ptr );
1501+
14601502 ilen = prog - temp ;
14611503 if (rw_image )
14621504 memcpy (rw_image + proglen , temp , ilen );
@@ -1476,6 +1518,14 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image
14761518 u8 * func ;
14771519 int nops ;
14781520
1521+ if (priv_frame_ptr ) {
1522+ if (src_reg == BPF_REG_FP )
1523+ src_reg = X86_REG_R9 ;
1524+
1525+ if (dst_reg == BPF_REG_FP )
1526+ dst_reg = X86_REG_R9 ;
1527+ }
1528+
14791529 switch (insn -> code ) {
14801530 /* ALU */
14811531 case BPF_ALU | BPF_ADD | BPF_X :
@@ -2136,9 +2186,15 @@ st: if (is_imm8(insn->off))
21362186 }
21372187 if (!imm32 )
21382188 return - EINVAL ;
2189+ if (priv_frame_ptr ) {
2190+ push_r9 (& prog );
2191+ ip += 2 ;
2192+ }
21392193 ip += x86_call_depth_emit_accounting (& prog , func , ip );
21402194 if (emit_call (& prog , func , ip ))
21412195 return - EINVAL ;
2196+ if (priv_frame_ptr )
2197+ pop_r9 (& prog );
21422198 break ;
21432199 }
21442200
@@ -3323,6 +3379,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
33233379 struct bpf_binary_header * rw_header = NULL ;
33243380 struct bpf_binary_header * header = NULL ;
33253381 struct bpf_prog * tmp , * orig_prog = prog ;
3382+ void __percpu * priv_stack_ptr = NULL ;
33263383 struct x64_jit_data * jit_data ;
33273384 int proglen , oldproglen = 0 ;
33283385 struct jit_context ctx = {};
@@ -3359,6 +3416,15 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
33593416 }
33603417 prog -> aux -> jit_data = jit_data ;
33613418 }
3419+ priv_stack_ptr = prog -> aux -> priv_stack_ptr ;
3420+ if (!priv_stack_ptr && prog -> aux -> priv_stack_requested ) {
3421+ priv_stack_ptr = __alloc_percpu_gfp (prog -> aux -> stack_depth , 16 , GFP_KERNEL );
3422+ if (!priv_stack_ptr ) {
3423+ prog = orig_prog ;
3424+ goto out_priv_stack ;
3425+ }
3426+ prog -> aux -> priv_stack_ptr = priv_stack_ptr ;
3427+ }
33623428 addrs = jit_data -> addrs ;
33633429 if (addrs ) {
33643430 ctx = jit_data -> ctx ;
@@ -3494,6 +3560,11 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
34943560 bpf_prog_fill_jited_linfo (prog , addrs + 1 );
34953561out_addrs :
34963562 kvfree (addrs );
3563+ if (!image && priv_stack_ptr ) {
3564+ free_percpu (priv_stack_ptr );
3565+ prog -> aux -> priv_stack_ptr = NULL ;
3566+ }
3567+ out_priv_stack :
34973568 kfree (jit_data );
34983569 prog -> aux -> jit_data = NULL ;
34993570 }
@@ -3547,6 +3618,7 @@ void bpf_jit_free(struct bpf_prog *prog)
35473618 prog -> bpf_func = (void * )prog -> bpf_func - cfi_get_offset ();
35483619 hdr = bpf_jit_binary_pack_hdr (prog );
35493620 bpf_jit_binary_pack_free (hdr , NULL );
3621+ free_percpu (prog -> aux -> priv_stack_ptr );
35503622 WARN_ON_ONCE (!bpf_prog_kallsyms_verify_off (prog ));
35513623 }
35523624
@@ -3562,6 +3634,11 @@ bool bpf_jit_supports_exceptions(void)
35623634 return IS_ENABLED (CONFIG_UNWINDER_ORC );
35633635}
35643636
3637+ bool bpf_jit_supports_private_stack (void )
3638+ {
3639+ return true;
3640+ }
3641+
35653642void arch_bpf_stack_walk (bool (* consume_fn )(void * cookie , u64 ip , u64 sp , u64 bp ), void * cookie )
35663643{
35673644#if defined(CONFIG_UNWINDER_ORC )
0 commit comments