mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 04:31:50 +00:00
s390/bpf: Add s390x eBPF JIT compiler backend
Replace 32 bit BPF JIT backend with new 64 bit eBPF backend. Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
1c6e4b1811
commit
0546231057
@ -115,7 +115,7 @@ config S390
|
||||
select HAVE_ARCH_SECCOMP_FILTER
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
|
||||
select HAVE_BPF_JIT if PACK_STACK
|
||||
select HAVE_BPF_JIT if PACK_STACK && HAVE_MARCH_Z9_109_FEATURES
|
||||
select HAVE_CMPXCHG_DOUBLE
|
||||
select HAVE_CMPXCHG_LOCAL
|
||||
select HAVE_DEBUG_KMEMLEAK
|
||||
|
@ -1,134 +1,115 @@
|
||||
/*
|
||||
* BPF Jit compiler for s390, help functions.
|
||||
*
|
||||
* Copyright IBM Corp. 2012
|
||||
* Copyright IBM Corp. 2012,2015
|
||||
*
|
||||
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||
* Michael Holzheu <holzheu@linux.vnet.ibm.com>
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include "bpf_jit.h"
|
||||
|
||||
/*
|
||||
* Calling convention:
|
||||
* registers %r2, %r6-%r8, %r10-%r11, %r13, %r15 are call saved
|
||||
* %r2: skb pointer
|
||||
* %r3: offset parameter
|
||||
* %r5: BPF A accumulator
|
||||
* %r8: return address
|
||||
* %r9: save register for skb pointer
|
||||
* %r10: skb->data
|
||||
* %r11: skb->len - skb->data_len (headlen)
|
||||
* %r12: BPF X accumulator
|
||||
* registers %r7-%r10, %r11,%r13, and %r15 are call saved
|
||||
*
|
||||
* Input (64 bit):
|
||||
* %r3 (%b2) = offset into skb data
|
||||
* %r6 (%b5) = return address
|
||||
* %r7 (%b6) = skb pointer
|
||||
* %r12 = skb data pointer
|
||||
*
|
||||
* Output:
|
||||
* %r14= %b0 = return value (read skb value)
|
||||
*
|
||||
* Work registers: %r2,%r4,%r5,%r14
|
||||
*
|
||||
* skb_copy_bits takes 4 parameters:
|
||||
* %r2 = skb pointer
|
||||
* %r3 = offset into skb data
|
||||
* %r4 = pointer to temp buffer
|
||||
* %r5 = length to copy
|
||||
* Return value in %r2: 0 = ok
|
||||
*
|
||||
* bpf_internal_load_pointer_neg_helper takes 3 parameters:
|
||||
* %r2 = skb pointer
|
||||
* %r3 = offset into data
|
||||
* %r4 = length to copy
|
||||
* Return value in %r2: Pointer to data
|
||||
*/
|
||||
#define SKBDATA %r8
|
||||
|
||||
/* A = *(u32 *) (skb->data+K+X) */
|
||||
ENTRY(sk_load_word_ind)
|
||||
ar %r3,%r12 # offset += X
|
||||
bmr %r8 # < 0 -> return with cc
|
||||
#define SKF_MAX_NEG_OFF -0x200000 /* SKF_LL_OFF from filter.h */
|
||||
|
||||
/* A = *(u32 *) (skb->data+K) */
|
||||
ENTRY(sk_load_word)
|
||||
llgfr %r1,%r3 # extend offset
|
||||
ahi %r3,4 # offset + 4
|
||||
clr %r11,%r3 # hlen <= offset + 4 ?
|
||||
jl sk_load_word_slow
|
||||
l %r5,0(%r1,%r10) # get word from skb
|
||||
xr %r1,%r1 # set cc to zero
|
||||
br %r8
|
||||
/*
|
||||
* Load SIZE bytes from SKB
|
||||
*/
|
||||
#define sk_load_common(NAME, SIZE, LOAD) \
|
||||
ENTRY(sk_load_##NAME); \
|
||||
ltgr %r3,%r3; /* Is offset negative? */ \
|
||||
jl sk_load_##NAME##_slow_neg; \
|
||||
ENTRY(sk_load_##NAME##_pos); \
|
||||
aghi %r3,SIZE; /* Offset + SIZE */ \
|
||||
clg %r3,STK_OFF_HLEN(%r15); /* Offset + SIZE > hlen? */ \
|
||||
jh sk_load_##NAME##_slow; \
|
||||
LOAD %r14,-SIZE(%r3,%r12); /* Get data from skb */ \
|
||||
b OFF_OK(%r6); /* Return */ \
|
||||
\
|
||||
sk_load_##NAME##_slow:; \
|
||||
lgr %r2,%r7; /* Arg1 = skb pointer */ \
|
||||
aghi %r3,-SIZE; /* Arg2 = offset */ \
|
||||
la %r4,STK_OFF_TMP(%r15); /* Arg3 = temp bufffer */ \
|
||||
lghi %r5,SIZE; /* Arg4 = size */ \
|
||||
brasl %r14,skb_copy_bits; /* Get data from skb */ \
|
||||
LOAD %r14,STK_OFF_TMP(%r15); /* Load from temp bufffer */ \
|
||||
ltgr %r2,%r2; /* Set cc to (%r2 != 0) */ \
|
||||
br %r6; /* Return */
|
||||
|
||||
sk_load_word_slow:
|
||||
lgr %r9,%r2 # save %r2
|
||||
lgr %r3,%r1 # offset
|
||||
la %r4,160(%r15) # pointer to temp buffer
|
||||
lghi %r5,4 # 4 bytes
|
||||
brasl %r14,skb_copy_bits # get data from skb
|
||||
l %r5,160(%r15) # load result from temp buffer
|
||||
ltgr %r2,%r2 # set cc to (%r2 != 0)
|
||||
lgr %r2,%r9 # restore %r2
|
||||
br %r8
|
||||
sk_load_common(word, 4, llgf) /* r14 = *(u32 *) (skb->data+offset) */
|
||||
sk_load_common(half, 2, llgh) /* r14 = *(u16 *) (skb->data+offset) */
|
||||
|
||||
/* A = *(u16 *) (skb->data+K+X) */
|
||||
ENTRY(sk_load_half_ind)
|
||||
ar %r3,%r12 # offset += X
|
||||
bmr %r8 # < 0 -> return with cc
|
||||
|
||||
/* A = *(u16 *) (skb->data+K) */
|
||||
ENTRY(sk_load_half)
|
||||
llgfr %r1,%r3 # extend offset
|
||||
ahi %r3,2 # offset + 2
|
||||
clr %r11,%r3 # hlen <= offset + 2 ?
|
||||
jl sk_load_half_slow
|
||||
llgh %r5,0(%r1,%r10) # get half from skb
|
||||
xr %r1,%r1 # set cc to zero
|
||||
br %r8
|
||||
|
||||
sk_load_half_slow:
|
||||
lgr %r9,%r2 # save %r2
|
||||
lgr %r3,%r1 # offset
|
||||
la %r4,162(%r15) # pointer to temp buffer
|
||||
lghi %r5,2 # 2 bytes
|
||||
brasl %r14,skb_copy_bits # get data from skb
|
||||
xc 160(2,%r15),160(%r15)
|
||||
l %r5,160(%r15) # load result from temp buffer
|
||||
ltgr %r2,%r2 # set cc to (%r2 != 0)
|
||||
lgr %r2,%r9 # restore %r2
|
||||
br %r8
|
||||
|
||||
/* A = *(u8 *) (skb->data+K+X) */
|
||||
ENTRY(sk_load_byte_ind)
|
||||
ar %r3,%r12 # offset += X
|
||||
bmr %r8 # < 0 -> return with cc
|
||||
|
||||
/* A = *(u8 *) (skb->data+K) */
|
||||
/*
|
||||
* Load 1 byte from SKB (optimized version)
|
||||
*/
|
||||
/* r14 = *(u8 *) (skb->data+offset) */
|
||||
ENTRY(sk_load_byte)
|
||||
llgfr %r1,%r3 # extend offset
|
||||
clr %r11,%r3 # hlen < offset ?
|
||||
jle sk_load_byte_slow
|
||||
lhi %r5,0
|
||||
ic %r5,0(%r1,%r10) # get byte from skb
|
||||
xr %r1,%r1 # set cc to zero
|
||||
br %r8
|
||||
ltgr %r3,%r3 # Is offset negative?
|
||||
jl sk_load_byte_slow_neg
|
||||
ENTRY(sk_load_byte_pos)
|
||||
clg %r3,STK_OFF_HLEN(%r15) # Offset >= hlen?
|
||||
jnl sk_load_byte_slow
|
||||
llgc %r14,0(%r3,%r12) # Get byte from skb
|
||||
b OFF_OK(%r6) # Return OK
|
||||
|
||||
sk_load_byte_slow:
|
||||
lgr %r9,%r2 # save %r2
|
||||
lgr %r3,%r1 # offset
|
||||
la %r4,163(%r15) # pointer to temp buffer
|
||||
lghi %r5,1 # 1 byte
|
||||
brasl %r14,skb_copy_bits # get data from skb
|
||||
xc 160(3,%r15),160(%r15)
|
||||
l %r5,160(%r15) # load result from temp buffer
|
||||
ltgr %r2,%r2 # set cc to (%r2 != 0)
|
||||
lgr %r2,%r9 # restore %r2
|
||||
br %r8
|
||||
lgr %r2,%r7 # Arg1 = skb pointer
|
||||
# Arg2 = offset
|
||||
la %r4,STK_OFF_TMP(%r15) # Arg3 = pointer to temp buffer
|
||||
lghi %r5,1 # Arg4 = size (1 byte)
|
||||
brasl %r14,skb_copy_bits # Get data from skb
|
||||
llgc %r14,STK_OFF_TMP(%r15) # Load result from temp buffer
|
||||
ltgr %r2,%r2 # Set cc to (%r2 != 0)
|
||||
br %r6 # Return cc
|
||||
|
||||
/* X = (*(u8 *)(skb->data+K) & 0xf) << 2 */
|
||||
ENTRY(sk_load_byte_msh)
|
||||
llgfr %r1,%r3 # extend offset
|
||||
clr %r11,%r3 # hlen < offset ?
|
||||
jle sk_load_byte_msh_slow
|
||||
lhi %r12,0
|
||||
ic %r12,0(%r1,%r10) # get byte from skb
|
||||
nill %r12,0x0f
|
||||
sll %r12,2
|
||||
xr %r1,%r1 # set cc to zero
|
||||
br %r8
|
||||
#define sk_negative_common(NAME, SIZE, LOAD) \
|
||||
sk_load_##NAME##_slow_neg:; \
|
||||
cgfi %r3,SKF_MAX_NEG_OFF; \
|
||||
jl bpf_error; \
|
||||
lgr %r2,%r7; /* Arg1 = skb pointer */ \
|
||||
/* Arg2 = offset */ \
|
||||
lghi %r4,SIZE; /* Arg3 = size */ \
|
||||
brasl %r14,bpf_internal_load_pointer_neg_helper; \
|
||||
ltgr %r2,%r2; \
|
||||
jz bpf_error; \
|
||||
LOAD %r14,0(%r2); /* Get data from pointer */ \
|
||||
xr %r3,%r3; /* Set cc to zero */ \
|
||||
br %r6; /* Return cc */
|
||||
|
||||
sk_load_byte_msh_slow:
|
||||
lgr %r9,%r2 # save %r2
|
||||
lgr %r3,%r1 # offset
|
||||
la %r4,163(%r15) # pointer to temp buffer
|
||||
lghi %r5,1 # 1 byte
|
||||
brasl %r14,skb_copy_bits # get data from skb
|
||||
xc 160(3,%r15),160(%r15)
|
||||
l %r12,160(%r15) # load result from temp buffer
|
||||
nill %r12,0x0f
|
||||
sll %r12,2
|
||||
ltgr %r2,%r2 # set cc to (%r2 != 0)
|
||||
lgr %r2,%r9 # restore %r2
|
||||
br %r8
|
||||
sk_negative_common(word, 4, llgf)
|
||||
sk_negative_common(half, 2, llgh)
|
||||
sk_negative_common(byte, 1, llgc)
|
||||
|
||||
bpf_error:
|
||||
# force a return 0 from jit handler
|
||||
ltgr %r15,%r15 # Set condition code
|
||||
br %r6
|
||||
|
58
arch/s390/net/bpf_jit.h
Normal file
58
arch/s390/net/bpf_jit.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* BPF Jit compiler defines
|
||||
*
|
||||
* Copyright IBM Corp. 2012,2015
|
||||
*
|
||||
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||
* Michael Holzheu <holzheu@linux.vnet.ibm.com>
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_S390_NET_BPF_JIT_H
|
||||
#define __ARCH_S390_NET_BPF_JIT_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/filter.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
extern u8 sk_load_word_pos[], sk_load_half_pos[], sk_load_byte_pos[];
|
||||
extern u8 sk_load_word[], sk_load_half[], sk_load_byte[];
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/*
|
||||
* Stackframe layout (packed stack):
|
||||
*
|
||||
* ^ high
|
||||
* +---------------+ |
|
||||
* | old backchain | |
|
||||
* +---------------+ |
|
||||
* | r15 - r6 | |
|
||||
* BFP -> +===============+ |
|
||||
* | | |
|
||||
* | BPF stack | |
|
||||
* | | |
|
||||
* +---------------+ |
|
||||
* | 8 byte hlen | |
|
||||
* R15+168 -> +---------------+ |
|
||||
* | 4 byte align | |
|
||||
* +---------------+ |
|
||||
* | 4 byte temp | |
|
||||
* | for bpf_jit.S | |
|
||||
* R15+160 -> +---------------+ |
|
||||
* | new backchain | |
|
||||
* R15+152 -> +---------------+ |
|
||||
* | + 152 byte SA | |
|
||||
* R15 -> +---------------+ + low
|
||||
*
|
||||
* We get 160 bytes stack space from calling function, but only use
|
||||
* 11 * 8 byte (old backchain + r15 - r6) for storing registers.
|
||||
*/
|
||||
#define STK_OFF (MAX_BPF_STACK + 8 + 4 + 4 + (160 - 11 * 8))
|
||||
#define STK_OFF_TMP 160 /* Offset of tmp buffer on stack */
|
||||
#define STK_OFF_HLEN 168 /* Offset of SKB header length on stack */
|
||||
|
||||
/* Offset to skip condition code check */
|
||||
#define OFF_OK 4
|
||||
|
||||
#endif /* __ARCH_S390_NET_BPF_JIT_H */
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user