All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jiri Olsa <jolsa@redhat.com>
To: Jin Yao <yao.jin@linux.intel.com>
Cc: acme@kernel.org, jolsa@kernel.org, peterz@infradead.org,
	mingo@redhat.com, alexander.shishkin@linux.intel.com,
	Linux-kernel@vger.kernel.org, ak@linux.intel.com,
	kan.liang@intel.com, yao.jin@intel.com
Subject: Re: [PATCH v2 07/27] perf evlist: Hybrid event uses its own cpus
Date: Fri, 12 Mar 2021 20:15:14 +0100	[thread overview]
Message-ID: <YEu9wl4FcF+AoRTy@krava> (raw)
In-Reply-To: <20210311070742.9318-8-yao.jin@linux.intel.com>

On Thu, Mar 11, 2021 at 03:07:22PM +0800, Jin Yao wrote:
> On hybrid platform, atom events can be only enabled on atom CPUs. Core
> events can be only enabled on core CPUs. So for a hybrid event, it can
> be only enabled on it's own CPUs.
> 
> But the problem for current perf is, the cpus for evsel (via PMU sysfs)
> have been merged to evsel_list->core.all_cpus. It might be all CPUs.
> 
> So we need to figure out one way to let the hybrid event only use it's
> own CPUs.
> 
> The idea is to create a new evlist__invalidate_all_cpus to invalidate
> the evsel_list->core.all_cpus then evlist__for_each_cpu returns cpu -1
> for hybrid evsel. If cpu is -1, hybrid evsel will use it's own cpus.

that's wild.. I don't understand when you say we don't have
cpus for evsel, because they have been merged.. each evsel
has evsel->core.own_cpus coming from pmu->cpus, right?

why can't you just filter out cpus that are in there?

jirka

