@@ -44,9 +44,12 @@ int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg,
44
44
}
45
45
46
46
struct powerpc_jit_data {
47
- struct bpf_binary_header * header ;
47
+ /* address of rw header */
48
+ struct bpf_binary_header * hdr ;
49
+ /* address of ro final header */
50
+ struct bpf_binary_header * fhdr ;
48
51
u32 * addrs ;
49
- u8 * image ;
52
+ u8 * fimage ;
50
53
u32 proglen ;
51
54
struct codegen_context ctx ;
52
55
};
@@ -67,11 +70,14 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
67
70
struct codegen_context cgctx ;
68
71
int pass ;
69
72
int flen ;
70
- struct bpf_binary_header * bpf_hdr ;
73
+ struct bpf_binary_header * fhdr = NULL ;
74
+ struct bpf_binary_header * hdr = NULL ;
71
75
struct bpf_prog * org_fp = fp ;
72
76
struct bpf_prog * tmp_fp ;
73
77
bool bpf_blinded = false;
74
78
bool extra_pass = false;
79
+ u8 * fimage = NULL ;
80
+ u32 * fcode_base ;
75
81
u32 extable_len ;
76
82
u32 fixup_len ;
77
83
@@ -101,9 +107,16 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
101
107
addrs = jit_data -> addrs ;
102
108
if (addrs ) {
103
109
cgctx = jit_data -> ctx ;
104
- image = jit_data -> image ;
105
- bpf_hdr = jit_data -> header ;
110
+ /*
111
+ * JIT compiled to a writable location (image/code_base) first.
112
+ * It is then moved to the readonly final location (fimage/fcode_base)
113
+ * using instruction patching.
114
+ */
115
+ fimage = jit_data -> fimage ;
116
+ fhdr = jit_data -> fhdr ;
106
117
proglen = jit_data -> proglen ;
118
+ hdr = jit_data -> hdr ;
119
+ image = (void * )hdr + ((void * )fimage - (void * )fhdr );
107
120
extra_pass = true;
108
121
/* During extra pass, ensure index is reset before repopulating extable entries */
109
122
cgctx .exentry_idx = 0 ;
@@ -123,7 +136,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
123
136
cgctx .stack_size = round_up (fp -> aux -> stack_depth , 16 );
124
137
125
138
/* Scouting faux-generate pass 0 */
126
- if (bpf_jit_build_body (fp , 0 , & cgctx , addrs , 0 , false)) {
139
+ if (bpf_jit_build_body (fp , NULL , NULL , & cgctx , addrs , 0 , false)) {
127
140
/* We hit something illegal or unsupported. */
128
141
fp = org_fp ;
129
142
goto out_addrs ;
@@ -138,7 +151,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
138
151
*/
139
152
if (cgctx .seen & SEEN_TAILCALL || !is_offset_in_branch_range ((long )cgctx .idx * 4 )) {
140
153
cgctx .idx = 0 ;
141
- if (bpf_jit_build_body (fp , 0 , & cgctx , addrs , 0 , false)) {
154
+ if (bpf_jit_build_body (fp , NULL , NULL , & cgctx , addrs , 0 , false)) {
142
155
fp = org_fp ;
143
156
goto out_addrs ;
144
157
}
@@ -160,26 +173,30 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
160
173
proglen = cgctx .idx * 4 ;
161
174
alloclen = proglen + FUNCTION_DESCR_SIZE + fixup_len + extable_len ;
162
175
163
- bpf_hdr = bpf_jit_binary_alloc (alloclen , & image , 4 , bpf_jit_fill_ill_insns );
164
- if (!bpf_hdr ) {
176
+ fhdr = bpf_jit_binary_pack_alloc (alloclen , & fimage , 4 , & hdr , & image ,
177
+ bpf_jit_fill_ill_insns );
178
+ if (!fhdr ) {
165
179
fp = org_fp ;
166
180
goto out_addrs ;
167
181
}
168
182
169
183
if (extable_len )
170
- fp -> aux -> extable = (void * )image + FUNCTION_DESCR_SIZE + proglen + fixup_len ;
184
+ fp -> aux -> extable = (void * )fimage + FUNCTION_DESCR_SIZE + proglen + fixup_len ;
171
185
172
186
skip_init_ctx :
173
187
code_base = (u32 * )(image + FUNCTION_DESCR_SIZE );
188
+ fcode_base = (u32 * )(fimage + FUNCTION_DESCR_SIZE );
174
189
175
190
/* Code generation passes 1-2 */
176
191
for (pass = 1 ; pass < 3 ; pass ++ ) {
177
192
/* Now build the prologue, body code & epilogue for real. */
178
193
cgctx .idx = 0 ;
179
194
cgctx .alt_exit_addr = 0 ;
180
195
bpf_jit_build_prologue (code_base , & cgctx );
181
- if (bpf_jit_build_body (fp , code_base , & cgctx , addrs , pass , extra_pass )) {
182
- bpf_jit_binary_free (bpf_hdr );
196
+ if (bpf_jit_build_body (fp , code_base , fcode_base , & cgctx , addrs , pass ,
197
+ extra_pass )) {
198
+ bpf_arch_text_copy (& fhdr -> size , & hdr -> size , sizeof (hdr -> size ));
199
+ bpf_jit_binary_pack_free (fhdr , hdr );
183
200
fp = org_fp ;
184
201
goto out_addrs ;
185
202
}
@@ -199,17 +216,19 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
199
216
200
217
#ifdef CONFIG_PPC64_ELF_ABI_V1
201
218
/* Function descriptor nastiness: Address + TOC */
202
- ((u64 * )image )[0 ] = (u64 )code_base ;
219
+ ((u64 * )image )[0 ] = (u64 )fcode_base ;
203
220
((u64 * )image )[1 ] = local_paca -> kernel_toc ;
204
221
#endif
205
222
206
- fp -> bpf_func = (void * )image ;
223
+ fp -> bpf_func = (void * )fimage ;
207
224
fp -> jited = 1 ;
208
225
fp -> jited_len = proglen + FUNCTION_DESCR_SIZE ;
209
226
210
- bpf_flush_icache (bpf_hdr , (u8 * )bpf_hdr + bpf_hdr -> size );
211
227
if (!fp -> is_func || extra_pass ) {
212
- bpf_jit_binary_lock_ro (bpf_hdr );
228
+ if (bpf_jit_binary_pack_finalize (fp , fhdr , hdr )) {
229
+ fp = org_fp ;
230
+ goto out_addrs ;
231
+ }
213
232
bpf_prog_fill_jited_linfo (fp , addrs );
214
233
out_addrs :
215
234
kfree (addrs );
@@ -219,8 +238,9 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
219
238
jit_data -> addrs = addrs ;
220
239
jit_data -> ctx = cgctx ;
221
240
jit_data -> proglen = proglen ;
222
- jit_data -> image = image ;
223
- jit_data -> header = bpf_hdr ;
241
+ jit_data -> fimage = fimage ;
242
+ jit_data -> fhdr = fhdr ;
243
+ jit_data -> hdr = hdr ;
224
244
}
225
245
226
246
out :
@@ -234,12 +254,13 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
234
254
* The caller should check for (BPF_MODE(code) == BPF_PROBE_MEM) before calling
235
255
* this function, as this only applies to BPF_PROBE_MEM, for now.
236
256
*/
237
- int bpf_add_extable_entry (struct bpf_prog * fp , u32 * image , int pass , struct codegen_context * ctx ,
238
- int insn_idx , int jmp_off , int dst_reg )
257
+ int bpf_add_extable_entry (struct bpf_prog * fp , u32 * image , u32 * fimage , int pass ,
258
+ struct codegen_context * ctx , int insn_idx , int jmp_off ,
259
+ int dst_reg )
239
260
{
240
261
off_t offset ;
241
262
unsigned long pc ;
242
- struct exception_table_entry * ex ;
263
+ struct exception_table_entry * ex , * ex_entry ;
243
264
u32 * fixup ;
244
265
245
266
/* Populate extable entries only in the last pass */
@@ -250,9 +271,16 @@ int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct code
250
271
WARN_ON_ONCE (ctx -> exentry_idx >= fp -> aux -> num_exentries ))
251
272
return - EINVAL ;
252
273
274
+ /*
275
+ * Program is first written to image before copying to the
276
+ * final location (fimage). Accordingly, update in the image first.
277
+ * As all offsets used are relative, copying as is to the
278
+ * final location should be alright.
279
+ */
253
280
pc = (unsigned long )& image [insn_idx ];
281
+ ex = (void * )fp -> aux -> extable - (void * )fimage + (void * )image ;
254
282
255
- fixup = (void * )fp -> aux -> extable -
283
+ fixup = (void * )ex -
256
284
(fp -> aux -> num_exentries * BPF_FIXUP_LEN * 4 ) +
257
285
(ctx -> exentry_idx * BPF_FIXUP_LEN * 4 );
258
286
@@ -263,17 +291,17 @@ int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct code
263
291
fixup [BPF_FIXUP_LEN - 1 ] =
264
292
PPC_RAW_BRANCH ((long )(pc + jmp_off ) - (long )& fixup [BPF_FIXUP_LEN - 1 ]);
265
293
266
- ex = & fp -> aux -> extable [ctx -> exentry_idx ];
294
+ ex_entry = & ex [ctx -> exentry_idx ];
267
295
268
- offset = pc - (long )& ex -> insn ;
296
+ offset = pc - (long )& ex_entry -> insn ;
269
297
if (WARN_ON_ONCE (offset >= 0 || offset < INT_MIN ))
270
298
return - ERANGE ;
271
- ex -> insn = offset ;
299
+ ex_entry -> insn = offset ;
272
300
273
- offset = (long )fixup - (long )& ex -> fixup ;
301
+ offset = (long )fixup - (long )& ex_entry -> fixup ;
274
302
if (WARN_ON_ONCE (offset >= 0 || offset < INT_MIN ))
275
303
return - ERANGE ;
276
- ex -> fixup = offset ;
304
+ ex_entry -> fixup = offset ;
277
305
278
306
ctx -> exentry_idx ++ ;
279
307
return 0 ;
@@ -307,3 +335,27 @@ int bpf_arch_text_invalidate(void *dst, size_t len)
307
335
308
336
return ret ;
309
337
}
338
+
339
+ void bpf_jit_free (struct bpf_prog * fp )
340
+ {
341
+ if (fp -> jited ) {
342
+ struct powerpc_jit_data * jit_data = fp -> aux -> jit_data ;
343
+ struct bpf_binary_header * hdr ;
344
+
345
+ /*
346
+ * If we fail the final pass of JIT (from jit_subprogs),
347
+ * the program may not be finalized yet. Call finalize here
348
+ * before freeing it.
349
+ */
350
+ if (jit_data ) {
351
+ bpf_jit_binary_pack_finalize (fp , jit_data -> fhdr , jit_data -> hdr );
352
+ kvfree (jit_data -> addrs );
353
+ kfree (jit_data );
354
+ }
355
+ hdr = bpf_jit_binary_pack_hdr (fp );
356
+ bpf_jit_binary_pack_free (hdr , NULL );
357
+ WARN_ON_ONCE (!bpf_prog_kallsyms_verify_off (fp ));
358
+ }
359
+
360
+ bpf_prog_unlock_free (fp );
361
+ }
0 commit comments