linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/4] perf record: Provide detailed information on s390 CPU
@ 2018-02-13 15:14 Thomas Richter
  2018-02-13 15:14 ` [PATCH 2/4] perf annotate: Scan cpuid for s390 and save machine type Thomas Richter
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Thomas Richter @ 2018-02-13 15:14 UTC (permalink / raw)
  To: linux-kernel, linux-perf-users, acme
  Cc: brueckner, schwidefsky, heiko.carstens, Thomas Richter

When perf record ... is setup to record data, the s390
cpu information was a fixed string "IBM/S390".

Replace this string with one containing more information
about the machine. The information included in the cpuid is
a comma separated list:
   manufacturer,type,model-capacity,model[,version,authorization]
with

- manufacturer: up to 16 byte name of the manufacturer (IBM).
- type: a four digit number refering to the machine
  generation.
- model-capacitiy: up to 16 characters describing number
  of cpus etc.
- model: up to 16 characters describing model.
- version: the CPU-MF counter facility version number,
  available on LPARs only, omitted on z/VM guests.
- authorization: the CPU-MF counter facility authorization level,
  available on LPARs only, omitted on z/VM guests.

Before:
[root@s8360047 perf]# ./perf record -- sleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.001 MB perf.data (4 samples) ]
[root@s8360047 perf]# ./perf report --header | fgrep cpuid
 # cpuid : IBM/S390
[root@s8360047 perf]#

After:
[root@s35lp76 perf]# ./perf report --header|fgrep cpuid
 # cpuid : IBM,3906,704,M03,3.5,002f
[root@s35lp76 perf]#

Signed-off-by: Thomas Richter <tmricht@linux.vnet.ibm.com>
Reviewed-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
---
 tools/perf/arch/s390/util/header.c | 126 +++++++++++++++++++++++++++++++++++--
 1 file changed, 121 insertions(+), 5 deletions(-)

diff --git a/tools/perf/arch/s390/util/header.c b/tools/perf/arch/s390/util/header.c
index 9fa6c3e5782c..3d29ba47edce 100644
--- a/tools/perf/arch/s390/util/header.c
+++ b/tools/perf/arch/s390/util/header.c
@@ -1,8 +1,9 @@
 /*
  * Implementation of get_cpuid().
  *
- * Copyright 2014 IBM Corp.
+ * Copyright IBM Corp. 2014, 2018
  * Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.com>
+ *	      Thomas Richter <tmricht@linux.vnet.ibm.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License (version 2 only)
@@ -13,16 +14,131 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <string.h>
+#include <ctype.h>
 
 #include "../../util/header.h"
+#include "../../util/util.h"
+
+#define SYSINFO_MANU	"Manufacturer:"
+#define SYSINFO_TYPE	"Type:"
+#define SYSINFO_MODEL	"Model:"
+#define SRVLVL_CPUMF	"CPU-MF:"
+#define SRVLVL_VERSION	"version="
+#define SRVLVL_AUTHORIZATION	"authorization="
+#define SYSINFO		"/proc/sysinfo"
+#define SRVLVL		"/proc/service_levels"
 
 int get_cpuid(char *buffer, size_t sz)
 {
-	const char *cpuid = "IBM/S390";
+	char *cp, *line = NULL, *line2;
+	char type[8], model[33], version[8], manufacturer[32], authorization[8];
+	int read;
+	unsigned long line_sz;
+	size_t nbytes;
+	FILE *sysinfo;
+
+	/*
+	 * Scan /proc/sysinfo line by line and read out values for
+	 * Manufacturer:, Type: and Model:, for example:
+	 * Manufacturer:    IBM
+	 * Type:            2964
+	 * Model:           702              N96
+	 * The first word is the Model Capacity and the second word is
+	 * Model (can be omitted). Both words have a maximum size of 16
+	 * bytes.
+	 */
+	memset(manufacturer, 0, sizeof(manufacturer));
+	memset(type, 0, sizeof(type));
+	memset(model, 0, sizeof(model));
+	memset(version, 0, sizeof(version));
+	memset(authorization, 0, sizeof(authorization));
+
+	sysinfo = fopen(SYSINFO, "r");
+	if (sysinfo == NULL)
+		return -1;
+
+	while ((read = getline(&line, &line_sz, sysinfo)) != -1) {
+		if (!strncmp(line, SYSINFO_MANU, strlen(SYSINFO_MANU))) {
+			line2 = line + strlen(SYSINFO_MANU);
+
+			while ((cp = strtok_r(line2, "\n ", &line2)))
+				strncat(manufacturer, cp, sizeof(manufacturer));
+		}
+
+		if (!strncmp(line, SYSINFO_TYPE, strlen(SYSINFO_TYPE))) {
+			line2 = line + strlen(SYSINFO_TYPE);
+
+			while ((cp = strtok_r(line2, "\n ", &line2)))
+				strncat(type, cp, sizeof(type));
+		}
+
+		if (!strncmp(line, SYSINFO_MODEL, strlen(SYSINFO_MODEL))) {
+			line2 = line + strlen(SYSINFO_MODEL);
+
+			while ((cp = strtok_r(line2, "\n ", &line2))) {
+				if (model[0])
+					strcat(model, ",");
+				if (strlen(model) + strlen(cp) < sizeof(model))
+					strncat(model, cp, strlen(cp));
+			}
+			break;
+		}
+	}
+	fclose(sysinfo);
 
-	if (strlen(cpuid) + 1 > sz)
+	/* Missing manufacturer, type or model information should not happen */
+	if (!manufacturer[0] || !type[0] || !model[0])
 		return -1;
 
-	strcpy(buffer, cpuid);
-	return 0;
+	/*
+	 * Scan /proc/service_levels and return the CPU-MF counter facility
+	 * version number and authorization level.
+	 * Optional, does not exist on z/VM guests.
+	 */
+	sysinfo = fopen(SRVLVL, "r");
+	if (sysinfo == NULL)
+		goto skip_sysinfo;
+	while ((read = getline(&line, &line_sz, sysinfo)) != -1) {
+		if (strncmp(line, SRVLVL_CPUMF, strlen(SRVLVL_CPUMF)))
+			continue;
+
+		line2 = line + strlen(SRVLVL_CPUMF);
+		while ((cp = strtok_r(line2, "\n ", &line2))) {
+			if (!strncmp(cp, SRVLVL_VERSION,
+				     strlen(SRVLVL_VERSION))) {
+				char *sep = strchr(cp, '=');
+
+				strncat(version, sep + 1, sizeof(version));
+			}
+			if (!strncmp(cp, SRVLVL_AUTHORIZATION,
+				     strlen(SRVLVL_AUTHORIZATION))) {
+				char *sep = strchr(cp, '=');
+
+				strncat(authorization, sep + 1,
+					sizeof(authorization));
+			}
+		}
+	}
+	fclose(sysinfo);
+
+skip_sysinfo:
+	free(line);
+
+	if (version[0] && authorization[0] )
+		nbytes = snprintf(buffer, sz, "%s,%s,%s,%s,%s",
+				  manufacturer, type, model, version,
+				  authorization);
+	else
+		nbytes = snprintf(buffer, sz, "%s,%s,%s", manufacturer, type,
+				  model);
+	return (nbytes >= sz) ? -1 : 0;
+}
+
+char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
+{
+	char *buf = malloc(128);
+
+	if (buf && get_cpuid(buf, 128) < 0)
+		zfree(&buf);
+	return buf;
 }
-- 
2.14.3

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

* [PATCH 2/4] perf annotate: Scan cpuid for s390 and save machine type
  2018-02-13 15:14 [PATCH 1/4] perf record: Provide detailed information on s390 CPU Thomas Richter
@ 2018-02-13 15:14 ` Thomas Richter
  2018-02-17 11:37   ` [tip:perf/core] " tip-bot for Thomas Richter
  2018-02-13 15:14 ` [PATCH 3/4] perf cpuid: Introduce a platform specfic cpuid compare function Thomas Richter
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Thomas Richter @ 2018-02-13 15:14 UTC (permalink / raw)
  To: linux-kernel, linux-perf-users, acme
  Cc: brueckner, schwidefsky, heiko.carstens, Thomas Richter

