Skip to content

Commit 0546231

Browse files
Michael HolzheuMartin Schwidefsky
Michael Holzheu
authored and
Martin Schwidefsky
committed
s390/bpf: Add s390x eBPF JIT compiler backend
Replace 32 bit BPF JIT backend with new 64 bit eBPF backend. Signed-off-by: Michael Holzheu <[email protected]> Signed-off-by: Martin Schwidefsky <[email protected]>
1 parent 1c6e4b1 commit 0546231

File tree

4 files changed

+1234
-803
lines changed

4 files changed

+1234
-803
lines changed

arch/s390/Kconfig

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ config S390
115115
select HAVE_ARCH_SECCOMP_FILTER
116116
select HAVE_ARCH_TRACEHOOK
117117
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
118-
select HAVE_BPF_JIT if PACK_STACK
118+
select HAVE_BPF_JIT if PACK_STACK && HAVE_MARCH_Z9_109_FEATURES
119119
select HAVE_CMPXCHG_DOUBLE
120120
select HAVE_CMPXCHG_LOCAL
121121
select HAVE_DEBUG_KMEMLEAK

arch/s390/net/bpf_jit.S

+89-108
Original file line numberDiff line numberDiff line change
@@ -1,134 +1,115 @@
11
/*
22
* BPF Jit compiler for s390, help functions.
33
*
4-
* Copyright IBM Corp. 2012
4+
* Copyright IBM Corp. 2012,2015
55
*
66
* Author(s): Martin Schwidefsky <[email protected]>
7+
* Michael Holzheu <[email protected]>
78
*/
9+
810
#include <linux/linkage.h>
11+
#include "bpf_jit.h"
912

1013
/*
1114
* Calling convention:
12-
* registers %r2, %r6-%r8, %r10-%r11, %r13, %r15 are call saved
13-
* %r2: skb pointer
14-
* %r3: offset parameter
15-
* %r5: BPF A accumulator
16-
* %r8: return address
17-
* %r9: save register for skb pointer
18-
* %r10: skb->data
19-
* %r11: skb->len - skb->data_len (headlen)
20-
* %r12: BPF X accumulator
15+
* registers %r7-%r10, %r11,%r13, and %r15 are call saved
16+
*
17+
* Input (64 bit):
18+
* %r3 (%b2) = offset into skb data
19+
* %r6 (%b5) = return address
20+
* %r7 (%b6) = skb pointer
21+
* %r12 = skb data pointer
22+
*
23+
* Output:
24+
* %r14= %b0 = return value (read skb value)
25+
*
26+
* Work registers: %r2,%r4,%r5,%r14
2127
*
2228
* skb_copy_bits takes 4 parameters:
2329
* %r2 = skb pointer
2430
* %r3 = offset into skb data
2531
* %r4 = pointer to temp buffer
2632
* %r5 = length to copy
33+
* Return value in %r2: 0 = ok
34+
*
35+
* bpf_internal_load_pointer_neg_helper takes 3 parameters:
36+
* %r2 = skb pointer
37+
* %r3 = offset into data
38+
* %r4 = length to copy
39+
* Return value in %r2: Pointer to data
2740
*/
28-
#define SKBDATA %r8
29-
30-
/* A = *(u32 *) (skb->data+K+X) */
31-
ENTRY(sk_load_word_ind)
32-
ar %r3,%r12 # offset += X
33-
bmr %r8 # < 0 -> return with cc
34-
35-
/* A = *(u32 *) (skb->data+K) */
36-
ENTRY(sk_load_word)
37-
llgfr %r1,%r3 # extend offset
38-
ahi %r3,4 # offset + 4
39-
clr %r11,%r3 # hlen <= offset + 4 ?
40-
jl sk_load_word_slow
41-
l %r5,0(%r1,%r10) # get word from skb
42-
xr %r1,%r1 # set cc to zero
43-
br %r8
4441

45-
sk_load_word_slow:
46-
lgr %r9,%r2 # save %r2
47-
lgr %r3,%r1 # offset
48-
la %r4,160(%r15) # pointer to temp buffer
49-
lghi %r5,4 # 4 bytes
50-
brasl %r14,skb_copy_bits # get data from skb
51-
l %r5,160(%r15) # load result from temp buffer
52-
ltgr %r2,%r2 # set cc to (%r2 != 0)
53-
lgr %r2,%r9 # restore %r2
54-
br %r8
42+
#define SKF_MAX_NEG_OFF -0x200000 /* SKF_LL_OFF from filter.h */
5543

