From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754790AbcGHLiP (ORCPT ); Fri, 8 Jul 2016 07:38:15 -0400 Received: from foss.arm.com ([217.140.101.70]:42040 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754540AbcGHLhr (ORCPT ); Fri, 8 Jul 2016 07:37:47 -0400 From: Suzuki K Poulose To: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org, catalin.marinas@arm.com, mark.rutland@arm.com, will.deacon@arm.com, Suzuki K Poulose Subject: [PATCH 4/8] arm64/insn: Add helpers for pc relative data processing instructions Date: Fri, 8 Jul 2016 12:37:14 +0100 Message-Id: <1467977839-27543-6-git-send-email-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1467977839-27543-1-git-send-email-suzuki.poulose@arm.com> References: <1467977839-27543-1-git-send-email-suzuki.poulose@arm.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Adds helpers for decoding/encoding the PC relative addresses for Data processing instructions (i.e, adr and adrp). This will be used for handling dynamic patching of 'adr/adrp' instructions in alternative code patching. Cc: Mark Rutland Cc: Will Deacon Cc: Catalin Marinas Signed-off-by: Suzuki K Poulose --- arch/arm64/include/asm/insn.h | 5 +++++ arch/arm64/kernel/insn.c | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h index 30e50eb..03dc4c2 100644 --- a/arch/arm64/include/asm/insn.h +++ b/arch/arm64/include/asm/insn.h @@ -277,6 +277,8 @@ __AARCH64_INSN_FUNCS(hint, 0xFFFFF01F, 0xD503201F) __AARCH64_INSN_FUNCS(br, 0xFFFFFC1F, 0xD61F0000) __AARCH64_INSN_FUNCS(blr, 0xFFFFFC1F, 0xD63F0000) __AARCH64_INSN_FUNCS(ret, 0xFFFFFC1F, 0xD65F0000) +__AARCH64_INSN_FUNCS(adrp, 0x9F000000, 0x90000000) +__AARCH64_INSN_FUNCS(adr, 0x9F000000, 0x10000000) #undef __AARCH64_INSN_FUNCS @@ -355,6 +357,9 @@ u32 aarch64_insn_gen_logical_shifted_reg(enum aarch64_insn_register dst, s32 aarch64_get_branch_offset(u32 insn); u32 aarch64_set_branch_offset(u32 insn, s32 offset); +s32 aarch64_get_addr_offset(u32 insn); +u32 aarch64_set_addr_offset(u32 insn, s32 offset); + bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn); int aarch64_insn_patch_text_nosync(void *addr, u32 insn); diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c index 368c082..3edd741 100644 --- a/arch/arm64/kernel/insn.c +++ b/arch/arm64/kernel/insn.c @@ -1175,6 +1175,29 @@ u32 aarch64_set_branch_offset(u32 insn, s32 offset) BUG(); } +s32 aarch64_get_addr_offset(u32 insn) +{ + if (aarch64_insn_is_adr(insn)) + return aarch64_insn_decode_immediate(AARCH64_INSN_IMM_ADR, insn); + if (aarch64_insn_is_adrp(insn)) + return aarch64_insn_decode_immediate(AARCH64_INSN_IMM_ADR, insn) << 12; + + /* Unhandled instruction */ + BUG(); +} + +u32 aarch64_set_addr_offset(u32 insn, s32 offset) +{ + if (aarch64_insn_is_adr(insn)) + return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_ADR, insn, + offset); + if (aarch64_insn_is_adrp(insn)) + return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_ADR, insn, + offset >> 12); + /* Unhandled instruction */ + BUG(); +} + bool aarch32_insn_is_wide(u32 insn) { return insn >= 0xe800; -- 2.7.4