Scan the cpuid string and extract the type number for later
use.

Signed-off-by: Thomas Richter <tmricht@linux.vnet.ibm.com>
Reviewed-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
---
 tools/perf/arch/s390/annotate/instructions.c | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/tools/perf/arch/s390/annotate/instructions.c b/tools/perf/arch/s390/annotate/instructions.c
index 8c72b44444cb..01df9d8303e1 100644
--- a/tools/perf/arch/s390/annotate/instructions.c
+++ b/tools/perf/arch/s390/annotate/instructions.c
@@ -23,12 +23,37 @@ static struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *na
 	return ops;
 }
 
+static int s390__cpuid_parse(struct arch *arch, char *cpuid)
+{
+	unsigned int family;
+	char model[16], model_c[16], cpumf_v[16], cpumf_a[16];
+	int ret;
+
+	/*
+	 * cpuid string format:
+	 * "IBM,family,model-capacity,model[,cpum_cf-version,cpum_cf-authorization]"
+	 */
+	ret = sscanf(cpuid, "%*[^,],%u,%[^,],%[^,],%[^,],%s", &family, model_c,
+		     model, cpumf_v, cpumf_a);
+	if (ret >= 2) {
+		arch->family = family;
+		arch->model = 0;
+		return 0;
+	}
+
+	return -1;
+}
+
 static int s390__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
 {
+	int err = 0;
+
 	if (!arch->initialized) {
 		arch->initialized = true;
 		arch->associate_instruction_ops = s390__associate_ins_ops;
+		if (cpuid)
+			err = s390__cpuid_parse(arch, cpuid);
 	}
 
-	return 0;
+	return err;
 }
-- 
2.14.3

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

* [PATCH 3/4] perf cpuid: Introduce a platform specfic cpuid compare function
  2018-02-13 15:14 [PATCH 1/4] perf record: Provide detailed information on s390 CPU Thomas Richter
  2018-02-13 15:14 ` [PATCH 2/4] perf annotate: Scan cpuid for s390 and save machine type Thomas Richter
@ 2018-02-13 15:14 ` Thomas Richter
  2018-02-17 11:38   ` [tip:perf/core] perf cpuid: Introduce a platform specific " tip-bot for Thomas Richter
  2018-02-13 15:14 ` [PATCH 4/4] perf test: Fix test case 23 for s390 z/VM or KVM guests Thomas Richter
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Thomas Richter @ 2018-02-13 15:14 UTC (permalink / raw)
  To: linux-kernel, linux-perf-users, acme
  Cc: brueckner, schwidefsky, heiko.carstens, Thomas Richter

The function get_cpuid_str() is called by perf_pmu__getcpuid()
and on s390 returns a complete description of the CPU and its
capabilities, which is a comma separated list.

To map the CPU type with the value defined in the
pmu-events/arch/s390/mapfile.csv, introduce an architecture
specific cpuid compare function named strcmp_cpuid_str()

The currently used regex algorithm is defined as the
weak default and will be used if no platform specific
one is defined. This matches the current behavior.

Signed-off-by: Thomas Richter <tmricht@linux.vnet.ibm.com>
Reviewed-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
---
 tools/perf/arch/s390/util/header.c | 18 +++++++++++++++
 tools/perf/util/header.h           |  1 +
 tools/perf/util/pmu.c              | 47 +++++++++++++++++++++++---------------
 3 files changed, 48 insertions(+), 18 deletions(-)

diff --git a/tools/perf/arch/s390/util/header.c b/tools/perf/arch/s390/util/header.c
index 3d29ba47edce..90360272ced6 100644
--- a/tools/perf/arch/s390/util/header.c
+++ b/tools/perf/arch/s390/util/header.c
@@ -142,3 +142,21 @@ char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
 		zfree(&buf);
 	return buf;
 }
+
+/*
+ * Compare the cpuid string returned by get_cpuid() function
+ * with the name generated by the jevents file read from
+ * pmu-events/arch/s390/mapfile.csv.
+ *
+ * Parameter mapcpuid is the cpuid as stored in the
+ * pmu-events/arch/s390/mapfile.csv. This is just the type number.
+ * Parameter cpuid is the cpuid returned by function get_cpuid().
+ */
+int strcmp_cpuid_str(const char *mapcpuid, const char *cpuid)
+{
+	char *cp = strchr(cpuid, ',');
+
+	if (cp == NULL)
+		return -1;
+	return strncmp(cp + 1, mapcpuid, strlen(mapcpuid));
+}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index f28aaaa3a440..942bdec6d70d 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -174,4 +174,5 @@ int write_padded(struct feat_fd *fd, const void *bf,
 int get_cpuid(char *buffer, size_t sz);
 
 char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused);
+int strcmp_cpuid_str(const char *s1, const char *s2);
 #endif /* __PERF_HEADER_H */
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 57e38fdf0b34..1111d5bf15ca 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -576,6 +576,34 @@ char * __weak get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
 	return NULL;
 }
 
+/* Return zero when the cpuid from the mapfile.csv matches the
+ * cpuid string generated on this platform.
+ * Otherwise return non-zero.
+ */
+int __weak strcmp_cpuid_str(const char *mapcpuid, const char *cpuid)
+{
+	regex_t re;
+	regmatch_t pmatch[1];
+	int match;
+
+	if (regcomp(&re, mapcpuid, REG_EXTENDED) != 0) {
+		/* Warn unable to generate match particular string. */
+		pr_info("Invalid regular expression %s\n", mapcpuid);
+		return 1;
+	}
+
+	match = !regexec(&re, cpuid, 1, pmatch, 0);
+	regfree(&re);
+	if (match) {
+		size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so);
+
+		/* Verify the entire string matched. */
+		if (match_len == strlen(cpuid))
+			return 0;
+	}
+	return 1;
+}
+
 static char *perf_pmu__getcpuid(struct perf_pmu *pmu)
 {
 	char *cpuid;
@@ -610,31 +638,14 @@ struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu)
 
 	i = 0;
 	for (;;) {
-		regex_t re;
-		regmatch_t pmatch[1];
-		int match;
-
 		map = &pmu_events_map[i++];
 		if (!map->table) {
 			map = NULL;
 			break;
 		}
 
-		if (regcomp(&re, map->cpuid, REG_EXTENDED) != 0) {
-			/* Warn unable to generate match particular string. */
-			pr_info("Invalid regular expression %s\n", map->cpuid);
+		if (!strcmp_cpuid_str(map->cpuid, cpuid))
 			break;
-		}
-
-		match = !regexec(&re, cpuid, 1, pmatch, 0);
-		regfree(&re);
-		if (match) {
-			size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so);
-
-			/* Verify the entire string matched. */
-			if (match_len == strlen(cpuid))
-				break;
-		}
 	}
 	free(cpuid);
 	return map;
