linux-perf-users.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Liang, Kan" <kan.liang@linux.intel.com>
To: Ian Rogers <irogers@google.com>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	Mike Leach <mike.leach@linaro.org>, Leo Yan <leo.yan@linaro.org>,
	John Garry <john.g.garry@oracle.com>,
	Will Deacon <will@kernel.org>, James Clark <james.clark@arm.com>,
	Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@redhat.com>,
	Arnaldo Carvalho de Melo <acme@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Alexander Shishkin <alexander.shishkin@linux.intel.com>,
	Jiri Olsa <jolsa@kernel.org>, Namhyung Kim <namhyung@kernel.org>,
	Adrian Hunter <adrian.hunter@intel.com>,
	Kajol Jain <kjain@linux.ibm.com>,
	Jing Zhang <renyu.zj@linux.alibaba.com>,
	Ravi Bangoria <ravi.bangoria@amd.com>,
	Madhavan Srinivasan <maddy@linux.ibm.com>,
	Athira Rajeev <atrajeev@linux.vnet.ibm.com>,
	Ming Wang <wangming01@loongson.cn>,
	Huacai Chen <chenhuacai@kernel.org>,
	Sandipan Das <sandipan.das@amd.com>,
	Dmitrii Dolgov <9erthalion6@gmail.com>,
	Sean Christopherson <seanjc@google.com>,
	Raul Silvera <rsilvera@google.com>,
	Ali Saidi <alisaidi@amazon.com>, Rob Herring <robh@kernel.org>,
	Thomas Richter <tmricht@linux.ibm.com>,
	Kang Minchul <tegongkang@gmail.com>,
	linux-kernel@vger.kernel.org, coresight@lists.linaro.org,
	linux-arm-kernel@lists.infradead.org,
	linux-perf-users@vger.kernel.org
Subject: Re: [PATCH v1 01/23] perf tools: Warn if no user requested CPUs match PMU's CPUs
Date: Sun, 21 May 2023 15:04:07 -0400	[thread overview]
Message-ID: <3586d413-b7c9-9790-ec4e-4132502c806d@linux.intel.com> (raw)
In-Reply-To: <20230517145803.559429-2-irogers@google.com>



On 2023-05-17 10:57 a.m., Ian Rogers wrote:
> In commit 1d3351e631fc ("perf tools: Enable on a list of CPUs for hybrid")
> perf on hybrid will warn if a user requested CPU doesn't match the PMU
> of the given event but only for hybrid PMUs. Make the logic generic
> for all PMUs and remove the hybrid logic.

The logic may not work for all PMUs, especially for uncore.

For uncore, the user should be able to read counters from any CPU of a
socket/die, not just the CPU from the cpumask.
Please see d6a2f9035bfc ("perf/core: Introduce PMU_EV_CAP_READ_ACTIVE_PKG").

