Skip to content

Commit 6c9f86d

Browse files
Xu Kuohaiborkmann
authored andcommitted
arm64: insn: Add encoders for LDRSB/LDRSH/LDRSW
To support BPF sign-extend load instructions, add encoders for LDRSB/LDRSH/LDRSW. LDRSB/LDRSH/LDRSW (immediate) is encoded as follows: 3 2 2 2 2 1 0 0 0 7 6 4 2 0 5 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | sz|1 1 1|0|0 1|opc| imm12 | Rn | Rt | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ LDRSB/LDRSH/LDRSW (register) is encoded as follows: 3 2 2 2 2 2 1 1 1 1 0 0 0 7 6 4 2 1 6 3 2 0 5 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | sz|1 1 1|0|0 0|opc|1| Rm | opt |S|1 0| Rn | Rt | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ where: - sz indicates whether 8-bit, 16-bit or 32-bit data is to be loaded - opc opc[1] (bit 23) is always 1 and opc[0] == 1 indicates regsize is 32-bit. Since BPF signed load instructions always exend the sign bit to bit 63 regardless of whether it loads an 8-bit, 16-bit or 32-bit data. So only 64-bit register size is required. That is, it's sufficient to set field opc fixed to 0x2. - opt Indicates whether to sign extend the offset register Rm and the effective bits of Rm. We set opt to 0x7 (SXTX) since we'll use Rm as a sgined 64-bit value in BPF. - S Optional only when opt field is 0x3 (LSL) In short, the above fields are encoded to the values listed below. sz opc opt S LDRSB (immediate) 0x0 0x2 na na LDRSH (immediate) 0x1 0x2 na na LDRSW (immediate) 0x2 0x2 na na LDRSB (register) 0x0 0x2 0x7 0 LDRSH (register) 0x1 0x2 0x7 0 LDRSW (register) 0x2 0x2 0x7 0 Signed-off-by: Xu Kuohai <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Tested-by: Florent Revest <[email protected]> Acked-by: Florent Revest <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent c2e5f4f commit 6c9f86d

File tree

2 files changed

+10
-0
lines changed

2 files changed

+10
-0
lines changed

arch/arm64/include/asm/insn.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ enum aarch64_insn_ldst_type {
186186
AARCH64_INSN_LDST_LOAD_ACQ_EX,
187187
AARCH64_INSN_LDST_STORE_EX,
188188
AARCH64_INSN_LDST_STORE_REL_EX,
189+
AARCH64_INSN_LDST_SIGNED_LOAD_IMM_OFFSET,
190+
AARCH64_INSN_LDST_SIGNED_LOAD_REG_OFFSET,
189191
};
190192

191193
enum aarch64_insn_adsb_type {
@@ -324,6 +326,7 @@ __AARCH64_INSN_FUNCS(prfm, 0x3FC00000, 0x39800000)
324326
__AARCH64_INSN_FUNCS(prfm_lit, 0xFF000000, 0xD8000000)
325327
__AARCH64_INSN_FUNCS(store_imm, 0x3FC00000, 0x39000000)
326328
__AARCH64_INSN_FUNCS(load_imm, 0x3FC00000, 0x39400000)
329+
__AARCH64_INSN_FUNCS(signed_load_imm, 0X3FC00000, 0x39800000)
327330
__AARCH64_INSN_FUNCS(store_pre, 0x3FE00C00, 0x38000C00)
328331
__AARCH64_INSN_FUNCS(load_pre, 0x3FE00C00, 0x38400C00)
329332
__AARCH64_INSN_FUNCS(store_post, 0x3FE00C00, 0x38000400)
@@ -337,6 +340,7 @@ __AARCH64_INSN_FUNCS(ldset, 0x3F20FC00, 0x38203000)
337340
__AARCH64_INSN_FUNCS(swp, 0x3F20FC00, 0x38208000)
338341
__AARCH64_INSN_FUNCS(cas, 0x3FA07C00, 0x08A07C00)
339342
__AARCH64_INSN_FUNCS(ldr_reg, 0x3FE0EC00, 0x38606800)
343+
__AARCH64_INSN_FUNCS(signed_ldr_reg, 0X3FE0FC00, 0x38A0E800)
340344
__AARCH64_INSN_FUNCS(ldr_imm, 0x3FC00000, 0x39400000)
341345
__AARCH64_INSN_FUNCS(ldr_lit, 0xBF000000, 0x18000000)
342346
__AARCH64_INSN_FUNCS(ldrsw_lit, 0xFF000000, 0x98000000)

arch/arm64/lib/insn.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,9 @@ u32 aarch64_insn_gen_load_store_reg(enum aarch64_insn_register reg,
385385
case AARCH64_INSN_LDST_LOAD_REG_OFFSET:
386386
insn = aarch64_insn_get_ldr_reg_value();
387387
break;
388+
case AARCH64_INSN_LDST_SIGNED_LOAD_REG_OFFSET:
389+
insn = aarch64_insn_get_signed_ldr_reg_value();
390+
break;
388391
case AARCH64_INSN_LDST_STORE_REG_OFFSET:
389392
insn = aarch64_insn_get_str_reg_value();
390393
break;
@@ -430,6 +433,9 @@ u32 aarch64_insn_gen_load_store_imm(enum aarch64_insn_register reg,
430433
case AARCH64_INSN_LDST_LOAD_IMM_OFFSET:
431434
insn = aarch64_insn_get_ldr_imm_value();
432435
break;
436+
case AARCH64_INSN_LDST_SIGNED_LOAD_IMM_OFFSET:
437+
insn = aarch64_insn_get_signed_load_imm_value();
438+
break;
433439
case AARCH64_INSN_LDST_STORE_IMM_OFFSET:
434440
insn = aarch64_insn_get_str_imm_value();
435441
break;

0 commit comments

Comments
 (0)