All of lore.kernel.org
 help / color / mirror / Atom feed
* umr: Various cleanups and better VM decoding
@ 2017-07-25 17:23 Tom St Denis
       [not found] ` <20170725172324.28365-1-tom.stdenis-5C7GfCeVMHo@public.gmane.org>
  0 siblings, 1 reply; 5+ messages in thread
From: Tom St Denis @ 2017-07-25 17:23 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

This series is a revamp of the series I sent out earlier in the 
week.  To recap:

Patch #1 removes the risky option and --print command.

Patch #2 allows you to specify VMIDs in hex as well as decimal

Patch #3 is a couple of simple cleanups found by review and 
static checking.

Patch #4 includes three changes that were worked on at the same
time.  First, you can halt SQ waves while reading them.  Next,
we add the --vm-decode command which is used to decode VM 
addresses (without reading data from the pages), and finally
the read_vram functions have been overhauled to print out
more useful information as well as fix some framebuffer offset
bugs present on VI due to recent kernel changes.

In a subsequent series I plan to factor our the PDE/PTE decoding
from the read_vram functions so that the --vm-decode can be less
noisy.  But that doesn't fit in with this series so it'll have
to wait.  So for now I apologize for the noisy --vm-decode output :-)

Cheers,
Tom



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

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH umr 1/4] Remove 'risky' option --print command. (v2)
       [not found] ` <20170725172324.28365-1-tom.stdenis-5C7GfCeVMHo@public.gmane.org>
@ 2017-07-25 17:23   ` Tom St Denis
  2017-07-25 17:23   ` [PATCH umr 2/4] Add ability to specify VMID in hex Tom St Denis
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Tom St Denis @ 2017-07-25 17:23 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW; +Cc: Tom St Denis

Signed-off-by: Tom St Denis <tom.stdenis@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>

(v2) Remove --print from man page
---
 demo/update/read_sensor.sh |  2 +-
 doc/umr.1                  |  9 ---------
 src/app/main.c             |  8 +-------
 src/app/scan.c             |  1 -
 src/app/set_bit.c          |  1 -
 src/app/set_reg.c          |  1 -
 src/lib/ip/gfx60.c         | 15 ++-------------
 src/lib/ip/gfx70.c         | 15 ++-------------
 src/lib/ip/gfx72.c         | 15 ++-------------
 src/lib/ip/gfx80.c         | 15 ++-------------
 src/lib/ip/gfx81.c         | 15 ++-------------
 src/lib/ip/gfx90.c         | 13 -------------
 src/lib/ip/gfx91.c         | 13 -------------
 src/lib/ip/mmhub10.c       | 13 -------------
 src/lib/ip/mmhub91.c       | 13 -------------
 src/lib/ip/mp100.c         | 13 -------------
 src/lib/ip/mp90.c          | 13 -------------
 src/lib/ip/oss10.c         | 15 ++-------------
 src/lib/ip/oss20.c         | 15 ++-------------
 src/lib/ip/oss30.c         | 15 ++-------------
 src/lib/ip/smu60.c         | 15 ++-------------
 src/lib/ip/smu700.c        | 15 ++-------------
 src/lib/ip/smu701.c        | 15 ++-------------
 src/lib/ip/smu710.c        | 15 ++-------------
 src/lib/ip/smu711.c        | 15 ++-------------
 src/lib/ip/smu712.c        | 15 ++-------------
 src/lib/ip/smu713.c        | 15 ++-------------
 src/lib/ip/smu80.c         | 15 ++-------------
 src/umr.h                  |  1 -
 29 files changed, 34 insertions(+), 307 deletions(-)

diff --git a/demo/update/read_sensor.sh b/demo/update/read_sensor.sh
index 94267f45492f..406037b9c7ca 100755
--- a/demo/update/read_sensor.sh
+++ b/demo/update/read_sensor.sh
@@ -6,7 +6,7 @@
 # In this case we're reading the NB voltage sensor from Carrizo
 
 # capture value in hex
-NB_VID=`umr -O risky,risky,read_smc -u carrizo.update -r carrizo.smu80.ixSMUSVI_NB_CURRENTVID | cut -b1-4`
+NB_VID=`umr -O read_smc -u carrizo.update -r carrizo.smu80.ixSMUSVI_NB_CURRENTVID | cut -b1-4`
 
 # convert to decimal
 NB_VID_DEC=`printf "%d" ${NB_VID}`
diff --git a/doc/umr.1 b/doc/umr.1
index 601866a57a7e..9384c2430bda 100644
--- a/doc/umr.1
+++ b/doc/umr.1
@@ -21,9 +21,6 @@ is not yet loaded or a display is not yet attached.
 Force a specific PCI device using the domain:bus:slot.function format in hex.
 This is useful when more than one GPU is available. If the amdgpu driver is
 loaded the corresponding instance will be automatically detected.
-.IP "--print, -p"
-Enable scanning and printing all registers.  Defaults to off as it can
-be very verbose.
 .IP "--config, -c"
 Print out configuation data read from kernel driver.
 .IP "--enumerate, -e"
@@ -107,12 +104,6 @@ separated strings.  Options should be specified before --update or --force comma
 .B quiet
      Disable various informative but not required (for functionality) outputs.
 
-.B risky
-     enables scanning risky ip blocks (such as GFX).  Specify twice for SMU
-     blocks.  This flag is necessary since some blocks are not stable to blindly
-     --scan (or --print) without causing GPU hangs.  The flag is intended to prevent
-     accidental hangs.
-
 .B read_smc
      Enable scanning of SMC registers.
 
diff --git a/src/app/main.c b/src/app/main.c
index 4fc26510be32..d8278a93e1cc 100644
--- a/src/app/main.c
+++ b/src/app/main.c
@@ -83,9 +83,7 @@ static void parse_options(char *str)
 		*p = 0;
 		if (*str == ',')
 			++str;