Thanks,
Kan
> 
> Warn if a CPU is requested that is offline for uncore events. Warn if
> a CPU is requested for a core PMU, but the CPU isn't within the cpu
> map of that PMU.
> 
> For example on a 16 (0-15) CPU system:
> ```
> $ perf stat -e imc_free_running/data_read/,cycles -C 16 true
> WARNING: Requested CPU(s) '16' not supported by PMU 'uncore_imc_free_running_1' for event 'imc_free_running/data_read/'
> WARNING: Requested CPU(s) '16' not supported by PMU 'uncore_imc_free_running_0' for event 'imc_free_running/data_read/'
> WARNING: Requested CPU(s) '16' not supported by PMU 'cpu' for event 'cycles'
> 
>  Performance counter stats for 'CPU(s) 16':
> 
>    <not supported> MiB  imc_free_running/data_read/
>    <not supported>      cycles
> 
>        0.000570094 seconds time elapsed
> ```
> 
> Signed-off-by: Ian Rogers <irogers@google.com>
> ---
>  tools/perf/builtin-record.c     |  6 +--
>  tools/perf/builtin-stat.c       |  5 +--
>  tools/perf/util/cpumap.h        |  2 +-
>  tools/perf/util/evlist-hybrid.c | 74 ---------------------------------
>  tools/perf/util/evlist-hybrid.h |  1 -
>  tools/perf/util/evlist.c        | 44 ++++++++++++++++++++
>  tools/perf/util/evlist.h        |  2 +
>  tools/perf/util/pmu.c           | 33 ---------------
>  tools/perf/util/pmu.h           |  4 --
>  9 files changed, 49 insertions(+), 122 deletions(-)
> 
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index ec0f2d5f189f..9d212236c75a 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -4198,11 +4198,7 @@ int cmd_record(int argc, const char **argv)
>  	/* Enable ignoring missing threads when -u/-p option is defined. */
>  	rec->opts.ignore_missing_thread = rec->opts.target.uid != UINT_MAX || rec->opts.target.pid;
>  
> -	if (evlist__fix_hybrid_cpus(rec->evlist, rec->opts.target.cpu_list)) {
> -		pr_err("failed to use cpu list %s\n",
> -		       rec->opts.target.cpu_list);
> -		goto out;
> -	}
> +	evlist__warn_user_requested_cpus(rec->evlist, rec->opts.target.cpu_list);
>  
>  	rec->opts.target.hybrid = perf_pmu__has_hybrid();
>  
> diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
> index bc45cee3f77c..612467216306 100644
> --- a/tools/perf/builtin-stat.c
> +++ b/tools/perf/builtin-stat.c
> @@ -2462,10 +2462,7 @@ int cmd_stat(int argc, const char **argv)
>  		}
>  	}
>  
> -	if (evlist__fix_hybrid_cpus(evsel_list, target.cpu_list)) {
> -		pr_err("failed to use cpu list %s\n", target.cpu_list);
> -		goto out;
> -	}
> +	evlist__warn_user_requested_cpus(evsel_list, target.cpu_list);
>  
>  	target.hybrid = perf_pmu__has_hybrid();
>  	if (evlist__create_maps(evsel_list, &target) < 0) {
> diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
> index e3426541e0aa..c1de993c083f 100644
> --- a/tools/perf/util/cpumap.h
> +++ b/tools/perf/util/cpumap.h
> @@ -59,7 +59,7 @@ struct perf_cpu cpu__max_present_cpu(void);
>  /**
>   * cpu_map__is_dummy - Events associated with a pid, rather than a CPU, use a single dummy map with an entry of -1.
>   */
> -static inline bool cpu_map__is_dummy(struct perf_cpu_map *cpus)
> +static inline bool cpu_map__is_dummy(const struct perf_cpu_map *cpus)
>  {
>  	return perf_cpu_map__nr(cpus) == 1 && perf_cpu_map__cpu(cpus, 0).cpu == -1;
>  }
> diff --git a/tools/perf/util/evlist-hybrid.c b/tools/perf/util/evlist-hybrid.c
> index 57f02beef023..db3f5fbdebe1 100644
> --- a/tools/perf/util/evlist-hybrid.c
> +++ b/tools/perf/util/evlist-hybrid.c
> @@ -86,77 +86,3 @@ bool evlist__has_hybrid(struct evlist *evlist)
>  
>  	return false;
>  }
> -
> -int evlist__fix_hybrid_cpus(struct evlist *evlist, const char *cpu_list)
> -{
> -	struct perf_cpu_map *cpus;
> -	struct evsel *evsel, *tmp;
> -	struct perf_pmu *pmu;
> -	int ret, unmatched_count = 0, events_nr = 0;
> -
> -	if (!perf_pmu__has_hybrid() || !cpu_list)
> -		return 0;
> -
> -	cpus = perf_cpu_map__new(cpu_list);
> -	if (!cpus)
> -		return -1;
> -
> -	/*
> -	 * The evsels are created with hybrid pmu's cpus. But now we
> -	 * need to check and adjust the cpus of evsel by cpu_list because
> -	 * cpu_list may cause conflicts with cpus of evsel. For example,
> -	 * cpus of evsel is cpu0-7, but the cpu_list is cpu6-8, we need
> -	 * to adjust the cpus of evsel to cpu6-7. And then propatate maps
> -	 * in evlist__create_maps().
> -	 */
> -	evlist__for_each_entry_safe(evlist, tmp, evsel) {
> -		struct perf_cpu_map *matched_cpus, *unmatched_cpus;
> -		char buf1[128], buf2[128];
> -
> -		pmu = perf_pmu__find_hybrid_pmu(evsel->pmu_name);
> -		if (!pmu)
> -			continue;
> -
> -		ret = perf_pmu__cpus_match(pmu, cpus, &matched_cpus,
> -					   &unmatched_cpus);
> -		if (ret)
> -			goto out;
> -
> -		events_nr++;
> -
> -		if (perf_cpu_map__nr(matched_cpus) > 0 &&
> -		    (perf_cpu_map__nr(unmatched_cpus) > 0 ||
> -		     perf_cpu_map__nr(matched_cpus) < perf_cpu_map__nr(cpus) ||
> -		     perf_cpu_map__nr(matched_cpus) < perf_cpu_map__nr(pmu->cpus))) {
> -			perf_cpu_map__put(evsel->core.cpus);
> -			perf_cpu_map__put(evsel->core.own_cpus);
> -			evsel->core.cpus = perf_cpu_map__get(matched_cpus);
> -			evsel->core.own_cpus = perf_cpu_map__get(matched_cpus);
> -
> -			if (perf_cpu_map__nr(unmatched_cpus) > 0) {
> -				cpu_map__snprint(matched_cpus, buf1, sizeof(buf1));
> -				pr_warning("WARNING: use %s in '%s' for '%s', skip other cpus in list.\n",
> -					   buf1, pmu->name, evsel->name);
> -			}
> -		}
> -
> -		if (perf_cpu_map__nr(matched_cpus) == 0) {
> -			evlist__remove(evlist, evsel);
> -			evsel__delete(evsel);
> -
> -			cpu_map__snprint(cpus, buf1, sizeof(buf1));
> -			cpu_map__snprint(pmu->cpus, buf2, sizeof(buf2));
> -			pr_warning("WARNING: %s isn't a '%s', please use a CPU list in the '%s' range (%s)\n",
> -				   buf1, pmu->name, pmu->name, buf2);
> -			unmatched_count++;
> -		}
> -
> -		perf_cpu_map__put(matched_cpus);
> -		perf_cpu_map__put(unmatched_cpus);
> -	}
> -	if (events_nr)
> -		ret = (unmatched_count == events_nr) ? -1 : 0;
> -out:
> -	perf_cpu_map__put(cpus);
> -	return ret;
> -}
> diff --git a/tools/perf/util/evlist-hybrid.h b/tools/perf/util/evlist-hybrid.h
> index aacdb1b0f948..19f74b4c340a 100644
> --- a/tools/perf/util/evlist-hybrid.h
> +++ b/tools/perf/util/evlist-hybrid.h
> @@ -10,6 +10,5 @@
>  int evlist__add_default_hybrid(struct evlist *evlist, bool precise);
>  void evlist__warn_hybrid_group(struct evlist *evlist);
>  bool evlist__has_hybrid(struct evlist *evlist);
> -int evlist__fix_hybrid_cpus(struct evlist *evlist, const char *cpu_list);
>  
>  #endif /* __PERF_EVLIST_HYBRID_H */
> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
> index a0504316b06f..5d0d99127a90 100644
> --- a/tools/perf/util/evlist.c
> +++ b/tools/perf/util/evlist.c
> @@ -2465,3 +2465,47 @@ void evlist__check_mem_load_aux(struct evlist *evlist)
>  		}
>  	}
>  }
> +
> +/**
> + * evlist__warn_user_requested_cpus() - Check each evsel against requested CPUs
> + *     and warn if the user CPU list is inapplicable for the event's PMUs
> + *     CPUs. Uncore PMUs list a CPU in sysfs, but this may be overwritten by a
> + *     user requested CPU and so any online CPU is applicable. Core PMUs handle
> + *     events on the CPUs in their list and otherwise the event isn't supported.
> + * @evlist: The list of events being checked.
> + * @cpu_list: The user provided list of CPUs.
> + */
> +void evlist__warn_user_requested_cpus(struct evlist *evlist, const char *cpu_list)
> +{
> +	struct perf_cpu_map *user_requested_cpus;
> +	struct evsel *pos;
> +
> +	if (!cpu_list)
> +		return;
> +
> +	user_requested_cpus = perf_cpu_map__new(cpu_list);
> +	if (!user_requested_cpus)
> +		return;
> +
> +	evlist__for_each_entry(evlist, pos) {
> +		const struct perf_cpu_map *to_test;
> +		struct perf_cpu cpu;
> +		int idx;
> +		bool warn = true;
> +		const struct perf_pmu *pmu = evsel__find_pmu(pos);
> +
> +		to_test = pmu && pmu->is_uncore ? cpu_map__online() : evsel__cpus(pos);
> +
> +		perf_cpu_map__for_each_cpu(cpu, idx, to_test) {
> +			if (perf_cpu_map__has(user_requested_cpus, cpu)) {
> +				warn = false;
> +				break;
> +			}
> +		}
> +		if (warn) {
> +			pr_warning("WARNING: Requested CPU(s) '%s' not supported by PMU '%s' for event '%s'\n",
> +				cpu_list, pmu ? pmu->name : "cpu", evsel__name(pos));
> +		}
> +	}
> +	perf_cpu_map__put(user_requested_cpus);
> +}
> diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
> index e7e5540cc970..5e7ff44f3043 100644
> --- a/tools/perf/util/evlist.h
> +++ b/tools/perf/util/evlist.h
> @@ -447,4 +447,6 @@ struct evsel *evlist__find_evsel(struct evlist *evlist, int idx);
>  
>  int evlist__scnprintf_evsels(struct evlist *evlist, size_t size, char *bf);
>  void evlist__check_mem_load_aux(struct evlist *evlist);
> +void evlist__warn_user_requested_cpus(struct evlist *evlist, const char *cpu_list);
> +
>  #endif /* __PERF_EVLIST_H */
> diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
> index f4f0afbc391c..1e0be23d4dd7 100644
> --- a/tools/perf/util/pmu.c
> +++ b/tools/perf/util/pmu.c
> @@ -2038,39 +2038,6 @@ int perf_pmu__match(char *pattern, char *name, char *tok)
>  	return 0;
>  }
>  
> -int perf_pmu__cpus_match(struct perf_pmu *pmu, struct perf_cpu_map *cpus,
> -			 struct perf_cpu_map **mcpus_ptr,
> -			 struct perf_cpu_map **ucpus_ptr)
> -{
> -	struct perf_cpu_map *pmu_cpus = pmu->cpus;
> -	struct perf_cpu_map *matched_cpus, *unmatched_cpus;
> -	struct perf_cpu cpu;
> -	int i, matched_nr = 0, unmatched_nr = 0;
> -
> -	matched_cpus = perf_cpu_map__default_new();
> -	if (!matched_cpus)
> -		return -1;
> -
> -	unmatched_cpus = perf_cpu_map__default_new();
> -	if (!unmatched_cpus) {
> -		perf_cpu_map__put(matched_cpus);
> -		return -1;
> -	}
> -
> -	perf_cpu_map__for_each_cpu(cpu, i, cpus) {
> -		if (!perf_cpu_map__has(pmu_cpus, cpu))
> -			RC_CHK_ACCESS(unmatched_cpus)->map[unmatched_nr++] = cpu;
> -		else
> -			RC_CHK_ACCESS(matched_cpus)->map[matched_nr++] = cpu;
> -	}
> -
> -	perf_cpu_map__set_nr(unmatched_cpus, unmatched_nr);
> -	perf_cpu_map__set_nr(matched_cpus, matched_nr);
> -	*mcpus_ptr = matched_cpus;
> -	*ucpus_ptr = unmatched_cpus;
> -	return 0;
> -}
> -
>  double __weak perf_pmu__cpu_slots_per_cycle(void)
>  {
>  	return NAN;
> diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
> index 0e0cb6283594..49033bb134f3 100644
> --- a/tools/perf/util/pmu.h
> +++ b/tools/perf/util/pmu.h
> @@ -257,10 +257,6 @@ void perf_pmu__warn_invalid_formats(struct perf_pmu *pmu);
>  bool perf_pmu__has_hybrid(void);
>  int perf_pmu__match(char *pattern, char *name, char *tok);
>  
> -int perf_pmu__cpus_match(struct perf_pmu *pmu, struct perf_cpu_map *cpus,
> -			 struct perf_cpu_map **mcpus_ptr,
> -			 struct perf_cpu_map **ucpus_ptr);
> -
>  char *pmu_find_real_name(const char *name);
>  char *pmu_find_alias_name(const char *name);
>  double perf_pmu__cpu_slots_per_cycle(void);

  reply	other threads:[~2023-05-21 19:04 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-17 14:57 [PATCH v1 00/23] PMU refactoring and improvements Ian Rogers
2023-05-17 14:57 ` [PATCH v1 01/23] perf tools: Warn if no user requested CPUs match PMU's CPUs Ian Rogers
2023-05-21 19:04   ` Liang, Kan [this message]
2023-05-22  4:52     ` Ian Rogers
2023-05-22 11:33       ` Liang, Kan
2023-05-17 14:57 ` [PATCH v1 02/23] perf evlist: Remove evlist__warn_hybrid_group Ian Rogers
2023-05-17 14:57 ` [PATCH v1 03/23] perf evlist: Remove __evlist__add_default Ian Rogers
2023-05-21 19:12   ` Liang, Kan
2023-05-22  5:12     ` Ian Rogers
2023-05-17 14:57 ` [PATCH v1 04/23] perf evlist: Reduce scope of evlist__has_hybrid Ian Rogers
2023-05-17 14:57 ` [PATCH v1 05/23] perf pmu: Remove perf_pmu__hybrid_mounted Ian Rogers
2023-05-21 19:23   ` Liang, Kan
2023-05-22  5:21     ` Ian Rogers
2023-05-22 11:55       ` Liang, Kan
2023-05-22 14:06         ` Ian Rogers
2023-05-23 17:23           ` Liang, Kan
2023-05-23 17:45             ` Ian Rogers
2023-05-17 14:57 ` [PATCH v1 06/23] perf pmu: Detect ARM and hybrid PMUs with sysfs Ian Rogers
2023-05-17 14:57 ` [PATCH v1 07/23] perf pmu: Add is_core to pmu Ian Rogers
2023-05-17 14:57 ` [PATCH v1 08/23] perf pmu: Rewrite perf_pmu__has_hybrid to avoid list Ian Rogers
2023-05-17 14:57 ` [PATCH v1 09/23] perf x86: Iterate hybrid PMUs as core PMUs Ian Rogers
2023-05-17 14:57 ` [PATCH v1 10/23] perf topology: Avoid hybrid list for hybrid topology Ian Rogers
2023-05-17 14:57 ` [PATCH v1 11/23] perf evsel: Compute is_hybrid from PMU being core Ian Rogers
2023-05-17 14:57 ` [PATCH v1 12/23] perf header: Avoid hybrid PMU list in write_pmu_caps Ian Rogers
2023-05-17 14:57 ` [PATCH v1 13/23] perf metrics: Remove perf_pmu__is_hybrid use Ian Rogers
2023-05-17 14:57 ` [PATCH v1 14/23] perf stat: Avoid hybrid PMU list Ian Rogers
2023-05-17 14:57 ` [PATCH v1 15/23] perf mem: " Ian Rogers
2023-05-17 14:57 ` [PATCH v1 16/23] perf pmu: Remove perf_pmu__hybrid_pmus list Ian Rogers
2023-05-17 14:57 ` [PATCH v1 17/23] perf pmus: Prefer perf_pmu__scan over perf_pmus__for_each_pmu Ian Rogers
2023-05-21 19:43   ` Liang, Kan
2023-05-17 14:57 ` [PATCH v1 18/23] perf x86 mem: minor refactor to is_mem_loads_aux_event Ian Rogers
2023-05-21 19:47   ` Liang, Kan
2023-05-17 14:57 ` [PATCH v1 19/23] perf pmu: Separate pmu and pmus Ian Rogers
2023-05-17 14:58 ` [PATCH v1 20/23] perf pmus: Split pmus list into core and uncore Ian Rogers
2023-05-21 20:02   ` Liang, Kan
2023-05-22  5:30     ` Ian Rogers
2023-05-17 14:58 ` [PATCH v1 21/23] perf pmus: Allow just core PMU scanning Ian Rogers
2023-05-17 14:58 ` [PATCH v1 22/23] perf pmus: Avoid repeated sysfs scanning Ian Rogers
2023-05-17 14:58 ` [PATCH v1 23/23] perf pmus: Ensure all PMUs are read for find_by_type Ian Rogers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3586d413-b7c9-9790-ec4e-4132502c806d@linux.intel.com \
    --to=kan.liang@linux.intel.com \
    --cc=9erthalion6@gmail.com \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=alisaidi@amazon.com \
    --cc=atrajeev@linux.vnet.ibm.com \
    --cc=chenhuacai@kernel.org \
    --cc=coresight@lists.linaro.org \
    --cc=irogers@google.com \
    --cc=james.clark@arm.com \
    --cc=john.g.garry@oracle.com \
    --cc=jolsa@kernel.org \
    --cc=kjain@linux.ibm.com \
    --cc=leo.yan@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=maddy@linux.ibm.com \
    --cc=mark.rutland@arm.com \
    --cc=mike.leach@linaro.org \
    --cc=mingo@redhat.com \
    --cc=namhyung@kernel.org \
    --cc=peterz@infradead.org \
    --cc=ravi.bangoria@amd.com \
    --cc=renyu.zj@linux.alibaba.com \
    --cc=robh@kernel.org \
    --cc=rsilvera@google.com \
    --cc=sandipan.das@amd.com \
    --cc=seanjc@google.com \
    --cc=suzuki.poulose@arm.com \
    --cc=tegongkang@gmail.com \
    --cc=tmricht@linux.ibm.com \
    --cc=wangming01@loongson.cn \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).