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) Cc: Jani Nikula <jani.nikula@xxxxxxxxx> Cc: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> CC: Joonas Lahtinen <joonas.lahtinen@xxxxxxxxxxxxxxx> Signed-off-by: Mika Kuoppala <mika.kuoppala@xxxxxxxxxxxxxxx> --- tools/intel_reg.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 137 insertions(+), 2 deletions(-) diff --git a/tools/intel_reg.c b/tools/intel_reg.c index 00d2a4a1..ec45c2c9 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,12 @@ struct config { /* register spec */ char *specfile; + + /* engine to use for lri (write) and srm (read) */ + char *engine; + /* use secure batch */ + bool engine_secure_batch; + struct reg *regs; ssize_t regcount; @@ -236,13 +243,116 @@ static void dump_decode(struct config *config, struct reg *reg, uint32_t val) } } +static const struct intel_execution_engine *find_engine(const char *name) +{ + const struct intel_execution_engine *e; + + for (e = intel_execution_engines; e->name; e++) { + if (!strcmp(e->name, name)) + return e; + } + + fprintf(stderr, "no such engine as '%s'\n", name); + + fprintf(stderr, "valid engines:"); + for (e = intel_execution_engines; e->name; e++) + fprintf(stderr, " %s", e->name); + + fprintf(stderr, "\n"); + + exit(EXIT_FAILURE); +} + +static int register_srm(struct config *config, struct reg *reg, + uint32_t *val_in) +{ + const int gen = intel_gen(intel_get_drm_devid(config->drm_fd)); + 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_engine *engine; + int i915, i; + uint32_t val; + i915 = config->drm_fd; + + engine = find_engine(config->engine); + + memset(obj, 0, sizeof(obj)); + obj[0].handle = gem_create(i915, 4096); + obj[1].handle = gem_create(i915, 4096); + obj[1].relocs_ptr = to_user_pointer(reloc); + obj[1].relocation_count = 1; + + batch = gem_mmap__cpu(i915, obj[1].handle, 0, 4096, PROT_WRITE); + gem_set_domain(i915, 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 = engine->exec_id; + + if (config->engine_secure_batch) { + execbuf.flags |= I915_EXEC_SECURE; + + if (config->verbosity > 0) + printf("%s: using priviledged (secure) batch\n", + engine->name); + } + + execbuf.rsvd1 = ctx; + gem_execbuf(i915, &execbuf); + gem_close(i915, obj[1].handle); + + r = gem_mmap__cpu(i915, obj[0].handle, 0, 4096, PROT_READ); + gem_set_domain(i915, obj[0].handle, I915_GEM_DOMAIN_CPU, 0); + + val = r[0]; + + gem_close(i915, 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 (config->engine) + val = register_srm(config, reg, NULL); + else + val = INREG(reg->mmio_offset + reg->addr); break; case PORT_PORTIO_VGA: iopl(3); @@ -299,7 +409,15 @@ 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 (config->engine) { + ret = register_srm(config, reg, &val); + if (config->verbosity > 0 && ret != val) + fprintf(stderr, + "value readback 0x%08x != 0x%08x\n", + ret, val); + } else { + OUTREG(reg->mmio_offset + reg->addr, val); + } break; case PORT_PORTIO_VGA: if (val > 0xff) { @@ -641,6 +759,8 @@ static int intel_reg_help(struct config *config, int argc, char *argv[]) printf(" --spec=PATH Read register spec from directory or file\n"); printf(" --mmio=FILE Use an MMIO snapshot\n"); printf(" --devid=DEVID Specify PCI device ID for --mmio=FILE\n"); + printf(" --engine=ENGINE Use a specific engine to read/write\n"); + printf(" --secure Use secure batch to do engine read/write\n"); printf(" --all Decode registers for all known platforms\n"); printf(" --binary Binary dump registers\n"); printf(" --verbose Increase verbosity\n"); @@ -758,6 +878,8 @@ enum opt { OPT_ALL, OPT_BINARY, OPT_SPEC, + OPT_ENGINE, + OPT_SECURE, OPT_VERBOSE, OPT_QUIET, OPT_HELP, @@ -776,6 +898,8 @@ int main(int argc, char *argv[]) static struct option options[] = { /* global options */ + { "engine", required_argument, NULL, OPT_ENGINE }, + { "secure", no_argument, NULL, OPT_SECURE}, { "spec", required_argument, NULL, OPT_SPEC }, { "verbose", no_argument, NULL, OPT_VERBOSE }, { "quiet", no_argument, NULL, OPT_QUIET }, @@ -830,6 +954,17 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } break; + case OPT_ENGINE: + config.engine = strdup(optarg); + if (!config.engine) { + fprintf(stderr, "strdup: %s\n", + strerror(errno)); + return EXIT_FAILURE; + } + break; + case OPT_SECURE: + config.engine_secure_batch = true; + break; case OPT_ALL: config.all_platforms = true; break; -- 2.11.0 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx