18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * bpf_jit64.h: BPF JIT compiler for PPC64 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2016 Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> 68c2ecf20Sopenharmony_ci * IBM Corporation 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci#ifndef _BPF_JIT64_H 98c2ecf20Sopenharmony_ci#define _BPF_JIT64_H 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include "bpf_jit.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* 148c2ecf20Sopenharmony_ci * Stack layout: 158c2ecf20Sopenharmony_ci * Ensure the top half (upto local_tmp_var) stays consistent 168c2ecf20Sopenharmony_ci * with our redzone usage. 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * [ prev sp ] <------------- 198c2ecf20Sopenharmony_ci * [ nv gpr save area ] 5*8 | 208c2ecf20Sopenharmony_ci * [ tail_call_cnt ] 8 | 218c2ecf20Sopenharmony_ci * [ local_tmp_var ] 16 | 228c2ecf20Sopenharmony_ci * fp (r31) --> [ ebpf stack space ] upto 512 | 238c2ecf20Sopenharmony_ci * [ frame header ] 32/112 | 248c2ecf20Sopenharmony_ci * sp (r1) ---> [ stack pointer ] -------------- 258c2ecf20Sopenharmony_ci */ 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/* for gpr non volatile registers BPG_REG_6 to 10 */ 288c2ecf20Sopenharmony_ci#define BPF_PPC_STACK_SAVE (5*8) 298c2ecf20Sopenharmony_ci/* for bpf JIT code internal usage */ 308c2ecf20Sopenharmony_ci#define BPF_PPC_STACK_LOCALS 24 318c2ecf20Sopenharmony_ci/* stack frame excluding BPF stack, ensure this is quadword aligned */ 328c2ecf20Sopenharmony_ci#define BPF_PPC_STACKFRAME (STACK_FRAME_MIN_SIZE + \ 338c2ecf20Sopenharmony_ci BPF_PPC_STACK_LOCALS + BPF_PPC_STACK_SAVE) 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci/* BPF register usage */ 388c2ecf20Sopenharmony_ci#define TMP_REG_1 (MAX_BPF_JIT_REG + 0) 398c2ecf20Sopenharmony_ci#define TMP_REG_2 (MAX_BPF_JIT_REG + 1) 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/* BPF to ppc register mappings */ 428c2ecf20Sopenharmony_cistatic const int b2p[] = { 438c2ecf20Sopenharmony_ci /* function return value */ 448c2ecf20Sopenharmony_ci [BPF_REG_0] = 8, 458c2ecf20Sopenharmony_ci /* function arguments */ 468c2ecf20Sopenharmony_ci [BPF_REG_1] = 3, 478c2ecf20Sopenharmony_ci [BPF_REG_2] = 4, 488c2ecf20Sopenharmony_ci [BPF_REG_3] = 5, 498c2ecf20Sopenharmony_ci [BPF_REG_4] = 6, 508c2ecf20Sopenharmony_ci [BPF_REG_5] = 7, 518c2ecf20Sopenharmony_ci /* non volatile registers */ 528c2ecf20Sopenharmony_ci [BPF_REG_6] = 27, 538c2ecf20Sopenharmony_ci [BPF_REG_7] = 28, 548c2ecf20Sopenharmony_ci [BPF_REG_8] = 29, 558c2ecf20Sopenharmony_ci [BPF_REG_9] = 30, 568c2ecf20Sopenharmony_ci /* frame pointer aka BPF_REG_10 */ 578c2ecf20Sopenharmony_ci [BPF_REG_FP] = 31, 588c2ecf20Sopenharmony_ci /* eBPF jit internal registers */ 598c2ecf20Sopenharmony_ci [BPF_REG_AX] = 2, 608c2ecf20Sopenharmony_ci [TMP_REG_1] = 9, 618c2ecf20Sopenharmony_ci [TMP_REG_2] = 10 628c2ecf20Sopenharmony_ci}; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci/* PPC NVR range -- update this if we ever use NVRs below r27 */ 658c2ecf20Sopenharmony_ci#define BPF_PPC_NVR_MIN 27 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci/* 688c2ecf20Sopenharmony_ci * WARNING: These can use TMP_REG_2 if the offset is not at word boundary, 698c2ecf20Sopenharmony_ci * so ensure that it isn't in use already. 708c2ecf20Sopenharmony_ci */ 718c2ecf20Sopenharmony_ci#define PPC_BPF_LL(r, base, i) do { \ 728c2ecf20Sopenharmony_ci if ((i) % 4) { \ 738c2ecf20Sopenharmony_ci EMIT(PPC_RAW_LI(b2p[TMP_REG_2], (i)));\ 748c2ecf20Sopenharmony_ci EMIT(PPC_RAW_LDX(r, base, \ 758c2ecf20Sopenharmony_ci b2p[TMP_REG_2])); \ 768c2ecf20Sopenharmony_ci } else \ 778c2ecf20Sopenharmony_ci EMIT(PPC_RAW_LD(r, base, i)); \ 788c2ecf20Sopenharmony_ci } while(0) 798c2ecf20Sopenharmony_ci#define PPC_BPF_STL(r, base, i) do { \ 808c2ecf20Sopenharmony_ci if ((i) % 4) { \ 818c2ecf20Sopenharmony_ci EMIT(PPC_RAW_LI(b2p[TMP_REG_2], (i)));\ 828c2ecf20Sopenharmony_ci EMIT(PPC_RAW_STDX(r, base, \ 838c2ecf20Sopenharmony_ci b2p[TMP_REG_2])); \ 848c2ecf20Sopenharmony_ci } else \ 858c2ecf20Sopenharmony_ci EMIT(PPC_RAW_STD(r, base, i)); \ 868c2ecf20Sopenharmony_ci } while(0) 878c2ecf20Sopenharmony_ci#define PPC_BPF_STLU(r, base, i) do { EMIT(PPC_RAW_STDU(r, base, i)); } while(0) 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci#define SEEN_FUNC 0x1000 /* might call external helpers */ 908c2ecf20Sopenharmony_ci#define SEEN_STACK 0x2000 /* uses BPF stack */ 918c2ecf20Sopenharmony_ci#define SEEN_TAILCALL 0x4000 /* uses tail calls */ 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistruct codegen_context { 948c2ecf20Sopenharmony_ci /* 958c2ecf20Sopenharmony_ci * This is used to track register usage as well 968c2ecf20Sopenharmony_ci * as calls to external helpers. 978c2ecf20Sopenharmony_ci * - register usage is tracked with corresponding 988c2ecf20Sopenharmony_ci * bits (r3-r10 and r27-r31) 998c2ecf20Sopenharmony_ci * - rest of the bits can be used to track other 1008c2ecf20Sopenharmony_ci * things -- for now, we use bits 16 to 23 1018c2ecf20Sopenharmony_ci * encoded in SEEN_* macros above 1028c2ecf20Sopenharmony_ci */ 1038c2ecf20Sopenharmony_ci unsigned int seen; 1048c2ecf20Sopenharmony_ci unsigned int idx; 1058c2ecf20Sopenharmony_ci unsigned int stack_size; 1068c2ecf20Sopenharmony_ci}; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci#endif /* !__ASSEMBLY__ */ 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci#endif 111