-- 
2.14.3

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

* [PATCH 4/4] perf test: Fix test case 23 for s390 z/VM or KVM guests
  2018-02-13 15:14 [PATCH 1/4] perf record: Provide detailed information on s390 CPU Thomas Richter
  2018-02-13 15:14 ` [PATCH 2/4] perf annotate: Scan cpuid for s390 and save machine type Thomas Richter
  2018-02-13 15:14 ` [PATCH 3/4] perf cpuid: Introduce a platform specfic cpuid compare function Thomas Richter
@ 2018-02-13 15:14 ` Thomas Richter
  2018-02-17 11:38   ` [tip:perf/core] " tip-bot for Thomas Richter
  2018-02-15 14:50 ` [PATCH 1/4] perf record: Provide detailed information on s390 CPU Arnaldo Carvalho de Melo
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Thomas Richter @ 2018-02-13 15:14 UTC (permalink / raw)
  To: linux-kernel, linux-perf-users, acme
  Cc: brueckner, schwidefsky, heiko.carstens, Thomas Richter

On s390 perf can be executed on a LPAR with support
for hardware events (i. e. cycles) or on a z/VM or KVM guest
where no hardware events are supported. In this
environment use software event named cpu-clock
for this test case.

Use the cpuid infrastructure functions to determine
the cpuid on s390 which contains an indication of the
cpu counter facility availability.

Signed-off-by: Thomas Richter <tmricht@linux.vnet.ibm.com>
Reviewed-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
---
 tools/perf/tests/code-reading.c | 33 +++++++++++++++++++++++++++++----
 1 file changed, 29 insertions(+), 4 deletions(-)

diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 3bf7b145b826..c7115d369511 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -482,6 +482,34 @@ static void fs_something(void)
 	}
 }
 
+static const char *do_determine_event(bool excl_kernel)
+{
+	const char *event = excl_kernel ? "cycles:u" : "cycles";
+
+#ifdef __s390x__
+	char cpuid[128], model[16], model_c[16], cpum_cf_v[16];
+	unsigned int family;
+	int ret, cpum_cf_a;
+
+	if (get_cpuid(cpuid, sizeof(cpuid)))
+		goto out_clocks;
+	ret = sscanf(cpuid, "%*[^,],%u,%[^,],%[^,],%[^,],%x", &family, model_c,
+		     model, cpum_cf_v, &cpum_cf_a);
+	if (ret != 5)		 /* Not available */
+		goto out_clocks;
+	if (excl_kernel && (cpum_cf_a & 4))
+		return event;
+	if (!excl_kernel && (cpum_cf_a & 2))
+		return event;
+
+	/* Fall through: missing authorization */
+out_clocks:
+	event = excl_kernel ? "cpu-clock:u" : "cpu-clock";
+
+#endif
+	return event;
+}
+
 static void do_something(void)
 {
 	fs_something();
@@ -592,10 +620,7 @@ static int do_test_code_reading(bool try_kcore)
 
 		perf_evlist__set_maps(evlist, cpus, threads);
 
-		if (excl_kernel)
-			str = "cycles:u";
-		else
-			str = "cycles";
+		str = do_determine_event(excl_kernel);
 		pr_debug("Parsing event '%s'\n", str);
 		ret = parse_events(evlist, str, NULL);
 		if (ret < 0) {
-- 
2.14.3

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

* Re: [PATCH 1/4] perf record: Provide detailed information on s390 CPU
  2018-02-13 15:14 [PATCH 1/4] perf record: Provide detailed information on s390 CPU Thomas Richter
                   ` (2 preceding siblings ...)
  2018-02-13 15:14 ` [PATCH 4/4] perf test: Fix test case 23 for s390 z/VM or KVM guests Thomas Richter
@ 2018-02-15 14:50 ` Arnaldo Carvalho de Melo
  2018-02-16 16:55 ` Arnaldo Carvalho de Melo
  2018-02-17 11:37 ` [tip:perf/core] " tip-bot for Thomas Richter
  5 siblings, 0 replies; 11+ messages in thread
From: Arnaldo Carvalho de Melo @ 2018-02-15 14:50 UTC (permalink / raw)
  To: Thomas Richter
  Cc: linux-kernel, linux-perf-users, brueckner, schwidefsky, heiko.carstens

Em Tue, Feb 13, 2018 at 04:14:16PM +0100, Thomas Richter escreveu:
> When perf record ... is setup to record data, the s390
> cpu information was a fixed string "IBM/S390".
> 
> Replace this string with one containing more information
> about the machine. The information included in the cpuid is
> a comma separated list:
>    manufacturer,type,model-capacity,model[,version,authorization]
> with

Thanks, applied 1-4

- Arnaldo

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

* Re: [PATCH 1/4] perf record: Provide detailed information on s390 CPU
  2018-02-13 15:14 [PATCH 1/4] perf record: Provide detailed information on s390 CPU Thomas Richter
                   ` (3 preceding siblings ...)
  2018-02-15 14:50 ` [PATCH 1/4] perf record: Provide detailed information on s390 CPU Arnaldo Carvalho de Melo
