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 131