All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V9 0/6] Freq/CPU%/CORE_BUSY% support
@ 2015-09-08 19:32 kan.liang
  2015-09-08 19:32 ` [PATCH V9 1/6] perf,tools: introduce generic FEAT for CPU attributes kan.liang
                   ` (6 more replies)
  0 siblings, 7 replies; 17+ messages in thread
From: kan.liang @ 2015-09-08 19:32 UTC (permalink / raw)
  To: acme, jolsa
  Cc: a.p.zijlstra, luto, mingo, eranian, ak, mark.rutland,
	adrian.hunter, namhyung, linux-kernel, Kan Liang

From: Kan Liang <kan.liang@intel.com>

This patch set supports per-sample freq/CPU%/CORE_BUSY% print in perf
report.
For printing these information, the perf.data file must have been obtained
by group read and using special events cycles, ref-cycles, msr/tsc/,
msr/aperf/ or msr/mperf/.

 - Freq (MHz): The frequency during the sample interval. Needs cycles
   ref-cycles event.
 - CPU%: CPU utilization during the sample interval. Needs ref-cycles and
   msr/tsc/ events.
 - CORE_BUSY%: actual percent performance (APERF/MPERF%) during the
   sample interval. Needs msr/aperf/ and msr/mperf/ events.

Here is an example:

$ perf record --freq-perf ~/tchain_edit

$ perf report --stdio --freq-perf

                                 Overhead   FREQ MHz   CPU%  CORE_BUSY%
Command      Shared Object     Symbol
 ........................................  .........  .....  ..........
...........  ................  ......................

    99.54%  99.54%  99.53%  99.53%  99.53%       2301     96         99
tchain_edit  tchain_edit       [.] f3
     0.20%   0.20%   0.20%   0.20%   0.20%       2301     98         99
tchain_edit  tchain_edit       [.] f2
     0.05%   0.05%   0.05%   0.05%   0.05%       2300     98         99
tchain_edit  [kernel.vmlinux]  [k] read_tsc

Changes since V1:
 - Save cpu max freq to header when recording
 - Read cpu max freq and msr type from header when reporting

Changes since V2:
 - Introduce generic FEAT for CPU related data stored
 - Make cpu max freq and msr type part of perf_session_env
 - rename cpu_u to cpu_util
 - Don't save sample value in perf_sample and discards new iterator.
   Calculating the freq_perf_info in add_entry_cb callback
 - Introduce symbol_conf.freq_perf_type for related hpp column visibility

Changes since V3:
 - add a identifier 'tag' for CPU attributes, max frequency.
 - add backpointers to evlist for env, and evsel for evlist.
 - Use bitmask for freq_perf_type
 - Replace macros by functions to caculate freq, cpu_util and core_busy
 - Move all caculation codes under symbol_conf.show_freq_perf condition.

Changes since V4:
 - Store cpu attributes id as tag and more readable cpu_attr

Changes since V5:
 - Rename freq to max_freq and use it
 - Add a loop in process_cpu_attributes to facility future extension

Changes since V6:
 - Split rename perf_session_env and add backpointer to evlist patches

Changes since V7:
 - Introduce --freq-perf option for perf record
 - Factor out fix for dump_sample

Changes since V8:
 - Rename --show-freq-perf to --freq-perf 
 - --freq-perf option imply --group

Kan Liang (6):
  perf,tools: introduce generic FEAT for CPU attributes
  perf,tools: read msr pmu type from header.
  perf, record: introduce --freq-perf option
  perf,tools: Dump per-sample freq/CPU%/CORE_BUSY% in report -D
  perf,tools: caculate and save freq/CPU%/CORE_BUSY% in he_stat
  perf,tools: Show freq/CPU%/CORE_BUSY% in perf report by --freq-perf

 tools/perf/Documentation/perf-record.txt |  4 ++
 tools/perf/Documentation/perf-report.txt | 12 ++++++
 tools/perf/builtin-record.c              | 39 +++++++++++++++++-
 tools/perf/builtin-report.c              | 59 ++++++++++++++++++++++++++
 tools/perf/ui/hist.c                     | 71 +++++++++++++++++++++++++++++---
 tools/perf/util/cpumap.c                 | 32 ++++++++++++++
 tools/perf/util/cpumap.h                 |  1 +
 tools/perf/util/header.c                 | 62 ++++++++++++++++++++++++++++
 tools/perf/util/header.h                 | 13 ++++++
 tools/perf/util/hist.h                   |  3 ++
 tools/perf/util/session.c                | 31 ++++++++++++--
 tools/perf/util/session.h                | 64 ++++++++++++++++++++++++++++
 tools/perf/util/sort.c                   |  3 ++
 tools/perf/util/sort.h                   |  3 ++
 tools/perf/util/symbol.h                 | 12 +++++-
 15 files changed, 399 insertions(+), 10 deletions(-)

-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH V9 1/6] perf,tools: introduce generic FEAT for CPU attributes
  2015-09-08 19:32 [PATCH V9 0/6] Freq/CPU%/CORE_BUSY% support kan.liang
@ 2015-09-08 19:32 ` kan.liang
  2015-09-10 13:58   ` Arnaldo Carvalho de Melo
  2015-09-08 19:32 ` [PATCH V9 2/6] perf,tools: read msr pmu type from header kan.liang
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 17+ messages in thread
From: kan.liang @ 2015-09-08 19:32 UTC (permalink / raw)
  To: acme, jolsa
  Cc: a.p.zijlstra, luto, mingo, eranian, ak, mark.rutland,
	adrian.hunter, namhyung, linux-kernel, Kan Liang

From: Kan Liang <kan.liang@intel.com>

This patch introduces generic FEAT for CPU attributes. For the patch
set, we only need cpu max frequency. But it can be easily extented to
support more other CPU attributes.
The cpu max frequency is from the first online cpu.

Signed-off-by: Kan Liang <kan.liang@intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/cpumap.c | 32 ++++++++++++++++++++++++++
 tools/perf/util/cpumap.h |  1 +
 tools/perf/util/header.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/header.h | 12 ++++++++++
 4 files changed, 104 insertions(+)

diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index a05d76a..671ee83 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -514,3 +514,35 @@ int cpu__setup_cpunode_map(void)
 	closedir(dir1);
 	return 0;
 }
+
+u64 get_cpu_max_freq(void)
+{
+	const char *mnt;
+	char path[PATH_MAX], tmp;
+	FILE *fp;
+	u64 freq;
+	int cpu = 0;
+	int ret;
+
+	mnt = sysfs__mountpoint();
+	if (!mnt)
+		return 0;
+
+	snprintf(path, PATH_MAX, "%s/devices/system/cpu/online", mnt);
+	fp = fopen(path, "r");
+	if (fp) {
+		ret = fscanf(fp, "%u%c", &cpu, &tmp);
+		fclose(fp);
+		if (ret < 1)
+			return 0;
+	}
+
+	snprintf(path, PATH_MAX, "%s/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", mnt, cpu);
+	fp = fopen(path, "r");
+	if (!fp)
+		return 0;
+	ret = fscanf(fp, "%lu", &freq);
+	fclose(fp);
+
+	return (ret == 1) ? freq : 0;
+}
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 8982d53..06cd2c4 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -60,6 +60,7 @@ int max_node_num;
 int *cpunode_map;
 
 int cpu__setup_cpunode_map(void);
+u64 get_cpu_max_freq(void);
 
 static inline int cpu__max_node(void)
 {
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 8fd7b7d..3535dcb 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -885,6 +885,23 @@ write_it:
 	return do_write_string(fd, buffer);
 }
 
+static int write_cpu_attributes(int fd, struct perf_header *h __maybe_unused,
+				struct perf_evlist *evlist __maybe_unused)
+{
+	u32 tag_id;
+	u64 max_freq;
+	int ret;
+
+	tag_id = PERF_HEADER_CPU_MAX_FREQ;
+	ret = do_write(fd, &tag_id, sizeof(tag_id));
+	if (ret < 0)
+		return ret;
+
+	max_freq = get_cpu_max_freq();
+
+	return do_write(fd, &max_freq, sizeof(max_freq));
+}
+
 static int write_branch_stack(int fd __maybe_unused,
 			      struct perf_header *h __maybe_unused,
 		       struct perf_evlist *evlist __maybe_unused)
@@ -1185,6 +1202,11 @@ static void print_cpuid(struct perf_header *ph, int fd __maybe_unused, FILE *fp)
 	fprintf(fp, "# cpuid : %s\n", ph->env.cpuid);
 }
 
+static void print_cpu_attributes(struct perf_header *ph, int fd __maybe_unused, FILE *fp)
+{
+	fprintf(fp, "# CPU attributes: max frequency = %lu KHz\n", ph->env.cpuattr.max_freq);
+}
+
 static void print_branch_stack(struct perf_header *ph __maybe_unused,
 			       int fd __maybe_unused, FILE *fp)
 {
@@ -1498,6 +1520,42 @@ static int process_cpuid(struct perf_file_section *section __maybe_unused,
 	return ph->env.cpuid ? 0 : -ENOMEM;
 }
 
+static int process_cpu_attributes(struct perf_file_section *section __maybe_unused,
+				  struct perf_header *ph, int fd,
+				  void *data __maybe_unused)
+{
+	ssize_t ret;
+	u32 i, tag_id;
+	u64 nr;
+
+	for (i = 0; i < PERF_HEADER_CPU_ATTR_MAX; i++) {
+
+		ret = readn(fd, &tag_id, sizeof(tag_id));
+		if (ret != sizeof(tag_id))
+			return -1;
+
+		if (ph->needs_swap)
+			nr = bswap_32(tag_id);
+
+		if (tag_id >= PERF_HEADER_CPU_ATTR_MAX) {
+			pr_debug("The number of cpu attributes is not expected. "
+				 "You may need to upgrade the perf tool.\n");
+			return -1;
+		}
+
+		ret = readn(fd, &nr, sizeof(nr));
+		if (ret != sizeof(nr))
+			return -1;
+
+		if (ph->needs_swap)
+			nr = bswap_64(nr);
+
+		ph->env.cpu_attr[tag_id] = nr;
+	}
+
+	return 0;
+}
+
 static int process_total_mem(struct perf_file_section *section __maybe_unused,
 			     struct perf_header *ph, int fd,
 			     void *data __maybe_unused)
@@ -1983,6 +2041,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
 	FEAT_OPP(HEADER_PMU_MAPPINGS,	pmu_mappings),
 	FEAT_OPP(HEADER_GROUP_DESC,	group_desc),
 	FEAT_OPP(HEADER_AUXTRACE,	auxtrace),
+	FEAT_OPP(HEADER_CPU_ATTR,	cpu_attributes),
 };
 
 struct header_print_data {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 975d803..dd9f6b0 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -31,6 +31,7 @@ enum {
 	HEADER_PMU_MAPPINGS,
 	HEADER_GROUP_DESC,
 	HEADER_AUXTRACE,
+	HEADER_CPU_ATTR,
 	HEADER_LAST_FEATURE,
 	HEADER_FEAT_BITS	= 256,
 };
@@ -71,6 +72,11 @@ struct cpu_topology_map {
 	int	core_id;
 };
 
+enum perf_header_cpu_attr {
+	PERF_HEADER_CPU_MAX_FREQ	= 0,
+	PERF_HEADER_CPU_ATTR_MAX,
+};
+
 struct perf_env {
 	char			*hostname;
 	char			*os_release;
@@ -95,6 +101,12 @@ struct perf_env {
 	char			*numa_nodes;
 	char			*pmu_mappings;
 	struct cpu_topology_map	*cpu;
+	union  {
+		u64		cpu_attr[PERF_HEADER_CPU_ATTR_MAX];
+		struct {
+			u64	max_freq;
+		} cpuattr;
+	};
 };
 
 struct perf_header {
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH V9 2/6] perf,tools: read msr pmu type from header.
  2015-09-08 19:32 [PATCH V9 0/6] Freq/CPU%/CORE_BUSY% support kan.liang
  2015-09-08 19:32 ` [PATCH V9 1/6] perf,tools: introduce generic FEAT for CPU attributes kan.liang
