All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jin Yao <yao.jin@linux.intel.com>
To: acme@kernel.org, jolsa@kernel.org, peterz@infradead.org,
	mingo@redhat.com, alexander.shishkin@linux.intel.com
Cc: Linux-kernel@vger.kernel.org, ak@linux.intel.com,
	kan.liang@intel.com, yao.jin@intel.com,
	Jin Yao <yao.jin@linux.intel.com>
Subject: [PATCH v2 11/27] perf parse-events: Support hardware events inside PMU
Date: Thu, 11 Mar 2021 15:07:26 +0800	[thread overview]
Message-ID: <20210311070742.9318-12-yao.jin@linux.intel.com> (raw)
In-Reply-To: <20210311070742.9318-1-yao.jin@linux.intel.com>

On hybrid platform, some hardware events are only available
on a specific pmu. For example, 'L1-dcache-load-misses' is only
available on 'cpu_core' pmu. And even for the event which can be
available on both pmus, the user also may want to just enable
one event. So now following syntax is supported:

cpu_core/<hardware event>/
cpu_core/<hardware cache event>/
cpu_core/<pmu event>/

cpu_atom/<hardware event>/
cpu_atom/<hardware cache event>/
cpu_atom/<pmu event>/

It limits the event to be enabled only on a specified pmu.

The patch uses this idea, for example, if we use "cpu_core/LLC-loads/",
in parse_events_add_pmu(), term->config is "LLC-loads".

We create a new "parse_events_state" with the pmu_name and use
parse_events__scanner to scan the term->config (the string "LLC-loads"
in this example). The parse_events_add_cache() will be called during
parsing. The parse_state->pmu_name is used to identify the pmu
where the event is enabled.

Let's see examples:

  root@ssp-pwrt-002:~# ./perf stat -e cpu_core/cycles/,cpu_core/LLC-loads/ -vv -- ./triad_loop
  Control descriptor is not initialized
  ------------------------------------------------------------
  perf_event_attr:
    type                             6
    size                             120
    config                           0x400000000
    sample_type                      IDENTIFIER
    read_format                      TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING
    disabled                         1
    inherit                          1
    enable_on_exec                   1
    exclude_guest                    1
  ------------------------------------------------------------
  sys_perf_event_open: pid 7267  cpu -1  group_fd -1  flags 0x8 = 3
  ------------------------------------------------------------
  perf_event_attr:
    type                             7
    size                             120
    config                           0x400000002
    sample_type                      IDENTIFIER
    read_format                      TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING
    disabled                         1
    inherit                          1
    enable_on_exec                   1
    exclude_guest                    1
  ------------------------------------------------------------
  sys_perf_event_open: pid 7267  cpu -1  group_fd -1  flags 0x8 = 4
  cycles: 0: 449252097 297999924 297999924
  LLC-loads: 0: 1857 297999924 297999924
  cycles: 449252097 297999924 297999924
  LLC-loads: 1857 297999924 297999924

   Performance counter stats for './triad_loop':

         449,252,097      cpu_core/cycles/
               1,857      cpu_core/LLC-loads/

         0.298898415 seconds time elapsed

  root@ssp-pwrt-002:~# ./perf stat -e cpu_atom/cycles/,cpu_atom/LLC-loads/ -vv -- taskset -c 16 ./triad_loop
  Control descriptor is not initialized
  ------------------------------------------------------------
  perf_event_attr:
    type                             6
    size                             120
    config                           0xa00000000
    sample_type                      IDENTIFIER
    read_format                      TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING
    disabled                         1
    inherit                          1
    enable_on_exec                   1
    exclude_guest                    1
  ------------------------------------------------------------
  sys_perf_event_open: pid 7339  cpu -1  group_fd -1  flags 0x8 = 3
  ------------------------------------------------------------
  perf_event_attr:
    type                             7
    size                             120
    config                           0xa00000002
    sample_type                      IDENTIFIER
    read_format                      TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING
    disabled                         1
    inherit                          1
    enable_on_exec                   1
    exclude_guest                    1
  ------------------------------------------------------------
  sys_perf_event_open: pid 7339  cpu -1  group_fd -1  flags 0x8 = 4
  cycles: 0: 602020010 343657939 342553275
  LLC-loads: 0: 3537 343657939 342553275
  cycles: 603961400 343657939 342553275
  LLC-loads: 3548 343657939 342553275

   Performance counter stats for 'taskset -c 16 ./triad_loop':

         603,961,400      cpu_atom/cycles/                                              (99.68%)
               3,548      cpu_atom/LLC-loads/                                           (99.68%)

         0.344904585 seconds time elapsed

Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
---
 tools/perf/util/parse-events.c | 100 +++++++++++++++++++++++++++++++--
 tools/perf/util/parse-events.h |   6 +-
 tools/perf/util/parse-events.y |  21 ++-----
 3 files changed, 105 insertions(+), 22 deletions(-)

diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 09e42245f71a..30435adc7a7b 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -489,7 +489,8 @@ static int create_hybrid_cache_event(struct list_head *list, int *idx,
 static int add_hybrid_cache(struct list_head *list, int *idx,
 			    struct perf_event_attr *attr, char *name,
 			    struct list_head *config_terms,
-			    bool *hybrid)
+			    bool *hybrid,
+			    struct parse_events_state *parse_state)
 {
 	struct perf_pmu *pmu;
 	int ret;
@@ -497,6 +498,11 @@ static int add_hybrid_cache(struct list_head *list, int *idx,
 	*hybrid = false;
 	perf_pmu__for_each_hybrid_pmu(pmu) {
 		*hybrid = true;
+		 if (parse_state->pmu_name &&
+		     strcmp(parse_state->pmu_name, pmu->name)) {
+			continue;
+		}
+
 		ret = create_hybrid_cache_event(list, idx, attr, name,
 						config_terms, pmu);
 		if (ret)
@@ -509,7 +515,8 @@ static int add_hybrid_cache(struct list_head *list, int *idx,
 int parse_events_add_cache(struct list_head *list, int *idx,
 			   char *type, char *op_result1, char *op_result2,
 			   struct parse_events_error *err,
-			   struct list_head *head_config)
+			   struct list_head *head_config,
+			   struct parse_events_state *parse_state)
 {
 	struct perf_event_attr attr;
 	LIST_HEAD(config_terms);
@@ -582,7 +589,7 @@ int parse_events_add_cache(struct list_head *list, int *idx,
 		perf_pmu__scan(NULL);
 
 	ret = add_hybrid_cache(list, idx, &attr, config_name ? : name,
-			       &config_terms, &hybrid);
+			       &config_terms, &hybrid, parse_state);
 	if (hybrid)
 		return ret;
 
@@ -1512,6 +1519,11 @@ static int add_hybrid_numeric(struct parse_events_state *parse_state,
 	*hybrid = false;
 	perf_pmu__for_each_hybrid_pmu(pmu) {
 		*hybrid = true;
+		if (parse_state->pmu_name &&
+		    strcmp(parse_state->pmu_name, pmu->name)) {
+			continue;
+		}
+
 		ret = create_hybrid_hw_event(parse_state, list, attr, pmu);
 		if (ret)
 			return ret;
@@ -1578,6 +1590,10 @@ static bool config_term_percore(struct list_head *config_terms)
 	return false;
 }
 
+static int parse_events_with_hybrid_pmu(struct parse_events_state *parse_state,
+			      const char *str, char *name, bool *found,
+			      struct list_head *list);
+
 int parse_events_add_pmu(struct parse_events_state *parse_state,
 			 struct list_head *list, char *name,
 			 struct list_head *head_config,
@@ -1589,7 +1605,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
 	struct perf_pmu *pmu;
 	struct evsel *evsel;
 	struct parse_events_error *err = parse_state->error;
-	bool use_uncore_alias;
+	bool use_uncore_alias, found;
 	LIST_HEAD(config_terms);
 
 	if (verbose > 1) {
@@ -1605,6 +1621,22 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
 		fprintf(stderr, "' that may result in non-fatal errors\n");
 	}
 
+	if (head_config && perf_pmu__is_hybrid(name)) {
+		struct parse_events_term *term;
+		int ret;
+
+		list_for_each_entry(term, head_config, list) {
+			if (!term->config)
+				continue;
+			ret = parse_events_with_hybrid_pmu(parse_state,
+							   term->config,
+							   name, &found,
+							   list);
+			if (found)
+				return ret;
+		}
+	}
+
 	pmu = parse_state->fake_pmu ?: perf_pmu__find(name);
 	if (!pmu) {
 		char *err_str;
@@ -1713,12 +1745,19 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
 	struct perf_pmu *pmu = NULL;
 	int ok = 0;
 
+        if (parse_state->pmu_name) {
+                list = alloc_list();
+                if (!list)
+                        return -1;
+                *listp = list;
+                return 0;
+        }
+
 	*listp = NULL;
 	/* Add it for all PMUs that support the alias */
-	list = malloc(sizeof(struct list_head));
+	list = alloc_list();
 	if (!list)
 		return -1;
-	INIT_LIST_HEAD(list);
 	while ((pmu = perf_pmu__scan(pmu)) != NULL) {
 		struct perf_pmu_alias *alias;
 
@@ -2284,6 +2323,44 @@ int parse_events_terms(struct list_head *terms, const char *str)
 	return ret;
 }
 
+static int list_num(struct list_head *list)
+{
+	struct list_head *pos;
+	int n = 0;
+
+	list_for_each(pos, list)
+		n++;
+
+	return n;
+}
+
+static int parse_events_with_hybrid_pmu(struct parse_events_state *parse_state,
+					const char *str, char *pmu_name,
+					bool *found, struct list_head *list)
+{
+	struct parse_events_state ps = {
+		.list		= LIST_HEAD_INIT(ps.list),
+		.stoken		= PE_START_EVENTS,
+		.pmu_name	= pmu_name,
+		.idx		= parse_state->idx,
+	};
+	int ret;
+
+	*found = false;
+	ret = parse_events__scanner(str, &ps);
+	perf_pmu__parse_cleanup();
+
+	if (!ret) {
+		if (!list_empty(&ps.list)) {
+			*found = true;
+			list_splice(&ps.list, list);
+			parse_state->idx = list_num(list);
+		}
+	}
+
+	return ret;
+}
+
 int __parse_events(struct evlist *evlist, const char *str,
 		   struct parse_events_error *err, struct perf_pmu *fake_pmu)
 {
@@ -3307,3 +3384,14 @@ char *parse_events_formats_error_string(char *additional_terms)
 fail:
 	return NULL;
 }
+
+struct list_head *alloc_list(void)
+{
+	struct list_head *list = malloc(sizeof(*list));
+
+	if (!list)
+		return NULL;
+
+	INIT_LIST_HEAD(list);
+	return list;
+}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index e80c9b74f2f2..39c7121a4659 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -138,6 +138,7 @@ struct parse_events_state {
 	struct list_head	  *terms;
 	int			   stoken;
 	struct perf_pmu		  *fake_pmu;
+	char			  *pmu_name;
 };
 
 void parse_events__handle_error(struct parse_events_error *err, int idx,
@@ -188,7 +189,8 @@ int parse_events_add_tool(struct parse_events_state *parse_state,
 int parse_events_add_cache(struct list_head *list, int *idx,
 			   char *type, char *op_result1, char *op_result2,
 			   struct parse_events_error *error,
-			   struct list_head *head_config);
+			   struct list_head *head_config,
+			   struct parse_events_state *parse_state);
 int parse_events_add_breakpoint(struct list_head *list, int *idx,
 				u64 addr, char *type, u64 len);
 int parse_events_add_pmu(struct parse_events_state *parse_state,
@@ -242,6 +244,8 @@ char *parse_events_formats_error_string(char *additional_terms);
 void parse_events_print_error(struct parse_events_error *err,
 			      const char *event);
 
+struct list_head *alloc_list(void);
+
 #ifdef HAVE_LIBELF_SUPPORT
 /*
  * If the probe point starts with '%',
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index d57ac86ce7ca..e0e68c3da9e4 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -26,18 +26,6 @@ do { \
 		YYABORT; \
 } while (0)
 
-static struct list_head* alloc_list(void)
-{
-	struct list_head *list;
-
-	list = malloc(sizeof(*list));
-	if (!list)
-		return NULL;
-
-	INIT_LIST_HEAD(list);
-	return list;
-}
-
 static void free_list_evsel(struct list_head* list_evsel)
 {
 	struct evsel *evsel, *tmp;
@@ -454,7 +442,8 @@ PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT opt_e
 
 	list = alloc_list();
 	ABORT_ON(!list);
-	err = parse_events_add_cache(list, &parse_state->idx, $1, $3, $5, error, $6);
+	err = parse_events_add_cache(list, &parse_state->idx, $1, $3, $5, error, $6,
+				parse_state);
 	parse_events_terms__delete($6);
 	free($1);
 	free($3);
@@ -475,7 +464,8 @@ PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT opt_event_config
 
 	list = alloc_list();
 	ABORT_ON(!list);
-	err = parse_events_add_cache(list, &parse_state->idx, $1, $3, NULL, error, $4);
+	err = parse_events_add_cache(list, &parse_state->idx, $1, $3, NULL, error, $4,
+				parse_state);
 	parse_events_terms__delete($4);
 	free($1);
 	free($3);
@@ -495,7 +485,8 @@ PE_NAME_CACHE_TYPE opt_event_config
 
 	list = alloc_list();
 	ABORT_ON(!list);
-	err = parse_events_add_cache(list, &parse_state->idx, $1, NULL, NULL, error, $2);
+	err = parse_events_add_cache(list, &parse_state->idx, $1, NULL, NULL, error, $2,
+				parse_state);
 	parse_events_terms__delete($2);
 	free($1);
 	if (err) {
-- 
2.17.1


  parent reply	other threads:[~2021-03-11  7:09 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
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 ` Jin Yao [this message]
2021-03-12 19:15   ` [PATCH v2 11/27] perf parse-events: Support hardware events inside PMU 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=20210311070742.9318-12-yao.jin@linux.intel.com \
    --to=yao.jin@linux.intel.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 \
    /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.