Skip to content

Commit 7b847f5

Browse files
rnavmpe
authored andcommitted
powerpc/bpf: Introduce accessors for using the tmp local stack space
While at it, ensure that the location of the local save area is consistent whether or not we setup our own stackframe. This property is utilised in the next patch that adds support for tail calls. Signed-off-by: Naveen N. Rao <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
1 parent 2685f82 commit 7b847f5

File tree

2 files changed

+55
-40
lines changed

2 files changed

+55
-40
lines changed

arch/powerpc/net/bpf_jit64.h

+11-5
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,25 @@
1616

1717
/*
1818
* Stack layout:
19+
* Ensure the top half (upto local_tmp_var) stays consistent
20+
* with our redzone usage.
1921
*
2022
* [ prev sp ] <-------------
2123
* [ nv gpr save area ] 8*8 |
24+
* [ tail_call_cnt ] 8 |
25+
* [ local_tmp_var ] 8 |
2226
* fp (r31) --> [ ebpf stack space ] 512 |
23-
* [ local/tmp var space ] 16 |
2427
* [ frame header ] 32/112 |
2528
* sp (r1) ---> [ stack pointer ] --------------
2629
*/
2730

28-
/* for bpf JIT code internal usage */
29-
#define BPF_PPC_STACK_LOCALS 16
3031
/* for gpr non volatile registers BPG_REG_6 to 10, plus skb cache registers */
3132
#define BPF_PPC_STACK_SAVE (8*8)
33+
/* for bpf JIT code internal usage */
34+
#define BPF_PPC_STACK_LOCALS 16
3235
/* Ensure this is quadword aligned */
33-
#define BPF_PPC_STACKFRAME (STACK_FRAME_MIN_SIZE + BPF_PPC_STACK_LOCALS + \
34-
MAX_BPF_STACK + BPF_PPC_STACK_SAVE)
36+
#define BPF_PPC_STACKFRAME (STACK_FRAME_MIN_SIZE + MAX_BPF_STACK + \
37+
BPF_PPC_STACK_LOCALS + BPF_PPC_STACK_SAVE)
3538

3639
#ifndef __ASSEMBLY__
3740

@@ -65,6 +68,9 @@ static const int b2p[] = {
6568
[TMP_REG_2] = 10
6669
};
6770

71+
/* PPC NVR range -- update this if we ever use NVRs below r24 */
72+
#define BPF_PPC_NVR_MIN 24
73+
6874
/* Assembly helpers */
6975
#define DECLARE_LOAD_FUNC(func) u64 func(u64 r3, u64 r4); \
7076
u64 func##_negative_offset(u64 r3, u64 r4); \

arch/powerpc/net/bpf_jit_comp64.c

+44-35
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,35 @@ static inline bool bpf_has_stack_frame(struct codegen_context *ctx)
5858
return ctx->seen & SEEN_FUNC || bpf_is_seen_register(ctx, BPF_REG_FP);
5959
}
6060

61+
/*
62+
* When not setting up our own stackframe, the redzone usage is:
63+
*
64+
* [ prev sp ] <-------------
65+
* [ ... ] |
66+
* sp (r1) ---> [ stack pointer ] --------------
67+
* [ nv gpr save area ] 8*8
68+
* [ tail_call_cnt ] 8
69+
* [ local_tmp_var ] 8
70+
* [ unused red zone ] 208 bytes protected
71+
*/
72+
static int bpf_jit_stack_local(struct codegen_context *ctx)
73+
{
74+
if (bpf_has_stack_frame(ctx))
75+
return STACK_FRAME_MIN_SIZE + MAX_BPF_STACK;
76+
else
77+
return -(BPF_PPC_STACK_SAVE + 16);
78+
}
79+
80+
static int bpf_jit_stack_offsetof(struct codegen_context *ctx, int reg)
81+
{
82+
if (reg >= BPF_PPC_NVR_MIN && reg < 32)
83+
return (bpf_has_stack_frame(ctx) ? BPF_PPC_STACKFRAME : 0)
84+
- (8 * (32 - reg));
85+
86+
pr_err("BPF JIT is asking about unknown registers");
87+
BUG();
88+
}
89+
6190
static void bpf_jit_emit_skb_loads(u32 *image, struct codegen_context *ctx)
6291
{
6392
/*
@@ -100,9 +129,8 @@ static void bpf_jit_emit_func_call(u32 *image, struct codegen_context *ctx, u64
100129
static void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx)
101130
{
102131
int i;
103-
bool new_stack_frame = bpf_has_stack_frame(ctx);
104132

105-
if (new_stack_frame) {
133+
if (bpf_has_stack_frame(ctx)) {
106134
/*
107135
* We need a stack frame, but we don't necessarily need to
108136
* save/restore LR unless we call other functions
@@ -122,53 +150,48 @@ static void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx)
122150
*/
123151
for (i = BPF_REG_6; i <= BPF_REG_10; i++)
124152
if (bpf_is_seen_register(ctx, i))
125-
PPC_BPF_STL(b2p[i], 1,
126-
(new_stack_frame ? BPF_PPC_STACKFRAME : 0) -
127-
(8 * (32 - b2p[i])));
153+
PPC_BPF_STL(b2p[i], 1, bpf_jit_stack_offsetof(ctx, b2p[i]));
128154

129155
/*
130156
* Save additional non-volatile regs if we cache skb
131157
* Also, setup skb data
132158
*/
133159
if (ctx->seen & SEEN_SKB) {
134160
PPC_BPF_STL(b2p[SKB_HLEN_REG], 1,
135-
BPF_PPC_STACKFRAME - (8 * (32 - b2p[SKB_HLEN_REG])));
161+
bpf_jit_stack_offsetof(ctx, b2p[SKB_HLEN_REG]));
136162
PPC_BPF_STL(b2p[SKB_DATA_REG], 1,
137-
BPF_PPC_STACKFRAME - (8 * (32 - b2p[SKB_DATA_REG])));
163+
bpf_jit_stack_offsetof(ctx, b2p[SKB_DATA_REG]));
138164
bpf_jit_emit_skb_loads(image, ctx);
139165
}
140166

