This test verifies different i915 perf sampling options for fields like PID, CTX ID, Timestamp, OA Report, TAG, MMIO. Cc: Lionel Landwerlin Signed-off-by: Sourab Gupta Signed-off-by: Sagar Arun Kamble --- 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 + * Sagar Arun Kamble + * + */ +#define _GNU_SOURCE +#include "xf86drm.h" +#include "i915_drm.h" +#include "igt_core.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 \ + \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