drm/amd/amdgpu: Add debugfs support for reading GPRs (v2)
Implemented for SGPRs for GFX v8 initially.
(v2) cleanup minor whitespace and remove sanity check and
     addressing is in dwords not bytes
Signed-off-by: Tom St Denis <tom.stdenis@amd.com>
Acked-by: Edward O'Callaghan <funfunctor@folklore1984.net>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
			
			
This commit is contained in:
		
							parent
							
								
									40ee5888fa
								
							
						
					
					
						commit
						c5a60ce81b
					
				| @ -842,6 +842,8 @@ struct amdgpu_gfx_funcs { | ||||
| 	uint64_t (*get_gpu_clock_counter)(struct amdgpu_device *adev); | ||||
| 	void (*select_se_sh)(struct amdgpu_device *adev, u32 se_num, u32 sh_num, u32 instance); | ||||
| 	void (*read_wave_data)(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields); | ||||
| 	void (*read_wave_vgprs)(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t thread, uint32_t start, uint32_t size, uint32_t *dst); | ||||
| 	void (*read_wave_sgprs)(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t start, uint32_t size, uint32_t *dst); | ||||
| }; | ||||
| 
 | ||||
| struct amdgpu_gfx { | ||||
|  | ||||
| @ -2985,6 +2985,66 @@ static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf, | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf, | ||||
| 					size_t size, loff_t *pos) | ||||
| { | ||||
| 	struct amdgpu_device *adev = f->f_inode->i_private; | ||||
| 	int r; | ||||
| 	ssize_t result = 0; | ||||
| 	uint32_t offset, se, sh, cu, wave, simd, thread, bank, *data; | ||||
| 
 | ||||
| 	if (size & 3 || *pos & 3) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	/* decode offset */ | ||||
| 	offset = (*pos & 0xFFF);       /* in dwords */ | ||||
| 	se = ((*pos >> 12) & 0xFF); | ||||
| 	sh = ((*pos >> 20) & 0xFF); | ||||
| 	cu = ((*pos >> 28) & 0xFF); | ||||
| 	wave = ((*pos >> 36) & 0xFF); | ||||
| 	simd = ((*pos >> 44) & 0xFF); | ||||
| 	thread = ((*pos >> 52) & 0xFF); | ||||
| 	bank = ((*pos >> 60) & 1); | ||||
| 
 | ||||
| 	data = kmalloc_array(1024, sizeof(*data), GFP_KERNEL); | ||||
| 	if (!data) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	/* switch to the specific se/sh/cu */ | ||||
| 	mutex_lock(&adev->grbm_idx_mutex); | ||||
| 	amdgpu_gfx_select_se_sh(adev, se, sh, cu); | ||||
| 
 | ||||
| 	if (bank == 0) { | ||||
| 		if (adev->gfx.funcs->read_wave_vgprs) | ||||
| 			adev->gfx.funcs->read_wave_vgprs(adev, simd, wave, thread, offset, size>>2, data); | ||||
| 	} else { | ||||
| 		if (adev->gfx.funcs->read_wave_sgprs) | ||||
| 			adev->gfx.funcs->read_wave_sgprs(adev, simd, wave, offset, size>>2, data); | ||||
| 	} | ||||
| 
 | ||||
| 	amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); | ||||
| 	mutex_unlock(&adev->grbm_idx_mutex); | ||||
| 
 | ||||
| 	while (size) { | ||||
| 		uint32_t value; | ||||
| 
 | ||||
| 		value = data[offset++]; | ||||
| 		r = put_user(value, (uint32_t *)buf); | ||||
| 		if (r) { | ||||
| 			result = r; | ||||
| 			goto err; | ||||
| 		} | ||||
| 
 | ||||
| 		result += 4; | ||||
| 		buf += 4; | ||||
| 		size -= 4; | ||||
| 	} | ||||
| 
 | ||||
