From patchwork Fri Nov 6 06:44:43 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 56092 Delivered-To: patch@linaro.org Received: by 10.112.61.134 with SMTP id p6csp829885lbr; Thu, 5 Nov 2015 22:46:04 -0800 (PST) X-Received: by 10.66.97.8 with SMTP id dw8mr14972431pab.113.1446792364558; Thu, 05 Nov 2015 22:46:04 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e4si13544342pas.138.2015.11.05.22.46.04; Thu, 05 Nov 2015 22:46:04 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dkim=neutral (body hash did not verify) header.i=@linaro_org.20150623.gappssmtp.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1032160AbbKFGp4 (ORCPT + 28 others); Fri, 6 Nov 2015 01:45:56 -0500 Received: from mail-pa0-f48.google.com ([209.85.220.48]:33685 "EHLO mail-pa0-f48.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1032001AbbKFGpw (ORCPT ); Fri, 6 Nov 2015 01:45:52 -0500 Received: by pabfh17 with SMTP id fh17so113113815pab.0 for ; Thu, 05 Nov 2015 22:45:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro_org.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Y0rxtq4cyGzbBiCv7eSoscXOYgJv1Vpkchg1Z5Ppkzg=; b=q29ndM6rllETGAyED1yIlno5vf21wJhsidJ44QXhquP2fnioLlMYZPYjqikwhtrSBZ Z45kqP/Hw2k/5ry0RVW2uwlDKcGCCt1R7Aixlh+Lx+eNb3z2idExyfSPtrlg9JRKGPKy ZhkkvVDiIv6H+cdlYYZJc8JXtyFvQRJDPYTve++jsPTSI/WKGBljynS0vWwxz3q+7Zx2 7o4ssGtxwY2LZVcOd6ziETzQARC2GqaFQDRXj23uJqG7+QMkDDzXF8ZaBaiLy1W5RL7I fYcxP8iL4dy0ghFjUgGagMhV0iveiH7l5pwu5CAWvHAj5rc7VYPtYLywfFC4gBU3Xvvv oZcA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Y0rxtq4cyGzbBiCv7eSoscXOYgJv1Vpkchg1Z5Ppkzg=; b=JRr5qHiWy14M9MLvhHrpqM57ei1cskbZ1veHxvj08mPnQ2Nzcijp93P+bZZe+p8K96 TpaNlK+lT1ABv+s+zxLeOuxHzGu6qHEJrHFNEoBxDtGkRzocNJnXBinJNtGjqRbmXLzd HE1YdGBGAod7CpWmaEWWZjfWiVdD3Ls7OTRydKeQLLJ/N7hv3ImLXAVpmn59fLRSIZsX pF86wr3mOQrQ+sEDS9ccYUAHgcmdZ2m7gPFBHr5Nyjdsb0+OdaV8oPWYuoT5pBGcqn07 kderT+xN/t9psp0ZPY+esjyegIpTyy3+BZHstRz5VrGLDfGtB7PHFv91rBuUtRkV8toq pn/w== X-Gm-Message-State: ALoCoQl5AaGuljE32v4RcWiZGBDNXIa7j7lO31xqlOw4RNA+r/4BjyOMWrz6fmmukfdayqayK35o X-Received: by 10.69.17.66 with SMTP id gc2mr6943970pbd.24.1446792352345; Thu, 05 Nov 2015 22:45:52 -0800 (PST) Received: from localhost.localdomain (61-205-2-204m5.grp1.mineo.jp. [61.205.2.204]) by smtp.googlemail.com with ESMTPSA id zi1sm11732096pbc.10.2015.11.05.22.45.47 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 05 Nov 2015 22:45:50 -0800 (PST) From: AKASHI Takahiro To: catalin.marinas@arm.com, will.deacon@arm.com, rostedt@goodmis.org Cc: jungseoklee85@gmail.com, broonie@kernel.org, david.griego@linaro.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, AKASHI Takahiro Subject: [PATCH v5 4/6] arm64: insn: add instruction decoders for ldp/stp and add/sub Date: Fri, 6 Nov 2015 15:44:43 +0900 Message-Id: <1446792285-1154-5-git-send-email-takahiro.akashi@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1446792285-1154-1-git-send-email-takahiro.akashi@linaro.org> References: <1446792285-1154-1-git-send-email-takahiro.akashi@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org A function prologue analyzer is a requisite for implementing stack tracer and getting better views of stack usages on arm64. To implement a function prologue analyzer, we have to be able to decode, at least, stp, add, sub and mov instructions. This patch adds decoders for those instructions, that are used solely by stack tracer for now, but generic enough for other uses. Signed-off-by: AKASHI Takahiro --- arch/arm64/include/asm/insn.h | 18 ++++++++ arch/arm64/kernel/insn.c | 102 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h index 30e50eb..8d5c538 100644 --- a/arch/arm64/include/asm/insn.h +++ b/arch/arm64/include/asm/insn.h @@ -165,6 +165,8 @@ enum aarch64_insn_ldst_type { AARCH64_INSN_LDST_STORE_PAIR_PRE_INDEX, AARCH64_INSN_LDST_LOAD_PAIR_POST_INDEX, AARCH64_INSN_LDST_STORE_PAIR_POST_INDEX, + AARCH64_INSN_LDST_LOAD_PAIR, + AARCH64_INSN_LDST_STORE_PAIR, }; enum aarch64_insn_adsb_type { @@ -225,6 +227,8 @@ static __always_inline u32 aarch64_insn_get_##abbr##_value(void) \ __AARCH64_INSN_FUNCS(str_reg, 0x3FE0EC00, 0x38206800) __AARCH64_INSN_FUNCS(ldr_reg, 0x3FE0EC00, 0x38606800) +__AARCH64_INSN_FUNCS(stp, 0x7FC00000, 0x29000000) +__AARCH64_INSN_FUNCS(ldp, 0x7FC00000, 0x29400000) __AARCH64_INSN_FUNCS(stp_post, 0x7FC00000, 0x28800000) __AARCH64_INSN_FUNCS(ldp_post, 0x7FC00000, 0x28C00000) __AARCH64_INSN_FUNCS(stp_pre, 0x7FC00000, 0x29800000) @@ -277,6 +281,7 @@ __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(eret, 0xFFFFFFFF, 0xD69F00E0) #undef __AARCH64_INSN_FUNCS @@ -370,6 +375,19 @@ bool aarch32_insn_is_wide(u32 insn); u32 aarch32_insn_extract_reg_num(u32 insn, int offset); u32 aarch32_insn_mcr_extract_opc2(u32 insn); u32 aarch32_insn_mcr_extract_crm(u32 insn); +int aarch64_insn_decode_add_sub_imm(u32 insn, + enum aarch64_insn_register *dst, + enum aarch64_insn_register *src, + int *imm, + enum aarch64_insn_variant *variant, + enum aarch64_insn_adsb_type *type); +int aarch64_insn_decode_load_store_pair(u32 insn, + enum aarch64_insn_register *reg1, + enum aarch64_insn_register *reg2, + enum aarch64_insn_register *base, + int *offset, + enum aarch64_insn_variant *variant, + enum aarch64_insn_ldst_type *type); #endif /* __ASSEMBLY__ */ #endif /* __ASM_INSN_H */ diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c index c08b9ad..b56a66c 100644 --- a/arch/arm64/kernel/insn.c +++ b/arch/arm64/kernel/insn.c @@ -33,6 +33,7 @@ #include #define AARCH64_INSN_SF_BIT BIT(31) +#define AARCH64_INSN_S_BIT BIT(29) #define AARCH64_INSN_N_BIT BIT(22) static int aarch64_insn_encoding_class[] = { @@ -1141,3 +1142,104 @@ u32 aarch32_insn_mcr_extract_crm(u32 insn) { return insn & CRM_MASK; } + +enum aarch64_insn_register aarch64_insn_extract_reg_num(u32 insn, + enum aarch64_insn_register_type type) +{ + int shift; + + switch (type) { + case AARCH64_INSN_REGTYPE_RT: + case AARCH64_INSN_REGTYPE_RD: + shift = 0; + break; + case AARCH64_INSN_REGTYPE_RN: + shift = 5; + break; + case AARCH64_INSN_REGTYPE_RT2: + case AARCH64_INSN_REGTYPE_RA: + shift = 10; + break; + case AARCH64_INSN_REGTYPE_RM: + shift = 16; + break; + default: + pr_err("%s: unknown register type decoding %d\n", __func__, + type); + return ~0L; + } + + return (insn & (GENMASK(4, 0) << shift)) >> shift; +} + +int aarch64_insn_decode_add_sub_imm(u32 insn, + enum aarch64_insn_register *dst, + enum aarch64_insn_register *src, + int *imm, + enum aarch64_insn_variant *variant, + enum aarch64_insn_adsb_type *type) +{ + if (aarch64_insn_is_add_imm(insn)) + *type = ((insn) & AARCH64_INSN_S_BIT) ? + AARCH64_INSN_ADSB_ADD_SETFLAGS : + AARCH64_INSN_ADSB_ADD; + else if (aarch64_insn_is_sub_imm(insn)) + *type = ((insn) & AARCH64_INSN_S_BIT) ? + AARCH64_INSN_ADSB_SUB_SETFLAGS : + AARCH64_INSN_ADSB_SUB; + else + return 0; + + *variant = (insn & AARCH64_INSN_SF_BIT) ? AARCH64_INSN_VARIANT_64BIT : + AARCH64_INSN_VARIANT_32BIT; + + *dst = aarch64_insn_extract_reg_num(insn, AARCH64_INSN_REGTYPE_RD); + + *src = aarch64_insn_extract_reg_num(insn, AARCH64_INSN_REGTYPE_RN); + + /* TODO: ignore shilft field[23:22] */ + *imm = (int)aarch64_insn_decode_immediate(AARCH64_INSN_IMM_12, insn); + + return 1; +} + +int aarch64_insn_decode_load_store_pair(u32 insn, + enum aarch64_insn_register *reg1, + enum aarch64_insn_register *reg2, + enum aarch64_insn_register *base, + int *offset, + enum aarch64_insn_variant *variant, + enum aarch64_insn_ldst_type *type) +{ + int imm; + + if (aarch64_insn_is_stp(insn)) + *type = AARCH64_INSN_LDST_STORE_PAIR; + else if (aarch64_insn_is_stp_post(insn)) + *type = AARCH64_INSN_LDST_STORE_PAIR_POST_INDEX; + else if (aarch64_insn_is_stp_pre(insn)) + *type = AARCH64_INSN_LDST_STORE_PAIR_PRE_INDEX; + else if (aarch64_insn_is_ldp(insn)) + *type = AARCH64_INSN_LDST_LOAD_PAIR; + else if (aarch64_insn_is_ldp_post(insn)) + *type = AARCH64_INSN_LDST_LOAD_PAIR_POST_INDEX; + else if (aarch64_insn_is_ldp_pre(insn)) + *type = AARCH64_INSN_LDST_LOAD_PAIR_PRE_INDEX; + else + return 0; + + *variant = (insn & AARCH64_INSN_S_BIT) ? AARCH64_INSN_VARIANT_64BIT : + AARCH64_INSN_VARIANT_32BIT; + + *reg1 = aarch64_insn_extract_reg_num(insn, AARCH64_INSN_REGTYPE_RT); + + *reg2 = aarch64_insn_extract_reg_num(insn, AARCH64_INSN_REGTYPE_RT2); + + *base = aarch64_insn_extract_reg_num(insn, AARCH64_INSN_REGTYPE_RN); + + imm = (int)aarch64_insn_decode_immediate(AARCH64_INSN_IMM_7, insn); + asm("sbfm %0, %0, 0, 6" : "+r" (imm)); + *offset = imm * 8; + + return 1; +}