Received: by 2002:ac0:a679:0:0:0:0:0 with SMTP id p54csp498280imp; Thu, 21 Feb 2019 05:46:30 -0800 (PST) X-Received: by 2002:a62:3681:: with SMTP id d123mr15810726pfa.242.1550756550163; Thu, 21 Feb 2019 05:42:30 -0800 (PST) X-Google-Smtp-Source: AHgI3IZfVApsVQnZnplavTMGIalDXINpSJL8rwvTDsgM6iMuk2XkKM2zWApAOqlKkFbnoZSR6ZsZ X-Received: by 2002:a62:3681:: with SMTP id d123mr15810651pfa.242.1550756549066; Thu, 21 Feb 2019 05:42:29 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1550756549; cv=none; d=google.com; s=arc-20160816; b=uV4dH9r3whoIgsEYsPQwmLMkcmrDQyFRXHzTawIbNOGzZggpH2BbTa5pqM+20n+PkC n1RXjYP4Z85j6jR5aYf9OzRRPa87wRjKSAmD8HZOljTmy8gugYvbQ+5A4jI8qRaaw4ZX SPVRE2dfsuCUEpKGDHgL3/nVVEYMqYL7EuV5c4V+Q7HEvwZ1rBtmoAeUuXimp6pE1kRW 8A9ZzC5z/6yF9vUCK5W6k/2f3O3727YR2i2xRbd6P03vbolOZUy/kcNvwLv6wrdsUvzU xJXheW0/iEyiNO+HhtLPWJ7GNBHqDVssQNf2fV5YuA4cqJFDWAJjGgk8QjtfPFYHYJDj AGNA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from; bh=9hiTbeA+83BcljQd8fIWRVcUCuZoE3io5eYMXdqE4ts=; b=f29W7RVntwAS4Hddq136TuHZWjQ18KyPXi1WsjuOBbWHScxMoVvPgjQRQupbsyxg2d m85p+yKN2DCoUqpgg8ZxilmzNhAT88+1yyGSUYkgsM6rhhNaGt7yG/r3mVr+kyNV0xf0 cznmmlqp6G27u3lSZ0z/17J5ZV0E45ym5lXuzCssFc+Kal7HDVghUP7mDmqpPvdQ+Jar DI2Jlh/xCuHNbeVzIPEpVnkPQ2G+Q80kAvMfku/QYWtxSZIiveY/cZd1zf1G4fJQdQw3 PxJ5TRp9cT7YerY+G0NrL4LnAhCtsa/0r5GXr2/tC1nqoRsijpeSOyxTew4aecGjHaeq hiZw== ARC-Authentication-Results: i=1; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id go14si1462422plb.380.2019.02.21.05.42.13; Thu, 21 Feb 2019 05:42:29 -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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727974AbfBUNlt (ORCPT + 99 others); Thu, 21 Feb 2019 08:41:49 -0500 Received: from smtp2200-217.mail.aliyun.com ([121.197.200.217]:48576 "EHLO smtp2200-217.mail.aliyun.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725991AbfBUNls (ORCPT ); Thu, 21 Feb 2019 08:41:48 -0500 X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07436282|-1;CH=green;DM=CONTINUE|CONTINUE|true|0.280854-0.0604844-0.658661;FP=0|0|0|0|0|-1|-1|-1;HT=e02c03303;MF=han_mao@c-sky.com;NM=1;PH=DS;RN=4;RT=4;SR=0;TI=SMTPD_---.E.S-MUP_1550756499; Received: from localhost(mailfrom:han_mao@c-sky.com fp:SMTPD_---.E.S-MUP_1550756499) by smtp.aliyun-inc.com(10.147.40.233); Thu, 21 Feb 2019 21:41:39 +0800 From: Mao Han To: linux-arch@vger.kernel.org, linux-kernel@vger.kernel.org Cc: guoren@kernel.org, Mao Han Subject: [PATCH] csky: Add perf callchin support Date: Thu, 21 Feb 2019 21:41:26 +0800 Message-Id: <20190221134126.930-1-han_mao@c-sky.com> X-Mailer: git-send-email 2.21.0.rc2 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch add support for perf callchain sampling on csky platform. As fp is used to unwind the stack, the program being sampled and the C library need to be compiled with -mbacktrace for user callchains, kernel callchains require CONFIG_STACKTRACE = y. Signed-off-by: Mao Han --- arch/csky/kernel/Makefile | 1 + arch/csky/kernel/perf_callchain.c | 133 ++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 arch/csky/kernel/perf_callchain.c diff --git a/arch/csky/kernel/Makefile b/arch/csky/kernel/Makefile index 484e6d3a3..4c462f584 100644 --- a/arch/csky/kernel/Makefile +++ b/arch/csky/kernel/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_CSKY_PMU_V1) += perf_event.o +obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o ifdef CONFIG_FUNCTION_TRACER CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE) diff --git a/arch/csky/kernel/perf_callchain.c b/arch/csky/kernel/perf_callchain.c new file mode 100644 index 000000000..0a7a546e9 --- /dev/null +++ b/arch/csky/kernel/perf_callchain.c @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd. + +#include +#include + +/* Kernel callchain */ +struct stackframe { + unsigned long fp; + unsigned long lr; +}; + +static int +unwind_frame_kernel(struct stackframe *frame) +{ + int graph = 0; + + /* 0x3 means misalignment */ + if (!kstack_end((void *)frame->fp) && + !((unsigned long)frame->fp & 0x3) && + ((unsigned long)frame->fp >= TASK_SIZE)) { + frame->lr = ((struct stackframe *)frame->fp)->lr; + frame->fp = ((struct stackframe *)frame->fp)->fp; + /* make sure CONFIG_FUNCTION_GRAPH_TRACER is turned on */ + if (__kernel_text_address(frame->lr)) + frame->lr = ftrace_graph_ret_addr + (NULL, &graph, frame->lr, NULL); + return 0; + } else { + return -EPERM; + } +} + +static void notrace +walk_stackframe(struct stackframe *fr, + struct perf_callchain_entry_ctx *entry) +{ + while (1) { + int ret; + + perf_callchain_store(entry, fr->lr); + + ret = unwind_frame_kernel(fr); + if (ret < 0) + break; + } +} + +/* + * Get the return address for a single stackframe and return a pointer to the + * next frame tail. + */ +static unsigned long +user_backtrace(struct perf_callchain_entry_ctx *entry, unsigned long fp, + unsigned long reg_lr) +{ + struct stackframe buftail; + unsigned long lr = 0; + unsigned long *user_frame_tail = (unsigned long *)fp; + + /* Check accessibility of one struct frame_tail beyond */ + if (!access_ok(user_frame_tail, sizeof(buftail))) + return 0; + if (__copy_from_user_inatomic + (&buftail, user_frame_tail, sizeof(buftail))) + return 0; + + if (reg_lr != 0) { + lr = reg_lr; + } else { + lr = buftail.lr; + } + fp = buftail.fp; + perf_callchain_store(entry, lr); + return fp; +} + +/* + * This will be called when the target is in user mode + * This function will only be called when we use + * "PERF_SAMPLE_CALLCHAIN" in + * kernel/events/core.c:perf_prepare_sample() + * + * How to trigger perf_callchain_[user/kernel] : + * $ perf record -e cpu-clock --call-graph fp ./program + * $ perf report --call-graph + * + * On C-SKY platform, the program being sampled and the C library + * need to be compiled with * -mbacktrace, otherwise the user + * stack will not contain function frame. + */ +void +perf_callchain_user(struct perf_callchain_entry_ctx *entry, + struct pt_regs *regs) +{ + unsigned long fp = 0; + + /* C-SKY does not support virtualization. */ + if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { + return; + } + + fp = regs->regs[2]; + perf_callchain_store(entry, regs->pc); + /* + * While backtrace from leaf function, lr is normally + * not saved inside frame on C-SKY, so get lr from pt_regs + * at the sample point. However, lr value can be incorrect if + * lr is used as temp register + */ + fp = user_backtrace(entry, fp, regs->lr); + + while ((entry->nr < entry->max_stack) && + fp && !((unsigned long)fp & 0x3)) + fp = user_backtrace(entry, fp, 0); +} + +void +perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, + struct pt_regs *regs) +{ + struct stackframe fr; + + /* C-SKY does not support virtualization. */ + if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { + pr_warn("C-SKY does not support perf in guest mode!"); + return; + } + + fr.fp = regs->regs[4]; + fr.lr = regs->lr; + walk_stackframe(&fr, entry); +} -- 2.21.0.rc2