[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