]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
c10302ef MS |
2 | /* |
3 | * BPF Jit compiler for s390, help functions. | |
4 | * | |
05462310 | 5 | * Copyright IBM Corp. 2012,2015 |
c10302ef MS |
6 | * |
7 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> | |
05462310 | 8 | * Michael Holzheu <holzheu@linux.vnet.ibm.com> |
c10302ef | 9 | */ |
05462310 | 10 | |
c10302ef | 11 | #include <linux/linkage.h> |
05462310 | 12 | #include "bpf_jit.h" |
c10302ef MS |
13 | |
14 | /* | |
15 | * Calling convention: | |
05462310 MH |
16 | * registers %r7-%r10, %r11,%r13, and %r15 are call saved |
17 | * | |
18 | * Input (64 bit): | |
19 | * %r3 (%b2) = offset into skb data | |
20 | * %r6 (%b5) = return address | |
21 | * %r7 (%b6) = skb pointer | |
22 | * %r12 = skb data pointer | |
23 | * | |
24 | * Output: | |
25 | * %r14= %b0 = return value (read skb value) | |
26 | * | |
27 | * Work registers: %r2,%r4,%r5,%r14 | |
c10302ef MS |
28 | * |
29 | * skb_copy_bits takes 4 parameters: | |
30 | * %r2 = skb pointer | |
31 | * %r3 = offset into skb data | |
db9aa8f4 MH |
32 | * %r4 = pointer to temp buffer |
33 | * %r5 = length to copy | |
05462310 MH |
34 | * Return value in %r2: 0 = ok |
35 | * | |
36 | * bpf_internal_load_pointer_neg_helper takes 3 parameters: | |
37 | * %r2 = skb pointer | |
38 | * %r3 = offset into data | |
39 | * %r4 = length to copy | |
40 | * Return value in %r2: Pointer to data | |
c10302ef | 41 | */ |
c10302ef | 42 | |
05462310 | 43 | #define SKF_MAX_NEG_OFF -0x200000 /* SKF_LL_OFF from filter.h */ |
c10302ef | 44 | |
05462310 MH |
45 | /* |
46 | * Load SIZE bytes from SKB | |
47 | */ | |
48 | #define sk_load_common(NAME, SIZE, LOAD) \ | |
49 | ENTRY(sk_load_##NAME); \ | |
50 | ltgr %r3,%r3; /* Is offset negative? */ \ | |
51 | jl sk_load_##NAME##_slow_neg; \ | |
52 | ENTRY(sk_load_##NAME##_pos); \ | |
53 | aghi %r3,SIZE; /* Offset + SIZE */ \ | |
54 | clg %r3,STK_OFF_HLEN(%r15); /* Offset + SIZE > hlen? */ \ | |
55 | jh sk_load_##NAME##_slow; \ | |
56 | LOAD %r14,-SIZE(%r3,%r12); /* Get data from skb */ \ | |
57 | b OFF_OK(%r6); /* Return */ \ | |
58 | \ | |
59 | sk_load_##NAME##_slow:; \ | |
60 | lgr %r2,%r7; /* Arg1 = skb pointer */ \ | |
61 | aghi %r3,-SIZE; /* Arg2 = offset */ \ | |
62 | la %r4,STK_OFF_TMP(%r15); /* Arg3 = temp bufffer */ \ | |
63 | lghi %r5,SIZE; /* Arg4 = size */ \ | |
64 | brasl %r14,skb_copy_bits; /* Get data from skb */ \ | |
65 | LOAD %r14,STK_OFF_TMP(%r15); /* Load from temp bufffer */ \ | |
66 | ltgr %r2,%r2; /* Set cc to (%r2 != 0) */ \ | |
67 | br %r6; /* Return */ | |
c10302ef | 68 | |
05462310 MH |
69 | sk_load_common(word, 4, llgf) /* r14 = *(u32 *) (skb->data+offset) */ |
70 | sk_load_common(half, 2, llgh) /* r14 = *(u16 *) (skb->data+offset) */ | |
c10302ef | 71 | |
05462310 MH |
72 | /* |
73 | * Load 1 byte from SKB (optimized version) | |
74 | */ | |
75 | /* r14 = *(u8 *) (skb->data+offset) */ | |
c10302ef | 76 | ENTRY(sk_load_byte) |
05462310 MH |
77 | ltgr %r3,%r3 # Is offset negative? |
78 | jl sk_load_byte_slow_neg | |
79 | ENTRY(sk_load_byte_pos) | |
80 | clg %r3,STK_OFF_HLEN(%r15) # Offset >= hlen? | |
81 | jnl sk_load_byte_slow | |
82 | llgc %r14,0(%r3,%r12) # Get byte from skb | |
83 | b OFF_OK(%r6) # Return OK | |
c10302ef MS |
84 | |
85 | sk_load_byte_slow: | |
05462310 MH |
86 | lgr %r2,%r7 # Arg1 = skb pointer |
87 | # Arg2 = offset | |
88 | la %r4,STK_OFF_TMP(%r15) # Arg3 = pointer to temp buffer | |
89 | lghi %r5,1 # Arg4 = size (1 byte) | |
90 | brasl %r14,skb_copy_bits # Get data from skb | |
91 | llgc %r14,STK_OFF_TMP(%r15) # Load result from temp buffer | |
92 | ltgr %r2,%r2 # Set cc to (%r2 != 0) | |
93 | br %r6 # Return cc | |
94 | ||
95 | #define sk_negative_common(NAME, SIZE, LOAD) \ | |
96 | sk_load_##NAME##_slow_neg:; \ | |
97 | cgfi %r3,SKF_MAX_NEG_OFF; \ | |
98 | jl bpf_error; \ | |
99 | lgr %r2,%r7; /* Arg1 = skb pointer */ \ | |
100 | /* Arg2 = offset */ \ | |
101 | lghi %r4,SIZE; /* Arg3 = size */ \ | |
102 | brasl %r14,bpf_internal_load_pointer_neg_helper; \ | |
103 | ltgr %r2,%r2; \ | |
104 | jz bpf_error; \ | |
105 | LOAD %r14,0(%r2); /* Get data from pointer */ \ | |
106 | xr %r3,%r3; /* Set cc to zero */ \ | |
107 | br %r6; /* Return cc */ | |
c10302ef | 108 | |
05462310 MH |
109 | sk_negative_common(word, 4, llgf) |
110 | sk_negative_common(half, 2, llgh) | |
111 | sk_negative_common(byte, 1, llgc) | |
c10302ef | 112 | |
05462310 MH |
113 | bpf_error: |
114 | # force a return 0 from jit handler | |
115 | ltgr %r15,%r15 # Set condition code | |
116 | br %r6 |