|
1 | 1 | /*
|
2 | 2 | * BPF Jit compiler for s390, help functions.
|
3 | 3 | *
|
4 |
| - * Copyright IBM Corp. 2012 |
| 4 | + * Copyright IBM Corp. 2012,2015 |
5 | 5 | *
|
6 | 6 | * Author(s): Martin Schwidefsky <[email protected]>
|
| 7 | + * Michael Holzheu <[email protected]> |
7 | 8 | */
|
| 9 | + |
8 | 10 | #include <linux/linkage.h>
|
| 11 | +#include "bpf_jit.h" |
9 | 12 |
|
10 | 13 | /*
|
11 | 14 | * 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 |
21 | 27 | *
|
22 | 28 | * skb_copy_bits takes 4 parameters:
|
23 | 29 | * %r2 = skb pointer
|
24 | 30 | * %r3 = offset into skb data
|
25 | 31 | * %r4 = pointer to temp buffer
|
26 | 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 |
27 | 40 | */
|
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 |
44 | 41 |
|
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 */ |
55 | 43 |
|
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 */ |
82 | 67 |
|
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) */ |
87 | 70 |
|
88 |
| - /* A = *(u8 *) (skb->data+K) */ |
| 71 | +/* |
| 72 | + * Load 1 byte from SKB (optimized version) |
| 73 | + */ |
| 74 | + /* r14 = *(u8 *) (skb->data+offset) */ |
89 | 75 | 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 |
97 | 83 |
|
98 | 84 | 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 */ |
109 | 107 |
|
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) |
121 | 111 |
|
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 |
0 commit comments