@ 2018-02-16 16:55 ` Arnaldo Carvalho de Melo
  2018-02-16 18:17   ` Arnaldo Carvalho de Melo
  2018-02-17 11:37 ` [tip:perf/core] " tip-bot for Thomas Richter
  5 siblings, 1 reply; 11+ messages in thread
From: Arnaldo Carvalho de Melo @ 2018-02-16 16:55 UTC (permalink / raw)
  To: Thomas Richter
  Cc: linux-kernel, linux-perf-users, brueckner, schwidefsky, heiko.carstens

Em Tue, Feb 13, 2018 at 04:14:16PM +0100, Thomas Richter escreveu:
> When perf record ... is setup to record data, the s390
> cpu information was a fixed string "IBM/S390".
> 
> Replace this string with one containing more information
> about the machine. The information included in the cpuid is
> a comma separated list:
>    manufacturer,type,model-capacity,model[,version,authorization]
> with
> 
> - manufacturer: up to 16 byte name of the manufacturer (IBM).
> - type: a four digit number refering to the machine
>   generation.
> - model-capacitiy: up to 16 characters describing number
>   of cpus etc.
> - model: up to 16 characters describing model.
> - version: the CPU-MF counter facility version number,
>   available on LPARs only, omitted on z/VM guests.
> - authorization: the CPU-MF counter facility authorization level,
>   available on LPARs only, omitted on z/VM guests.
> 
> Before:
> [root@s8360047 perf]# ./perf record -- sleep 1
> [ perf record: Woken up 1 times to write data ]
> [ perf record: Captured and wrote 0.001 MB perf.data (4 samples) ]
> [root@s8360047 perf]# ./perf report --header | fgrep cpuid
>  # cpuid : IBM/S390
> [root@s8360047 perf]#


  49    38.13 ubuntu:16.04-x-s390           : FAIL s390x-linux-gnu-gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609


Humm, this seems to be the one causing this:

  LINK     /tmp/build/perf/plugin_hrtimer.so
  LINK     /tmp/build/perf/plugin_kmem.so
In file included from /usr/s390x-linux-gnu/include/string.h:635:0,
                 from arch/s390/util/header.c:16:
In function 'strncat',
    inlined from 'get_cpuid' at arch/s390/util/header.c:65:5:
/usr/s390x-linux-gnu/include/bits/string3.h:156:10: error: call to __builtin___strncat_chk might overflow destination buffer [-Werror]
   return __builtin___strncat_chk (__dest, __src, __len, __bos (__dest));
          ^
In function 'strncat',
    inlined from 'get_cpuid' at arch/s390/util/header.c:72:5:
/usr/s390x-linux-gnu/include/bits/string3.h:156:10: error: call to __builtin___strncat_chk might overflow destination buffer [-Werror]
   return __builtin___strncat_chk (__dest, __src, __len, __bos (__dest));
          ^
In function 'strncat',
    inlined from 'get_cpuid' at arch/s390/util/header.c:111:5:
/usr/s390x-linux-gnu/include/bits/string3.h:156:10: error: call to __builtin___strncat_chk might overflow destination buffer [-Werror]
   return __builtin___strncat_chk (__dest, __src, __len, __bos (__dest));
          ^
In function 'strncat',
    inlined from 'get_cpuid' at arch/s390/util/header.c:117:5:
/usr/s390x-linux-gnu/include/bits/string3.h:156:10: error: call to __builtin___strncat_chk might overflow destination buffer [-Werror]
   return __builtin___strncat_chk (__dest, __src, __len, __bos (__dest));
          ^
  LINK     /tmp/build/perf/plugin_kvm.so
  MKDIR    /tmp/build/perf/arch/s390/util/
  LINK     /tmp/build/perf/plugin_mac80211.so
  CC       /tmp/build/perf/arch/s390/util/kvm-stat.o
  LINK     /tmp/build/perf/plugin_sched_switch.so
cc1: all warnings being treated as errors
mv: cannot stat '/tmp/build/perf/arch/s390/util/.header.o.tmp': No such file or directory
/git/linux/tools/build/Makefile.build:96: recipe for target '/tmp/build/perf/arch/s390/util/header.o' failed
make[6]: *** [/tmp/build/perf/arch/s390/util/header.o] Error 1
make[6]: *** Waiting for unfinished jobs....
  LINK     /tmp/build/perf/plugin_function.so

 
> After:
> [root@s35lp76 perf]# ./perf report --header|fgrep cpuid
>  # cpuid : IBM,3906,704,M03,3.5,002f
> [root@s35lp76 perf]#
> 
> Signed-off-by: Thomas Richter <tmricht@linux.vnet.ibm.com>
> Reviewed-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
> ---
>  tools/perf/arch/s390/util/header.c | 126 +++++++++++++++++++++++++++++++++++--
>  1 file changed, 121 insertions(+), 5 deletions(-)
> 
> diff --git a/tools/perf/arch/s390/util/header.c b/tools/perf/arch/s390/util/header.c
> index 9fa6c3e5782c..3d29ba47edce 100644
> --- a/tools/perf/arch/s390/util/header.c
> +++ b/tools/perf/arch/s390/util/header.c
> @@ -1,8 +1,9 @@
>  /*
>   * Implementation of get_cpuid().
>   *
> - * Copyright 2014 IBM Corp.
> + * Copyright IBM Corp. 2014, 2018
>   * Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.com>
> + *	      Thomas Richter <tmricht@linux.vnet.ibm.com>
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License (version 2 only)
> @@ -13,16 +14,131 @@
>  #include <unistd.h>
>  #include <stdio.h>
>  #include <string.h>
> +#include <ctype.h>
>  
>  #include "../../util/header.h"
> +#include "../../util/util.h"
> +
> +#define SYSINFO_MANU	"Manufacturer:"
> +#define SYSINFO_TYPE	"Type:"
> +#define SYSINFO_MODEL	"Model:"
> +#define SRVLVL_CPUMF	"CPU-MF:"
> +#define SRVLVL_VERSION	"version="
> +#define SRVLVL_AUTHORIZATION	"authorization="
> +#define SYSINFO		"/proc/sysinfo"
> +#define SRVLVL		"/proc/service_levels"
>  
>  int get_cpuid(char *buffer, size_t sz)
>  {
> -	const char *cpuid = "IBM/S390";
> +	char *cp, *line = NULL, *line2;
> +	char type[8], model[33], version[8], manufacturer[32], authorization[8];
> +	int read;
> +	unsigned long line_sz;
> +	size_t nbytes;
> +	FILE *sysinfo;
> +
> +	/*
> +	 * Scan /proc/sysinfo line by line and read out values for
> +	 * Manufacturer:, Type: and Model:, for example:
> +	 * Manufacturer:    IBM
> +	 * Type:            2964
> +	 * Model:           702              N96
> +	 * The first word is the Model Capacity and the second word is
> +	 * Model (can be omitted). Both words have a maximum size of 16
> +	 * bytes.
> +	 */
> +	memset(manufacturer, 0, sizeof(manufacturer));
> +	memset(type, 0, sizeof(type));
> +	memset(model, 0, sizeof(model));
> +	memset(version, 0, sizeof(version));
> +	memset(authorization, 0, sizeof(authorization));
> +
> +	sysinfo = fopen(SYSINFO, "r");
> +	if (sysinfo == NULL)
> +		return -1;
> +
> +	while ((read = getline(&line, &line_sz, sysinfo)) != -1) {
> +		if (!strncmp(line, SYSINFO_MANU, strlen(SYSINFO_MANU))) {
> +			line2 = line + strlen(SYSINFO_MANU);
> +
> +			while ((cp = strtok_r(line2, "\n ", &line2)))
> +				strncat(manufacturer, cp, sizeof(manufacturer));
> +		}
> +
> +		if (!strncmp(line, SYSINFO_TYPE, strlen(SYSINFO_TYPE))) {
> +			line2 = line + strlen(SYSINFO_TYPE);
> +
> +			while ((cp = strtok_r(line2, "\n ", &line2)))
> +				strncat(type, cp, sizeof(type));
> +		}
> +
> +		if (!strncmp(line, SYSINFO_MODEL, strlen(SYSINFO_MODEL))) {
> +			line2 = line + strlen(SYSINFO_MODEL);
> +
> +			while ((cp = strtok_r(line2, "\n ", &line2))) {
> +				if (model[0])
> +					strcat(model, ",");
> +				if (strlen(model) + strlen(cp) < sizeof(model))
> +					strncat(model, cp, strlen(cp));
> +			}
> +			break;
> +		}
> +	}
> +	fclose(sysinfo);
>  
> -	if (strlen(cpuid) + 1 > sz)
> +	/* Missing manufacturer, type or model information should not happen */
> +	if (!manufacturer[0] || !type[0] || !model[0])
>  		return -1;
>  
> -	strcpy(buffer, cpuid);
> -	return 0;
> +	/*
> +	 * Scan /proc/service_levels and return the CPU-MF counter facility
> +	 * version number and authorization level.
> +	 * Optional, does not exist on z/VM guests.
> +	 */
> +	sysinfo = fopen(SRVLVL, "r");
> +	if (sysinfo == NULL)
> +		goto skip_sysinfo;
> +	while ((read = getline(&line, &line_sz, sysinfo)) != -1) {
> +		if (strncmp(line, SRVLVL_CPUMF, strlen(SRVLVL_CPUMF)))
> +			continue;
> +
> +		line2 = line + strlen(SRVLVL_CPUMF);
> +		while ((cp = strtok_r(line2, "\n ", &line2))) {
> +			if (!strncmp(cp, SRVLVL_VERSION,
> +				     strlen(SRVLVL_VERSION))) {
> +				char *sep = strchr(cp, '=');
> +
> +				strncat(version, sep + 1, sizeof(version));
> +			}
> +			if (!strncmp(cp, SRVLVL_AUTHORIZATION,
> +				     strlen(SRVLVL_AUTHORIZATION))) {
> +				char *sep = strchr(cp, '=');
> +
> +				strncat(authorization, sep + 1,
> +					sizeof(authorization));
> +			}
> +		}
> +	}
> +	fclose(sysinfo);
> +
> +skip_sysinfo:
> +	free(line);
> +
> +	if (version[0] && authorization[0] )
> +		nbytes = snprintf(buffer, sz, "%s,%s,%s,%s,%s",
> +				  manufacturer, type, model, version,
> +				  authorization);
> +	else
> +		nbytes = snprintf(buffer, sz, "%s,%s,%s", manufacturer, type,
> +				  model);
> +	return (nbytes >= sz) ? -1 : 0;
> +}
> +
> +char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
> +{
> +	char *buf = malloc(128);
> +
> +	if (buf && get_cpuid(buf, 128) < 0)
> +		zfree(&buf);
> +	return buf;
>  }
> -- 
> 2.14.3

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

* Re: [PATCH 1/4] perf record: Provide detailed information on s390 CPU
  2018-02-16 16:55 ` Arnaldo Carvalho de Melo
@ 2018-02-16 18:17   ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 11+ messages in thread
From: Arnaldo Carvalho de Melo @ 2018-02-16 18:17 UTC (permalink / raw)
  To: Thomas Richter
  Cc: linux-kernel, linux-perf-users, brueckner, schwidefsky, heiko.carstens

Em Fri, Feb 16, 2018 at 01:55:43PM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Tue, Feb 13, 2018 at 04:14:16PM +0100, Thomas Richter escreveu:
> 
> 
>   49    38.13 ubuntu:16.04-x-s390           : FAIL s390x-linux-gnu-gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
> 
> 
> Humm, this seems to be the one causing this:
> 
>   LINK     /tmp/build/perf/plugin_hrtimer.so
>   LINK     /tmp/build/perf/plugin_kmem.so
> In file included from /usr/s390x-linux-gnu/include/string.h:635:0,
>                  from arch/s390/util/header.c:16:
> In function 'strncat',
>     inlined from 'get_cpuid' at arch/s390/util/header.c:65:5:
> /usr/s390x-linux-gnu/include/bits/string3.h:156:10: error: call to __builtin___strncat_chk might overflow destination buffer [-Werror]
>    return __builtin___strncat_chk (__dest, __src, __len, __bos (__dest));

Ok, now I can build it:

[acme@seventh perf]$ file ../tmp/perf
../tmp/perf: ELF 64-bit MSB shared object, IBM S/390, version 1 (SYSV), dynamically linked, interpreter /lib/ld64.so.1, for GNU/Linux 3.2.0, BuildID[sha1]=82a8ff9eb04082acd1630a0f4ff3816d68982eb7, with debug_info, not stripped
[acme@seventh perf]$

With the following patch, using scnprintf (snprintf also has issues),
please try applying this on top of yours and checking that the end
result is sane.

- Arnaldo

diff --git a/tools/perf/arch/s390/util/header.c b/tools/perf/arch/s390/util/header.c
index 3d29ba47edce..a78064c25ced 100644
--- a/tools/perf/arch/s390/util/header.c
+++ b/tools/perf/arch/s390/util/header.c
@@ -32,6 +32,7 @@ int get_cpuid(char *buffer, size_t sz)
 {
 	char *cp, *line = NULL, *line2;
 	char type[8], model[33], version[8], manufacturer[32], authorization[8];
+	int tpsize = 0, mdsize = 0, vssize = 0, mfsize = 0, atsize = 0;
 	int read;
 	unsigned long line_sz;
 	size_t nbytes;
@@ -61,25 +62,27 @@ int get_cpuid(char *buffer, size_t sz)
 		if (!strncmp(line, SYSINFO_MANU, strlen(SYSINFO_MANU))) {
 			line2 = line + strlen(SYSINFO_MANU);
 
-			while ((cp = strtok_r(line2, "\n ", &line2)))
-				strncat(manufacturer, cp, sizeof(manufacturer));
+			while ((cp = strtok_r(line2, "\n ", &line2))) {
+				mfsize += scnprintf(manufacturer + mfsize,
+						    sizeof(manufacturer) - mfsize, "%s", cp);
+			}
 		}
 
 		if (!strncmp(line, SYSINFO_TYPE, strlen(SYSINFO_TYPE))) {
 			line2 = line + strlen(SYSINFO_TYPE);
 
-			while ((cp = strtok_r(line2, "\n ", &line2)))
-				strncat(type, cp, sizeof(type));
+			while ((cp = strtok_r(line2, "\n ", &line2))) {
+				tpsize += scnprintf(type + tpsize,
+						    sizeof(type) - tpsize, "%s", cp);
+			}
 		}
 
 		if (!strncmp(line, SYSINFO_MODEL, strlen(SYSINFO_MODEL))) {
 			line2 = line + strlen(SYSINFO_MODEL);
 
 			while ((cp = strtok_r(line2, "\n ", &line2))) {
-				if (model[0])
-					strcat(model, ",");
-				if (strlen(model) + strlen(cp) < sizeof(model))
-					strncat(model, cp, strlen(cp));
+				mdsize += scnprintf(model + mdsize, sizeof(type) - mdsize,
+						    "%s%s", model[0] ? "," : "", cp);
 			}
 			break;
 		}
@@ -108,14 +111,15 @@ int get_cpuid(char *buffer, size_t sz)
 				     strlen(SRVLVL_VERSION))) {
 				char *sep = strchr(cp, '=');
 
-				strncat(version, sep + 1, sizeof(version));
+				vssize += scnprintf(version + vssize,
+						    sizeof(version) - vssize, "%s", sep + 1);
 			}
 			if (!strncmp(cp, SRVLVL_AUTHORIZATION,
 				     strlen(SRVLVL_AUTHORIZATION))) {
 				char *sep = strchr(cp, '=');
 
-				strncat(authorization, sep + 1,
-					sizeof(authorization));
+				atsize += scnprintf(authorization + atsize,
+						    sizeof(authorization) - atsize, "%s", sep + 1);
 			}
 		}
 	}

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