141167
/* Setup frame pointer to point to the bpf stack area */
142168
if (bpf_is_seen_register(ctx, BPF_REG_FP))
143169
PPC_ADDI(b2p[BPF_REG_FP], 1,
144-
BPF_PPC_STACKFRAME - BPF_PPC_STACK_SAVE);
170+
STACK_FRAME_MIN_SIZE + MAX_BPF_STACK);
145171
}
146172

147173
static void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
148174
{
149175
int i;
150-
bool new_stack_frame = bpf_has_stack_frame(ctx);
151176

152177
/* Move result to r3 */
153178
PPC_MR(3, b2p[BPF_REG_0]);
154179

155180
/* Restore NVRs */
156181
for (i = BPF_REG_6; i <= BPF_REG_10; i++)
157182
if (bpf_is_seen_register(ctx, i))
158-
PPC_BPF_LL(b2p[i], 1,
159-
(new_stack_frame ? BPF_PPC_STACKFRAME : 0) -
160-
(8 * (32 - b2p[i])));
183+
PPC_BPF_LL(b2p[i], 1, bpf_jit_stack_offsetof(ctx, b2p[i]));
161184

162185
/* Restore non-volatile registers used for skb cache */
163186
if (ctx->seen & SEEN_SKB) {
164187
PPC_BPF_LL(b2p[SKB_HLEN_REG], 1,
165-
BPF_PPC_STACKFRAME - (8 * (32 - b2p[SKB_HLEN_REG])));
188+
bpf_jit_stack_offsetof(ctx, b2p[SKB_HLEN_REG]));
166189
PPC_BPF_LL(b2p[SKB_DATA_REG], 1,
167-
BPF_PPC_STACKFRAME - (8 * (32 - b2p[SKB_DATA_REG])));
190+
bpf_jit_stack_offsetof(ctx, b2p[SKB_DATA_REG]));
168191
}
169192

170193
/* Tear down our stack frame */
171-
if (new_stack_frame) {
194+
if (bpf_has_stack_frame(ctx)) {
172195
PPC_ADDI(1, 1, BPF_PPC_STACKFRAME);
173196
if (ctx->seen & SEEN_FUNC) {
174197
PPC_BPF_LL(0, 1, PPC_LR_STKOFF);
@@ -200,7 +223,6 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
200223
u64 imm64;
201224
u8 *func;
202225
u32 true_cond;
203-
int stack_local_off;
204226

205227
/*
206228
* addrs[] maps a BPF bytecode address into a real offset from
@@ -219,9 +241,9 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
219241
* optimization but everything else should work without
220242
* any issues.
221243
*/
222-
if (dst_reg >= 24 && dst_reg <= 31)
244+
if (dst_reg >= BPF_PPC_NVR_MIN && dst_reg < 32)
223245
bpf_set_seen_register(ctx, insn[i].dst_reg);
224-
if (src_reg >= 24 && src_reg <= 31)
246+
if (src_reg >= BPF_PPC_NVR_MIN && src_reg < 32)
225247
bpf_set_seen_register(ctx, insn[i].src_reg);
226248

227249
switch (code) {
@@ -490,25 +512,12 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
490512
* Way easier and faster(?) to store the value
491513
* into stack and then use ldbrx
492514
*
493-
* First, determine where in stack we can store
494-
* this:
495-
* - if we have allotted a stack frame, then we
496-
* will utilize the area set aside by
497-
* BPF_PPC_STACK_LOCALS
498-
* - else, we use the area beneath the NV GPR
499-
* save area
500-
*
501515
* ctx->seen will be reliable in pass2, but
502516
* the instructions generated will remain the
503517
* same across all passes
504518
*/
505-
if (bpf_has_stack_frame(ctx))
506-
stack_local_off = STACK_FRAME_MIN_SIZE;
507-
else
508-
stack_local_off = -(BPF_PPC_STACK_SAVE + 8);
509-
510-
PPC_STD(dst_reg, 1, stack_local_off);
511-
PPC_ADDI(b2p[TMP_REG_1], 1, stack_local_off);
519+
PPC_STD(dst_reg, 1, bpf_jit_stack_local(ctx));
520+
PPC_ADDI(b2p[TMP_REG_1], 1, bpf_jit_stack_local(ctx));
512521
PPC_LDBRX(dst_reg, 0, b2p[TMP_REG_1]);
513522
break;
514523
}
@@ -668,7 +677,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
668677

669678
/* Save skb pointer if we need to re-cache skb data */
670679
if (bpf_helper_changes_skb_data(func))
671-
PPC_BPF_STL(3, 1, STACK_FRAME_MIN_SIZE);
680+
PPC_BPF_STL(3, 1, bpf_jit_stack_local(ctx));
672681

673682
bpf_jit_emit_func_call(image, ctx, (u64)func);
674683

@@ -678,7 +687,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
678687
/* refresh skb cache */
679688
if (bpf_helper_changes_skb_data(func)) {
680689
/* reload skb pointer to r3 */
681-
PPC_BPF_LL(3, 1, STACK_FRAME_MIN_SIZE);
690+
PPC_BPF_LL(3, 1, bpf_jit_stack_local(ctx));
682691
bpf_jit_emit_skb_loads(image, ctx);
683692
}
684693
break;

0 commit comments

Comments
 (0)