Commit c10302ef authored by Martin Schwidefsky's avatar Martin Schwidefsky

s390/bpf,jit: BPF Just In Time compiler for s390

The s390 implementation of the JIT compiler for packet filter speedup.
Reviewed-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 6f0f9b6b
......@@ -5,3 +5,4 @@ obj-$(CONFIG_CRYPTO_HW) += crypto/
obj-$(CONFIG_S390_HYPFS_FS) += hypfs/
obj-$(CONFIG_APPLDATA_BASE) += appldata/
obj-$(CONFIG_MATHEMU) += math-emu/
obj-y += net/
......@@ -84,6 +84,7 @@ config S390
select HAVE_KERNEL_XZ
select HAVE_ARCH_MUTEX_CPU_RELAX
select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
select HAVE_BPF_JIT if 64BIT && PACK_STACK
select ARCH_SAVE_PAGE_KEYS if HIBERNATION
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
select HAVE_MEMBLOCK
......
......@@ -140,6 +140,7 @@ extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
extern unsigned long thread_saved_pc(struct task_struct *t);
extern void show_code(struct pt_regs *regs);
extern void print_fn_code(unsigned char *code, unsigned long len);
unsigned long get_wchan(struct task_struct *p);
#define task_pt_regs(tsk) ((struct pt_regs *) \
......
......@@ -1601,3 +1601,26 @@ void show_code(struct pt_regs *regs)
}
printk("\n");
}
void print_fn_code(unsigned char *code, unsigned long len)
{
char buffer[64], *ptr;
int opsize, i;
while (len) {
ptr = buffer;
opsize = insn_length(*code);
ptr += sprintf(ptr, "%p: ", code);
for (i = 0; i < opsize; i++)
ptr += sprintf(ptr, "%02x", code[i]);
*ptr++ = '\t';
if (i < 4)
*ptr++ = '\t';
ptr += print_insn(ptr, code, (unsigned long) code);
*ptr++ = '\n';
*ptr++ = 0;
printk(buffer);
code += opsize;
len -= opsize;
}
}
#
# Arch-specific network modules
#
obj-$(CONFIG_BPF_JIT) += bpf_jit.o bpf_jit_comp.o
/*
* BPF Jit compiler for s390, help functions.
*
* Copyright IBM Corp. 2012
*
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
#include <linux/linkage.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
*
* skb_copy_bits takes 4 parameters:
* %r2 = skb pointer
* %r3 = offset into skb data
* %r4 = length to copy
* %r5 = pointer to temp buffer
*/
#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
/* 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
sk_load_word_slow:
lgr %r9,%r2 # save %r2
lhi %r4,4 # 4 bytes
la %r5,160(%r15) # pointer to temp buffer
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
/* 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
lhi %r4,2 # 2 bytes
la %r5,162(%r15) # pointer to temp buffer
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) */
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
sk_load_byte_slow:
lgr %r9,%r2 # save %r2
lhi %r4,1 # 1 bytes
la %r5,163(%r15) # pointer to temp buffer
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
/* A = (*(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_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
sk_load_byte_msh_slow:
lgr %r9,%r2 # save %r2
lhi %r4,2 # 2 bytes
la %r5,162(%r15) # pointer to temp buffer
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
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment