From patchwork Mon May 28 08:45:00 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leo Yan X-Patchwork-Id: 137032 Delivered-To: patch@linaro.org Received: by 2002:a2e:9706:0:0:0:0:0 with SMTP id r6-v6csp2560024lji; Mon, 28 May 2018 01:45:52 -0700 (PDT) X-Google-Smtp-Source: AB8JxZrJ6XYj1tMUD4hPPLpsWBV9oKG2c26lr1zY0ZgUmI0qnvsqzkF4ATlkvoBXt1ci9V0SKQys X-Received: by 2002:a63:8a4a:: with SMTP id y71-v6mr9613731pgd.291.1527497151875; Mon, 28 May 2018 01:45:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527497151; cv=none; d=google.com; s=arc-20160816; b=d+bNXH6cIW6c+JvE0Cm9k2tSirRHGa8rnGDx8dHW3TdxEeC0PYU5jo2dd4Wi0j1sDQ 9QJtK51izN0/2o32EUZQDE80nZuo9hBTDzjlq0jRt/calxA2t0vJmWwtSarsADjjOQkG 4lmgPHD3Sm3TVLbmPIZEn2iUpY68znCYt0T39sqAKomPaOOS4vtSI3RtUVEQfxSzY7IA lUy0QN2aYAtlmeoHYKkqf3pI26HwAkbCZm+IkPwa4KhrxgKxf0XzYgKTW/sHUtHhAQ+8 Pzov99oA7EegsQVH1VQBcYa7dDNPM/SnbJnkAuhDPsZB6qjFewtWctgvnO3fVkgpxXfE MT9Q== 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:arc-authentication-results; bh=Lji3vyYRuIF5z4NfQhW1RnWAxHyPoIpzDIEswsoWVp4=; b=XrpBNqmila30EDWjSImUODJcOcS4/QepxMIA1fBVOxEqFJhx9sdoEa6I0WWfWjewl8 p1qN8YvQ9wVdkWLlzUjjN0yzVD4leYHLNwnKlRZFUk9rRnSB4zMGngny0agcmKnFI61C r7FLf3tuC9OZvALX0ElibsPG0qkDRUKc2c9xcnE8oS3sG9AKL4c6cN3G4cxPmx29kmAz 5Y1JjVUBiF9YCvGmucO+NsJ/vbEZGa/Lwu+Xv8i5E+JtAgHYHYP0JGC+XyMTZKpnrOSd MoF9iojUziZP+VNeToL2SIJJ+ntrp+Kbq2pn5B2bSDzaQP2SnUqX6wWuXx0ZROWb1CCx z3jA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=WW+eEcGy; 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=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l4-v6si5702765pgq.65.2018.05.28.01.45.51; Mon, 28 May 2018 01:45:51 -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; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=WW+eEcGy; 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=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932105AbeE1Ipu (ORCPT + 30 others); Mon, 28 May 2018 04:45:50 -0400 Received: from mail-wm0-f68.google.com ([74.125.82.68]:50907 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754125AbeE1Ipn (ORCPT ); Mon, 28 May 2018 04:45:43 -0400 Received: by mail-wm0-f68.google.com with SMTP id t11-v6so30094146wmt.0 for ; Mon, 28 May 2018 01:45:43 -0700 (PDT) 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=Lji3vyYRuIF5z4NfQhW1RnWAxHyPoIpzDIEswsoWVp4=; b=WW+eEcGyCWeBef21OlxgVGrVRY0JrUSYpwUYryP9DwNie2RnnC10cn/vF9cCOsDJnX RA6kiEYtWInbK1Y/AS/2rPsb7ZxXgmNdshKZAQk3kdQUBmHqbBDUE4pIau+SqgQmI8YE rNa6QaFMqBrNtyKPOCKcxm1icUtgeMb0MTLEI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Lji3vyYRuIF5z4NfQhW1RnWAxHyPoIpzDIEswsoWVp4=; b=n0i/B29R7OAkvb+rdC0lKxXZpHKK0T95VrvSF6s/PG3om3K/PrI3aRQ4DJqPLg2fRf AFCtZSt+wFSl9RYGhSjPGLQOU5/VB0cUA3rrHIPIPDs+zhB4p1ZMBlez6gFPkswvbl5M xIuvoCP+hPxn/b88VZzrOm8ZDluKD5cyVkWGhS3UCjcKPxSCXV6GRqfwoEMvhkzktkxm SJlemRAqdyeWsv9ml5sdf63A5BZly1+LvyHQxsdvvtrQD0PZx6/NThzc3HstVbeIqHmy voazie94XNRKL4ETqhjxdB9ARQ+t9RqXrOM1ER7hP1EjfC0alYFnRfTV+U2pfBPFnyyJ uu9A== X-Gm-Message-State: ALKqPwcj/bbomANNxS4LgBIrRxBcy2duk7hg/xuwfBZK8JPADrezq0YI QOVEgCFQ+VD1+s8GKF5lSsivIw== X-Received: by 2002:a1c:a54e:: with SMTP id o75-v6mr1723268wme.157.1527497142290; Mon, 28 May 2018 01:45:42 -0700 (PDT) Received: from localhost.localdomain ([45.76.138.171]) by smtp.gmail.com with ESMTPSA id 123-v6sm21783013wmt.19.2018.05.28.01.45.35 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 28 May 2018 01:45:41 -0700 (PDT) From: Leo Yan To: Arnaldo Carvalho de Melo , Mathieu Poirier , Jonathan Corbet , Robert Walker , mike.leach@linaro.org, kim.phillips@arm.co, Tor Jeremiassen Cc: Peter Zijlstra , Ingo Molnar , Alexander Shishkin , Jiri Olsa , Namhyung Kim , linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, coresight@lists.linaro.org, Leo Yan Subject: [RFT v3 1/4] perf cs-etm: Generate branch sample for missed packets Date: Mon, 28 May 2018 16:45:00 +0800 Message-Id: <1527497103-3593-2-git-send-email-leo.yan@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1527497103-3593-1-git-send-email-leo.yan@linaro.org> References: <1527497103-3593-1-git-send-email-leo.yan@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit e573e978fb12 ("perf cs-etm: Inject capabilitity for CoreSight traces") reworks the samples generation flow from CoreSight trace to match the correct format so Perf report tool can display the samples properly. But the change has side effect for branch packet handling, it only generate branch samples by checking previous packet flag 'last_instr_taken_branch' is true, this results in below three kinds packets are missed to generate branch samples: - The start tracing packet at the beginning of tracing data; - The exception handling packet; - If one CS_ETM_TRACE_ON packet is inserted, we also miss to handle it for branch samples. CS_ETM_TRACE_ON packet itself can give the info that there have a discontinuity in the trace, on the other hand we also miss to generate proper branch sample for packets before and after CS_ETM_TRACE_ON packet. This patch is to add branch sample handling for up three kinds packets: - In function cs_etm__sample(), check if 'prev_packet->sample_type' is zero and in this case it generates branch sample for the start tracing packet; furthermore, we also need to handle the condition for prev_packet::end_addr is zero in the cs_etm__last_executed_instr(); - In function cs_etm__sample(), check if 'prev_packet->exc' is true and generate branch sample for exception handling packet; - If there has one CS_ETM_TRACE_ON packet is coming, we firstly generate branch sample in the function cs_etm__flush(), this can save complete info for the previous CS_ETM_RANGE packet just before CS_ETM_TRACE_ON packet. We also generate branch sample for the new CS_ETM_RANGE packet after CS_ETM_TRACE_ON packet, this have two purposes, the first one purpose is to save the info for the new CS_ETM_RANGE packet, the second purpose is to save CS_ETM_TRACE_ON packet info so we can have hint for a discontinuity in the trace. For CS_ETM_TRACE_ON packet, its fields 'packet->start_addr' and 'packet->end_addr' equal to 0xdeadbeefdeadbeefUL which are emitted in the decoder layer as dummy value. This patch is to convert these values to zeros for more readable; this is accomplished by functions cs_etm__last_executed_instr() and cs_etm__first_executed_instr(). The later one is a new function introduced by this patch. Reviewed-by: Robert Walker Fixes: e573e978fb12 ("perf cs-etm: Inject capabilitity for CoreSight traces") Signed-off-by: Leo Yan --- tools/perf/util/cs-etm.c | 93 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 73 insertions(+), 20 deletions(-) -- 2.7.4 diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index 822ba91..8418173 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -495,6 +495,20 @@ static inline void cs_etm__reset_last_branch_rb(struct cs_etm_queue *etmq) static inline u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet) { /* + * The packet is the start tracing packet if the end_addr is zero, + * returns 0 for this case. + */ + if (!packet->end_addr) + return 0; + + /* + * The packet is the CS_ETM_TRACE_ON packet if the end_addr is + * magic number 0xdeadbeefdeadbeefUL, returns 0 for this case. + */ + if (packet->end_addr == 0xdeadbeefdeadbeefUL) + return 0; + + /* * The packet records the execution range with an exclusive end address * * A64 instructions are constant size, so the last executed @@ -505,6 +519,18 @@ static inline u64 cs_etm__last_executed_instr(struct cs_etm_packet *packet) return packet->end_addr - A64_INSTR_SIZE; } +static inline u64 cs_etm__first_executed_instr(struct cs_etm_packet *packet) +{ + /* + * The packet is the CS_ETM_TRACE_ON packet if the start_addr is + * magic number 0xdeadbeefdeadbeefUL, returns 0 for this case. + */ + if (packet->start_addr == 0xdeadbeefdeadbeefUL) + return 0; + + return packet->start_addr; +} + static inline u64 cs_etm__instr_count(const struct cs_etm_packet *packet) { /* @@ -546,7 +572,7 @@ static void cs_etm__update_last_branch_rb(struct cs_etm_queue *etmq) be = &bs->entries[etmq->last_branch_pos]; be->from = cs_etm__last_executed_instr(etmq->prev_packet); - be->to = etmq->packet->start_addr; + be->to = cs_etm__first_executed_instr(etmq->packet); /* No support for mispredict */ be->flags.mispred = 0; be->flags.predicted = 1; @@ -701,7 +727,7 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq) sample.ip = cs_etm__last_executed_instr(etmq->prev_packet); sample.pid = etmq->pid; sample.tid = etmq->tid; - sample.addr = etmq->packet->start_addr; + sample.addr = cs_etm__first_executed_instr(etmq->packet); sample.id = etmq->etm->branches_id; sample.stream_id = etmq->etm->branches_id; sample.period = 1; @@ -897,13 +923,28 @@ static int cs_etm__sample(struct cs_etm_queue *etmq) etmq->period_instructions = instrs_over; } - if (etm->sample_branches && - etmq->prev_packet && - etmq->prev_packet->sample_type == CS_ETM_RANGE && - etmq->prev_packet->last_instr_taken_branch) { - ret = cs_etm__synth_branch_sample(etmq); - if (ret) - return ret; + if (etm->sample_branches && etmq->prev_packet) { + bool generate_sample = false; + + /* Generate sample for start tracing packet */ + if (etmq->prev_packet->sample_type == 0 || + etmq->prev_packet->sample_type == CS_ETM_TRACE_ON) + generate_sample = true; + + /* Generate sample for exception packet */ + if (etmq->prev_packet->exc == true) + generate_sample = true; + + /* Generate sample for normal branch packet */ + if (etmq->prev_packet->sample_type == CS_ETM_RANGE && + etmq->prev_packet->last_instr_taken_branch) + generate_sample = true; + + if (generate_sample) { + ret = cs_etm__synth_branch_sample(etmq); + if (ret) + return ret; + } } if (etm->sample_branches || etm->synth_opts.last_branch) { @@ -922,11 +963,16 @@ static int cs_etm__sample(struct cs_etm_queue *etmq) static int cs_etm__flush(struct cs_etm_queue *etmq) { int err = 0; + struct cs_etm_auxtrace *etm = etmq->etm; struct cs_etm_packet *tmp; - if (etmq->etm->synth_opts.last_branch && - etmq->prev_packet && - etmq->prev_packet->sample_type == CS_ETM_RANGE) { + if (!etmq->prev_packet) + return 0; + + if (etmq->prev_packet->sample_type != CS_ETM_RANGE) + return 0; + + if (etmq->etm->synth_opts.last_branch) { /* * Generate a last branch event for the branches left in the * circular buffer at the end of the trace. @@ -939,18 +985,25 @@ static int cs_etm__flush(struct cs_etm_queue *etmq) err = cs_etm__synth_instruction_sample( etmq, addr, etmq->period_instructions); + if (err) + return err; etmq->period_instructions = 0; + } - /* - * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for - * the next incoming packet. - */ - tmp = etmq->packet; - etmq->packet = etmq->prev_packet; - etmq->prev_packet = tmp; + if (etm->sample_branches) { + err = cs_etm__synth_branch_sample(etmq); + if (err) + return err; } - return err; + /* + * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for + * the next incoming packet. + */ + tmp = etmq->packet; + etmq->packet = etmq->prev_packet; + etmq->prev_packet = tmp; + return 0; } static int cs_etm__run_decoder(struct cs_etm_queue *etmq)