[Intel-gfx] [PATCH igt] tools/intel_reg: Add reading and writing registers through engine

Mika Kuoppala mika.kuoppala at linux.intel.com
Wed Jan 10 13:42:58 UTC 2018


Add option to specify engine for register read/write operation.
If engine is specified, use MI_LOAD_REGISTER_IMM and MI_STORE_REGISTER_IMM
to write and read register using a batch targeted at that engine.

v2: no MI_NOOP after BBE (Chris)
v3: use modern engine names (Chris), use global fd
v4: strcasecmp (Chris)
v5: use register definition format for engine (Jani)

Cc: Jani Nikula <jani.nikula at intel.com>
Cc: Chris Wilson <chris at chris-wilson.co.uk>
CC: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
Signed-off-by: Mika Kuoppala <mika.kuoppala at linux.intel.com>
Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk> (v4)
---
 man/intel_reg.rst      |   9 ++-
 tools/intel_reg.c      | 169 +++++++++++++++++++++++++++++++++++++++++++++++--
 tools/intel_reg_spec.h |   1 +
 3 files changed, 171 insertions(+), 8 deletions(-)

diff --git a/man/intel_reg.rst b/man/intel_reg.rst
index d1af178a..4ec24c4c 100644
--- a/man/intel_reg.rst
+++ b/man/intel_reg.rst
@@ -103,7 +103,7 @@ Display brief help.
 REGISTER REFERENCES
 ===================
 
-Registers are defined as [(PORTNAME|PORTNUM|MMIO-OFFSET):](REGNAME|REGADDR).
+Registers are defined as [(PORTNAME|PORTNUM|ENGINE|MMIO-OFFSET):](REGNAME|REGADDR).
 
 PORTNAME
     The register access method, most often MMIO, which is the default. The
@@ -120,6 +120,13 @@ PORTNUM
     Numbers above 0xff are automatically interpreted as MMIO offsets, not port
     numbers.
 
+ENGINE
+    Instead of cpu based MMIO, specified engine can be used for access method.
+    Batchbuffer will be targeted for the engine to do read/write. The list of
+    available engines is architecture specific and can be found with
+    "intel_reg help". Prefixing engine name with '-' uses non-privileged
+    batchbuffer for access.
+
 MMIO-OFFSET
     Use MMIO, and add this offset to the register address.
 
diff --git a/tools/intel_reg.c b/tools/intel_reg.c
index 00d2a4a1..ddff2794 100644
--- a/tools/intel_reg.c
+++ b/tools/intel_reg.c
@@ -33,6 +33,7 @@
 #include <unistd.h>
 
 #include "igt.h"
+#include "igt_gt.h"
 #include "intel_io.h"
 #include "intel_chipset.h"
 
@@ -73,6 +74,10 @@ struct config {
 
 	/* register spec */
 	char *specfile;
+
+	/* fd for engine access avoiding reopens */
+	int fd;
+
 	struct reg *regs;
 	ssize_t regcount;
 
@@ -236,13 +241,130 @@ static void dump_decode(struct config *config, struct reg *reg, uint32_t val)
 	}
 }
 
