Loading arch/arm64/include/asm/insn.h +7 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,7 @@ enum aarch64_insn_imm_type { enum aarch64_insn_register_type { AARCH64_INSN_REGTYPE_RT, AARCH64_INSN_REGTYPE_RN, }; enum aarch64_insn_register { Loading Loading @@ -119,6 +120,7 @@ enum aarch64_insn_variant { enum aarch64_insn_branch_type { AARCH64_INSN_BRANCH_NOLINK, AARCH64_INSN_BRANCH_LINK, AARCH64_INSN_BRANCH_RETURN, AARCH64_INSN_BRANCH_COMP_ZERO, AARCH64_INSN_BRANCH_COMP_NONZERO, }; Loading @@ -138,6 +140,9 @@ __AARCH64_INSN_FUNCS(hvc, 0xFFE0001F, 0xD4000002) __AARCH64_INSN_FUNCS(smc, 0xFFE0001F, 0xD4000003) __AARCH64_INSN_FUNCS(brk, 0xFFE0001F, 0xD4200000) __AARCH64_INSN_FUNCS(hint, 0xFFFFF01F, 0xD503201F) __AARCH64_INSN_FUNCS(br, 0xFFFFFC1F, 0xD61F0000) __AARCH64_INSN_FUNCS(blr, 0xFFFFFC1F, 0xD63F0000) __AARCH64_INSN_FUNCS(ret, 0xFFFFFC1F, 0xD65F0000) #undef __AARCH64_INSN_FUNCS Loading @@ -156,6 +161,8 @@ u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr, enum aarch64_insn_branch_type type); u32 aarch64_insn_gen_hint(enum aarch64_insn_hint_op op); u32 aarch64_insn_gen_nop(void); u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg, enum aarch64_insn_branch_type type); bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn); Loading arch/arm64/kernel/insn.c +33 −2 Original line number Diff line number Diff line Loading @@ -283,6 +283,9 @@ static u32 aarch64_insn_encode_register(enum aarch64_insn_register_type type, case AARCH64_INSN_REGTYPE_RT: shift = 0; break; case AARCH64_INSN_REGTYPE_RN: shift = 5; break; default: pr_err("%s: unknown register type encoding %d\n", __func__, type); Loading Loading @@ -325,10 +328,16 @@ u32 __kprobes aarch64_insn_gen_branch_imm(unsigned long pc, unsigned long addr, */ offset = branch_imm_common(pc, addr, SZ_128M); if (type == AARCH64_INSN_BRANCH_LINK) switch (type) { case AARCH64_INSN_BRANCH_LINK: insn = aarch64_insn_get_bl_value(); else break; case AARCH64_INSN_BRANCH_NOLINK: insn = aarch64_insn_get_b_value(); break; default: BUG_ON(1); } return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_26, insn, offset >> 2); Loading Loading @@ -380,3 +389,25 @@ u32 __kprobes aarch64_insn_gen_nop(void) { return aarch64_insn_gen_hint(AARCH64_INSN_HINT_NOP); } u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg, enum aarch64_insn_branch_type type) { u32 insn; switch (type) { case AARCH64_INSN_BRANCH_NOLINK: insn = aarch64_insn_get_br_value(); break; case AARCH64_INSN_BRANCH_LINK: insn = aarch64_insn_get_blr_value(); break; case AARCH64_INSN_BRANCH_RETURN: insn = aarch64_insn_get_ret_value(); break; default: BUG_ON(1); } return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, reg); } Loading
arch/arm64/include/asm/insn.h +7 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,7 @@ enum aarch64_insn_imm_type { enum aarch64_insn_register_type { AARCH64_INSN_REGTYPE_RT, AARCH64_INSN_REGTYPE_RN, }; enum aarch64_insn_register { Loading Loading @@ -119,6 +120,7 @@ enum aarch64_insn_variant { enum aarch64_insn_branch_type { AARCH64_INSN_BRANCH_NOLINK, AARCH64_INSN_BRANCH_LINK, AARCH64_INSN_BRANCH_RETURN, AARCH64_INSN_BRANCH_COMP_ZERO, AARCH64_INSN_BRANCH_COMP_NONZERO, }; Loading @@ -138,6 +140,9 @@ __AARCH64_INSN_FUNCS(hvc, 0xFFE0001F, 0xD4000002) __AARCH64_INSN_FUNCS(smc, 0xFFE0001F, 0xD4000003) __AARCH64_INSN_FUNCS(brk, 0xFFE0001F, 0xD4200000) __AARCH64_INSN_FUNCS(hint, 0xFFFFF01F, 0xD503201F) __AARCH64_INSN_FUNCS(br, 0xFFFFFC1F, 0xD61F0000) __AARCH64_INSN_FUNCS(blr, 0xFFFFFC1F, 0xD63F0000) __AARCH64_INSN_FUNCS(ret, 0xFFFFFC1F, 0xD65F0000) #undef __AARCH64_INSN_FUNCS Loading @@ -156,6 +161,8 @@ u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr, enum aarch64_insn_branch_type type); u32 aarch64_insn_gen_hint(enum aarch64_insn_hint_op op); u32 aarch64_insn_gen_nop(void); u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg, enum aarch64_insn_branch_type type); bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn); Loading
arch/arm64/kernel/insn.c +33 −2 Original line number Diff line number Diff line Loading @@ -283,6 +283,9 @@ static u32 aarch64_insn_encode_register(enum aarch64_insn_register_type type, case AARCH64_INSN_REGTYPE_RT: shift = 0; break; case AARCH64_INSN_REGTYPE_RN: shift = 5; break; default: pr_err("%s: unknown register type encoding %d\n", __func__, type); Loading Loading @@ -325,10 +328,16 @@ u32 __kprobes aarch64_insn_gen_branch_imm(unsigned long pc, unsigned long addr, */ offset = branch_imm_common(pc, addr, SZ_128M); if (type == AARCH64_INSN_BRANCH_LINK) switch (type) { case AARCH64_INSN_BRANCH_LINK: insn = aarch64_insn_get_bl_value(); else break; case AARCH64_INSN_BRANCH_NOLINK: insn = aarch64_insn_get_b_value(); break; default: BUG_ON(1); } return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_26, insn, offset >> 2); Loading Loading @@ -380,3 +389,25 @@ u32 __kprobes aarch64_insn_gen_nop(void) { return aarch64_insn_gen_hint(AARCH64_INSN_HINT_NOP); } u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg, enum aarch64_insn_branch_type type) { u32 insn; switch (type) { case AARCH64_INSN_BRANCH_NOLINK: insn = aarch64_insn_get_br_value(); break; case AARCH64_INSN_BRANCH_LINK: insn = aarch64_insn_get_blr_value(); break; case AARCH64_INSN_BRANCH_RETURN: insn = aarch64_insn_get_ret_value(); break; default: BUG_ON(1); } return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, reg); }