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