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