From patchwork Thu Oct 8 10:01: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: 54657 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-lb0-f199.google.com (mail-lb0-f199.google.com [209.85.217.199]) by patches.linaro.org (Postfix) with ESMTPS id 33AA722FF4 for ; Thu, 8 Oct 2015 10:04:13 +0000 (UTC) Received: by lbos8 with SMTP id s8sf20528142lbo.2 for ; Thu, 08 Oct 2015 03:04:12 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=a330nSRyjdg8irmwW4wvUspQJbt9sZoAvTxKjQ+IsRQ=; b=FAPfJ8fgLnsUgVxs42wAnRpX2hrHR6uDSWyd/KQNE7L4i8ivwl6hXxBklfE4q62p6Y cgv+mjIF218z4OPt3xqnF9Fsx34zWZAzSoKE5CI4N7AB72Ss3LogQlwcbcNP+7SQtrlW S4zD+wMP5AwAhKqYXjVTT4S/vJeaHBPP+OTM3YZNGT46NXRZSTqPBvxGF+s3u1+IW8wR w3TNSdHFNj+kYEUMhRbfyUIniitOujcPOU5uaKsmlt4FvIcHk1J+N1skvLfpQLsIWWr1 /jxvA/5fSEx/B/6OTtCklciyTXe0DRr2cc2m5fhWAQW6Rq01LFs65/ZXqJWQruIodPMe 1LmQ== X-Gm-Message-State: ALoCoQnPiOQyJg6GWMnLN3/W+hmqYOXq/g+JOOcAH+sLau/XgF3L5iLtQu02hs74t6Naic0guArW X-Received: by 10.180.105.98 with SMTP id gl2mr529753wib.0.1444298652165; Thu, 08 Oct 2015 03:04:12 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.25.22.31 with SMTP id m31ls172984lfi.21.gmail; Thu, 08 Oct 2015 03:04:11 -0700 (PDT) X-Received: by 10.112.198.136 with SMTP id jc8mr316078lbc.107.1444298651987; Thu, 08 Oct 2015 03:04:11 -0700 (PDT) Received: from mail-lb0-f170.google.com (mail-lb0-f170.google.com. [209.85.217.170]) by mx.google.com with ESMTPS id i129si29058268lfe.150.2015.10.08.03.04.11 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 08 Oct 2015 03:04:11 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.170 as permitted sender) client-ip=209.85.217.170; Received: by lbbwt4 with SMTP id wt4so41112091lbb.1 for ; Thu, 08 Oct 2015 03:04:11 -0700 (PDT) X-Received: by 10.112.156.167 with SMTP id wf7mr3161376lbb.88.1444298651832; Thu, 08 Oct 2015 03:04:11 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.59.35 with SMTP id w3csp483122lbq; Thu, 8 Oct 2015 03:04:10 -0700 (PDT) X-Received: by 10.107.3.94 with SMTP id 91mr6958093iod.178.1444298648006; Thu, 08 Oct 2015 03:04:08 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b39si31033675ioj.143.2015.10.08.03.04.07; Thu, 08 Oct 2015 03:04:07 -0700 (PDT) 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; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755849AbbJHKDz (ORCPT + 30 others); Thu, 8 Oct 2015 06:03:55 -0400 Received: from mail-pa0-f50.google.com ([209.85.220.50]:36022 "EHLO mail-pa0-f50.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752409AbbJHKDw (ORCPT ); Thu, 8 Oct 2015 06:03:52 -0400 Received: by pablk4 with SMTP id lk4so50747631pab.3 for ; Thu, 08 Oct 2015 03:03:51 -0700 (PDT) X-Received: by 10.66.150.161 with SMTP id uj1mr7110145pab.148.1444298631557; Thu, 08 Oct 2015 03:03:51 -0700 (PDT) Received: from localhost.localdomain (61-205-1-208m5.grp1.mineo.jp. [61.205.1.208]) by smtp.googlemail.com with ESMTPSA id ya10sm44431428pbc.69.2015.10.08.03.03.46 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 08 Oct 2015 03:03:50 -0700 (PDT) From: AKASHI Takahiro To: catalin.marinas@arm.com, will.deacon@arm.com, rostedt@goodmis.org Cc: jungseoklee85@gmail.com, olof@lixom.net, broonie@kernel.org, david.griego@linaro.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, AKASHI Takahiro Subject: [PATCH v3 6/7] arm64: insn: add instruction decoders for ldp/stp and add/sub Date: Thu, 8 Oct 2015 19:01:43 +0900 Message-Id: <1444298504-10392-7-git-send-email-takahiro.akashi@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1444298504-10392-1-git-send-email-takahiro.akashi@linaro.org> References: <1444298504-10392-1-git-send-email-takahiro.akashi@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: takahiro.akashi@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.170 as permitted sender) smtp.mailfrom=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , 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(+) 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 f341866..baf2d52 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; +}