[PATCH umr] Add ability to read/write SMC registers directly
Tom St Denis
tom.stdenis at amd.com
Thu Jun 15 16:54:17 UTC 2017
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");
+ 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
More information about the amd-gfx
mailing list