This is handy if you are given a debug output with a register name and value you want to decode. For instance, a VM fault in the kernel log, $ umr -i 1 -O bits --lookup mmVM_CONTEXT1_PROTECTION_FAULT_STATUS 0x0803D00C gmc81.mmVM_CONTEXT1_PROTECTION_FAULT_STATUS => 0x0803d00c .PROTECTIONS[0:7] == 12 (0x0000000c) .MEMORY_CLIENT_ID[12:20] == 61 (0x0000003d) .MEMORY_CLIENT_RW[24:24] == 0 (0x00000000) .VMID[25:28] == 4 (0x00000004) .ATOMIC[29:29] == 0 (0x00000000) Signed-off-by: Tom St Denis <tom.stdenis at amd.com> --- doc/umr.1 | 5 +++-- src/app/main.c | 6 +++++- src/app/umr_lookup.c | 41 ++++++++++++++++++++++++++++------------- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/doc/umr.1 b/doc/umr.1 index d20184def2d3..601866a57a7e 100644 --- a/doc/umr.1 +++ b/doc/umr.1 @@ -32,8 +32,9 @@ Enumerate all AMDGPU supported devices. List all blocks attached to the asic that has been detected. .IP "--list-regs, -lr <string>" List all registers in an IP block (can use '-O bits' to list bitfields) -.IP "--lookup, -lu <address> <number>" -Look up an MMIO register by address and bitfield decode the value specified. +.IP "--lookup, -lu <address_or_regname> <number>" +Look up an MMIO register by address and bitfield decode the value specified (with 0x prefix) or by +register name. .IP "--write -w <string> <number>" Write a value specified in hex to a register specified with a complete register path in the form < diff --git a/src/app/main.c b/src/app/main.c index 822aa88afd85..ac3c25e2937e 100644 --- a/src/app/main.c +++ b/src/app/main.c @@ -393,12 +393,16 @@ int main(int argc, char **argv) "\n\t--bank, -b <se_bank> <sh_bank> <instance>\n\t\tSelect a GFX INSTANCE/SH/SE bank in decimal. Can use 'x' to denote broadcast.\n" "\n\t--force, -f <number>\n\t\tForce a PCIE DID number in hex or asic name. Useful if amdgpu is" "\n\t\tnot loaded or a display is not attached.\n" +"\n\t--pci <device>" + "\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" "\n\t--list-regs, -lr <string>\n\t\tList registers for a given IP block (can use '-O bits' to list bitfields).\n" -"\n\t--lookup, -lu <address> <value>\n\t\tLook up bit decoding of an MMIO register by address.\n" +"\n\t--lookup, -lu <address_or_regname> <value>\n\t\tLook up bit decoding of an MMIO register by address (with 0x prefix) or by register name.\n" "\n\t--write, -w <address> <number>\n\t\tWrite a value in hex to a register specified as a register path in the" "\n\t\tform <asicname.ipname.regname>. For instance \"tonga.uvd5.mmUVD_SOFT_RESET\"." "\n\t\tCan be used multiple times to set multiple registers. You can" diff --git a/src/app/umr_lookup.c b/src/app/umr_lookup.c index 3f3402ae34e7..d07130ab0dfa 100644 --- a/src/app/umr_lookup.c +++ b/src/app/umr_lookup.c @@ -27,23 +27,38 @@ void umr_lookup(struct umr_asic *asic, char *address, char *value) { - int i, j, k; + int byaddress, i, j, k; uint32_t regno, num; - sscanf(address, "%"SCNx32, ®no); + byaddress = sscanf(address, "0x%"SCNx32, ®no); sscanf(value, "%"SCNx32, &num); - for (i = 0; i < asic->no_blocks; i++) - for (j = 0; j < asic->blocks[i]->no_regs; j++) - if (asic->blocks[i]->regs[j].type == REG_MMIO && - asic->blocks[i]->regs[j].addr == regno) { - printf("%s => 0x%08lx\n", asic->blocks[i]->regs[j].regname, (unsigned long)num); - for (k = 0; k < asic->blocks[i]->regs[j].no_bits; k++) { - uint32_t v; - v = (1UL << (asic->blocks[i]->regs[j].bits[k].stop + 1 - asic->blocks[i]->regs[j].bits[k].start)) - 1; - v &= (num >> asic->blocks[i]->regs[j].bits[k].start); - asic->blocks[i]->regs[j].bits[k].bitfield_print(asic, asic->asicname, asic->blocks[i]->ipname, asic->blocks[i]->regs[j].regname, asic->blocks[i]->regs[j].bits[k].regname, asic->blocks[i]->regs[j].bits[k].start, asic->blocks[i]->regs[j].bits[k].stop, v); + if (byaddress) { + for (i = 0; i < asic->no_blocks; i++) + for (j = 0; j < asic->blocks[i]->no_regs; j++) + if (asic->blocks[i]->regs[j].type == REG_MMIO && + asic->blocks[i]->regs[j].addr == regno) { + printf("%s.%s => 0x%08lx\n", asic->blocks[i]->ipname, asic->blocks[i]->regs[j].regname, (unsigned long)num); + for (k = 0; k < asic->blocks[i]->regs[j].no_bits; k++) { + uint32_t v; + v = (1UL << (asic->blocks[i]->regs[j].bits[k].stop + 1 - asic->blocks[i]->regs[j].bits[k].start)) - 1; + v &= (num >> asic->blocks[i]->regs[j].bits[k].start); + asic->blocks[i]->regs[j].bits[k].bitfield_print(asic, asic->asicname, asic->blocks[i]->ipname, asic->blocks[i]->regs[j].regname, asic->blocks[i]->regs[j].bits[k].regname, asic->blocks[i]->regs[j].bits[k].start, asic->blocks[i]->regs[j].bits[k].stop, v); + } } - } + } else { + for (i = 0; i < asic->no_blocks; i++) + for (j = 0; j < asic->blocks[i]->no_regs; j++) + if (asic->blocks[i]->regs[j].type == REG_MMIO && + !strcmp(asic->blocks[i]->regs[j].regname, address)) { + printf("%s.%s => 0x%08lx\n", asic->blocks[i]->ipname, asic->blocks[i]->regs[j].regname, (unsigned long)num); + for (k = 0; k < asic->blocks[i]->regs[j].no_bits; k++) { + uint32_t v; + v = (1UL << (asic->blocks[i]->regs[j].bits[k].stop + 1 - asic->blocks[i]->regs[j].bits[k].start)) - 1; + v &= (num >> asic->blocks[i]->regs[j].bits[k].start); + asic->blocks[i]->regs[j].bits[k].bitfield_print(asic, asic->asicname, asic->blocks[i]->ipname, asic->blocks[i]->regs[j].regname, asic->blocks[i]->regs[j].bits[k].regname, asic->blocks[i]->regs[j].bits[k].start, asic->blocks[i]->regs[j].bits[k].stop, v); + } + } + } } -- 2.12.0