/* mem.c - rmtool mem stats: read-only FB/heap/BAR1 information. * * Allocation, mapping, pinning and arbitrary-handle inspection are * deliberately not implemented: they are write operations against the live * driver and are out of scope for this read-only oracle. */ #include #include #include #include #include "rmtool.h" static const NvU32 fb_indices[] = { NV2080_CTRL_FB_INFO_INDEX_TOTAL_RAM_SIZE, NV2080_CTRL_FB_INFO_INDEX_USABLE_RAM_SIZE, NV2080_CTRL_FB_INFO_INDEX_HEAP_SIZE, NV2080_CTRL_FB_INFO_INDEX_HEAP_FREE, NV2080_CTRL_FB_INFO_INDEX_LARGEST_FREE_REGION_SIZE_KB, NV2080_CTRL_FB_INFO_INDEX_BAR1_SIZE, NV2080_CTRL_FB_INFO_INDEX_BAR1_AVAIL_SIZE, }; static const char *fb_names[] = { "vram_total_kib", "vram_usable_kib", "heap_size_kib", "heap_free_kib", "largest_free_region_kib", "bar1_size_kib", "bar1_avail_kib", }; #define FB_N (sizeof(fb_indices) / sizeof(fb_indices[0])) static void usage(void) { printf("usage: rmtool mem stats [-d N|BDF] [--format=...]\n" " rmtool mem info -h HANDLE (not implemented: write " "path)\n" "rmtool is read-only; alloc/map/unmap/pin are refused.\n"); } static int mem_stats(struct rm_ctx *ctx) { NvU32 values[FB_N]; struct rm_kv kv[FB_N + 4]; char v[FB_N + 4][128]; NvU32 status; int rc, n = 0; unsigned int i; rc = rm_ctx_open(ctx); if (rc != 0) { fprintf(stderr, "rmtool: cannot open RM client: rc=%d\n", rc); return 2; } memset(values, 0, sizeof(values)); status = rm_query_fb(ctx, fb_indices, values, FB_N); if (status != 0) { fprintf(stderr, "rmtool: FB_GET_INFO_V2: %s\n", rm_status_str(status)); return 2; } for (i = 0; i < FB_N; i++) { char human[32]; rm_human_kib(values[i], human, sizeof(human)); snprintf(v[n], sizeof(v[n]), "%u (%s)", values[i], human); kv[n].key = fb_names[i]; kv[n].value = v[n]; n++; } if (values[2] >= values[3]) { unsigned int used = values[2] - values[3]; char human[32]; rm_human_kib(used, human, sizeof(human)); snprintf(v[n], sizeof(v[n]), "%u (%s)", used, human); kv[n].key = "heap_used_kib (derived)"; kv[n].value = v[n]; n++; } rm_print_kv("VRAM / heap (FB_GET_INFO_V2, KiB units)", kv, n, ctx->format); return 0; } static int parse_common(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; } return 0; } int cmd_mem(int argc, char **argv, struct rm_ctx *ctx) { int rc; if (argc < 2) { usage(); return 2; } if (strcmp(argv[1], "stats") == 0) { rc = parse_common(argc - 1, argv + 1, ctx); if (rc < 0) return 2; if (rc == 1) { usage(); return 0; } return mem_stats(ctx); } if (strcmp(argv[1], "alloc") == 0 || strcmp(argv[1], "map") == 0 || strcmp(argv[1], "unmap") == 0 || strcmp(argv[1], "pin") == 0 || strcmp(argv[1], "info") == 0) { fprintf(stderr, "rmtool: 'mem %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; }