[PATCH umr] Add ability to read/write SMC registers directly

Deucher, Alexander Alexander.Deucher at amd.com
Thu Jun 15 18:09:00 UTC 2017


> -----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, &reg) == 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, &reg) == 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


More information about the amd-gfx mailing list