Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp299067imu; Fri, 16 Nov 2018 02:45:30 -0800 (PST) X-Google-Smtp-Source: AJdET5e1CnNcl391KBlC2G9uqHYtIJBQyOpDminSZHWrArcuDRtbKZ2OGE0wrsl7zwcQOSITISuI X-Received: by 2002:a63:1c61:: with SMTP id c33mr9254667pgm.354.1542365130387; Fri, 16 Nov 2018 02:45:30 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542365130; cv=none; d=google.com; s=arc-20160816; b=t73g1lwsd89QAbb7E0hfcXAlUGI/yQSb3TEnRNrwOBHy2lJqydrUnkAAs5FJg3xzTq jUd8jrWYVxiiJNZMc3SrMAqtj1Tsr74ytuRpY5UwkP5DWbdWxFDXZ2LwRwACH5zhvZEN +SrEq+LOS9rrYEJ1xo/G8wt0w7j4UFsPuOzvykWWRoxO112IxS6HpGGSLqkGMI/dkyCq cUWz/tNB21gDcaInPPRgyR0P9uUlBiW/cP46KeCpXRWcP1r00WX/CQhcml2XxCJUEXtF jxw9q0D6yrYijsS3k6hZAaDjAEUSWECHjv4fKU/V+SXP5OeyQPtR68BN6pk3UULZSjan ROgQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=UcW894I9ua18ct2+D3l3mwnsQPAfxSE7YZ/MOpz75Xo=; b=Rg9xxrECOz1QZpgQ40si/j5YkBzqC4jyGqstIH5S9kl2H2uTDwPphznNb/OUxs86ow qxYOk29bt6o8FpiYT0a1/2DEHBTig2uevSjPEooLI3e/uad8luqyEIJvCQM/IRxfcTFK huDRGEwWgGbDFJhdMVfBdKupCUDlfcICVb2KpldjHpT8HfrB+N6PW2PioFnJKF4+IwzE /tNBMQrNvZigOXseDlSSDl2W+B4SiM3w9C6I82FogLRIr2MpSvyIcyoLX+WaJgFc9PQi LrivI/q9+VmnGyniWBJR4vveDOcSY6boKjUFFqrIij0MfrhXpGGdk5Si8al6mFR+QjVk NLgQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@synopsys.com header.s=mail header.b=Xvm0JhI1; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=synopsys.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id n18-v6si29987205plp.294.2018.11.16.02.45.16; Fri, 16 Nov 2018 02:45:30 -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; dkim=pass header.i=@synopsys.com header.s=mail header.b=Xvm0JhI1; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=synopsys.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389574AbeKPU4Y (ORCPT + 99 others); Fri, 16 Nov 2018 15:56:24 -0500 Received: from smtprelay4.synopsys.com ([198.182.47.9]:47764 "EHLO smtprelay.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2389504AbeKPU4Y (ORCPT ); Fri, 16 Nov 2018 15:56:24 -0500 Received: from mailhost.synopsys.com (mailhost1.synopsys.com [10.12.238.239]) by smtprelay.synopsys.com (Postfix) with ESMTP id 86D3424E10EB; Fri, 16 Nov 2018 02:44:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synopsys.com; s=mail; t=1542365077; bh=ddN2RvhrI2lM5i9EjWX1ehmbpMs+Igf7E9RyrHTdYVM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Xvm0JhI1GBT4O43VSzVNbCdUg8gohQCebx/+qZ7Lbuasa3yyaE+LGX8+ZZzt7uBU9 fhGRA0tTmIDrsWjPNFRN3Mx4kqSBoD+6443y5clv0RJhOH9oKU94Y3jN8F80Q5iDIT ZaKqfy8K8fyNAFN7VVRlI2iJVwJfXu+Ad+nRzzf+OgYI6mPOle0GdIWP8PkSGF07S5 OUQNiZt/tDxh4dqqWOapwDEdrnen51yd2U+vH6kBtJYRoQ3vsAFZDIGxOXNvc9n1ZJ V8V3zTIwscleRysvRMVrytfZuebSoI8NMurFMV51+a8wr3flSyUUZcNu6NCIYyaCLX /8zGClv9IASxw== Received: from paltsev-e7480.internal.synopsys.com (paltsev-e7480.internal.synopsys.com [10.121.3.66]) by mailhost.synopsys.com (Postfix) with ESMTP id 6F6FE55B3; Fri, 16 Nov 2018 02:44:35 -0800 (PST) From: Eugeniy Paltsev To: linux-snps-arc@lists.infradead.org, Vineet Gupta Cc: linux-kernel@vger.kernel.org, Alexey Brodkin , Eugeniy Paltsev Subject: [PATCH 2/3] ARC: ARCv2: Introduce SmaRT support Date: Fri, 16 Nov 2018 13:44:26 +0300 Message-Id: <20181116104427.25264-3-Eugeniy.Paltsev@synopsys.com> X-Mailer: git-send-email 2.14.5 In-Reply-To: <20181116104427.25264-1-Eugeniy.Paltsev@synopsys.com> References: <20181116104427.25264-1-Eugeniy.Paltsev@synopsys.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add compile-time 'ARC_SMART_TRACE' option for enabling SmaRT support. Small real time trace (SmaRT) is an optional on-chip debug hardware component that captures instruction-trace history. It stores the address of the most recent non-sequential instructions executed into internal buffer. Usually we use MetaWare debugger to enable SmaRT and display trace information. This patch allows to display the decoded content of SmaRT buffer without MetaWare debugger. It is done by extending ordinary exception message with decoded SmaRT instruction-trace history. In some cases it's really useful as it allows to show pre-exception instruction-trace which was not tainted by exception handler code, printk code, etc... Nevertheless this option has negative performance impact due to implementation as we dump SmaRT buffer content into external memory buffer in the beginning of every slowpath exception handler code. We choose this implementation as a compromise between performance impact and SmaRT buffer tainting. Although the performance impact is not really significant (according to lmbench) we leave this option disabled by default. Here is th examples of user-space and kernel-space fault messages with 'ARC_SMART_TRACE' option enabled: User-space exception: ----------------------->8------------------------- Exception: u_hell[101]: at 0x103a2 [off 0x103a2 in /root/u_hell, VMA: 00010000:00012000] ECR: 0x00050200 => Invalid Write @ 0x00000000 by insn @ 0x000103a2 SmaRT [64 entries] (U=userspace, E=exception/interrupt, R=repeated, V=valid): dst[ 0]: ___V 0x90231dd8: smart_populate+0x0/0xcc src[ 0]: 0x9023230c: do_page_fault+0x2c/0x2ec dst[ 1]: ___V 0x902322e0: do_page_fault+0x0/0x2ec src[ 1]: 0x9022e064: EV_TLBProtV+0xec/0xf0 dst[ 2]: ___V 0x9022df78: EV_TLBProtV+0x0/0xf0 src[ 2]: 0x9023315c: do_slow_path_pf+0x10/0x14 dst[ 3]: ___V 0x9023314c: do_slow_path_pf+0x0/0x14 src[ 3]: 0x902330e8: EV_TLBMissD+0x80/0xe0 dst[ 4]: _E_V 0x90233068: EV_TLBMissD+0x0/0xe0 src[ 4]: 0x000103a2: off 0x103a2 in /root/u_hell (VMA: 00010000:00012000) dst[ 5]: U__V 0x00010398: off 0x10398 in /root/u_hell src[ 5]: 0x2004f238: off 0x43238 in /lib/libuClibc-1.0.18.so (VMA: 2000c000:20072000) dst[ 6]: U__V 0x2004f214: off 0x43214 in /lib/libuClibc-1.0.18.so src[ 6]: 0x20049a82: off 0x3da82 in /lib/libuClibc-1.0.18.so ...[snip]... ----------------------->8------------------------- Kernel-space exception: ----------------------->8------------------------- Exception: at dw_mci_probe+0x12/0x954: ECR: 0x00050100 => Invalid Read @ 0x00000004 by insn @ 0x905e7ca2 SmaRT [64 entries] (U=userspace, E=exception/interrupt, R=repeated, V=valid): dst[ 0]: ___V 0x90231dd8: smart_populate+0x0/0xcc src[ 0]: 0x9023230c: do_page_fault+0x2c/0x2ec dst[ 1]: ___V 0x902322e0: do_page_fault+0x0/0x2ec src[ 1]: 0x9022e064: EV_TLBProtV+0xec/0xf0 dst[ 2]: ___V 0x9022e00c: EV_TLBProtV+0x94/0xf0 src[ 2]: 0x9022e004: EV_TLBProtV+0x8c/0xf0 dst[ 3]: ___V 0x9022df78: EV_TLBProtV+0x0/0xf0 src[ 3]: 0x9023315c: do_slow_path_pf+0x10/0x14 dst[ 4]: ___V 0x9023314c: do_slow_path_pf+0x0/0x14 src[ 4]: 0x902330a4: EV_TLBMissD+0x3c/0xe0 dst[ 5]: _E_V 0x90233068: EV_TLBMissD+0x0/0xe0 src[ 5]: 0x905e7ca2: dw_mci_probe+0x12/0x954 dst[ 6]: ___V 0x905e7c90: dw_mci_probe+0x0/0x954 src[ 6]: 0x905ea61c: dw_mci_pltfm_probe+0xa8/0xc4 dst[ 7]: ___V 0x905ea5f4: dw_mci_pltfm_probe+0x80/0xc4 src[ 7]: 0x904a9b2e: devm_ioremap_resource+0x4e/0x12c dst[ 8]: ___V 0x904a9b1e: devm_ioremap_resource+0x3e/0x12c src[ 8]: 0x904a9bc0: devm_ioremap_resource+0xe0/0x12c dst[ 9]: ___V 0x904a9bbc: devm_ioremap_resource+0xdc/0x12c src[ 9]: 0x9075a3b0: _raw_spin_unlock_irqrestore+0x28/0x2c ...[snip]... ----------------------->8------------------------- The number of SmaRT buffer lines to record/display can be configured in runtime via '/proc/sys/arc_smart_trace/entries' procfs option. SmaRT can be suspended in runtime by setting '/proc/sys/arc_smart_trace/entries' to 0. The code was written in such a way to achieve minimal interference with MetaWare SmaRT support: * SmaRT is disabled only for small amount of time in smart_populate function. * SmaRT enable/disable via MetaWare doesn't lead to any serious issues (SmaRT disable via MetaWare may lead to last SmaRT record to be invalid, though) Signed-off-by: Eugeniy Paltsev --- NOTE: this PATCH series has prerequisite: http://patchwork.ozlabs.org/patch/986820/ Changes RFCv2->PATCHv1: * Move smart_exists, smart_supported and smart_stack_size functions to smart.h * Improve Kconfig SmaRT help description. * Other minor changes. Changes RFCv1->RFCv2: * Changes in output display: * Only print VMAs if they are changed. * Split entry for two lines and print source and destination addresses on different lines. * Add procfs options to configure/suspend SmaRT in runtime. * Add SmaRT version check. Limit supported SmaRT versions to >= 0x03. * Move all SmaRT related stuff to smart.h and smart.c * Other minor changes. arch/arc/Kconfig | 12 ++ arch/arc/include/asm/arcregs.h | 23 ++++ arch/arc/include/asm/smart.h | 62 ++++++++++ arch/arc/kernel/Makefile | 1 + arch/arc/kernel/setup.c | 4 + arch/arc/kernel/smart.c | 253 +++++++++++++++++++++++++++++++++++++++++ arch/arc/kernel/traps.c | 8 ++ arch/arc/kernel/troubleshoot.c | 3 + arch/arc/mm/fault.c | 2 + 9 files changed, 368 insertions(+) create mode 100644 arch/arc/include/asm/smart.h create mode 100644 arch/arc/kernel/smart.c diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index a045f3086047..4de066fb530a 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -528,6 +528,18 @@ config ARC_DBG_TLB_PARANOIA bool "Paranoia Checks in Low Level TLB Handlers" default n +config ARC_SMART_TRACE + bool "Enable SmaRT real time trace on-chip debug HW" + depends on ISA_ARCV2 + help + Enable SmaRT (small real time trace) on-chip debug hardware component + that captures instruction-trace history if exists. This trace will be + printed if any unexpected exception is occurred. + In runtime the SmaRT can be disabled/enabled and the number of SmaRT + buffer lines to record/display can be configured via + '/proc/sys/arc_smart_trace/entries' procfs option. By default SmaRT + is enabled and configured to use all available buffer entries. + endif config ARC_UBOOT_SUPPORT diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h index 49bfbd879caa..cd8228d82872 100644 --- a/arch/arc/include/asm/arcregs.h +++ b/arch/arc/include/asm/arcregs.h @@ -118,6 +118,20 @@ #define ARC_AUX_DPFP_2H 0x304 #define ARC_AUX_DPFP_STAT 0x305 +/* SmaRT registers */ +#define ARC_AUX_SMART_CONTROL 0x700 +#define SMART_CTL_EN BIT(0) +#define SMART_CTL_DATA_POS 8 +#define SMART_CTL_DATA_SRC (0 << SMART_CTL_DATA_POS) +#define SMART_CTL_DATA_DST (1 << SMART_CTL_DATA_POS) +#define SMART_CTL_DATA_FLAG (2 << SMART_CTL_DATA_POS) +#define SMART_CTL_IDX_POS 10 +#define ARC_AUX_SMART_DATA 0x701 +#define SMART_FLAG_U BIT(8) +#define SMART_FLAG_E BIT(9) +#define SMART_FLAG_R BIT(10) +#define SMART_FLAG_V BIT(31) + #ifndef __ASSEMBLY__ #include @@ -199,6 +213,15 @@ struct bcr_dccm_arcv2 { #endif }; +/* SmaRT BCR encoding starting from version 0x03 */ +struct bcr_smart_v3p { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int stack_size:22, pad:2, ver:8; +#else + unsigned int ver:8, pad:2, stack_size:22; +#endif +}; + /* ARCompact: Both SP and DP FPU BCRs have same format */ struct bcr_fp_arcompact { #ifdef CONFIG_CPU_BIG_ENDIAN diff --git a/arch/arc/include/asm/smart.h b/arch/arc/include/asm/smart.h new file mode 100644 index 000000000000..ceb14c58285a --- /dev/null +++ b/arch/arc/include/asm/smart.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +/* + * Copyright (C) 2018 Synopsys + * Author: Eugeniy Paltsev + */ + +#ifndef __ASM_SMART_H +#define __ASM_SMART_H + +#include + +/* + * SmaRT versions < 0x03 have different registers encoding and small + * buffer size. We don't support them. + */ +#define SMART_VERSION_SUPPORTED_P 0x03 + +#ifdef CONFIG_ARC_SMART_TRACE +void smart_populate(void); +void smart_show(void); +void smart_init(void); + +#define SMART_POPULATE() smart_populate() + +#else +#define SMART_POPULATE() +static inline void smart_show(void) {} +static inline void smart_init(void) {} + +#endif /* CONFIG_ARC_SMART_TRACE */ + +/* smart_exist - do we have at least some version of SmaRT? */ +static inline bool smart_exist(void) +{ + struct bcr_smart_v3p bcr; + + READ_BCR(ARC_REG_SMART_BCR, bcr); + return !!bcr.ver; +} + +/* smart_supported - do we have an version of SmaRT which we can use? */ +static inline bool smart_supported(void) +{ + struct bcr_smart_v3p bcr; + + READ_BCR(ARC_REG_SMART_BCR, bcr); + return bcr.ver >= SMART_VERSION_SUPPORTED_P; +} + +static inline u32 smart_stack_size(void) +{ + struct bcr_smart_v3p bcr; + + READ_BCR(ARC_REG_SMART_BCR, bcr); + if (bcr.ver >= SMART_VERSION_SUPPORTED_P) + return bcr.stack_size; + else + return 0; +} + +#endif /* __ASM_SMART_H */ diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile index 2dc5f4296d44..4e58a5f90c78 100644 --- a/arch/arc/kernel/Makefile +++ b/arch/arc/kernel/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_ARC_EMUL_UNALIGNED) += unaligned.o obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_ARC_METAWARE_HLINK) += arc_hostlink.o obj-$(CONFIG_PERF_EVENTS) += perf_event.o +obj-$(CONFIG_ARC_SMART_TRACE) += smart.o obj-$(CONFIG_ARC_FPU_SAVE_RESTORE) += fpu.o CFLAGS_fpu.o += -mdpfp diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index b2cae79a25d7..c5641e6ffc2a 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c @@ -28,6 +28,7 @@ #include #include #include +#include #define FIX_PTR(x) __asm__ __volatile__(";" : "+r"(x)) @@ -447,6 +448,9 @@ void setup_processor(void) pr_info("%s", arc_platform_smp_cpuinfo()); arc_chk_core_config(); + + if (IS_ENABLED(CONFIG_ARC_SMART_TRACE)) + smart_init(); } static inline int is_kernel(unsigned long addr) diff --git a/arch/arc/kernel/smart.c b/arch/arc/kernel/smart.c new file mode 100644 index 000000000000..70675ceb59d3 --- /dev/null +++ b/arch/arc/kernel/smart.c @@ -0,0 +1,253 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// Synopsys SmaRT (Small Real time Trace) handling code +// +// Copyright (C) 2018 Synopsys +// Author: Eugeniy Paltsev + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define SMART_BUFF_MAX 4096 /* HW limit */ + +struct smart_buff { + u32 entries_collected; + u32 src[SMART_BUFF_MAX]; + u32 dst[SMART_BUFF_MAX]; + u32 flags[SMART_BUFF_MAX]; +}; + +DEFINE_PER_CPU(struct smart_buff, smart_buff_log); + +struct smart_fvma_info { + bool vma_found; + struct faulting_vma_info fvma; +}; + +/* 0 value of 'smart_entries_use' will be treated as 'disable' */ +static unsigned int smart_entries_use = SMART_BUFF_MAX; + +/* limits for smart_trace/entries */ +static unsigned int smart_entries_min; +static unsigned int smart_entries_max = SMART_BUFF_MAX; + +static struct ctl_table ctl_smart_vars[] = { + { + .procname = "entries", + .data = &smart_entries_use, + .maxlen = sizeof(smart_entries_use), + .mode = 0644, + .proc_handler = proc_douintvec_minmax, + .extra1 = &smart_entries_min, + .extra2 = &smart_entries_max, + }, {} +}; + +static struct ctl_table ctl_smart[] = { + { + .procname = "arc_smart_trace", + .mode = 0555, + .child = ctl_smart_vars, + }, {} +}; + +static inline void smart_enable(void) +{ + write_aux_reg(ARC_AUX_SMART_CONTROL, SMART_CTL_EN); +} + +static inline void smart_disable(void) +{ + write_aux_reg(ARC_AUX_SMART_CONTROL, 0); +} + +static bool smart_fvma_changed(struct smart_fvma_info *curr, + struct smart_fvma_info *prev) +{ + if (!prev->vma_found) + return true; + + return prev->fvma.vm_start != curr->fvma.vm_start || + prev->fvma.vm_end != curr->fvma.vm_end; +} + +static void smart_show_fault_vma(unsigned long address, char *buf, int buflen, + struct smart_fvma_info *curr, + struct smart_fvma_info *prev) +{ + int ret; + + ret = get_faulting_vma_info(address, buf, buflen, &curr->fvma); + curr->vma_found = !ret; + if (ret) { + pr_cont(": No matching VMA found\n"); + return; + } + + if (smart_fvma_changed(curr, prev)) + pr_cont(": off 0x%lx in %s (VMA: %08lx:%08lx)\n", + curr->fvma.offset, curr->fvma.file_path, + curr->fvma.vm_start, curr->fvma.vm_end); + else + pr_cont(": off 0x%lx in %s\n", + curr->fvma.offset, curr->fvma.file_path); +} + +/* Show decoded userspace/kernelspace address */ +static void smart_show_address(u32 address, char *buf, int buflen, + struct smart_fvma_info *curr, + struct smart_fvma_info *prev) +{ + curr->vma_found = false; + + if (address < 0x80000000) + smart_show_fault_vma(address, buf, buflen, curr, prev); + else + pr_cont(": %pS\n", (void *)address); +} + +static void smart_show_dst(int i, u32 flags, u32 dst, char *buf, int buflen, + struct smart_fvma_info *curr, + struct smart_fvma_info *prev) +{ + pr_info(" dst[%4d]: %s%s%s%s %#010x", i, + flags & SMART_FLAG_U ? "U" : "_", + flags & SMART_FLAG_E ? "E" : "_", + flags & SMART_FLAG_R ? "R" : "_", + flags & SMART_FLAG_V ? "V" : "_", + dst); + + smart_show_address(dst, buf, buflen, curr, prev); +} + +static void smart_show_src(int i, u32 src, char *buf, int buflen, + struct smart_fvma_info *curr, + struct smart_fvma_info *prev) +{ + pr_info(" src[%4d]: %#010x", i, src); + + smart_show_address(src, buf, buflen, curr, prev); +} + +static void smart_show_entries(struct smart_buff *smart_buff, u32 stack_use, + char *buf, int buflen) +{ + struct smart_fvma_info fvma_0, fvma_1; + int i; + + /* + * fvma_1 will be treat as 'previous' vma while we process first entry. + * We had to errase is to show first VMAs unconditionally. + */ + fvma_1.vma_found = false; + + for (i = 0; i < stack_use; i++) { + smart_show_dst(i, smart_buff->flags[i], smart_buff->dst[i], + buf, buflen, &fvma_0, &fvma_1); + + smart_show_src(i, smart_buff->src[i], buf, buflen, + &fvma_1, &fvma_0); + } +} + +/* Should be called per cpu */ +void __init smart_init(void) +{ + struct smart_buff *smart_buff_cpu; + + /* + * We don't check 'smart_entries_use' value here as sysctl is not + * available yet, so smart_entries_use' value is unchanged. + */ + if (!smart_supported()) + return; + + smart_buff_cpu = this_cpu_ptr(&smart_buff_log); + smart_buff_cpu->entries_collected = 0; + + smart_enable(); +} + +void smart_show(void) +{ + struct smart_buff *smart_buff_cpu; + u32 stack_size, stack_use; + char *buf; + + if (!smart_supported() || !smart_entries_use) + return; + + smart_buff_cpu = this_cpu_ptr(&smart_buff_log); + + stack_size = smart_stack_size(); + stack_use = min_t(u32, stack_size, smart_buff_cpu->entries_collected); + pr_info("SmaRT [%d entries] (U=userspace, E=exception/interrupt, R=repeated, V=valid):\n", + stack_use); + + buf = (char *)__get_free_page(GFP_NOWAIT); + if (!buf) + return; + + smart_show_entries(smart_buff_cpu, stack_use, buf, PAGE_SIZE - 1); + + free_page((unsigned long)buf); +} + +#define SMART_CTL_IDX(i) ((i) << SMART_CTL_IDX_POS) +#define SMART_CTL_GET_SRC(i) (SMART_CTL_IDX(i) | SMART_CTL_DATA_SRC) +#define SMART_CTL_GET_DST(i) (SMART_CTL_IDX(i) | SMART_CTL_DATA_DST) +#define SMART_CTL_GET_FLG(i) (SMART_CTL_IDX(i) | SMART_CTL_DATA_FLAG) + +void smart_populate(void) +{ + struct smart_buff *smart_buff_cpu; + u32 stack_size, stack_use; + int i; + + if (!smart_supported() || !smart_entries_use) { + smart_buff_cpu = this_cpu_ptr(&smart_buff_log); + smart_buff_cpu->entries_collected = 0; + + return; + } + + /* + * The ARC_AUX_SMART_DATA register may be read safely only when the + * processor is in the state in which SmaRT is not collecting data. + */ + smart_disable(); + + smart_buff_cpu = this_cpu_ptr(&smart_buff_log); + + stack_size = smart_stack_size(); + stack_use = min_t(u32, stack_size, smart_entries_use); + smart_buff_cpu->entries_collected = stack_use; + + for (i = 0; i < stack_use; i++) { + write_aux_reg(ARC_AUX_SMART_CONTROL, SMART_CTL_GET_SRC(i)); + smart_buff_cpu->src[i] = read_aux_reg(ARC_AUX_SMART_DATA); + write_aux_reg(ARC_AUX_SMART_CONTROL, SMART_CTL_GET_DST(i)); + smart_buff_cpu->dst[i] = read_aux_reg(ARC_AUX_SMART_DATA); + write_aux_reg(ARC_AUX_SMART_CONTROL, SMART_CTL_GET_FLG(i)); + smart_buff_cpu->flags[i] = read_aux_reg(ARC_AUX_SMART_DATA); + } + + smart_enable(); +} + +static int __init smart_register_sysctl(void) +{ + if (!register_sysctl_table(ctl_smart)) + pr_err("Unable to register SmaRT sysctl\n"); + + return 0; +} + +arch_initcall(smart_register_sysctl); diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c index e66fd40296b3..cdeae95c7af9 100644 --- a/arch/arc/kernel/traps.c +++ b/arch/arc/kernel/traps.c @@ -22,6 +22,7 @@ #include #include #include +#include void __init trap_init(void) { @@ -70,6 +71,7 @@ int name(unsigned long address, struct pt_regs *regs) \ { \ siginfo_t info; \ \ + SMART_POPULATE(); \ clear_siginfo(&info); \ info.si_signo = signr; \ info.si_errno = 0; \ @@ -96,6 +98,8 @@ DO_ERROR_INFO(SIGSEGV, "gcc generated __builtin_trap", do_trap5_error, 0) int do_misaligned_access(unsigned long address, struct pt_regs *regs, struct callee_regs *cregs) { + SMART_POPULATE(); + /* If emulation not enabled, or failed, kill the task */ if (misaligned_fixup(address, regs, cregs) != 0) return do_misaligned_error(address, regs); @@ -128,6 +132,8 @@ void do_non_swi_trap(unsigned long address, struct pt_regs *regs) { unsigned int param = regs->ecr_param; + SMART_POPULATE(); + switch (param) { case 1: trap_is_brkpt(address, regs); @@ -159,6 +165,8 @@ void do_insterror_or_kprobe(unsigned long address, struct pt_regs *regs) { int rc; + SMART_POPULATE(); + /* Check if this exception is caused by kprobes */ rc = notify_die(DIE_IERR, "kprobe_ierr", regs, address, 0, SIGILL); if (rc == NOTIFY_STOP) diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c index 00efcdfde0ee..1410fdfcdfef 100644 --- a/arch/arc/kernel/troubleshoot.c +++ b/arch/arc/kernel/troubleshoot.c @@ -17,6 +17,7 @@ #include #include +#include /* * Common routine to print scratch regs (r0-r12) or callee regs (r13-r25) @@ -218,6 +219,8 @@ void show_exception_mesg(struct pt_regs *regs) show_exception_mesg_u(regs); else show_exception_mesg_k(regs); + + smart_show(); } void show_regs(struct pt_regs *regs) diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c index 026d662a7668..17bb1be7037d 100644 --- a/arch/arc/mm/fault.c +++ b/arch/arc/mm/fault.c @@ -18,6 +18,7 @@ #include #include #include +#include /* * kernel virtual address is required to implement vmalloc/pkmap/fixmap @@ -72,6 +73,7 @@ void do_page_fault(unsigned long address, struct pt_regs *regs) int write = regs->ecr_cause & ECR_C_PROTV_STORE; /* ST/EX */ unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; + SMART_POPULATE(); clear_siginfo(&info); /* -- 2.14.5