1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * bpf_jit64.h: BPF JIT compiler for PPC64
4 *
5 * Copyright 2016 Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
6 *		  IBM Corporation
7 */
8#ifndef _BPF_JIT64_H
9#define _BPF_JIT64_H
10
11#include "bpf_jit.h"
12
13/*
14 * Stack layout:
15 * Ensure the top half (upto local_tmp_var) stays consistent
16 * with our redzone usage.
17 *
18 *		[	prev sp		] <-------------
19 *		[   nv gpr save area	] 5*8		|
20 *		[    tail_call_cnt	] 8		|
21 *		[    local_tmp_var	] 16		|
22 * fp (r31) -->	[   ebpf stack space	] upto 512	|
23 *		[     frame header	] 32/112	|
24 * sp (r1) --->	[    stack pointer	] --------------
25 */
26
27/* for gpr non volatile registers BPG_REG_6 to 10 */
28#define BPF_PPC_STACK_SAVE	(5*8)
29/* for bpf JIT code internal usage */
30#define BPF_PPC_STACK_LOCALS	24
31/* stack frame excluding BPF stack, ensure this is quadword aligned */
32#define BPF_PPC_STACKFRAME	(STACK_FRAME_MIN_SIZE + \
33				 BPF_PPC_STACK_LOCALS + BPF_PPC_STACK_SAVE)
34
35#ifndef __ASSEMBLY__
36
37/* BPF register usage */
38#define TMP_REG_1	(MAX_BPF_JIT_REG + 0)
39#define TMP_REG_2	(MAX_BPF_JIT_REG + 1)
40
41/* BPF to ppc register mappings */
42static const int b2p[] = {
43	/* function return value */
44	[BPF_REG_0] = 8,
45	/* function arguments */
46	[BPF_REG_1] = 3,
47	[BPF_REG_2] = 4,
48	[BPF_REG_3] = 5,
49	[BPF_REG_4] = 6,
50	[BPF_REG_5] = 7,
51	/* non volatile registers */
52	[BPF_REG_6] = 27,
53	[BPF_REG_7] = 28,
54	[BPF_REG_8] = 29,
55	[BPF_REG_9] = 30,
56	/* frame pointer aka BPF_REG_10 */
57	[BPF_REG_FP] = 31,
58	/* eBPF jit internal registers */
59	[BPF_REG_AX] = 2,
60	[TMP_REG_1] = 9,
61	[TMP_REG_2] = 10
62};
63
64/* PPC NVR range -- update this if we ever use NVRs below r27 */
65#define BPF_PPC_NVR_MIN		27
66
67/*
68 * WARNING: These can use TMP_REG_2 if the offset is not at word boundary,
69 * so ensure that it isn't in use already.
70 */
71#define PPC_BPF_LL(r, base, i) do {					      \
72				if ((i) % 4) {				      \
73					EMIT(PPC_RAW_LI(b2p[TMP_REG_2], (i)));\
74					EMIT(PPC_RAW_LDX(r, base,	      \
75							b2p[TMP_REG_2]));     \
76				} else					      \
77					EMIT(PPC_RAW_LD(r, base, i));	      \
78				} while(0)
79#define PPC_BPF_STL(r, base, i) do {					      \
80				if ((i) % 4) {				      \
81					EMIT(PPC_RAW_LI(b2p[TMP_REG_2], (i)));\
82					EMIT(PPC_RAW_STDX(r, base,	      \
83							b2p[TMP_REG_2]));     \
84				} else					      \
85					EMIT(PPC_RAW_STD(r, base, i));	      \
86				} while(0)
87#define PPC_BPF_STLU(r, base, i) do { EMIT(PPC_RAW_STDU(r, base, i)); } while(0)
88
89#define SEEN_FUNC	0x1000 /* might call external helpers */
90#define SEEN_STACK	0x2000 /* uses BPF stack */
91#define SEEN_TAILCALL	0x4000 /* uses tail calls */
92
93struct codegen_context {
94	/*
95	 * This is used to track register usage as well
96	 * as calls to external helpers.
97	 * - register usage is tracked with corresponding
98	 *   bits (r3-r10 and r27-r31)
99	 * - rest of the bits can be used to track other
100	 *   things -- for now, we use bits 16 to 23
101	 *   encoded in SEEN_* macros above
102	 */
103	unsigned int seen;
104	unsigned int idx;
105	unsigned int stack_size;
106};
107
108#endif /* !__ASSEMBLY__ */
109
110#endif
111