@ 2015-09-08 19:32 ` kan.liang
  2015-09-10 13:59   ` Arnaldo Carvalho de Melo
  2015-09-14 21:16   ` Arnaldo Carvalho de Melo
  2015-09-08 19:32 ` [PATCH V9 3/6] perf, record: introduce --freq-perf option kan.liang
                   ` (4 subsequent siblings)
  6 siblings, 2 replies; 17+ messages in thread
From: kan.liang @ 2015-09-08 19:32 UTC (permalink / raw)
  To: acme, jolsa
  Cc: a.p.zijlstra, luto, mingo, eranian, ak, mark.rutland,
	adrian.hunter, namhyung, linux-kernel, Kan Liang

From: Kan Liang <kan.liang@intel.com>

Get msr pmu type when processing pmu_mappings

Signed-off-by: Kan Liang <kan.liang@intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/header.c | 3 +++
 tools/perf/util/header.h | 1 +
 2 files changed, 4 insertions(+)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 3535dcb..04f415d 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1879,6 +1879,9 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused
 		/* include a NULL character at the end */
 		strbuf_add(&sb, "", 1);
 
+		if (!strcmp(name, "msr"))
+			ph->env.msr_pmu_type = type;
+
 		free(name);
 		pmu_num--;
 	}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index dd9f6b0..d9034e8 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -107,6 +107,7 @@ struct perf_env {
 			u64	max_freq;
 		} cpuattr;
 	};
+	unsigned int		msr_pmu_type;
 };
 
 struct perf_header {
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH V9 3/6] perf, record: introduce --freq-perf option
  2015-09-08 19:32 [PATCH V9 0/6] Freq/CPU%/CORE_BUSY% support kan.liang
  2015-09-08 19:32 ` [PATCH V9 1/6] perf,tools: introduce generic FEAT for CPU attributes kan.liang
  2015-09-08 19:32 ` [PATCH V9 2/6] perf,tools: read msr pmu type from header kan.liang
@ 2015-09-08 19:32 ` kan.liang
  2015-09-09 14:34   ` Jiri Olsa
  2015-09-14 21:14   ` Arnaldo Carvalho de Melo
  2015-09-08 19:32 ` [PATCH V9 4/6] perf,tools: Dump per-sample freq/CPU%/CORE_BUSY% in report -D kan.liang
                   ` (3 subsequent siblings)
  6 siblings, 2 replies; 17+ messages in thread
From: kan.liang @ 2015-09-08 19:32 UTC (permalink / raw)
  To: acme, jolsa
  Cc: a.p.zijlstra, luto, mingo, eranian, ak, mark.rutland,
	adrian.hunter, namhyung, linux-kernel, Kan Liang

From: Kan Liang <kan.liang@intel.com>

To generate the frequency and performance output, perf must sample read
special events like cycles, ref-cycles, msr/tsc/, msr/aperf/ or
msr/mperf/.
With the --freq-perf option, perf record can automatically check and add
those event into evlist for sampling read.

Signed-off-by: Kan Liang <kan.liang@intel.com>
---
 tools/perf/Documentation/perf-record.txt |  4 ++++
 tools/perf/builtin-record.c              | 39 +++++++++++++++++++++++++++++++-
 tools/perf/util/session.h                | 10 ++++++++
 3 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 2e9ce77..3f40712 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -308,6 +308,10 @@ This option sets the time out limit. The default value is 500 ms.
 Record context switch events i.e. events of type PERF_RECORD_SWITCH or
 PERF_RECORD_SWITCH_CPU_WIDE.
 
+--freq-perf::
+Add frequency and performance related events to do sample read.
+These events include cycles, ref-cycles, msr/tsc/, msr/aperf/ and msr/mperf/.
+
 SEE ALSO
 --------
 linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 142eeb3..e87dda3 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -13,7 +13,7 @@
 #include "util/util.h"
 #include "util/parse-options.h"
 #include "util/parse-events.h"
-
+#include "util/pmu.h"
 #include "util/callchain.h"
 #include "util/cgroup.h"
 #include "util/header.h"
@@ -50,6 +50,7 @@ struct record {
 	bool			no_buildid;
 	bool			no_buildid_cache;
 	long			samples;
+	bool			freq_perf;
 };
 
 static int record__write(struct record *rec, void *bf, size_t size)
@@ -948,6 +949,35 @@ out_free:
 	return ret;
 }
 
+const char *freq_perf_events[FREQ_PERF_MAX][3] = {
+	{ "msr", "tsc", "msr/tsc/" },
+	{ "msr", "aperf", "msr/aperf/" },
+	{ "msr", "mperf", "msr/mperf/" },
+	{ NULL, "cycles", "cycles" },
+	{ NULL, "ref-cycles", "ref-cycles" },
+};
+
+static int
+record_add_freq_perf_events(struct perf_evlist *evlist)
+{
+	int i;
+	char freq_perf_attrs[100];
+
+	strcpy(freq_perf_attrs, "{cycles,ref-cycles");
+	for (i = 0; i < FREQ_PERF_MAX; i++) {
+		if ((i == FREQ_PERF_CYCLES) ||
+		    (i == FREQ_PERF_REF_CYCLES))
+			continue;
+		if (pmu_have_event(freq_perf_events[i][0], freq_perf_events[i][1])) {
+			strcat(freq_perf_attrs, ",");
+			strcat(freq_perf_attrs, freq_perf_events[i][2]);
+		}
+	}
+	strcat(freq_perf_attrs, "}:S");
+
+	return parse_events(evlist, freq_perf_attrs, NULL);
+}
+
 static const char * const __record_usage[] = {
 	"perf record [<options>] [<command>]",
 	"perf record [<options>] -- <command> [<options>]",
@@ -1096,6 +1126,8 @@ struct option __record_options[] = {
 			"per thread proc mmap processing timeout in ms"),
 	OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
 		    "Record context switch events"),
+	OPT_BOOLEAN(0, "freq-perf", &record.freq_perf,
+		    "Add frequency and performance related events to do sample read."),
 	OPT_END()
 };
 
@@ -1157,6 +1189,11 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (rec->no_buildid_cache || rec->no_buildid)
 		disable_buildid_cache();
 
