[PATCH umr] Add 'no_kernel' option

Tom St Denis tom.stdenis at amd.com
Fri Apr 28 11:44:50 UTC 2017


This flag allows umr to perform some operations it would normally
need the kernel for in userspace.  This is useful if the kernel driver
is misbehaving.  Don't use this on a healthy system as it could invoke
race conditions.

This flag enables userland activities such as

- reading/writing MMIO registers (with bank selection)
- reading wave status and SGPR registers

Signed-off-by: Tom St Denis <tom.stdenis at amd.com>
---
 doc/umr.1             |  5 +++
 src/app/main.c        |  5 ++-
 src/app/scan.c        |  6 +++-
 src/app/set_bit.c     |  4 +++
 src/app/set_reg.c     |  4 +++
 src/lib/discover.c    | 49 +++++++++++++++++----------
 src/lib/mmio.c        | 57 ++++++++++++++++++++++++++++++-
 src/lib/read_sgpr.c   | 58 +++++++++++++++++++++++++-------
 src/lib/wave_status.c | 92 ++++++++++++++++++++++++++++++++++++++++++---------
 src/umr.h             | 23 +++++++++++--
 10 files changed, 252 insertions(+), 51 deletions(-)

diff --git a/doc/umr.1 b/doc/umr.1
index 90be2d6316ce..50ce03330b5c 100644
--- a/doc/umr.1
+++ b/doc/umr.1
@@ -138,6 +138,11 @@ separated strings.
      Enable colour output for --top command, scales from blue, green, yellow, to red.  Also
      accepted is 'use_color'.
 
+.B no_kernel
+     Disable using kernel files to access the device.  Implies ''use_pci''.  This is meant to
+     be used only if the KMD is hung or otherwise not working correctly.  Using it on live systems
+     may result in race conditions.
+
 .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 96a790cbec7c..1d9ef9edceb8 100644
--- a/src/app/main.c
+++ b/src/app/main.c
@@ -109,6 +109,9 @@ static void parse_options(char *str)
 			options.quiet = 1;
 		} else if (!strcmp(option, "follow_ib")) {
 			options.follow_ib = 1;
+		} else if (!strcmp(option, "no_kernel")) {
+			options.no_kernel = 1;
+			options.use_pci = 1;
 		} else {
 			printf("error: Unknown option [%s]\n", option);
 			exit(EXIT_FAILURE);
@@ -413,7 +416,7 @@ int main(int argc, char **argv)
 	"\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.\n"
+	"\n\t\tuse_pci, use_colour, read_smc, quiet, no_kernel.\n"
 "\n\n", UMR_BUILD_VER, UMR_BUILD_REV);
 			exit(EXIT_SUCCESS);
 		} else {
diff --git a/src/app/scan.c b/src/app/scan.c
index e91fbd4649c8..3320509f8be2 100644
--- a/src/app/scan.c
+++ b/src/app/scan.c
@@ -88,7 +88,11 @@ int umr_scan_asic(struct umr_asic *asic, char *asicname, char *ipname, char *reg
 								goto error;
 							}
 						} else if (asic->blocks[i]->regs[j].type == REG_MMIO) {
-							asic->blocks[i]->regs[j].value = asic->pci.mem[asic->blocks[i]->regs[j].addr];
+							if (options.use_bank && options.no_kernel)
+								umr_grbm_select_index(asic, options.se_bank, options.sh_bank, options.instance_bank);
+							asic->blocks[i]->regs[j].value = umr_read_reg(asic, asic->blocks[i]->regs[j].addr * 4);
+							if (options.use_bank && options.no_kernel)
+								umr_grbm_select_index(asic, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
 						}
 						if (regname[0]) {
 							if (options.named)
diff --git a/src/app/set_bit.c b/src/app/set_bit.c
index bed7ee858b6a..49f6c4750b8a 100644
--- a/src/app/set_bit.c
+++ b/src/app/set_bit.c
@@ -96,9 +96,13 @@ int umr_set_register_bit(struct umr_asic *asic, char *regpath, char *regvalue)
 										}
 									}
 								} else if (asic->blocks[i]->regs[j].type == REG_MMIO) {
+									if (options.use_bank && options.no_kernel)
+										umr_grbm_select_index(asic, options.se_bank, options.sh_bank, options.instance_bank);
 									copy = asic->pci.mem[asic->blocks[i]->regs[j].addr] & ~mask;
 									copy |= (value << asic->blocks[i]->regs[j].bits[k].start) & mask;
 									asic->pci.mem[asic->blocks[i]->regs[j].addr] = copy;
+									if (options.use_bank && options.no_kernel)
+										umr_grbm_select_index(asic, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
 									if (!options.quiet) printf("%s <= 0x%08lx\n", regpath, (unsigned long)copy);
 								}
 								return 0;
diff --git a/src/app/set_reg.c b/src/app/set_reg.c
index ed8f708e977f..acc8228cf421 100644
--- a/src/app/set_reg.c
+++ b/src/app/set_reg.c
@@ -84,7 +84,11 @@ int umr_set_register(struct umr_asic *asic, char *regpath, char *regvalue)
 								}
 							}
 						} else if (asic->blocks[i]->regs[j].type == REG_MMIO) {
+							if (options.use_bank && options.no_kernel)
+								umr_grbm_select_index(asic, options.se_bank, options.sh_bank, options.instance_bank);
 							asic->pci.mem[asic->blocks[i]->regs[j].addr] = value;
+							if (options.use_bank && options.no_kernel)
+								umr_grbm_select_index(asic, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
 						}
 						return 0;
 					}