> 
> We will see following code piece in patch.
> 
> if (cpu == -1 && !evlist->thread_mode)
>         evsel__enable_cpus(pos);
> 
> It lets the event be enabled on event's own cpus.
> 
> Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
> ---
>  tools/perf/builtin-stat.c          | 37 ++++++++++++++-
>  tools/perf/util/evlist.c           | 72 ++++++++++++++++++++++++++++--
>  tools/perf/util/evlist.h           |  4 ++
>  tools/perf/util/evsel.h            |  8 ++++
>  tools/perf/util/python-ext-sources |  2 +
>  5 files changed, 117 insertions(+), 6 deletions(-)
> 
> diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
> index 2e2e4a8345ea..68ecf68699a9 100644
> --- a/tools/perf/builtin-stat.c
> +++ b/tools/perf/builtin-stat.c
> @@ -393,6 +393,18 @@ static int read_counter_cpu(struct evsel *counter, struct timespec *rs, int cpu)
>  	return 0;
>  }
>  
> +static int read_counter_cpus(struct evsel *counter, struct timespec *rs)
> +{
> +	int cpu, nr_cpus, err = 0;
> +	struct perf_cpu_map *cpus = evsel__cpus(counter);
> +
> +	nr_cpus = cpus ? cpus->nr : 1;
> +	for (cpu = 0; cpu < nr_cpus; cpu++)
> +		err = read_counter_cpu(counter, rs, cpu);
> +
> +	return err;
> +}
> +
>  static int read_affinity_counters(struct timespec *rs)
>  {
>  	struct evsel *counter;
> @@ -414,8 +426,14 @@ static int read_affinity_counters(struct timespec *rs)
>  			if (evsel__cpu_iter_skip(counter, cpu))
>  				continue;
>  			if (!counter->err) {
> -				counter->err = read_counter_cpu(counter, rs,
> -								counter->cpu_iter - 1);
> +				if (cpu == -1 && !evsel_list->thread_mode) {
> +					counter->err = read_counter_cpus(counter, rs);
> +				} else if (evsel_list->thread_mode) {
> +					counter->err = read_counter_cpu(counter, rs, 0);
> +				} else {
> +					counter->err = read_counter_cpu(counter, rs,
> +									counter->cpu_iter - 1);
> +				}
>  			}
>  		}
>  	}
> @@ -781,6 +799,21 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
>  	if (group)
>  		evlist__set_leader(evsel_list);
>  
> +	/*
> +	 * On hybrid platform, the cpus for evsel (via PMU sysfs) have been
> +	 * merged to evsel_list->core.all_cpus. We use evlist__invalidate_all_cpus
> +	 * to invalidate the evsel_list->core.all_cpus then evlist__for_each_cpu
> +	 * returns cpu -1 for hybrid evsel. If cpu is -1, hybrid evsel will
> +	 * use it's own cpus.
> +	 */
> +	if (evlist__has_hybrid_events(evsel_list)) {
> +		evlist__invalidate_all_cpus(evsel_list);
> +		if (!target__has_cpu(&target) ||
> +		    target__has_per_thread(&target)) {
> +			evsel_list->thread_mode = true;
> +		}
> +	}
> +
>  	if (affinity__setup(&affinity) < 0)
>  		return -1;
>  
> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
> index 882cd1f721d9..3ee12fcd0c9f 100644
> --- a/tools/perf/util/evlist.c
> +++ b/tools/perf/util/evlist.c
> @@ -381,7 +381,8 @@ bool evsel__cpu_iter_skip_no_inc(struct evsel *ev, int cpu)
>  bool evsel__cpu_iter_skip(struct evsel *ev, int cpu)
>  {
>  	if (!evsel__cpu_iter_skip_no_inc(ev, cpu)) {
> -		ev->cpu_iter++;
> +		if (cpu != -1)
> +			ev->cpu_iter++;
>  		return false;
>  	}
>  	return true;
> @@ -410,6 +411,16 @@ static int evlist__is_enabled(struct evlist *evlist)
>  	return false;
>  }
>  
> +static void evsel__disable_cpus(struct evsel *evsel)
> +{
> +	int cpu, nr_cpus;
> +	struct perf_cpu_map *cpus = evsel__cpus(evsel);
> +
> +	nr_cpus = cpus ? cpus->nr : 1;
> +	for (cpu = 0; cpu < nr_cpus; cpu++)
> +		evsel__disable_cpu(evsel, cpu);
> +}
> +
>  static void __evlist__disable(struct evlist *evlist, char *evsel_name)
>  {
>  	struct evsel *pos;
> @@ -436,7 +447,12 @@ static void __evlist__disable(struct evlist *evlist, char *evsel_name)
>  					has_imm = true;
>  				if (pos->immediate != imm)
>  					continue;
> -				evsel__disable_cpu(pos, pos->cpu_iter - 1);
> +				if (cpu == -1 && !evlist->thread_mode)
> +					evsel__disable_cpus(pos);
> +				else if (evlist->thread_mode)
> +					evsel__disable_cpu(pos, 0);
> +				else
> +					evsel__disable_cpu(pos, pos->cpu_iter - 1);
>  			}
>  		}
>  		if (!has_imm)
> @@ -472,6 +488,15 @@ void evlist__disable_evsel(struct evlist *evlist, char *evsel_name)
>  	__evlist__disable(evlist, evsel_name);
>  }
>  
> +static void evsel__enable_cpus(struct evsel *evsel)
> +{
> +	int cpu, nr_cpus;
> +	struct perf_cpu_map *cpus = evsel__cpus(evsel);
> +
> +	nr_cpus = cpus ? cpus->nr : 1;
> +	for (cpu = 0; cpu < nr_cpus; cpu++)
> +		evsel__enable_cpu(evsel, cpu);
> +}
>  static void __evlist__enable(struct evlist *evlist, char *evsel_name)
>  {
>  	struct evsel *pos;
> @@ -491,7 +516,12 @@ static void __evlist__enable(struct evlist *evlist, char *evsel_name)
>  				continue;
>  			if (!evsel__is_group_leader(pos) || !pos->core.fd)
>  				continue;
> -			evsel__enable_cpu(pos, pos->cpu_iter - 1);
> +                        if (cpu == -1 && !evlist->thread_mode)
> +                                evsel__enable_cpus(pos);
> +                        else if (evlist->thread_mode)
> +                                evsel__enable_cpu(pos, 0);
> +                        else
> +                                evsel__enable_cpu(pos, pos->cpu_iter - 1);
>  		}
>  	}
>  	affinity__cleanup(&affinity);
> @@ -1274,6 +1304,16 @@ void evlist__set_selected(struct evlist *evlist, struct evsel *evsel)
>  	evlist->selected = evsel;
>  }
>  
> +static void evsel__close_cpus(struct evsel *evsel)
> +{
> +	int cpu, nr_cpus;
> +	struct perf_cpu_map *cpus = evsel__cpus(evsel);
> +
> +	nr_cpus = cpus ? cpus->nr : 1;
> +	for (cpu = 0; cpu < nr_cpus; cpu++)
> +		perf_evsel__close_cpu(&evsel->core, cpu);
> +}
> +
>  void evlist__close(struct evlist *evlist)
>  {
>  	struct evsel *evsel;
> @@ -1298,7 +1338,13 @@ void evlist__close(struct evlist *evlist)
>  		evlist__for_each_entry_reverse(evlist, evsel) {
>  			if (evsel__cpu_iter_skip(evsel, cpu))
>  			    continue;
> -			perf_evsel__close_cpu(&evsel->core, evsel->cpu_iter - 1);
> +
> +			if (cpu == -1 && !evlist->thread_mode)
> +				evsel__close_cpus(evsel);
> +			else if (evlist->thread_mode)
> +				perf_evsel__close_cpu(&evsel->core, 0);
> +			else
> +				perf_evsel__close_cpu(&evsel->core, evsel->cpu_iter - 1);
>  		}
>  	}
>  	affinity__cleanup(&affinity);
> @@ -2130,3 +2176,21 @@ struct evsel *evlist__find_evsel(struct evlist *evlist, int idx)
>  	}
>  	return NULL;
>  }
> +
> +bool evlist__has_hybrid_events(struct evlist *evlist)
> +{
> +	struct evsel *evsel;
> +
> +	evlist__for_each_entry(evlist, evsel) {
> +		if (evsel__is_hybrid_event(evsel))
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
> +void evlist__invalidate_all_cpus(struct evlist *evlist)
> +{
> +	perf_cpu_map__put(evlist->core.all_cpus);
> +	evlist->core.all_cpus = perf_cpu_map__empty_new(1);
> +}
> diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
> index b695ffaae519..0da683511d98 100644
> --- a/tools/perf/util/evlist.h
> +++ b/tools/perf/util/evlist.h
> @@ -52,6 +52,7 @@ struct evlist {
>  	struct perf_evlist core;
>  	int		 nr_groups;
>  	bool		 enabled;
> +	bool		 thread_mode;
>  	int		 id_pos;
>  	int		 is_pos;
>  	u64		 combined_sample_type;
> @@ -365,4 +366,7 @@ int evlist__ctlfd_ack(struct evlist *evlist);
>  #define EVLIST_DISABLED_MSG "Events disabled\n"
>  
>  struct evsel *evlist__find_evsel(struct evlist *evlist, int idx);
> +void evlist__invalidate_all_cpus(struct evlist *evlist);
> +
> +bool evlist__has_hybrid_events(struct evlist *evlist);
>  #endif /* __PERF_EVLIST_H */
> diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
> index 6026487353dd..69aadc52c1bd 100644
> --- a/tools/perf/util/evsel.h
> +++ b/tools/perf/util/evsel.h
> @@ -7,9 +7,11 @@
>  #include <sys/types.h>
>  #include <linux/perf_event.h>
>  #include <linux/types.h>
> +#include <string.h>
>  #include <internal/evsel.h>
>  #include <perf/evsel.h>
>  #include "symbol_conf.h"
> +#include "pmu-hybrid.h"
>  #include <internal/cpumap.h>
>  
>  struct bpf_object;
> @@ -435,4 +437,10 @@ struct perf_env *evsel__env(struct evsel *evsel);
>  int evsel__store_ids(struct evsel *evsel, struct evlist *evlist);
>  
>  void evsel__zero_per_pkg(struct evsel *evsel);
> +
> +static inline bool evsel__is_hybrid_event(struct evsel *evsel)
> +{
> +	return evsel->pmu_name && perf_pmu__is_hybrid(evsel->pmu_name);
> +}
> +
>  #endif /* __PERF_EVSEL_H */
> diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
> index 845dd46e3c61..d7c976671e3a 100644
> --- a/tools/perf/util/python-ext-sources
> +++ b/tools/perf/util/python-ext-sources
> @@ -37,3 +37,5 @@ util/units.c
>  util/affinity.c
>  util/rwsem.c
>  util/hashmap.c
> +util/pmu-hybrid.c
> +util/fncache.c
> -- 
> 2.17.1
> 


  reply	other threads:[~2021-03-12 19:16 UTC|newest]

Thread overview: 59+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-11  7:07 [PATCH v2 00/27] perf tool: AlderLake hybrid support series 1 Jin Yao
2021-03-11  7:07 ` [PATCH v2 01/27] tools headers uapi: Update tools's copy of linux/perf_event.h Jin Yao
2021-03-11  7:07 ` [PATCH v2 02/27] perf jevents: Support unit value "cpu_core" and "cpu_atom" Jin Yao
2021-03-11  7:07 ` [PATCH v2 03/27] perf pmu: Simplify arguments of __perf_pmu__new_alias Jin Yao
2021-03-11  7:07 ` [PATCH v2 04/27] perf pmu: Save pmu name Jin Yao
2021-03-15 23:03   ` Jiri Olsa
2021-03-16  0:59     ` Jin, Yao
2021-03-11  7:07 ` [PATCH v2 05/27] perf pmu: Save detected hybrid pmus to a global pmu list Jin Yao
2021-03-11  7:07 ` [PATCH v2 06/27] perf pmu: Add hybrid helper functions Jin Yao
2021-03-11  7:07 ` [PATCH v2 07/27] perf evlist: Hybrid event uses its own cpus Jin Yao
2021-03-12 19:15   ` Jiri Olsa [this message]
2021-03-15  1:25     ` Jin, Yao
2021-03-11  7:07 ` [PATCH v2 08/27] perf stat: Uniquify hybrid event name Jin Yao
2021-03-15 23:04   ` Jiri Olsa
2021-03-11  7:07 ` [PATCH v2 09/27] perf parse-events: Create two hybrid hardware events Jin Yao
2021-03-12 19:15   ` Jiri Olsa
2021-03-15  2:04     ` Jin, Yao
2021-03-15 17:34       ` Jiri Olsa
2021-03-15 23:05   ` Jiri Olsa
2021-03-16  3:13     ` Jin, Yao
2021-03-11  7:07 ` [PATCH v2 10/27] perf parse-events: Create two hybrid cache events Jin Yao
2021-03-15 23:05   ` Jiri Olsa
2021-03-16  3:51     ` Jin, Yao
2021-03-11  7:07 ` [PATCH v2 11/27] perf parse-events: Support hardware events inside PMU Jin Yao
2021-03-12 19:15   ` Jiri Olsa
2021-03-15  2:28     ` Jin, Yao
2021-03-15 17:37       ` Jiri Olsa
2021-03-16  1:49         ` Jin, Yao
2021-03-16 14:04           ` Jiri Olsa
2021-03-17  2:12             ` Jin, Yao
2021-03-17 10:06               ` Jiri Olsa
2021-03-17 12:17                 ` Jin, Yao
2021-03-17 13:42                   ` Arnaldo Carvalho de Melo
2021-03-18 12:16                     ` Jiri Olsa
2021-03-18 13:21                       ` Arnaldo Carvalho de Melo
2021-03-18 18:16                         ` Liang, Kan
2021-03-19  2:48                     ` Andi Kleen
2021-03-18 11:51                   ` Jiri Olsa
2021-03-11  7:07 ` [PATCH v2 12/27] perf parse-events: Support hybrid raw events Jin Yao
2021-03-11  7:07 ` [PATCH v2 13/27] perf evlist: Create two hybrid 'cycles' events by default Jin Yao
2021-03-11  7:07 ` [PATCH v2 14/27] perf stat: Add default hybrid events Jin Yao
2021-03-11  7:07 ` [PATCH v2 15/27] perf stat: Filter out unmatched aggregation for hybrid event Jin Yao
2021-03-11  7:07 ` [PATCH v2 16/27] perf evlist: Warn as events from different hybrid PMUs in a group Jin Yao
2021-03-15 23:03   ` Jiri Olsa
2021-03-16  5:25     ` Jin, Yao
2021-03-18 11:52       ` Jiri Olsa
2021-03-11  7:07 ` [PATCH v2 17/27] perf evsel: Adjust hybrid event and global event mixed group Jin Yao
2021-03-15 23:04   ` Jiri Olsa
2021-03-16  4:39     ` Jin, Yao
2021-03-11  7:07 ` [PATCH v2 18/27] perf script: Support PERF_TYPE_HARDWARE_PMU and PERF_TYPE_HW_CACHE_PMU Jin Yao
2021-03-11  7:07 ` [PATCH v2 19/27] perf tests: Add hybrid cases for 'Parse event definition strings' test Jin Yao
2021-03-11  7:07 ` [PATCH v2 20/27] perf tests: Add hybrid cases for 'Roundtrip evsel->name' test Jin Yao
2021-03-11  7:07 ` [PATCH v2 21/27] perf tests: Skip 'Setup struct perf_event_attr' test for hybrid Jin Yao
2021-03-11  7:07 ` [PATCH v2 22/27] perf tests: Support 'Track with sched_switch' " Jin Yao
2021-03-11  7:07 ` [PATCH v2 23/27] perf tests: Support 'Parse and process metrics' " Jin Yao
2021-03-11  7:07 ` [PATCH v2 24/27] perf tests: Support 'Session topology' " Jin Yao
2021-03-11  7:07 ` [PATCH v2 25/27] perf tests: Support 'Convert perf time to TSC' " Jin Yao
2021-03-11  7:07 ` [PATCH v2 26/27] perf tests: Skip 'perf stat metrics (shadow stat) test' " Jin Yao
2021-03-11  7:07 ` [PATCH v2 27/27] perf Documentation: Document intel-hybrid support Jin Yao

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=YEu9wl4FcF+AoRTy@krava \
    --to=jolsa@redhat.com \
    --cc=Linux-kernel@vger.kernel.org \
    --cc=acme@kernel.org \
    --cc=ak@linux.intel.com \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=jolsa@kernel.org \
    --cc=kan.liang@intel.com \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=yao.jin@intel.com \
    --cc=yao.jin@linux.intel.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.