56-
/* A = *(u16 *) (skb->data+K+X) */
57-
ENTRY(sk_load_half_ind)
58-
ar %r3,%r12 # offset += X
59-
bmr %r8 # < 0 -> return with cc
60-
61-
/* A = *(u16 *) (skb->data+K) */
62-
ENTRY(sk_load_half)
63-
llgfr %r1,%r3 # extend offset
64-
ahi %r3,2 # offset + 2
65-
clr %r11,%r3 # hlen <= offset + 2 ?
66-
jl sk_load_half_slow
67-
llgh %r5,0(%r1,%r10) # get half from skb
68-
xr %r1,%r1 # set cc to zero
69-
br %r8
70-
71-
sk_load_half_slow:
72-
lgr %r9,%r2 # save %r2
73-
lgr %r3,%r1 # offset
74-
la %r4,162(%r15) # pointer to temp buffer
75-
lghi %r5,2 # 2 bytes
76-
brasl %r14,skb_copy_bits # get data from skb
77-
xc 160(2,%r15),160(%r15)
78-
l %r5,160(%r15) # load result from temp buffer
79-
ltgr %r2,%r2 # set cc to (%r2 != 0)
80-
lgr %r2,%r9 # restore %r2
81-
br %r8
44+
/*
45+
* Load SIZE bytes from SKB
46+
*/
47+
#define sk_load_common(NAME, SIZE, LOAD) \
48+
ENTRY(sk_load_##NAME); \
49+
ltgr %r3,%r3; /* Is offset negative? */ \
50+
jl sk_load_##NAME##_slow_neg; \
51+
ENTRY(sk_load_##NAME##_pos); \
52+
aghi %r3,SIZE; /* Offset + SIZE */ \
53+
clg %r3,STK_OFF_HLEN(%r15); /* Offset + SIZE > hlen? */ \
54+
jh sk_load_##NAME##_slow; \
55+
LOAD %r14,-SIZE(%r3,%r12); /* Get data from skb */ \
56+
b OFF_OK(%r6); /* Return */ \
57+
\
58+
sk_load_##NAME##_slow:; \
59+
lgr %r2,%r7; /* Arg1 = skb pointer */ \
60+
aghi %r3,-SIZE; /* Arg2 = offset */ \
61+
la %r4,STK_OFF_TMP(%r15); /* Arg3 = temp bufffer */ \
62+
lghi %r5,SIZE; /* Arg4 = size */ \
63+
brasl %r14,skb_copy_bits; /* Get data from skb */ \
64+
LOAD %r14,STK_OFF_TMP(%r15); /* Load from temp bufffer */ \
65+
ltgr %r2,%r2; /* Set cc to (%r2 != 0) */ \
66+
br %r6; /* Return */
8267

83-
/* A = *(u8 *) (skb->data+K+X) */
84-
ENTRY(sk_load_byte_ind)
85-
ar %r3,%r12 # offset += X
86-
bmr %r8 # < 0 -> return with cc
68+
sk_load_common(word, 4, llgf) /* r14 = *(u32 *) (skb->data+offset) */
69+
sk_load_common(half, 2, llgh) /* r14 = *(u16 *) (skb->data+offset) */
8770

88-
/* A = *(u8 *) (skb->data+K) */
71+
/*
72+
* Load 1 byte from SKB (optimized version)
73+
*/
74+
/* r14 = *(u8 *) (skb->data+offset) */
8975
ENTRY(sk_load_byte)
90-
llgfr %r1,%r3 # extend offset
91-
clr %r11,%r3 # hlen < offset ?
92-
jle sk_load_byte_slow
93-
lhi %r5,0
94-
ic %r5,0(%r1,%r10) # get byte from skb
95-
xr %r1,%r1 # set cc to zero
96-
br %r8
76+
ltgr %r3,%r3 # Is offset negative?
77+
jl sk_load_byte_slow_neg
78+
ENTRY(sk_load_byte_pos)
79+
clg %r3,STK_OFF_HLEN(%r15) # Offset >= hlen?
80+
jnl sk_load_byte_slow
81+
llgc %r14,0(%r3,%r12) # Get byte from skb
82+
b OFF_OK(%r6) # Return OK
9783

9884
sk_load_byte_slow:
99-
lgr %r9,%r2 # save %r2
100-
lgr %r3,%r1 # offset
101-
la %r4,163(%r15) # pointer to temp buffer
102-
lghi %r5,1 # 1 byte
103-
brasl %r14,skb_copy_bits # get data from skb
104-
xc 160(3,%r15),160(%r15)
105-
l %r5,160(%r15) # load result from temp buffer
106-
ltgr %r2,%r2 # set cc to (%r2 != 0)
107-
lgr %r2,%r9 # restore %r2
108-
br %r8
85+
lgr %r2,%r7 # Arg1 = skb pointer
86+
# Arg2 = offset
87+
la %r4,STK_OFF_TMP(%r15) # Arg3 = pointer to temp buffer
88+
lghi %r5,1 # Arg4 = size (1 byte)
89+
brasl %r14,skb_copy_bits # Get data from skb
90+
llgc %r14,STK_OFF_TMP(%r15) # Load result from temp buffer
91+
ltgr %r2,%r2 # Set cc to (%r2 != 0)
92+
br %r6 # Return cc
93+
94+
#define sk_negative_common(NAME, SIZE, LOAD) \
95+
sk_load_##NAME##_slow_neg:; \
96+
cgfi %r3,SKF_MAX_NEG_OFF; \
97+
jl bpf_error; \
98+
lgr %r2,%r7; /* Arg1 = skb pointer */ \
99+
/* Arg2 = offset */ \
100+
lghi %r4,SIZE; /* Arg3 = size */ \
101+
brasl %r14,bpf_internal_load_pointer_neg_helper; \
102+
ltgr %r2,%r2; \
103+
jz bpf_error; \
104+
LOAD %r14,0(%r2); /* Get data from pointer */ \
105+
xr %r3,%r3; /* Set cc to zero */ \
106+
br %r6; /* Return cc */
109107

110-
/* X = (*(u8 *)(skb->data+K) & 0xf) << 2 */
111-
ENTRY(sk_load_byte_msh)
112-
llgfr %r1,%r3 # extend offset
113-
clr %r11,%r3 # hlen < offset ?
114-
jle sk_load_byte_msh_slow
115-
lhi %r12,0
116-
ic %r12,0(%r1,%r10) # get byte from skb
117-
nill %r12,0x0f
118-
sll %r12,2
119-
xr %r1,%r1 # set cc to zero
120-
br %r8
108+
sk_negative_common(word, 4, llgf)
109+
sk_negative_common(half, 2, llgh)
110+
sk_negative_common(byte, 1, llgc)
121111

122-
sk_load_byte_msh_slow:
123-
lgr %r9,%r2 # save %r2
124-
lgr %r3,%r1 # offset
125-
la %r4,163(%r15) # pointer to temp buffer
126-
lghi %r5,1 # 1 byte
127-
brasl %r14,skb_copy_bits # get data from skb
128-
xc 160(3,%r15),160(%r15)
129-
l %r12,160(%r15) # load result from temp buffer
130-
nill %r12,0x0f
131-
sll %r12,2
132-
ltgr %r2,%r2 # set cc to (%r2 != 0)
133-
lgr %r2,%r9 # restore %r2
134-
br %r8
112+
bpf_error:
113+
# force a return 0 from jit handler
114+
ltgr %r15,%r15 # Set condition code
115+
br %r6

arch/s390/net/bpf_jit.h

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* BPF Jit compiler defines
3+
*
4+
* Copyright IBM Corp. 2012,2015
5+
*
6+
* Author(s): Martin Schwidefsky <[email protected]>
7+
* Michael Holzheu <[email protected]>
8+
*/
9+
10+
#ifndef __ARCH_S390_NET_BPF_JIT_H
11+
#define __ARCH_S390_NET_BPF_JIT_H
12+
13+
#ifndef __ASSEMBLY__
14+
15+
#include <linux/filter.h>
16+
#include <linux/types.h>
17+
18+
extern u8 sk_load_word_pos[], sk_load_half_pos[], sk_load_byte_pos[];
19+
extern u8 sk_load_word[], sk_load_half[], sk_load_byte[];
20+
21+
#endif /* __ASSEMBLY__ */
22+
23+
/*
24+
* Stackframe layout (packed stack):
25+
*
26+
* ^ high
27+
* +---------------+ |
28+
* | old backchain | |
29+
* +---------------+ |
30+
* | r15 - r6 | |
31+
* BFP -> +===============+ |
32+
* | | |
33+
* | BPF stack | |
34+
* | | |
35+
* +---------------+ |
36+
* | 8 byte hlen | |
37+
* R15+168 -> +---------------+ |
38+
* | 4 byte align | |
39+
* +---------------+ |
40+
* | 4 byte temp | |
41+
* | for bpf_jit.S | |
42+
* R15+160 -> +---------------+ |
43+
* | new backchain | |
44+
* R15+152 -> +---------------+ |
45+
* | + 152 byte SA | |
46+
* R15 -> +---------------+ + low
47+
*
48+
* We get 160 bytes stack space from calling function, but only use
49+
* 11 * 8 byte (old backchain + r15 - r6) for storing registers.
50+
*/
51+
#define STK_OFF (MAX_BPF_STACK + 8 + 4 + 4 + (160 - 11 * 8))
52+
#define STK_OFF_TMP 160 /* Offset of tmp buffer on stack */
53+
#define STK_OFF_HLEN 168 /* Offset of SKB header length on stack */
54+
55+
/* Offset to skip condition code check */
56+
#define OFF_OK 4
57+
58+
#endif /* __ARCH_S390_NET_BPF_JIT_H */

0 commit comments

Comments
 (0)