Loading...
1/*
2 * BPF Jit compiler for s390, help functions.
3 *
4 * Copyright IBM Corp. 2012,2015
5 *
6 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
7 * Michael Holzheu <holzheu@linux.vnet.ibm.com>
8 */
9
10#include <linux/linkage.h>
11#include "bpf_jit.h"
12
13/*
14 * Calling convention:
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
27 *
28 * skb_copy_bits takes 4 parameters:
29 * %r2 = skb pointer
30 * %r3 = offset into skb data
31 * %r4 = pointer to temp buffer
32 * %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
40 */
41
42#define SKF_MAX_NEG_OFF -0x200000 /* SKF_LL_OFF from filter.h */
43
44/*
45 * Load SIZE bytes from SKB
46 */
47#define sk_load_common(NAME, SIZE, LOAD) \
48ENTRY(sk_load_##NAME); \
49 ltgr %r3,%r3; /* Is offset negative? */ \
50 jl sk_load_##NAME##_slow_neg; \
51ENTRY(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 \
58sk_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 */
67
68sk_load_common(word, 4, llgf) /* r14 = *(u32 *) (skb->data+offset) */
69sk_load_common(half, 2, llgh) /* r14 = *(u16 *) (skb->data+offset) */
70
71/*
72 * Load 1 byte from SKB (optimized version)
73 */
74 /* r14 = *(u8 *) (skb->data+offset) */
75ENTRY(sk_load_byte)
76 ltgr %r3,%r3 # Is offset negative?
77 jl sk_load_byte_slow_neg
78ENTRY(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
83
84sk_load_byte_slow:
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) \
95sk_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 */
107
108sk_negative_common(word, 4, llgf)
109sk_negative_common(half, 2, llgh)
110sk_negative_common(byte, 1, llgc)
111
112bpf_error:
113# force a return 0 from jit handler
114 ltgr %r15,%r15 # Set condition code
115 br %r6
1/*
2 * BPF Jit compiler for s390, help functions.
3 *
4 * Copyright IBM Corp. 2012
5 *
6 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
7 */
8#include <linux/linkage.h>
9
10/*
11 * 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
21 *
22 * skb_copy_bits takes 4 parameters:
23 * %r2 = skb pointer
24 * %r3 = offset into skb data
25 * %r4 = length to copy
26 * %r5 = pointer to temp buffer
27 */
28#define SKBDATA %r8
29
30 /* A = *(u32 *) (skb->data+K+X) */
31ENTRY(sk_load_word_ind)
32 ar %r3,%r12 # offset += X
33 bmr %r8 # < 0 -> return with cc
34
35 /* A = *(u32 *) (skb->data+K) */
36ENTRY(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
44
45sk_load_word_slow:
46 lgr %r9,%r2 # save %r2
47 lhi %r4,4 # 4 bytes
48 la %r5,160(%r15) # pointer to temp buffer
49 brasl %r14,skb_copy_bits # get data from skb
50 l %r5,160(%r15) # load result from temp buffer
51 ltgr %r2,%r2 # set cc to (%r2 != 0)
52 lgr %r2,%r9 # restore %r2
53 br %r8
54
55 /* A = *(u16 *) (skb->data+K+X) */
56ENTRY(sk_load_half_ind)
57 ar %r3,%r12 # offset += X
58 bmr %r8 # < 0 -> return with cc
59
60 /* A = *(u16 *) (skb->data+K) */
61ENTRY(sk_load_half)
62 llgfr %r1,%r3 # extend offset
63 ahi %r3,2 # offset + 2
64 clr %r11,%r3 # hlen <= offset + 2 ?
65 jl sk_load_half_slow
66 llgh %r5,0(%r1,%r10) # get half from skb
67 xr %r1,%r1 # set cc to zero
68 br %r8
69
70sk_load_half_slow:
71 lgr %r9,%r2 # save %r2
72 lhi %r4,2 # 2 bytes
73 la %r5,162(%r15) # pointer to temp buffer
74 brasl %r14,skb_copy_bits # get data from skb
75 xc 160(2,%r15),160(%r15)
76 l %r5,160(%r15) # load result from temp buffer
77 ltgr %r2,%r2 # set cc to (%r2 != 0)
78 lgr %r2,%r9 # restore %r2
79 br %r8
80
81 /* A = *(u8 *) (skb->data+K+X) */
82ENTRY(sk_load_byte_ind)
83 ar %r3,%r12 # offset += X
84 bmr %r8 # < 0 -> return with cc
85
86 /* A = *(u8 *) (skb->data+K) */
87ENTRY(sk_load_byte)
88 llgfr %r1,%r3 # extend offset
89 clr %r11,%r3 # hlen < offset ?
90 jle sk_load_byte_slow
91 lhi %r5,0
92 ic %r5,0(%r1,%r10) # get byte from skb
93 xr %r1,%r1 # set cc to zero
94 br %r8
95
96sk_load_byte_slow:
97 lgr %r9,%r2 # save %r2
98 lhi %r4,1 # 1 bytes
99 la %r5,163(%r15) # pointer to temp buffer
100 brasl %r14,skb_copy_bits # get data from skb
101 xc 160(3,%r15),160(%r15)
102 l %r5,160(%r15) # load result from temp buffer
103 ltgr %r2,%r2 # set cc to (%r2 != 0)
104 lgr %r2,%r9 # restore %r2
105 br %r8
106
107 /* A = (*(u8 *)(skb->data+K) & 0xf) << 2 */
108ENTRY(sk_load_byte_msh)
109 llgfr %r1,%r3 # extend offset
110 clr %r11,%r3 # hlen < offset ?
111 jle sk_load_byte_slow
112 lhi %r12,0
113 ic %r12,0(%r1,%r10) # get byte from skb
114 nill %r12,0x0f
115 sll %r12,2
116 xr %r1,%r1 # set cc to zero
117 br %r8
118
119sk_load_byte_msh_slow:
120 lgr %r9,%r2 # save %r2
121 lhi %r4,2 # 2 bytes
122 la %r5,162(%r15) # pointer to temp buffer
123 brasl %r14,skb_copy_bits # get data from skb
124 xc 160(3,%r15),160(%r15)
125 l %r12,160(%r15) # load result from temp buffer
126 nill %r12,0x0f
127 sll %r12,2
128 ltgr %r2,%r2 # set cc to (%r2 != 0)
129 lgr %r2,%r9 # restore %r2
130 br %r8