Skip to content

Commit 9053ba0

Browse files
iii-iAlexei Starovoitov
authored andcommitted
s390/bpf: Add macros for calling external functions
After the V!=R rework (commit c98d2ec ("s390/mm: Uncouple physical vs virtual address spaces")), kernel and BPF programs are allocated within a 4G region, making it possible to use relative addressing to directly use kernel functions from BPF code. Add two new macros for calling kernel functions from BPF code: EMIT6_PCREL_RILB_PTR() and EMIT6_PCREL_RILC_PTR(). Factor out parts of the existing macros that are helpful for implementing the new ones. Signed-off-by: Ilya Leoshkevich <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent f756200 commit 9053ba0

File tree

1 file changed

+42
-18
lines changed

1 file changed

+42
-18
lines changed

arch/s390/net/bpf_jit_comp.c

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,18 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
127127
jit->seen_regs |= (1 << r1);
128128
}
129129

130+
static s32 off_to_pcrel(struct bpf_jit *jit, u32 off)
131+
{
132+
return off - jit->prg;
133+
}
134+
135+
static s64 ptr_to_pcrel(struct bpf_jit *jit, const void *ptr)
136+
{
137+
if (jit->prg_buf)
138+
return (const u8 *)ptr - ((const u8 *)jit->prg_buf + jit->prg);
139+
return 0;
140+
}
141+
130142
#define REG_SET_SEEN(b1) \
131143
({ \
132144
reg_set_seen(jit, b1); \
@@ -201,7 +213,7 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
201213

202214
#define EMIT4_PCREL_RIC(op, mask, target) \
203215
({ \
204-
int __rel = ((target) - jit->prg) / 2; \
216+
int __rel = off_to_pcrel(jit, target) / 2; \
205217
_EMIT4((op) | (mask) << 20 | (__rel & 0xffff)); \
206218
})
207219

@@ -239,7 +251,7 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
239251

240252
#define EMIT6_PCREL_RIEB(op1, op2, b1, b2, mask, target) \
241253
({ \
242-
unsigned int rel = (int)((target) - jit->prg) / 2; \
254+
unsigned int rel = off_to_pcrel(jit, target) / 2; \
243255
_EMIT6((op1) | reg(b1, b2) << 16 | (rel & 0xffff), \
244256
(op2) | (mask) << 12); \
245257
REG_SET_SEEN(b1); \
@@ -248,7 +260,7 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
248260

249261
#define EMIT6_PCREL_RIEC(op1, op2, b1, imm, mask, target) \
250262
({ \
251-
unsigned int rel = (int)((target) - jit->prg) / 2; \
263+
unsigned int rel = off_to_pcrel(jit, target) / 2; \
252264
_EMIT6((op1) | (reg_high(b1) | (mask)) << 16 | \
253265
(rel & 0xffff), (op2) | ((imm) & 0xff) << 8); \
254266
REG_SET_SEEN(b1); \
@@ -257,29 +269,41 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
257269

258270
#define EMIT6_PCREL(op1, op2, b1, b2, i, off, mask) \
259271
({ \
260-
int rel = (addrs[(i) + (off) + 1] - jit->prg) / 2; \
272+
int rel = off_to_pcrel(jit, addrs[(i) + (off) + 1]) / 2;\
261273
_EMIT6((op1) | reg(b1, b2) << 16 | (rel & 0xffff), (op2) | (mask));\
262274
REG_SET_SEEN(b1); \
263275
REG_SET_SEEN(b2); \
264276
})
265277

278+
static void emit6_pcrel_ril(struct bpf_jit *jit, u32 op, s64 pcrel)
279+
{
280+
u32 pc32dbl = (s32)(pcrel / 2);
281+
282+
_EMIT6(op | pc32dbl >> 16, pc32dbl & 0xffff);
283+
}
284+
285+
static void emit6_pcrel_rilb(struct bpf_jit *jit, u32 op, u8 b, s64 pcrel)
286+
{
287+
emit6_pcrel_ril(jit, op | reg_high(b) << 16, pcrel);
288+
REG_SET_SEEN(b);
289+
}
290+
266291
#define EMIT6_PCREL_RILB(op, b, target) \
267-
({ \
268-
unsigned int rel = (int)((target) - jit->prg) / 2; \
269-
_EMIT6((op) | reg_high(b) << 16 | rel >> 16, rel & 0xffff);\
270-
REG_SET_SEEN(b); \
271-
})
292+
emit6_pcrel_rilb(jit, op, b, off_to_pcrel(jit, target))
272293

273-
#define EMIT6_PCREL_RIL(op, target) \
274-
({ \
275-
unsigned int rel = (int)((target) - jit->prg) / 2; \
276-
_EMIT6((op) | rel >> 16, rel & 0xffff); \
277-
})
294+
#define EMIT6_PCREL_RILB_PTR(op, b, target_ptr) \
295+
emit6_pcrel_rilb(jit, op, b, ptr_to_pcrel(jit, target_ptr))
296+
297+
static void emit6_pcrel_rilc(struct bpf_jit *jit, u32 op, u8 mask, s64 pcrel)
298+
{
299+
emit6_pcrel_ril(jit, op | mask << 20, pcrel);
300+
}
278301

279302
#define EMIT6_PCREL_RILC(op, mask, target) \
280-
({ \
281-
EMIT6_PCREL_RIL((op) | (mask) << 20, (target)); \
282-
})
303+
emit6_pcrel_rilc(jit, op, mask, off_to_pcrel(jit, target))
304+
305+
#define EMIT6_PCREL_RILC_PTR(op, mask, target_ptr) \
306+
emit6_pcrel_rilc(jit, op, mask, ptr_to_pcrel(jit, target_ptr))
283307

284308
#define _EMIT6_IMM(op, imm) \
285309
({ \
@@ -503,7 +527,7 @@ static void bpf_skip(struct bpf_jit *jit, int size)
503527
{
504528
if (size >= 6 && !is_valid_rel(size)) {
505529
/* brcl 0xf,size */
506-
EMIT6_PCREL_RIL(0xc0f4000000, size);
530+
EMIT6_PCREL_RILC(0xc0040000, 0xf, size);
507531
size -= 6;
508532
} else if (size >= 4 && is_valid_rel(size)) {
509533
/* brc 0xf,size */

0 commit comments

Comments
 (0)