Also add --vram-read and -vr which will eventually replace --vram and -v. Signed-off-by: Tom St Denis <tom.stdenis at amd.com> --- doc/umr.1 | 6 ++++- src/app/main.c | 43 +++++++++++++++++++++++++++++--- src/lib/read_vram.c | 72 ++++++++++++++++++++++++++++++++++------------------- src/umr.h | 6 ++++- 4 files changed, 97 insertions(+), 30 deletions(-) diff --git a/doc/umr.1 b/doc/umr.1 index 06950925b7b6..b990ff2c412f 100644 --- a/doc/umr.1 +++ b/doc/umr.1 @@ -94,12 +94,16 @@ The VMID can be specified in hexadecimal (with leading '0x') or in decimal. Implies '-O verbose' for the duration of the command so does not require it to be manually specified. -.IP "--vram, -v [vmid@]<address> <size>" +.IP "--vram-read, -vr [vmid@]<address> <size>" Read 'size' bytes (in hex) from the address specified (in hexadecimal) from VRAM to stdout. Optionally specify the VMID (in decimal or in hex with a 0x prefix) treating the address as a virtual address instead. Can use 'use_pci' to directly access VRAM. +.IP "--vram-write, -vw [vmid@]<address> <size>" +Write 'size' bytes (in hex) to the address specified (in hexadecimal) to VRAM +from stdin. + .IP "--update, -u" <filename> Specify update file to add, change, or delete registers from the register database. Useful for adding registers that are not including in the kernel headers. diff --git a/src/app/main.c b/src/app/main.c index 920f6815e220..8fdad3580686 100644 --- a/src/app/main.c +++ b/src/app/main.c @@ -382,7 +382,8 @@ int main(int argc, char **argv) printf("--vm-decode requires two parameters\n"); return EXIT_FAILURE; } - } else if (!strcmp(argv[i], "--vram") || !strcmp(argv[i], "-v")) { + } else if (!strcmp(argv[i], "--vram") || !strcmp(argv[i], "-v") || + !strcmp(argv[i], "--vram-read") || !strcmp(argv[i], "-vr")) { if (i + 2 < argc) { unsigned char buf[256]; uint64_t address; @@ -413,7 +414,41 @@ int main(int argc, char **argv) } while (size); i += 2; } else { - printf("--vram requires two parameters\n"); + printf("--vram-read requires two parameters\n"); + return EXIT_FAILURE; + } + } else if (!strcmp(argv[i], "--vram-write") || !strcmp(argv[i], "-vw")) { + if (i + 2 < argc) { + unsigned char buf[256]; + uint64_t address; + uint32_t size, n, vmid; + + if (!asic) + asic = get_asic(); + + // allow specifying the vmid in hex as well so + // people can add the HUB flags more easily + if ((n = sscanf(argv[i+1], "0x%"SCNx32"@%"SCNx64, &vmid, &address)) != 2) + if ((n = sscanf(argv[i+1], "%"SCNu32"@%"SCNx64, &vmid, &address)) != 2) { + sscanf(argv[i+1], "%"SCNx64, &address); + vmid = UMR_LINEAR_HUB; + } + + // imply user hub if hub name specified + if (options.hub_name[0]) + vmid |= UMR_USER_HUB; + + sscanf(argv[i+2], "%"SCNx32, &size); + do { + n = size > sizeof(buf) ? sizeof(buf) : size; + fread(buf, 1, n, stdin); + umr_write_vram(asic, vmid, address, n, buf); + size -= n; + address += n; + } while (size); + i += 2; + } else { + printf("--vram-write requires two parameters\n"); return EXIT_FAILURE; } } else if (!strcmp(argv[i], "--option") || !strcmp(argv[i], "-O")) { @@ -479,11 +514,13 @@ int main(int argc, char **argv) "\n\t\tThe VMID can be specified in hexadecimal (with leading '0x') or in decimal." "\n\t\tImplies '-O verbose' for the duration of the command so does not require it" "\n\t\tto be manually specified.\n" -"\n\t--vram, -v [<vmid>@]<address> <size>" +"\n\t--vram-read, -vr [<vmid>@]<address> <size>" "\n\t\tRead 'size' bytes (in hex) from a given address (in hex) to stdout. Optionally" "\n\t\tspecify the VMID (in decimal or in hex with a '0x' prefix) treating the address" "\n\t\tas a virtual address instead. Can use 'verbose' option to print out PDE/PTE" "\n\t\tdecodings.\n" +"\n\t--vram-write, -vw [<vmid>@]<address> <size>" + "\n\t\tWrite 'size' bytes (in hex) to a given address (in hex) from stdin.\n" "\n\t--option -O <string>[,<string>,...]\n\t\tEnable various flags: bits, bitsfull, empty_log, follow, named, many," "\n\t\tuse_pci, use_colour, read_smc, quiet, no_kernel, verbose, halt_waves.\n" "\n\n", UMR_BUILD_VER, UMR_BUILD_REV); diff --git a/src/lib/read_vram.c b/src/lib/read_vram.c index c254f5a2e406..00783974ce6d 100644 --- a/src/lib/read_vram.c +++ b/src/lib/read_vram.c @@ -182,7 +182,7 @@ error: return err; } -static void read_via_mmio(struct umr_asic *asic, uint64_t address, uint32_t size, void *dst) +static void access_vram_via_mmio(struct umr_asic *asic, uint64_t address, uint32_t size, void *dst, int write_en) { uint32_t MM_INDEX, MM_INDEX_HI, MM_DATA; uint32_t *out = dst; @@ -202,7 +202,10 @@ static void read_via_mmio(struct umr_asic *asic, uint64_t address, uint32_t size while (size) { umr_write_reg(asic, MM_INDEX, address | 0x80000000, REG_MMIO); umr_write_reg(asic, MM_INDEX_HI, address >> 31, REG_MMIO); - *out++ = umr_read_reg(asic, MM_DATA, REG_MMIO); + if (write_en == 0) + *out++ = umr_read_reg(asic, MM_DATA, REG_MMIO); + else + umr_write_reg(asic, MM_DATA, *out++, REG_MMIO); size -= 4; address += 4; } @@ -214,7 +217,7 @@ static void read_via_mmio(struct umr_asic *asic, uint64_t address, uint32_t size #define DEBUG(...) #endif -static int umr_read_sram(uint64_t address, uint32_t size, void *dst) +static int umr_access_sram(uint64_t address, uint32_t size, void *dst, int write_en) { int fd; @@ -224,11 +227,18 @@ static int umr_read_sram(uint64_t address, uint32_t size, void *dst) if (fd < 0) fd = open("/dev/mem", O_RDWR | O_DSYNC); if (fd >= 0) { - memset(dst, 0xFF, size); lseek(fd, address, SEEK_SET); - if (read(fd, dst, size) != size) { - close(fd); - return -1; + if (write_en == 0) { + memset(dst, 0xFF, size); + if (read(fd, dst, size) != size) { + close(fd); + return -1; + } + } else { + if (write(fd, dst, size) != size) { + close(fd); + return -1; + } } close(fd); return 0; @@ -236,7 +246,10 @@ static int umr_read_sram(uint64_t address, uint32_t size, void *dst) return -1; } -static int umr_read_vram_vi(struct umr_asic *asic, uint32_t vmid, uint64_t address, uint32_t size, void *dst) + +static int umr_access_vram_vi(struct umr_asic *asic, uint32_t vmid, + uint64_t address, uint32_t size, + void *dst, int write_en) { uint64_t start_addr, page_table_start_addr, page_table_base_addr, page_table_size, pte_idx, pde_idx, pte_entry, pde_entry, @@ -415,14 +428,14 @@ static int umr_read_vram_vi(struct umr_asic *asic, uint32_t vmid, uint64_t addre // allow destination to be NULL to simply use decoder if (pdst) { if (pte_fields.system) { - if (umr_read_sram(start_addr, chunk_size, pdst) < 0) { - fprintf(stderr, "[ERROR]: Cannot read system ram, perhaps CONFIG_STRICT_DEVMEM is set in your kernel config?\n"); + if (umr_access_sram(start_addr, chunk_size, pdst, write_en) < 0) { + fprintf(stderr, "[ERROR]: Cannot access system ram, perhaps CONFIG_STRICT_DEVMEM is set in your kernel config?\n"); fprintf(stderr, "[ERROR]: Alternatively download and install /dev/fmem\n"); return -1; } } else { - if (umr_read_vram(asic, UMR_LINEAR_HUB, start_addr, chunk_size, pdst) < 0) { - fprintf(stderr, "[ERROR]: Cannot read from VRAM\n"); + if (umr_access_vram(asic, UMR_LINEAR_HUB, start_addr, chunk_size, pdst, write_en) < 0) { + fprintf(stderr, "[ERROR]: Cannot access VRAM\n"); return -1; } } @@ -434,7 +447,9 @@ static int umr_read_vram_vi(struct umr_asic *asic, uint32_t vmid, uint64_t addre return 0; } -static int umr_read_vram_ai(struct umr_asic *asic, uint32_t vmid, uint64_t address, uint32_t size, void *dst) +static int umr_access_vram_ai(struct umr_asic *asic, uint32_t vmid, + uint64_t address, uint32_t size, + void *dst, int write_en) { uint64_t start_addr, page_table_start_addr, page_table_base_addr, page_table_size, pte_idx, pde_idx, pte_entry, pde_entry, @@ -757,14 +772,14 @@ static int umr_read_vram_ai(struct umr_asic *asic, uint32_t vmid, uint64_t addre // allow destination to be NULL to simply use decoder if (pdst) { if (pte_fields.system) { - if (umr_read_sram(start_addr, chunk_size, pdst) < 0) { - fprintf(stderr, "[ERROR]: Cannot read system ram, perhaps CONFIG_STRICT_DEVMEM is set in your kernel config?\n"); + if (umr_access_sram(start_addr, chunk_size, pdst, write_en) < 0) { + fprintf(stderr, "[ERROR]: Cannot access system ram, perhaps CONFIG_STRICT_DEVMEM is set in your kernel config?\n"); fprintf(stderr, "[ERROR]: Alternatively download and install /dev/fmem\n"); return -1; } } else { - if (umr_read_vram(asic, UMR_LINEAR_HUB, start_addr, chunk_size, pdst) < 0) { - fprintf(stderr, "[ERROR]: Cannot read from VRAM\n"); + if (umr_access_vram(asic, UMR_LINEAR_HUB, start_addr, chunk_size, pdst, write_en) < 0) { + fprintf(stderr, "[ERROR]: Cannot access VRAM\n"); return -1; } } @@ -776,14 +791,14 @@ static int umr_read_vram_ai(struct umr_asic *asic, uint32_t vmid, uint64_t addre return 0; } -int umr_read_vram(struct umr_asic *asic, uint32_t vmid, uint64_t address, uint32_t size, void *dst) +int umr_access_vram(struct umr_asic *asic, uint32_t vmid, uint64_t address, uint32_t size, void *data, int write_en) { // only aligned reads if ((address & 3) || (size & 3)) return -1; // only aligned destinations - if (((intptr_t)dst) & 3) { + if (((intptr_t)data) & 3) { fprintf(stderr, "[BUG]: vram read destination is not 4-byte aligned\n"); return -1; } @@ -793,12 +808,19 @@ int umr_read_vram(struct umr_asic *asic, uint32_t vmid, uint64_t address, uint32 // addressing is physical if (asic->options.use_pci == 0) { lseek(asic->fd.vram, address, SEEK_SET); - if (read(asic->fd.vram, dst, size) != size) { - fprintf(stderr, "[ERROR]: Could not read from VRAM at address 0x%llx\n", (unsigned long long)address); - return -1; + if (write_en == 0) { + if (read(asic->fd.vram, data, size) != size) { + fprintf(stderr, "[ERROR]: Could not read from VRAM at address 0x%llx\n", (unsigned long long)address); + return -1; + } + } else { + if (write(asic->fd.vram, data, size) != size) { + fprintf(stderr, "[ERROR]: Could not write to VRAM at address 0x%llx\n", (unsigned long long)address); + return -1; + } } } else { - read_via_mmio(asic, address, size, dst); + access_vram_via_mmio(asic, address, size, data, write_en); } return 0; } @@ -818,10 +840,10 @@ int umr_read_vram(struct umr_asic *asic, uint32_t vmid, uint64_t address, uint32 case FAMILY_SI: case FAMILY_CIK: case FAMILY_VI: - return umr_read_vram_vi(asic, vmid, address, size, dst); + return umr_access_vram_vi(asic, vmid, address, size, data, write_en); case FAMILY_RV: case FAMILY_AI: - return umr_read_vram_ai(asic, vmid, address, size, dst); + return umr_access_vram_ai(asic, vmid, address, size, data, write_en); default: fprintf(stderr, "[BUG]: Unsupported ASIC family type for umr_read_vram()\n"); return -1; diff --git a/src/umr.h b/src/umr.h index b6fe4ee876a7..e49c80c081d2 100644 --- a/src/umr.h +++ b/src/umr.h @@ -545,7 +545,11 @@ int umr_sq_cmd_halt_waves(struct umr_asic *asic, enum umr_sq_cmd_halt_resume mod /* IB/ring decoding/dumping/etc */ void umr_print_decode(struct umr_asic *asic, struct umr_ring_decoder *decoder, uint32_t ib); void umr_dump_ib(struct umr_asic *asic, struct umr_ring_decoder *decoder); -int umr_read_vram(struct umr_asic *asic, uint32_t vmid, uint64_t address, uint32_t size, void *dst); + +// memory access +int umr_access_vram(struct umr_asic *asic, uint32_t vmid, uint64_t address, uint32_t size, void *data, int write_en); +#define umr_read_vram(asic, vmid, address, size, dst) umr_access_vram(asic, vmid, address, size, dst, 0) +#define umr_write_vram(asic, vmid, address, size, src) umr_access_vram(asic, vmid, address, size, src, 1) #define RED (options.use_colour ? "\x1b[31;1m" : "") #define YELLOW (options.use_colour ? "\x1b[33;1m" : "") -- 2.12.0