+	if (rec->freq_perf && record_add_freq_perf_events(rec->evlist)) {
+		pr_err("Cannot set up freq and performance events\n");
+		goto out_symbol_exit;
+	}
+
 	if (rec->evlist->nr_entries == 0 &&
 	    perf_evlist__add_default(rec->evlist) < 0) {
 		pr_err("Not enough memory for event selector list\n");
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index b44afc7..3915be7 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -42,6 +42,16 @@ struct perf_session {
 #define PRINT_IP_OPT_ONELINE	(1<<4)
 #define PRINT_IP_OPT_SRCLINE	(1<<5)
 
+enum perf_freq_perf_index {
+	FREQ_PERF_TSC		= 0,
+	FREQ_PERF_APERF		= 1,
+	FREQ_PERF_MPERF		= 2,
+	FREQ_PERF_CYCLES	= 3,
+	FREQ_PERF_REF_CYCLES	= 4,
+
+	FREQ_PERF_MAX
+};
+
 struct perf_tool;
 
 struct perf_session *perf_session__new(struct perf_data_file *file,
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH V9 4/6] perf,tools: Dump per-sample freq/CPU%/CORE_BUSY% in report -D
  2015-09-08 19:32 [PATCH V9 0/6] Freq/CPU%/CORE_BUSY% support kan.liang
                   ` (2 preceding siblings ...)
  2015-09-08 19:32 ` [PATCH V9 3/6] perf, record: introduce --freq-perf option kan.liang
@ 2015-09-08 19:32 ` kan.liang
  2015-09-10 14:21   ` Arnaldo Carvalho de Melo
  2015-09-08 19:32 ` [PATCH V9 5/6] perf,tools: caculate and save freq/CPU%/CORE_BUSY% in he_stat kan.liang
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 17+ messages in thread
From: kan.liang @ 2015-09-08 19:32 UTC (permalink / raw)
  To: acme, jolsa
  Cc: a.p.zijlstra, luto, mingo, eranian, ak, mark.rutland,
	adrian.hunter, namhyung, linux-kernel, Kan Liang

From: Kan Liang <kan.liang@intel.com>

The group read results from cycles/ref-cycles/TSC/ASTATE/MSTATE event
can be used to calculate the frequency, CPU Utilization and percent
performance during each sampling period.
This patch shows them in report -D.

Here is an example:

$ perf record --freq-perf  ~/tchain_edit

Here is one sample from perf report -D

1972044565107 0x3498 [0x88]: PERF_RECORD_SAMPLE(IP, 0x2): 10608/10608:
0x4005fd period: 564686 addr: 0
... sample_read:
.... group nr 5
..... id 0000000000000012, value 0000000002143901
..... id 0000000000000052, value 0000000002143896
..... id 0000000000000094, value 00000000021e443d
..... id 00000000000000d4, value 00000000021db984
..... id 0000000000000114, value 00000000021db964
..... Freq 2301 MHz
..... CPU% 98%
..... CORE_BUSY% 99%

Signed-off-by: Kan Liang <kan.liang@intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/session.c | 28 +++++++++++++++++++++---
 tools/perf/util/session.h | 54 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 79 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 23fed17..ba763f7 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -7,7 +7,6 @@
 #include <sys/mman.h>
 
 #include "evlist.h"
-#include "evsel.h"
 #include "session.h"
 #include "tool.h"
 #include "sort.h"
@@ -878,8 +877,15 @@ static void perf_evlist__print_tstamp(struct perf_evlist *evlist,
 		printf("%" PRIu64 " ", sample->time);
 }
 
-static void sample_read__printf(struct perf_sample *sample, u64 read_format)
+static void sample_read__printf(struct perf_sample *sample,
+				struct perf_evsel *evsel)
 {
+	u64 read_format = evsel->attr.read_format;
+	struct perf_evlist *evlist = evsel->evlist;
+	struct perf_sample_id *sid;
+	perf_freq_t data = { 0 };
+	u64 cpu_max_freq = evlist->env->cpuattr.max_freq;
+
 	printf("... sample_read:\n");
 
 	if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
@@ -902,10 +908,26 @@ static void sample_read__printf(struct perf_sample *sample, u64 read_format)
 			printf("..... id %016" PRIx64
 			       ", value %016" PRIx64 "\n",
 			       value->id, value->value);
+
+			sid = perf_evlist__id2sid(evlist, value->id);
+			evsel = sid->evsel;
+			if (evsel != NULL)
+				perf_freq__init(evlist->env->msr_pmu_type,
+						evsel, data, value->value);
 		}
 	} else
 		printf("..... id %016" PRIx64 ", value %016" PRIx64 "\n",
 			sample->read.one.id, sample->read.one.value);
+
+	if (perf_freq__has_freq(data))
+		printf("..... Freq %lu MHz\n",
+		       perf_freq__get_freq(data, cpu_max_freq/1000));
+	if (perf_freq__has_cpu_util(data))
+		printf("..... CPU%% %lu%%\n",
+		       perf_freq__get_cpu_util(data));
+	if (perf_freq__has_core_busy(data))
+		printf("..... CORE_BUSY%% %lu%%\n",
+		       perf_freq__get_core_busy(data));
 }
 
 static void dump_event(struct perf_evlist *evlist, union perf_event *event,
@@ -965,7 +987,7 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
 		printf("... transaction: %" PRIx64 "\n", sample->transaction);
 
 	if (sample_type & PERF_SAMPLE_READ)
-		sample_read__printf(sample, evsel->attr.read_format);
+		sample_read__printf(sample, evsel);
 }
 
 static struct machine *machines__find_for_cpumode(struct machines *machines,
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 3915be7..83bf4a9 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -11,6 +11,7 @@
 #include "ordered-events.h"
 #include <linux/rbtree.h>
 #include <linux/perf_event.h>
+#include "evsel.h"
 
 struct ip_callchain;
 struct thread;
@@ -42,6 +43,10 @@ struct perf_session {
 #define PRINT_IP_OPT_ONELINE	(1<<4)
 #define PRINT_IP_OPT_SRCLINE	(1<<5)
 
+#define PERF_MSR_TSC		0
+#define PERF_MSR_APERF		1
+#define PERF_MSR_MPERF		2
+
 enum perf_freq_perf_index {
 	FREQ_PERF_TSC		= 0,
 	FREQ_PERF_APERF		= 1,
@@ -52,6 +57,55 @@ enum perf_freq_perf_index {
 	FREQ_PERF_MAX
 };
 
+typedef u64 perf_freq_t[FREQ_PERF_MAX];
+
+static inline void perf_freq__init(unsigned int msr_pmu_type,
+			    struct perf_evsel *evsel,
+			    perf_freq_t array,
+			    u64 value)
+{
+	if (evsel->attr.type == msr_pmu_type) {
+		if (evsel->attr.config == PERF_MSR_TSC)
+			array[FREQ_PERF_TSC] = value;
+		if (evsel->attr.config == PERF_MSR_APERF)
+			array[FREQ_PERF_APERF] = value;
+		if (evsel->attr.config == PERF_MSR_MPERF)
+			array[FREQ_PERF_MPERF] = value;
+	}
+	if (evsel->attr.type == PERF_TYPE_HARDWARE) {
+		if (evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES)
+			array[FREQ_PERF_CYCLES] = value;
+		if (evsel->attr.config == PERF_COUNT_HW_REF_CPU_CYCLES)
+			array[FREQ_PERF_REF_CYCLES] = value;
+	}
+}
+
+static inline bool perf_freq__has_freq(perf_freq_t array)
+{
+	return ((array[FREQ_PERF_CYCLES] > 0) && (array[FREQ_PERF_REF_CYCLES] > 0));
+}
+static inline u64 perf_freq__get_freq(perf_freq_t array, u64 cpu_max_freq)
+{
+	return ((array[FREQ_PERF_CYCLES] * cpu_max_freq) / array[FREQ_PERF_REF_CYCLES]);
+}
+static inline bool perf_freq__has_cpu_util(perf_freq_t array)
+{
+	return ((array[FREQ_PERF_TSC] > 0) && (array[FREQ_PERF_REF_CYCLES] > 0));
+}
+static inline u64 perf_freq__get_cpu_util(perf_freq_t array)
+{
+	return ((100 * array[FREQ_PERF_REF_CYCLES]) / array[FREQ_PERF_TSC]);
+}
+
+static inline bool perf_freq__has_core_busy(perf_freq_t array)
+{
+	return ((array[FREQ_PERF_APERF] > 0) && (array[FREQ_PERF_MPERF] > 0));
+}
+static inline u64 perf_freq__get_core_busy(perf_freq_t array)
+{
+	return ((100 * array[FREQ_PERF_APERF]) / array[FREQ_PERF_MPERF]);
+}
+
 struct perf_tool;
 
 struct perf_session *perf_session__new(struct perf_data_file *file,
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH V9 5/6] perf,tools: caculate and save freq/CPU%/CORE_BUSY% in he_stat
  2015-09-08 19:32 [PATCH V9 0/6] Freq/CPU%/CORE_BUSY% support kan.liang
                   ` (3 preceding siblings ...)
  2015-09-08 19:32 ` [PATCH V9 4/6] perf,tools: Dump per-sample freq/CPU%/CORE_BUSY% in report -D kan.liang
@ 2015-09-08 19:32 ` kan.liang
  2015-09-08 19:32 ` [PATCH V9 6/6] perf,tools: Show freq/CPU%/CORE_BUSY% in perf report by --freq-perf kan.liang
  2015-09-09 14:39 ` [PATCH V9 0/6] Freq/CPU%/CORE_BUSY% support Jiri Olsa
  6 siblings, 0 replies; 17+ messages in thread
From: kan.liang @ 2015-09-08 19:32 UTC (permalink / raw)
  To: acme, jolsa
  Cc: a.p.zijlstra, luto, mingo, eranian, ak, mark.rutland,
	adrian.hunter, namhyung, linux-kernel, Kan Liang

From: Kan Liang <kan.liang@intel.com>

Caculate freq/CPU%/CORE_BUSY% in add_entry_cb, and update the value in
he_stat.

Signed-off-by: Kan Liang <kan.liang@intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-report.c | 36 ++++++++++++++++++++++++++++++++++++
 tools/perf/util/sort.h      |  3 +++
 2 files changed, 39 insertions(+)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 4b43245..d6e5203 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -90,6 +90,38 @@ static int report__config(const char *var, const char *value, void *cb)
 	return perf_default_config(var, value, cb);
 }
 
+static void set_he_freq_perf(struct perf_session *session,
+			     struct hist_entry_iter *iter)
+{
+	struct hist_entry *he = iter->he;
+	struct perf_evsel *evsel = iter->evsel;
+	struct perf_evsel *leader = evsel;
+	struct perf_sample *sample = iter->sample;
+	struct perf_evlist *evlist = session->evlist;
+	u64 cpu_max_freq = session->header.env.cpuattr.max_freq;
+	perf_freq_t data = { 0 };
+	u64 nr = 0;
+
+	perf_freq__init(session->header.env.msr_pmu_type,
+			evsel, data,
+			sample->read.group.values[nr].value);
+	evlist__for_each_continue(evlist, evsel) {
+		if ((evsel->leader != leader) ||
+		     (++nr >= sample->read.group.nr))
+			break;
+		perf_freq__init(session->header.env.msr_pmu_type,
+				evsel, data,
+				sample->read.group.values[nr].value);
+	}
+
+	if (perf_freq__has_freq(data))
+		he->stat.freq = perf_freq__get_freq(data, cpu_max_freq/1000);
+	if (perf_freq__has_cpu_util(data))
+		he->stat.cpu_util = perf_freq__get_cpu_util(data);
+	if (perf_freq__has_core_busy(data))
+		he->stat.core_busy = perf_freq__get_core_busy(data);
+}
+
 static int hist_iter__report_callback(struct hist_entry_iter *iter,
 				      struct addr_location *al, bool single,
 				      void *arg)
@@ -101,6 +133,10 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter,
 	struct mem_info *mi;
 	struct branch_info *bi;
 
+	if ((iter->ops == &hist_iter_normal) &&
+	    perf_evsel__is_group_leader(evsel))
+		set_he_freq_perf(rep->session, iter);
+
 	if (!ui__has_annotation())
 		return 0;
 
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 654ac8a..f39e287 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -54,6 +54,9 @@ struct he_stat {
 	u64			period_guest_us;
 	u64			weight;
 	u32			nr_events;
+	u64			freq;
+	u64			cpu_util;
+	u64			core_busy;
 };
 
 struct hist_entry_diff {
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH V9 6/6] perf,tools: Show freq/CPU%/CORE_BUSY% in perf report by --freq-perf
  2015-09-08 19:32 [PATCH V9 0/6] Freq/CPU%/CORE_BUSY% support kan.liang
                   ` (4 preceding siblings ...)
  2015-09-08 19:32 ` [PATCH V9 5/6] perf,tools: caculate and save freq/CPU%/CORE_BUSY% in he_stat kan.liang
@ 2015-09-08 19:32 ` kan.liang
  2015-09-09 14:36   ` Jiri Olsa
  2015-09-09 14:39 ` [PATCH V9 0/6] Freq/CPU%/CORE_BUSY% support Jiri Olsa
  6 siblings, 1 reply; 17+ messages in thread
From: kan.liang @ 2015-09-08 19:32 UTC (permalink / raw)
  To: acme, jolsa
  Cc: a.p.zijlstra, luto, mingo, eranian, ak, mark.rutland,
	adrian.hunter, namhyung, linux-kernel, Kan Liang

From: Kan Liang <kan.liang@intel.com>

Show frequency, CPU Utilization and percent performance for each symbol
in perf report by --freq-perf

In sampling group, only group leader do sampling. So only need to print
group leader's freq in --group.

--freq-perf option also implies --group.

Here is an example.

$ perf report --stdio --freq-perf

                                 Overhead   FREQ MHz   CPU%  CORE_BUSY%
Command      Shared Object     Symbol
 ........................................  .........  .....  ..........
...........  ................  ......................

    99.54%  99.54%  99.53%  99.53%  99.53%       2301     96         99
tchain_edit  tchain_edit       [.] f3
     0.20%   0.20%   0.20%   0.20%   0.20%       2301     98         99
tchain_edit  tchain_edit       [.] f2
     0.05%   0.05%   0.05%   0.05%   0.05%       2300     98         99
tchain_edit  [kernel.vmlinux]  [k] read_tsc

Signed-off-by: Kan Liang <kan.liang@intel.com>
---
 tools/perf/Documentation/perf-report.txt | 12 ++++++
 tools/perf/builtin-report.c              | 25 ++++++++++-
 tools/perf/ui/hist.c                     | 71 +++++++++++++++++++++++++++++---
 tools/perf/util/hist.h                   |  3 ++
 tools/perf/util/session.c                | 33 ++++++++-------
 tools/perf/util/sort.c                   |  3 ++
 tools/perf/util/symbol.h                 | 12 +++++-
 7 files changed, 137 insertions(+), 22 deletions(-)

diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index b941d5e..9804e63 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -307,6 +307,18 @@ OPTIONS
 	special event -e cpu/mem-loads/ or -e cpu/mem-stores/. See
 	'perf mem' for simpler access.
 
+--freq-perf::
+	Show CPU frequency and performance result from sample read.
+	To generate the frequency and performance output, the perf.data file
+	must have been obtained by group read and using special events cycles,
+	ref-cycles, msr/tsc/, msr/aperf/ or msr/mperf/
+	Freq MHz: The frequency during the sample interval. Needs cycles and
+		  ref-cycles event.
+	CPU%: CPU utilization during the sample interval. Needs ref-cycles and
+	      msr/tsc/ events.
+	CORE_BUSY%: actual percent performance (APERF/MPERF%) during the
+		    sample interval. Needs msr/aperf/ and msr/mperf/ events.
+
 --percent-limit::
 	Do not show entries which have an overhead under that percent.
 	(Default: 0).
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index d6e5203..bd466d8 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -134,7 +134,8 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter,
 	struct branch_info *bi;
 
 	if ((iter->ops == &hist_iter_normal) &&
-	    perf_evsel__is_group_leader(evsel))
+	    perf_evsel__is_group_leader(evsel) &&
+	    symbol_conf.freq_perf)
 		set_he_freq_perf(rep->session, iter);
 
 	if (!ui__has_annotation())
@@ -785,6 +786,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 	OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
 		    "Enable kernel symbol demangling"),
 	OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"),
+	OPT_BOOLEAN(0, "freq-perf", &symbol_conf.freq_perf,
+		    "show CPU freqency and performance info"),
 	OPT_CALLBACK(0, "percent-limit", &report, "percent",
 		     "Don't show entries under that percent", parse_percent_limit),
 	OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
@@ -803,7 +806,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 	struct perf_data_file file = {
 		.mode  = PERF_DATA_MODE_READ,
 	};
+	struct perf_evsel *pos;
 	int ret = hists__init();
+	perf_freq_t freq_data_status = { 0 };
 
 	if (ret < 0)
 		return ret;
@@ -888,6 +893,24 @@ repeat:
 		symbol_conf.cumulate_callchain = false;
 	}
 
+
+	if (symbol_conf.freq_perf) {
+		symbol_conf.freq_perf_type = 0;
+		evlist__for_each(session->evlist, pos) {
+			perf_freq__init(session->header.env.msr_pmu_type,
+					pos, freq_data_status, 1);
+		}
+		if (perf_freq__has_freq(freq_data_status))
+			symbol_conf.freq_perf_type |= 1U << DISPLAY_FREQ;
+		if (perf_freq__has_cpu_util(freq_data_status))
+			symbol_conf.freq_perf_type |= 1U << DISPLAY_CPU_UTIL;
+		if (perf_freq__has_core_busy(freq_data_status))
+			symbol_conf.freq_perf_type |= 1U << DISPLAY_CORE_BUSY;
+
+		/* --freq-perf option imply --group */
+		symbol_conf.event_group = true;
+	}
+
 	if (setup_sorting() < 0) {
 		if (sort_order)
 			parse_options_usage(report_usage, options, "s", 1);
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 25d6083..059d3e3 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -17,7 +17,7 @@
 
 static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
 		      hpp_field_fn get_field, const char *fmt, int len,
-		      hpp_snprint_fn print_fn, bool fmt_percent)
+		      hpp_snprint_fn print_fn, bool fmt_percent, bool single)
 {
 	int ret;
 	struct hists *hists = he->hists;
@@ -36,7 +36,7 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
 	} else
 		ret = hpp__call_print_fn(hpp, print_fn, fmt, len, get_field(he));
 
-	if (perf_evsel__is_group_event(evsel)) {
+	if (perf_evsel__is_group_event(evsel) && !single) {
 		int prev_idx, idx_delta;
 		struct hist_entry *pair;
 		int nr_members = evsel->nr_members;
@@ -109,10 +109,16 @@ int hpp__fmt(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
 	     const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent)
 {
 	int len = fmt->user_len ?: fmt->len;
+	bool single = false;
+
+	if (((fmt == &perf_hpp__format[PERF_HPP__FREQ]) ||
+	     (fmt == &perf_hpp__format[PERF_HPP__CPU_UTIL]) ||
+	     (fmt == &perf_hpp__format[PERF_HPP__CORE_BUSY])))
+		single = true;
 
 	if (symbol_conf.field_sep) {
 		return __hpp__fmt(hpp, he, get_field, fmtstr, 1,
-				  print_fn, fmt_percent);
+				  print_fn, fmt_percent, single);
 	}
 
 	if (fmt_percent)
@@ -120,7 +126,7 @@ int hpp__fmt(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
 	else
 		len -= 1;
 
-	return  __hpp__fmt(hpp, he, get_field, fmtstr, len, print_fn, fmt_percent);
+	return  __hpp__fmt(hpp, he, get_field, fmtstr, len, print_fn, fmt_percent, single);
 }
 
 int hpp__fmt_acc(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
@@ -234,6 +240,30 @@ static int hpp__header_fn(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
 	return scnprintf(hpp->buf, hpp->size, "%*s", len, fmt->name);
 }
 
+static int hpp__single_width_fn(struct perf_hpp_fmt *fmt,
+			 struct perf_hpp *hpp __maybe_unused,
+			 struct perf_evsel *evsel)
+{
+	int len = fmt->user_len ?: fmt->len;
+
+	if (symbol_conf.event_group && !symbol_conf.freq_perf)
+		len = max(len, evsel->nr_members * fmt->len);
+
+	if (len < (int)strlen(fmt->name))
+		len = strlen(fmt->name);
+
+	return len;
+}
+
+static int hpp__single_header_fn(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
+			  struct perf_evsel *evsel)
+{
+	int len = hpp__single_width_fn(fmt, hpp, evsel);
+
+	return scnprintf(hpp->buf, hpp->size, "%*s", len, fmt->name);
+}
+
+
 static int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...)
 {
 	va_list args;
@@ -363,6 +393,9 @@ HPP_PERCENT_ACC_FNS(overhead_acc, period)
 
 HPP_RAW_FNS(samples, nr_events)
 HPP_RAW_FNS(period, period)
+HPP_RAW_FNS(freq, freq)
+HPP_RAW_FNS(cpu_util, cpu_util)
+HPP_RAW_FNS(core_busy, core_busy)
 
 static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
 			    struct hist_entry *a __maybe_unused,
@@ -395,6 +428,17 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
 		.sort	= hpp__sort_ ## _fn,		\
 	}
 
+#define HPP__SINGLE_PRINT_FNS(_name, _fn)		\
+	{						\
+		.name   = _name,			\
+		.header	= hpp__single_header_fn,	\
+		.width	= hpp__single_width_fn,		\
+		.entry	= hpp__entry_ ## _fn,		\
+		.cmp	= hpp__nop_cmp,			\
+		.collapse = hpp__nop_cmp,		\
+		.sort	= hpp__sort_ ## _fn,		\
+	}
+
 #define HPP__PRINT_FNS(_name, _fn)			\
 	{						\
 		.name   = _name,			\
@@ -414,7 +458,10 @@ struct perf_hpp_fmt perf_hpp__format[] = {
 	HPP__COLOR_PRINT_FNS("guest usr", overhead_guest_us),
 	HPP__COLOR_ACC_PRINT_FNS("Children", overhead_acc),
 	HPP__PRINT_FNS("Samples", samples),
-	HPP__PRINT_FNS("Period", period)
+	HPP__PRINT_FNS("Period", period),
+	HPP__SINGLE_PRINT_FNS("FREQ MHz", freq),
+	HPP__SINGLE_PRINT_FNS("CPU%", cpu_util),
+	HPP__SINGLE_PRINT_FNS("CORE_BUSY%", core_busy)
 };
 
 LIST_HEAD(perf_hpp__list);
@@ -485,6 +532,15 @@ void perf_hpp__init(void)
 	if (symbol_conf.show_total_period)
 		perf_hpp__column_enable(PERF_HPP__PERIOD);
 
+	if (symbol_conf.freq_perf) {
+		if (symbol_conf.freq_perf_type & (1U << DISPLAY_FREQ))
+			perf_hpp__column_enable(PERF_HPP__FREQ);
+		if (symbol_conf.freq_perf_type & (1U << DISPLAY_CPU_UTIL))
+			perf_hpp__column_enable(PERF_HPP__CPU_UTIL);
+		if (symbol_conf.freq_perf_type & (1U << DISPLAY_CORE_BUSY))
+			perf_hpp__column_enable(PERF_HPP__CORE_BUSY);
+	}
+
 	/* prepend overhead field for backward compatiblity.  */
 	list = &perf_hpp__format[PERF_HPP__OVERHEAD].sort_list;
 	if (list_empty(list))
@@ -652,6 +708,9 @@ void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists)
 		return;
 
 	switch (idx) {
+	case PERF_HPP__CPU_UTIL:
+		fmt->len = 5;
+		break;
 	case PERF_HPP__OVERHEAD:
 	case PERF_HPP__OVERHEAD_SYS:
 	case PERF_HPP__OVERHEAD_US:
@@ -661,6 +720,8 @@ void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists)
 
 	case PERF_HPP__OVERHEAD_GUEST_SYS:
 	case PERF_HPP__OVERHEAD_GUEST_US:
+	case PERF_HPP__FREQ:
+	case PERF_HPP__CORE_BUSY:
 		fmt->len = 9;
 		break;
 
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 4d6aa1d..664b34d 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -241,6 +241,9 @@ enum {
 	PERF_HPP__OVERHEAD_ACC,
 	PERF_HPP__SAMPLES,
 	PERF_HPP__PERIOD,
+	PERF_HPP__FREQ,
+	PERF_HPP__CPU_UTIL,
+	PERF_HPP__CORE_BUSY,
 
 	PERF_HPP__MAX_INDEX
 };
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index ba763f7..fc1b451 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -908,26 +908,29 @@ static void sample_read__printf(struct perf_sample *sample,
 			printf("..... id %016" PRIx64
 			       ", value %016" PRIx64 "\n",
 			       value->id, value->value);
-
-			sid = perf_evlist__id2sid(evlist, value->id);
-			evsel = sid->evsel;
-			if (evsel != NULL)
-				perf_freq__init(evlist->env->msr_pmu_type,
-						evsel, data, value->value);
+			if (symbol_conf.freq_perf) {
+				sid = perf_evlist__id2sid(evlist, value->id);
+				evsel = sid->evsel;
+				if (evsel != NULL)
+					perf_freq__init(evlist->env->msr_pmu_type,
+							evsel, data, value->value);
+			}
 		}
 	} else
 		printf("..... id %016" PRIx64 ", value %016" PRIx64 "\n",
 			sample->read.one.id, sample->read.one.value);
 
-	if (perf_freq__has_freq(data))
-		printf("..... Freq %lu MHz\n",
-		       perf_freq__get_freq(data, cpu_max_freq/1000));
-	if (perf_freq__has_cpu_util(data))
-		printf("..... CPU%% %lu%%\n",
-		       perf_freq__get_cpu_util(data));
-	if (perf_freq__has_core_busy(data))
-		printf("..... CORE_BUSY%% %lu%%\n",
-		       perf_freq__get_core_busy(data));
+	if (symbol_conf.freq_perf) {
+		if (perf_freq__has_freq(data))
+			printf("..... Freq %lu MHz\n",
+			       perf_freq__get_freq(data, cpu_max_freq/1000));
+		if (perf_freq__has_cpu_util(data))
+			printf("..... CPU%% %lu%%\n",
+			       perf_freq__get_cpu_util(data));
+		if (perf_freq__has_core_busy(data))
+			printf("..... CORE_BUSY%% %lu%%\n",
+			       perf_freq__get_core_busy(data));
+	}
 }
 
 static void dump_event(struct perf_evlist *evlist, union perf_event *event,
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 5e4ed17..89ef407 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1325,6 +1325,9 @@ static struct hpp_dimension hpp_sort_dimensions[] = {
 	DIM(PERF_HPP__OVERHEAD_ACC, "overhead_children"),
 	DIM(PERF_HPP__SAMPLES, "sample"),
 	DIM(PERF_HPP__PERIOD, "period"),
+	DIM(PERF_HPP__FREQ, "freq"),
+	DIM(PERF_HPP__CPU_UTIL, "cpu_u"),
+	DIM(PERF_HPP__CORE_BUSY, "core_busy"),
 };
 
 #undef DIM
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 40073c6..40d2044 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -80,6 +80,14 @@ static inline size_t symbol__size(const struct symbol *sym)
 struct strlist;
 struct intlist;
 
+enum freq_perf_type_index {
+	DISPLAY_FREQ		= 0,
+	DISPLAY_CPU_UTIL,
+	DISPLAY_CORE_BUSY,
+
+	DISPLAY_MAX
+};
+
 struct symbol_conf {
 	unsigned short	priv_size;
 	unsigned short	nr_events;
@@ -107,7 +115,8 @@ struct symbol_conf {
 			show_hist_headers,
 			branch_callstack,
 			has_filter,
-			show_ref_callgraph;
+			show_ref_callgraph,
+			freq_perf;
 	const char	*vmlinux_name,
 			*kallsyms_name,
 			*source_prefix,
@@ -132,6 +141,7 @@ struct symbol_conf {
 	struct intlist	*pid_list,
 			*tid_list;
 	const char	*symfs;
+	u64		freq_perf_type;
 };
 
 extern struct symbol_conf symbol_conf;
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH V9 3/6] perf, record: introduce --freq-perf option
  2015-09-08 19:32 ` [PATCH V9 3/6] perf, record: introduce --freq-perf option kan.liang
@ 2015-09-09 14:34   ` Jiri Olsa
  2015-09-14 21:14   ` Arnaldo Carvalho de Melo
  1 sibling, 0 replies; 17+ messages in thread
From: Jiri Olsa @ 2015-09-09 14:34 UTC (permalink / raw)
  To: kan.liang
  Cc: acme, jolsa, a.p.zijlstra, luto, mingo, eranian, ak,
	mark.rutland, adrian.hunter, namhyung, linux-kernel

On Tue, Sep 08, 2015 at 03:32:46PM -0400, kan.liang@intel.com wrote:
> From: Kan Liang <kan.liang@intel.com>
> 
> To generate the frequency and performance output, perf must sample read
> special events like cycles, ref-cycles, msr/tsc/, msr/aperf/ or
> msr/mperf/.
> With the --freq-perf option, perf record can automatically check and add
> those event into evlist for sampling read.
> 
> Signed-off-by: Kan Liang <kan.liang@intel.com>

Acked-by: Jiri Olsa <jolsa@kernel.org>

thanks,
jirka

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH V9 6/6] perf,tools: Show freq/CPU%/CORE_BUSY% in perf report by --freq-perf
  2015-09-08 19:32 ` [PATCH V9 6/6] perf,tools: Show freq/CPU%/CORE_BUSY% in perf report by --freq-perf kan.liang
@ 2015-09-09 14:36   ` Jiri Olsa
  0 siblings, 0 replies; 17+ messages in thread
