On SI..VI platforms this allows access to SMC registers without kernel access. Signed-off-by: Tom St Denis <tom.stdenis at amd.com> (v2): Use difference instances of accessors to SMC as well as properly break out use_pci/!use_pci support in the umr_read_smc/umr_write_smc functions. --- src/app/main.c | 4 +- src/app/scan.c | 4 +- src/lib/mmio.c | 128 +++++++++++++++++++++++++++++++++++++++++--------- src/lib/read_sgpr.c | 4 +- src/lib/read_vram.c | 6 +-- src/lib/wave_status.c | 8 ++-- src/umr.h | 4 +- 7 files changed, 121 insertions(+), 37 deletions(-) diff --git a/src/app/main.c b/src/app/main.c index 60bf20480fd3..bcca76225727 100644 --- a/src/app/main.c +++ b/src/app/main.c @@ -224,7 +224,7 @@ int main(int argc, char **argv) if (!asic) asic = get_asic(); if (!memcmp(argv[i+1], "0x", 2) && sscanf(argv[i+1], "%"SCNx32, ®) == 1 && sscanf(argv[i+2], "%"SCNx32, &val) == 1) - umr_write_reg(asic, reg, val); + umr_write_reg(asic, reg, val, REG_MMIO); else umr_set_register(asic, argv[i+1], argv[i+2]); i += 2; @@ -271,7 +271,7 @@ int main(int argc, char **argv) asic = get_asic(); if (!memcmp(argv[i+1], "0x", 2) && sscanf(argv[i+1], "%"SCNx32, ®) == 1) { - reg = umr_read_reg(asic, reg); + reg = umr_read_reg(asic, reg, REG_MMIO); printf("0x%08lx\n", (unsigned long)reg); } else { str = strstr(argv[i+1], "."); diff --git a/src/app/scan.c b/src/app/scan.c index 0e1f9e3f94b5..29a3e46ba3f7 100644 --- a/src/app/scan.c +++ b/src/app/scan.c @@ -87,10 +87,10 @@ int umr_scan_asic(struct umr_asic *asic, char *asicname, char *ipname, char *reg r = -1; goto error; } - } else if (asic->blocks[i]->regs[j].type == REG_MMIO) { + } else if (asic->blocks[i]->regs[j].type == REG_MMIO || asic->blocks[i]->regs[j].type == REG_SMC) { 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); + asic->blocks[i]->regs[j].value = umr_read_reg(asic, asic->blocks[i]->regs[j].addr * (asic->blocks[i]->regs[j].type == REG_MMIO ? 4 : 1), asic->blocks[i]->regs[j].type); if (options.use_bank && options.no_kernel) umr_grbm_select_index(asic, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); } diff --git a/src/lib/mmio.c b/src/lib/mmio.c index 22110e09a9b4..dfd9f0d33e5d 100644 --- a/src/lib/mmio.c +++ b/src/lib/mmio.c @@ -24,36 +24,55 @@ */ #include "umr.h" -uint32_t umr_read_reg(struct umr_asic *asic, uint64_t addr) +static uint32_t umr_smc_read(struct umr_asic *asic, uint64_t addr) { - uint32_t value=0; - if (addr == 0xFFFFFFFF) - fprintf(stderr, "[BUG]: reading from addr==0xFFFFFFFF is likely a bug\n"); - - if (asic->pci.mem && !(addr & ~0xFFFFFULL)) { // only use pci if enabled and not using high bits - return asic->pci.mem[addr/4]; + uint32_t value; + if (asic->options.use_pci) { + switch (asic->config.gfx.family) { + case 110: // SI + case 120: // CIK + case 130: // VI + umr_write_reg_by_name(asic, "mmSMC_IND_INDEX_1", addr); + return umr_read_reg_by_name(asic, "mmSMC_IND_DATA_1"); + case 135: // CZ + umr_write_reg_by_name(asic, "mmMP0PUB_IND_INDEX_1", addr); + return umr_read_reg_by_name(asic, "mmMP0PUB_IND_DATA_1"); + default: + fprintf(stderr, "[BUG] Unsupported family type in umr_smc_read()\n"); + return 0; + } } else { - if (lseek(asic->fd.mmio, addr, SEEK_SET) < 0) - perror("Cannot seek to MMIO address"); - if (read(asic->fd.mmio, &value, 4) != 4) - perror("Cannot read from MMIO reg"); + if (lseek(asic->fd.smc, addr, SEEK_SET) < 0) + perror("Cannot seek to SMC address"); + if (read(asic->fd.smc, &value, 4) != 4) + perror("Cannot read from SMC reg"); return value; } + } -int umr_write_reg(struct umr_asic *asic, uint64_t addr, uint32_t value) +static uint32_t umr_smc_write(struct umr_asic *asic, uint64_t addr, uint32_t value) { - if (addr == 0xFFFFFFFF) - fprintf(stderr, "[BUG]: reading from addr==0xFFFFFFFF is likely a bug\n"); - - if (asic->pci.mem && !(addr & ~0xFFFFFULL)) { - asic->pci.mem[addr/4] = value; + if (asic->options.use_pci) { + switch (asic->config.gfx.family) { + case 110: // SI + case 120: // CIK + case 130: // VI + umr_write_reg_by_name(asic, "mmSMC_IND_INDEX_1", addr); + return umr_write_reg_by_name(asic, "mmSMC_IND_DATA_1", value); + case 135: // CZ + umr_write_reg_by_name(asic, "mmMP0PUB_IND_INDEX_1", addr); + return umr_write_reg_by_name(asic, "mmMP0PUB_IND_DATA_1", value); + default: + fprintf(stderr, "[BUG] Unsupported family type in umr_smc_read()\n"); + return -1; + } } else { - if (lseek(asic->fd.mmio, addr, SEEK_SET) < 0) { + if (lseek(asic->fd.smc, addr, SEEK_SET) < 0) { perror("Cannot seek to MMIO address"); return -1; } - if (write(asic->fd.mmio, &value, 4) != 4) { + if (write(asic->fd.smc, &value, 4) != 4) { perror("Cannot write to MMIO reg"); return -1; } @@ -61,14 +80,79 @@ int umr_write_reg(struct umr_asic *asic, uint64_t addr, uint32_t value) return 0; } +uint32_t umr_read_reg(struct umr_asic *asic, uint64_t addr, enum regclass type) +{ + uint32_t value=0; + if (addr == 0xFFFFFFFF) + fprintf(stderr, "[BUG]: reading from addr==0xFFFFFFFF is likely a bug\n"); + + switch (type) { + case REG_MMIO: + if (asic->pci.mem && !(addr & ~0xFFFFFULL)) { // only use pci if enabled and not using high bits + return asic->pci.mem[addr/4]; + } else { + if (lseek(asic->fd.mmio, addr, SEEK_SET) < 0) + perror("Cannot seek to MMIO address"); + if (read(asic->fd.mmio, &value, 4) != 4) + perror("Cannot read from MMIO reg"); + return value; + } + break; + case REG_SMC: + return umr_smc_read(asic, addr); + default: + fprintf(stderr, "[BUG] Unsupported register type in umr_read_reg().\n"); + return 0; + } +} + +int umr_write_reg(struct umr_asic *asic, uint64_t addr, uint32_t value, enum regclass type) +{ + if (addr == 0xFFFFFFFF) + fprintf(stderr, "[BUG]: reading from addr==0xFFFFFFFF is likely a bug\n"); + + switch (type) { + case REG_MMIO: + if (asic->pci.mem && !(addr & ~0xFFFFFULL)) { + asic->pci.mem[addr/4] = value; + } else { + if (lseek(asic->fd.mmio, addr, SEEK_SET) < 0) { + perror("Cannot seek to MMIO address"); + return -1; + } + if (write(asic->fd.mmio, &value, 4) != 4) { + perror("Cannot write to MMIO reg"); + return -1; + } + } + break; + case REG_SMC: + return umr_smc_write(asic, addr, value); + default: + fprintf(stderr, "[BUG] Unsupported register type in umr_write_reg().\n"); + return -1; + } + return 0; +} + uint32_t umr_read_reg_by_name(struct umr_asic *asic, char *name) { - return umr_read_reg(asic, umr_find_reg(asic, name) * 4); + struct umr_reg *reg; + reg = umr_find_reg_data(asic, 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) { - return umr_write_reg(asic, umr_find_reg(asic, name) * 4, value); + struct umr_reg *reg; + reg = umr_find_reg_data(asic, name); + if (reg) + return umr_write_reg(asic, reg->addr * (reg->type == REG_MMIO ? 4 : 1), value, reg->type); + else + return -1; } uint32_t umr_bitslice_reg(struct umr_asic *asic, struct umr_reg *reg, char *bitname, uint32_t regvalue) @@ -141,7 +225,7 @@ int umr_grbm_select_index(struct umr_asic *asic, uint32_t se, uint32_t sh, uint3 } else { data |= umr_bitslice_compose_value(asic, grbm_idx, "SH_INDEX", instance); } - return umr_write_reg(asic, grbm_idx->addr * 4, data); + return umr_write_reg(asic, grbm_idx->addr * 4, data, REG_MMIO); } else { return -1; } diff --git a/src/lib/read_sgpr.c b/src/lib/read_sgpr.c index 858657cc83c4..cceb189c1854 100644 --- a/src/lib/read_sgpr.c +++ b/src/lib/read_sgpr.c @@ -41,9 +41,9 @@ static void wave_read_regs_via_mmio(struct umr_asic *asic, uint32_t simd, 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); + umr_write_reg(asic, ind_index->addr * 4, data, REG_MMIO); while (num--) - *(out++) = umr_read_reg(asic, ind_data->addr * 4); + *(out++) = umr_read_reg(asic, ind_data->addr * 4, REG_MMIO); } else { fprintf(stderr, "[BUG]: The required SQ_IND_{INDEX,DATA} registers are not found on the asic <%s>\n", asic->asicname); return; diff --git a/src/lib/read_vram.c b/src/lib/read_vram.c index 502153dceaa5..3d458db8fa11 100644 --- a/src/lib/read_vram.c +++ b/src/lib/read_vram.c @@ -43,9 +43,9 @@ static void read_via_mmio(struct umr_asic *asic, uint64_t address, uint32_t size } while (size) { - umr_write_reg(asic, MM_INDEX, address | 0x80000000); - umr_write_reg(asic, MM_INDEX_HI, address >> 31); - *out++ = umr_read_reg(asic, MM_DATA); + umr_write_reg(asic, MM_INDEX, address | 0x80000000, REG_MMIO); + umr_write_reg(asic, MM_INDEX_HI, address >> 31, REG_MMIO); + *out++ = umr_read_reg(asic, MM_DATA, REG_MMIO); size -= 4; address += 4; } diff --git a/src/lib/wave_status.c b/src/lib/wave_status.c index 27bd6a4c86ed..6b8098e69a09 100644 --- a/src/lib/wave_status.c +++ b/src/lib/wave_status.c @@ -42,8 +42,8 @@ static int umr_get_wave_sq_info_vi(struct umr_asic *asic, unsigned se, unsigned return -1; } - umr_write_reg(asic, index|bank, 8 << 16); - value = umr_read_reg(asic, data|bank); + umr_write_reg(asic, index|bank, 8 << 16, REG_MMIO); + value = umr_read_reg(asic, data|bank, REG_MMIO); ws->sq_info.busy = value & 1; ws->sq_info.wave_level = (value >> 4) & 0x3F; return 0; @@ -62,8 +62,8 @@ static uint32_t wave_read_ind(struct umr_asic *asic, uint32_t simd, uint32_t wav 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); + umr_write_reg(asic, ind_index->addr * 4, data, REG_MMIO); + return umr_read_reg(asic, ind_data->addr * 4, REG_MMIO); } else { fprintf(stderr, "[BUG]: The required SQ_IND_{INDEX,DATA} registers are not found on the asic <%s>\n", asic->asicname); return -1; diff --git a/src/umr.h b/src/umr.h index ccfac5da6438..cc17e256a834 100644 --- a/src/umr.h +++ b/src/umr.h @@ -471,8 +471,8 @@ uint32_t umr_find_reg(struct umr_asic *asic, 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 -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); +uint32_t umr_read_reg(struct umr_asic *asic, uint64_t addr, enum regclass type); +int umr_write_reg(struct umr_asic *asic, uint64_t addr, uint32_t value, enum regclass type); // read/write a register given a name uint32_t umr_read_reg_by_name(struct umr_asic *asic, char *name); -- 2.12.0