From patchwork Wed Aug 27 13:02:30 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wang Nan X-Patchwork-Id: 36103 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ig0-f198.google.com (mail-ig0-f198.google.com [209.85.213.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id D0E84203C5 for ; Wed, 27 Aug 2014 13:16:32 +0000 (UTC) Received: by mail-ig0-f198.google.com with SMTP id h18sf1260368igc.5 for ; Wed, 27 Aug 2014 06:16:32 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe:content-type; bh=ji+aUGd3RWDskngESYtoEsphgUPeZmuybCJQDDolTSQ=; b=Waz3Vv70BdDL7SrxTtirzBICrkwW9IWxHPAAHfeg6IA8mGxs/7wNJsvY1lweBsj/CN UW11iu976Y+4GdYH2C37s8xBCA8p9CoV27RTjcd8+/u3scA5MIWPTCA+t03rA2tJNgrj kEU3EmXucEGN65cWrj20i+Nz2P66IizvqWzZFcIxLKVqndLLz/s0KfmQxGfYKS91B99W ovGL+NZx47zf+315xI2bfJTF0dwRQggQQY7ZdgvKd4JYyjPSTyxja8r/NZOiioFIWWU0 IlGSwTbXsHmbBkhYcZVlHVuOQU2EVguh/8XNVihQrXHawmnnrPOcVODom7RasiJBYeGF 2BUg== X-Gm-Message-State: ALoCoQmD/veT+qc2lbBGmyJDT/BYqYDU4hfNPDenF3H6fC8Yy3Zr9XYlhr7Yum4OqhAqIRhxPVcq X-Received: by 10.50.118.100 with SMTP id kl4mr18001738igb.8.1409145392385; Wed, 27 Aug 2014 06:16:32 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.80.210 with SMTP id c76ls84706qgd.56.gmail; Wed, 27 Aug 2014 06:16:32 -0700 (PDT) X-Received: by 10.52.137.51 with SMTP id qf19mr58190vdb.97.1409145391763; Wed, 27 Aug 2014 06:16:31 -0700 (PDT) Received: from mail-vc0-f172.google.com (mail-vc0-f172.google.com [209.85.220.172]) by mx.google.com with ESMTPS id h4si232870vdx.8.2014.08.27.06.16.31 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 27 Aug 2014 06:16:31 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.172 as permitted sender) client-ip=209.85.220.172; Received: by mail-vc0-f172.google.com with SMTP id im17so64503vcb.31 for ; Wed, 27 Aug 2014 06:16:31 -0700 (PDT) X-Received: by 10.220.118.136 with SMTP id v8mr279951vcq.50.1409145391554; Wed, 27 Aug 2014 06:16:31 -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.221.45.67 with SMTP id uj3csp80246vcb; Wed, 27 Aug 2014 06:16:31 -0700 (PDT) X-Received: by 10.67.4.1 with SMTP id ca1mr46682592pad.50.1409145390530; Wed, 27 Aug 2014 06:16:30 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id to9si578853pab.89.2014.08.27.06.16.29 for ; Wed, 27 Aug 2014 06:16:30 -0700 (PDT) Received-SPF: none (google.com: linux-kernel-owner@vger.kernel.org does not designate permitted sender hosts) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934563AbaH0NPw (ORCPT + 26 others); Wed, 27 Aug 2014 09:15:52 -0400 Received: from szxga02-in.huawei.com ([119.145.14.65]:22631 "EHLO szxga02-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934456AbaH0NPs (ORCPT ); Wed, 27 Aug 2014 09:15:48 -0400 Received: from 172.24.2.119 (EHLO lggeml425-hub.china.huawei.com) ([172.24.2.119]) by szxrg02-dlp.huawei.com (MOS 4.3.7-GA FastPath queued) with ESMTP id BYR81787; Wed, 27 Aug 2014 21:14:17 +0800 (CST) Received: from kernel-host.huawei (10.107.197.247) by lggeml425-hub.china.huawei.com (10.72.61.35) with Microsoft SMTP Server id 14.3.158.1; Wed, 27 Aug 2014 21:14:07 +0800 From: Wang Nan To: Russell King , "David A. Long" , Jon Medhurst , Taras Kondratiuk , Ben Dooks , "Ananth N Mavinakayanahalli" , Anil S Keshavamurthy , "David S. Miller" , Masami Hiramatsu , Will Deacon CC: Wang Nan , Pei Feiyue , , Subject: [PATCH v5 1/3] ARM: probes: check stack operation when decoding Date: Wed, 27 Aug 2014 21:02:30 +0800 Message-ID: <1409144552-12751-2-git-send-email-wangnan0@huawei.com> X-Mailer: git-send-email 1.8.4 In-Reply-To: <1409144552-12751-1-git-send-email-wangnan0@huawei.com> References: <1409144552-12751-1-git-send-email-wangnan0@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.107.197.247] X-CFilter-Loop: Reflected 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: wangnan0@huawei.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.172 as permitted sender) smtp.mail=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: , This patch improves arm instruction decoder, allows it check whether an instruction is a stack store operation. This information is important for kprobe optimization. For normal str instruction, this patch add a series of _SP_STACK register indicator in the decoder to test the base and offset register in ldr , [, ] against sp. For stm instruction, it check sp register in instruction specific decoder. Signed-off-by: Wang Nan Cc: Russell King Cc: "David A. Long" Cc: Jon Medhurst Cc: Taras Kondratiuk Cc: Ben Dooks Cc: Ananth N Mavinakayanahalli Cc: Anil S Keshavamurthy Cc: "David S. Miller" Cc: Masami Hiramatsu Cc: Will Deacon Reviewed-by: Masami Hiramatsu --- arch/arm/include/asm/probes.h | 1 + arch/arm/kernel/kprobes-common.c | 4 ++++ arch/arm/kernel/probes-arm.c | 4 ++-- arch/arm/kernel/probes-thumb.c | 6 +++--- arch/arm/kernel/probes.c | 20 ++++++++++++++++++-- arch/arm/kernel/probes.h | 6 ++++++ 6 files changed, 34 insertions(+), 7 deletions(-) diff --git a/arch/arm/include/asm/probes.h b/arch/arm/include/asm/probes.h index 806cfe6..3f6912c 100644 --- a/arch/arm/include/asm/probes.h +++ b/arch/arm/include/asm/probes.h @@ -38,6 +38,7 @@ struct arch_probes_insn { probes_check_cc *insn_check_cc; probes_insn_singlestep_t *insn_singlestep; probes_insn_fn_t *insn_fn; + bool is_stack_operation; }; #endif diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c index 0bf5d64..4e8b918 100644 --- a/arch/arm/kernel/kprobes-common.c +++ b/arch/arm/kernel/kprobes-common.c @@ -133,6 +133,10 @@ kprobe_decode_ldmstm(probes_opcode_t insn, struct arch_probes_insn *asi, int is_ldm = insn & 0x100000; int rn = (insn >> 16) & 0xf; + /* whether this is a push instruction? */ + if ((rn == 0xd) && (!is_ldm)) + asi->is_stack_operation = true; + if (rn <= 12 && (reglist & 0xe000) == 0) { /* Instruction only uses registers in the range R0..R12 */ handler = emulate_generic_r0_12_noflags; diff --git a/arch/arm/kernel/probes-arm.c b/arch/arm/kernel/probes-arm.c index 8eaef81..5c187ba 100644 --- a/arch/arm/kernel/probes-arm.c +++ b/arch/arm/kernel/probes-arm.c @@ -577,7 +577,7 @@ static const union decode_item arm_cccc_01xx_table[] = { /* STR (immediate) cccc 010x x0x0 xxxx xxxx xxxx xxxx xxxx */ /* STRB (immediate) cccc 010x x1x0 xxxx xxxx xxxx xxxx xxxx */ DECODE_EMULATEX (0x0e100000, 0x04000000, PROBES_STORE, - REGS(NOPCWB, ANY, 0, 0, 0)), + REGS(NOPCWB_SP_STACK, ANY, 0, 0, 0)), /* LDR (immediate) cccc 010x x0x1 xxxx xxxx xxxx xxxx xxxx */ /* LDRB (immediate) cccc 010x x1x1 xxxx xxxx xxxx xxxx xxxx */ @@ -587,7 +587,7 @@ static const union decode_item arm_cccc_01xx_table[] = { /* STR (register) cccc 011x x0x0 xxxx xxxx xxxx xxxx xxxx */ /* STRB (register) cccc 011x x1x0 xxxx xxxx xxxx xxxx xxxx */ DECODE_EMULATEX (0x0e100000, 0x06000000, PROBES_STORE, - REGS(NOPCWB, ANY, 0, 0, NOPC)), + REGS(NOPCWB_SP_STACK, ANY, 0, 0, NOPC_SP_STACK)), /* LDR (register) cccc 011x x0x1 xxxx xxxx xxxx xxxx xxxx */ /* LDRB (register) cccc 011x x1x1 xxxx xxxx xxxx xxxx xxxx */ diff --git a/arch/arm/kernel/probes-thumb.c b/arch/arm/kernel/probes-thumb.c index 4131351..d0d30d8 100644 --- a/arch/arm/kernel/probes-thumb.c +++ b/arch/arm/kernel/probes-thumb.c @@ -54,7 +54,7 @@ static const union decode_item t32_table_1110_100x_x1xx[] = { /* STRD (immediate) 1110 1001 x1x0 xxxx xxxx xxxx xxxx xxxx */ /* LDRD (immediate) 1110 1001 x1x1 xxxx xxxx xxxx xxxx xxxx */ DECODE_EMULATEX (0xff400000, 0xe9400000, PROBES_T32_LDRDSTRD, - REGS(NOPCWB, NOSPPC, NOSPPC, 0, 0)), + REGS(NOPCWB_SP_STACK, NOSPPC, NOSPPC, 0, 0)), /* TBB 1110 1000 1101 xxxx xxxx xxxx 0000 xxxx */ /* TBH 1110 1000 1101 xxxx xxxx xxxx 0001 xxxx */ @@ -345,12 +345,12 @@ static const union decode_item t32_table_1111_100x[] = { /* STR (immediate) 1111 1000 1100 xxxx xxxx xxxx xxxx xxxx */ /* LDR (immediate) 1111 1000 1101 xxxx xxxx xxxx xxxx xxxx */ DECODE_EMULATEX (0xffe00000, 0xf8c00000, PROBES_T32_LDRSTR, - REGS(NOPCX, ANY, 0, 0, 0)), + REGS(NOPCX_SP_STACK, ANY, 0, 0, 0)), /* STR (register) 1111 1000 0100 xxxx xxxx 0000 00xx xxxx */ /* LDR (register) 1111 1000 0101 xxxx xxxx 0000 00xx xxxx */ DECODE_EMULATEX (0xffe00fc0, 0xf8400000, PROBES_T32_LDRSTR, - REGS(NOPCX, ANY, 0, 0, NOSPPC)), + REGS(NOPCX_SP_STACK, ANY, 0, 0, NOSPPC)), /* LDRB (literal) 1111 1000 x001 1111 xxxx xxxx xxxx xxxx */ /* LDRSB (literal) 1111 1001 x001 1111 xxxx xxxx xxxx xxxx */ diff --git a/arch/arm/kernel/probes.c b/arch/arm/kernel/probes.c index 1c77b8d..f811cac 100644 --- a/arch/arm/kernel/probes.c +++ b/arch/arm/kernel/probes.c @@ -258,7 +258,9 @@ set_emulated_insn(probes_opcode_t insn, struct arch_probes_insn *asi, * non-zero value, the corresponding nibble in pinsn is validated and modified * according to the type. */ -static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs, bool modify) +static bool __kprobes decode_regs(probes_opcode_t *pinsn, + struct arch_probes_insn *asi, + u32 regs, bool modify) { probes_opcode_t insn = *pinsn; probes_opcode_t mask = 0xf; /* Start at least significant nibble */ @@ -307,11 +309,14 @@ static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs, bool modify) goto reject; break; + case REG_TYPE_NOPCWB_SP_STACK: case REG_TYPE_NOPCWB: if (!is_writeback(insn)) break; /* No writeback, so any register is OK */ /* fall through... */ + case REG_TYPE_NOPC_SP_STACK: case REG_TYPE_NOPC: + case REG_TYPE_NOPCX_SP_STACK: case REG_TYPE_NOPCX: /* Reject PC (R15) */ if (((insn ^ 0xffffffff) & mask) == 0) @@ -319,6 +324,15 @@ static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs, bool modify) break; } + /* check stack operation */ + switch (regs & 0xf) { + case REG_TYPE_NOPCWB_SP_STACK: + case REG_TYPE_NOPC_SP_STACK: + case REG_TYPE_NOPCX_SP_STACK: + if (((insn ^ 0xdddddddd) & mask) == 0) + asi->is_stack_operation = true; + } + /* Replace value of nibble with new register number... */ insn &= ~mask; insn |= new_bits & mask; @@ -394,6 +408,8 @@ probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, const struct decode_header *next; bool matched = false; + asi->is_stack_operation = false; + if (emulate) insn = prepare_emulated_insn(insn, asi, thumb); @@ -410,7 +426,7 @@ probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, if (!matched && (insn & h->mask.bits) != h->value.bits) continue; - if (!decode_regs(&insn, regs, emulate)) + if (!decode_regs(&insn, asi, regs, emulate)) return INSN_REJECTED; switch (type) { diff --git a/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h index dba9f24..568fd01 100644 --- a/arch/arm/kernel/probes.h +++ b/arch/arm/kernel/probes.h @@ -278,13 +278,19 @@ enum decode_reg_type { REG_TYPE_NOSP, /* Register must not be SP */ REG_TYPE_NOSPPC, /* Register must not be SP or PC */ REG_TYPE_NOPC, /* Register must not be PC */ + REG_TYPE_NOPC_SP_STACK, /* REG_TYPE_NOPC and if this reg is sp + then this is a stack operation */ REG_TYPE_NOPCWB, /* No PC if load/store write-back flag also set */ + REG_TYPE_NOPCWB_SP_STACK, /* REG_TYPE_NOPCWB and, if this reg is sp + then this is a stack operation */ /* The following types are used when the encoding for PC indicates * another instruction form. This distiction only matters for test * case coverage checks. */ REG_TYPE_NOPCX, /* Register must not be PC */ + REG_TYPE_NOPCX_SP_STACK, /* REG_TYPE_NOPCX and if this reg is sp + then this is a stack operation */ REG_TYPE_NOSPPCX, /* Register must not be SP or PC */ /* Alias to allow '0' arg to be used in REGS macro. */