summaryrefslogtreecommitdiffstats
path: root/tools/perf/arch/s390
diff options
context:
space:
mode:
authorIngo Molnar2018-02-17 11:39:47 +0100
committerIngo Molnar2018-02-17 11:39:47 +0100
commit11737ca9e3b9d84448fa405a80980aa9957bcee8 (patch)
tree33b79a0c5a5c96344fe6f72e3a37104385a90ea7 /tools/perf/arch/s390
parentMerge branch 'perf/urgent' into perf/core, to pick up fixes (diff)
parentperf tests shell lib: Use a wildcard to remove the vfs_getname probe (diff)
downloadkernel-qcow2-linux-11737ca9e3b9d84448fa405a80980aa9957bcee8.tar.gz
kernel-qcow2-linux-11737ca9e3b9d84448fa405a80980aa9957bcee8.tar.xz
kernel-qcow2-linux-11737ca9e3b9d84448fa405a80980aa9957bcee8.zip
Merge tag 'perf-core-for-mingo-4.17-20180216' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: - Fix wrong jump arrow in systems with branch records with cycles, i.e. Intel's >= Skylake (Jin Yao) - Fix 'perf record --per-thread' problem introduced when implementing 'perf stat --per-thread (Jin Yao) - Use arch__compare_symbol_names() to fix 'perf test vmlinux', that was using strcmp(symbol names) while the dso routines doing symbol lookups used the arch overridable one, making this test fail in architectures that overrided that function with something other than strcmp() (Jiri Olsa) - Add 'perf script --show-round-event' to display PERF_RECORD_FINISHED_ROUND entries (Jiri Olsa) - Fix dwarf unwind for stripped binaries in 'perf test' (Jiri Olsa) - Use ordered_events for 'perf report --tasks', otherwise we may get artifacts when PERF_RECORD_FORK gets processed before PERF_RECORD_COMM (when they got recorded in different CPUs) (Jiri Olsa) - Add support to display group output for non group events, i.e. now when one uses 'perf report --group' on a perf.data file recorded without explicitly grouping events with {} (e.g. "perf record -e '{cycles,instructions}'" get the same output that would produce, i.e. see all those non-grouped events in multiple columns, at the same time (Jiri Olsa) - Skip non-address kallsyms entries, e.g. '(null)' for !root (Jiri Olsa) - Kernel maps fixes wrt perf.data(report) versus live system (top) (Jiri Olsa) - Fix memory corruption when using 'perf record -j call -g -a <application>' followed by 'perf report --branch-history' (Jiri Olsa) - ARM CoreSight fixes (Mathieu Poirier) - Add inject capability for CoreSight Traces (Robert Waker) - Update documentation for use of 'perf' + ARM CoreSight (Robert Walker) - Man pages fixes (Sangwon Hong, Jaecheol Shin) - Fix some 'perf test' cases on s/390 and x86_64 (some backtraces changed with a glibc update) (Thomas Richter) - Add detailed CPUID info in the 'perf.data' headers for s/390 to then use it in 'perf annotate' (Thomas Richter) - Add '--interval-count N' to 'perf stat', to use with -I, i.e. 'perf stat -I 1000 --interval-count 2' will show stats every 1000ms, two times (yuzhoujian) - Add 'perf stat --timeout Nms', that will run for that many milliseconds and then stop, printing the counters (yuzhoujian) - Fix description for 'perf report --mem-modex (Andi Kleen) - Use a wildcard to remove the vfs_getname probe in the 'perf test' shell based test cases (Arnaldo Carvalho de Melo) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/arch/s390')
-rw-r--r--tools/perf/arch/s390/annotate/instructions.c27
-rw-r--r--tools/perf/arch/s390/util/header.c148
2 files changed, 169 insertions, 6 deletions
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;
}
diff --git a/tools/perf/arch/s390/util/header.c b/tools/perf/arch/s390/util/header.c
index 9fa6c3e5782c..231294b80dc4 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,153 @@
#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);
- if (strlen(cpuid) + 1 > sz)
+ 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);
+
+ /* 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;
+}
+
+/*
+ * 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));
}