-		if (!strcmp(option, "risky")) {
-			options.risky++;
-		} else if (!strcmp(option, "named")) {
+		if (!strcmp(option, "named")) {
 			options.named = 1;
 		} else if (!strcmp(option, "many")) {
 			options.named = 1;
@@ -184,9 +182,6 @@ int main(int argc, char **argv)
 				printf("--pci requires domain:bus:slot.function\n");
 				return EXIT_FAILURE;
 			}
-		} else if (!strcmp(argv[i], "--print") || !strcmp(argv[i], "-p")) {
-			options.print = 1;
-			options.need_scan = 1;
 		} else if (!strcmp(argv[i], "--config") || !strcmp(argv[i], "-c")) {
 			if (!asic)
 				asic = get_asic();
@@ -398,7 +393,6 @@ int main(int argc, char **argv)
 	"\n\t\tForce a specific PCI device using the domain:bus:slot.function format in hex."
 	"\n\t\tThis is useful when more than one GPU is available. If the amdgpu driver is"
 	"\n\t\tloaded the corresponding instance will be automatically detected.\n"
-"\n\t--print, -p\n\t\tEnable dumping of all device registers. (default: off)\n"
 "\n\t--config, -c\n\t\tPrint out configuation data read from kernel driver.\n"
 "\n\t--enumerate, -e\n\t\tEnumerate all AMDGPU devices detected.\n"
 "\n\t--list-blocks, -lb\n\t\tList IP blocks discovered for this device.\n"
diff --git a/src/app/scan.c b/src/app/scan.c
index 29a3e46ba3f7..f83b925f00ae 100644
--- a/src/app/scan.c
+++ b/src/app/scan.c
@@ -45,7 +45,6 @@ int umr_scan_asic(struct umr_asic *asic, char *asicname, char *ipname, char *reg
 							r = asic->blocks[i]->grant(asic);
 							if (r) {
 								if (ipname[0]) {
-									fprintf(stderr, "[ERROR]: Must specify at least one 'risky' option before scanning specific blocks.\n");
 									exit(EXIT_FAILURE);
 								}
 								continue;
diff --git a/src/app/set_bit.c b/src/app/set_bit.c
index 44cdf6ada0b5..c9941126f822 100644
--- a/src/app/set_bit.c
+++ b/src/app/set_bit.c
@@ -64,7 +64,6 @@ int umr_set_register_bit(struct umr_asic *asic, char *regpath, char *regvalue)
 									}
 									if (asic->blocks[i]->grant) {
 										if (asic->blocks[i]->grant(asic)) {
-											fprintf(stderr, "[ERROR]: Must specify at least one 'risky' before writing to this block.\n");
 											return -1;
 										}
 									}
diff --git a/src/app/set_reg.c b/src/app/set_reg.c
index 9952843ea6f3..79eab1c3e391 100644
--- a/src/app/set_reg.c
+++ b/src/app/set_reg.c
@@ -61,7 +61,6 @@ int umr_set_register(struct umr_asic *asic, char *regpath, char *regvalue)
 
 							if (asic->blocks[i]->grant) {
 								if (asic->blocks[i]->grant(asic)) {
-									fprintf(stderr, "[ERROR]: Must specify at least one 'risky' before writing to this block.\n");
 									return -1;
 								}
 							}
diff --git a/src/lib/ip/gfx60.c b/src/lib/ip/gfx60.c
index 73cf7878709d..d122bd4a9660 100644
--- a/src/lib/ip/gfx60.c
+++ b/src/lib/ip/gfx60.c
@@ -30,22 +30,12 @@ static const struct umr_reg gfx60_registers[] = {
 #include "gfx60_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_gfx60(struct umr_options *options)
 {
 	struct umr_ip_block *ip;
 
+	(void)options;
+
 	ip = calloc(1, sizeof *ip);
 	if (!ip)
 		return NULL;
@@ -57,7 +47,6 @@ struct umr_ip_block *umr_create_gfx60(struct umr_options *options)
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 1) ? grant : deny;
 	memcpy(ip->regs, gfx60_registers, sizeof(gfx60_registers));
 	return ip;
 }
diff --git a/src/lib/ip/gfx70.c b/src/lib/ip/gfx70.c
index e9bfa4bca8f6..73e06f115285 100644
--- a/src/lib/ip/gfx70.c
+++ b/src/lib/ip/gfx70.c
@@ -29,22 +29,12 @@ static const struct umr_reg gfx70_registers[] = {
 #include "gfx70_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_gfx70(struct umr_options *options)
 {
 	struct umr_ip_block *ip;
 
+	(void)options;
+
 	ip = calloc(1, sizeof *ip);
 	if (!ip)
 		return NULL;
@@ -56,7 +46,6 @@ struct umr_ip_block *umr_create_gfx70(struct umr_options *options)
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 1) ? grant : deny;
 	memcpy(ip->regs, gfx70_registers, sizeof(gfx70_registers));
 	return ip;
 }
diff --git a/src/lib/ip/gfx72.c b/src/lib/ip/gfx72.c
index cd04f8df3a70..61fa00df3f77 100644
--- a/src/lib/ip/gfx72.c
+++ b/src/lib/ip/gfx72.c
@@ -30,22 +30,12 @@ static const struct umr_reg gfx72_registers[] = {
 #include "gfx72_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_gfx72(struct umr_options *options)
 {
 	struct umr_ip_block *ip;
 
+	(void)options;
+
 	ip = calloc(1, sizeof *ip);
 	if (!ip)
 		return NULL;
@@ -57,7 +47,6 @@ struct umr_ip_block *umr_create_gfx72(struct umr_options *options)
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 1) ? grant : deny;
 	memcpy(ip->regs, gfx72_registers, sizeof(gfx72_registers));
 	return ip;
 }
diff --git a/src/lib/ip/gfx80.c b/src/lib/ip/gfx80.c
index 211c92570b21..ecdf7d236346 100644
--- a/src/lib/ip/gfx80.c
+++ b/src/lib/ip/gfx80.c
@@ -30,22 +30,12 @@ static const struct umr_reg gfx80_registers[] = {
 #include "gfx80_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_gfx80(struct umr_options *options)
 {
 	struct umr_ip_block *ip;
 
+	(void)options;
+
 	ip = calloc(1, sizeof *ip);
 	if (!ip)
 		return NULL;
@@ -57,7 +47,6 @@ struct umr_ip_block *umr_create_gfx80(struct umr_options *options)
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 1) ? grant : deny;
 	memcpy(ip->regs, gfx80_registers, sizeof(gfx80_registers));
 	return ip;
 }
diff --git a/src/lib/ip/gfx81.c b/src/lib/ip/gfx81.c
index ef19203df141..cd485cc4af7f 100644
--- a/src/lib/ip/gfx81.c
+++ b/src/lib/ip/gfx81.c
@@ -30,22 +30,12 @@ static const struct umr_reg gfx81_registers[] = {
 #include "gfx81_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_gfx81(struct umr_options *options)
 {
 	struct umr_ip_block *ip;
 
+	(void)options;
+
 	ip = calloc(1, sizeof *ip);
 	if (!ip)
 		return NULL;
@@ -57,7 +47,6 @@ struct umr_ip_block *umr_create_gfx81(struct umr_options *options)
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 1) ? grant : deny;
 	memcpy(ip->regs, gfx81_registers, sizeof(gfx81_registers));
 	return ip;
 }
diff --git a/src/lib/ip/gfx90.c b/src/lib/ip/gfx90.c
index e4a049ecb843..a1059c6cdc7d 100644
--- a/src/lib/ip/gfx90.c
+++ b/src/lib/ip/gfx90.c
@@ -30,18 +30,6 @@ static const struct umr_reg_soc15 gfx90_registers[] = {
 #include "gfx90_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_gfx90(struct umr_ip_offsets_soc15 *soc15_offsets, struct umr_options *options)
 {
 	struct umr_ip_block *ip;
@@ -57,7 +45,6 @@ struct umr_ip_block *umr_create_gfx90(struct umr_ip_offsets_soc15 *soc15_offsets
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 1) ? grant : deny;
 
 	if (umr_transfer_soc15_to_reg(options, soc15_offsets, "GC", gfx90_registers, ip)) {
 		free(ip);
diff --git a/src/lib/ip/gfx91.c b/src/lib/ip/gfx91.c
index 14ca0fd3a634..a647a713eadc 100644
--- a/src/lib/ip/gfx91.c
+++ b/src/lib/ip/gfx91.c
@@ -30,18 +30,6 @@ static const struct umr_reg_soc15 gfx91_registers[] = {
 #include "gfx91_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_gfx91(struct umr_ip_offsets_soc15 *soc15_offsets, struct umr_options *options)
 {
 	struct umr_ip_block *ip;
@@ -57,7 +45,6 @@ struct umr_ip_block *umr_create_gfx91(struct umr_ip_offsets_soc15 *soc15_offsets
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 1) ? grant : deny;
 
 	if (umr_transfer_soc15_to_reg(options, soc15_offsets, "GC", gfx91_registers, ip)) {
 		free(ip);
diff --git a/src/lib/ip/mmhub10.c b/src/lib/ip/mmhub10.c
index 48589c7d0838..edb49a43a854 100644
--- a/src/lib/ip/mmhub10.c
+++ b/src/lib/ip/mmhub10.c
@@ -30,18 +30,6 @@ static const struct umr_reg_soc15 mmhub10_registers[] = {
 #include "mmhub10_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_mmhub10(struct umr_ip_offsets_soc15 *soc15_offsets, struct umr_options *options)
 {
 	struct umr_ip_block *ip;
@@ -57,7 +45,6 @@ struct umr_ip_block *umr_create_mmhub10(struct umr_ip_offsets_soc15 *soc15_offse
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 1) ? grant : deny;
 
 	if (umr_transfer_soc15_to_reg(options, soc15_offsets, "MMHUB", mmhub10_registers, ip)) {
 		free(ip);
diff --git a/src/lib/ip/mmhub91.c b/src/lib/ip/mmhub91.c
index 5274a4f84024..d3b6b17ce1f8 100644
--- a/src/lib/ip/mmhub91.c
+++ b/src/lib/ip/mmhub91.c
@@ -30,18 +30,6 @@ static const struct umr_reg_soc15 mmhub91_registers[] = {
 #include "mmhub91_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_mmhub91(struct umr_ip_offsets_soc15 *soc15_offsets, struct umr_options *options)
 {
 	struct umr_ip_block *ip;
@@ -57,7 +45,6 @@ struct umr_ip_block *umr_create_mmhub91(struct umr_ip_offsets_soc15 *soc15_offse
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 1) ? grant : deny;
 
 	if (umr_transfer_soc15_to_reg(options, soc15_offsets, "MMHUB", mmhub91_registers, ip)) {
 		free(ip);
diff --git a/src/lib/ip/mp100.c b/src/lib/ip/mp100.c
index 575511acc14f..f313ac7fbca1 100644
--- a/src/lib/ip/mp100.c
+++ b/src/lib/ip/mp100.c
@@ -30,18 +30,6 @@ static const struct umr_reg_soc15 mp100_registers[] = {
 #include "mp100_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_mp100(struct umr_ip_offsets_soc15 *soc15_offsets, struct umr_options *options)
 {
 	struct umr_ip_block *ip;
@@ -57,7 +45,6 @@ struct umr_ip_block *umr_create_mp100(struct umr_ip_offsets_soc15 *soc15_offsets
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 1) ? grant : deny;
 
 	if (umr_transfer_soc15_to_reg(options, soc15_offsets, "MP0", mp100_registers, ip)) { // this might be broken because there is MP1/2 as well
 		free(ip);
diff --git a/src/lib/ip/mp90.c b/src/lib/ip/mp90.c
index 787f296f16ec..29b37069b461 100644
--- a/src/lib/ip/mp90.c
+++ b/src/lib/ip/mp90.c
@@ -30,18 +30,6 @@ static const struct umr_reg_soc15 mp90_registers[] = {
 #include "mp90_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_mp90(struct umr_ip_offsets_soc15 *soc15_offsets, struct umr_options *options)
 {
 	struct umr_ip_block *ip;
@@ -57,7 +45,6 @@ struct umr_ip_block *umr_create_mp90(struct umr_ip_offsets_soc15 *soc15_offsets,
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 1) ? grant : deny;
 
 	if (umr_transfer_soc15_to_reg(options, soc15_offsets, "MP0", mp90_registers, ip)) { // this might be broken because there is MP1/2 as well
 		free(ip);
diff --git a/src/lib/ip/oss10.c b/src/lib/ip/oss10.c
index 7d820da64de2..6105620e04b1 100644
--- a/src/lib/ip/oss10.c
+++ b/src/lib/ip/oss10.c
@@ -30,22 +30,12 @@ static const struct umr_reg oss10_registers[] = {
 #include "oss10_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_oss10(struct umr_options *options)
 {
 	struct umr_ip_block *ip;
 
+	(void)options;
+
 	ip = calloc(1, sizeof *ip);
 	if (!ip)
 		return NULL;
@@ -57,7 +47,6 @@ struct umr_ip_block *umr_create_oss10(struct umr_options *options)
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 2) ? grant : deny;
 	memcpy(ip->regs, oss10_registers, sizeof(oss10_registers));
 	return ip;
 }
diff --git a/src/lib/ip/oss20.c b/src/lib/ip/oss20.c
index 26da1cd1fbc4..c50f188f4622 100644
--- a/src/lib/ip/oss20.c
+++ b/src/lib/ip/oss20.c
@@ -30,22 +30,12 @@ static const struct umr_reg oss20_registers[] = {
 #include "oss20_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_oss20(struct umr_options *options)
 {
 	struct umr_ip_block *ip;
 
+	(void)options;
+
 	ip = calloc(1, sizeof *ip);
 	if (!ip)
 		return NULL;
@@ -57,7 +47,6 @@ struct umr_ip_block *umr_create_oss20(struct umr_options *options)
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 2) ? grant : deny;
 	memcpy(ip->regs, oss20_registers, sizeof(oss20_registers));
 	return ip;
 }
diff --git a/src/lib/ip/oss30.c b/src/lib/ip/oss30.c
index a44421af7e43..9cd423f53a3f 100644
--- a/src/lib/ip/oss30.c
+++ b/src/lib/ip/oss30.c
@@ -30,22 +30,12 @@ static const struct umr_reg oss30_registers[] = {
 #include "oss30_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_oss30(struct umr_options *options)
 {
 	struct umr_ip_block *ip;
 
+	(void)options;
+
 	ip = calloc(1, sizeof *ip);
 	if (!ip)
 		return NULL;
@@ -57,7 +47,6 @@ struct umr_ip_block *umr_create_oss30(struct umr_options *options)
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 2) ? grant : deny;
 	memcpy(ip->regs, oss30_registers, sizeof(oss30_registers));
 	return ip;
 }
diff --git a/src/lib/ip/smu60.c b/src/lib/ip/smu60.c
index 545d1bafd268..d55c9a8db379 100644
--- a/src/lib/ip/smu60.c
+++ b/src/lib/ip/smu60.c
@@ -30,22 +30,12 @@ static const struct umr_reg smu60_registers[] = {
 #include "smu60_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_smu60(struct umr_options *options)
 {
 	struct umr_ip_block *ip;
 
+	(void)options;
+
 	ip = calloc(1, sizeof *ip);
 	if (!ip)
 		return NULL;
@@ -57,7 +47,6 @@ struct umr_ip_block *umr_create_smu60(struct umr_options *options)
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 2) ? grant : deny;
 	memcpy(ip->regs, smu60_registers, sizeof(smu60_registers));
 	return ip;
 }
diff --git a/src/lib/ip/smu700.c b/src/lib/ip/smu700.c
index 86d242609d17..9d06f7cf804e 100644
--- a/src/lib/ip/smu700.c
+++ b/src/lib/ip/smu700.c
@@ -30,22 +30,12 @@ static const struct umr_reg smu700_registers[] = {
 #include "smu700_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_smu700(struct umr_options *options)
 {
 	struct umr_ip_block *ip;
 
+	(void)options;
+
 	ip = calloc(1, sizeof *ip);
 	if (!ip)
 		return NULL;
@@ -57,7 +47,6 @@ struct umr_ip_block *umr_create_smu700(struct umr_options *options)
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 2) ? grant : deny;
 	memcpy(ip->regs, smu700_registers, sizeof(smu700_registers));
 	return ip;
 }
diff --git a/src/lib/ip/smu701.c b/src/lib/ip/smu701.c
index 06c811e50eaf..c6eb5bbb06de 100644
--- a/src/lib/ip/smu701.c
+++ b/src/lib/ip/smu701.c
@@ -30,22 +30,12 @@ static const struct umr_reg smu701_registers[] = {
 #include "smu701_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_smu701(struct umr_options *options)
 {
 	struct umr_ip_block *ip;
 
+	(void)options;
+
 	ip = calloc(1, sizeof *ip);
 	if (!ip)
 		return NULL;
@@ -57,7 +47,6 @@ struct umr_ip_block *umr_create_smu701(struct umr_options *options)
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 2) ? grant : deny;
 	memcpy(ip->regs, smu701_registers, sizeof(smu701_registers));
 	return ip;
 }
diff --git a/src/lib/ip/smu710.c b/src/lib/ip/smu710.c
index 6d68464e78d0..b34aa6fe9a20 100644
--- a/src/lib/ip/smu710.c
+++ b/src/lib/ip/smu710.c
@@ -30,22 +30,12 @@ static const struct umr_reg smu710_registers[] = {
 #include "smu710_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_smu710(struct umr_options *options)
 {
 	struct umr_ip_block *ip;
 
+	(void)options;
+
 	ip = calloc(1, sizeof *ip);
 	if (!ip)
 		return NULL;
@@ -57,7 +47,6 @@ struct umr_ip_block *umr_create_smu710(struct umr_options *options)
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 2) ? grant : deny;
 	memcpy(ip->regs, smu710_registers, sizeof(smu710_registers));
 	return ip;
 }
diff --git a/src/lib/ip/smu711.c b/src/lib/ip/smu711.c
index 00a9f2bd0214..4594dacb5493 100644
--- a/src/lib/ip/smu711.c
+++ b/src/lib/ip/smu711.c
@@ -30,22 +30,12 @@ static const struct umr_reg smu711_registers[] = {
 #include "smu711_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_smu711(struct umr_options *options)
 {
 	struct umr_ip_block *ip;
 
+	(void)options;
+
 	ip = calloc(1, sizeof *ip);
 	if (!ip)
 		return NULL;
@@ -57,7 +47,6 @@ struct umr_ip_block *umr_create_smu711(struct umr_options *options)
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 2) ? grant : deny;
 	memcpy(ip->regs, smu711_registers, sizeof(smu711_registers));
 	return ip;
 }
diff --git a/src/lib/ip/smu712.c b/src/lib/ip/smu712.c
index 45b1b1e71eaf..a57929b17d55 100644
--- a/src/lib/ip/smu712.c
+++ b/src/lib/ip/smu712.c
@@ -30,22 +30,12 @@ static const struct umr_reg smu712_registers[] = {
 #include "smu712_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_smu712(struct umr_options *options)
 {
 	struct umr_ip_block *ip;
 
+	(void)options;
+
 	ip = calloc(1, sizeof *ip);
 	if (!ip)
 		return NULL;
@@ -57,7 +47,6 @@ struct umr_ip_block *umr_create_smu712(struct umr_options *options)
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 2) ? grant : deny;
 	memcpy(ip->regs, smu712_registers, sizeof(smu712_registers));
 	return ip;
 }
diff --git a/src/lib/ip/smu713.c b/src/lib/ip/smu713.c
index c1e0ff8f3547..376e796d5c92 100644
--- a/src/lib/ip/smu713.c
+++ b/src/lib/ip/smu713.c
@@ -30,22 +30,12 @@ static const struct umr_reg smu713_registers[] = {
 #include "smu713_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_smu713(struct umr_options *options)
 {
 	struct umr_ip_block *ip;
 
+	(void)options;
+
 	ip = calloc(1, sizeof *ip);
 	if (!ip)
 		return NULL;
@@ -57,7 +47,6 @@ struct umr_ip_block *umr_create_smu713(struct umr_options *options)
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 2) ? grant : deny;
 	memcpy(ip->regs, smu713_registers, sizeof(smu713_registers));
 	return ip;
 }
diff --git a/src/lib/ip/smu80.c b/src/lib/ip/smu80.c
index d1cd966fecd5..da0abe888677 100644
--- a/src/lib/ip/smu80.c
+++ b/src/lib/ip/smu80.c
@@ -30,22 +30,12 @@ static const struct umr_reg smu80_registers[] = {
 #include "smu80_regs.i"
 };
 
-static int grant(struct umr_asic *asic)
-{
-	(void)asic;
-	return 0;
-}
-
-static int deny(struct umr_asic *asic)
-{
-	(void)asic;
-	return -1;
-}
-
 struct umr_ip_block *umr_create_smu80(struct umr_options *options)
 {
 	struct umr_ip_block *ip;
 
+	(void)options;
+
 	ip = calloc(1, sizeof *ip);
 	if (!ip)
 		return NULL;
@@ -57,7 +47,6 @@ struct umr_ip_block *umr_create_smu80(struct umr_options *options)
 		free(ip);
 		return NULL;
 	}
-	ip->grant = (options->risky >= 2) ? grant : deny;
 	memcpy(ip->regs, smu80_registers, sizeof(smu80_registers));
 	return ip;
 }
diff --git a/src/umr.h b/src/umr.h
index 51690400f583..a0e94a7e4db9 100644
--- a/src/umr.h
+++ b/src/umr.h
@@ -162,7 +162,6 @@ struct umr_options {
 	    instance,
 	    need_scan,
 	    print,
-	    risky,
 	    bitfields,
 	    bitfields_full,
 	    named,
-- 
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] 5+ messages in thread

* [PATCH umr 2/4] Add ability to specify VMID in hex
       [not found] ` <20170725172324.28365-1-tom.stdenis-5C7GfCeVMHo@public.gmane.org>
  2017-07-25 17:23   ` [PATCH umr 1/4] Remove 'risky' option --print command. (v2) Tom St Denis
@ 2017-07-25 17:23   ` Tom St Denis
  2017-07-25 17:23   ` [PATCH umr 3/4] Various cleanups found by static analysis. (v2) Tom St Denis
  2017-07-25 17:23   ` [PATCH umr 4/4] Add ability to halt waves and better VM decoding (v3) Tom St Denis
  3 siblings, 0 replies; 5+ messages in thread
From: Tom St Denis @ 2017-07-25 17:23 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW; +Cc: Tom St Denis

Signed-off-by: Tom St Denis <tom.stdenis@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
---
 doc/umr.1      |  5 +++--
 src/app/main.c | 11 +++++++----
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/doc/umr.1 b/doc/umr.1
index 9384c2430bda..0a991f9923a4 100644
--- a/doc/umr.1
+++ b/doc/umr.1
@@ -89,8 +89,9 @@ will operate regardless of whether GFX PG is enabled or not.  Can use
 to decode the wave bitfields.
 .IP "--vram, -v [vmid@]<address> <size>"
 Read 'size' bytes (in hex) from the address specified (in hexadecimal) from VRAM
-to stdout.  Optionally specify the VMID (in decimal) treating the address as a
-virtual address instead.  Can use 'use_pci' to directly access 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 "--update, -u" <filename>
 Specify update file to add, change, or delete registers from the register
diff --git a/src/app/main.c b/src/app/main.c
index d8278a93e1cc..6e0bc57200b0 100644
--- a/src/app/main.c
+++ b/src/app/main.c
@@ -346,10 +346,13 @@ int main(int argc, char **argv)
 				if (!asic)
 					asic = get_asic();
 
-				if ((n = sscanf(argv[i+1], "%"SCNu32"@%"SCNx64, &vmid, &address)) != 2) {
-					sscanf(argv[i+1], "%"SCNx64, &address);
-					vmid = 0xFFFF;
-				}
+				// 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;
+					}
 				sscanf(argv[i+2], "%"SCNx32, &size);
 				while (size) {
 					n = size > sizeof(buf) ? sizeof(buf) : size;
-- 
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] 5+ messages in thread

* [PATCH umr 3/4] Various cleanups found by static analysis. (v2)
       [not found] ` <20170725172324.28365-1-tom.stdenis-5C7GfCeVMHo@public.gmane.org>
  2017-07-25 17:23   ` [PATCH umr 1/4] Remove 'risky' option --print command. (v2) Tom St Denis
  2017-07-25 17:23   ` [PATCH umr 2/4] Add ability to specify VMID in hex Tom St Denis
@ 2017-07-25 17:23   ` Tom St Denis
  2017-07-25 17:23   ` [PATCH umr 4/4] Add ability to halt waves and better VM decoding (v3) Tom St Denis
  3 siblings, 0 replies; 5+ messages in thread
From: Tom St Denis @ 2017-07-25 17:23 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW; +Cc: Tom St Denis

Signed-off-by: Tom St Denis <tom.stdenis@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>

(v2): Updated enumerate to not stop on other AMD PCI devices
---
 src/app/enum.c               | 4 +---
 src/lib/create_asic_helper.c | 5 +++++
 src/lib/discover.c           | 9 +++++++--
 src/lib/mmio.c               | 8 ++++++++
 4 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/src/app/enum.c b/src/app/enum.c
index 2c4b7695e3cb..1c56fe643616 100644
--- a/src/app/enum.c
+++ b/src/app/enum.c
@@ -55,7 +55,6 @@ void umr_enumerate_devices(void)
 		return;
 	}
 	do {
-		x = 0;
 		do {
 			pdevice = pci_device_next(pci_iter);
 		} while (pdevice && pdevice->vendor_id != 0x1002);
@@ -64,12 +63,11 @@ void umr_enumerate_devices(void)
 			asics[devices].instance = -1;
 			asics[devices].asic->pci.pdevice = &asics[devices].pcopy;
 			asics[devices++].pcopy = *pdevice;
-			x = 1;
 		}
 	} while (pdevice && devices < MAX_DEV);
 
 	// now try to match devices against instances
-	for (y = 0; y < MAX_DEV; y++) {
+	for (y = 0; y < devices; y++) {
 		snprintf(path, sizeof(path)-1, "/sys/kernel/debug/dri/%d/name", y);
 		dri = fopen(path, "r");
 		if (dri) {
diff --git a/src/lib/create_asic_helper.c b/src/lib/create_asic_helper.c
index d0ee34ac951e..ffca35d7af93 100644
--- a/src/lib/create_asic_helper.c
+++ b/src/lib/create_asic_helper.c
@@ -48,6 +48,11 @@ struct umr_asic *umr_create_asic_helper(char *name, int family, ...)
 	}
 	va_end(ap);
 
+	if (!asic->no_blocks) {
+		free(asic);
+		return NULL;
+	}
+
 	asic->blocks = calloc(asic->no_blocks, sizeof(struct umr_ip_block *));
 	if (!asic->blocks) {
 		free(asic);
diff --git a/src/lib/discover.c b/src/lib/discover.c
index 0c4ee1c09ad8..0fc053712e37 100644
--- a/src/lib/discover.c
+++ b/src/lib/discover.c
@@ -269,20 +269,25 @@ struct umr_asic *umr_discover_asic(struct umr_options *options)
 				goto err_pci;
 			}
 			pci_iterator_destroy(pci_iter);
+
+			// enable device if kernel module isn't present
+			if (asic->options.no_kernel)
+				pci_device_enable(asic->pci.pdevice);
+
 			pci_device_probe(asic->pci.pdevice);
 
 			use_region = 6;
 			// try to detect based on ASIC family
 			if (asic->family <= FAMILY_SI) {
 				// try region 2 for SI
-				if (	asic->pci.pdevice->regions[2].is_64 == 0 &&
+				if (asic->pci.pdevice->regions[2].is_64 == 0 &&
 					asic->pci.pdevice->regions[2].is_prefetchable == 0 &&
 					asic->pci.pdevice->regions[2].is_IO == 0) {
 						use_region = 2;
 				}
 			} else if (asic->family <= FAMILY_VI) {
 				// try region 5 for CIK..VI
-				if (	asic->pci.pdevice->regions[5].is_64 == 0 &&
+				if (asic->pci.pdevice->regions[5].is_64 == 0 &&
 					asic->pci.pdevice->regions[5].is_prefetchable == 0 &&
 					asic->pci.pdevice->regions[5].is_IO == 0) {
 						use_region = 5;
diff --git a/src/lib/mmio.c b/src/lib/mmio.c
index 987704cb9944..47e5150d3201 100644
--- a/src/lib/mmio.c
+++ b/src/lib/mmio.c
@@ -88,6 +88,10 @@ uint32_t umr_read_reg(struct umr_asic *asic, uint64_t addr, enum regclass type)
 	if (addr == 0xFFFFFFFF)
 		fprintf(stderr, "[BUG]: reading from addr==0xFFFFFFFF is likely a bug\n");
 
+	// lop off top bits in no-kernel mode
+	if (asic->options.no_kernel)
+		addr &= 0xFFFFFF;
+
 	switch (type) {
 		case REG_MMIO:
 			if (asic->pci.mem && !(addr & ~0xFFFFFULL)) { // only use pci if enabled and not using high bits 
@@ -113,6 +117,10 @@ int umr_write_reg(struct umr_asic *asic, uint64_t addr, uint32_t value, enum reg
 	if (addr == 0xFFFFFFFF)
 		fprintf(stderr, "[BUG]: reading from addr==0xFFFFFFFF is likely a bug\n");
 
+	// lop off top bits in no-kernel mode
+	if (asic->options.no_kernel)
+		addr &= 0xFFFFFF;
+
 	switch (type) {
 		case REG_MMIO:
 			if (asic->pci.mem && !(addr & ~0xFFFFFULL)) {
-- 
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] 5+ messages in thread

* [PATCH umr 4/4] Add ability to halt waves and better VM decoding (v3)
       [not found] ` <20170725172324.28365-1-tom.stdenis-5C7GfCeVMHo@public.gmane.org>
                     ` (2 preceding siblings ...)
  2017-07-25 17:23   ` [PATCH umr 3/4] Various cleanups found by static analysis. (v2) Tom St Denis
@ 2017-07-25 17:23   ` Tom St Denis
  3 siblings, 0 replies; 5+ messages in thread
From: Tom St Denis @ 2017-07-25 17:23 UTC (permalink / raw)
  To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW; +Cc: Tom St Denis

This patch involves two things I was working on at once so the
patches are a bit intertwined.  It adds

1.  The ability to halt SQ waves when reading waves on CIK and later
ASICs.

2.  The ability to enable verbose decoding when reading vram

3.  The ability to decode virtual addresses in the mmhub (for say VCN)

Signed-off-by: Tom St Denis <tom.stdenis@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>

(v2): Tidy up AI verbose VM decoding output
(v3): More details in verbose output and removed some duplicate DEBUG output
---
 doc/umr.1                   |  13 +++
 src/app/main.c              |  56 ++++++++-
 src/app/print_waves.c       |   6 +
 src/lib/CMakeLists.txt      |   1 +
 src/lib/dump_ib.c           |   6 +-
 src/lib/find_reg.c          |  11 +-
 src/lib/mmio.c              |  36 ++++--
 src/lib/read_vram.c         | 270 +++++++++++++++++++++++++++++++++-----------
 src/lib/ring_decode.c       |   4 +-
 src/lib/sq_cmd_halt_waves.c |  57 ++++++++++
 src/umr.h                   |  26 +++++
 11 files changed, 403 insertions(+), 83 deletions(-)
 create mode 100644 src/lib/sq_cmd_halt_waves.c

diff --git a/doc/umr.1 b/doc/umr.1
index 0a991f9923a4..06950925b7b6 100644
--- a/doc/umr.1
+++ b/doc/umr.1
@@ -87,6 +87,13 @@ invoking it very rapidly.  Unlike the wave count reading in --top this command
 will operate regardless of whether GFX PG is enabled or not.  Can use
 .B bits
 to decode the wave bitfields.
+
+.IP "--vm-decode, -vm vmid@<address> <num_of_pages>"
+Decode page mappings at a specified address (in hex) from the VMID specified.
+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>"
 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)
@@ -145,6 +152,12 @@ separated strings.  Options should be specified before --update or --force comma
      be used only if the KMD is hung or otherwise not working correctly.  Using it on live systems
      may result in race conditions.
 
+.B verbose
+     Enable verbose diagnostics (used in --vram).
+
+.B halt_waves
+     Halt/resume all waves while reading wave status.
+
 .SH "Notes"
 
 - The "Waves" field in the DRM section of --top only works if GFX PG has been disabled.  Otherwise,
diff --git a/src/app/main.c b/src/app/main.c
index 6e0bc57200b0..0b46643400ba 100644
--- a/src/app/main.c
+++ b/src/app/main.c
@@ -107,6 +107,10 @@ static void parse_options(char *str)
 			options.quiet = 1;
 		} else if (!strcmp(option, "follow_ib")) {
 			options.follow_ib = 1;
+		} else if (!strcmp(option, "verbose")) {
+			options.verbose = 1;
+		} else if (!strcmp(option, "halt_waves")) {
+			options.halt_waves = 1;
 		} else if (!strcmp(option, "no_kernel")) {
 			options.no_kernel = 1;
 			options.use_pci = 1;
@@ -337,6 +341,38 @@ int main(int argc, char **argv)
 		} else if (!strcmp(argv[i], "--enumerate") || !strcmp(argv[i], "-e")) {
 			umr_enumerate_devices();
 			return 0;
+		} else if (!strcmp(argv[i], "--vm-decode") || !strcmp(argv[i], "-vm")) {
+			if (i + 2 < argc) {
+				uint64_t address;
+				uint32_t size, n, vmid;
+				int overbose;
+
+				if (!asic)
+					asic = get_asic();
+
+				overbose = asic->options.verbose;
+				asic->options.verbose = 1;
+
+				// 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) {
+						fprintf(stderr, "[ERROR]: Must specify a VMID for the --vm-decode command\n");
+						exit(EXIT_FAILURE);
+					}
+				sscanf(argv[i+2], "%"SCNx32, &size);
+				while (size--) {
+					if (umr_read_vram(asic, vmid, address, 0, NULL))
+						break;
+					address += 0x1000;
+				}
+				i += 2;
+
+				asic->options.verbose = overbose;
+			} else {
+				printf("--vm-decode requires two parameters\n");
+				return EXIT_FAILURE;
+			}
 		} else if (!strcmp(argv[i], "--vram") || !strcmp(argv[i], "-v")) {
 			if (i + 2 < argc) {
 				unsigned char buf[256];
@@ -354,13 +390,13 @@ int main(int argc, char **argv)
 						vmid = UMR_LINEAR_HUB;
 					}
 				sscanf(argv[i+2], "%"SCNx32, &size);
-				while (size) {
+				do {
 					n = size > sizeof(buf) ? sizeof(buf) : size;
 					umr_read_vram(asic, vmid, address, n, buf);
 					fwrite(buf, 1, n, stdout);
 					size -= n;
 					address += n;
-				}
+				} while (size);
 				i += 2;
 			} else {
 				printf("--vram requires two parameters\n");
@@ -422,12 +458,20 @@ int main(int argc, char **argv)
 "\n\t--top, -t\n\t\tSummarize GPU utilization.  Can select a SE block with --bank.  Can use"
 	"\n\t\toptions 'use_colour' to colourize output and 'use_pci' to improve efficiency.\n"
 "\n\t--waves, -wa\n\t\tPrint out information about any active CU waves.  Can use '-O bits'"
-	"\n\t\tto see decoding of various wave fields.\n"
+	"\n\t\tto see decoding of various wave fields.  Can use the '-O halt_waves' option"
+	"\n\t\tto halt the SQ while reading registers.\n"
+"\n\t--vm-decode, -vm vmid@<address> <num_of_pages>"
+	"\n\t\tDecode page mappings at a specified address (in hex) from the VMID specified."
+	"\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\tRead 'size' bytes (in hex) from a given address (in hex) to stdout. Optionally"
-	"\n\t\tspecify the VMID (in decimal) treating the address as a virtual address instead.\n"
-"\n\t--option -O <string>[,<string>,...]\n\t\tEnable various flags: risky, bits, bitsfull, empty_log, follow, named, many,"
-	"\n\t\tuse_pci, use_colour, read_smc, quiet, no_kernel.\n"
+	"\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--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);
 			exit(EXIT_SUCCESS);
 		} else {
diff --git a/src/app/print_waves.c b/src/app/print_waves.c
index e157db9f9386..1efd8a13bd28 100644
--- a/src/app/print_waves.c
+++ b/src/app/print_waves.c
@@ -40,6 +40,9 @@ void umr_print_waves(struct umr_asic *asic)
 	struct umr_wave_status ws;
 	int first = 1, col = 0;
 
+	if (asic->options.halt_waves)
+		umr_sq_cmd_halt_waves(asic, UMR_SQ_CMD_HALT);
+
 	if (asic->family <= FAMILY_CIK)
 		shift = 3;  // on SI..CIK allocations were done in 8-dword blocks
 	else
@@ -206,4 +209,7 @@ void umr_print_waves(struct umr_asic *asic)
 	}
 	if (first)
 		printf("No active waves!\n");
+
+	if (asic->options.halt_waves)
+		umr_sq_cmd_halt_waves(asic, UMR_SQ_CMD_RESUME);
 }
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index 217ae80cdfd7..fcb4f9c9dc80 100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -21,6 +21,7 @@ add_library(umrcore STATIC
   read_vram.c
   ring_decode.c
   scan_config.c
+  sq_cmd_halt_waves.c
   transfer_soc15.c
   wave_status.c
   update.c
diff --git a/src/lib/dump_ib.c b/src/lib/dump_ib.c
index 4e81dbe3eb09..cba497373fe2 100644
--- a/src/lib/dump_ib.c
+++ b/src/lib/dump_ib.c
@@ -28,9 +28,11 @@
 void umr_dump_ib(struct umr_asic *asic, struct umr_ring_decoder *decoder)
 {
 	uint32_t *data = NULL, x;
+	static const char *hubs[] = { "gfxhub", "mmhub" };
 
-	printf("Dumping IB at VMID:%u 0x%llx of %u words\n",
-		(unsigned)decoder->next_ib_info.vmid,
+	printf("Dumping IB at (%s) VMID:%u 0x%llx of %u words\n",
+		hubs[decoder->next_ib_info.vmid >> 8],
+		(unsigned)decoder->next_ib_info.vmid & 0xFF,
 		(unsigned long long)decoder->next_ib_info.ib_addr,
 		(unsigned)decoder->next_ib_info.size/4);
 
diff --git a/src/lib/find_reg.c b/src/lib/find_reg.c
index d4647163ea63..ecd7f132c9c9 100644
--- a/src/lib/find_reg.c
+++ b/src/lib/find_reg.c
@@ -36,14 +36,21 @@ uint32_t umr_find_reg(struct umr_asic *asic, char *regname)
 	return 0xFFFFFFFF;
 }
 
-struct umr_reg *umr_find_reg_data(struct umr_asic *asic, char *regname)
+struct umr_reg *umr_find_reg_data_by_ip(struct umr_asic *asic, char *ip, char *regname)
 {
 	int i, j;
 
-	for (i = 0; i < asic->no_blocks; i++)
+	for (i = 0; i < asic->no_blocks; i++) {
+		if (ip && memcmp(asic->blocks[i]->ipname, ip, strlen(ip))) continue;
 		for (j = 0; j < asic->blocks[i]->no_regs; j++)
 			if (!strcmp(asic->blocks[i]->regs[j].regname, regname))
 				return &asic->blocks[i]->regs[j];
+	}
 	fprintf(stderr, "[BUG]: reg [%s] not found on asic [%s]\n", regname, asic->asicname);
 	return NULL;
 }
+
+struct umr_reg *umr_find_reg_data(struct umr_asic *asic, char *regname)
+{
+	return umr_find_reg_data_by_ip(asic, NULL, regname);
+}
diff --git a/src/lib/mmio.c b/src/lib/mmio.c
index 47e5150d3201..eb91e289404f 100644
--- a/src/lib/mmio.c
+++ b/src/lib/mmio.c
@@ -145,26 +145,36 @@ int umr_write_reg(struct umr_asic *asic, uint64_t addr, uint32_t value, enum reg
 	return 0;
 }
 
-uint32_t umr_read_reg_by_name(struct umr_asic *asic, char *name)
+uint32_t umr_read_reg_by_name_by_ip(struct umr_asic *asic, char *ip, char *name)
 {
 	struct umr_reg *reg;
-	reg = umr_find_reg_data(asic, name);
+	reg = umr_find_reg_data_by_ip(asic, ip, name);
 	if (reg)
 		return umr_read_reg(asic, reg->addr * (reg->type == REG_MMIO ? 4 : 1), reg->type);
 	else
 		return 0;
 }
 
-int umr_write_reg_by_name(struct umr_asic *asic, char *name, uint32_t value)
+uint32_t umr_read_reg_by_name(struct umr_asic *asic, char *name)
+{
+	return umr_read_reg_by_name_by_ip(asic, NULL, name);
+}
+
+int umr_write_reg_by_name_by_ip(struct umr_asic *asic, char *ip, char *name, uint32_t value)
 {
 	struct umr_reg *reg;
-	reg = umr_find_reg_data(asic, name);
+	reg = umr_find_reg_data_by_ip(asic, ip, name);
 	if (reg)
 		return umr_write_reg(asic, reg->addr * (reg->type == REG_MMIO ? 4 : 1), value, reg->type);
 	else
 		return -1;
 }
 
+int umr_write_reg_by_name(struct umr_asic *asic, char *name, uint32_t value)
+{
+	return umr_write_reg_by_name_by_ip(asic, NULL, name, value);
+}
+
 uint32_t umr_bitslice_reg(struct umr_asic *asic, struct umr_reg *reg, char *bitname, uint32_t regvalue)
 {
 	int i;
@@ -193,26 +203,36 @@ uint32_t umr_bitslice_compose_value(struct umr_asic *asic, struct umr_reg *reg,
 	return 0;
 }
 
-uint32_t umr_bitslice_reg_by_name(struct umr_asic *asic, char *regname, char *bitname, uint32_t regvalue)
+uint32_t umr_bitslice_reg_by_name_by_ip(struct umr_asic *asic, char *ip, char *regname, char *bitname, uint32_t regvalue)
 {
 	struct umr_reg *reg;
-	reg = umr_find_reg_data(asic, regname);
+	reg = umr_find_reg_data_by_ip(asic, ip, regname);
 	if (reg)
 		return umr_bitslice_reg(asic, reg, bitname, regvalue);
 	else
 		return 0;
 }
 
-uint32_t umr_bitslice_compose_value_by_name(struct umr_asic *asic, char *regname, char *bitname, uint32_t regvalue)
+uint32_t umr_bitslice_reg_by_name(struct umr_asic *asic, char *regname, char *bitname, uint32_t regvalue)
+{
+	return umr_bitslice_reg_by_name_by_ip(asic, NULL, regname, bitname, regvalue);
+}
+
+uint32_t umr_bitslice_compose_value_by_name_by_ip(struct umr_asic *asic, char *ip, char *regname, char *bitname, uint32_t regvalue)
 {
 	struct umr_reg *reg;
-	reg = umr_find_reg_data(asic, regname);
+	reg = umr_find_reg_data_by_ip(asic, ip, regname);
 	if (reg)
 		return umr_bitslice_compose_value(asic, reg, bitname, regvalue);
 	else
 		return 0;
 }
 
+uint32_t umr_bitslice_compose_value_by_name(struct umr_asic *asic, char *regname, char *bitname, uint32_t regvalue)
+{
+	return umr_bitslice_compose_value_by_name_by_ip(asic, NULL, regname, bitname, regvalue);
+}
+
 int umr_grbm_select_index(struct umr_asic *asic, uint32_t se, uint32_t sh, uint32_t instance)
 {
 	struct umr_reg *grbm_idx;
diff --git a/src/lib/read_vram.c b/src/lib/read_vram.c
index 3d458db8fa11..b58400f1f4ca 100644
--- a/src/lib/read_vram.c
+++ b/src/lib/read_vram.c
@@ -83,7 +83,7 @@ static int umr_read_vram_vi(struct umr_asic *asic, uint32_t vmid, uint64_t addre
 {
 	uint64_t start_addr, page_table_start_addr, page_table_base_addr,
 		 page_table_size, pte_idx, pde_idx, pte_entry, pde_entry,
-		 vm_fb_base;
+		 vm_fb_base, pde_mask, pte_mask;
 	uint32_t chunk_size, tmp;
 	int page_table_depth;
 	struct {
@@ -99,9 +99,18 @@ static int umr_read_vram_vi(struct umr_asic *asic, uint32_t vmid, uint64_t addre
 			system,
 			valid;
 	} pte_fields;
+	struct {
+		uint32_t
+			mmVM_CONTEXTx_PAGE_TABLE_START_ADDR,
+			mmVM_CONTEXTx_CNTL,
+			mmVM_CONTEXTx_PAGE_TABLE_BASE_ADDR,
+			mmMC_VM_FB_LOCATION;
+	} registers;
 	char buf[64];
 	unsigned char *pdst = dst;
 
+	memset(&registers, 0, sizeof registers);
+
 	/*
 	 * PTE format on VI:
 	 * 63:40 reserved
@@ -125,44 +134,70 @@ static int umr_read_vram_vi(struct umr_asic *asic, uint32_t vmid, uint64_t addre
 
 	// read vm registers
 	sprintf(buf, "mmVM_CONTEXT%d_PAGE_TABLE_START_ADDR", (int)vmid ? 1 : 0);
-		page_table_start_addr = (uint64_t)umr_read_reg_by_name(asic, buf) << 12;
+		registers.mmVM_CONTEXTx_PAGE_TABLE_START_ADDR = umr_read_reg_by_name(asic, buf);
+		page_table_start_addr = (uint64_t)registers.mmVM_CONTEXTx_PAGE_TABLE_START_ADDR << 12;
 
 	sprintf(buf, "mmVM_CONTEXT%d_CNTL", (int)vmid ? 1 : 0);
-		tmp = umr_read_reg_by_name(asic, buf);
+		tmp = registers.mmVM_CONTEXTx_CNTL = umr_read_reg_by_name(asic, buf);
 		page_table_depth      = umr_bitslice_reg_by_name(asic, buf, "PAGE_TABLE_DEPTH", tmp);
 		page_table_size       = umr_bitslice_reg_by_name(asic, buf, "PAGE_TABLE_BLOCK_SIZE", tmp);
 
 	sprintf(buf, "mmVM_CONTEXT%d_PAGE_TABLE_BASE_ADDR", (int)vmid);
-		page_table_base_addr  = (uint64_t)umr_read_reg_by_name(asic, buf) << 12;
-
-	vm_fb_base  = ((uint64_t)umr_read_reg_by_name(asic, "mmMC_VM_FB_LOCATION") >> 16) << 24;
-
-	DEBUG("mmVM_CONTEXTx_PAGE_TABLE_START_ADDR = %08llx\n", (unsigned long long)page_table_start_addr);
-	DEBUG("mmVM_CONTEXTx_PAGE_TABLE_BASE_ADDR = 0x%08llx\n", (unsigned long long)page_table_base_addr);
-	DEBUG("mmVM_CONTEXTx_CNTL.PAGE_TABLE_BLOCK_SIZE = %lu\n", page_table_size);
-	DEBUG("mmVM_CONTEXTx_CNTL.PAGE_TABLE_DEPTH = %d\n", page_table_depth);
-	DEBUG("mmMC_VM_FB_LOCATION == %llx\n", (unsigned long long)vm_fb_base);
+		registers.mmVM_CONTEXTx_PAGE_TABLE_BASE_ADDR = umr_read_reg_by_name(asic, buf);
+		page_table_base_addr  = (uint64_t)registers.mmVM_CONTEXTx_PAGE_TABLE_BASE_ADDR << 12;
+
+	registers.mmMC_VM_FB_LOCATION = umr_read_reg_by_name(asic, "mmMC_VM_FB_LOCATION");
+	vm_fb_base  = ((uint64_t)registers.mmMC_VM_FB_LOCATION & 0xFFFF) << 24;
+
+
+	if (asic->options.verbose)
+		fprintf(stderr,
+				"[VERBOSE]: mmVM_CONTEXT%d_PAGE_TABLE_START_ADDR=0x%llx\n"
+				"[VERBOSE]: mmVM_CONTEXT%d_PAGE_TABLE_BASE_ADDR=0x%llx\n"
+				"[VERBOSE]: mmVM_CONTEXT%d_CNTL=0x%llx\n"
+				"[VERBOSE]: mmMC_VM_FB_LOCATION=0x%llx\n",
+			(int)vmid ? 1 : 0,
+			(unsigned long long)registers.mmVM_CONTEXTx_PAGE_TABLE_START_ADDR,
+			(int)vmid ? 1 : 0,
+			(unsigned long long)registers.mmVM_CONTEXTx_PAGE_TABLE_BASE_ADDR,
+			(int)vmid ? 1 : 0,
+			(unsigned long long)registers.mmVM_CONTEXTx_CNTL,
+			(unsigned long long)registers.mmMC_VM_FB_LOCATION);
 
 	address -= page_table_start_addr;
 
-	while (size) {
+	do {
 		if (page_table_depth == 1) {
 			// decode addr into pte and pde selectors...
-			pde_idx = (address >> (12 + 9 + page_table_size)) & ((1ULL << (40 - 12 - 9 - page_table_size)) - 1);
-			pte_idx = (address >> 12) & ((1ULL << (9 + page_table_size)) - 1);
+			pde_mask = ((1ULL << (40 - 12 - 9 - page_table_size)) - 1);
+			pte_mask = ((1ULL << (9 + page_table_size)) - 1);
+
+			pde_idx = (address >> (12 + 9 + page_table_size)) & pde_mask;
+			pte_idx = (address >> 12) & pte_mask;
+
+			// shift masks so we can use them later
+			pte_mask <<= 12;
+			pde_mask <<= (12 + 9 + page_table_size);
 
 			// read PDE entry
-			umr_read_vram(asic, 0xFFFF, page_table_base_addr + pde_idx * 8, 8, &pde_entry);
+			umr_read_vram(asic, UMR_LINEAR_HUB, page_table_base_addr + pde_idx * 8 - vm_fb_base, 8, &pde_entry);
 
 			// decode PDE values
 			pde_fields.frag_size     = (pde_entry >> 59) & 0x1F;
 			pde_fields.pte_base_addr = pde_entry & 0xFFFFFFF000ULL;
 			pde_fields.valid         = pde_entry & 1;
-			DEBUG("PDE==%llx, pde_idx=%llx, frag_size=%u, pte_base_addr=0x%llx, valid=%d\n",
-				(unsigned long long)pde_entry, (unsigned long long)pde_idx, (unsigned)pde_fields.frag_size, (unsigned long long)pde_fields.pte_base_addr, (int)pde_fields.valid);
+			if (asic->options.verbose)
+				fprintf(stderr, "[VERBOSE]: PDE=0x%016llx, VA=0x%010llx, PBA==0x%010llx, V=%d\n",
+						(unsigned long long)pde_entry,
+						(unsigned long long)address & pde_mask,
+						(unsigned long long)pde_fields.pte_base_addr,
+						(int)pde_fields.valid);
+
+			if (!pde_fields.valid)
+				return -1;
 
 			// now read PTE entry for this page
-			if (umr_read_vram(asic, 0xFFFF, pde_fields.pte_base_addr + pte_idx*8, 8, &pte_entry) < 0)
+			if (umr_read_vram(asic, UMR_LINEAR_HUB, pde_fields.pte_base_addr + pte_idx*8 - vm_fb_base, 8, &pte_entry) < 0)
 				return -1;
 
 			// decode PTE values
@@ -170,8 +205,16 @@ static int umr_read_vram_vi(struct umr_asic *asic, uint32_t vmid, uint64_t addre
 			pte_fields.fragment       = (pte_entry >> 7)  & 0x1F;
 			pte_fields.system         = (pte_entry >> 1) & 1;
 			pte_fields.valid          = pte_entry & 1;
-			DEBUG("PTE=%llx, pte_idx=%llx, page_base_addr=0x%llx, fragment=%u, system=%d, valid=%d\n",
-				(unsigned long long)pte_entry, (unsigned long long)pte_idx, (unsigned long long)pte_fields.page_base_addr, (unsigned)pte_fields.fragment, (int)pte_fields.system, (int)pte_fields.valid);
+			if (asic->options.verbose)
+				fprintf(stderr, "[VERBOSE]: PTE=0x%016llx, VA=0x%010llx, PBA==0x%010llx, V=%d, S=%d\n",
+					(unsigned long long)pte_entry,
+					(unsigned long long)address & pte_mask,
+					(unsigned long long)pte_fields.page_base_addr,
+					(int)pte_fields.valid,
+					(int)pte_fields.system);
+
+			if (!pte_fields.valid)
+				return -1;
 
 			// compute starting address
 			start_addr = pte_fields.page_base_addr + (address & 0xFFF);
@@ -179,7 +222,7 @@ static int umr_read_vram_vi(struct umr_asic *asic, uint32_t vmid, uint64_t addre
 			// depth == 0 == PTE only
 			pte_idx = (address >> 12);
 
-			if (umr_read_vram(asic, 0xFFFF, page_table_base_addr + pte_idx * 8, 8, &pte_entry) < 0)
+			if (umr_read_vram(asic, UMR_LINEAR_HUB, page_table_base_addr + pte_idx * 8 - vm_fb_base, 8, &pte_entry) < 0)
 				return -1;
 
 			// decode PTE values
@@ -187,7 +230,16 @@ static int umr_read_vram_vi(struct umr_asic *asic, uint32_t vmid, uint64_t addre
 			pte_fields.fragment       = (pte_entry >> 7)  & 0x1F;
 			pte_fields.system         = (pte_entry >> 1) & 1;
 			pte_fields.valid          = pte_entry & 1;
-			DEBUG("pte_idx=%llx, page_base_addr=0x%llx, fragment=%u, system=%d, valid=%d\n", (unsigned long long)pte_idx, (unsigned long long)pte_fields.page_base_addr, (unsigned)pte_fields.fragment, (int)pte_fields.system, (int)pte_fields.valid);
+			if (asic->options.verbose)
+				fprintf(stderr, "[VERBOSE]: PTE=0x%016llx, VA=0x%010llx, PBA==0x%010llx, PTE.system=%d, PTE.valid=%d\n",
+					(unsigned long long)pte_entry,
+					(unsigned long long)address & ~0xFFFULL,
+					(unsigned long long)pte_fields.page_base_addr,
+					(int)pte_fields.system,
+					(int)pte_fields.valid);
+
+			if (!pte_fields.valid)
+				return -1;
 
 			// compute starting address
 			start_addr = pte_fields.page_base_addr + (address & 0xFFF);
@@ -207,7 +259,7 @@ static int umr_read_vram_vi(struct umr_asic *asic, uint32_t vmid, uint64_t addre
 				return -1;
 			}
 		} else {
-			if (umr_read_vram(asic, 0xFFFF, start_addr, chunk_size, pdst) < 0) {
+			if (umr_read_vram(asic, UMR_LINEAR_HUB, start_addr, chunk_size, pdst) < 0) {
 				fprintf(stderr, "[ERROR]: Cannot read from VRAM\n");
 				return -1;
 			}
@@ -215,7 +267,7 @@ static int umr_read_vram_vi(struct umr_asic *asic, uint32_t vmid, uint64_t addre
 		pdst += chunk_size;
 		size -= chunk_size;
 		address += chunk_size;
-	}
+	} while (size);
 	return 0;
 }
 
@@ -223,9 +275,21 @@ static int umr_read_vram_ai(struct umr_asic *asic, uint32_t vmid, uint64_t addre
 {
 	uint64_t start_addr, page_table_start_addr, page_table_base_addr,
 		 page_table_size, pte_idx, pde_idx, pte_entry, pde_entry,
-		 pde_address, vga_base_address, vm_fb_offset, vm_fb_base;
+		 pde_address, vga_base_address, vm_fb_offset, vm_fb_base,
+		 va_mask;
 	uint32_t chunk_size, tmp;
-	int page_table_depth, first;
+	int page_table_depth, first, depth, indent;
+	struct {
+		uint32_t
+			mmVM_CONTEXTx_PAGE_TABLE_START_ADDR_LO32,
+			mmVM_CONTEXTx_PAGE_TABLE_START_ADDR_HI32,
+			mmVM_CONTEXTx_CNTL,
+			mmVM_CONTEXTx_PAGE_TABLE_BASE_ADDR_LO32,
+			mmVM_CONTEXTx_PAGE_TABLE_BASE_ADDR_HI32,
+			mmVGA_MEMORY_BASE_ADDRESS,
+			mmVGA_MEMORY_BASE_ADDRESS_HIGH,
+			mmMC_VM_FB_OFFSET;
+	} registers;
 	struct {
 		uint64_t
 			frag_size,
@@ -244,6 +308,9 @@ static int umr_read_vram_ai(struct umr_asic *asic, uint32_t vmid, uint64_t addre
 	} pte_fields;
 	char buf[64];
 	unsigned char *pdst = dst;
+	char *hub;
+
+	memset(&registers, 0, sizeof registers);
 
 	/*
 	 * PTE format on AI:
@@ -266,61 +333,111 @@ static int umr_read_vram_ai(struct umr_asic *asic, uint32_t vmid, uint64_t addre
 	 * 0 valid
 	 */
 
+	if ((vmid & 0xFF00) == UMR_MM_HUB)
+		hub = "mmhub";
+	else
+		hub = "gfx";
+
+	vmid &= 0xFF;
+
 	// read vm registers
 	sprintf(buf, "mmVM_CONTEXT%d_PAGE_TABLE_START_ADDR_LO32", (int)vmid);
-		page_table_start_addr = (uint64_t)umr_read_reg_by_name(asic, buf) << 12;
+		registers.mmVM_CONTEXTx_PAGE_TABLE_START_ADDR_LO32 = umr_read_reg_by_name_by_ip(asic, hub, buf);
+		page_table_start_addr = (uint64_t)registers.mmVM_CONTEXTx_PAGE_TABLE_START_ADDR_LO32 << 12;
 	sprintf(buf, "mmVM_CONTEXT%d_PAGE_TABLE_START_ADDR_HI32", (int)vmid);
-		page_table_start_addr |= (uint64_t)umr_read_reg_by_name(asic, buf) << 44;
+		registers.mmVM_CONTEXTx_PAGE_TABLE_START_ADDR_HI32 = umr_read_reg_by_name_by_ip(asic, hub, buf);
+		page_table_start_addr |= (uint64_t)registers.mmVM_CONTEXTx_PAGE_TABLE_START_ADDR_HI32 << 44;
 
 	sprintf(buf, "mmVM_CONTEXT%d_CNTL", (int)vmid);
-		tmp = umr_read_reg_by_name(asic, buf);
+		tmp = registers.mmVM_CONTEXTx_CNTL = umr_read_reg_by_name_by_ip(asic, hub, buf);
 		page_table_depth      = umr_bitslice_reg_by_name(asic, buf, "PAGE_TABLE_DEPTH", tmp);
 		page_table_size       = umr_bitslice_reg_by_name(asic, buf, "PAGE_TABLE_BLOCK_SIZE", tmp);
 
 	sprintf(buf, "mmVM_CONTEXT%d_PAGE_TABLE_BASE_ADDR_LO32", (int)vmid);
-		page_table_base_addr  = (uint64_t)umr_read_reg_by_name(asic, buf) << 0;
+		registers.mmVM_CONTEXTx_PAGE_TABLE_BASE_ADDR_LO32 = umr_read_reg_by_name_by_ip(asic, hub, buf);
+		page_table_base_addr  = (uint64_t)registers.mmVM_CONTEXTx_PAGE_TABLE_BASE_ADDR_LO32 << 0;
 	sprintf(buf, "mmVM_CONTEXT%d_PAGE_TABLE_BASE_ADDR_HI32", (int)vmid);
-		page_table_base_addr  |= (uint64_t)umr_read_reg_by_name(asic, buf) << 32;
-
-	DEBUG("VIRT_ADDR = %08llx\n", (unsigned long long)address);
-	DEBUG("mmVM_CONTEXTx_PAGE_TABLE_START_ADDR = %08llx\n", (unsigned long long)page_table_start_addr);
-	DEBUG("mmVM_CONTEXTx_PAGE_TABLE_BASE_ADDR = 0x%08llx\n", (unsigned long long)page_table_base_addr);
-	DEBUG("mmVM_CONTEXTx_CNTL.PAGE_TABLE_BLOCK_SIZE = %lu\n", page_table_size);
-	DEBUG("mmVM_CONTEXTx_CNTL.PAGE_TABLE_DEPTH = %d\n", page_table_depth);
-
-	address -= page_table_start_addr;
+		registers.mmVM_CONTEXTx_PAGE_TABLE_BASE_ADDR_HI32 = umr_read_reg_by_name_by_ip(asic, hub, buf);
+		page_table_base_addr  |= (uint64_t)registers.mmVM_CONTEXTx_PAGE_TABLE_BASE_ADDR_HI32 << 32;
 
 	// update addresses for APUs
 	if (asic->config.gfx.family == 142) {
 		DEBUG("Reading vram config...\n");
-		vga_base_address  = (uint64_t)umr_read_reg_by_name(asic, "mmVGA_MEMORY_BASE_ADDRESS") << 0;
-		vga_base_address |= (uint64_t)umr_read_reg_by_name(asic, "mmVGA_MEMORY_BASE_ADDRESS_HIGH") << 32;
-		vm_fb_offset      = (uint64_t)umr_read_reg_by_name(asic, "mmMC_VM_FB_OFFSET") << 24;
+		registers.mmVGA_MEMORY_BASE_ADDRESS = umr_read_reg_by_name(asic, "mmVGA_MEMORY_BASE_ADDRESS");
+		registers.mmVGA_MEMORY_BASE_ADDRESS_HIGH = umr_read_reg_by_name(asic, "mmVGA_MEMORY_BASE_ADDRESS_HIGH");
+		registers.mmMC_VM_FB_OFFSET = umr_read_reg_by_name(asic, "mmMC_VM_FB_OFFSET");
+		vga_base_address  = (uint64_t)registers.mmVGA_MEMORY_BASE_ADDRESS << 0;
+		vga_base_address |= (uint64_t)registers.mmVGA_MEMORY_BASE_ADDRESS_HIGH << 32;
+		vm_fb_offset      = (uint64_t)registers.mmMC_VM_FB_OFFSET << 24;
 	} else {
 		vga_base_address = 0;
 		vm_fb_offset = 0;
 	}
 	vm_fb_base = (uint64_t)umr_read_reg_by_name(asic, "mmMC_VM_FB_LOCATION_BASE") << 24;
 
+	if (asic->options.verbose)
+		fprintf(stderr,
+				"[VERBOSE]: mmVM_CONTEXT%d_PAGE_TABLE_START_ADDR_LO32=0x%llx\n"
+				"[VERBOSE]: mmVM_CONTEXT%d_PAGE_TABLE_START_ADDR_HI32=0x%llx\n"
+				"[VERBOSE]: mmVM_CONTEXT%d_PAGE_TABLE_BASE_ADDR_LO32=0x%llx\n"
+				"[VERBOSE]: mmVM_CONTEXT%d_PAGE_TABLE_BASE_ADDR_HI32=0x%llx\n"
+				"[VERBOSE]: mmVM_CONTEXT%d_CNTL=0x%llx\n"
+				"[VERBOSE]: mmVGA_MEMORY_BASE_ADDRESS=0x%llx\n"
+				"[VERBOSE]: mmVGA_MEMORY_BASE_ADDRESS_HIGH=0x%llx\n"
+				"[VERBOSE]: mmMC_VM_FB_OFFSET=0x%llx\n",
+			(int)vmid, (unsigned long long)registers.mmVM_CONTEXTx_PAGE_TABLE_START_ADDR_LO32,
+			(int)vmid, (unsigned long long)registers.mmVM_CONTEXTx_PAGE_TABLE_START_ADDR_HI32,
+			(int)vmid, (unsigned long long)registers.mmVM_CONTEXTx_PAGE_TABLE_BASE_ADDR_LO32,
+			(int)vmid, (unsigned long long)registers.mmVM_CONTEXTx_PAGE_TABLE_BASE_ADDR_HI32,
+			(int)vmid, (unsigned long long)registers.mmVM_CONTEXTx_CNTL,
+			(unsigned long long)registers.mmVGA_MEMORY_BASE_ADDRESS,
+			(unsigned long long)registers.mmVGA_MEMORY_BASE_ADDRESS_HIGH,
+			(unsigned long long)registers.mmMC_VM_FB_OFFSET);
+
+
 	DEBUG("mmMC_VM_FB_LOCATION_BASE == %llx\n", (unsigned long long)vm_fb_base);
 	DEBUG("mmMC_VM_FB_OFFSET = 0x%08llx\n", (unsigned long long)vm_fb_offset);
 	DEBUG("mmVGA_MEMORY_BASE_ADDRESS = 0x%08llx\n", (unsigned long long)vga_base_address);
 	DEBUG("\n");
 
 	// transform page_table_base
+	pde_entry = page_table_base_addr;
 	page_table_base_addr -= vm_fb_offset;
+	address -= page_table_start_addr;
 
-	while (size) {
+	do {
 		first = 1;
 		if (page_table_depth >= 1) {
+			// decode PDE values
+			pde_fields.frag_size     = (pde_entry >> 59) & 0x1F;
+			pde_fields.pte_base_addr = pde_entry & 0xFFFFFFFFFF000ULL;
+			pde_fields.valid         = pde_entry & 1;
+			pde_fields.system        = (pde_entry >> 1) & 1;
+			pde_fields.cache         = (pde_entry >> 2) & 1;
+			pde_fields.pte           = (pde_entry >> 54) & 1;
+
 			// mask off valid bit
 			page_table_base_addr &= ~1ULL;
 
+			// read PTE selector
 			pte_idx = (address >> 12) & ((1ULL << (9 + page_table_size)) - 1);
 
 			// AI+ supports more than 1 level of PDEs so we iterate for all of the depths
 			pde_address = page_table_base_addr;
 			pde_fields.system = 0;
+			depth = 0;
+			va_mask = ((unsigned long long)511 << ((page_table_depth)*9 + (12 + 9 + page_table_size)));
+			if (asic->options.verbose)
+				fprintf(stderr, "[VERBOSE]: PDE%d=0x%016llx, VA=0x%012llx, PBA==0x%012llx, V=%d, S=%d, C=%d, P=%d\n",
+						depth++,
+						(unsigned long long)pde_entry,
+						(unsigned long long)address & va_mask,
+						(unsigned long long)pde_fields.pte_base_addr,
+						(int)pde_fields.valid,
+						(int)pde_fields.system,
+						(int)pde_fields.cache,
+						(int)pde_fields.pte);
+			indent = page_table_depth * 3;
 			while (page_table_depth) {
 				DEBUG("Decoding depth %u...(0x%llx)\n", (unsigned)page_table_depth, (unsigned long long)address);
 				// decode addr into pte and pde selectors...
@@ -333,10 +450,11 @@ static int umr_read_vram_ai(struct umr_asic *asic, uint32_t vmid, uint64_t addre
 				first = 0;
 
 				DEBUG("pde_idx == %llx\n", (unsigned long long)pde_idx);
-				DEBUG("selector mask == %llx\n", ((unsigned long long)511 << ((page_table_depth-1)*9 + (12 + 9 + page_table_size))));
+				va_mask = ((unsigned long long)511 << ((page_table_depth-2)*9 + (12 + 9 + page_table_size)));
+				DEBUG("selector mask == %llx\n", va_mask);
 
 				// read PDE entry
-				if (umr_read_vram(asic, 0xFFFF, pde_address + pde_idx * 8, 8, &pde_entry) < 0)
+				if (umr_read_vram(asic, UMR_LINEAR_HUB, pde_address + pde_idx * 8, 8, &pde_entry) < 0)
 					return -1;
 
 				// decode PDE values
@@ -346,21 +464,33 @@ static int umr_read_vram_ai(struct umr_asic *asic, uint32_t vmid, uint64_t addre
 				pde_fields.system        = (pde_entry >> 1) & 1;
 				pde_fields.cache         = (pde_entry >> 2) & 1;
 				pde_fields.pte           = (pde_entry >> 54) & 1;
-				DEBUG("PDE==%llx, frag_size=%u, pte_base_addr=0x%llx, valid=%d, system=%d, cache=%d, pte=%d\n",
-					(unsigned long long)pde_entry, (unsigned)pde_fields.frag_size, (unsigned long long)pde_fields.pte_base_addr,
-					(int)pde_fields.valid, (int)pde_fields.system, (int)pde_fields.cache, (int)pde_fields.pte);
+				if (asic->options.verbose)
+					fprintf(stderr, "[VERBOSE]: PDE%d=0x%016llx, VA=0x%012llx, PBA==0x%012llx, V=%d, S=%d, C=%d, P=%d\n",
+							depth,
+							(unsigned long long)pde_entry,
+							(unsigned long long)address & va_mask,
+							(unsigned long long)pde_fields.pte_base_addr,
+							(int)pde_fields.valid,
+							(int)pde_fields.system,
+							(int)pde_fields.cache,
+							(int)pde_fields.pte);
 
 				if (!pde_fields.system)
 					pde_fields.pte_base_addr -= vm_fb_offset;
 
+				if (!pde_fields.valid)
+					return -1;
+
 				// for the next round the address we're decoding is the phys address in the currently decoded PDE
 				--page_table_depth;
+				++depth;
+				indent -= 3;
 				pde_address = pde_fields.pte_base_addr;
 				DEBUG("...done\n\n");
 			}
 
 			// now read PTE entry for this page
-			if (umr_read_vram(asic, 0xFFFF, pde_fields.pte_base_addr + pte_idx*8, 8, &pte_entry) < 0)
+			if (umr_read_vram(asic, UMR_LINEAR_HUB, pde_fields.pte_base_addr + pte_idx*8, 8, &pte_entry) < 0)
 				return -1;
 
 			// decode PTE values
@@ -368,13 +498,20 @@ static int umr_read_vram_ai(struct umr_asic *asic, uint32_t vmid, uint64_t addre
 			pte_fields.fragment       = (pte_entry >> 7)  & 0x1F;
 			pte_fields.system         = (pte_entry >> 1) & 1;
 			pte_fields.valid          = pte_entry & 1;
-			DEBUG("PTE=%llx, pte_idx=%llx, page_base_addr=0x%llx, fragment=%u, system=%d, valid=%d\n",
-				(unsigned long long)pte_entry, (unsigned long long)pte_idx, (unsigned long long)pte_fields.page_base_addr, (unsigned)pte_fields.fragment,
-				(int)pte_fields.system, (int)pte_fields.valid);
+			if (asic->options.verbose)
+				fprintf(stderr, "[VERBOSE]: PTE==0x%016llx, VA=0x%012llx, PBA==0x%012llx, V=%d, S=%d\n",
+					(unsigned long long)pte_entry,
+					(unsigned long long)address & ((1ULL << (9 + page_table_size)) - 1),
+					(unsigned long long)pte_fields.page_base_addr,
+					(int)pte_fields.valid,
+					(int)pte_fields.system);
 
 			if (!pte_fields.system)
 				pte_fields.page_base_addr -= vm_fb_offset;
 
+			if (!pte_fields.valid)
+				return -1;
+
 			// compute starting address
 			start_addr = pte_fields.page_base_addr + (address & 0xFFF);
 			DEBUG("phys address to read from: %llx\n\n\n", (unsigned long long)start_addr);
@@ -387,14 +524,17 @@ static int umr_read_vram_ai(struct umr_asic *asic, uint32_t vmid, uint64_t addre
 			pde_fields.pte_base_addr = page_table_base_addr & 0xFFFFFFFFFF000ULL;
 			pde_fields.system        = (page_table_base_addr >> 1) & 1;
 			pde_fields.valid         = page_table_base_addr & 1;
-			DEBUG("pde_idx=%llx, frag_size=%u, pte_base_addr=0x%llx, system=%d, valid=%d\n",
-				(unsigned long long)pde_idx, (unsigned)pde_fields.frag_size, (unsigned long long)pde_fields.pte_base_addr,
-				(int)pde_fields.system, (int)pde_fields.valid);
+			if (asic->options.verbose)
+				fprintf(stderr, "[VERBOSE]: PDE=0x%016llx, PBA==0x%012llx, V=%d, S=%d\n",
+						(unsigned long long)page_table_base_addr,
+						(unsigned long long)pde_fields.pte_base_addr,
+						(int)pde_fields.valid,
+						(int)pde_fields.system);
 
 			// PTE addr = baseaddr[47:6] + (logical - start) >> fragsize)
 			pte_idx = (address >> (12 + pde_fields.frag_size));
 
-			if (umr_read_vram(asic, 0xFFFF, pde_fields.pte_base_addr + pte_idx * 8, 8, &pte_entry) < 0)
+			if (umr_read_vram(asic, UMR_LINEAR_HUB, pde_fields.pte_base_addr + pte_idx * 8, 8, &pte_entry) < 0)
 				return -1;
 
 			// decode PTE values
@@ -402,9 +542,13 @@ static int umr_read_vram_ai(struct umr_asic *asic, uint32_t vmid, uint64_t addre
 			pte_fields.fragment       = (pte_entry >> 7)  & 0x1F;
 			pte_fields.system         = (pte_entry >> 1) & 1;
 			pte_fields.valid          = pte_entry & 1;
-			DEBUG("pte_idx=%llx, page_base_addr=0x%llx, fragment=%u, system=%d, valid=%d\n",
-				(unsigned long long)pte_idx, (unsigned long long)pte_fields.page_base_addr, (unsigned)pte_fields.fragment,
-				(int)pte_fields.system, (int)pte_fields.valid);
+			if (asic->options.verbose)
+				fprintf(stderr, "[VERBOSE]: PTE=0x%016llx, PBA==0x%012llx, F=%u, V=%d, S=%d\n",
+					(unsigned long long)pte_entry,
+					(unsigned long long)pte_fields.page_base_addr,
+					(unsigned)pte_fields.fragment,
+					(int)pte_fields.valid,
+					(int)pte_fields.system);
 
 
 			// compute starting address
@@ -427,7 +571,7 @@ static int umr_read_vram_ai(struct umr_asic *asic, uint32_t vmid, uint64_t addre
 				return -1;
 			}
 		} else {
-			if (umr_read_vram(asic, 0xFFFF, start_addr, chunk_size, pdst) < 0) {
+			if (umr_read_vram(asic, UMR_LINEAR_HUB, start_addr, chunk_size, pdst) < 0) {
 				fprintf(stderr, "[ERROR]: Cannot read from VRAM\n");
 				return -1;
 			}
@@ -435,7 +579,7 @@ static int umr_read_vram_ai(struct umr_asic *asic, uint32_t vmid, uint64_t addre
 		pdst += chunk_size;
 		size -= chunk_size;
 		address += chunk_size;
-	}
+	} while (size);
 	return 0;
 }
 
@@ -451,7 +595,7 @@ int umr_read_vram(struct umr_asic *asic, uint32_t vmid, uint64_t address, uint32
 		return -1;
 	}
 
-	if (vmid == 0xFFFF) {
+	if ((vmid & 0xFF00) == UMR_LINEAR_HUB) {
 		DEBUG("Reading physical VRAM addr: 0x%llx\n", (unsigned long long)address);
 		// addressing is physical
 		if (asic->options.use_pci == 0) {
diff --git a/src/lib/ring_decode.c b/src/lib/ring_decode.c
index 35e72ed58e4f..772ea49dda6f 100644
--- a/src/lib/ring_decode.c
+++ b/src/lib/ring_decode.c
@@ -589,7 +589,7 @@ static void print_decode_pm4(struct umr_asic *asic, struct umr_ring_decoder *dec
 			// detect VCN/UVD IBs and chain them once all
 			// 4 pieces of information are found
 			if (!strcmp(name, "mmUVD_LMI_RBC_IB_VMID")) {
-				decoder->pm4.next_ib_state.ib_vmid = ib;
+				decoder->pm4.next_ib_state.ib_vmid = ib | ((asic->family <= FAMILY_VI) ? 0 : UMR_MM_HUB);
 				decoder->pm4.next_ib_state.tally |= 1;
 			} else if (!strcmp(name, "mmUVD_LMI_RBC_IB_64BIT_BAR_LOW")) {
 				decoder->pm4.next_ib_state.ib_addr_lo = ib;
@@ -598,7 +598,7 @@ static void print_decode_pm4(struct umr_asic *asic, struct umr_ring_decoder *dec
 				decoder->pm4.next_ib_state.ib_addr_hi = ib;
 				decoder->pm4.next_ib_state.tally |= 4;
 			} else if (!strcmp(name, "mmUVD_RBC_IB_SIZE")) {
-				decoder->pm4.next_ib_state.ib_size = ib;
+				decoder->pm4.next_ib_state.ib_size = ib * 4;
 				decoder->pm4.next_ib_state.tally |= 8;
 			}
 
diff --git a/src/lib/sq_cmd_halt_waves.c b/src/lib/sq_cmd_halt_waves.c
new file mode 100644
index 000000000000..83aa52d2cfb2
--- /dev/null
+++ b/src/lib/sq_cmd_halt_waves.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Tom St Denis <tom.stdenis@amd.com>
+ *
+ */
+#include "umr.h"
+
+int umr_sq_cmd_halt_waves(struct umr_asic *asic, enum umr_sq_cmd_halt_resume mode)
+{
+	struct umr_reg *reg;
+	uint32_t value;
+	uint64_t addr;
+
+	reg = umr_find_reg_data(asic, "SQ_CMD");
+	if (!reg) {
+		fprintf(stderr, "[BUG]: Cannot find SQ_CMD register in umr_sq_cmd_halt_waves()\n");
+		return -1;
+	}
+
+	// compose value
+	if (asic->family == FAMILY_CIK) {
+		value = umr_bitslice_compose_value(asic, reg, "CMD", mode == UMR_SQ_CMD_HALT ? 1 : 2); // SETHALT
+	} else {
+		value = umr_bitslice_compose_value(asic, reg, "CMD", 1); // SETHALT
+		value |= umr_bitslice_compose_value(asic, reg, "DATA", mode == UMR_SQ_CMD_HALT ? 1 : 0);
+	}
+	value |= umr_bitslice_compose_value(asic, reg, "MODE", 1); // BROADCAST
+
+	// compose address
+	addr = reg->addr * 4;
+	addr |= (1ULL << 62) |      // we need to take the lock so we can ensure a broadcast write
+			(0x3FFULL << 24) |
+			(0x3FFULL << 34) |
+			(0x3FFULL << 44);
+	umr_write_reg(asic, addr, value, reg->type);
+
+	return 0;
+}
diff --git a/src/umr.h b/src/umr.h
index a0e94a7e4db9..dd7f80c38f0c 100644
--- a/src/umr.h
+++ b/src/umr.h
@@ -33,6 +33,20 @@
 #include <pciaccess.h>
 #include <pthread.h>
 
+/* SQ_CMD halt/resume */
+enum umr_sq_cmd_halt_resume {
+	UMR_SQ_CMD_HALT=0,
+	UMR_SQ_CMD_RESUME,
+};
+
+/* memory space hubs */
+enum umr_hub_space {
+	UMR_GFX_HUB = 0 << 8,        // default on everything before AI
+	UMR_MM_HUB = 1 << 8,         // available on AI and later
+
+	UMR_LINEAR_HUB = 0xFF << 8,  // this is for linear access to vram
+};
+
 /* sourced from amd_powerplay.h from the kernel */
 enum amd_pp_sensors {
 	AMDGPU_PP_SENSOR_GFX_SCLK = 0,
@@ -174,6 +188,8 @@ struct umr_options {
 	    read_smc,
 	    quiet,
 	    follow_ib,
+	    verbose,
+	    halt_waves,
 	    no_kernel;
 	unsigned
 	    instance_bank,
@@ -477,6 +493,7 @@ int umr_create_mmio_accel(struct umr_asic *asic);
 uint32_t umr_find_reg(struct umr_asic *asic, char *regname);
 
 // find the register data for a register
+struct umr_reg *umr_find_reg_data_by_ip(struct umr_asic *asic, char *ip, char *regname);
 struct umr_reg *umr_find_reg_data(struct umr_asic *asic, char *regname);
 
 // read/write a 32-bit register given a BYTE address
@@ -487,17 +504,26 @@ int umr_write_reg(struct umr_asic *asic, uint64_t addr, uint32_t value, enum reg
 uint32_t umr_read_reg_by_name(struct umr_asic *asic, char *name);
 int umr_write_reg_by_name(struct umr_asic *asic, char *name, uint32_t value);
 
+// read/write a register by ip/name
+uint32_t umr_read_reg_by_name_by_ip(struct umr_asic *asic, char *ip, char *name);
+int umr_write_reg_by_name_by_ip(struct umr_asic *asic, char *ip, char *name, uint32_t value);
+
 // slice a full register into bits (shifted into LSB)
 uint32_t umr_bitslice_reg(struct umr_asic *asic, struct umr_reg *reg, char *bitname, uint32_t regvalue);
 uint32_t umr_bitslice_reg_by_name(struct umr_asic *asic, char *regname, char *bitname, uint32_t regvalue);
+uint32_t umr_bitslice_reg_by_name_by_ip(struct umr_asic *asic, char *ip, char *regname, char *bitname, uint32_t regvalue);
 
 // compose a 32-bit register with a value and a bitfield
 uint32_t umr_bitslice_compose_value(struct umr_asic *asic, struct umr_reg *reg, char *bitname, uint32_t regvalue);
 uint32_t umr_bitslice_compose_value_by_name(struct umr_asic *asic, char *reg, char *bitname, uint32_t regvalue);
+uint32_t umr_bitslice_compose_value_by_name_by_ip(struct umr_asic *asic, char *ip, char *regname, char *bitname, uint32_t regvalue);
 
 // select a GRBM_GFX_IDX
 int umr_grbm_select_index(struct umr_asic *asic, uint32_t se, uint32_t sh, uint32_t instance);
 
+// halt/resume SQ waves
+int umr_sq_cmd_halt_waves(struct umr_asic *asic, enum umr_sq_cmd_halt_resume mode);
+
 /* 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);
-- 
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] 5+ messages in thread

end of thread, other threads:[~2017-07-25 17:23 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-07-25 17:23 umr: Various cleanups and better VM decoding Tom St Denis
     [not found] ` <20170725172324.28365-1-tom.stdenis-5C7GfCeVMHo@public.gmane.org>
2017-07-25 17:23   ` [PATCH umr 1/4] Remove 'risky' option --print command. (v2) Tom St Denis
2017-07-25 17:23   ` [PATCH umr 2/4] Add ability to specify VMID in hex Tom St Denis
2017-07-25 17:23   ` [PATCH umr 3/4] Various cleanups found by static analysis. (v2) Tom St Denis
2017-07-25 17:23   ` [PATCH umr 4/4] Add ability to halt waves and better VM decoding (v3) 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.