Greg Kroah-Hartman | b244131 | 2017-11-01 15:07:57 +0100 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
Martin Schwidefsky | c10302e | 2012-07-31 16:23:59 +0200 | [diff] [blame] | 2 | /* |
| 3 | * BPF Jit compiler for s390, help functions. |
| 4 | * |
Michael Holzheu | 0546231 | 2015-04-01 16:08:32 +0200 | [diff] [blame] | 5 | * Copyright IBM Corp. 2012,2015 |
Martin Schwidefsky | c10302e | 2012-07-31 16:23:59 +0200 | [diff] [blame] | 6 | * |
| 7 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> |
Michael Holzheu | 0546231 | 2015-04-01 16:08:32 +0200 | [diff] [blame] | 8 | * Michael Holzheu <holzheu@linux.vnet.ibm.com> |
Martin Schwidefsky | c10302e | 2012-07-31 16:23:59 +0200 | [diff] [blame] | 9 | */ |
Michael Holzheu | 0546231 | 2015-04-01 16:08:32 +0200 | [diff] [blame] | 10 | |
Martin Schwidefsky | c10302e | 2012-07-31 16:23:59 +0200 | [diff] [blame] | 11 | #include <linux/linkage.h> |
Michael Holzheu | 0546231 | 2015-04-01 16:08:32 +0200 | [diff] [blame] | 12 | #include "bpf_jit.h" |
Martin Schwidefsky | c10302e | 2012-07-31 16:23:59 +0200 | [diff] [blame] | 13 | |
| 14 | /* |
| 15 | * Calling convention: |
Michael Holzheu | 0546231 | 2015-04-01 16:08:32 +0200 | [diff] [blame] | 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 |
Martin Schwidefsky | c10302e | 2012-07-31 16:23:59 +0200 | [diff] [blame] | 28 | * |
| 29 | * skb_copy_bits takes 4 parameters: |
| 30 | * %r2 = skb pointer |
| 31 | * %r3 = offset into skb data |
Michael Holzheu | db9aa8f | 2015-01-15 10:20:28 +0100 | [diff] [blame] | 32 | * %r4 = pointer to temp buffer |
| 33 | * %r5 = length to copy |
Michael Holzheu | 0546231 | 2015-04-01 16:08:32 +0200 | [diff] [blame] | 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 |
Martin Schwidefsky | c10302e | 2012-07-31 16:23:59 +0200 | [diff] [blame] | 41 | */ |
Martin Schwidefsky | c10302e | 2012-07-31 16:23:59 +0200 | [diff] [blame] | 42 | |
Michael Holzheu | 0546231 | 2015-04-01 16:08:32 +0200 | [diff] [blame] | 43 | #define SKF_MAX_NEG_OFF -0x200000 /* SKF_LL_OFF from filter.h */ |
Martin Schwidefsky | c10302e | 2012-07-31 16:23:59 +0200 | [diff] [blame] | 44 | |
Michael Holzheu | 0546231 | 2015-04-01 16:08:32 +0200 | [diff] [blame] | 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 */ |
Martin Schwidefsky | c10302e | 2012-07-31 16:23:59 +0200 | [diff] [blame] | 68 | |
Michael Holzheu | 0546231 | 2015-04-01 16:08:32 +0200 | [diff] [blame] | 69 | sk_load_common(word, 4, llgf) /* r14 = *(u32 *) (skb->data+offset) */ |
| 70 | sk_load_common(half, 2, llgh) /* r14 = *(u16 *) (skb->data+offset) */ |
Martin Schwidefsky | c10302e | 2012-07-31 16:23:59 +0200 | [diff] [blame] | 71 | |
Michael Holzheu | 0546231 | 2015-04-01 16:08:32 +0200 | [diff] [blame] | 72 | /* |
| 73 | * Load 1 byte from SKB (optimized version) |
| 74 | */ |
| 75 | /* r14 = *(u8 *) (skb->data+offset) */ |
Martin Schwidefsky | c10302e | 2012-07-31 16:23:59 +0200 | [diff] [blame] | 76 | ENTRY(sk_load_byte) |
Michael Holzheu | 0546231 | 2015-04-01 16:08:32 +0200 | [diff] [blame] | 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 |
Martin Schwidefsky | c10302e | 2012-07-31 16:23:59 +0200 | [diff] [blame] | 84 | |
| 85 | sk_load_byte_slow: |
Michael Holzheu | 0546231 | 2015-04-01 16:08:32 +0200 | [diff] [blame] | 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 |
Martin Schwidefsky | c10302e | 2012-07-31 16:23:59 +0200 | [diff] [blame] | 94 | |
Michael Holzheu | 0546231 | 2015-04-01 16:08:32 +0200 | [diff] [blame] | 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 */ |
Martin Schwidefsky | c10302e | 2012-07-31 16:23:59 +0200 | [diff] [blame] | 108 | |
Michael Holzheu | 0546231 | 2015-04-01 16:08:32 +0200 | [diff] [blame] | 109 | sk_negative_common(word, 4, llgf) |
| 110 | sk_negative_common(half, 2, llgh) |
| 111 | sk_negative_common(byte, 1, llgc) |
| 112 | |
| 113 | bpf_error: |
| 114 | # force a return 0 from jit handler |
| 115 | ltgr %r15,%r15 # Set condition code |
| 116 | br %r6 |