From: Jiri Olsa @ 2015-09-09 14:36 UTC (permalink / raw)
  To: kan.liang
  Cc: acme, jolsa, a.p.zijlstra, luto, mingo, eranian, ak,
	mark.rutland, adrian.hunter, namhyung, linux-kernel

On Tue, Sep 08, 2015 at 03:32:49PM -0400, kan.liang@intel.com wrote:
> From: Kan Liang <kan.liang@intel.com>
> 
> Show frequency, CPU Utilization and percent performance for each symbol
> in perf report by --freq-perf
> 
> In sampling group, only group leader do sampling. So only need to print
> group leader's freq in --group.
> 
> --freq-perf option also implies --group.
> 
> Here is an example.
> 
> $ perf report --stdio --freq-perf
> 
>                                  Overhead   FREQ MHz   CPU%  CORE_BUSY%
> Command      Shared Object     Symbol
>  ........................................  .........  .....  ..........
> ...........  ................  ......................
> 
>     99.54%  99.54%  99.53%  99.53%  99.53%       2301     96         99
> tchain_edit  tchain_edit       [.] f3
>      0.20%   0.20%   0.20%   0.20%   0.20%       2301     98         99
> tchain_edit  tchain_edit       [.] f2
>      0.05%   0.05%   0.05%   0.05%   0.05%       2300     98         99
> tchain_edit  [kernel.vmlinux]  [k] read_tsc
> 
> Signed-off-by: Kan Liang <kan.liang@intel.com>

