Commit 2e8db84f authored by Xu Kuohai's avatar Xu Kuohai Committed by Pu Lehui
Browse files

arm64: Add LDR (literal) instruction

mainline inclusion
from mainline-v6.0-rc1
commit f1e8a24e
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I9FGRE

Reference: https://github.com/torvalds/linux/commit/f1e8a24ed2ca



--------------------------------

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: default avatarXu Kuohai <xukuohai@huawei.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Reviewed-by: default avatarJean-Philippe Brucker <jean-philippe@linaro.org>
Acked-by: default avatarWill Deacon <will@kernel.org>
Link: https://lore.kernel.org/bpf/20220711150823.2128542-3-xukuohai@huawei.com


Conflicts:
	arch/arm64/lib/insn.c
Signed-off-by: default avatarPu Lehui <pulehui@huawei.com>
parent 4112a12e
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -416,6 +416,9 @@ u32 aarch64_insn_gen_load_store_imm(enum aarch64_insn_register reg,
				    unsigned int imm,
				    enum aarch64_insn_size_type size,
				    enum aarch64_insn_ldst_type type);
u32 aarch64_insn_gen_load_literal(unsigned long pc, unsigned long addr,
				  enum aarch64_insn_register reg,
				  bool is64bit);
u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1,
				     enum aarch64_insn_register reg2,
				     enum aarch64_insn_register base,
+26 −4
Original line number Diff line number Diff line
@@ -466,7 +466,7 @@ static u32 aarch64_insn_encode_ldst_size(enum aarch64_insn_size_type type,
	return insn;
}

static inline long branch_imm_common(unsigned long pc, unsigned long addr,
static inline long label_imm_common(unsigned long pc, unsigned long addr,
				     long range)
{
	long offset;
@@ -497,7 +497,7 @@ u32 __kprobes aarch64_insn_gen_branch_imm(unsigned long pc, unsigned long addr,
	 * ARM64 virtual address arrangement guarantees all kernel and module
	 * texts are within +/-128M.
	 */
	offset = branch_imm_common(pc, addr, SZ_128M);
	offset = label_imm_common(pc, addr, SZ_128M);
	if (offset >= SZ_128M)
		return AARCH64_BREAK_FAULT;

@@ -525,7 +525,7 @@ u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr,
	u32 insn;
	long offset;

	offset = branch_imm_common(pc, addr, SZ_1M);
	offset = label_imm_common(pc, addr, SZ_1M);
	if (offset >= SZ_1M)
		return AARCH64_BREAK_FAULT;

@@ -564,7 +564,7 @@ u32 aarch64_insn_gen_cond_branch_imm(unsigned long pc, unsigned long addr,
	u32 insn;
	long offset;

	offset = branch_imm_common(pc, addr, SZ_1M);
	offset = label_imm_common(pc, addr, SZ_1M);

	insn = aarch64_insn_get_bcond_value();

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

u32 aarch64_insn_gen_load_literal(unsigned long pc, unsigned long addr,
				  enum aarch64_insn_register reg,
				  bool is64bit)
{
	u32 insn;
	long offset;

	offset = label_imm_common(pc, addr, SZ_1M);
	if (offset >= SZ_1M)
		return AARCH64_BREAK_FAULT;

	insn = aarch64_insn_get_ldr_lit_value();

	if (is64bit)
		insn |= BIT(30);

	insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RT, insn, reg);

	return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_19, insn,
					     offset >> 2);
}

u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1,
				     enum aarch64_insn_register reg2,
				     enum aarch64_insn_register base,