+static const struct intel_execution_engine2 *find_engine(const char *name)
+{
+	const struct intel_execution_engine2 *e;
+
+	if (strlen(name) < 2)
+		return NULL;
+
+	if (name[0] == '-')
+		name++;
+
+	for (e = intel_execution_engines2; e->name; e++) {
+		if (!strcasecmp(e->name, name))
+			return e;
+	}
+
+	return NULL;
+}
+
+static int register_srm(struct config *config, struct reg *reg,
+			uint32_t *val_in)
+{
+	const int gen = intel_gen(config->devid);
+	const bool r64b = gen >= 8;
+	const uint32_t ctx = 0;
+	struct drm_i915_gem_exec_object2 obj[2];
+	struct drm_i915_gem_relocation_entry reloc[1];
+	struct drm_i915_gem_execbuffer2 execbuf;
+	uint32_t *batch, *r;
+	const struct intel_execution_engine2 *engine;
+	bool secure;
+	int fd, i;
+	uint32_t val;
+
+	if (config->fd == -1) {
+		config->fd = __drm_open_driver(DRIVER_INTEL);
+		if (config->fd == -1) {
+			fprintf(stderr, "Error opening driver: %s",
+				strerror(errno));
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	fd = config->fd;
+	engine = find_engine(reg->engine);
+	if (engine == NULL)
+		exit(EXIT_FAILURE);
+
+	secure = reg->engine[0] != '-';
+
+	memset(obj, 0, sizeof(obj));
+	obj[0].handle = gem_create(fd, 4096);
+	obj[1].handle = gem_create(fd, 4096);
+	obj[1].relocs_ptr = to_user_pointer(reloc);
+	obj[1].relocation_count = 1;
+
+	batch = gem_mmap__cpu(fd, obj[1].handle, 0, 4096, PROT_WRITE);
+	gem_set_domain(fd, obj[1].handle,
+		       I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
+
+	i = 0;
+	if (val_in) {
+		batch[i++] = MI_NOOP;
+		batch[i++] = MI_NOOP;
+
+		batch[i++] = MI_LOAD_REGISTER_IMM;
+		batch[i++] = reg->addr;
+		batch[i++] = *val_in;
+		batch[i++] = MI_NOOP;
+	}
+
+	batch[i++] = 0x24 << 23 | (1 + r64b); /* SRM */
+	batch[i++] = reg->addr;
+	reloc[0].target_handle = obj[0].handle;
+	reloc[0].presumed_offset = obj[0].offset;
+	reloc[0].offset = i * sizeof(uint32_t);
+	reloc[0].delta = 0;
+	reloc[0].read_domains = I915_GEM_DOMAIN_RENDER;
+	reloc[0].write_domain = I915_GEM_DOMAIN_RENDER;
+	batch[i++] = reloc[0].delta;
+	if (r64b)
+		batch[i++] = 0;
+
+	batch[i++] = MI_BATCH_BUFFER_END;
+	munmap(batch, 4096);
+
+	memset(&execbuf, 0, sizeof(execbuf));
+	execbuf.buffers_ptr = to_user_pointer(obj);
+	execbuf.buffer_count = 2;
+	execbuf.flags = gem_class_instance_to_eb_flags(fd,
+						       engine->class,
+						       engine->instance);
+	if (secure)
+		execbuf.flags |= I915_EXEC_SECURE;
+
+	if (config->verbosity > 0)
+		printf("%s: using %sprivileged batch\n",
+		       engine->name,
+		       secure ? "" : "non-");
+
+	execbuf.rsvd1 = ctx;
+	gem_execbuf(fd, &execbuf);
+	gem_close(fd, obj[1].handle);
+
+	r = gem_mmap__cpu(fd, obj[0].handle, 0, 4096, PROT_READ);
+	gem_set_domain(fd, obj[0].handle, I915_GEM_DOMAIN_CPU, 0);
+
+	val = r[0];
+	munmap(r, 4096);
+
+	gem_close(fd, obj[0].handle);
+
+	return val;
+}
+
 static int read_register(struct config *config, struct reg *reg, uint32_t *valp)
 {
 	uint32_t val = 0;
 
 	switch (reg->port_desc.port) {
 	case PORT_MMIO:
-		val = INREG(reg->mmio_offset + reg->addr);
+		if (reg->engine)
+			val = register_srm(config, reg, NULL);
+		else
+			val = INREG(reg->mmio_offset + reg->addr);
 		break;
 	case PORT_PORTIO_VGA:
 		iopl(3);
@@ -299,7 +421,11 @@ static int write_register(struct config *config, struct reg *reg, uint32_t val)
 
 	switch (reg->port_desc.port) {
 	case PORT_MMIO:
-		OUTREG(reg->mmio_offset + reg->addr, val);
+		if (reg->engine) {
+			register_srm(config, reg, &val);
+		} else {
+			OUTREG(reg->mmio_offset + reg->addr, val);
+		}
 		break;
 	case PORT_PORTIO_VGA:
 		if (val > 0xff) {
@@ -351,7 +477,25 @@ static int write_register(struct config *config, struct reg *reg, uint32_t val)
 	return ret;
 }
 
-/* s has [(PORTNAME|PORTNUM|MMIO-OFFSET):](REGNAME|REGADDR) */
+static int parse_engine(struct reg *reg, const char *s)
+{
+	const struct intel_execution_engine2 *e;
+
+	e = find_engine(s);
+	if (e) {
+		reg->port_desc.port = PORT_MMIO;
+		reg->port_desc.name = strdup(s);
+		reg->port_desc.stride = 4;
+		reg->engine = strdup(s);
+		reg->mmio_offset = 0;
+	} else {
+		reg->engine = NULL;
+	}
+
+	return reg->engine == NULL;
+}
+
+/* s has [(PORTNAME|PORTNUM|ENGINE|MMIO-OFFSET):](REGNAME|REGADDR) */
 static int parse_reg(struct config *config, struct reg *reg, const char *s)
 {
 	unsigned long addr;
@@ -367,7 +511,9 @@ static int parse_reg(struct config *config, struct reg *reg, const char *s)
 	} else if (p) {
 		char *port_name = strndup(s, p - s);
 
-		ret = parse_port_desc(reg, port_name);
+		ret = parse_engine(reg, port_name);
+		if (ret)
+			ret = parse_port_desc(reg, port_name);
 
 		free(port_name);
 		p++;
@@ -616,6 +762,7 @@ static const struct command commands[] = {
 
 static int intel_reg_help(struct config *config, int argc, char *argv[])
 {
+	const struct intel_execution_engine2 *e;
 	int i;
 
 	printf("Intel graphics register multitool\n\n");
@@ -629,14 +776,18 @@ static int intel_reg_help(struct config *config, int argc, char *argv[])
 
 	printf("\n");
 	printf("REGISTER is defined as:\n");
-        printf("  [(PORTNAME|PORTNUM|MMIO-OFFSET):](REGNAME|REGADDR)\n");
+        printf("  [(PORTNAME|PORTNUM|ENGINE|MMIO-OFFSET):](REGNAME|REGADDR)\n");
 
 	printf("\n");
 	printf("PORTNAME is one of:\n");
 	intel_reg_spec_print_ports();
-	printf("\n");
+	printf("\n\n");
+
+	printf("ENGINE is one of:\n");
+	for (e = intel_execution_engines2; e->name; e++)
+		printf("%s -%s ", e->name, e->name);
+	printf("\n\n");
 
-	printf("\n");
 	printf("OPTIONS common to most COMMANDS:\n");
 	printf(" --spec=PATH    Read register spec from directory or file\n");
 	printf(" --mmio=FILE    Use an MMIO snapshot\n");
@@ -771,6 +922,7 @@ int main(int argc, char *argv[])
 	const struct command *command = NULL;
 	struct config config = {
 		.count = 1,
+		.fd = -1,
 	};
 	bool help = false;
 
@@ -898,5 +1050,8 @@ int main(int argc, char *argv[])
 
 	free(config.mmiofile);
 
+	if (config.fd >= 0)
+		close(config.fd);
+
 	return ret;
 }
diff --git a/tools/intel_reg_spec.h b/tools/intel_reg_spec.h
index dcb31430..c94c61ba 100644
--- a/tools/intel_reg_spec.h
+++ b/tools/intel_reg_spec.h
@@ -53,6 +53,7 @@ struct port_desc {
 
 struct reg {
 	struct port_desc port_desc;
+	char *engine;
 	uint32_t mmio_offset;
 	uint32_t addr;
 	char *name;
-- 
2.14.1



More information about the Intel-gfx mailing list