On Mon, 08 Jan 2018, Mika Kuoppala <[email protected]> wrote:
> 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.

Copy-pasting from the man page, we already have the notation:

"Registers are defined as [(PORTNAME|PORTNUM|MMIO-OFFSET):](REGNAME|REGADDR)."

Why don't we add this as ENGINE:REGNAME or something instead of an extra
--engine parameter? As a "port". Sure, it's more work, but I really like
the current possibility of reading all types of registers at once. Now
you prevent dumps that would contain both mmio and batch based reads.

BR,
Jani.


>
> v2: no MI_NOOP after BBE (Chris)
> v3: use modern engine names (Chris), use global fd
>
> Cc: Jani Nikula <[email protected]>
> Cc: Chris Wilson <[email protected]>
> CC: Joonas Lahtinen <[email protected]>
> Signed-off-by: Mika Kuoppala <[email protected]>
> ---
>  tools/intel_reg.c | 156 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 154 insertions(+), 2 deletions(-)
>
> diff --git a/tools/intel_reg.c b/tools/intel_reg.c
> index 00d2a4a1..7f3494ef 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,11 @@ struct config {
>  
>       /* register spec */
>       char *specfile;
> +
> +     /* engine to use for lri (write) and srm (read) */
> +     char *engine;
> +     int fd;
> +
>       struct reg *regs;
>       ssize_t regcount;
>  
> @@ -236,13 +242,140 @@ static void dump_decode(struct config *config, struct 
> reg *reg, uint32_t val)
>       }
>  }
>  
> +static const struct intel_execution_engine2 *find_engine(const char *name,
> +                                                      bool *secure)
> +{
> +     const struct intel_execution_engine2 *e;
> +
> +     if (strlen(name) < 2)
> +             goto out;
> +
> +     if (name[0] == '-') {
> +             *secure = false;
> +             name++;
> +     } else {
> +             *secure = true;
> +     }
> +
> +     for (e = intel_execution_engines2; e->name; e++) {
> +             if (!strcmp(e->name, name))
> +                     return e;
> +     }
> +
> +out:
> +     fprintf(stderr, "no such engine as '%s'\n", name);
> +
> +     fprintf(stderr, "valid engines:");
> +     for (e = intel_execution_engines2; 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(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(config->engine, &secure);
> +
> +     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 (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 +432,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 (config->engine) {
> +                     register_srm(config, reg, &val);
> +             } else {
> +                     OUTREG(reg->mmio_offset + reg->addr, val);
> +             }
>               break;
>       case PORT_PORTIO_VGA:
>               if (val > 0xff) {
> @@ -641,6 +778,7 @@ 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(" --all          Decode registers for all known platforms\n");
>       printf(" --binary       Binary dump registers\n");
>       printf(" --verbose      Increase verbosity\n");
> @@ -758,6 +896,7 @@ enum opt {
>       OPT_ALL,
>       OPT_BINARY,
>       OPT_SPEC,
> +     OPT_ENGINE,
>       OPT_VERBOSE,
>       OPT_QUIET,
>       OPT_HELP,
> @@ -771,11 +910,13 @@ int main(int argc, char *argv[])
>       const struct command *command = NULL;
>       struct config config = {
>               .count = 1,
> +             .fd = -1,
>       };
>       bool help = false;
>  
>       static struct option options[] = {
>               /* global options */
> +             { "engine",     required_argument,      NULL,   OPT_ENGINE },
>               { "spec",       required_argument,      NULL,   OPT_SPEC },
>               { "verbose",    no_argument,            NULL,   OPT_VERBOSE },
>               { "quiet",      no_argument,            NULL,   OPT_QUIET },
> @@ -830,6 +971,14 @@ 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_ALL:
>                       config.all_platforms = true;
>                       break;
> @@ -898,5 +1047,8 @@ int main(int argc, char *argv[])
>  
>       free(config.mmiofile);
>  
> +     if (config.fd >= 0)
> +             close(config.fd);
> +
>       return ret;
>  }

-- 
Jani Nikula, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to