From patchwork Mon Jul 18 19:51:29 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mathieu Poirier X-Patchwork-Id: 72251 Delivered-To: patch@linaro.org Received: by 10.140.29.52 with SMTP id a49csp291033qga; Mon, 18 Jul 2016 12:52:38 -0700 (PDT) X-Received: by 10.67.7.165 with SMTP id dd5mr58701696pad.124.1468871558096; Mon, 18 Jul 2016 12:52:38 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id j21si5037758pfj.191.2016.07.18.12.52.37; Mon, 18 Jul 2016 12:52:38 -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; 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 dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752482AbcGRTvz (ORCPT + 29 others); Mon, 18 Jul 2016 15:51:55 -0400 Received: from mail-io0-f182.google.com ([209.85.223.182]:36793 "EHLO mail-io0-f182.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752320AbcGRTvo (ORCPT ); Mon, 18 Jul 2016 15:51:44 -0400 Received: by mail-io0-f182.google.com with SMTP id b62so327694iod.3 for ; Mon, 18 Jul 2016 12:51: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=SYD1XD2j+BB33seh1wJUt6IHxWpgrEKVjEq+jXxNDuU=; b=SWB/DTbdcLf10wo+DJZH4si3qZjopJQp6dM/i7+Xod4xiyTlx8j+ZmHsmLgEckO8Lx 3FVl4bnfY5pZP9Z40FJzhYAnzBB3V1mTg4QhmrHaIcTemSKa6GOoumxkDw1hDHi2XpTs c5/WPsWlJPKKorFcZT5UmA0vBg/QAnLL4F2VA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=SYD1XD2j+BB33seh1wJUt6IHxWpgrEKVjEq+jXxNDuU=; b=JYo6cfUsukCTXahUfnYrLsej1WOvLPfxGQ6K+jAx+JfyMzK34hz53kgMpn1IUwVhg1 5WlBCaeV6D3OPtxmoDx+jOVF8AITMkLkfA+4WuW71xJ+sUmFP9Hwzp0xUhluyqONJyyn tSY0VEi52ViiUEJKQRzT790/aFOIg+ZgT0RTbF+c9nbIisDTcTb+z3crooZAFrxDqCBP dh7SXuHKTV89La9uitIg23OKNgZaGX+8Vv4Txbq3890KXo03CCdWk+MXWFZvULSeM4yk 53N2shemstqNcyDZUUSRtUISxuTTEHGlwVJB6ZdcKYxz5E7SXLOOoe4UkkMuQfheKaz7 0w9w== X-Gm-Message-State: ALyK8tIYOAd7aGiFD/OoBcrEIs2v2PsXggUG2BE8NYfnmFm4TEVKepY/aajGX8cqSz1s9v9Z X-Received: by 10.107.20.82 with SMTP id 79mr20624569iou.108.1468871502806; Mon, 18 Jul 2016 12:51:42 -0700 (PDT) Received: from t430.cg.shawcable.net (S0106002369de4dac.cg.shawcable.net. [68.147.8.254]) by smtp.gmail.com with ESMTPSA id r128sm5270676ita.6.2016.07.18.12.51.41 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 18 Jul 2016 12:51:42 -0700 (PDT) From: Mathieu Poirier To: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org, alexander.shishkin@linux.intel.com, Mathieu Poirier Subject: [PATCH 08/10] coresight: etm4x: adding configurable address range filtering Date: Mon, 18 Jul 2016 13:51:29 -0600 Message-Id: <1468871491-10997-9-git-send-email-mathieu.poirier@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1468871491-10997-1-git-send-email-mathieu.poirier@linaro.org> References: <1468871491-10997-1-git-send-email-mathieu.poirier@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch adds the capability to specify address ranges from the perf cmd line using the --filter option. If the IP falls within the range(s) program flow traces are generated. Signed-off-by: Mathieu Poirier --- drivers/hwtracing/coresight/coresight-etm4x.c | 128 ++++++++++++++++++++++++-- 1 file changed, 119 insertions(+), 9 deletions(-) -- 2.7.4 diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 9eba6d8f4633..b807333ce6a1 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -46,7 +46,9 @@ module_param_named(boot_enable, boot_enable, int, S_IRUGO); /* The number of ETMv4 currently registered */ static int etm4_count; static struct etmv4_drvdata *etmdrvdata[NR_CPUS]; -static void etm4_set_default(struct etmv4_config *config); +static void etm4_set_default_config(struct etmv4_config *config); +static int etm4_set_event_filters(struct etmv4_drvdata *drvdata, + struct perf_event *event); static void etm4_os_unlock(struct etmv4_drvdata *drvdata) { @@ -195,11 +197,14 @@ static void etm4_enable_hw(void *info) static int etm4_parse_event_config(struct etmv4_drvdata *drvdata, struct perf_event *event) { + int ret = 0; struct etmv4_config *config = &drvdata->config; struct perf_event_attr *attr = &event->attr; - if (!attr) - return -EINVAL; + if (!attr) { + ret = -EINVAL; + goto out; + } /* Clear configuration from previous run */ memset(config, 0, sizeof(struct etmv4_config)); @@ -211,7 +216,12 @@ static int etm4_parse_event_config(struct etmv4_drvdata *drvdata, config->mode = ETM_MODE_EXCL_USER; /* Always start from the default config */ - etm4_set_default(config); + etm4_set_default_config(config); + + /* Configure filters specified on the perf cmd line, if any. */ + ret = etm4_set_event_filters(drvdata, event); + if (ret) + goto out; /* Go from generic option to ETMv4 specifics */ if (attr->config & BIT(ETM_OPT_CYCACC)) @@ -219,23 +229,30 @@ static int etm4_parse_event_config(struct etmv4_drvdata *drvdata, if (attr->config & BIT(ETM_OPT_TS)) config->cfg |= ETMv4_MODE_TIMESTAMP; - return 0; +out: + return ret; } static int etm4_enable_perf(struct coresight_device *csdev, struct perf_event *event) { + int ret = 0; struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); - if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id())) - return -EINVAL; + if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id())) { + ret = -EINVAL; + goto out; + } /* Configure the tracer based on the session's specifics */ - etm4_parse_event_config(drvdata, event); + ret = etm4_parse_event_config(drvdata, event); + if (ret) + goto out; /* And enable it */ etm4_enable_hw(drvdata); - return 0; +out: + return ret; } static int etm4_enable_sysfs(struct coresight_device *csdev) @@ -685,6 +702,99 @@ static void etm4_set_default(struct etmv4_config *config) etm4_set_default_filter(config); } +static int etm4_get_next_comparator(struct etmv4_drvdata *drvdata, u32 type) +{ + int nr_comparator, index = 0; + struct etmv4_config *config = &drvdata->config; + + /* + * nr_addr_cmp holds the number of comparator _pair_, so time 2 + * for the total number of comparators. + */ + nr_comparator = drvdata->nr_addr_cmp * 2; + + /* Go through the tally of comparators looking for a free one. */ + while (index < nr_comparator) { + switch (type) { + case ETM_ADDR_TYPE_RANGE: + if (config->addr_type[index] == ETM_ADDR_TYPE_NONE && + config->addr_type[index + 1] == ETM_ADDR_TYPE_NONE) + return index; + + /* Address range comparators go in pairs */ + index += 2; + break; + default: + return -EINVAL; + } + } + + /* If we are here all the comparators have been used. */ + return -ENOSPC; +} + +static int etm4_set_event_filters(struct etmv4_drvdata *drvdata, + struct perf_event *event) +{ + int i, comparator, ret = 0; + struct etmv4_config *config = &drvdata->config; + struct etm_filters *filters = event->hw.addr_filters; + + if (!filters) + goto default_filter; + + /* Sync events with what Perf got */ + perf_event_addr_filters_sync(event); + + /* + * If there are no filters to deal with simply go ahead with + * the default filter, i.e the entire address range. + */ + if (!filters->nr_filters) + goto default_filter; + + for (i = 0; i < filters->nr_filters; i++) { + struct etm_filter *filter = &filters->filter[i]; + enum etm_addr_type type = filter->type; + + /* See if a comparator is free. */ + comparator = etm4_get_next_comparator(drvdata, type); + if (comparator < 0) { + ret = comparator; + goto out; + } + + switch (type) { + case ETM_ADDR_TYPE_RANGE: + etm4_set_comparator_filter(config, + filter->start_addr, + filter->stop_addr, + comparator); + /* + * TRCVICTLR::SSSTATUS == 1, the start-stop logic is + * in the started state + */ + config->vinst_ctrl |= BIT(9); + + /* No start-stop filtering for ViewInst */ + config->vissctlr = 0x0; + break; + default: + ret = -EINVAL; + goto out; + } + } + + goto out; + + +default_filter: + etm4_set_default_filter(config); + +out: + return ret; +} + void etm4_config_trace_mode(struct etmv4_config *config) { u32 addr_acc, mode;