it seems ok to me, though I think it could be split
into HPP__SINGLE_PRINT_FNS support and the rest..

but I prefer if Arnaldo or Namhyung could review this one

thanks,
jirka

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH V9 0/6] Freq/CPU%/CORE_BUSY% support
  2015-09-08 19:32 [PATCH V9 0/6] Freq/CPU%/CORE_BUSY% support kan.liang
                   ` (5 preceding siblings ...)
  2015-09-08 19:32 ` [PATCH V9 6/6] perf,tools: Show freq/CPU%/CORE_BUSY% in perf report by --freq-perf kan.liang
@ 2015-09-09 14:39 ` Jiri Olsa
  6 siblings, 0 replies; 17+ messages in thread
From: Jiri Olsa @ 2015-09-09 14:39 UTC (permalink / raw)
  To: kan.liang
  Cc: acme, jolsa, a.p.zijlstra, luto, mingo, eranian, ak,
	mark.rutland, adrian.hunter, namhyung, linux-kernel

On Tue, Sep 08, 2015 at 03:32:43PM -0400, kan.liang@intel.com wrote:
> From: Kan Liang <kan.liang@intel.com>
> 
> This patch set supports per-sample freq/CPU%/CORE_BUSY% print in perf
> report.
> For printing these information, the perf.data file must have been obtained
> by group read and using special events cycles, ref-cycles, msr/tsc/,
> msr/aperf/ or msr/mperf/.
> 
>  - Freq (MHz): The frequency during the sample interval. Needs cycles
>    ref-cycles event.
>  - CPU%: CPU utilization during the sample interval. Needs ref-cycles and
>    msr/tsc/ events.
>  - CORE_BUSY%: actual percent performance (APERF/MPERF%) during the
>    sample interval. Needs msr/aperf/ and msr/mperf/ events.
> 
> Here is an example:
> 
> $ perf record --freq-perf ~/tchain_edit
> 
> $ perf report --stdio --freq-perf
> 
>                                  Overhead   FREQ MHz   CPU%  CORE_BUSY%
> Command      Shared Object     Symbol
>  ........................................  .........  .....  ..........
> ...........  ................  ......................
> 
>     99.54%  99.54%  99.53%  99.53%  99.53%       2301     96         99
> tchain_edit  tchain_edit       [.] f3
>      0.20%   0.20%   0.20%   0.20%   0.20%       2301     98         99
> tchain_edit  tchain_edit       [.] f2
>      0.05%   0.05%   0.05%   0.05%   0.05%       2300     98         99
> tchain_edit  [kernel.vmlinux]  [k] read_tsc
> 
> Changes since V1:
>  - Save cpu max freq to header when recording
>  - Read cpu max freq and msr type from header when reporting
> 
> Changes since V2:
>  - Introduce generic FEAT for CPU related data stored
>  - Make cpu max freq and msr type part of perf_session_env
>  - rename cpu_u to cpu_util
>  - Don't save sample value in perf_sample and discards new iterator.
>    Calculating the freq_perf_info in add_entry_cb callback
>  - Introduce symbol_conf.freq_perf_type for related hpp column visibility
> 
> Changes since V3:
>  - add a identifier 'tag' for CPU attributes, max frequency.
>  - add backpointers to evlist for env, and evsel for evlist.
>  - Use bitmask for freq_perf_type
>  - Replace macros by functions to caculate freq, cpu_util and core_busy
>  - Move all caculation codes under symbol_conf.show_freq_perf condition.
> 
> Changes since V4:
>  - Store cpu attributes id as tag and more readable cpu_attr
> 
> Changes since V5:
>  - Rename freq to max_freq and use it
>  - Add a loop in process_cpu_attributes to facility future extension
> 
> Changes since V6:
>  - Split rename perf_session_env and add backpointer to evlist patches
> 
> Changes since V7:
>  - Introduce --freq-perf option for perf record
>  - Factor out fix for dump_sample
> 
> Changes since V8:
>  - Rename --show-freq-perf to --freq-perf 
>  - --freq-perf option imply --group

I believe I just acked all of it but the last one,
otherwise I'm ok with it

thanks,
jirka

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH V9 1/6] perf,tools: introduce generic FEAT for CPU attributes
  2015-09-08 19:32 ` [PATCH V9 1/6] perf,tools: introduce generic FEAT for CPU attributes kan.liang
