summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorLionel Landwerlin <lionel.g.landwerlin@intel.com>2019-09-08 17:57:30 +0300
committerLionel Landwerlin <lionel.g.landwerlin@intel.com>2020-02-19 18:45:54 +0200
commit53f8f541caae201ceb24160b1690ea94c60af9a7 (patch)
tree99da2579b95847ab64d3b08612560a2c3398d2ca /tools
parent60a6e2b045b2969cb65ebb609c4e6e4437131ed5 (diff)
lib: Add i915_perf library
This library contains the database of performance metrics for each supported generation as well as its associated programming. It also allow for the user to get human readable data out of HW generated data. v2: Switch a few python scripts to python3 v3: Fix some python2-ism s/lkf/ehl/ Autotools support v4: set soversion on i915_perf.so Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Acked-by: Chris Wilson <chris@chris-wilson.co.uk> Acked-by: Petri Latvala <petri.latvala@intel.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile.am2
-rw-r--r--tools/i915-perf/Makefile.am14
-rw-r--r--tools/i915-perf/i915_perf_configs.c277
-rw-r--r--tools/i915-perf/meson.build5
-rw-r--r--tools/meson.build1
5 files changed, 298 insertions, 1 deletions
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 20227eae7..9352b41cb 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -14,7 +14,7 @@ intel_dp_compliance_LDADD = $(top_builddir)/lib/libintel_tools.la
bin_PROGRAMS += amd_hdmi_compliance
amd_hdmi_compliance_CFLAGS = $(AM_CFLAGS) $(GLIB_CFLAGS)
-SUBDIRS = null_state_gen registers
+SUBDIRS = i915-perf null_state_gen registers
AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include/drm-uapi -I$(top_srcdir)/lib \
-I$(top_srcdir)/lib/stubs/syscalls
diff --git a/tools/i915-perf/Makefile.am b/tools/i915-perf/Makefile.am
new file mode 100644
index 000000000..400aad993
--- /dev/null
+++ b/tools/i915-perf/Makefile.am
@@ -0,0 +1,14 @@
+bin_PROGRAMS = i915-perf-configs
+
+AM_CFLAGS = $(CWARNFLAGS) -Wno-unused-result $(DEBUG_CFLAGS)\
+ -I$(top_srcdir)/include/drm-uapi \
+ -I$(top_srcdir)/lib \
+ -D_GNU_SOURCE \
+ $(DRM_CFLAGS) $(WERROR_CFLAGS) \
+ $(NULL)
+
+LDADD = $(top_builddir)/lib/libintel_tools.la
+
+i915_perf_configs_SOURCES = i915_perf_configs.c
+i915_perf_configs_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/lib/i915
+i915_perf_configs_LDADD = $(LDADD) $(top_builddir)/lib/libi915_perf.la
diff --git a/tools/i915-perf/i915_perf_configs.c b/tools/i915-perf/i915_perf_configs.c
new file mode 100644
index 000000000..2a0283c9f
--- /dev/null
+++ b/tools/i915-perf/i915_perf_configs.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2018 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <assert.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/sysmacros.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <i915_drm.h>
+
+#include "intel_chipset.h"
+#include "i915/perf.h"
+
+static bool
+read_file_uint64(const char *file, uint64_t *value)
+{
+ char buf[32];
+ int fd, n;
+
+ fd = open(file, 0);
+ if (fd < 0)
+ return false;
+ n = read(fd, buf, sizeof (buf) - 1);
+ close(fd);
+ if (n < 0)
+ return false;
+
+ buf[n] = '\0';
+ *value = strtoull(buf, 0, 0);
+
+ return true;
+}
+
+static uint32_t
+read_device_param(const char *stem, int id, const char *param)
+{
+ char *name;
+ int ret = asprintf(&name, "/sys/class/drm/%s%u/device/%s", stem, id, param);
+ uint64_t value;
+ bool success;
+
+ assert(ret != -1);
+
+ success = read_file_uint64(name, &value);
+ free(name);
+
+ return success ? value : 0;
+}
+
+static int
+find_intel_render_node(void)
+{
+ for (int i = 128; i < (128 + 16); i++) {
+ if (read_device_param("renderD", i, "vendor") == 0x8086)
+ return i;
+ }
+
+ return -1;
+}
+
+static int
+open_render_node(uint32_t *devid)
+{
+ char *name;
+ int ret;
+ int fd;
+
+ int render = find_intel_render_node();
+ if (render < 0)
+ return -1;
+
+ ret = asprintf(&name, "/dev/dri/renderD%u", render);
+ assert(ret != -1);
+
+ *devid = read_device_param("renderD", render, "device");
+
+ fd = open(name, O_RDWR);
+ free(name);
+
+ return fd;
+}
+
+static int
+get_card_for_fd(int fd)
+{
+ struct stat sb;
+ int mjr, mnr;
+ char buffer[128];
+ DIR *drm_dir;
+ struct dirent *entry;
+ int retval = -1;
+
+ if (fstat(fd, &sb)) {
+ fprintf(stderr, "Failed to stat DRM fd\n");
+ return -1;
+ }
+
+ mjr = major(sb.st_rdev);
+ mnr = minor(sb.st_rdev);
+
+ snprintf(buffer, sizeof(buffer), "/sys/dev/char/%d:%d/device/drm", mjr, mnr);
+
+ drm_dir = opendir(buffer);
+ assert(drm_dir != NULL);
+
+ while ((entry = readdir(drm_dir))) {
+ if (entry->d_type == DT_DIR && strncmp(entry->d_name, "card", 4) == 0) {
+ retval = strtoull(entry->d_name + 4, NULL, 10);
+ break;
+ }
+ }
+
+ closedir(drm_dir);
+
+ return retval;
+}
+
+static int
+perf_ioctl(int fd, unsigned long request, void *arg)
+{
+ int ret;
+
+ do {
+ ret = ioctl(fd, request, arg);
+ } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
+
+ return ret;
+}
+
+static const char *
+metric_name(struct intel_perf *perf, const char *hw_config_guid)
+{
+ struct intel_perf_metric_set *metric_set;
+
+ igt_list_for_each_entry(metric_set, &perf->metric_sets, link) {
+ if (!strcmp(metric_set->hw_config_guid, hw_config_guid))
+ return metric_set->symbol_name;
+ }
+
+ return "Unknown";
+}
+
+static void
+usage(void)
+{
+ printf("Usage: i915-perf-configs [options]\n"
+ "Manages i915-perf configurations stored in i915.\n"
+ " --purge, -p Purge configurations from the kernel\n"
+ " --list, -l List configurations from the kernel\n");
+}
+
+int
+main(int argc, char *argv[])
+{
+ char metrics_path[128];
+ DIR *metrics_dir;
+ struct dirent *entry;
+ int drm_fd, drm_card;
+ int opt;
+ bool purge = false;
+ const struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"list", no_argument, 0, 'l'},
+ {"purge", no_argument, 0, 'p'},
+ {0, 0, 0, 0}
+ };
+ const struct intel_device_info *devinfo;
+ struct intel_perf *perf;
+ uint32_t devid = 0;
+
+ while ((opt = getopt_long(argc, argv, "hlp", long_options, NULL)) != -1) {
+ switch (opt) {
+ case 'h':
+ usage();
+ return EXIT_SUCCESS;
+ case 'l':
+ break;
+ case 'p':
+ purge = true;
+ break;
+ default:
+ fprintf(stderr, "Internal error: "
+ "unexpected getopt value: %d\n", opt);
+ usage();
+ return EXIT_FAILURE;
+ }
+ }
+
+ drm_fd = open_render_node(&devid);
+ drm_card = get_card_for_fd(drm_fd);
+
+ fprintf(stdout, "Found device id=0x%x\n", devid);
+
+ devinfo = intel_get_device_info(drm_fd);
+ if (!devinfo) {
+ fprintf(stderr, "No device info found.\n");
+ return EXIT_FAILURE;
+ }
+
+ fprintf(stdout, "Device gen=%i gt=%i\n", devinfo->gen, devinfo->gt);
+
+ perf = intel_perf_for_fd(drm_fd);
+ if (!perf) {
+ fprintf(stderr, "No perf data found.\n");
+ return EXIT_FAILURE;
+ }
+
+ snprintf(metrics_path, sizeof(metrics_path),
+ "/sys/class/drm/card%d/metrics", drm_card);
+ metrics_dir = opendir(metrics_path);
+ if (!metrics_dir)
+ return EXIT_FAILURE;
+
+ fprintf(stdout, "Looking at metrics in %s\n", metrics_path);
+
+ while ((entry = readdir(metrics_dir))) {
+ char metric_id_path[400];
+ uint64_t metric_id;
+
+ if (entry->d_type != DT_DIR)
+ continue;
+
+ snprintf(metric_id_path, sizeof(metric_id_path),
+ "%s/%s/id", metrics_path, entry->d_name);
+
+ if (!read_file_uint64(metric_id_path, &metric_id))
+ continue;
+
+ if (purge) {
+ if (perf_ioctl(drm_fd, DRM_IOCTL_I915_PERF_REMOVE_CONFIG, &metric_id) == 0)
+ fprintf(stdout, "\tRemoved config %s id=%03" PRIu64 " name=%s\n",
+ entry->d_name, metric_id, metric_name(perf, entry->d_name));
+ else
+ fprintf(stdout, "\tFailed to remove config %s id=%03" PRIu64 " name=%s\n",
+ entry->d_name, metric_id, metric_name(perf, entry->d_name));
+ } else {
+ fprintf(stdout, "\tConfig %s id=%03" PRIu64 " name=%s\n",
+ entry->d_name, metric_id, metric_name(perf, entry->d_name));
+ }
+ }
+
+ closedir(metrics_dir);
+ close(drm_fd);
+
+ return EXIT_SUCCESS;
+}
diff --git a/tools/i915-perf/meson.build b/tools/i915-perf/meson.build
new file mode 100644
index 000000000..0ebdd1855
--- /dev/null
+++ b/tools/i915-perf/meson.build
@@ -0,0 +1,5 @@
+executable('i915-perf-configs',
+ [ 'i915_perf_configs.c' ],
+ include_directories: inc,
+ dependencies: [lib_igt_chipset, lib_igt_i915_perf],
+ install: true)
diff --git a/tools/meson.build b/tools/meson.build
index cf3f37b2e..59b56d5de 100644
--- a/tools/meson.build
+++ b/tools/meson.build
@@ -100,4 +100,5 @@ executable('amd_hdmi_compliance', 'amd_hdmi_compliance.c',
install_rpath : bindir_rpathdir,
install : true)
+subdir('i915-perf')
subdir('null_state_gen')