| err: | ||||
| 	kfree(data); | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| static const struct file_operations amdgpu_debugfs_regs_fops = { | ||||
| 	.owner = THIS_MODULE, | ||||
| 	.read = amdgpu_debugfs_regs_read, | ||||
| @ -3027,6 +3087,11 @@ static const struct file_operations amdgpu_debugfs_wave_fops = { | ||||
| 	.read = amdgpu_debugfs_wave_read, | ||||
| 	.llseek = default_llseek | ||||
| }; | ||||
| static const struct file_operations amdgpu_debugfs_gpr_fops = { | ||||
| 	.owner = THIS_MODULE, | ||||
| 	.read = amdgpu_debugfs_gpr_read, | ||||
| 	.llseek = default_llseek | ||||
| }; | ||||
| 
 | ||||
| static const struct file_operations *debugfs_regs[] = { | ||||
| 	&amdgpu_debugfs_regs_fops, | ||||
| @ -3036,6 +3101,7 @@ static const struct file_operations *debugfs_regs[] = { | ||||
| 	&amdgpu_debugfs_gca_config_fops, | ||||
| 	&amdgpu_debugfs_sensors_fops, | ||||
| 	&amdgpu_debugfs_wave_fops, | ||||
| 	&amdgpu_debugfs_gpr_fops, | ||||
| }; | ||||
| 
 | ||||
| static const char *debugfs_regs_names[] = { | ||||
| @ -3046,6 +3112,7 @@ static const char *debugfs_regs_names[] = { | ||||
| 	"amdgpu_gca_config", | ||||
| 	"amdgpu_sensors", | ||||
| 	"amdgpu_wave", | ||||
| 	"amdgpu_gpr", | ||||
| }; | ||||
| 
 | ||||
| static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) | ||||
|  | ||||
| @ -5184,6 +5184,21 @@ static uint32_t wave_read_ind(struct amdgpu_device *adev, uint32_t simd, uint32_ | ||||
| 	return RREG32(mmSQ_IND_DATA); | ||||
| } | ||||
| 
 | ||||
| static void wave_read_regs(struct amdgpu_device *adev, uint32_t simd, | ||||
| 			   uint32_t wave, uint32_t thread, | ||||
| 			   uint32_t regno, uint32_t num, uint32_t *out) | ||||
| { | ||||
| 	WREG32(mmSQ_IND_INDEX, | ||||
| 		(wave << SQ_IND_INDEX__WAVE_ID__SHIFT) | | ||||
| 		(simd << SQ_IND_INDEX__SIMD_ID__SHIFT) | | ||||
| 		(regno << SQ_IND_INDEX__INDEX__SHIFT) | | ||||
| 		(thread << SQ_IND_INDEX__THREAD_ID__SHIFT) | | ||||
| 		(SQ_IND_INDEX__FORCE_READ_MASK) | | ||||
| 		(SQ_IND_INDEX__AUTO_INCR_MASK)); | ||||
| 	while (num--) | ||||
| 		*(out++) = RREG32(mmSQ_IND_DATA); | ||||
| } | ||||
| 
 | ||||
| static void gfx_v8_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields) | ||||
| { | ||||
| 	/* type 0 wave data */ | ||||
| @ -5208,11 +5223,21 @@ static void gfx_v8_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, u | ||||
| 	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0); | ||||
| } | ||||
| 
 | ||||
| static void gfx_v8_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd, | ||||
| 				     uint32_t wave, uint32_t start, | ||||
| 				     uint32_t size, uint32_t *dst) | ||||
| { | ||||
| 	wave_read_regs( | ||||
| 		adev, simd, wave, 0, | ||||
| 		start + SQIND_WAVE_SGPRS_OFFSET, size, dst); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static const struct amdgpu_gfx_funcs gfx_v8_0_gfx_funcs = { | ||||
| 	.get_gpu_clock_counter = &gfx_v8_0_get_gpu_clock_counter, | ||||
| 	.select_se_sh = &gfx_v8_0_select_se_sh, | ||||
| 	.read_wave_data = &gfx_v8_0_read_wave_data, | ||||
| 	.read_wave_sgprs = &gfx_v8_0_read_wave_sgprs, | ||||
| }; | ||||
| 
 | ||||
| static int gfx_v8_0_early_init(void *handle) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user