1 /* bpf_jit.S: Packet/header access helper functions
2 * for PPC64 BPF compiler.
4 * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; version 2
12 #include <asm/ppc_asm.h>
16 * All of these routines are called directly from generated code,
17 * whose register usage is:
21 * r6 *** address parameter to helper ***
29 * To consider: These helpers are so small it could be better to just
30 * generate them inline. Inline code can do the simple headlen check
31 * then branch directly to slow_path_XXX if required. (In fact, could
32 * load a spare GPR with the address of slow_path_generic and pass size
33 * as an argument, making the call site a mtlr, li and bllr.)
35 * Technically, the "is addr < 0" check is unnecessary & slowing down
36 * the ABS path, as it's statically checked on generation.
42 /* Are we accessing past headlen? */
43 subi r_scratch1, r_HL, 4
44 cmpd r_scratch1, r_addr
45 blt bpf_slow_path_word
46 /* Nope, just hitting the header. cr0 here is eq or gt! */
48 /* When big endian we don't need to byteswap. */
49 blr /* Return success, cr0 != LT */
55 subi r_scratch1, r_HL, 2
56 cmpd r_scratch1, r_addr
57 blt bpf_slow_path_half
66 ble bpf_slow_path_byte
71 * BPF_S_LDX_B_MSH: ldxb 4*([offset]&0xf)
72 * r_addr is the offset value, already known positive
74 .globl sk_load_byte_msh
77 ble bpf_slow_path_byte_msh
79 rlwinm r_X, r_X, 2, 32-4-2, 31-2
83 /* Entered with cr0 = lt */
85 /* Generated code will 'blt epilogue', returning 0. */
88 /* Call out to skb_copy_bits:
89 * We'll need to back up our volatile regs first; we have
90 * local variable space at r1+(BPF_PPC_STACK_BASIC).
91 * Allocate a new stack frame here to remain ABI-compliant in
94 #define bpf_slow_path_common(SIZE) \
97 /* R3 goes in parameter space of caller's frame */ \
98 std r_skb, (BPF_PPC_STACKFRAME+48)(r1); \
99 std r_A, (BPF_PPC_STACK_BASIC+(0*8))(r1); \
100 std r_X, (BPF_PPC_STACK_BASIC+(1*8))(r1); \
101 addi r5, r1, BPF_PPC_STACK_BASIC+(2*8); \
102 stdu r1, -BPF_PPC_SLOWPATH_FRAME(r1); \
103 /* R3 = r_skb, as passed */ \
107 /* R3 = 0 on success */ \
108 addi r1, r1, BPF_PPC_SLOWPATH_FRAME; \
110 ld r_A, (BPF_PPC_STACK_BASIC+(0*8))(r1); \
111 ld r_X, (BPF_PPC_STACK_BASIC+(1*8))(r1); \
114 blt bpf_error; /* cr0 = LT */ \
115 ld r_skb, (BPF_PPC_STACKFRAME+48)(r1); \
119 bpf_slow_path_common(4)
120 /* Data value is on stack, and cr0 != LT */
121 lwz r_A, BPF_PPC_STACK_BASIC+(2*8)(r1)
125 bpf_slow_path_common(2)
126 lhz r_A, BPF_PPC_STACK_BASIC+(2*8)(r1)
130 bpf_slow_path_common(1)
131 lbz r_A, BPF_PPC_STACK_BASIC+(2*8)(r1)
134 bpf_slow_path_byte_msh:
135 bpf_slow_path_common(1)
136 lbz r_X, BPF_PPC_STACK_BASIC+(2*8)(r1)
137 rlwinm r_X, r_X, 2, 32-4-2, 31-2