diff --git a/src/lib/discover.c b/src/lib/discover.c
index c9c2f74a4818..5a6d7e47b0c2 100644
--- a/src/lib/discover.c
+++ b/src/lib/discover.c
@@ -111,24 +111,37 @@ struct umr_asic *umr_discover_asic(struct umr_options *options)
 
 	if (asic) {
 		memcpy(&asic->options, options, sizeof(*options));
-		snprintf(fname, sizeof(fname)-1, "/sys/kernel/debug/dri/%d/amdgpu_regs", asic->instance);
-		asic->fd.mmio = open(fname, O_RDWR);
-		snprintf(fname, sizeof(fname)-1, "/sys/kernel/debug/dri/%d/amdgpu_regs_didt", asic->instance);
-		asic->fd.didt = open(fname, O_RDWR);
-		snprintf(fname, sizeof(fname)-1, "/sys/kernel/debug/dri/%d/amdgpu_regs_pcie", asic->instance);
-		asic->fd.pcie = open(fname, O_RDWR);
-		snprintf(fname, sizeof(fname)-1, "/sys/kernel/debug/dri/%d/amdgpu_regs_smc", asic->instance);
-		asic->fd.smc = open(fname, O_RDWR);
-		snprintf(fname, sizeof(fname)-1, "/sys/kernel/debug/dri/%d/amdgpu_sensors", asic->instance);
-		asic->fd.sensors = open(fname, O_RDWR);
-		snprintf(fname, sizeof(fname)-1, "/sys/kernel/debug/dri/%d/amdgpu_wave", asic->instance);
-		asic->fd.wave = open(fname, O_RDWR);
-		snprintf(fname, sizeof(fname)-1, "/sys/kernel/debug/dri/%d/amdgpu_vram", asic->instance);
-		asic->fd.vram = open(fname, O_RDWR);
-		snprintf(fname, sizeof(fname)-1, "/sys/kernel/debug/dri/%d/amdgpu_gpr", asic->instance);
-		asic->fd.gpr = open(fname, O_RDWR);
-		asic->fd.drm = -1; // default to closed
-		// if appending to the fd list remember to update close_asic() and discover_by_did()...
+		if (!asic->options.no_kernel) {
+			snprintf(fname, sizeof(fname)-1, "/sys/kernel/debug/dri/%d/amdgpu_regs", asic->instance);
+			asic->fd.mmio = open(fname, O_RDWR);
+			snprintf(fname, sizeof(fname)-1, "/sys/kernel/debug/dri/%d/amdgpu_regs_didt", asic->instance);
+			asic->fd.didt = open(fname, O_RDWR);
+			snprintf(fname, sizeof(fname)-1, "/sys/kernel/debug/dri/%d/amdgpu_regs_pcie", asic->instance);
+			asic->fd.pcie = open(fname, O_RDWR);
+			snprintf(fname, sizeof(fname)-1, "/sys/kernel/debug/dri/%d/amdgpu_regs_smc", asic->instance);
+			asic->fd.smc = open(fname, O_RDWR);
+			snprintf(fname, sizeof(fname)-1, "/sys/kernel/debug/dri/%d/amdgpu_sensors", asic->instance);
+			asic->fd.sensors = open(fname, O_RDWR);
+			snprintf(fname, sizeof(fname)-1, "/sys/kernel/debug/dri/%d/amdgpu_wave", asic->instance);
+			asic->fd.wave = open(fname, O_RDWR);
+			snprintf(fname, sizeof(fname)-1, "/sys/kernel/debug/dri/%d/amdgpu_vram", asic->instance);
+			asic->fd.vram = open(fname, O_RDWR);
+			snprintf(fname, sizeof(fname)-1, "/sys/kernel/debug/dri/%d/amdgpu_gpr", asic->instance);
+			asic->fd.gpr = open(fname, O_RDWR);
+			asic->fd.drm = -1; // default to closed
+			// if appending to the fd list remember to update close_asic() and discover_by_did()...
+		} else {
+			// no files open!
+			asic->fd.mmio = -1;
+			asic->fd.didt = -1;
+			asic->fd.pcie = -1;
+			asic->fd.smc = -1;
+			asic->fd.sensors = -1;
+			asic->fd.wave = -1;
+			asic->fd.vram = -1;
+			asic->fd.gpr = -1;
+			asic->fd.drm = -1;
+		}
 
 		if (options->use_pci) {
 			// init PCI mapping
diff --git a/src/lib/mmio.c b/src/lib/mmio.c
index 5d7cdd3191a1..ca812817e018 100644
--- a/src/lib/mmio.c
+++ b/src/lib/mmio.c
@@ -85,9 +85,64 @@ uint32_t umr_bitslice_reg(struct umr_asic *asic, struct umr_reg *reg, char *bitn
 	return 0;
 }
 
+uint32_t umr_bitslice_compose_value(struct umr_asic *asic, struct umr_reg *reg, char *bitname, uint32_t regvalue)
+{
+	int i;
+	for (i = 0; i < reg->no_bits; i++) {
+		if (!strcmp(bitname, reg->bits[i].regname)) {
+			regvalue &= (1UL << (reg->bits[i].stop - reg->bits[i].start + 1)) - 1;
+			regvalue <<= reg->bits[i].start;
+			return regvalue;
+		}
+	}
+	fprintf(stderr, "BUG: Bitfield [%s] not found in reg [%s] on asic [%s]\n", bitname, reg->regname, asic->asicname);
+	return 0;
+}
+
 uint32_t umr_bitslice_reg_by_name(struct umr_asic *asic, char *regname, char *bitname, uint32_t regvalue)
 {
 	struct umr_reg *reg;
 	reg = umr_find_reg_data(asic, regname);
-	return umr_bitslice_reg(asic, reg, bitname, regvalue);
+	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)
+{
+	struct umr_reg *reg;
+	reg = umr_find_reg_data(asic, regname);
+	if (reg)
+		return umr_bitslice_compose_value(asic, reg, bitname, regvalue);
+	else
+		return 0;
+}
+
+int umr_grbm_select_index(struct umr_asic *asic, uint32_t se, uint32_t sh, uint32_t instance)
+{
+	struct umr_reg *grbm_idx;
+	uint32_t data = 0;
+
+	grbm_idx = umr_find_reg_data(asic, "mmGRBM_GFX_INDEX");
+	if (grbm_idx) {
+		if (instance == 0xFFFFFFFF) {
+			data |= umr_bitslice_compose_value(asic, grbm_idx, "INSTANCE_BROADCAST_WRITES", 1);
+		} else {
+			data |= umr_bitslice_compose_value(asic, grbm_idx, "INSTANCE_INDEX", instance);
+		}
+		if (se == 0xFFFFFFFF) {
+			data |= umr_bitslice_compose_value(asic, grbm_idx, "SE_BROADCAST_WRITES", 1);
+		} else {
+			data |= umr_bitslice_compose_value(asic, grbm_idx, "SE_INDEX", instance);
+		}
+		if (sh == 0xFFFFFFFF) {
+			data |= umr_bitslice_compose_value(asic, grbm_idx, "SH_BROADCAST_WRITES", 1);
+		} else {
+			data |= umr_bitslice_compose_value(asic, grbm_idx, "SH_INDEX", instance);
+		}
+		return umr_write_reg(asic, grbm_idx->addr * 4, data);
+	} else {
+		return -1;
+	}
 }
diff --git a/src/lib/read_sgpr.c b/src/lib/read_sgpr.c
index f12983edcb04..8f799175b7ff 100644
--- a/src/lib/read_sgpr.c
+++ b/src/lib/read_sgpr.c
@@ -24,6 +24,33 @@
  */
 #include "umr.h"
 
+static void wave_read_regs_via_mmio(struct umr_asic *asic, uint32_t simd,
+			   uint32_t wave, uint32_t thread,
+			   uint32_t regno, uint32_t num, uint32_t *out)
+{
+	struct umr_reg *ind_index, *ind_data;
+	uint32_t data;
+
+	ind_index = umr_find_reg_data(asic, "mmSQ_IND_INDEX");
+	ind_data  = umr_find_reg_data(asic, "mmSQ_IND_DATA");
+
+	if (ind_index && ind_data) {
+		data = umr_bitslice_compose_value(asic, ind_index, "WAVE_ID", wave);
+		data |= umr_bitslice_compose_value(asic, ind_index, "SIMD_ID", simd);
+		data |= umr_bitslice_compose_value(asic, ind_index, "INDEX", regno);
+		data |= umr_bitslice_compose_value(asic, ind_index, "THREAD_ID", thread);
+		data |= umr_bitslice_compose_value(asic, ind_index, "FORCE_READ", 1);
+		data |= umr_bitslice_compose_value(asic, ind_index, "AUTO_INCR", 1);
+		umr_write_reg(asic, ind_index->addr * 4, data);
+		while (num--)
+			*(out++) = umr_read_reg(asic, ind_data->addr * 4);
+	} else {
+		fprintf(stderr, "[BUG] The required SQ_IND_{INDEX,DATA} registers are not found on the asic <%s>\n", asic->asicname);
+		return;
+	}
+}
+
+
 int umr_read_sgprs(struct umr_asic *asic, struct umr_wave_status *ws, uint32_t *dst)
 {
 	uint64_t addr, shift;
@@ -33,16 +60,23 @@ int umr_read_sgprs(struct umr_asic *asic, struct umr_wave_status *ws, uint32_t *
 	else
 		shift = 4;  // on VI allocations are in 16-dword blocks
 
-	addr =
-		(1ULL << 60)                             | // reading SGPRs
-		((uint64_t)ws->gpr_alloc.sgpr_base << shift) | // starting address to read from
-		((uint64_t)ws->hw_id.se_id << 12)        |
-		((uint64_t)ws->hw_id.sh_id << 20)        |
-		((uint64_t)ws->hw_id.cu_id << 28)        |
-		((uint64_t)ws->hw_id.wave_id << 36)      |
-		((uint64_t)ws->hw_id.simd_id << 44)      |
-		(0ULL << 52); // thread_id
-
-	lseek(asic->fd.gpr, addr, SEEK_SET);
-	return read(asic->fd.gpr, dst, 4 * ((ws->gpr_alloc.sgpr_size + 1) << shift));
+	if (!asic->options.no_kernel) {
+		addr =
+			(1ULL << 60)                             | // reading SGPRs
+			((uint64_t)ws->gpr_alloc.sgpr_base << shift) | // starting address to read from
+			((uint64_t)ws->hw_id.se_id << 12)        |
+			((uint64_t)ws->hw_id.sh_id << 20)        |
+			((uint64_t)ws->hw_id.cu_id << 28)        |
+			((uint64_t)ws->hw_id.wave_id << 36)      |
+			((uint64_t)ws->hw_id.simd_id << 44)      |
+			(0ULL << 52); // thread_id
+
+		lseek(asic->fd.gpr, addr, SEEK_SET);
+		return read(asic->fd.gpr, dst, 4 * ((ws->gpr_alloc.sgpr_size + 1) << shift));
+	} else {
+		umr_grbm_select_index(asic, ws->hw_id.se_id, ws->hw_id.sh_id, ws->hw_id.cu_id);
+		wave_read_regs_via_mmio(asic, ws->hw_id.simd_id, ws->hw_id.wave_id, ws->gpr_alloc.sgpr_base << shift, 0, (ws->gpr_alloc.sgpr_size + 1) << shift, dst);
+		umr_grbm_select_index(asic, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
+		return 0;
+	}
 }
diff --git a/src/lib/wave_status.c b/src/lib/wave_status.c
index 695a1bb836d1..22f92c2caad5 100644
--- a/src/lib/wave_status.c
+++ b/src/lib/wave_status.c
@@ -49,20 +49,75 @@ static int umr_get_wave_sq_info_vi(struct umr_asic *asic, unsigned se, unsigned
 	return 0;
 }
 
+static uint32_t wave_read_ind(struct umr_asic *asic, uint32_t simd, uint32_t wave, uint32_t address)
+{
+	struct umr_reg *ind_index, *ind_data;
+	uint32_t data;
+
+	ind_index = umr_find_reg_data(asic, "mmSQ_IND_INDEX");
+	ind_data  = umr_find_reg_data(asic, "mmSQ_IND_DATA");
+
+	if (ind_index && ind_data) {
+		data = umr_bitslice_compose_value(asic, ind_index, "WAVE_ID", wave);
+		data |= umr_bitslice_compose_value(asic, ind_index, "SIMD_ID", simd);
+		data |= umr_bitslice_compose_value(asic, ind_index, "INDEX", address);
+		data |= umr_bitslice_compose_value(asic, ind_index, "FORCE_READ", 1);
+		umr_write_reg(asic, ind_index->addr * 4, data);
+		return umr_read_reg(asic, ind_data->addr * 4);
+	} else {
+		fprintf(stderr, "[BUG] The required SQ_IND_{INDEX,DATA} registers are not found on the asic <%s>\n", asic->asicname);
+		return -1;
+	}
+}
+
+
+static int read_wave_status_via_mmio(struct umr_asic *asic, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields)
+{
+	/* type 0/1 wave data */
+	dst[(*no_fields)++] = (asic->family <= FAMILY_VI) ? 0 : 1;
+	dst[(*no_fields)++] = wave_read_ind(asic, simd, wave, umr_find_reg_data(asic, "ixSQ_WAVE_STATUS")->addr);
+	dst[(*no_fields)++] = wave_read_ind(asic, simd, wave, umr_find_reg_data(asic, "ixSQ_WAVE_PC_LO")->addr);
+	dst[(*no_fields)++] = wave_read_ind(asic, simd, wave, umr_find_reg_data(asic, "ixSQ_WAVE_PC_HI")->addr);
+	dst[(*no_fields)++] = wave_read_ind(asic, simd, wave, umr_find_reg_data(asic, "ixSQ_WAVE_EXEC_LO")->addr);
+	dst[(*no_fields)++] = wave_read_ind(asic, simd, wave, umr_find_reg_data(asic, "ixSQ_WAVE_EXEC_HI")->addr);
+	dst[(*no_fields)++] = wave_read_ind(asic, simd, wave, umr_find_reg_data(asic, "ixSQ_WAVE_HW_ID")->addr);
+	dst[(*no_fields)++] = wave_read_ind(asic, simd, wave, umr_find_reg_data(asic, "ixSQ_WAVE_INST_DW0")->addr);
+	dst[(*no_fields)++] = wave_read_ind(asic, simd, wave, umr_find_reg_data(asic, "ixSQ_WAVE_INST_DW1")->addr);
+	dst[(*no_fields)++] = wave_read_ind(asic, simd, wave, umr_find_reg_data(asic, "ixSQ_WAVE_GPR_ALLOC")->addr);
+	dst[(*no_fields)++] = wave_read_ind(asic, simd, wave, umr_find_reg_data(asic, "ixSQ_WAVE_LDS_ALLOC")->addr);
+	dst[(*no_fields)++] = wave_read_ind(asic, simd, wave, umr_find_reg_data(asic, "ixSQ_WAVE_TRAPSTS")->addr);
+	dst[(*no_fields)++] = wave_read_ind(asic, simd, wave, umr_find_reg_data(asic, "ixSQ_WAVE_IB_STS")->addr);
+	if (asic->family <= FAMILY_VI) {
+		dst[(*no_fields)++] = wave_read_ind(asic, simd, wave, umr_find_reg_data(asic, "ixSQ_WAVE_TBA_LO")->addr);
+		dst[(*no_fields)++] = wave_read_ind(asic, simd, wave, umr_find_reg_data(asic, "ixSQ_WAVE_TBA_HI")->addr);
+		dst[(*no_fields)++] = wave_read_ind(asic, simd, wave, umr_find_reg_data(asic, "ixSQ_WAVE_TMA_LO")->addr);
+		dst[(*no_fields)++] = wave_read_ind(asic, simd, wave, umr_find_reg_data(asic, "ixSQ_WAVE_TMA_HI")->addr);
+	}
+	dst[(*no_fields)++] = wave_read_ind(asic, simd, wave, umr_find_reg_data(asic, "ixSQ_WAVE_IB_DBG0")->addr);
+	dst[(*no_fields)++] = wave_read_ind(asic, simd, wave, umr_find_reg_data(asic, "ixSQ_WAVE_M0")->addr);
+
+	return 0;
+}
+
 static int umr_get_wave_status_vi(struct umr_asic *asic, unsigned se, unsigned sh, unsigned cu, unsigned simd, unsigned wave, struct umr_wave_status *ws)
 {
 	uint32_t x, value, buf[32];
 
 	memset(buf, 0, sizeof buf);
 
-	lseek(asic->fd.wave,
-		0 |
-		((uint64_t)se << 7) |
-		((uint64_t)sh << 15) |
-		((uint64_t)cu << 23) |
-		((uint64_t)wave << 31) |
-		((uint64_t)simd << 37), SEEK_SET);
-	read(asic->fd.wave, &buf, 32*4);
+	if (!asic->options.no_kernel) {
+		lseek(asic->fd.wave,
+			0 |
+			((uint64_t)se << 7) |
+			((uint64_t)sh << 15) |
+			((uint64_t)cu << 23) |
+			((uint64_t)wave << 31) |
+			((uint64_t)simd << 37), SEEK_SET);
+		read(asic->fd.wave, &buf, 32*4);
+	} else {
+		int n = 0;
+		read_wave_status_via_mmio(asic, simd, wave, &buf[0], &n);
+	}
 
 	if (buf[0] != 0) {
 		fprintf(stderr, "Was expecting type 0 wave data on a CZ/VI part!\n");
@@ -152,14 +207,19 @@ static int umr_get_wave_status_next(struct umr_asic *asic, unsigned se, unsigned
 
 	memset(buf, 0, sizeof buf);
 
-	lseek(asic->fd.wave,
-		0 |
-		((uint64_t)se << 7) |
-		((uint64_t)sh << 15) |
-		((uint64_t)cu << 23) |
-		((uint64_t)wave << 31) |
-		((uint64_t)simd << 37), SEEK_SET);
-	read(asic->fd.wave, &buf, 32*4);
+	if (!asic->options.no_kernel) {
+		lseek(asic->fd.wave,
+			0 |
+			((uint64_t)se << 7) |
+			((uint64_t)sh << 15) |
+			((uint64_t)cu << 23) |
+			((uint64_t)wave << 31) |
+			((uint64_t)simd << 37), SEEK_SET);
+		read(asic->fd.wave, &buf, 32*4);
+	} else {
+		int n = 0;
+		read_wave_status_via_mmio(asic, simd, wave, &buf[0], &n);
+	}
 
 	if (buf[0] != 1) {
 		fprintf(stderr, "Was expecting type 1 wave data on a FAMILY_AI part!\n");
diff --git a/src/umr.h b/src/umr.h
index 27d0015d17a3..b0b8fcb4cc72 100644
--- a/src/umr.h
+++ b/src/umr.h
@@ -171,7 +171,8 @@ struct umr_options {
 	    use_colour,
 	    read_smc,
 	    quiet,
-	    follow_ib;
+	    follow_ib,
+	    no_kernel;
 	unsigned
 	    instance_bank,
 	    se_bank,
@@ -453,15 +454,33 @@ int umr_read_sgprs(struct umr_asic *asic, struct umr_wave_status *ws, uint32_t *
 int umr_read_sensor(struct umr_asic *asic, int sensor, void *dst, int *size);
 
 /* mmio helpers */
+// init the mmio lookup table
+int umr_create_mmio_accel(struct umr_asic *asic);
+
+// find the word address of a register
 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(struct umr_asic *asic, char *regname);
+
+// read/write a 32-bit register given a BYTE address
 uint32_t umr_read_reg(struct umr_asic *asic, uint64_t addr);
 int umr_write_reg(struct umr_asic *asic, uint64_t addr, uint32_t value);
+
+// read/write a register given a name
 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);
+
+// 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);
-int umr_create_mmio_accel(struct umr_asic *asic);
+
+// 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);
+
+// select a GRBM_GFX_IDX
+int umr_grbm_select_index(struct umr_asic *asic, uint32_t se, uint32_t sh, uint32_t instance);
 
 /* IB/ring decoding/dumping/etc */
 void umr_print_decode(struct umr_asic *asic, struct umr_ring_decoder *decoder, uint32_t ib);
-- 
2.12.0



More information about the amd-gfx mailing list