File: bpf_asm.h

package info (click to toggle)
dtrace 2.0.5-1
  • links: PTS
  • area: main
  • in suites: sid
  • size: 24,408 kB
  • sloc: ansic: 61,247; sh: 17,997; asm: 1,717; lex: 947; awk: 754; yacc: 695; perl: 37; sed: 17; makefile: 15
file content (199 lines) | stat: -rw-r--r-- 4,921 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/*
 * Oracle Linux DTrace.
 * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * http://oss.oracle.com/licenses/upl.
 */

#ifndef BPF_ASM_H
#define BPF_ASM_H

#include <linux/bpf.h>

#ifndef BPF_JMP32
# define BPF_JMP32	0x06
#endif
#define BPF_REG_FP	BPF_REG_10

/*
 * The maximum stack size for BPF programs is defined in the kernel headers and
 * is not generally available outside of the kernel source tree.  We define it
 * here because we depend on it in the layout of the DTrace BPF program stack.
 * If the kernel supports a larger stack, we end up not taking advantage of it.
 * If the kernel supports a smaller stack, we may end up generating programs
 * that the BPF verifier will reject.
 */
#ifndef MAX_BPF_STACK
# define MAX_BPF_STACK	512
#endif

#define BPF_ALU64_REG(op, dst, src)					\
	((struct bpf_insn) {						\
		.code = BPF_ALU64 | (op) | BPF_X,			\
		.dst_reg = (dst),					\
		.src_reg = (src),					\
		.off = 0,						\
		.imm = 0						\
	})

#define BPF_ALU32_REG(op, dst, src)					\
	((struct bpf_insn) {						\
		.code = BPF_ALU | (op) | BPF_X,				\
		.dst_reg = (dst),					\
		.src_reg = (src),					\
		.off = 0,						\
		.imm = 0						\
	})

#define BPF_END_REG(sz, dst, dir)					\
	((struct bpf_insn) {						\
		.code = BPF_ALU | BPF_END | (dir),			\
		.dst_reg = (dst),					\
		.src_reg = 0,						\
		.off = 0,						\
		.imm = (sz) == BPF_DW ? 64 :				\
		       (sz) == BPF_W ? 32 :				\
		       (sz) == BPF_H ? 16 : 0				\
	})

#define BPF_NEG_REG(dst)						\
	((struct bpf_insn) {						\
		.code = BPF_ALU64 | BPF_NEG,				\
		.dst_reg = (dst),					\
		.src_reg = 0,						\
		.off = 0,						\
		.imm = 0						\
	})

#define BPF_ALU64_IMM(op, dst, val)					\
	((struct bpf_insn) {						\
		.code = BPF_ALU64 | (op) | BPF_K,			\
		.dst_reg = (dst),					\
		.src_reg = 0,						\
		.off = 0,						\
		.imm = (val)						\
	})

#define BPF_MOV_REG(dst, src)	BPF_ALU64_REG(BPF_MOV, dst, src)
#define BPF_MOV_IMM(dst, val)	BPF_ALU64_IMM(BPF_MOV, dst, val)

#define BPF_MOV32_REG(dst, src)	BPF_ALU32_REG(BPF_MOV, dst, src)

#define BPF_LOAD(sz, dst, src, ofs)					\
	((struct bpf_insn) {						\
		.code = BPF_LDX | BPF_MEM | (sz),			\
		.dst_reg = (dst),					\
		.src_reg = (src),					\
		.off = (ofs),						\
		.imm = 0						\
	})

#define BPF_LDDW(dst, val)						\
	((struct bpf_insn) {						\
		.code = BPF_LD | BPF_IMM | BPF_DW,			\
		.dst_reg = (dst),					\
		.src_reg = 0,						\
		.off = 0,						\
		.imm = (uint32_t)(val)					\
	}),								\
	((struct bpf_insn) {						\
		.code = 0,						\
		.dst_reg = 0,						\
		.src_reg = 0,						\
		.off = 0,						\
		.imm = (uint32_t)((uint64_t)(val) >> 32)		\
	})

#define BPF_STORE(sz, dst, ofs, src)					\
	((struct bpf_insn) {						\
		.code = BPF_STX | BPF_MEM | (sz),			\
		.dst_reg = (dst),					\
		.src_reg = (src),					\
		.off = (ofs),						\
		.imm = 0						\
	})

#define BPF_XADD_REG(sz, dst, ofs, src)					\
	((struct bpf_insn) {						\
		.code = BPF_STX | BPF_XADD | (sz),			\
		.dst_reg = (dst),					\
		.src_reg = (src),					\
		.off = (ofs),						\
		.imm = 0						\
	})

#define BPF_STORE_IMM(sz, dst, ofs, val)				\
	((struct bpf_insn) {						\
		.code = BPF_ST | BPF_MEM | (sz),			\
		.dst_reg = (dst),					\
		.src_reg = 0,						\
		.off = (ofs),						\
		.imm = (val)						\
	})

#define BPF_CALL_HELPER(id)						\
	((struct bpf_insn) {						\
		.code = BPF_JMP | BPF_CALL,				\
		.dst_reg = 0,						\
		.src_reg = 0,						\
		.off = 0,						\
		.imm = (id)						\
	})

#define BPF_CALL_FUNC(val)						\
	((struct bpf_insn) {						\
		.code = BPF_JMP | BPF_CALL,				\
		.dst_reg = 0,						\
		.src_reg = BPF_PSEUDO_CALL,				\
		.off = 0,						\
		.imm = (val)						\
	})

#define BPF_RETURN()							\
	((struct bpf_insn) {						\
		.code = BPF_JMP | BPF_EXIT,				\
		.dst_reg = 0,						\
		.src_reg = 0,						\
		.off = 0,						\
		.imm = 0						\
	})

#define BPF_BRANCH_REG(op, r1, r2, ofs)					\
	((struct bpf_insn) {						\
		.code = BPF_JMP | (op) | BPF_X,				\
		.dst_reg = (r1),					\
		.src_reg = (r2),					\
		.off = (ofs),						\
		.imm = 0						\
	})

#define BPF_BRANCH_IMM(op, r1, val, ofs)				\
	((struct bpf_insn) {						\
		.code = BPF_JMP | (op) | BPF_K,				\
		.dst_reg = (r1),					\
		.src_reg = 0,						\
		.off = (ofs),						\
		.imm = (val)						\
	})

#define BPF_JUMP(ofs)							\
	((struct bpf_insn) {						\
		.code = BPF_JMP | BPF_JA,				\
		.dst_reg = 0,						\
		.src_reg = 0,						\
		.off = (ofs),						\
		.imm = 0						\
	})

#define BPF_NOP()	BPF_JUMP(0)

#define BPF_IS_CALL(x)	((x).code == (BPF_JMP | BPF_CALL))
#define BPF_IS_NOP(x)	((x).code == (BPF_JMP | BPF_JA) && (x).off == 0)

#define BPF_EQUAL(x, y)	((x).code == (y).code &&			\
			 (x).dst_reg == (y).dst_reg &&			\
			 (x).src_reg == (y).src_reg &&			\
			 (x).off == (y).off &&				\
			 (x).imm == (y).imm)

#endif /* BPF_ASM_H */