* [tip:perf/core] perf record: Provide detailed information on s390 CPU
  2018-02-13 15:14 [PATCH 1/4] perf record: Provide detailed information on s390 CPU Thomas Richter
                   ` (4 preceding siblings ...)
  2018-02-16 16:55 ` Arnaldo Carvalho de Melo
@ 2018-02-17 11:37 ` tip-bot for Thomas Richter
  5 siblings, 0 replies; 11+ messages in thread
From: tip-bot for Thomas Richter @ 2018-02-17 11:37 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, acme, mingo, tmricht, tglx, schwidefsky, heiko.carstens,
	brueckner, linux-kernel

Commit-ID:  eca0fa28cd0df7369701dbee0e30ddce19c039b8
Gitweb:     https://git.kernel.org/tip/eca0fa28cd0df7369701dbee0e30ddce19c039b8
Author:     Thomas Richter <tmricht@linux.vnet.ibm.com>
AuthorDate: Tue, 13 Feb 2018 16:14:16 +0100
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Fri, 16 Feb 2018 15:15:23 -0300

perf record: Provide detailed information on s390 CPU

When perf record ... is setup to record data, the s390 cpu information
was a fixed string "IBM/S390".

Replace this string with one containing more information about the
machine. The information included in the cpuid is a comma separated
list:

   manufacturer,type,model-capacity,model[,version,authorization]
with

- manufacturer: up to 16 byte name of the manufacturer (IBM).
- type: a four digit number refering to the machine
  generation.
- model-capacitiy: up to 16 characters describing number
  of cpus etc.
- model: up to 16 characters describing model.
- version: the CPU-MF counter facility version number,
  available on LPARs only, omitted on z/VM guests.
- authorization: the CPU-MF counter facility authorization level,
  available on LPARs only, omitted on z/VM guests.

Before:

  [root@s8360047 perf]# ./perf record -- sleep 1
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 0.001 MB perf.data (4 samples) ]
  [root@s8360047 perf]# ./perf report --header | fgrep cpuid
   # cpuid : IBM/S390
  [root@s8360047 perf]#

After:

  [root@s35lp76 perf]# ./perf report --header|fgrep cpuid
   # cpuid : IBM,3906,704,M03,3.5,002f
  [root@s35lp76 perf]#

Signed-off-by: Thomas Richter <tmricht@linux.vnet.ibm.com>
Reviewed-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Link: http://lkml.kernel.org/r/20180213151419.80737-1-tmricht@linux.vnet.ibm.com
[ Use scnprintf instead of strncat to fix build errors on gcc GNU C99 5.4.0 20160609 -march=zEC12 -m64 -mzarch -ggdb3 -O6 -std=gnu99 -fPIC -fno-omit-frame-pointer -funwind-tables -fstack-protector-all ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/arch/s390/util/header.c | 130 +++++++++++++++++++++++++++++++++++--
 1 file changed, 125 insertions(+), 5 deletions(-)

diff --git a/tools/perf/arch/s390/util/header.c b/tools/perf/arch/s390/util/header.c
index 9fa6c3e..a78064c 100644
--- a/tools/perf/arch/s390/util/header.c
+++ b/tools/perf/arch/s390/util/header.c
@@ -1,8 +1,9 @@
 /*
  * Implementation of get_cpuid().
  *
- * Copyright 2014 IBM Corp.
+ * Copyright IBM Corp. 2014, 2018
  * Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.com>
+ *	      Thomas Richter <tmricht@linux.vnet.ibm.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License (version 2 only)
@@ -13,16 +14,135 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <string.h>
+#include <ctype.h>
 
 #include "../../util/header.h"
+#include "../../util/util.h"
+
+#define SYSINFO_MANU	"Manufacturer:"
+#define SYSINFO_TYPE	"Type:"
+#define SYSINFO_MODEL	"Model:"
+#define SRVLVL_CPUMF	"CPU-MF:"
+#define SRVLVL_VERSION	"version="
+#define SRVLVL_AUTHORIZATION	"authorization="
+#define SYSINFO		"/proc/sysinfo"
+#define SRVLVL		"/proc/service_levels"
 
 int get_cpuid(char *buffer, size_t sz)
 {
-	const char *cpuid = "IBM/S390";
+	char *cp, *line = NULL, *line2;
+	char type[8], model[33], version[8], manufacturer[32], authorization[8];
+	int tpsize = 0, mdsize = 0, vssize = 0, mfsize = 0, atsize = 0;
+	int read;
+	unsigned long line_sz;
+	size_t nbytes;
+	FILE *sysinfo;
+
+	/*
+	 * Scan /proc/sysinfo line by line and read out values for
+	 * Manufacturer:, Type: and Model:, for example:
+	 * Manufacturer:    IBM
+	 * Type:            2964
+	 * Model:           702              N96
+	 * The first word is the Model Capacity and the second word is
+	 * Model (can be omitted). Both words have a maximum size of 16
+	 * bytes.
+	 */
+	memset(manufacturer, 0, sizeof(manufacturer));
+	memset(type, 0, sizeof(type));
+	memset(model, 0, sizeof(model));
+	memset(version, 0, sizeof(version));
+	memset(authorization, 0, sizeof(authorization));
+
+	sysinfo = fopen(SYSINFO, "r");
+	if (sysinfo == NULL)
+		return -1;
+
+	while ((read = getline(&line, &line_sz, sysinfo)) != -1) {
+		if (!strncmp(line, SYSINFO_MANU, strlen(SYSINFO_MANU))) {
+			line2 = line + strlen(SYSINFO_MANU);
+
+			while ((cp = strtok_r(line2, "\n ", &line2))) {
+				mfsize += scnprintf(manufacturer + mfsize,
+						    sizeof(manufacturer) - mfsize, "%s", cp);
+			}
+		}
+
+		if (!strncmp(line, SYSINFO_TYPE, strlen(SYSINFO_TYPE))) {
+			line2 = line + strlen(SYSINFO_TYPE);
+
+			while ((cp = strtok_r(line2, "\n ", &line2))) {
+				tpsize += scnprintf(type + tpsize,
+						    sizeof(type) - tpsize, "%s", cp);
+			}
+		}
+
+		if (!strncmp(line, SYSINFO_MODEL, strlen(SYSINFO_MODEL))) {
+			line2 = line + strlen(SYSINFO_MODEL);
+
+			while ((cp = strtok_r(line2, "\n ", &line2))) {
+				mdsize += scnprintf(model + mdsize, sizeof(type) - mdsize,
+						    "%s%s", model[0] ? "," : "", cp);
+			}
+			break;
+		}
+	}
+	fclose(sysinfo);
 
-	if (strlen(cpuid) + 1 > sz)
+	/* Missing manufacturer, type or model information should not happen */
+	if (!manufacturer[0] || !type[0] || !model[0])
 		return -1;
 
-	strcpy(buffer, cpuid);
-	return 0;
+	/*
+	 * Scan /proc/service_levels and return the CPU-MF counter facility
+	 * version number and authorization level.
+	 * Optional, does not exist on z/VM guests.
+	 */
+	sysinfo = fopen(SRVLVL, "r");
+	if (sysinfo == NULL)
+		goto skip_sysinfo;
+	while ((read = getline(&line, &line_sz, sysinfo)) != -1) {
+		if (strncmp(line, SRVLVL_CPUMF, strlen(SRVLVL_CPUMF)))
+			continue;
+
+		line2 = line + strlen(SRVLVL_CPUMF);
+		while ((cp = strtok_r(line2, "\n ", &line2))) {
+			if (!strncmp(cp, SRVLVL_VERSION,
+				     strlen(SRVLVL_VERSION))) {
+				char *sep = strchr(cp, '=');
+
+				vssize += scnprintf(version + vssize,
+						    sizeof(version) - vssize, "%s", sep + 1);
+			}
+			if (!strncmp(cp, SRVLVL_AUTHORIZATION,
+				     strlen(SRVLVL_AUTHORIZATION))) {
+				char *sep = strchr(cp, '=');
+
+				atsize += scnprintf(authorization + atsize,
+						    sizeof(authorization) - atsize, "%s", sep + 1);
+			}
+		}
+	}
+	fclose(sysinfo);
+
+skip_sysinfo:
+	free(line);
+
+	if (version[0] && authorization[0] )
+		nbytes = snprintf(buffer, sz, "%s,%s,%s,%s,%s",
+				  manufacturer, type, model, version,
+				  authorization);
+	else
+		nbytes = snprintf(buffer, sz, "%s,%s,%s", manufacturer, type,
+				  model);
+	return (nbytes >= sz) ? -1 : 0;
+}
+
+char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
+{
+	char *buf = malloc(128);
+
+	if (buf && get_cpuid(buf, 128) < 0)
+		zfree(&buf);
+	return buf;
 }

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

* [tip:perf/core] perf annotate: Scan cpuid for s390 and save machine type
  2018-02-13 15:14 ` [PATCH 2/4] perf annotate: Scan cpuid for s390 and save machine type Thomas Richter
