From patchwork Thu Aug 11 16:21:04 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mathieu Poirier X-Patchwork-Id: 9275589 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 275BC600CB for ; Thu, 11 Aug 2016 16:26:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 19CC92871D for ; Thu, 11 Aug 2016 16:26:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0EB532871F; Thu, 11 Aug 2016 16:26:48 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 51EF02871D for ; Thu, 11 Aug 2016 16:26:47 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1bXsn2-0005Is-Ae; Thu, 11 Aug 2016 16:25:04 +0000 Received: from mail-it0-x231.google.com ([2607:f8b0:4001:c0b::231]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1bXsjx-00030e-6y for linux-arm-kernel@lists.infradead.org; Thu, 11 Aug 2016 16:21:57 +0000 Received: by mail-it0-x231.google.com with SMTP id f6so709138ith.0 for ; Thu, 11 Aug 2016 09:21:32 -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=r0/zxscO368g9qtTtrpUebIaa+NjjTqhjVmttHs6Lk4=; b=LmEUALYV2ykhHbmynBqVAr2hm00Td7MmfdYTl3DRe8GR5CiPMabIvqOYnXAO5Ymqew 1vRgUPwX+qWXoaW2Nz2NcZkiTjDA3JJA4TSdo6Bd68PAuWRTD1J8Tne9eY3Jlhn4IBxa wSsCcdy6b3+u7MgAZQmwItKpm+3CmPL1IkfNU= 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=r0/zxscO368g9qtTtrpUebIaa+NjjTqhjVmttHs6Lk4=; b=DQGxsXIULgo6UrpTchvhfdkk8wVS2ZgkQQftIKItC9zxVDbMJ6drv2iSRCOQqyLaRk WATLC/1Ud8swil9q0LPioHkyPH9cY7/Dcy+tnQVMpwNcV94XLMbMkbvCCsP3wTKGmWF9 D7ZNtchTL7GPhsn/v9LIWxRy8B9PYY1Xgw/BSXVPdITgzjokwDBTAGK9wC4LW2Lv8riA egpdKbjCEsE55upcuD/z5VvlPHu+DKqTLtmO8Q6r1jAz9sjDOxBVbD82Z2Gri1Hsifrv pCPUX3xopkmAIyG2JLdirBPTof47vXL9G1ir3k3o6VkwZq6vgftH1mky/+wdv8ZKJ02l 0+5w== X-Gm-Message-State: AEkoouv4IVnYPDHLvZit0YoyXwc9vumAlcxShL2TUd9zw/UxOF+ortgVRnV0GSyUH1r+V54B X-Received: by 10.36.10.145 with SMTP id 139mr10974141itw.68.1470932492068; Thu, 11 Aug 2016 09:21:32 -0700 (PDT) Received: from t430.cg.shawcable.net (S0106002369de4dac.cg.shawcable.net. [68.147.8.254]) by smtp.gmail.com with ESMTPSA id d71sm1605485ioj.33.2016.08.11.09.21.30 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 11 Aug 2016 09:21:31 -0700 (PDT) From: Mathieu Poirier To: peterz@infradead.org Subject: [PATCH V5 9/9] coresight: etm-perf: incorporating sink definition from cmd line Date: Thu, 11 Aug 2016 10:21:04 -0600 Message-Id: <1470932464-726-10-git-send-email-mathieu.poirier@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1470932464-726-1-git-send-email-mathieu.poirier@linaro.org> References: <1470932464-726-1-git-send-email-mathieu.poirier@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160811_092153_567430_36EBFBF3 X-CRM114-Status: GOOD ( 22.20 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mathieu Poirier , linux-kernel@vger.kernel.org, acme@kernel.org, vince@deater.net, mingo@redhat.com, mtk.manpages@gmail.com, jolsa@kernel.org, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Now that PMU specific configuration is available as part of the event, lookup the sink identified by users from the perf command line and build a path from source to sink. With this functionality it is no longer required to select a sink in a separate step (from sysFS) before a perf trace session can be started. Signed-off-by: Mathieu Poirier --- drivers/hwtracing/coresight/coresight-etm-perf.c | 139 ++++++++++++++++++++++- 1 file changed, 138 insertions(+), 1 deletion(-) diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c index f8c7a8733b23..eab038805cbe 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.c +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -71,11 +72,25 @@ static const struct attribute_group *etm_pmu_attr_groups[] = { static void etm_event_read(struct perf_event *event) {} +static void etm_event_destroy(struct perf_event *event) +{ + void *sink; + + sink = perf_event_drv_configs_set(event, NULL); + kfree(sink); +} + static int etm_event_init(struct perf_event *event) { + struct hw_perf_event *hw_event = &event->hw; + if (event->attr.type != etm_pmu.type) return -ENOENT; + event->destroy = etm_event_destroy; + raw_spin_lock_init(&hw_event->drv_configs_lock); + hw_event->drv_configs = NULL; + return 0; } @@ -159,6 +174,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages, int nr_pages, bool overwrite) { int cpu; + char *cmdl_sink; cpumask_t *mask; struct coresight_device *sink; struct etm_event_data *event_data = NULL; @@ -171,6 +187,14 @@ static void *etm_setup_aux(struct perf_event *event, void **pages, mask = &event_data->mask; + /* + * If a sink was specified from the perf cmdline it will be part of + * the event's drv_configs. + */ + cmdl_sink = (char *)perf_event_drv_configs_get(event); + if (IS_ERR(cmdl_sink)) + cmdl_sink = NULL; + /* Setup the path for each CPU in a trace session */ for_each_cpu(cpu, mask) { struct coresight_device *csdev; @@ -184,7 +208,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages, * list of devices from source to sink that can be * referenced later when the path is actually needed. */ - event_data->path[cpu] = coresight_build_path(csdev, NULL); + event_data->path[cpu] = coresight_build_path(csdev, cmdl_sink); if (!event_data->path[cpu]) goto err; } @@ -342,6 +366,118 @@ static void etm_event_del(struct perf_event *event, int mode) etm_event_stop(event, PERF_EF_UPDATE); } +enum { + ETM_TOKEN_SINK_CPU, + ETM_TOKEN_SINK, + ETM_TOKEN_ERR, +}; + +static const match_table_t drv_cfg_tokens = { + {ETM_TOKEN_SINK_CPU, "sink=cpu%d:%s"}, + {ETM_TOKEN_SINK, "sink=%s"}, + {ETM_TOKEN_ERR, NULL}, +}; + +/** + * etm_parse_drv_configs - parse configuration string + * + * Returns: ERR_PTR() upon error, NULL if the config string CPU is different + * from the event's CPU and the address of a valid string if one has + * been found. + */ +static char *etm_parse_drv_configs(int event_cpu, char *config_str) +{ + char *sink = NULL, *config = config_str; + int cpu, token; + substring_t args[MAX_OPT_ARGS]; + + /* See above declared @drv_cfg_tokens for the usable formats */ + token = match_token(config, drv_cfg_tokens, args); + switch (token) { + case ETM_TOKEN_SINK: + /* Simply return the sink that was specified */ + sink = match_strdup(&args[0]); + break; + case ETM_TOKEN_SINK_CPU: + /* + * We have a sink and a CPU, so we need to make sure the + * given CPU matches the event's CPU. If not this sink is + * destined to another tracer. This isn't an error hence not + * setting @ret. + */ + + /* Get the cpu */ + if (match_int(&args[0], &cpu)) { + sink = ERR_PTR(-EINVAL); + goto out; + } + + /* This sink configuration is meant for another CPU */ + if (event_cpu != cpu) + goto out; + + sink = match_strdup(&args[1]); + break; + default: + sink = ERR_PTR(-EINVAL); + } + +out: + return sink; +} + +static int +etm_set_drv_configs(struct perf_event *event, + struct list_head *drv_configs) +{ + char *config, *sink; + int len; + struct perf_drv_config *drv_config; + void *old_sink; + + list_for_each_entry(drv_config, drv_configs, entry) { + /* ETM HW configuration needs a sink specification */ + if (!drv_config->option) + return -EINVAL; + + len = strlen(drv_config->config) + strlen("=") + + strlen(drv_config->option) + 1; + + config = kmalloc(len, GFP_KERNEL); + if (!config) + return -ENOMEM; + + /* Reconstruct user configuration */ + snprintf(config, len, "%s=%s", + drv_config->config, drv_config->option); + + sink = etm_parse_drv_configs(event->cpu, config); + kfree(config); + + /* No need to continue if the parse encountered and error */ + if (IS_ERR(sink)) + return PTR_ERR(sink); + + /* A valid sink was found */ + if (sink) + goto found; + } + + /* + * A sink wasn't found, which isn't automatically an error. Other + * options on the cmd line may still need to be parsed. + */ + return 0; + +found: + /* Record the sink that was found */ + old_sink = perf_event_drv_configs_set(event, sink); + /* And get rid of whatever we had before */ + kfree(old_sink); + + return 0; +} + int etm_perf_symlink(struct coresight_device *csdev, bool link) { char entry[sizeof("cpu9999999")]; @@ -383,6 +519,7 @@ static int __init etm_perf_init(void) etm_pmu.stop = etm_event_stop; etm_pmu.add = etm_event_add; etm_pmu.del = etm_event_del; + etm_pmu.set_drv_configs = etm_set_drv_configs; ret = perf_pmu_register(&etm_pmu, CORESIGHT_ETM_PMU_NAME, -1); if (ret == 0)