[PATCH umr] Add vram write functionality
Tom St Denis
tom.stdenis at amd.com
Tue Aug 29 13:41:42 UTC 2017
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
More information about the amd-gfx
mailing list