@ 2018-02-17 11:37   ` tip-bot for Thomas Richter
  0 siblings, 0 replies; 11+ messages in thread
From: tip-bot for Thomas Richter @ 2018-02-17 11:37 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, heiko.carstens, tmricht, linux-kernel, schwidefsky, mingo,
	brueckner, acme, tglx

Commit-ID:  c59124fa59757fadc80ad881056a21f98c71b146
Gitweb:     https://git.kernel.org/tip/c59124fa59757fadc80ad881056a21f98c71b146
Author:     Thomas Richter <tmricht@linux.vnet.ibm.com>
AuthorDate: Tue, 13 Feb 2018 16:14:17 +0100
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Fri, 16 Feb 2018 15:16:57 -0300

perf annotate: Scan cpuid for s390 and save machine type

Scan the cpuid string and extract the type number for later use.

Signed-off-by: Thomas Richter <tmricht@linux.vnet.ibm.com>
Reviewed-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Link: http://lkml.kernel.org/r/20180213151419.80737-2-tmricht@linux.vnet.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/arch/s390/annotate/instructions.c | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/tools/perf/arch/s390/annotate/instructions.c b/tools/perf/arch/s390/annotate/instructions.c
index 8c72b44..01df9d8 100644
--- a/tools/perf/arch/s390/annotate/instructions.c
+++ b/tools/perf/arch/s390/annotate/instructions.c
@@ -23,12 +23,37 @@ static struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *na
 	return ops;
 }
 
+static int s390__cpuid_parse(struct arch *arch, char *cpuid)
+{
+	unsigned int family;
+	char model[16], model_c[16], cpumf_v[16], cpumf_a[16];
+	int ret;
+
+	/*
+	 * cpuid string format:
+	 * "IBM,family,model-capacity,model[,cpum_cf-version,cpum_cf-authorization]"
+	 */
+	ret = sscanf(cpuid, "%*[^,],%u,%[^,],%[^,],%[^,],%s", &family, model_c,
+		     model, cpumf_v, cpumf_a);
+	if (ret >= 2) {
+		arch->family = family;
+		arch->model = 0;
+		return 0;
+	}
+
+	return -1;
+}
+
 static int s390__annotate_init(struct arch *arch, char *cpuid __maybe_unused)
 {
+	int err = 0;
+
 	if (!arch->initialized) {
 		arch->initialized = true;
 		arch->associate_instruction_ops = s390__associate_ins_ops;
+		if (cpuid)
+			err = s390__cpuid_parse(arch, cpuid);
 	}
 
-	return 0;
+	return err;
 }

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

* [tip:perf/core] perf cpuid: Introduce a platform specific cpuid compare function
  2018-02-13 15:14 ` [PATCH 3/4] perf cpuid: Introduce a platform specfic cpuid compare function Thomas Richter