@ 2015-09-10 13:58   ` Arnaldo Carvalho de Melo
  2015-09-10 15:35     ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 17+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-09-10 13:58 UTC (permalink / raw)
  To: kan.liang
  Cc: jolsa, a.p.zijlstra, luto, mingo, eranian, ak, mark.rutland,
	adrian.hunter, namhyung, linux-kernel

Em Tue, Sep 08, 2015 at 03:32:44PM -0400, kan.liang@intel.com escreveu:
> From: Kan Liang <kan.liang@intel.com>
> 
> This patch introduces generic FEAT for CPU attributes. For the patch
> set, we only need cpu max frequency. But it can be easily extented to
> support more other CPU attributes.
> The cpu max frequency is from the first online cpu.

Ok, but don't we have to do error handling? i.e. you are returning 0 for
any error in trying to read the cpu max freq, shouldn't we bail out
somewhere?

And please move this get_cpu_max_freq() thing out of the cpumap.[ch]
files, it is not even a need completely specific to perf tooling, there
must be somewhere in tools/lib/api/ (kernel APIs) where this fits, no?

More comments below.

- Arnaldo
 
> Signed-off-by: Kan Liang <kan.liang@intel.com>
> Acked-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  tools/perf/util/cpumap.c | 32 ++++++++++++++++++++++++++
>  tools/perf/util/cpumap.h |  1 +
>  tools/perf/util/header.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++
>  tools/perf/util/header.h | 12 ++++++++++
>  4 files changed, 104 insertions(+)
> 
> diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
> index a05d76a..671ee83 100644
> --- a/tools/perf/util/cpumap.c
> +++ b/tools/perf/util/cpumap.c
> @@ -514,3 +514,35 @@ int cpu__setup_cpunode_map(void)
>  	closedir(dir1);
>  	return 0;
>  }
> +
> +u64 get_cpu_max_freq(void)
> +{
> +	const char *mnt;
> +	char path[PATH_MAX], tmp;
> +	FILE *fp;
> +	u64 freq;
> +	int cpu = 0;
> +	int ret;
> +
> +	mnt = sysfs__mountpoint();
> +	if (!mnt)
> +		return 0;

See? Can't find the sysfs mount point? No problem, return 0 max freq.

> +
> +	snprintf(path, PATH_MAX, "%s/devices/system/cpu/online", mnt);
> +	fp = fopen(path, "r");
> +	if (fp) {
> +		ret = fscanf(fp, "%u%c", &cpu, &tmp);
> +		fclose(fp);
> +		if (ret < 1)
> +			return 0;

Can't parse it? 0

> +	}
> +
> +	snprintf(path, PATH_MAX, "%s/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", mnt, cpu);
> +	fp = fopen(path, "r");
> +	if (!fp)
> +		return 0;

Ditto. Return soem error here please.

> +	ret = fscanf(fp, "%lu", &freq);
> +	fclose(fp);
> +
> +	return (ret == 1) ? freq : 0;
> +}
> diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
> index 8982d53..06cd2c4 100644
> --- a/tools/perf/util/cpumap.h
> +++ b/tools/perf/util/cpumap.h
> @@ -60,6 +60,7 @@ int max_node_num;
>  int *cpunode_map;
>  
>  int cpu__setup_cpunode_map(void);
> +u64 get_cpu_max_freq(void);

>  
>  static inline int cpu__max_node(void)
>  {
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> index 8fd7b7d..3535dcb 100644
> --- a/tools/perf/util/header.c
> +++ b/tools/perf/util/header.c
> @@ -885,6 +885,23 @@ write_it:
>  	return do_write_string(fd, buffer);
>  }
>  
> +static int write_cpu_attributes(int fd, struct perf_header *h __maybe_unused,
> +				struct perf_evlist *evlist __maybe_unused)
> +{
> +	u32 tag_id;
> +	u64 max_freq;
> +	int ret;
> +
> +	tag_id = PERF_HEADER_CPU_MAX_FREQ;
> +	ret = do_write(fd, &tag_id, sizeof(tag_id));
> +	if (ret < 0)
> +		return ret;
> +
> +	max_freq = get_cpu_max_freq();

Here, do the error handling, return whatever errno code this function
returned, probably the feature code will use it to warn the user
somehow.

> +
> +	return do_write(fd, &max_freq, sizeof(max_freq));
> +}
> +
>  static int write_branch_stack(int fd __maybe_unused,
>  			      struct perf_header *h __maybe_unused,
>  		       struct perf_evlist *evlist __maybe_unused)
> @@ -1185,6 +1202,11 @@ static void print_cpuid(struct perf_header *ph, int fd __maybe_unused, FILE *fp)
>  	fprintf(fp, "# cpuid : %s\n", ph->env.cpuid);
>  }
>  
> +static void print_cpu_attributes(struct perf_header *ph, int fd __maybe_unused, FILE *fp)
> +{
> +	fprintf(fp, "# CPU attributes: max frequency = %lu KHz\n", ph->env.cpuattr.max_freq);
> +}
> +
>  static void print_branch_stack(struct perf_header *ph __maybe_unused,
>  			       int fd __maybe_unused, FILE *fp)
>  {
> @@ -1498,6 +1520,42 @@ static int process_cpuid(struct perf_file_section *section __maybe_unused,
>  	return ph->env.cpuid ? 0 : -ENOMEM;
>  }
>  
> +static int process_cpu_attributes(struct perf_file_section *section __maybe_unused,
> +				  struct perf_header *ph, int fd,
> +				  void *data __maybe_unused)
> +{
> +	ssize_t ret;
> +	u32 i, tag_id;
> +	u64 nr;
> +
> +	for (i = 0; i < PERF_HEADER_CPU_ATTR_MAX; i++) {
> +
> +		ret = readn(fd, &tag_id, sizeof(tag_id));
> +		if (ret != sizeof(tag_id))
> +			return -1;

Return some sensible errno... Its not because
perf_header__process_sections() doesn't check them that we shouldn't
return ;-\ I'll fix perf_header__process_sections() to stop the process
and warn the user if some error happens...

> +
> +		if (ph->needs_swap)
> +			nr = bswap_32(tag_id);
> +
> +		if (tag_id >= PERF_HEADER_CPU_ATTR_MAX) {
> +			pr_debug("The number of cpu attributes is not expected. "
> +				 "You may need to upgrade the perf tool.\n");
> +			return -1;


ditto
> +		}
> +
> +		ret = readn(fd, &nr, sizeof(nr));
> +		if (ret != sizeof(nr))
> +			return -1;


ditto

> +
> +		if (ph->needs_swap)
> +			nr = bswap_64(nr);
> +
> +		ph->env.cpu_attr[tag_id] = nr;
> +	}
> +
> +	return 0;
> +}
> +
>  static int process_total_mem(struct perf_file_section *section __maybe_unused,
>  			     struct perf_header *ph, int fd,
>  			     void *data __maybe_unused)
> @@ -1983,6 +2041,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
>  	FEAT_OPP(HEADER_PMU_MAPPINGS,	pmu_mappings),
>  	FEAT_OPP(HEADER_GROUP_DESC,	group_desc),
>  	FEAT_OPP(HEADER_AUXTRACE,	auxtrace),
> +	FEAT_OPP(HEADER_CPU_ATTR,	cpu_attributes),
>  };
>  
>  struct header_print_data {
> diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
> index 975d803..dd9f6b0 100644
> --- a/tools/perf/util/header.h
> +++ b/tools/perf/util/header.h
> @@ -31,6 +31,7 @@ enum {
>  	HEADER_PMU_MAPPINGS,
>  	HEADER_GROUP_DESC,
>  	HEADER_AUXTRACE,
> +	HEADER_CPU_ATTR,
>  	HEADER_LAST_FEATURE,
>  	HEADER_FEAT_BITS	= 256,
>  };
> @@ -71,6 +72,11 @@ struct cpu_topology_map {
>  	int	core_id;
>  };
>  
> +enum perf_header_cpu_attr {
> +	PERF_HEADER_CPU_MAX_FREQ	= 0,
> +	PERF_HEADER_CPU_ATTR_MAX,
> +};
> +
>  struct perf_env {
>  	char			*hostname;
>  	char			*os_release;
> @@ -95,6 +101,12 @@ struct perf_env {
>  	char			*numa_nodes;
>  	char			*pmu_mappings;
>  	struct cpu_topology_map	*cpu;
> +	union  {
> +		u64		cpu_attr[PERF_HEADER_CPU_ATTR_MAX];
> +		struct {
> +			u64	max_freq;
> +		} cpuattr;
> +	};

Ok, these need moving to env.h, but lets first get that patchkit
merged... Looking at your other patches

>  };
>  
>  struct perf_header {
> -- 
> 1.8.3.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH V9 2/6] perf,tools: read msr pmu type from header.
  2015-09-08 19:32 ` [PATCH V9 2/6] perf,tools: read msr pmu type from header kan.liang
@ 2015-09-10 13:59   ` Arnaldo Carvalho de Melo
  2015-09-14 21:16   ` Arnaldo Carvalho de Melo
  1 sibling, 0 replies; 17+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-09-10 13:59 UTC (permalink / raw)
  To: kan.liang
  Cc: jolsa, a.p.zijlstra, luto, mingo, eranian, ak, mark.rutland,
	adrian.hunter, namhyung, linux-kernel

Em Tue, Sep 08, 2015 at 03:32:45PM -0400, kan.liang@intel.com escreveu:
> From: Kan Liang <kan.liang@intel.com>
> 
> Get msr pmu type when processing pmu_mappings

This one looks ok, I am porting it to my current perf/core, that
includes that perf/env branch, will fix up things as we discuss it.

- Arnaldo
 
> Signed-off-by: Kan Liang <kan.liang@intel.com>
> Acked-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  tools/perf/util/header.c | 3 +++
>  tools/perf/util/header.h | 1 +
>  2 files changed, 4 insertions(+)
> 
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> index 3535dcb..04f415d 100644
> --- a/tools/perf/util/header.c
> +++ b/tools/perf/util/header.c
> @@ -1879,6 +1879,9 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused
>  		/* include a NULL character at the end */
>  		strbuf_add(&sb, "", 1);
>  
> +		if (!strcmp(name, "msr"))
> +			ph->env.msr_pmu_type = type;
> +
>  		free(name);
>  		pmu_num--;
>  	}
> diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
> index dd9f6b0..d9034e8 100644
> --- a/tools/perf/util/header.h
> +++ b/tools/perf/util/header.h
> @@ -107,6 +107,7 @@ struct perf_env {
>  			u64	max_freq;
>  		} cpuattr;
>  	};
> +	unsigned int		msr_pmu_type;
>  };
>  
>  struct perf_header {
> -- 
> 1.8.3.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH V9 4/6] perf,tools: Dump per-sample freq/CPU%/CORE_BUSY% in report -D
  2015-09-08 19:32 ` [PATCH V9 4/6] perf,tools: Dump per-sample freq/CPU%/CORE_BUSY% in report -D kan.liang
@ 2015-09-10 14:21   ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 17+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-09-10 14:21 UTC (permalink / raw)
  To: kan.liang
  Cc: jolsa, a.p.zijlstra, luto, mingo, eranian, ak, mark.rutland,
	adrian.hunter, namhyung, linux-kernel

Em Tue, Sep 08, 2015 at 03:32:47PM -0400, kan.liang@intel.com escreveu:
> From: Kan Liang <kan.liang@intel.com>
> 
> The group read results from cycles/ref-cycles/TSC/ASTATE/MSTATE event
> can be used to calculate the frequency, CPU Utilization and percent
> performance during each sampling period.
> This patch shows them in report -D.
> 
> Here is an example:
> 
> $ perf record --freq-perf  ~/tchain_edit
> 
> Here is one sample from perf report -D
> 
> 1972044565107 0x3498 [0x88]: PERF_RECORD_SAMPLE(IP, 0x2): 10608/10608:
> 0x4005fd period: 564686 addr: 0
> ... sample_read:
> .... group nr 5
> ..... id 0000000000000012, value 0000000002143901
> ..... id 0000000000000052, value 0000000002143896
> ..... id 0000000000000094, value 00000000021e443d
> ..... id 00000000000000d4, value 00000000021db984
> ..... id 0000000000000114, value 00000000021db964
> ..... Freq 2301 MHz
> ..... CPU% 98%
> ..... CORE_BUSY% 99%
> 
> Signed-off-by: Kan Liang <kan.liang@intel.com>
> Acked-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  tools/perf/util/session.c | 28 +++++++++++++++++++++---
>  tools/perf/util/session.h | 54 +++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 79 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
> index 23fed17..ba763f7 100644
> --- a/tools/perf/util/session.c
> +++ b/tools/perf/util/session.c
> @@ -7,7 +7,6 @@
>  #include <sys/mman.h>
>  
>  #include "evlist.h"
> -#include "evsel.h"
>  #include "session.h"
>  #include "tool.h"
>  #include "sort.h"
> @@ -878,8 +877,15 @@ static void perf_evlist__print_tstamp(struct perf_evlist *evlist,
>  		printf("%" PRIu64 " ", sample->time);
>  }
>  
> -static void sample_read__printf(struct perf_sample *sample, u64 read_format)
> +static void sample_read__printf(struct perf_sample *sample,
> +				struct perf_evsel *evsel)

Hey, this is a _printf_ function, i.e. one thinks about functions with
such name it doing just that, printing whatever is _already_ in the data
structures, at maximum messing with _output_ related internal state.

This probably needs setting up at some other place, so that when it
comes here it is already all worked out.

- Arnaldo

>  {
> +	u64 read_format = evsel->attr.read_format;
> +	struct perf_evlist *evlist = evsel->evlist;
> +	struct perf_sample_id *sid;
> +	perf_freq_t data = { 0 };
> +	u64 cpu_max_freq = evlist->env->cpuattr.max_freq;
> +
>  	printf("... sample_read:\n");
>  
>  	if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
> @@ -902,10 +908,26 @@ static void sample_read__printf(struct perf_sample *sample, u64 read_format)
>  			printf("..... id %016" PRIx64
>  			       ", value %016" PRIx64 "\n",
>  			       value->id, value->value);
> +
> +			sid = perf_evlist__id2sid(evlist, value->id);
> +			evsel = sid->evsel;
> +			if (evsel != NULL)
> +				perf_freq__init(evlist->env->msr_pmu_type,
> +						evsel, data, value->value);
>  		}
>  	} else
>  		printf("..... id %016" PRIx64 ", value %016" PRIx64 "\n",
>  			sample->read.one.id, sample->read.one.value);
> +
> +	if (perf_freq__has_freq(data))
> +		printf("..... Freq %lu MHz\n",
> +		       perf_freq__get_freq(data, cpu_max_freq/1000));
> +	if (perf_freq__has_cpu_util(data))
> +		printf("..... CPU%% %lu%%\n",
> +		       perf_freq__get_cpu_util(data));
> +	if (perf_freq__has_core_busy(data))
> +		printf("..... CORE_BUSY%% %lu%%\n",
> +		       perf_freq__get_core_busy(data));
>  }
>  
>  static void dump_event(struct perf_evlist *evlist, union perf_event *event,
> @@ -965,7 +987,7 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
>  		printf("... transaction: %" PRIx64 "\n", sample->transaction);
>  
>  	if (sample_type & PERF_SAMPLE_READ)
> -		sample_read__printf(sample, evsel->attr.read_format);
> +		sample_read__printf(sample, evsel);
>  }
>  
>  static struct machine *machines__find_for_cpumode(struct machines *machines,
> diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
> index 3915be7..83bf4a9 100644
> --- a/tools/perf/util/session.h
> +++ b/tools/perf/util/session.h
> @@ -11,6 +11,7 @@
>  #include "ordered-events.h"
>  #include <linux/rbtree.h>
>  #include <linux/perf_event.h>
> +#include "evsel.h"
>  
>  struct ip_callchain;
>  struct thread;
> @@ -42,6 +43,10 @@ struct perf_session {
>  #define PRINT_IP_OPT_ONELINE	(1<<4)
>  #define PRINT_IP_OPT_SRCLINE	(1<<5)
>  
> +#define PERF_MSR_TSC		0
> +#define PERF_MSR_APERF		1
> +#define PERF_MSR_MPERF		2
> +
>  enum perf_freq_perf_index {
>  	FREQ_PERF_TSC		= 0,
>  	FREQ_PERF_APERF		= 1,
> @@ -52,6 +57,55 @@ enum perf_freq_perf_index {
>  	FREQ_PERF_MAX
>  };
>  
> +typedef u64 perf_freq_t[FREQ_PERF_MAX];
> +
> +static inline void perf_freq__init(unsigned int msr_pmu_type,
> +			    struct perf_evsel *evsel,
> +			    perf_freq_t array,
> +			    u64 value)
> +{
> +	if (evsel->attr.type == msr_pmu_type) {
> +		if (evsel->attr.config == PERF_MSR_TSC)
> +			array[FREQ_PERF_TSC] = value;
> +		if (evsel->attr.config == PERF_MSR_APERF)
> +			array[FREQ_PERF_APERF] = value;
> +		if (evsel->attr.config == PERF_MSR_MPERF)
> +			array[FREQ_PERF_MPERF] = value;
> +	}
> +	if (evsel->attr.type == PERF_TYPE_HARDWARE) {
> +		if (evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES)
> +			array[FREQ_PERF_CYCLES] = value;
> +		if (evsel->attr.config == PERF_COUNT_HW_REF_CPU_CYCLES)
> +			array[FREQ_PERF_REF_CYCLES] = value;
> +	}
> +}
> +
> +static inline bool perf_freq__has_freq(perf_freq_t array)
> +{
> +	return ((array[FREQ_PERF_CYCLES] > 0) && (array[FREQ_PERF_REF_CYCLES] > 0));
> +}
> +static inline u64 perf_freq__get_freq(perf_freq_t array, u64 cpu_max_freq)
> +{
> +	return ((array[FREQ_PERF_CYCLES] * cpu_max_freq) / array[FREQ_PERF_REF_CYCLES]);
> +}
> +static inline bool perf_freq__has_cpu_util(perf_freq_t array)
> +{
> +	return ((array[FREQ_PERF_TSC] > 0) && (array[FREQ_PERF_REF_CYCLES] > 0));
> +}
> +static inline u64 perf_freq__get_cpu_util(perf_freq_t array)
> +{
> +	return ((100 * array[FREQ_PERF_REF_CYCLES]) / array[FREQ_PERF_TSC]);
> +}
> +
> +static inline bool perf_freq__has_core_busy(perf_freq_t array)
> +{
> +	return ((array[FREQ_PERF_APERF] > 0) && (array[FREQ_PERF_MPERF] > 0));
> +}
> +static inline u64 perf_freq__get_core_busy(perf_freq_t array)
> +{
> +	return ((100 * array[FREQ_PERF_APERF]) / array[FREQ_PERF_MPERF]);
> +}
> +
>  struct perf_tool;
>  
>  struct perf_session *perf_session__new(struct perf_data_file *file,
> -- 
> 1.8.3.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH V9 1/6] perf,tools: introduce generic FEAT for CPU attributes
  2015-09-10 13:58   ` Arnaldo Carvalho de Melo
