18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * bpf_jit32.h: BPF JIT compiler for PPC 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Split from bpf_jit.h 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#ifndef _BPF_JIT32_H 108c2ecf20Sopenharmony_ci#define _BPF_JIT32_H 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <asm/asm-compat.h> 138c2ecf20Sopenharmony_ci#include "bpf_jit.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC64 168c2ecf20Sopenharmony_ci#define BPF_PPC_STACK_R3_OFF 48 178c2ecf20Sopenharmony_ci#define BPF_PPC_STACK_LOCALS 32 188c2ecf20Sopenharmony_ci#define BPF_PPC_STACK_BASIC (48+64) 198c2ecf20Sopenharmony_ci#define BPF_PPC_STACK_SAVE (18*8) 208c2ecf20Sopenharmony_ci#define BPF_PPC_STACKFRAME (BPF_PPC_STACK_BASIC+BPF_PPC_STACK_LOCALS+ \ 218c2ecf20Sopenharmony_ci BPF_PPC_STACK_SAVE) 228c2ecf20Sopenharmony_ci#define BPF_PPC_SLOWPATH_FRAME (48+64) 238c2ecf20Sopenharmony_ci#else 248c2ecf20Sopenharmony_ci#define BPF_PPC_STACK_R3_OFF 24 258c2ecf20Sopenharmony_ci#define BPF_PPC_STACK_LOCALS 16 268c2ecf20Sopenharmony_ci#define BPF_PPC_STACK_BASIC (24+32) 278c2ecf20Sopenharmony_ci#define BPF_PPC_STACK_SAVE (18*4) 288c2ecf20Sopenharmony_ci#define BPF_PPC_STACKFRAME (BPF_PPC_STACK_BASIC+BPF_PPC_STACK_LOCALS+ \ 298c2ecf20Sopenharmony_ci BPF_PPC_STACK_SAVE) 308c2ecf20Sopenharmony_ci#define BPF_PPC_SLOWPATH_FRAME (24+32) 318c2ecf20Sopenharmony_ci#endif 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#define REG_SZ (BITS_PER_LONG/8) 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci/* 368c2ecf20Sopenharmony_ci * Generated code register usage: 378c2ecf20Sopenharmony_ci * 388c2ecf20Sopenharmony_ci * As normal PPC C ABI (e.g. r1=sp, r2=TOC), with: 398c2ecf20Sopenharmony_ci * 408c2ecf20Sopenharmony_ci * skb r3 (Entry parameter) 418c2ecf20Sopenharmony_ci * A register r4 428c2ecf20Sopenharmony_ci * X register r5 438c2ecf20Sopenharmony_ci * addr param r6 448c2ecf20Sopenharmony_ci * r7-r10 scratch 458c2ecf20Sopenharmony_ci * skb->data r14 468c2ecf20Sopenharmony_ci * skb headlen r15 (skb->len - skb->data_len) 478c2ecf20Sopenharmony_ci * m[0] r16 488c2ecf20Sopenharmony_ci * m[...] ... 498c2ecf20Sopenharmony_ci * m[15] r31 508c2ecf20Sopenharmony_ci */ 518c2ecf20Sopenharmony_ci#define r_skb 3 528c2ecf20Sopenharmony_ci#define r_ret 3 538c2ecf20Sopenharmony_ci#define r_A 4 548c2ecf20Sopenharmony_ci#define r_X 5 558c2ecf20Sopenharmony_ci#define r_addr 6 568c2ecf20Sopenharmony_ci#define r_scratch1 7 578c2ecf20Sopenharmony_ci#define r_scratch2 8 588c2ecf20Sopenharmony_ci#define r_D 14 598c2ecf20Sopenharmony_ci#define r_HL 15 608c2ecf20Sopenharmony_ci#define r_M 16 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci/* 658c2ecf20Sopenharmony_ci * Assembly helpers from arch/powerpc/net/bpf_jit.S: 668c2ecf20Sopenharmony_ci */ 678c2ecf20Sopenharmony_ci#define DECLARE_LOAD_FUNC(func) \ 688c2ecf20Sopenharmony_ci extern u8 func[], func##_negative_offset[], func##_positive_offset[] 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ciDECLARE_LOAD_FUNC(sk_load_word); 718c2ecf20Sopenharmony_ciDECLARE_LOAD_FUNC(sk_load_half); 728c2ecf20Sopenharmony_ciDECLARE_LOAD_FUNC(sk_load_byte); 738c2ecf20Sopenharmony_ciDECLARE_LOAD_FUNC(sk_load_byte_msh); 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci#define PPC_LBZ_OFFS(r, base, i) do { if ((i) < 32768) EMIT(PPC_RAW_LBZ(r, base, i)); \ 768c2ecf20Sopenharmony_ci else { EMIT(PPC_RAW_ADDIS(r, base, IMM_HA(i))); \ 778c2ecf20Sopenharmony_ci EMIT(PPC_RAW_LBZ(r, r, IMM_L(i))); } } while(0) 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci#define PPC_LD_OFFS(r, base, i) do { if ((i) < 32768) EMIT(PPC_RAW_LD(r, base, i)); \ 808c2ecf20Sopenharmony_ci else { EMIT(PPC_RAW_ADDIS(r, base, IMM_HA(i))); \ 818c2ecf20Sopenharmony_ci EMIT(PPC_RAW_LD(r, r, IMM_L(i))); } } while(0) 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci#define PPC_LWZ_OFFS(r, base, i) do { if ((i) < 32768) EMIT(PPC_RAW_LWZ(r, base, i)); \ 848c2ecf20Sopenharmony_ci else { EMIT(PPC_RAW_ADDIS(r, base, IMM_HA(i))); \ 858c2ecf20Sopenharmony_ci EMIT(PPC_RAW_LWZ(r, r, IMM_L(i))); } } while(0) 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci#define PPC_LHZ_OFFS(r, base, i) do { if ((i) < 32768) EMIT(PPC_RAW_LHZ(r, base, i)); \ 888c2ecf20Sopenharmony_ci else { EMIT(PPC_RAW_ADDIS(r, base, IMM_HA(i))); \ 898c2ecf20Sopenharmony_ci EMIT(PPC_RAW_LHZ(r, r, IMM_L(i))); } } while(0) 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC64 928c2ecf20Sopenharmony_ci#define PPC_LL_OFFS(r, base, i) do { PPC_LD_OFFS(r, base, i); } while(0) 938c2ecf20Sopenharmony_ci#else 948c2ecf20Sopenharmony_ci#define PPC_LL_OFFS(r, base, i) do { PPC_LWZ_OFFS(r, base, i); } while(0) 958c2ecf20Sopenharmony_ci#endif 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 988c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC64 998c2ecf20Sopenharmony_ci#define PPC_BPF_LOAD_CPU(r) \ 1008c2ecf20Sopenharmony_ci do { BUILD_BUG_ON(sizeof_field(struct paca_struct, paca_index) != 2); \ 1018c2ecf20Sopenharmony_ci PPC_LHZ_OFFS(r, 13, offsetof(struct paca_struct, paca_index)); \ 1028c2ecf20Sopenharmony_ci } while (0) 1038c2ecf20Sopenharmony_ci#else 1048c2ecf20Sopenharmony_ci#define PPC_BPF_LOAD_CPU(r) \ 1058c2ecf20Sopenharmony_ci do { BUILD_BUG_ON(sizeof_field(struct task_struct, cpu) != 4); \ 1068c2ecf20Sopenharmony_ci PPC_LHZ_OFFS(r, 2, offsetof(struct task_struct, cpu)); \ 1078c2ecf20Sopenharmony_ci } while(0) 1088c2ecf20Sopenharmony_ci#endif 1098c2ecf20Sopenharmony_ci#else 1108c2ecf20Sopenharmony_ci#define PPC_BPF_LOAD_CPU(r) do { EMIT(PPC_RAW_LI(r, 0)); } while(0) 1118c2ecf20Sopenharmony_ci#endif 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci#define PPC_LHBRX_OFFS(r, base, i) \ 1148c2ecf20Sopenharmony_ci do { PPC_LI32(r, i); EMIT(PPC_RAW_LHBRX(r, r, base)); } while(0) 1158c2ecf20Sopenharmony_ci#ifdef __LITTLE_ENDIAN__ 1168c2ecf20Sopenharmony_ci#define PPC_NTOHS_OFFS(r, base, i) PPC_LHBRX_OFFS(r, base, i) 1178c2ecf20Sopenharmony_ci#else 1188c2ecf20Sopenharmony_ci#define PPC_NTOHS_OFFS(r, base, i) PPC_LHZ_OFFS(r, base, i) 1198c2ecf20Sopenharmony_ci#endif 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci#define PPC_BPF_LL(r, base, i) do { EMIT(PPC_RAW_LWZ(r, base, i)); } while(0) 1228c2ecf20Sopenharmony_ci#define PPC_BPF_STL(r, base, i) do { EMIT(PPC_RAW_STW(r, base, i)); } while(0) 1238c2ecf20Sopenharmony_ci#define PPC_BPF_STLU(r, base, i) do { EMIT(PPC_RAW_STWU(r, base, i)); } while(0) 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci#define SEEN_DATAREF 0x10000 /* might call external helpers */ 1268c2ecf20Sopenharmony_ci#define SEEN_XREG 0x20000 /* X reg is used */ 1278c2ecf20Sopenharmony_ci#define SEEN_MEM 0x40000 /* SEEN_MEM+(1<<n) = use mem[n] for temporary 1288c2ecf20Sopenharmony_ci * storage */ 1298c2ecf20Sopenharmony_ci#define SEEN_MEM_MSK 0x0ffff 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistruct codegen_context { 1328c2ecf20Sopenharmony_ci unsigned int seen; 1338c2ecf20Sopenharmony_ci unsigned int idx; 1348c2ecf20Sopenharmony_ci int pc_ret0; /* bpf index of first RET #0 instruction (if any) */ 1358c2ecf20Sopenharmony_ci}; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci#endif 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci#endif 140