Also add --vram-read and -vr which will eventually replace --vram and -v.

Signed-off-by: Tom St Denis <tom.stde...@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

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to