@ 2015-09-10 15:35     ` Arnaldo Carvalho de Melo
  2015-09-10 20:50       ` Liang, Kan
  0 siblings, 1 reply; 17+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-09-10 15:35 UTC (permalink / raw)
  To: kan.liang
  Cc: Jiri Olsa, Peter Zijlstra, luto, Ingo Molnar, Stephane Eranian,
	ak, mark.rutland, adrian.hunter, Namhyung Kim, linux-kernel

Em Thu, Sep 10, 2015 at 10:58:38AM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Tue, Sep 08, 2015 at 03:32:44PM -0400, kan.liang@intel.com escreveu:
> > This patch introduces generic FEAT for CPU attributes. For the patch
> > set, we only need cpu max frequency. But it can be easily extented to
> > support more other CPU attributes.
> > The cpu max frequency is from the first online cpu.
 
> Ok, but don't we have to do error handling? i.e. you are returning 0 for
> any error in trying to read the cpu max freq, shouldn't we bail out
> somewhere?
 
> And please move this get_cpu_max_freq() thing out of the cpumap.[ch]
> files, it is not even a need completely specific to perf tooling, there
> must be somewhere in tools/lib/api/ (kernel APIs) where this fits, no?

So, I've updated my perf/env branch with routines to do that, that uses
infrastructure to read files from virtual dirs that was there plus a few
I just introduced, in the same vein, I will update your patches to use
them and put there as well, for your consideration.

The HEAD there is the one below:

- Arnaldo

commit 2bc1fae4ed8a842f52dc374449d37c3ec1fa1986
Author: Arnaldo Carvalho de Melo <acme@redhat.com>
Date:   Thu Sep 10 12:20:14 2015 -0300

    tools lib cpu: Introduce cpu.[ch] to read sysfs cpu related information
    
    E.g.:
    
     $ ./cpu__get_max_freq
     3200000
    
    It does that, as Kan's patch does, by looking at these files:
    
      $ cat /sys/devices/system/cpu/online
      0-3
      $ ./sysfs__read_ull
      devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq
      /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq=3200000
      $
    
    I.e. find out the first online CPU, then read its cpufreq info.
    
    But do it in tools/lib/api/, so that other tools living code can use
    it, not just perf.
    
    Based-on-a-patch-by: Kan Liang <kan.liang@intel.com>
    Cc: Adrian Hunter <adrian.hunter@intel.com>
    Cc: Borislav Petkov <bp@suse.de>
    Cc: David Ahern <dsahern@gmail.com>
    Cc: Frederic Weisbecker <fweisbec@gmail.com>
    Cc: Jiri Olsa <jolsa@redhat.com>
    Cc: Namhyung Kim <namhyung@kernel.org>
    Cc: Stephane Eranian <eranian@google.com>
    Link: http://lkml.kernel.org/n/tip-915v4cvxqplaub8qco66b9mv@git.kernel.org
    Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

diff --git a/tools/lib/api/Build b/tools/lib/api/Build
index 3653965cf481..e8b8a23b9bf4 100644
--- a/tools/lib/api/Build
+++ b/tools/lib/api/Build
@@ -1,2 +1,3 @@
 libapi-y += fd/
 libapi-y += fs/
+libapi-y += cpu.o
diff --git a/tools/lib/api/cpu.c b/tools/lib/api/cpu.c
new file mode 100644
index 000000000000..8c6489356e3a
--- /dev/null
+++ b/tools/lib/api/cpu.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+
+#include "cpu.h"
+#include "fs/fs.h"
+
+int cpu__get_max_freq(unsigned long long *freq)
+{
+	char entry[PATH_MAX];
+	int cpu;
+
+	if (sysfs__read_int("devices/system/cpu/online", &cpu) < 0)
+		return -1;
+
+	snprintf(entry, sizeof(entry),
+		 "devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", cpu);
+
+	return sysfs__read_ull(entry, freq);
+}
diff --git a/tools/lib/api/cpu.h b/tools/lib/api/cpu.h
new file mode 100644
index 000000000000..81e9d3955961
--- /dev/null
+++ b/tools/lib/api/cpu.h
@@ -0,0 +1,6 @@
+#ifndef __API_CPU__
+#define __API_CPU__
+
+int cpu__get_max_freq(unsigned long long *freq);
+
+#endif /* __API_CPU__ */

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* RE: [PATCH V9 1/6] perf,tools: introduce generic FEAT for CPU attributes
  2015-09-10 15:35     ` Arnaldo Carvalho de Melo
@ 2015-09-10 20:50       ` Liang, Kan
  0 siblings, 0 replies; 17+ messages in thread
From: Liang, Kan @ 2015-09-10 20:50 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Peter Zijlstra, luto, Ingo Molnar, Stephane Eranian,
	ak, mark.rutland, Hunter, Adrian, Namhyung Kim, linux-kernel

> 
> Em Thu, Sep 10, 2015 at 10:58:38AM -0300, Arnaldo Carvalho de Melo
> escreveu:
> > Em Tue, Sep 08, 2015 at 03:32:44PM -0400, kan.liang@intel.com escreveu:
> > > This patch introduces generic FEAT for CPU attributes. For the patch
> > > set, we only need cpu max frequency. But it can be easily extented
> > > to support more other CPU attributes.
> > > The cpu max frequency is from the first online cpu.
> 
> > Ok, but don't we have to do error handling? i.e. you are returning 0
> > for any error in trying to read the cpu max freq, shouldn't we bail
> > out somewhere?
> 
> > And please move this get_cpu_max_freq() thing out of the cpumap.[ch]
> > files, it is not even a need completely specific to perf tooling,
> > there must be somewhere in tools/lib/api/ (kernel APIs) where this fits,
> no?
> 
> So, I've updated my perf/env branch with routines to do that, that uses
> infrastructure to read files from virtual dirs that was there plus a few I just
> introduced, in the same vein

The two new patches in perf/env are good to me.
Commit 4ee5cc5708d89f380ab5371181b65dd74935352d
Commit 57d54be1e9074049c8695c522a499f8a7d62ef2d
Acked-by: Kan Liang <kan.liang@intel.com>

> I will update your patches to use them and
> put there as well, for your consideration.
> 

Thanks. Please let me know, when you finished.
I will update the rest of the per-sample freq patches, and repost them
for review then.

Thanks,
Kan

