Skip to content

Commit cc2b8ed

Browse files
Ard Biesheuvelborkmann
authored andcommitted
arm64/bpf: use movn/movk/movk sequence to generate kernel addresses
On arm64, all executable code is guaranteed to reside in the vmalloc space (or the module space), and so jump targets will only use 48 bits at most, and the remaining bits are guaranteed to be 0x1. This means we can generate an immediate jump address using a sequence of one MOVN (move wide negated) and two MOVK instructions, where the first one sets the lower 16 bits but also sets all top bits to 0x1. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Acked-by: Will Deacon <will.deacon@arm.com> Acked-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
1 parent 93029d7 commit cc2b8ed

File tree

1 file changed

+6
-11
lines changed

1 file changed

+6
-11
lines changed

arch/arm64/net/bpf_jit_comp.c

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -134,19 +134,18 @@ static inline void emit_a64_mov_i64(const int reg, const u64 val,
134134
}
135135

136136
/*
137-
* This is an unoptimized 64 immediate emission used for BPF to BPF call
138-
* addresses. It will always do a full 64 bit decomposition as otherwise
139-
* more complexity in the last extra pass is required since we previously
140-
* reserved 4 instructions for the address.
137+
* Kernel addresses in the vmalloc space use at most 48 bits, and the
138+
* remaining bits are guaranteed to be 0x1. So we can compose the address
139+
* with a fixed length movn/movk/movk sequence.
141140
*/
142141
static inline void emit_addr_mov_i64(const int reg, const u64 val,
143142
struct jit_ctx *ctx)
144143
{
145144
u64 tmp = val;
146145
int shift = 0;
147146

148-
emit(A64_MOVZ(1, reg, tmp & 0xffff, shift), ctx);
149-
for (;shift < 48;) {
147+
emit(A64_MOVN(1, reg, ~tmp & 0xffff, shift), ctx);
148+
while (shift < 32) {
150149
tmp >>= 16;
151150
shift += 16;
152151
emit(A64_MOVK(1, reg, tmp & 0xffff, shift), ctx);
@@ -634,11 +633,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
634633
&func_addr, &func_addr_fixed);
635634
if (ret < 0)
636635
return ret;
637-
if (func_addr_fixed)
638-
/* We can use optimized emission here. */
639-
emit_a64_mov_i64(tmp, func_addr, ctx);
640-
else
641-
emit_addr_mov_i64(tmp, func_addr, ctx);
636+
emit_addr_mov_i64(tmp, func_addr, ctx);
642637
emit(A64_BLR(tmp), ctx);
643638
emit(A64_MOV(1, r0, A64_R(0)), ctx);
644639
break;

0 commit comments

Comments
 (0)