> -----Original Message----- > From: amd-gfx [mailto:amd-gfx-bounces at lists.freedesktop.org] On Behalf > Of Tom St Denis > Sent: Thursday, June 15, 2017 12:54 PM > To: amd-gfx at lists.freedesktop.org > Cc: StDenis, Tom > Subject: [PATCH umr] Add ability to read/write SMC registers directly > > On SI..VI platforms this allows access to SMC registers without kernel access. > > Signed-off-by: Tom St Denis <tom.stdenis at amd.com> > --- > src/app/main.c | 4 +- > src/app/scan.c | 4 +- > src/lib/mmio.c | 112 +++++++++++++++++++++++++++++++++++++++- > ---------- > 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, 104 insertions(+), 38 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..58f69fc56bd5 100644 > --- a/src/lib/mmio.c > +++ b/src/lib/mmio.c > @@ -24,51 +24,117 @@ > */ > #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) > +{ > + switch (asic->config.gfx.family) { > + case 120: // CIK > + case 110: // SI > + umr_write_reg_by_name(asic, > "mmSMC_IND_INDEX_0", addr); > + return umr_read_reg_by_name(asic, > "mmSMC_IND_DATA_0"); > + case 130: // VI > + umr_write_reg_by_name(asic, > "mmSMC_IND_INDEX_11", addr); > + return umr_read_reg_by_name(asic, > "mmSMC_IND_DATA_11"); > + case 135: // CZ > + umr_write_reg_by_name(asic, > "mmMP0PUB_IND_INDEX", addr); > + return umr_read_reg_by_name(asic, > "mmMP0PUB_IND_DATA"); You could use another instance of these accessors to avoid clashing with the driver. Reviewed-by: Alex Deucher <alexander.deucher at amd.com> > + default: > + fprintf(stderr, "[BUG] Unsupported family type in > umr_smc_read()\n"); > + return 0; > + } > +} > + > +static uint32_t umr_smc_write(struct umr_asic *asic, uint64_t addr, > uint32_t value) > +{ > + switch (asic->config.gfx.family) { > + case 120: // CIK > + case 110: // SI > + umr_write_reg_by_name(asic, > "mmSMC_IND_INDEX_0", addr); > + return umr_write_reg_by_name(asic, > "mmSMC_IND_DATA_0", value); > + case 130: // VI > + umr_write_reg_by_name(asic, > "mmSMC_IND_INDEX_11", addr); > + return umr_write_reg_by_name(asic, > "mmSMC_IND_DATA_11", value); > + case 135: // CZ > + umr_write_reg_by_name(asic, > "mmMP0PUB_IND_INDEX", addr); > + return umr_write_reg_by_name(asic, > "mmMP0PUB_IND_DATA", value); > + default: > + fprintf(stderr, "[BUG] Unsupported family type in > umr_smc_read()\n"); > + return -1; > + } > +} > + > +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"); > > - 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; > + 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) > +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"); > > - 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"); > + 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; > - } > - if (write(asic->fd.mmio, &value, 4) != 4) { > - perror("Cannot write to MMIO reg"); > - 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 +207,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 > > _______________________________________________ > amd-gfx mailing list > amd-gfx at lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/amd-gfx