Skip to content

Commit f1e8a24

Browse files
Xu Kuohaiborkmann
authored andcommitted
arm64: Add LDR (literal) instruction
Add LDR (literal) instruction to load data from address relative to PC. This instruction will be used to implement long jump from bpf prog to bpf trampoline in the follow-up patch. The instruction encoding: 3 2 2 2 0 0 0 7 6 4 5 0 +-----+-------+---+-----+-------------------------------------+--------+ | 0 x | 0 1 1 | 0 | 0 0 | imm19 | Rt | +-----+-------+---+-----+-------------------------------------+--------+ for 32-bit, variant x == 0; for 64-bit, x == 1. branch_imm_common() is used to check the distance between pc and target address, since it's reused by this patch and LDR (literal) is not a branch instruction, rename it to label_imm_common(). Signed-off-by: Xu Kuohai <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Reviewed-by: Jean-Philippe Brucker <[email protected]> Acked-by: Will Deacon <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 535a57a commit f1e8a24

File tree

2 files changed

+29
-4
lines changed

2 files changed

+29
-4
lines changed

arch/arm64/include/asm/insn.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,9 @@ u32 aarch64_insn_gen_load_store_imm(enum aarch64_insn_register reg,
510510
unsigned int imm,
511511
enum aarch64_insn_size_type size,
512512
enum aarch64_insn_ldst_type type);
513+
u32 aarch64_insn_gen_load_literal(unsigned long pc, unsigned long addr,
514+
enum aarch64_insn_register reg,
515+
bool is64bit);
513516
u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1,
514517
enum aarch64_insn_register reg2,
515518
enum aarch64_insn_register base,

arch/arm64/lib/insn.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ static u32 aarch64_insn_encode_ldst_size(enum aarch64_insn_size_type type,
323323
return insn;
324324
}
325325

326-
static inline long branch_imm_common(unsigned long pc, unsigned long addr,
326+
static inline long label_imm_common(unsigned long pc, unsigned long addr,
327327
long range)
328328
{
329329
long offset;
@@ -354,7 +354,7 @@ u32 __kprobes aarch64_insn_gen_branch_imm(unsigned long pc, unsigned long addr,
354354
* ARM64 virtual address arrangement guarantees all kernel and module
355355
* texts are within +/-128M.
356356
*/
357-
offset = branch_imm_common(pc, addr, SZ_128M);
357+
offset = label_imm_common(pc, addr, SZ_128M);
358358
if (offset >= SZ_128M)
359359
return AARCH64_BREAK_FAULT;
360360

@@ -382,7 +382,7 @@ u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr,
382382
u32 insn;
383383
long offset;
384384

385-
offset = branch_imm_common(pc, addr, SZ_1M);
385+
offset = label_imm_common(pc, addr, SZ_1M);
386386
if (offset >= SZ_1M)
387387
return AARCH64_BREAK_FAULT;
388388

@@ -421,7 +421,7 @@ u32 aarch64_insn_gen_cond_branch_imm(unsigned long pc, unsigned long addr,
421421
u32 insn;
422422
long offset;
423423

424-
offset = branch_imm_common(pc, addr, SZ_1M);
424+
offset = label_imm_common(pc, addr, SZ_1M);
425425

426426
insn = aarch64_insn_get_bcond_value();
427427

@@ -543,6 +543,28 @@ u32 aarch64_insn_gen_load_store_imm(enum aarch64_insn_register reg,
543543
return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_12, insn, imm);
544544
}
545545

546+
u32 aarch64_insn_gen_load_literal(unsigned long pc, unsigned long addr,
547+
enum aarch64_insn_register reg,
548+
bool is64bit)
549+
{
550+
u32 insn;
551+
long offset;
552+
553+
offset = label_imm_common(pc, addr, SZ_1M);
554+
if (offset >= SZ_1M)
555+
return AARCH64_BREAK_FAULT;
556+
557+
insn = aarch64_insn_get_ldr_lit_value();
558+
559+
if (is64bit)
560+
insn |= BIT(30);
561+
562+
insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn, reg);
563+
564+
return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_19, insn,
565+
offset >> 2);
566+
}
567+
546568
u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1,
547569
enum aarch64_insn_register reg2,
548570
enum aarch64_insn_register base,

0 commit comments

Comments
 (0)