summaryrefslogtreecommitdiffstats
path: root/tools/rmtool/src/engine.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/rmtool/src/engine.c')
-rw-r--r--tools/rmtool/src/engine.c252
1 files changed, 252 insertions, 0 deletions
diff --git a/tools/rmtool/src/engine.c b/tools/rmtool/src/engine.c
new file mode 100644
index 0000000..c247e47
--- /dev/null
+++ b/tools/rmtool/src/engine.c
@@ -0,0 +1,252 @@
+/* engine.c - rmtool engine list/info via read-only GPU/engine controls. */
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+#include "rmtool.h"
+
+static void usage(void)
+{
+ printf("usage: rmtool engine list [-d N|BDF] [--format=...]\n"
+ " rmtool engine info [-d N|BDF] -e ENGINE\n"
+ "ENGINE is a FIFO table name (gr, ce0, nvdec0, ...).\n");
+}
+
+static int parse_list(int argc, char **argv, struct rm_ctx *ctx)
+{
+ static const struct option long_opts[] = {
+ { "device-spec", required_argument, NULL, 'd' },
+ { "format", required_argument, NULL, 'f' },
+ { "device", required_argument, NULL, 1000 },
+ { "help", no_argument, NULL, 'h' },
+ { NULL, 0, NULL, 0 },
+ };
+ int opt;
+
+ optind = 1;
+ opterr = 0;
+ while ((opt = getopt_long(argc, argv, "d:f:h", long_opts, NULL)) != -1) {
+ int rc;
+
+ if (opt == 'h')
+ return 1;
+ rc = rm_apply_common_opt(ctx, opt, optarg);
+ if (rc < 0)
+ return -1;
+ }
+ if (optind < argc) {
+ fprintf(stderr, "rmtool: unexpected argument '%s'\n",
+ argv[optind]);
+ return -1;
+ }
+ return 0;
+}
+
+static int engine_list(struct rm_ctx *ctx)
+{
+ NV2080_CTRL_GPU_GET_ENGINES_V2_PARAMS engines;
+ NV2080_FIFO_DEVICE_ENTRY *fifo;
+ const char *headers[] = { "IDX", "TYPE", "NAME", "PBDMAS",
+ "PBDMA IDS" };
+ char (*cells)[64];
+ int rc;
+ NvU32 status, n_fifo = 0;
+ unsigned int i;
+
+ fifo = calloc(1, sizeof(*fifo) * 512);
+ cells = calloc(1, sizeof(*cells) * (NV2080_GPU_MAX_ENGINES_LIST_SIZE *
+ 5));
+ if (fifo == NULL || cells == NULL) {
+ free(fifo);
+ free(cells);
+ return 2;
+ }
+ rc = rm_ctx_open(ctx);
+ if (rc != 0) {
+ fprintf(stderr, "rmtool: cannot open RM client: rc=%d\n", rc);
+ free(fifo);
+ free(cells);
+ return 2;
+ }
+ status = rm_query_engines(ctx, &engines);
+ if (status != 0) {
+ fprintf(stderr, "rmtool: GPU_GET_ENGINES_V2: %s\n",
+ rm_status_str(status));
+ free(fifo);
+ free(cells);
+ return 2;
+ }
+ status = rm_query_fifo_table(ctx, fifo, 512, &n_fifo);
+
+ for (i = 0; i < engines.engineCount; i++) {
+ char type[24];
+
+ snprintf(type, sizeof(type), "0x%x", engines.engineList[i]);
+ snprintf(cells[i * 5 + 0], sizeof(cells[0]), "%u", i);
+ snprintf(cells[i * 5 + 1], sizeof(cells[0]), "%s", type);
+ snprintf(cells[i * 5 + 2], sizeof(cells[0]), "%s",
+ rm_engine_name(fifo, n_fifo, engines.engineList[i]));
+ snprintf(cells[i * 5 + 3], sizeof(cells[0]), "-");
+ snprintf(cells[i * 5 + 4], sizeof(cells[0]), "-");
+ }
+ if (status == 0) {
+ NvU32 j;
+
+ for (j = 0; j < n_fifo && j < engines.engineCount; j++) {
+ snprintf(cells[j * 5 + 2], sizeof(cells[0]), "%s",
+ fifo[j].engineName);
+ snprintf(cells[j * 5 + 3], sizeof(cells[0]), "%u",
+ fifo[j].numPbdmas);
+ snprintf(cells[j * 5 + 4], sizeof(cells[0]),
+ "%u,%u", fifo[j].pbdmaIds[0],
+ fifo[j].pbdmaIds[1]);
+ }
+ }
+ if (ctx->format == RM_FMT_TABLE)
+ printf("%u engine(s); FIFO table %s\n", engines.engineCount,
+ status == 0 ? "read" : "unavailable");
+ rm_print_table("engines", headers, &cells[0][0], sizeof(cells[0]),
+ (int)engines.engineCount, 5, ctx->format);
+ free(fifo);
+ free(cells);
+ return 0;
+}
+
+static int engine_info(struct rm_ctx *ctx, const char *want)
+{
+ NV2080_FIFO_DEVICE_ENTRY *fifo;
+ struct rm_kv kv[8];
+ char v[8][256];
+ NvU32 n_fifo = 0, i;
+ int rc, n = 0;
+ NvU32 status;
+
+ fifo = calloc(1, sizeof(*fifo) * 512);
+ if (fifo == NULL)
+ return 2;
+ rc = rm_ctx_open(ctx);
+ if (rc != 0) {
+ fprintf(stderr, "rmtool: cannot open RM client: rc=%d\n", rc);
+ free(fifo);
+ return 2;
+ }
+ status = rm_query_fifo_table(ctx, fifo, 512, &n_fifo);
+ if (status != 0) {
+ fprintf(stderr, "rmtool: FIFO_GET_DEVICE_INFO_TABLE: %s\n",
+ rm_status_str(status));
+ free(fifo);
+ return 2;
+ }
+ for (i = 0; i < n_fifo; i++) {
+ if (strcasecmp(fifo[i].engineName, want) != 0)
+ continue;
+ snprintf(v[0], sizeof(v[0]), "%s", fifo[i].engineName);
+ kv[n].key = "Engine";
+ kv[n++].value = v[0];
+ snprintf(v[1], sizeof(v[1]), "%u", i);
+ kv[n].key = "Table index";
+ kv[n++].value = v[1];
+ snprintf(v[2], sizeof(v[2]), "%u", fifo[i].numPbdmas);
+ kv[n].key = "PBDMA count";
+ kv[n++].value = v[2];
+ snprintf(v[3], sizeof(v[3]), "%u,%u", fifo[i].pbdmaIds[0],
+ fifo[i].pbdmaIds[1]);
+ kv[n].key = "PBDMA ids";
+ kv[n++].value = v[3];
+ snprintf(v[4], sizeof(v[4]), "%u,%u",
+ fifo[i].pbdmaFaultIds[0], fifo[i].pbdmaFaultIds[1]);
+ kv[n].key = "PBDMA fault ids";
+ kv[n++].value = v[4];
+ snprintf(v[5], sizeof(v[5]),"%u", fifo[i].engineData[0]);
+ kv[n].key = "engineData[0] (type)";
+ kv[n++].value = v[5];
+ {
+ size_t off = 0;
+ unsigned int j;
+
+ for (j = 0; j < 16 && off < sizeof(v[6]); j++)
+ off += (size_t)snprintf(v[6] + off,
+ sizeof(v[6]) - off,
+ "%s%u", j ? "," : "",
+ fifo[i].engineData[j]);
+ }
+ kv[n].key = "engineData[0..15]";
+ kv[n++].value = v[6];
+ rm_print_kv("engine info (FIFO device table)", kv, n,
+ ctx->format);
+ free(fifo);
+ return 0;
+ }
+ fprintf(stderr, "rmtool: engine '%s' not found in FIFO table "
+ "(%u entries)\n", want, n_fifo);
+ free(fifo);
+ return 2;
+}
+
+int cmd_engine(int argc, char **argv, struct rm_ctx *ctx)
+{
+ const char *want = NULL;
+ int rc;
+
+ if (argc < 2) {
+ usage();
+ return 2;
+ }
+ if (strcmp(argv[1], "list") == 0) {
+ rc = parse_list(argc - 1, argv + 1, ctx);
+ if (rc < 0)
+ return 2;
+ if (rc == 1) {
+ usage();
+ return 0;
+ }
+ return engine_list(ctx);
+ }
+ if (strcmp(argv[1], "info") == 0) {
+ int opt;
+ static const struct option long_opts[] = {
+ { "device-spec", required_argument, NULL, 'd' },
+ { "format", required_argument, NULL, 'f' },
+ { "engine", required_argument, NULL, 'e' },
+ { "device", required_argument, NULL, 1000 },
+ { "help", no_argument, NULL, 'h' },
+ { NULL, 0, NULL, 0 },
+ };
+
+ optind = 1;
+ opterr = 0;
+ while ((opt = getopt_long(argc - 1, argv + 1, "d:f:e:h",
+ long_opts, NULL)) != -1) {
+ if (opt == 'h') {
+ usage();
+ return 0;
+ }
+ if (opt == 'e') {
+ want = optarg;
+ continue;
+ }
+ if (rm_apply_common_opt(ctx, opt, optarg) < 0)
+ return 2;
+ }
+ if (want == NULL) {
+ usage();
+ return 2;
+ }
+ return engine_info(ctx, want);
+ }
+ if (strcmp(argv[1], "allocate") == 0 ||
+ strcmp(argv[1], "start") == 0 ||
+ strcmp(argv[1], "stop") == 0 ||
+ strcmp(argv[1], "config") == 0) {
+ fprintf(stderr,
+ "rmtool: 'engine %s' is a write/ownership operation "
+ "and is refused by policy (read-only host oracle). "
+ "See debug/risc-v-gsp-rm-vm/docs/17-RM-HARNESS.md.\n",
+ argv[1]);
+ return 4;
+ }
+ usage();
+ return 2;
+}