All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH umr] Add vram write functionality
@ 2017-08-29 13:41 Tom St Denis
  0 siblings, 0 replies; only message in thread
From: Tom St Denis @ 2017-08-29 13:41 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW; +Cc: Tom St Denis

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

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

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2017-08-29 13:41 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-29 13:41 [PATCH umr] Add vram write functionality Tom St Denis

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.