> The HEAD there is the one below:
> 
> - Arnaldo
> 
> commit 2bc1fae4ed8a842f52dc374449d37c3ec1fa1986
> Author: Arnaldo Carvalho de Melo <acme@redhat.com>
> Date:   Thu Sep 10 12:20:14 2015 -0300
> 
>     tools lib cpu: Introduce cpu.[ch] to read sysfs cpu related information
> 
>     E.g.:
> 
>      $ ./cpu__get_max_freq
>      3200000
> 
>     It does that, as Kan's patch does, by looking at these files:
> 
>       $ cat /sys/devices/system/cpu/online
>       0-3
>       $ ./sysfs__read_ull
>       devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq
>       /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq=3200000
>       $
> 
>     I.e. find out the first online CPU, then read its cpufreq info.
> 
>     But do it in tools/lib/api/, so that other tools living code can use
>     it, not just perf.
> 
>     Based-on-a-patch-by: Kan Liang <kan.liang@intel.com>
>     Cc: Adrian Hunter <adrian.hunter@intel.com>
>     Cc: Borislav Petkov <bp@suse.de>
>     Cc: David Ahern <dsahern@gmail.com>
>     Cc: Frederic Weisbecker <fweisbec@gmail.com>
>     Cc: Jiri Olsa <jolsa@redhat.com>
>     Cc: Namhyung Kim <namhyung@kernel.org>
>     Cc: Stephane Eranian <eranian@google.com>
>     Link: http://lkml.kernel.org/n/tip-
> 915v4cvxqplaub8qco66b9mv@git.kernel.org
>     Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
> 
> diff --git a/tools/lib/api/Build b/tools/lib/api/Build index
> 3653965cf481..e8b8a23b9bf4 100644
> --- a/tools/lib/api/Build
> +++ b/tools/lib/api/Build
> @@ -1,2 +1,3 @@
>  libapi-y += fd/
>  libapi-y += fs/
> +libapi-y += cpu.o
> diff --git a/tools/lib/api/cpu.c b/tools/lib/api/cpu.c new file mode 100644
> index 000000000000..8c6489356e3a
> --- /dev/null
> +++ b/tools/lib/api/cpu.c
> @@ -0,0 +1,18 @@
> +#include <stdio.h>
> +
> +#include "cpu.h"
> +#include "fs/fs.h"
> +
> +int cpu__get_max_freq(unsigned long long *freq) {
> +	char entry[PATH_MAX];
> +	int cpu;
> +
> +	if (sysfs__read_int("devices/system/cpu/online", &cpu) < 0)
> +		return -1;
> +
> +	snprintf(entry, sizeof(entry),
> +		 "devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq",
> cpu);
> +
> +	return sysfs__read_ull(entry, freq);
> +}
> diff --git a/tools/lib/api/cpu.h b/tools/lib/api/cpu.h new file mode 100644
> index 000000000000..81e9d3955961
> --- /dev/null
> +++ b/tools/lib/api/cpu.h
> @@ -0,0 +1,6 @@
> +#ifndef __API_CPU__
> +#define __API_CPU__
> +
> +int cpu__get_max_freq(unsigned long long *freq);
> +
> +#endif /* __API_CPU__ */

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH V9 3/6] perf, record: introduce --freq-perf option
  2015-09-08 19:32 ` [PATCH V9 3/6] perf, record: introduce --freq-perf option kan.liang
  2015-09-09 14:34   ` Jiri Olsa
@ 2015-09-14 21:14   ` Arnaldo Carvalho de Melo
  1 sibling, 0 replies; 17+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-09-14 21:14 UTC (permalink / raw)
  To: kan.liang
  Cc: jolsa, a.p.zijlstra, luto, mingo, eranian, ak, mark.rutland,
	adrian.hunter, namhyung, linux-kernel

Em Tue, Sep 08, 2015 at 03:32:46PM -0400, kan.liang@intel.com escreveu:
> From: Kan Liang <kan.liang@intel.com>
> 
> To generate the frequency and performance output, perf must sample read
> special events like cycles, ref-cycles, msr/tsc/, msr/aperf/ or
> msr/mperf/.
> With the --freq-perf option, perf record can automatically check and add
> those event into evlist for sampling read.
> 
> Signed-off-by: Kan Liang <kan.liang@intel.com>
> ---
>  tools/perf/Documentation/perf-record.txt |  4 ++++
>  tools/perf/builtin-record.c              | 39 +++++++++++++++++++++++++++++++-
>  tools/perf/util/session.h                | 10 ++++++++
>  3 files changed, 52 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
> index 2e9ce77..3f40712 100644
> --- a/tools/perf/Documentation/perf-record.txt
> +++ b/tools/perf/Documentation/perf-record.txt
> @@ -308,6 +308,10 @@ This option sets the time out limit. The default value is 500 ms.
>  Record context switch events i.e. events of type PERF_RECORD_SWITCH or
>  PERF_RECORD_SWITCH_CPU_WIDE.
>  
> +--freq-perf::
> +Add frequency and performance related events to do sample read.
> +These events include cycles, ref-cycles, msr/tsc/, msr/aperf/ and msr/mperf/.
> +
>  SEE ALSO
>  --------
>  linkperf:perf-stat[1], linkperf:perf-list[1]
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index 142eeb3..e87dda3 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -13,7 +13,7 @@
>  #include "util/util.h"
>  #include "util/parse-options.h"
>  #include "util/parse-events.h"
> -
> +#include "util/pmu.h"
>  #include "util/callchain.h"
>  #include "util/cgroup.h"
>  #include "util/header.h"
> @@ -50,6 +50,7 @@ struct record {
>  	bool			no_buildid;
>  	bool			no_buildid_cache;
>  	long			samples;
> +	bool			freq_perf;
>  };
>  
>  static int record__write(struct record *rec, void *bf, size_t size)
> @@ -948,6 +949,35 @@ out_free:
>  	return ret;
>  }
>  
> +const char *freq_perf_events[FREQ_PERF_MAX][3] = {
> +	{ "msr", "tsc", "msr/tsc/" },
> +	{ "msr", "aperf", "msr/aperf/" },
> +	{ "msr", "mperf", "msr/mperf/" },
> +	{ NULL, "cycles", "cycles" },
> +	{ NULL, "ref-cycles", "ref-cycles" },
> +};
> +
> +static int
> +record_add_freq_perf_events(struct perf_evlist *evlist)
> +{
> +	int i;
> +	char freq_perf_attrs[100];
> +
> +	strcpy(freq_perf_attrs, "{cycles,ref-cycles");
> +	for (i = 0; i < FREQ_PERF_MAX; i++) {
> +		if ((i == FREQ_PERF_CYCLES) ||
> +		    (i == FREQ_PERF_REF_CYCLES))
> +			continue;
> +		if (pmu_have_event(freq_perf_events[i][0], freq_perf_events[i][1])) {
> +			strcat(freq_perf_attrs, ",");
> +			strcat(freq_perf_attrs, freq_perf_events[i][2]);
> +		}
> +	}
> +	strcat(freq_perf_attrs, "}:S");
> +
> +	return parse_events(evlist, freq_perf_attrs, NULL);
> +}
> +
>  static const char * const __record_usage[] = {
>  	"perf record [<options>] [<command>]",
>  	"perf record [<options>] -- <command> [<options>]",
> @@ -1096,6 +1126,8 @@ struct option __record_options[] = {
>  			"per thread proc mmap processing timeout in ms"),
>  	OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
>  		    "Record context switch events"),
> +	OPT_BOOLEAN(0, "freq-perf", &record.freq_perf,
> +		    "Add frequency and performance related events to do sample read."),

	Isn't this too vague? Can you try rewriting it? what do you mean
with "performance related events"?

	You forgot to add the entry to
tools/perf/Documentation/perf-record.txt, where a less terse explanation
could have helped me understand the part above, oops, sorry, you added
it, but it was really terse! Can you elaborate a bit? Why would one want
to use this? To achieve what? Don't assume everybody knows :-)

>  	OPT_END()
>  };
>  
> @@ -1157,6 +1189,11 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
>  	if (rec->no_buildid_cache || rec->no_buildid)
>  		disable_buildid_cache();
>  
> +	if (rec->freq_perf && record_add_freq_perf_events(rec->evlist)) {
> +		pr_err("Cannot set up freq and performance events\n");
> +		goto out_symbol_exit;
> +	}
> +
>  	if (rec->evlist->nr_entries == 0 &&
>  	    perf_evlist__add_default(rec->evlist) < 0) {
>  		pr_err("Not enough memory for event selector list\n");
> diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
> index b44afc7..3915be7 100644
> --- a/tools/perf/util/session.h
> +++ b/tools/perf/util/session.h
> @@ -42,6 +42,16 @@ struct perf_session {
>  #define PRINT_IP_OPT_ONELINE	(1<<4)
>  #define PRINT_IP_OPT_SRCLINE	(1<<5)
>  
> +enum perf_freq_perf_index {

That is really an overly long enum name! What about:

	enum perf_freqs {
		PERF_FREQ_TSC,
		...
	}

> +	FREQ_PERF_TSC		= 0,
> +	FREQ_PERF_APERF		= 1,
> +	FREQ_PERF_MPERF		= 2,
> +	FREQ_PERF_CYCLES	= 3,
> +	FREQ_PERF_REF_CYCLES	= 4,
> +
> +	FREQ_PERF_MAX
> +};
> +
>  struct perf_tool;
>  
>  struct perf_session *perf_session__new(struct perf_data_file *file,
> -- 
> 1.8.3.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH V9 2/6] perf,tools: read msr pmu type from header.
  2015-09-08 19:32 ` [PATCH V9 2/6] perf,tools: read msr pmu type from header kan.liang
  2015-09-10 13:59   ` Arnaldo Carvalho de Melo
@ 2015-09-14 21:16   ` Arnaldo Carvalho de Melo
  1 sibling, 0 replies; 17+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-09-14 21:16 UTC (permalink / raw)
  To: kan.liang
  Cc: jolsa, a.p.zijlstra, luto, mingo, eranian, ak, mark.rutland,
	adrian.hunter, namhyung, linux-kernel

Em Tue, Sep 08, 2015 at 03:32:45PM -0400, kan.liang@intel.com escreveu:
> From: Kan Liang <kan.liang@intel.com>
> 
> Get msr pmu type when processing pmu_mappings
> 
> Signed-off-by: Kan Liang <kan.liang@intel.com>
> Acked-by: Jiri Olsa <jolsa@kernel.org>

This one is simple enough, merged already.

- Arnaldo

> ---
>  tools/perf/util/header.c | 3 +++
>  tools/perf/util/header.h | 1 +
>  2 files changed, 4 insertions(+)
> 
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> index 3535dcb..04f415d 100644
> --- a/tools/perf/util/header.c
> +++ b/tools/perf/util/header.c
> @@ -1879,6 +1879,9 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused
>  		/* include a NULL character at the end */
>  		strbuf_add(&sb, "", 1);
>  
> +		if (!strcmp(name, "msr"))
> +			ph->env.msr_pmu_type = type;
> +
>  		free(name);
>  		pmu_num--;
>  	}
> diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
> index dd9f6b0..d9034e8 100644
> --- a/tools/perf/util/header.h
> +++ b/tools/perf/util/header.h
> @@ -107,6 +107,7 @@ struct perf_env {
>  			u64	max_freq;
>  		} cpuattr;
>  	};
> +	unsigned int		msr_pmu_type;
>  };
>  
>  struct perf_header {
> -- 
> 1.8.3.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2015-09-14 21:16 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-08 19:32 [PATCH V9 0/6] Freq/CPU%/CORE_BUSY% support kan.liang
2015-09-08 19:32 ` [PATCH V9 1/6] perf,tools: introduce generic FEAT for CPU attributes kan.liang
2015-09-10 13:58   ` Arnaldo Carvalho de Melo
2015-09-10 15:35     ` Arnaldo Carvalho de Melo
2015-09-10 20:50       ` Liang, Kan
2015-09-08 19:32 ` [PATCH V9 2/6] perf,tools: read msr pmu type from header kan.liang
2015-09-10 13:59   ` Arnaldo Carvalho de Melo
2015-09-14 21:16   ` Arnaldo Carvalho de Melo
2015-09-08 19:32 ` [PATCH V9 3/6] perf, record: introduce --freq-perf option kan.liang
2015-09-09 14:34   ` Jiri Olsa
2015-09-14 21:14   ` Arnaldo Carvalho de Melo
2015-09-08 19:32 ` [PATCH V9 4/6] perf,tools: Dump per-sample freq/CPU%/CORE_BUSY% in report -D kan.liang
2015-09-10 14:21   ` Arnaldo Carvalho de Melo
2015-09-08 19:32 ` [PATCH V9 5/6] perf,tools: caculate and save freq/CPU%/CORE_BUSY% in he_stat kan.liang
2015-09-08 19:32 ` [PATCH V9 6/6] perf,tools: Show freq/CPU%/CORE_BUSY% in perf report by --freq-perf kan.liang
2015-09-09 14:36   ` Jiri Olsa
2015-09-09 14:39 ` [PATCH V9 0/6] Freq/CPU%/CORE_BUSY% support Jiri Olsa

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.