[Intel-gfx] [PATCH i-g-t 1/1] igt/dapc: Test Driver Assisted Performance Capture (DAPC)
Sagar Arun Kamble
sagar.a.kamble at intel.com
Mon Aug 28 09:53:03 UTC 2017
This test verifies different i915 perf sampling options for fields like
PID, CTX ID, Timestamp, OA Report, TAG, MMIO.
Cc: Lionel Landwerlin <lionel.g.landwerlin at intel.com>
Signed-off-by: Sourab Gupta <sourab.gupta at intel.com>
Signed-off-by: Sagar Arun Kamble <sagar.a.kamble at intel.com>
---
tests/Makefile.sources | 1 +
tests/dapc.c | 1017 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 1018 insertions(+)
create mode 100644 tests/dapc.c
diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index bb013c7..61feb0d 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -26,6 +26,7 @@ TESTS_progs = \
core_getversion \
core_prop_blob \
core_setmaster_vs_auth \
+ dapc \
debugfs_test \
drm_import_export \
drm_mm \
diff --git a/tests/dapc.c b/tests/dapc.c
new file mode 100644
index 0000000..f49b1cd
--- /dev/null
+++ b/tests/dapc.c
@@ -0,0 +1,1017 @@
+/*
+ * Copyright © 2017 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 (including the next
+ * paragraph) 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.
+ *
+ * dapc: Driver Assisted Performance Capture
+ * This tests the i915 perf functionality to sample various metrics by
+ * associating with the CS stream or just standalone periodic OA samples.
+ * Verifies fields like PID, CTX ID, Timestamp, OA Report, MMIO, Tags are
+ * generated properly for each sample.
+ *
+ * Authors:
+ * Sourab Gupta <sourab.gupta at intel.com>
+ * Sagar Arun Kamble <sagar.a.kamble at intel.com>
+ *
+ */
+#define _GNU_SOURCE
+#include "xf86drm.h"
+#include "i915_drm.h"
+#include "igt_core.h"
+#include <linux/perf_event.h>
+#include <asm/unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <dirent.h>
+#include <limits.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <assert.h>
+#include <time.h>
+
+#define COLLECT_DATA { \
+ printf("(%s) Collecting data. ", __func__); \
+ printf("Press enter to continue...\n"); \
+ getc(stdin); \
+}
+
+#define OA_SAMPLE_SIZE_MAX (8 + /* drm_i915_perf_record_header */ \
+ 8 + /* source info */ \
+ 8 + /* ctx ID */ \
+ 8 + /* Pid */ \
+ 8 + /* Tag */ \
+ 256) /* raw OA counter snapshot */
+
+#define TS_SAMPLE_SIZE_MAX (8 + /* drm_i915_perf_record_header */ \
+ 8 + /* ctx ID */ \
+ 8 + /* Pid */ \
+ 8 + /* Tag */ \
+ 8) /* Timestamp */ \
+
+#define TS_MMIO_SAMPLE_SIZE_MAX (8 + /* drm_i915_perf_record_header */ \
+ 8 + /* ctx ID */ \
+ 8 + /* Pid */ \
+ 8 + /* Tag */ \
+ 8 + /* Timestamp */ \
+ 4*I915_PERF_MMIO_NUM_MAX) /* MMIO reg */
+
+#define OA_TS_MMIO_SAMPLE_SIZE_MAX (8 + /* drm_i915_perf_record_header */ \
+ 8 + /* source info */ \
+ 8 + /* ctx ID */ \
+ 8 + /* Pid */ \
+ 8 + /* Tag */ \
+ 8 + /* Timestamp */ \
+ (4*I915_PERF_MMIO_NUM_MAX) + /* MMIO reg*/ \
+ 256) /* raw OA counter snapshot */
+
+#define READ_OA_BUF_SIZE_MAX (100*OA_SAMPLE_SIZE_MAX)
+#define READ_TS_BUF_SIZE_MAX (100*TS_SAMPLE_SIZE_MAX)
+#define READ_TS_MMIO_BUF_SIZE_MAX (100*TS_MMIO_SAMPLE_SIZE_MAX)
+#define READ_OA_TS_MMIO_BUF_SIZE_MAX (100*OA_TS_MMIO_SAMPLE_SIZE_MAX)
+
+#define SAMPLE_OA (1<<0)
+#define SAMPLE_TS (1<<1)
+#define SAMPLE_MMIO (1<<2)
+
+struct intel_device {
+ uint32_t device;
+ uint32_t subsystem_device;
+ uint32_t subsystem_vendor;
+};
+
+enum platform {
+ ARCH_HSW,
+ ARCH_BDW,
+ ARCH_SKL,
+} arch;
+
+/* DAPC OA samples read() from i915 perf */
+struct dapc_oa_sample {
+ struct drm_i915_perf_record_header header;
+ uint64_t source_info;
+ uint64_t ctx_id;
+ uint64_t pid;
+ uint64_t tag;
+ uint8_t oa_report[];
+};
+
+/* DAPC timestamp samples read() from i915 perf */
+struct dapc_ts_sample {
+ struct drm_i915_perf_record_header header;
+ uint64_t ctx_id;
+ uint64_t pid;
+ uint64_t tag;
+ uint64_t timestamp;
+};
+
+/* DAPC timestamp + mmio samples read() from i915 perf */
+struct dapc_ts_mmio_sample {
+ struct drm_i915_perf_record_header header;
+ uint64_t ctx_id;
+ uint64_t pid;
+ uint64_t tag;
+ uint64_t timestamp;
+ uint32_t mmio[2];
+};
+
+/* DAPC OA + timestamp + mmio samples read() from i915 perf */
+struct dapc_oa_ts_mmio_sample {
+ struct drm_i915_perf_record_header header;
+ uint64_t source_info;
+ uint64_t ctx_id;
+ uint64_t pid;
+ uint64_t tag;
+ uint64_t timestamp;
+
+ /*
+ * Hardcoding 2 here since the array size would depend on no. of mmio
+ * values queried. TODO: Find a better way to do this.
+ */
+ uint32_t mmio[2];
+ uint8_t oa_report[];
+};
+
+struct i915_oa_format {
+ int format;
+ int size;
+};
+
+static struct i915_oa_format hsw_oa_formats[I915_OA_FORMAT_MAX] = {
+ [I915_OA_FORMAT_A13] = { 0, 64 },
+ [I915_OA_FORMAT_A29] = { 1, 128 },
+ [I915_OA_FORMAT_A13_B8_C8] = { 2, 128 },
+ /* A29_B8_C8 Disallowed as 192 bytes doesn't factor into buffer size */
+ [I915_OA_FORMAT_B4_C8] = { 4, 64 },
+ [I915_OA_FORMAT_A45_B8_C8] = { 5, 256 },
+ [I915_OA_FORMAT_B4_C8_A16] = { 6, 128 },
+ [I915_OA_FORMAT_C4_B8] = { 7, 64 },
+};
+
+static struct i915_oa_format gen8_plus_oa_formats[I915_OA_FORMAT_MAX] = {
+ [I915_OA_FORMAT_A12] = { 0, 64 },
+ [I915_OA_FORMAT_A12_B8_C8] = { 2, 128 },
+ [I915_OA_FORMAT_A32u40_A4u32_B8_C8] = { 5, 256 },
+ [I915_OA_FORMAT_C4_B8] = { 7, 64 },
+};
+
+static const char * const hsw_guids[] = {
+ "403d8832-1a27-4aa6-a64e-f5389ce7b212",
+ "39ad14bc-2380-45c4-91eb-fbcb3aa7ae7b",
+ "3865be28-6982-49fe-9494-e4d1b4795413",
+ "bb5ed49b-2497-4095-94f6-26ba294db88a",
+ "3358d639-9b5f-45ab-976d-9b08cbfc6240",
+ "bc274488-b4b6-40c7-90da-b77d7ad16189",
+};
+
+/*
+ * Need to update GUID based on latest i915 configuration. Currently
+ * first GUID is being tested.
+ */
+static const char * const skl_guids[] = {
+ "1651949f-0ac0-4cb1-a06f-dafd74a407d1",
+ "f519e481-24d2-4d42-87c9-3fdd12c00202",
+ "fdfc01cc-e28e-423a-aae0-b5ed5d4d7a9f",
+ "c9c7ace5-614a-4f8e-90c7-30064c36cad2",
+ "99797dc2-b48f-4d83-b973-613cff01202b",
+ "afa148ea-77fb-48ee-b8f8-e5e971ecf589",
+ "bfce7061-e6f1-4a78-bed8-c9cc69af70f9",
+ "c35ddcab-b1f2-452f-969a-a8209d531a00",
+ "2b0d0c83-706a-4cb6-b55e-d6bcf51fa6d3",
+ "d084f6a9-f706-4b74-b98c-65daa5340517",
+ "c7ed493c-54ff-4152-baf4-07e31e7a24cb",
+ "43ad9300-198a-4734-8f3a-2a2151b9dab6",
+ "ccfce3f2-6c63-4630-a043-f2a0243fed8f",
+ "2e564b28-98fa-42a0-8bbc-7915de3cc03c",
+ "a305533f-7e36-4fb6-8749-c6280bce3457",
+ "34ecd59f-6b52-4004-916f-afe9530a0442",
+ "ee1990d9-6e93-4c7c-aa9e-b40e1ec4d41b",
+};
+
+static struct intel_device intel_dev;
+static int drm_fd = -1;
+static int drm_card = -1;
+static int perf_event_fd_rcs = -1;
+
+static uint64_t read_file_uint64(const char *file)
+{
+ char buf[32];
+ int fd, n;
+
+ fd = open(file, 0);
+ if (fd < 0)
+ return 0;
+ n = read(fd, buf, sizeof(buf) - 1);
+ close(fd);
+ if (n < 0)
+ return 0;
+
+ buf[n] = '\0';
+ return strtoull(buf, 0, 0);
+}
+
+static uint32_t read_device_param(int id, const char *param)
+{
+ char *name;
+ int ret = asprintf(&name, "/sys/class/drm/renderD%u/device/%s",
+ id, param);
+ uint32_t value;
+
+ assert(ret != -1);
+
+ value = read_file_uint64(name);
+ free(name);
+
+ return value;
+}
+
+static int get_card_for_fd(int fd)
+{
+ struct stat sb;
+ int mjr, mnr;
+ char buffer[128];
+ DIR *drm_dir;
+ int entry_size;
+ struct dirent *entry1, *entry2;
+ int name_max;
+
+ if (fstat(fd, &sb)) {
+ printf("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);
+
+ name_max = pathconf(buffer, _PC_NAME_MAX);
+
+ if (name_max == -1)
+ name_max = 255;
+
+ entry_size = 256;
+ entry1 = alloca(entry_size);
+
+ while ((readdir_r(drm_dir, entry1, &entry2) == 0) && entry2 != NULL)
+ if (entry2->d_type == DT_DIR &&
+ strncmp(entry2->d_name, "card", 4) == 0)
+ return strtoull(entry2->d_name + 4, NULL, 10);
+
+ return -1;
+}
+
+
+static int open_render_node(struct intel_device *dev)
+{
+ char *name;
+ int i, fd;
+
+ for (i = 128; i < (128 + 16); i++) {
+ int ret;
+
+ ret = asprintf(&name, "/dev/dri/renderD%u", i);
+ assert(ret != -1);
+
+ fd = open(name, O_RDWR);
+ free(name);
+
+ if (fd == -1)
+ continue;
+
+ if (read_device_param(i, "vendor") != 0x8086) {
+ close(fd);
+ fd = -1;
+ continue;
+ }
+
+ dev->device = read_device_param(i, "device");
+ dev->subsystem_device = read_device_param(i,
+ "subsystem_device");
+ dev->subsystem_vendor = read_device_param(i,
+ "subsystem_vendor");
+
+ return fd;
+ }
+
+ return fd;
+}
+
+/* Handle restarting ioctl if interrupted... */
+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;
+}
+
+int read_perf_dapc_samples(uint8_t *temp_buf, uint8_t *out_data,
+ uint8_t sample_flags, int fd)
+{
+ int count, max_read_size = 16*1024*1024, size_copied = 0, offset = 0;
+
+ if (sample_flags & SAMPLE_OA)
+ max_read_size = READ_OA_BUF_SIZE_MAX;
+ else if (sample_flags & SAMPLE_TS)
+ max_read_size = READ_TS_BUF_SIZE_MAX;
+ else if (sample_flags & (SAMPLE_TS|SAMPLE_MMIO))
+ max_read_size = READ_TS_MMIO_BUF_SIZE_MAX;
+ else if (sample_flags & (SAMPLE_OA|SAMPLE_TS|SAMPLE_MMIO)) {
+ max_read_size = READ_OA_TS_MMIO_BUF_SIZE_MAX;
+ } else {
+ printf("Unknown sample flags: %d\n", sample_flags);
+ return -1;
+ }
+
+ count = read(fd, temp_buf, max_read_size);
+
+ if (count < 0) {
+ printf("Error reading i915 OA event stream. Errno:%d", errno);
+ perror("Error : ");
+ return count;
+ }
+
+ if (count == 0)
+ return 0;
+
+ while (offset < count) {
+ struct drm_i915_perf_record_header *header =
+ (struct drm_i915_perf_record_header *)(temp_buf + offset);
+
+ if (header->size == 0) {
+ printf("Spurious header size == 0\n");
+ /* XXX: How should we handle this instead of exiting()*/
+ exit(1);
+ }
+
+ offset += header->size;
+
+ switch (header->type) {
+ case DRM_I915_PERF_RECORD_OA_BUFFER_LOST:
+ printf("i915_oa: OA buffer overflow\n");
+ break;
+ case DRM_I915_PERF_RECORD_OA_REPORT_LOST:
+ printf("i915_oa: OA report lost\n");
+ break;
+ case DRM_I915_PERF_RECORD_SAMPLE:
+ if (sample_flags & SAMPLE_OA) {
+ struct dapc_oa_sample *sample =
+ (struct dapc_oa_sample *)header;
+
+ if (sample->source_info ==
+ I915_PERF_SAMPLE_OA_SOURCE_RCS) {
+ /* DAPC sample */
+ printf("DAPC OA sample\n");
+ } else {
+ /* Periodic sample. No need to copy */
+ printf("Periodic sample\n");
+ continue;
+ }
+ }
+ memcpy(out_data + size_copied, header, header->size);
+ size_copied += header->size;
+ break;
+ default:
+ printf("i915_oa: Spurious header type = %d\n",
+ header->type);
+ }
+ }
+
+ return size_copied;
+}
+
+bool read_metrics_id_from_sysfs(int *metrics_id)
+{
+ char buffer[128];
+ const char *guid;
+
+ assert(drm_card >= 0);
+
+ /*
+ * Select render basic metrics ID - i.e. first guid, from the arch
+ * specific guids.
+ */
+ switch (arch) {
+ case ARCH_HSW:
+ guid = hsw_guids[0];
+ break;
+ case ARCH_SKL:
+ guid = skl_guids[0];
+ break;
+ default:
+ printf("guid not found for the arch\n");
+ return false;
+ }
+
+ snprintf(buffer, sizeof(buffer),
+ "/sys/class/drm/card%d/metrics/%s/id",
+ drm_card, guid);
+ *metrics_id = read_file_uint64(buffer);
+
+ return true;
+}
+
+static void open_i915_rcs_oa_stream(int report_format, int metrics_id)
+{
+ int period_exponent = 16;//0;
+ int ring_id = I915_EXEC_RENDER; /* RCS */
+ struct drm_i915_perf_open_param param;
+ uint64_t properties[] = {
+ DRM_I915_PERF_PROP_SAMPLE_OA, true,
+ DRM_I915_PERF_PROP_OA_METRICS_SET, metrics_id,
+ DRM_I915_PERF_PROP_OA_FORMAT, report_format,
+ DRM_I915_PERF_PROP_OA_EXPONENT, period_exponent,
+ DRM_I915_PERF_PROP_ENGINE, ring_id,
+ DRM_I915_PERF_PROP_SAMPLE_OA_SOURCE, true,
+ DRM_I915_PERF_PROP_SAMPLE_CTX_ID, true,
+ DRM_I915_PERF_PROP_SAMPLE_PID, true,
+ DRM_I915_PERF_PROP_SAMPLE_TAG, true,
+ };
+ int fd;
+
+ memset(¶m, 0, sizeof(param));
+
+ param.flags = 0;
+ param.flags |= I915_PERF_FLAG_FD_CLOEXEC;
+ param.flags |= I915_PERF_FLAG_FD_NONBLOCK;
+
+ param.properties_ptr = (uint64_t)properties;
+ param.num_properties = sizeof(properties) / 16;
+
+ fd = perf_ioctl(drm_fd, DRM_IOCTL_I915_PERF_OPEN, ¶m);
+
+ if (fd == -1) {
+ perror("Error opening i915 perf event : ");
+ return;
+ }
+
+ printf("Opened i915 perf event.\n");
+ perf_event_fd_rcs = fd;
+}
+
+static void open_i915_rcs_ts_stream(void)
+{
+ struct drm_i915_perf_open_param param;
+ int ring_id = I915_EXEC_RENDER; /* RCS */
+ uint64_t properties[] = {
+ DRM_I915_PERF_PROP_ENGINE, ring_id,
+ DRM_I915_PERF_PROP_SAMPLE_TS, true,
+ DRM_I915_PERF_PROP_SAMPLE_CTX_ID, true,
+ DRM_I915_PERF_PROP_SAMPLE_PID, true,
+ DRM_I915_PERF_PROP_SAMPLE_TAG, true,
+ };
+ int fd;
+
+ memset(¶m, 0, sizeof(param));
+
+ param.flags = 0;
+ param.flags |= I915_PERF_FLAG_FD_CLOEXEC;
+ param.flags |= I915_PERF_FLAG_FD_NONBLOCK;
+
+ param.properties_ptr = (uint64_t)properties;
+ param.num_properties = sizeof(properties) / 16;
+
+ fd = perf_ioctl(drm_fd, DRM_IOCTL_I915_PERF_OPEN, ¶m);
+
+ if (fd == -1) {
+ perror("Error opening i915 perf event : ");
+ return;
+ }
+
+ printf("Opened i915 perf event.\n");
+ perf_event_fd_rcs = fd;
+}
+
+static void open_i915_rcs_ts_mmio_stream(
+ struct drm_i915_perf_mmio_list *mmio_list)
+{
+ struct drm_i915_perf_open_param param;
+ int ring_id = I915_EXEC_RENDER; /* RCS */
+ uint64_t properties[] = {
+ DRM_I915_PERF_PROP_ENGINE, ring_id,
+ DRM_I915_PERF_PROP_SAMPLE_TS, true,
+ DRM_I915_PERF_PROP_SAMPLE_MMIO, (uint64_t)mmio_list,
+ DRM_I915_PERF_PROP_SAMPLE_CTX_ID, true,
+ DRM_I915_PERF_PROP_SAMPLE_PID, true,
+ DRM_I915_PERF_PROP_SAMPLE_TAG, true,
+ };
+ int fd;
+
+ memset(¶m, 0, sizeof(param));
+
+ param.flags = 0;
+ param.flags |= I915_PERF_FLAG_FD_CLOEXEC;
+ param.flags |= I915_PERF_FLAG_FD_NONBLOCK;
+
+ param.properties_ptr = (uint64_t)properties;
+ param.num_properties = sizeof(properties) / 16;
+
+ fd = perf_ioctl(drm_fd, DRM_IOCTL_I915_PERF_OPEN, ¶m);
+
+ if (fd == -1) {
+ perror("Error opening i915 perf event : ");
+ return;
+ }
+
+ printf("Opened i915 perf event.\n");
+ perf_event_fd_rcs = fd;
+}
+
+static void open_i915_rcs_oa_ts_mmio_stream(int report_format, int metrics_id,
+ struct drm_i915_perf_mmio_list *mmio_list)
+{
+ int period_exponent = 16;//0;
+ int ring_id = I915_EXEC_RENDER; /* RCS */
+ struct drm_i915_perf_open_param param;
+ uint64_t properties[] = {
+ DRM_I915_PERF_PROP_SAMPLE_OA, true,
+ DRM_I915_PERF_PROP_OA_METRICS_SET, metrics_id,
+ DRM_I915_PERF_PROP_OA_FORMAT, report_format,
+ DRM_I915_PERF_PROP_OA_EXPONENT, period_exponent,
+ DRM_I915_PERF_PROP_ENGINE, ring_id,
+ DRM_I915_PERF_PROP_SAMPLE_OA_SOURCE, true,
+ DRM_I915_PERF_PROP_SAMPLE_TS, true,
+ DRM_I915_PERF_PROP_SAMPLE_MMIO, (uint64_t)mmio_list,
+ DRM_I915_PERF_PROP_SAMPLE_CTX_ID, true,
+ DRM_I915_PERF_PROP_SAMPLE_PID, true,
+ DRM_I915_PERF_PROP_SAMPLE_TAG, true,
+ };
+ int fd;
+
+ memset(¶m, 0, sizeof(param));
+
+ param.flags = 0;
+ param.flags |= I915_PERF_FLAG_FD_CLOEXEC;
+ param.flags |= I915_PERF_FLAG_FD_NONBLOCK;
+
+ param.properties_ptr = (uint64_t)properties;
+ param.num_properties = sizeof(properties) / 16;
+
+ fd = perf_ioctl(drm_fd, DRM_IOCTL_I915_PERF_OPEN, ¶m);
+
+ if (fd == -1) {
+ perror("Error opening i915 perf event : ");
+ return;
+ }
+
+ printf("Opened i915 perf event.\n");
+ perf_event_fd_rcs = fd;
+}
+
+static void open_i915_periodic_oa_stream(int report_format, int metrics_id)
+{
+ int period_exponent = 16;//0;
+ struct drm_i915_perf_open_param param;
+ uint64_t properties[] = {
+ DRM_I915_PERF_PROP_SAMPLE_OA, true,
+ DRM_I915_PERF_PROP_OA_METRICS_SET, metrics_id,
+ DRM_I915_PERF_PROP_OA_FORMAT, report_format,
+ DRM_I915_PERF_PROP_OA_EXPONENT, period_exponent,
+ DRM_I915_PERF_PROP_SAMPLE_OA_SOURCE, true,
+ };
+ int fd;
+
+ memset(¶m, 0, sizeof(param));
+
+ param.flags = 0;
+ param.flags |= I915_PERF_FLAG_FD_CLOEXEC;
+ param.flags |= I915_PERF_FLAG_FD_NONBLOCK;
+
+ param.properties_ptr = (uint64_t)properties;
+ param.num_properties = sizeof(properties) / 16;
+
+ fd = perf_ioctl(drm_fd, DRM_IOCTL_I915_PERF_OPEN, ¶m);
+
+ if (fd == -1) {
+ perror("Error opening i915 perf event : ");
+ return;
+ }
+
+ printf("Opened i915 perf event.\n");
+ perf_event_fd_rcs = fd;
+}
+
+static void close_i915_perf_stream(void)
+{
+ if (perf_event_fd_rcs != -1) {
+ close(perf_event_fd_rcs);
+ perf_event_fd_rcs = -1;
+ }
+}
+
+static void test_perf_dapc_rcs_oa(void)
+{
+ uint64_t report_format;
+ int metrics_id;
+ int size, report_size, current_size = 0;
+ uint8_t *dapc_data, *temp_buffer, *current_hdr;
+ int ret = 0;
+
+ if (arch == ARCH_HSW) {
+ report_format = I915_OA_FORMAT_A29;
+ report_size = hsw_oa_formats[report_format].size;
+ } else {
+ report_format = I915_OA_FORMAT_A12;
+ report_size = gen8_plus_oa_formats[report_format].size;
+ }
+
+ if (report_size < 0)
+ return;
+
+ dapc_data = malloc(READ_OA_BUF_SIZE_MAX);
+ temp_buffer = malloc(READ_OA_BUF_SIZE_MAX);
+
+ ret = read_metrics_id_from_sysfs(&metrics_id);
+ if (!ret) {
+ printf("Reading metrics id from sysfs failed\n");
+ return;
+ }
+
+ open_i915_rcs_oa_stream(report_format, metrics_id);
+
+ /* Collect samples */
+ COLLECT_DATA;
+
+ /* Read samples */
+ size = read_perf_dapc_samples(temp_buffer, dapc_data, SAMPLE_OA,
+ perf_event_fd_rcs);
+
+ current_hdr = dapc_data;
+
+ printf("size retrieved = %d\n", size);
+ /* Verify the sanity of DAPC node headers */
+ while (current_size < size) {
+ struct dapc_oa_sample *sample = (struct dapc_oa_sample *)
+ (current_hdr + current_size);
+
+ igt_assert(sample->pid != 0);
+ printf("pid = %lu, ctx_id = %lu, OA(first 8 bytes):0x%llx, "
+ "oa ts=0x%x\n",
+ sample->pid, sample->ctx_id,
+ *(unsigned long long int *)sample->oa_report,
+ *(uint32_t *)(sample->oa_report + 4));
+
+ current_size += sample->header.size;
+ }
+ close_i915_perf_stream();
+
+ free(dapc_data);
+ free(temp_buffer);
+}
+
+static void test_perf_dapc_rcs_ts(void)
+{
+
+ uint64_t prev_ts = 0, init_ts = 0;
+ int size, current_size = 0;
+ uint8_t *dapc_data, *temp_buffer, *current_hdr;
+
+ dapc_data = malloc(READ_TS_BUF_SIZE_MAX);
+ temp_buffer = malloc(READ_TS_BUF_SIZE_MAX);
+
+ memset(dapc_data, 0, READ_TS_BUF_SIZE_MAX);
+ memset(temp_buffer, 0, READ_TS_BUF_SIZE_MAX);
+
+ open_i915_rcs_ts_stream();
+
+ /* Collect samples */
+ COLLECT_DATA;
+
+ /* Read samples */
+ size = read_perf_dapc_samples(temp_buffer, dapc_data, SAMPLE_TS,
+ perf_event_fd_rcs);
+
+ current_hdr = dapc_data;
+
+ printf("size collected = %d\n", size);
+
+ /* Verify the sanity of DAPC data */
+ while (current_size < size) {
+ struct dapc_ts_sample *sample = (struct dapc_ts_sample *)
+ (current_hdr + current_size);
+ uint64_t ts = sample->timestamp;
+
+ igt_assert(sample->pid != 0);
+ printf("pid = %lu, ctx_id = %lu, tag=%lu, ts=0x%llx\n",
+ sample->pid, sample->ctx_id, sample->tag,
+ (unsigned long long)ts);
+
+ igt_assert(ts > init_ts);
+ igt_assert(ts > prev_ts);
+ prev_ts = ts;
+
+ current_size += sample->header.size;
+ }
+
+ printf("total size read = %d\n", current_size);
+ close_i915_perf_stream();
+
+ free(dapc_data);
+ free(temp_buffer);
+}
+
+
+static void test_perf_dapc_rcs_ts_mmio(void)
+{
+
+ uint64_t prev_ts = 0, init_ts = 0;
+ int r, size, current_size = 0;
+ uint8_t *dapc_data, *temp_buffer, *current_hdr;
+ struct drm_i915_perf_mmio_list mmio;
+
+ dapc_data = malloc(READ_TS_MMIO_BUF_SIZE_MAX);
+ temp_buffer = malloc(READ_TS_MMIO_BUF_SIZE_MAX);
+
+ memset(&mmio, 0, sizeof(mmio));
+
+#define GEN6_GT_GFX_RC6 0x138108
+#define GEN6_GT_GFX_RC6p 0x13810C
+ mmio.mmio_list[0] = GEN6_GT_GFX_RC6;
+ mmio.mmio_list[1] = GEN6_GT_GFX_RC6p;
+ mmio.num_mmio = 2;
+
+ open_i915_rcs_ts_mmio_stream(&mmio);
+
+ /* Collect samples */
+ COLLECT_DATA;
+
+ /* Read samples */
+ size = read_perf_dapc_samples(temp_buffer, dapc_data,
+ SAMPLE_TS|SAMPLE_MMIO, perf_event_fd_rcs);
+
+ current_hdr = dapc_data;
+
+ printf("size collected = %d\n", size);
+ /* Verify the sanity of DAPC data */
+ while (current_size < size) {
+ struct dapc_ts_mmio_sample *sample =
+ (struct dapc_ts_mmio_sample *)
+ (current_hdr + current_size);
+ uint64_t ts = sample->timestamp;
+
+ igt_assert(sample->pid != 0);
+ printf("pid = %lu, ctx_id = %lu, ts=0x%llx\n",
+ sample->pid, sample->ctx_id,
+ (unsigned long long)ts);
+
+ igt_assert(ts > init_ts);
+ igt_assert(ts > prev_ts);
+ prev_ts = ts;
+
+ for (r = 0; r < mmio.num_mmio; r++) {
+ printf("mmio 0x%08X = 0x%08X\n",
+ mmio.mmio_list[r],
+ sample->mmio[r]);
+ }
+
+ current_size += sample->header.size;
+ }
+
+ printf("total size read = %d\n", current_size);
+ close_i915_perf_stream();
+
+ free(dapc_data);
+ free(temp_buffer);
+}
+
+static void test_perf_dapc_rcs_oa_ts_mmio(void)
+{
+
+ uint64_t report_format;
+ uint64_t prev_ts = 0, init_ts = 0;
+ int r, report_size, size, metrics_id, current_size = 0;
+ uint8_t *dapc_data, *temp_buffer, *current_hdr;
+ struct drm_i915_perf_mmio_list mmio;
+ int ret = 0;
+
+ if (arch == ARCH_HSW) {
+ report_format = I915_OA_FORMAT_A29;
+ report_size = hsw_oa_formats[report_format].size;
+ } else {
+ report_format = I915_OA_FORMAT_A12;
+ report_size = gen8_plus_oa_formats[report_format].size;
+ }
+
+ if (report_size < 0)
+ return;
+
+ dapc_data = malloc(READ_OA_TS_MMIO_BUF_SIZE_MAX);
+ temp_buffer = malloc(READ_OA_TS_MMIO_BUF_SIZE_MAX);
+
+ memset(&mmio, 0, sizeof(mmio));
+
+#define GEN6_GT_GFX_RC6 0x138108
+#define GEN6_GT_GFX_RC6p 0x13810C
+ mmio.mmio_list[0] = GEN6_GT_GFX_RC6;
+ mmio.mmio_list[1] = GEN6_GT_GFX_RC6p;
+ mmio.num_mmio = 2;
+
+ ret = read_metrics_id_from_sysfs(&metrics_id);
+ if (!ret) {
+ printf("Reading metrics id from sysfs failed\n");
+ return;
+ }
+
+ open_i915_rcs_oa_ts_mmio_stream(report_format, metrics_id, &mmio);
+
+ /* Collect samples */
+ COLLECT_DATA;
+
+ /* Read samples */
+ size = read_perf_dapc_samples(temp_buffer, dapc_data,
+ SAMPLE_OA|SAMPLE_TS|SAMPLE_MMIO,
+ perf_event_fd_rcs);
+
+ current_hdr = dapc_data;
+
+ printf("size collected = %d\n", size);
+ /* Verify the sanity of DAPC data */
+ while (current_size < size) {
+ struct dapc_oa_ts_mmio_sample *sample =
+ (struct dapc_oa_ts_mmio_sample *)
+ (current_hdr + current_size);
+ uint64_t ts = sample->timestamp;
+
+ igt_assert(sample->pid != 0);
+ printf("pid = %lu, ctx_id = %lu, ts=0x%llx\n",
+ sample->pid, sample->ctx_id,
+ (unsigned long long)ts);
+
+ igt_assert(ts > init_ts);
+ igt_assert(ts > prev_ts);
+ prev_ts = ts;
+
+ for (r = 0; r < mmio.num_mmio; r++) {
+ printf("mmio 0x%08X = 0x%08X\n",
+ mmio.mmio_list[r], sample->mmio[r]);
+ }
+
+ current_size += sample->header.size;
+ printf("current size = %d\n", current_size);
+ }
+
+ printf("total size read = %d\n", current_size);
+ close_i915_perf_stream();
+
+ free(dapc_data);
+ free(temp_buffer);
+}
+
+static void test_perf_dapc_periodic_oa(void)
+{
+ uint64_t report_format;
+ int size, report_size, metrics_id;
+ uint8_t *dapc_data, *temp_buffer;
+ int ret = 0;
+
+ if (arch == ARCH_HSW) {
+ report_format = I915_OA_FORMAT_A29;
+ report_size = hsw_oa_formats[report_format].size;
+ } else {
+ report_format = I915_OA_FORMAT_A12;
+ report_size = gen8_plus_oa_formats[report_format].size;
+ }
+
+ if (report_size < 0)
+ return;
+
+ dapc_data = malloc(READ_OA_BUF_SIZE_MAX);
+ temp_buffer = malloc(READ_OA_BUF_SIZE_MAX);
+
+ ret = read_metrics_id_from_sysfs(&metrics_id);
+ if (!ret) {
+ printf("Reading metrics id from sysfs failed\n");
+ return;
+ }
+
+ open_i915_periodic_oa_stream(report_format, metrics_id);
+
+ /* Collect samples */
+ COLLECT_DATA;
+
+ /* Read samples */
+ size = read_perf_dapc_samples(temp_buffer, dapc_data, SAMPLE_OA,
+ perf_event_fd_rcs);
+
+ close_i915_perf_stream();
+
+ free(dapc_data);
+ free(temp_buffer);
+}
+
+static bool
+initialize(void)
+{
+
+ if (intel_dev.device)
+ return true;
+
+ drm_fd = open_render_node(&intel_dev);
+ if (drm_fd < 0) {
+ printf("Failed to open render node\n");
+ return false;
+ }
+
+ drm_card = get_card_for_fd(drm_fd);
+ if (drm_card < 0) {
+ printf("Failed to get drm card info\n");
+ return false;
+ }
+
+ return true;
+}
+
+int main(int argc, char **argv)
+{
+ bool ret;
+ int option;
+ int platform;
+
+ if (argc != 3) {
+ printf("Usage: \n./dapc <Platform> <Test_mode>\
+ \nPlatform: 0-HSW, 1-BDW, 2-SKL\n\
+ \nTest_mode:\n\
+ \t0 - RCS OA mode\n\
+ \t1 - RCS TS mode\n\
+ \t2 - RCS TS+MMIO mode\n\
+ \t3 - RCS OA+TS+MMIO mode\n\
+ \t4 - Periodic OA mode\n");
+ return 0;
+ }
+
+ ret = initialize();
+ if (!ret)
+ return -1;
+
+ platform = atoi(argv[1]);
+ switch (platform) {
+ case 0:
+ arch = ARCH_HSW;
+ break;
+ case 1:
+ arch = ARCH_BDW;
+ break;
+ case 2:
+ arch = ARCH_SKL;
+ break;
+ default:
+ fprintf(stderr, "Invalid platform:%d\n", platform);
+ return -1;
+ }
+
+ option = atoi(argv[2]);
+ switch (option) {
+ case 0:
+ test_perf_dapc_rcs_oa();
+ break;
+ case 1:
+ test_perf_dapc_rcs_ts();
+ break;
+ case 2:
+ test_perf_dapc_rcs_ts_mmio();
+ break;
+ case 3:
+ test_perf_dapc_rcs_oa_ts_mmio();
+ break;
+ case 4:
+ test_perf_dapc_periodic_oa();
+ break;
+ default:
+ fprintf(stderr, "Invalid Option:%d\n", option);
+ return -1;
+ }
+
+ return 0;
+}
--
1.9.1
More information about the Intel-gfx
mailing list