Skip to content

Commit

Permalink
arm64: introduce aarch64_insn_gen_branch_reg()
Browse files Browse the repository at this point in the history
Introduce function to generate unconditional branch (register)
instructions.

Signed-off-by: Zi Shen Lim <[email protected]>
Acked-by: Will Deacon <[email protected]>
Signed-off-by: Will Deacon <[email protected]>
  • Loading branch information
zlim authored and wildea01 committed Sep 8, 2014
1 parent 617d2fb commit c0cafba
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 2 deletions.
7 changes: 7 additions & 0 deletions arch/arm64/include/asm/insn.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
};
Expand All @@ -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

Expand All @@ -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);

Expand Down
35 changes: 33 additions & 2 deletions arch/arm64/kernel/insn.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}

0 comments on commit c0cafba

Please sign in to comment.