From patchwork Tue Dec 15 08:33:42 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 58384 Delivered-To: patch@linaro.org Received: by 10.112.129.4 with SMTP id ns4csp57386lbb; Tue, 15 Dec 2015 00:37:22 -0800 (PST) X-Received: by 10.98.16.67 with SMTP id y64mr39906840pfi.152.1450168642011; Tue, 15 Dec 2015 00:37:22 -0800 (PST) Return-Path: Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id kr7si439643pab.120.2015.12.15.00.37.21 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 15 Dec 2015 00:37:21 -0800 (PST) Received-SPF: pass (google.com: domain of linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org designates 2001:1868:205::9 as permitted sender) client-ip=2001:1868:205::9; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org designates 2001:1868:205::9 as permitted sender) smtp.mailfrom=linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org; dkim=neutral (body hash did not verify) header.i=@linaro.org Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1a8l5b-0001Pr-3r; Tue, 15 Dec 2015 08:36:07 +0000 Received: from mail-pa0-x22e.google.com ([2607:f8b0:400e:c03::22e]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1a8l4u-0007xx-Jd for linux-arm-kernel@lists.infradead.org; Tue, 15 Dec 2015 08:35:29 +0000 Received: by mail-pa0-x22e.google.com with SMTP id hk6so1121353pad.2 for ; Tue, 15 Dec 2015 00:35:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=iO+VK2ZdQrDAQL6ykLtd5fXWCIRH6a20v+1CKBMgMA4=; b=JC00BFf62ycmcwFhJIWxdiSKsZh4uxETIAd9u6itR3r1ZQfgt8XIzFDkS8QFlcfpbL Pu+FCsM5avCnPp6OTG2cRWrngGkzx8zK6uV0cZUMfoG5mVR1TB+EQrfMxtm940ZSPT8B Wc7RRgxLoiDxpH3NZAd+7vugJz44wjgHEhpGU= 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=iO+VK2ZdQrDAQL6ykLtd5fXWCIRH6a20v+1CKBMgMA4=; b=Eoxs0f4eXZuPCghK3RHhETy8WvT5IOnfLPa5IomfW1r4K3TumzJ1PZz3ZYUbWWe4ar PaxjKAoJ8VJxJOY1N7CaD3F/zD9FvuyL9WfQ3EPmPpU1aThYAhO4J/mVQ3VruFmKcjL+ QirrE2JfW2fRfNLYKZCfpHtSgK9nPRTJj5XnqVy4q8N42CuZdoGga+rhAcQNTKHn98Ed tT/LUVJ31dWtJovNJfoCwRzFuQL2cpJUSvwxYPQpnYcBxWgmMpUUzeCGpUptFt7Q9QOP 74EGvOy9DwQhA2i/Fute96bS34WF2NKSkhVYJx6QQzePMoSs4zSCInAxgom1E2eB8VA/ xFxw== X-Gm-Message-State: ALoCoQkfkFbOjdiHUmVfs1mZ0GBAfk1wLK2CVP75EoFAzbv5yEkYmBiB4L1cauuFVHtqozRxZ7NOi+2DYICV0TwkzjusWmWglw== X-Received: by 10.67.23.226 with SMTP id id2mr30715331pad.149.1450168502125; Tue, 15 Dec 2015 00:35:02 -0800 (PST) Received: from localhost.localdomain (61-205-82-105m5.grp2.mineo.jp. [61.205.82.105]) by smtp.googlemail.com with ESMTPSA id f5sm586757pas.8.2015.12.15.00.34.57 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 15 Dec 2015 00:35:01 -0800 (PST) From: AKASHI Takahiro To: catalin.marinas@arm.com, will.deacon@arm.com, rostedt@goodmis.org Subject: [PATCH v7 4/6] arm64: insn: add instruction decoders for ldp/stp and add/sub Date: Tue, 15 Dec 2015 17:33:42 +0900 Message-Id: <1450168424-10010-5-git-send-email-takahiro.akashi@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1450168424-10010-1-git-send-email-takahiro.akashi@linaro.org> References: <1450168424-10010-1-git-send-email-takahiro.akashi@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20151215_003525_087019_C58891A5 X-CRM114-Status: GOOD ( 14.90 ) X-Spam-Score: -2.7 (--) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-2.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [2607:f8b0:400e:c03:0:0:0:22e listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: jungseoklee85@gmail.com, AKASHI Takahiro , broonie@kernel.org, yalin.wang2010@gmail.com, david.griego@linaro.org, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org Once a function prologue analyzer is implemented, it can be utilized to make the output from ftrace-based stack tracer more precise, especially stack usage for each function. But the current insn routines lacks support for some instructions, including stp, add, sub and mov to parse a function prologue. This patch adds decoders against such instructions. Those decoders are used solely by stack tracer for now, but generic enough for other uses. Reviewed-by: Jungseok Lee Tested-by: Jungseok Lee Signed-off-by: AKASHI Takahiro --- arch/arm64/include/asm/insn.h | 18 ++++++ arch/arm64/kernel/insn.c | 128 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 138 insertions(+), 8 deletions(-) -- 1.7.9.5 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h index 30e50eb..6fca8b0 100644 --- a/arch/arm64/include/asm/insn.h +++ b/arch/arm64/include/asm/insn.h @@ -161,6 +161,8 @@ enum aarch64_insn_size_type { enum aarch64_insn_ldst_type { AARCH64_INSN_LDST_LOAD_REG_OFFSET, AARCH64_INSN_LDST_STORE_REG_OFFSET, + AARCH64_INSN_LDST_LOAD_PAIR_REG_OFFSET, + AARCH64_INSN_LDST_STORE_PAIR_REG_OFFSET, AARCH64_INSN_LDST_LOAD_PAIR_PRE_INDEX, AARCH64_INSN_LDST_STORE_PAIR_PRE_INDEX, AARCH64_INSN_LDST_LOAD_PAIR_POST_INDEX, @@ -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_reg, 0x7FC00000, 0x29000000) +__AARCH64_INSN_FUNCS(ldp_reg, 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, 0xD69F03E0) #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_extract_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_extract_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..99d6e57 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[] = { @@ -388,17 +389,10 @@ u32 __kprobes aarch64_insn_encode_immediate(enum aarch64_insn_imm_type type, return insn; } -static u32 aarch64_insn_encode_register(enum aarch64_insn_register_type type, - u32 insn, - enum aarch64_insn_register reg) +static int aarch64_insn_get_reg_shift(enum aarch64_insn_register_type type) { int shift; - if (reg < AARCH64_INSN_REG_0 || reg > AARCH64_INSN_REG_SP) { - pr_err("%s: unknown register encoding %d\n", __func__, reg); - return 0; - } - switch (type) { case AARCH64_INSN_REGTYPE_RT: case AARCH64_INSN_REGTYPE_RD: @@ -415,6 +409,26 @@ static u32 aarch64_insn_encode_register(enum aarch64_insn_register_type type, shift = 16; break; default: + shift = -1; + break; + } + + return shift; +} + +static u32 aarch64_insn_encode_register(enum aarch64_insn_register_type type, + u32 insn, + enum aarch64_insn_register reg) +{ + int shift; + + if (reg < AARCH64_INSN_REG_0 || reg > AARCH64_INSN_REG_SP) { + pr_err("%s: unknown register encoding %d\n", __func__, reg); + return 0; + } + + shift = aarch64_insn_get_reg_shift(type); + if (shift < 0) { pr_err("%s: unknown register type encoding %d\n", __func__, type); return 0; @@ -632,6 +646,12 @@ u32 aarch64_insn_gen_load_store_pair(enum aarch64_insn_register reg1, int shift; switch (type) { + case AARCH64_INSN_LDST_LOAD_PAIR_REG_OFFSET: + insn = aarch64_insn_get_ldp_reg_value(); + break; + case AARCH64_INSN_LDST_STORE_PAIR_REG_OFFSET: + insn = aarch64_insn_get_stp_reg_value(); + break; case AARCH64_INSN_LDST_LOAD_PAIR_PRE_INDEX: insn = aarch64_insn_get_ldp_pre_value(); break; @@ -1141,3 +1161,95 @@ u32 aarch32_insn_mcr_extract_crm(u32 insn) { return insn & CRM_MASK; } + +static enum aarch64_insn_register aarch64_insn_decode_reg_num(u32 insn, + enum aarch64_insn_register_type type) +{ + int shift; + + shift = aarch64_insn_get_reg_shift(type); + if (shift < 0) { + pr_err("%s: unknown register type decoding %d\n", __func__, + type); + return ~0L; + } + + return (insn >> shift) & 0x1f; +} + +int aarch64_insn_extract_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 shift; + + 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 -EINVAL; + + *variant = (insn & AARCH64_INSN_SF_BIT) ? AARCH64_INSN_VARIANT_64BIT : + AARCH64_INSN_VARIANT_32BIT; + + *dst = aarch64_insn_decode_reg_num(insn, AARCH64_INSN_REGTYPE_RD); + + *src = aarch64_insn_decode_reg_num(insn, AARCH64_INSN_REGTYPE_RN); + + *imm = (int)aarch64_insn_decode_immediate(AARCH64_INSN_IMM_12, insn); + shift = (insn >> 22) & 0x3; + if (shift == 0x1) + *imm <<= 12; + else if (shift != 0x0) + return -EINVAL; + + return 0; +} + +int aarch64_insn_extract_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) +{ + u64 imm; + + if (aarch64_insn_is_stp_reg(insn)) + *type = AARCH64_INSN_LDST_STORE_PAIR_REG_OFFSET; + 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_reg(insn)) + *type = AARCH64_INSN_LDST_LOAD_PAIR_REG_OFFSET; + 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 -EINVAL; + + *variant = (insn & AARCH64_INSN_S_BIT) ? AARCH64_INSN_VARIANT_64BIT : + AARCH64_INSN_VARIANT_32BIT; + + *reg1 = aarch64_insn_decode_reg_num(insn, AARCH64_INSN_REGTYPE_RT); + + *reg2 = aarch64_insn_decode_reg_num(insn, AARCH64_INSN_REGTYPE_RT2); + + *base = aarch64_insn_decode_reg_num(insn, AARCH64_INSN_REGTYPE_RN); + + imm = aarch64_insn_decode_immediate(AARCH64_INSN_IMM_7, insn); + *offset = (int)(sign_extend64(imm, 6) * 8); + + return 0; +}