@@ -53,6 +53,7 @@ struct bpf_jit {
53
53
#define SEEN_LITERAL 8 /* code uses literals */
54
54
#define SEEN_FUNC 16 /* calls C functions */
55
55
#define SEEN_TAIL_CALL 32 /* code uses tail calls */
56
+ #define SEEN_SKB_CHANGE 64 /* code changes skb data */
56
57
#define SEEN_STACK (SEEN_FUNC | SEEN_MEM | SEEN_SKB)
57
58
58
59
/*
@@ -381,6 +382,26 @@ static void save_restore_regs(struct bpf_jit *jit, int op)
381
382
} while (re <= 15 );
382
383
}
383
384
385
+ /*
386
+ * For SKB access %b1 contains the SKB pointer. For "bpf_jit.S"
387
+ * we store the SKB header length on the stack and the SKB data
388
+ * pointer in REG_SKB_DATA.
389
+ */
390
+ static void emit_load_skb_data_hlen (struct bpf_jit * jit )
391
+ {
392
+ /* Header length: llgf %w1,<len>(%b1) */
393
+ EMIT6_DISP_LH (0xe3000000 , 0x0016 , REG_W1 , REG_0 , BPF_REG_1 ,
394
+ offsetof(struct sk_buff , len ));
395
+ /* s %w1,<data_len>(%b1) */
396
+ EMIT4_DISP (0x5b000000 , REG_W1 , BPF_REG_1 ,
397
+ offsetof(struct sk_buff , data_len ));
398
+ /* stg %w1,ST_OFF_HLEN(%r0,%r15) */
399
+ EMIT6_DISP_LH (0xe3000000 , 0x0024 , REG_W1 , REG_0 , REG_15 , STK_OFF_HLEN );
400
+ /* lg %skb_data,data_off(%b1) */
401
+ EMIT6_DISP_LH (0xe3000000 , 0x0004 , REG_SKB_DATA , REG_0 ,
402
+ BPF_REG_1 , offsetof(struct sk_buff , data ));
403
+ }
404
+
384
405
/*
385
406
* Emit function prologue
386
407
*
@@ -421,25 +442,12 @@ static void bpf_jit_prologue(struct bpf_jit *jit, bool is_classic)
421
442
EMIT6_DISP_LH (0xe3000000 , 0x0024 , REG_W1 , REG_0 ,
422
443
REG_15 , 152 );
423
444
}
424
- /*
425
- * For SKB access %b1 contains the SKB pointer. For "bpf_jit.S"
426
- * we store the SKB header length on the stack and the SKB data
427
- * pointer in REG_SKB_DATA.
428
- */
429
- if (jit -> seen & SEEN_SKB ) {
430
- /* Header length: llgf %w1,<len>(%b1) */
431
- EMIT6_DISP_LH (0xe3000000 , 0x0016 , REG_W1 , REG_0 , BPF_REG_1 ,
432
- offsetof(struct sk_buff , len ));
433
- /* s %w1,<data_len>(%b1) */
434
- EMIT4_DISP (0x5b000000 , REG_W1 , BPF_REG_1 ,
435
- offsetof(struct sk_buff , data_len ));
436
- /* stg %w1,ST_OFF_HLEN(%r0,%r15) */
445
+ if (jit -> seen & SEEN_SKB )
446
+ emit_load_skb_data_hlen (jit );
447
+ if (jit -> seen & SEEN_SKB_CHANGE )
448
+ /* stg %b1,ST_OFF_SKBP(%r0,%r15) */
437
449
EMIT6_DISP_LH (0xe3000000 , 0x0024 , REG_W1 , REG_0 , REG_15 ,
438
- STK_OFF_HLEN );
439
- /* lg %skb_data,data_off(%b1) */
440
- EMIT6_DISP_LH (0xe3000000 , 0x0004 , REG_SKB_DATA , REG_0 ,
441
- BPF_REG_1 , offsetof(struct sk_buff , data ));
442
- }
450
+ STK_OFF_SKBP );
443
451
/* Clear A (%b0) and X (%b7) registers for converted BPF programs */
444
452
if (is_classic ) {
445
453
if (REG_SEEN (BPF_REG_A ))
@@ -967,10 +975,6 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
967
975
*/
968
976
const u64 func = (u64 )__bpf_call_base + imm ;
969
977
970
- if (bpf_helper_changes_skb_data ((void * )func ))
971
- /* TODO reload skb->data, hlen */
972
- return -1 ;
973
-
974
978
REG_SET_SEEN (BPF_REG_5 );
975
979
jit -> seen |= SEEN_FUNC ;
976
980
/* lg %w1,<d(imm)>(%l) */
@@ -980,6 +984,13 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
980
984
EMIT2 (0x0d00 , REG_14 , REG_W1 );
981
985
/* lgr %b0,%r2: load return value into %b0 */
982
986
EMIT4 (0xb9040000 , BPF_REG_0 , REG_2 );
987
+ if (bpf_helper_changes_skb_data ((void * )func )) {
988
+ jit -> seen |= SEEN_SKB_CHANGE ;
989
+ /* lg %b1,ST_OFF_SKBP(%r15) */
990
+ EMIT6_DISP_LH (0xe3000000 , 0x0004 , BPF_REG_1 , REG_0 ,
991
+ REG_15 , STK_OFF_SKBP );
992
+ emit_load_skb_data_hlen (jit );
993
+ }
983
994
break ;
984
995
}
985
996
case BPF_JMP | BPF_CALL | BPF_X :
0 commit comments