@ 2018-02-17 11:38   ` tip-bot for Thomas Richter
  0 siblings, 0 replies; 11+ messages in thread
From: tip-bot for Thomas Richter @ 2018-02-17 11:38 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, linux-kernel, mingo, acme, tglx, schwidefsky, brueckner,
	heiko.carstens, tmricht

Commit-ID:  4cb7d3ecfca90684ad00f893c34a2028fcc5f764
Gitweb:     https://git.kernel.org/tip/4cb7d3ecfca90684ad00f893c34a2028fcc5f764
Author:     Thomas Richter <tmricht@linux.vnet.ibm.com>
AuthorDate: Tue, 13 Feb 2018 16:14:18 +0100
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Fri, 16 Feb 2018 15:16:57 -0300

perf cpuid: Introduce a platform specific cpuid compare function

The function get_cpuid_str() is called by perf_pmu__getcpuid() and on
s390 returns a complete description of the CPU and its capabilities,
which is a comma separated list.

To map the CPU type with the value defined in the
pmu-events/arch/s390/mapfile.csv, introduce an architecture specific
cpuid compare function named strcmp_cpuid_str()

The currently used regex algorithm is defined as the weak default and
will be used if no platform specific one is defined. This matches the
current behavior.

Signed-off-by: Thomas Richter <tmricht@linux.vnet.ibm.com>
Reviewed-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Link: http://lkml.kernel.org/r/20180213151419.80737-3-tmricht@linux.vnet.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/arch/s390/util/header.c | 18 +++++++++++++++
 tools/perf/util/header.h           |  1 +
 tools/perf/util/pmu.c              | 47 +++++++++++++++++++++++---------------
 3 files changed, 48 insertions(+), 18 deletions(-)

diff --git a/tools/perf/arch/s390/util/header.c b/tools/perf/arch/s390/util/header.c
index a78064c..231294b 100644
--- a/tools/perf/arch/s390/util/header.c
+++ b/tools/perf/arch/s390/util/header.c
@@ -146,3 +146,21 @@ char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
 		zfree(&buf);
 	return buf;
 }
+
+/*
+ * Compare the cpuid string returned by get_cpuid() function
+ * with the name generated by the jevents file read from
+ * pmu-events/arch/s390/mapfile.csv.
+ *
+ * Parameter mapcpuid is the cpuid as stored in the
+ * pmu-events/arch/s390/mapfile.csv. This is just the type number.
+ * Parameter cpuid is the cpuid returned by function get_cpuid().
+ */
+int strcmp_cpuid_str(const char *mapcpuid, const char *cpuid)
+{
+	char *cp = strchr(cpuid, ',');
+
+	if (cp == NULL)
+		return -1;
+	return strncmp(cp + 1, mapcpuid, strlen(mapcpuid));
+}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index f28aaaa..942bdec 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -174,4 +174,5 @@ int write_padded(struct feat_fd *fd, const void *bf,
 int get_cpuid(char *buffer, size_t sz);
 
 char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused);
+int strcmp_cpuid_str(const char *s1, const char *s2);
 #endif /* __PERF_HEADER_H */
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 57e38fd..1111d5b 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -576,6 +576,34 @@ char * __weak get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
 	return NULL;
 }
 
+/* Return zero when the cpuid from the mapfile.csv matches the
+ * cpuid string generated on this platform.
+ * Otherwise return non-zero.
+ */
+int __weak strcmp_cpuid_str(const char *mapcpuid, const char *cpuid)
+{
+	regex_t re;
+	regmatch_t pmatch[1];
+	int match;
+
+	if (regcomp(&re, mapcpuid, REG_EXTENDED) != 0) {
+		/* Warn unable to generate match particular string. */
+		pr_info("Invalid regular expression %s\n", mapcpuid);
+		return 1;
+	}
+
+	match = !regexec(&re, cpuid, 1, pmatch, 0);
+	regfree(&re);
+	if (match) {
+		size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so);
+
+		/* Verify the entire string matched. */
+		if (match_len == strlen(cpuid))
+			return 0;
+	}
+	return 1;
+}
+
 static char *perf_pmu__getcpuid(struct perf_pmu *pmu)
 {
 	char *cpuid;
@@ -610,31 +638,14 @@ struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu)
 
 	i = 0;
 	for (;;) {
-		regex_t re;
-		regmatch_t pmatch[1];
-		int match;
-
 		map = &pmu_events_map[i++];
 		if (!map->table) {
 			map = NULL;
 			break;
 		}
 
-		if (regcomp(&re, map->cpuid, REG_EXTENDED) != 0) {
-			/* Warn unable to generate match particular string. */
-			pr_info("Invalid regular expression %s\n", map->cpuid);
+		if (!strcmp_cpuid_str(map->cpuid, cpuid))
 			break;
-		}
-
-		match = !regexec(&re, cpuid, 1, pmatch, 0);
-		regfree(&re);
-		if (match) {
-			size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so);
-
-			/* Verify the entire string matched. */
-			if (match_len == strlen(cpuid))
-				break;
-		}
 	}
 	free(cpuid);
 	return map;

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

* [tip:perf/core] perf test: Fix test case 23 for s390 z/VM or KVM guests
  2018-02-13 15:14 ` [PATCH 4/4] perf test: Fix test case 23 for s390 z/VM or KVM guests Thomas Richter
@ 2018-02-17 11:38   ` tip-bot for Thomas Richter
  0 siblings, 0 replies; 11+ messages in thread
From: tip-bot for Thomas Richter @ 2018-02-17 11:38 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tmricht, brueckner, linux-kernel, tglx, acme, heiko.carstens,
	hpa, schwidefsky, mingo

Commit-ID:  b3be39c51cc58eb60c698cf64987e9d465a9263a
Gitweb:     https://git.kernel.org/tip/b3be39c51cc58eb60c698cf64987e9d465a9263a
Author:     Thomas Richter <tmricht@linux.vnet.ibm.com>
AuthorDate: Tue, 13 Feb 2018 16:14:19 +0100
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Fri, 16 Feb 2018 15:16:57 -0300

perf test: Fix test case 23 for s390 z/VM or KVM guests

On s390 perf can be executed on a LPAR with support for hardware events
(i. e. cycles) or on a z/VM or KVM guest where no hardware events are
supported. In this environment use software event named cpu-clock for
this test case.

Use the cpuid infrastructure functions to determine the cpuid on s390
which contains an indication of the cpu counter facility availability.

Signed-off-by: Thomas Richter <tmricht@linux.vnet.ibm.com>
Reviewed-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Link: http://lkml.kernel.org/r/20180213151419.80737-4-tmricht@linux.vnet.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/tests/code-reading.c | 33 +++++++++++++++++++++++++++++----
 1 file changed, 29 insertions(+), 4 deletions(-)

diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 3bf7b14..c7115d3 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -482,6 +482,34 @@ static void fs_something(void)
 	}
 }
 
+static const char *do_determine_event(bool excl_kernel)
+{
+	const char *event = excl_kernel ? "cycles:u" : "cycles";
+
+#ifdef __s390x__
+	char cpuid[128], model[16], model_c[16], cpum_cf_v[16];
+	unsigned int family;
+	int ret, cpum_cf_a;
+
+	if (get_cpuid(cpuid, sizeof(cpuid)))
+		goto out_clocks;
+	ret = sscanf(cpuid, "%*[^,],%u,%[^,],%[^,],%[^,],%x", &family, model_c,
+		     model, cpum_cf_v, &cpum_cf_a);
+	if (ret != 5)		 /* Not available */
+		goto out_clocks;
+	if (excl_kernel && (cpum_cf_a & 4))
+		return event;
+	if (!excl_kernel && (cpum_cf_a & 2))
+		return event;
+
+	/* Fall through: missing authorization */
+out_clocks:
+	event = excl_kernel ? "cpu-clock:u" : "cpu-clock";
+
+#endif
+	return event;
+}
+
 static void do_something(void)
 {
 	fs_something();
@@ -592,10 +620,7 @@ static int do_test_code_reading(bool try_kcore)
 
 		perf_evlist__set_maps(evlist, cpus, threads);
 
-		if (excl_kernel)
-			str = "cycles:u";
-		else
-			str = "cycles";
+		str = do_determine_event(excl_kernel);
 		pr_debug("Parsing event '%s'\n", str);
 		ret = parse_events(evlist, str, NULL);
 		if (ret < 0) {

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

end of thread, other threads:[~2018-02-17 11:38 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-13 15:14 [PATCH 1/4] perf record: Provide detailed information on s390 CPU Thomas Richter
2018-02-13 15:14 ` [PATCH 2/4] perf annotate: Scan cpuid for s390 and save machine type Thomas Richter
2018-02-17 11:37   ` [tip:perf/core] " tip-bot for Thomas Richter
2018-02-13 15:14 ` [PATCH 3/4] perf cpuid: Introduce a platform specfic cpuid compare function Thomas Richter
2018-02-17 11:38   ` [tip:perf/core] perf cpuid: Introduce a platform specific " tip-bot for Thomas Richter
2018-02-13 15:14 ` [PATCH 4/4] perf test: Fix test case 23 for s390 z/VM or KVM guests Thomas Richter
2018-02-17 11:38   ` [tip:perf/core] " tip-bot for Thomas Richter
2018-02-15 14:50 ` [PATCH 1/4] perf record: Provide detailed information on s390 CPU Arnaldo Carvalho de Melo
2018-02-16 16:55 ` Arnaldo Carvalho de Melo
2018-02-16 18:17   ` Arnaldo Carvalho de Melo
2018-02-17 11:37 ` [tip:perf/core] " tip-bot for Thomas Richter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).