From patchwork Tue Oct 17 13:41:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Rutland X-Patchwork-Id: 116111 Delivered-To: patch@linaro.org Received: by 10.140.22.163 with SMTP id 32csp4910271qgn; Tue, 17 Oct 2017 06:41:14 -0700 (PDT) X-Google-Smtp-Source: AOwi7QBaynCBOPYNpam/+mMuKVhiPhU+sTsdf+YZ8UibUCs8DZsGBGUFgp/i0POm5NdDBlQwhua+ X-Received: by 10.99.140.8 with SMTP id m8mr11164836pgd.23.1508247673922; Tue, 17 Oct 2017 06:41:13 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1508247673; cv=none; d=google.com; s=arc-20160816; b=D/WjkZGF8YomkJMe9b4chCO4qJyrWiOHXzXdzuUEJTAReTPS4dOfpOa4887hE+VnV9 OVyel89PYK9zdUjMr7R5IyEwssFK3dWl5+Idpqe3Su2yls7VfrSbKamtbnHsZUbrj2TD sXcKr024+GbcTYCmGxiU4vYSn4NUmOpVh9KMh7XaPVA4TUmGugMrPxCaQRLJ5Xsk5KVN UeicvyC2NtY6Wn8vwLFVdV9BBnoy4TgwhKRwEZWILE2QkNUSj2RkIRe/Im/yBGBwnnPb FHcYT5UboTd/EuQnzQLg5f0g382cCrWjkNNNbexkFkR7UsdDa8Cv3M1OBqSULVObQN/E QBHw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :arc-authentication-results; bh=9Iho9IcmW5aRP3jLti0Rwl5qK5g04WcnTaUGmCHlNQM=; b=uuGxIkL8d18OqDnCjkfN172PeuK0bdutJRGl1lJpEAWlUji1Mww9gIIegHhskdctox SQh2QvqRvyQXfPKEVxzZp9w0+xpZyuiDlsKNvRKXm1ZaAJrmX4LrrWx/On7SwyQ+iBJ5 l9+E1dxrCCpP4ElYubQuBIQwZDRescSEGuDvftTN4/pxefHKebKeIOXkQ2DFIAVvB4cv gHlcffRiHGk3IJR/tq1T8/PZcjHUVxzeA4rDtM8Mt4ll6TnaP7tAoGlcDZ6iINyh1kbQ MPzcOafZs4jTrl/SFOoU0M4NApo0hzqRO8oYDCTbEl5QrJmMR1oEWfl2Y7n/Yfq7Xa4l LGFw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-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 f6si6107037plt.152.2017.10.17.06.41.13; Tue, 17 Oct 2017 06:41:13 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of stable-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 stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1762372AbdJQNlN (ORCPT + 9 others); Tue, 17 Oct 2017 09:41:13 -0400 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70]:47074 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758422AbdJQNlM (ORCPT ); Tue, 17 Oct 2017 09:41:12 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 7803F1529; Tue, 17 Oct 2017 06:41:12 -0700 (PDT) Received: from lakrids.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id F2CFF3F483; Tue, 17 Oct 2017 06:41:10 -0700 (PDT) From: Mark Rutland To: stable@vger.kernel.org Cc: Mark Rutland , Adrian Hunter , Borislav Petkov , David Ahern , Namhyung Kim , Peter Zijlstra , Arnaldo Carvalho de Melo Subject: [PATCH v4.13.y] perf pmu: Unbreak perf record for arm/arm64 with events with explicit PMU Date: Tue, 17 Oct 2017 14:41:05 +0100 Message-Id: <20171017134105.26457-1-mark.rutland@arm.com> X-Mailer: git-send-email 2.11.0 Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org Commit 66ec11919a0f96e936bb731fdbc2851316077d26 upstream. Currently, perf record is broken on arm/arm64 systems when the PMU is specified explicitly as part of the event, e.g. $ ./perf record -e armv8_cortex_a53/cpu_cycles/u true In such cases, perf record fails to open events unless perf_event_paranoid is set to -1, even if the PMU in question supports mode exclusion. Further, even when perf_event_paranoid is toggled, no samples are recorded. This is an unintended side effect of commit: e3ba76deef23064f ("perf tools: Force uncore events to system wide monitoring) ... which assumes that if a PMU has an associated cpu_map, it is an uncore PMU, and forces events for such PMUs to be system-wide. This is not true for arm/arm64 systems, which can have heterogeneous CPUs. To account for this, multiple CPU PMUs are exposed, each with a "cpus" field under sysfs, which the perf tool parses into a cpu_map. ARM PMUs do not have a "cpumask" file, and only have a "cpus" file. For the gory details as to why, see commit: 7e3fcffe95544010 ("perf pmu: Support alternative sysfs cpumask") Given all of this, we can instead identify uncore PMUs by explicitly checking for a "cpumask" file, and restore arm/arm64 PMU support back to a working state. This patch does so, adding a new perf_pmu::is_uncore field, and splitting the existing cpumask parsing so that it can be reused. Signed-off-by: Mark Rutland Tested-by Will Deacon Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Borislav Petkov Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: 4.12+ Fixes: e3ba76deef23064f ("perf tools: Force uncore events to system wide monitoring) Link: http://lkml.kernel.org/r/1507315102-5942-1-git-send-email-mark.rutland@arm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 9 ++++--- tools/perf/util/pmu.c | 56 +++++++++++++++++++++++++++++++----------- tools/perf/util/pmu.h | 1 + 3 files changed, 47 insertions(+), 19 deletions(-) -- 2.11.0 diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 01e779b91c8e..2e3ffc3bc483 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -309,10 +309,11 @@ static char *get_config_name(struct list_head *head_terms) static struct perf_evsel * __add_event(struct list_head *list, int *idx, struct perf_event_attr *attr, - char *name, struct cpu_map *cpus, + char *name, struct perf_pmu *pmu, struct list_head *config_terms) { struct perf_evsel *evsel; + struct cpu_map *cpus = pmu ? pmu->cpus : NULL; event_attr_init(attr); @@ -323,7 +324,7 @@ __add_event(struct list_head *list, int *idx, (*idx)++; evsel->cpus = cpu_map__get(cpus); evsel->own_cpus = cpu_map__get(cpus); - evsel->system_wide = !!cpus; + evsel->system_wide = pmu ? pmu->is_uncore : false; if (name) evsel->name = strdup(name); @@ -1232,7 +1233,7 @@ int parse_events_add_pmu(struct parse_events_evlist *data, if (!head_config) { attr.type = pmu->type; - evsel = __add_event(list, &data->idx, &attr, NULL, pmu->cpus, NULL); + evsel = __add_event(list, &data->idx, &attr, NULL, pmu, NULL); return evsel ? 0 : -ENOMEM; } @@ -1253,7 +1254,7 @@ int parse_events_add_pmu(struct parse_events_evlist *data, return -EINVAL; evsel = __add_event(list, &data->idx, &attr, - get_config_name(head_config), pmu->cpus, + get_config_name(head_config), pmu, &config_terms); if (evsel) { evsel->unit = info.unit; diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index ac16a9db1fb5..1c4d7b4e4fb5 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -470,17 +470,36 @@ static void pmu_read_sysfs(void) closedir(dir); } +static struct cpu_map *__pmu_cpumask(const char *path) +{ + FILE *file; + struct cpu_map *cpus; + + file = fopen(path, "r"); + if (!file) + return NULL; + + cpus = cpu_map__read(file); + fclose(file); + return cpus; +} + +/* + * Uncore PMUs have a "cpumask" file under sysfs. CPU PMUs (e.g. on arm/arm64) + * may have a "cpus" file. + */ +#define CPUS_TEMPLATE_UNCORE "%s/bus/event_source/devices/%s/cpumask" +#define CPUS_TEMPLATE_CPU "%s/bus/event_source/devices/%s/cpus" + static struct cpu_map *pmu_cpumask(const char *name) { - struct stat st; char path[PATH_MAX]; - FILE *file; struct cpu_map *cpus; const char *sysfs = sysfs__mountpoint(); const char *templates[] = { - "%s/bus/event_source/devices/%s/cpumask", - "%s/bus/event_source/devices/%s/cpus", - NULL + CPUS_TEMPLATE_UNCORE, + CPUS_TEMPLATE_CPU, + NULL }; const char **template; @@ -489,20 +508,25 @@ static struct cpu_map *pmu_cpumask(const char *name) for (template = templates; *template; template++) { snprintf(path, PATH_MAX, *template, sysfs, name); - if (stat(path, &st) == 0) - break; + cpus = __pmu_cpumask(path); + if (cpus) + return cpus; } - if (!*template) - return NULL; + return NULL; +} - file = fopen(path, "r"); - if (!file) - return NULL; +static bool pmu_is_uncore(const char *name) +{ + char path[PATH_MAX]; + struct cpu_map *cpus; + const char *sysfs = sysfs__mountpoint(); - cpus = cpu_map__read(file); - fclose(file); - return cpus; + snprintf(path, PATH_MAX, CPUS_TEMPLATE_UNCORE, sysfs, name); + cpus = __pmu_cpumask(path); + cpu_map__put(cpus); + + return !!cpus; } /* @@ -617,6 +641,8 @@ static struct perf_pmu *pmu_lookup(const char *name) pmu->cpus = pmu_cpumask(name); + pmu->is_uncore = pmu_is_uncore(name); + INIT_LIST_HEAD(&pmu->format); INIT_LIST_HEAD(&pmu->aliases); list_splice(&format, &pmu->format); diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index 389e9729331f..fe0de0502ce2 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -22,6 +22,7 @@ struct perf_pmu { char *name; __u32 type; bool selectable; + bool is_uncore; struct perf_event_attr *default_config; struct cpu_map *cpus; struct list_head format; /* HEAD struct perf_pmu_format -> list */