1 /* 2 * bpf_jit32.h: BPF JIT compiler for PPC 3 * 4 * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation 5 * 6 * Split from bpf_jit.h 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * as published by the Free Software Foundation; version 2 11 * of the License. 12 */ 13 #ifndef _BPF_JIT32_H 14 #define _BPF_JIT32_H 15 16 #include "bpf_jit.h" 17 18 #ifdef CONFIG_PPC64 19 #define BPF_PPC_STACK_R3_OFF 48 20 #define BPF_PPC_STACK_LOCALS 32 21 #define BPF_PPC_STACK_BASIC (48+64) 22 #define BPF_PPC_STACK_SAVE (18*8) 23 #define BPF_PPC_STACKFRAME (BPF_PPC_STACK_BASIC+BPF_PPC_STACK_LOCALS+ \ 24 BPF_PPC_STACK_SAVE) 25 #define BPF_PPC_SLOWPATH_FRAME (48+64) 26 #else 27 #define BPF_PPC_STACK_R3_OFF 24 28 #define BPF_PPC_STACK_LOCALS 16 29 #define BPF_PPC_STACK_BASIC (24+32) 30 #define BPF_PPC_STACK_SAVE (18*4) 31 #define BPF_PPC_STACKFRAME (BPF_PPC_STACK_BASIC+BPF_PPC_STACK_LOCALS+ \ 32 BPF_PPC_STACK_SAVE) 33 #define BPF_PPC_SLOWPATH_FRAME (24+32) 34 #endif 35 36 #define REG_SZ (BITS_PER_LONG/8) 37 38 /* 39 * Generated code register usage: 40 * 41 * As normal PPC C ABI (e.g. r1=sp, r2=TOC), with: 42 * 43 * skb r3 (Entry parameter) 44 * A register r4 45 * X register r5 46 * addr param r6 47 * r7-r10 scratch 48 * skb->data r14 49 * skb headlen r15 (skb->len - skb->data_len) 50 * m[0] r16 51 * m[...] ... 52 * m[15] r31 53 */ 54 #define r_skb 3 55 #define r_ret 3 56 #define r_A 4 57 #define r_X 5 58 #define r_addr 6 59 #define r_scratch1 7 60 #define r_scratch2 8 61 #define r_D 14 62 #define r_HL 15 63 #define r_M 16 64 65 #ifndef __ASSEMBLY__ 66 67 /* 68 * Assembly helpers from arch/powerpc/net/bpf_jit.S: 69 */ 70 #define DECLARE_LOAD_FUNC(func) \ 71 extern u8 func[], func##_negative_offset[], func##_positive_offset[] 72 73 DECLARE_LOAD_FUNC(sk_load_word); 74 DECLARE_LOAD_FUNC(sk_load_half); 75 DECLARE_LOAD_FUNC(sk_load_byte); 76 DECLARE_LOAD_FUNC(sk_load_byte_msh); 77 78 #define PPC_LBZ_OFFS(r, base, i) do { if ((i) < 32768) PPC_LBZ(r, base, i); \ 79 else { PPC_ADDIS(r, base, IMM_HA(i)); \ 80 PPC_LBZ(r, r, IMM_L(i)); } } while(0) 81 82 #define PPC_LD_OFFS(r, base, i) do { if ((i) < 32768) PPC_LD(r, base, i); \ 83 else { PPC_ADDIS(r, base, IMM_HA(i)); \ 84 PPC_LD(r, r, IMM_L(i)); } } while(0) 85 86 #define PPC_LWZ_OFFS(r, base, i) do { if ((i) < 32768) PPC_LWZ(r, base, i); \ 87 else { PPC_ADDIS(r, base, IMM_HA(i)); \ 88 PPC_LWZ(r, r, IMM_L(i)); } } while(0) 89 90 #define PPC_LHZ_OFFS(r, base, i) do { if ((i) < 32768) PPC_LHZ(r, base, i); \ 91 else { PPC_ADDIS(r, base, IMM_HA(i)); \ 92 PPC_LHZ(r, r, IMM_L(i)); } } while(0) 93 94 #ifdef CONFIG_PPC64 95 #define PPC_LL_OFFS(r, base, i) do { PPC_LD_OFFS(r, base, i); } while(0) 96 #else 97 #define PPC_LL_OFFS(r, base, i) do { PPC_LWZ_OFFS(r, base, i); } while(0) 98 #endif 99 100 #ifdef CONFIG_SMP 101 #ifdef CONFIG_PPC64 102 #define PPC_BPF_LOAD_CPU(r) \ 103 do { BUILD_BUG_ON(FIELD_SIZEOF(struct paca_struct, paca_index) != 2); \ 104 PPC_LHZ_OFFS(r, 13, offsetof(struct paca_struct, paca_index)); \ 105 } while (0) 106 #else 107 #define PPC_BPF_LOAD_CPU(r) \ 108 do { BUILD_BUG_ON(FIELD_SIZEOF(struct thread_info, cpu) != 4); \ 109 PPC_LHZ_OFFS(r, (1 & ~(THREAD_SIZE - 1)), \ 110 offsetof(struct thread_info, cpu)); \ 111 } while(0) 112 #endif 113 #else 114 #define PPC_BPF_LOAD_CPU(r) do { PPC_LI(r, 0); } while(0) 115 #endif 116 117 #define PPC_LHBRX_OFFS(r, base, i) \ 118 do { PPC_LI32(r, i); PPC_LHBRX(r, r, base); } while(0) 119 #ifdef __LITTLE_ENDIAN__ 120 #define PPC_NTOHS_OFFS(r, base, i) PPC_LHBRX_OFFS(r, base, i) 121 #else 122 #define PPC_NTOHS_OFFS(r, base, i) PPC_LHZ_OFFS(r, base, i) 123 #endif 124 125 #define PPC_BPF_LL(r, base, i) do { PPC_LWZ(r, base, i); } while(0) 126 #define PPC_BPF_STL(r, base, i) do { PPC_STW(r, base, i); } while(0) 127 #define PPC_BPF_STLU(r, base, i) do { PPC_STWU(r, base, i); } while(0) 128 129 #define SEEN_DATAREF 0x10000 /* might call external helpers */ 130 #define SEEN_XREG 0x20000 /* X reg is used */ 131 #define SEEN_MEM 0x40000 /* SEEN_MEM+(1<<n) = use mem[n] for temporary 132 * storage */ 133 #define SEEN_MEM_MSK 0x0ffff 134 135 struct codegen_context { 136 unsigned int seen; 137 unsigned int idx; 138 int pc_ret0; /* bpf index of first RET #0 instruction (if any) */ 139 }; 140 141 #endif 142 143 #endif 144