Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Tom St Denis and committed by
Alex Deucher
c5a60ce8 40ee5888

+94
+2
drivers/gpu/drm/amd/amdgpu/amdgpu.h
··· 842 842 uint64_t (*get_gpu_clock_counter)(struct amdgpu_device *adev); 843 843 void (*select_se_sh)(struct amdgpu_device *adev, u32 se_num, u32 sh_num, u32 instance); 844 844 void (*read_wave_data)(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields); 845 + 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); 846 + void (*read_wave_sgprs)(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t start, uint32_t size, uint32_t *dst); 845 847 }; 846 848 847 849 struct amdgpu_gfx {
+67
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
··· 2985 2985 return result; 2986 2986 } 2987 2987 2988 + static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf, 2989 + size_t size, loff_t *pos) 2990 + { 2991 + struct amdgpu_device *adev = f->f_inode->i_private; 2992 + int r; 2993 + ssize_t result = 0; 2994 + uint32_t offset, se, sh, cu, wave, simd, thread, bank, *data; 2995 + 2996 + if (size & 3 || *pos & 3) 2997 + return -EINVAL; 2998 + 2999 + /* decode offset */ 3000 + offset = (*pos & 0xFFF); /* in dwords */ 3001 + se = ((*pos >> 12) & 0xFF); 3002 + sh = ((*pos >> 20) & 0xFF); 3003 + cu = ((*pos >> 28) & 0xFF); 3004 + wave = ((*pos >> 36) & 0xFF); 3005 + simd = ((*pos >> 44) & 0xFF); 3006 + thread = ((*pos >> 52) & 0xFF); 3007 + bank = ((*pos >> 60) & 1); 3008 + 3009 + data = kmalloc_array(1024, sizeof(*data), GFP_KERNEL); 3010 + if (!data) 3011 + return -ENOMEM; 3012 + 3013 + /* switch to the specific se/sh/cu */ 3014 + mutex_lock(&adev->grbm_idx_mutex); 3015 + amdgpu_gfx_select_se_sh(adev, se, sh, cu); 3016 + 3017 + if (bank == 0) { 3018 + if (adev->gfx.funcs->read_wave_vgprs) 3019 + adev->gfx.funcs->read_wave_vgprs(adev, simd, wave, thread, offset, size>>2, data); 3020 + } else { 3021 + if (adev->gfx.funcs->read_wave_sgprs) 3022 + adev->gfx.funcs->read_wave_sgprs(adev, simd, wave, offset, size>>2, data); 3023 + } 3024 + 3025 + amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); 3026 + mutex_unlock(&adev->grbm_idx_mutex); 3027 + 3028 + while (size) { 3029 + uint32_t value; 3030 + 3031 + value = data[offset++]; 3032 + r = put_user(value, (uint32_t *)buf); 3033 + if (r) { 3034 + result = r; 3035 + goto err; 3036 + } 3037 + 3038 + result += 4; 3039 + buf += 4; 3040 + size -= 4; 3041 + } 3042 + 3043 + err: 3044 + kfree(data); 3045 + return result; 3046 + } 3047 + 2988 3048 static const struct file_operations amdgpu_debugfs_regs_fops = { 2989 3049 .owner = THIS_MODULE, 2990 3050 .read = amdgpu_debugfs_regs_read, ··· 3087 3027 .read = amdgpu_debugfs_wave_read, 3088 3028 .llseek = default_llseek 3089 3029 }; 3030 + static const struct file_operations amdgpu_debugfs_gpr_fops = { 3031 + .owner = THIS_MODULE, 3032 + .read = amdgpu_debugfs_gpr_read, 3033 + .llseek = default_llseek 3034 + }; 3090 3035 3091 3036 static const struct file_operations *debugfs_regs[] = { 3092 3037 &amdgpu_debugfs_regs_fops, ··· 3101 3036 &amdgpu_debugfs_gca_config_fops, 3102 3037 &amdgpu_debugfs_sensors_fops, 3103 3038 &amdgpu_debugfs_wave_fops, 3039 + &amdgpu_debugfs_gpr_fops, 3104 3040 }; 3105 3041 3106 3042 static const char *debugfs_regs_names[] = { ··· 3112 3046 "amdgpu_gca_config", 3113 3047 "amdgpu_sensors", 3114 3048 "amdgpu_wave", 3049 + "amdgpu_gpr", 3115 3050 }; 3116 3051 3117 3052 static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev)
+25
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
··· 5184 5184 return RREG32(mmSQ_IND_DATA); 5185 5185 } 5186 5186 5187 + static void wave_read_regs(struct amdgpu_device *adev, uint32_t simd, 5188 + uint32_t wave, uint32_t thread, 5189 + uint32_t regno, uint32_t num, uint32_t *out) 5190 + { 5191 + WREG32(mmSQ_IND_INDEX, 5192 + (wave << SQ_IND_INDEX__WAVE_ID__SHIFT) | 5193 + (simd << SQ_IND_INDEX__SIMD_ID__SHIFT) | 5194 + (regno << SQ_IND_INDEX__INDEX__SHIFT) | 5195 + (thread << SQ_IND_INDEX__THREAD_ID__SHIFT) | 5196 + (SQ_IND_INDEX__FORCE_READ_MASK) | 5197 + (SQ_IND_INDEX__AUTO_INCR_MASK)); 5198 + while (num--) 5199 + *(out++) = RREG32(mmSQ_IND_DATA); 5200 + } 5201 + 5187 5202 static void gfx_v8_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields) 5188 5203 { 5189 5204 /* type 0 wave data */ ··· 5223 5208 dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0); 5224 5209 } 5225 5210 5211 + static void gfx_v8_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd, 5212 + uint32_t wave, uint32_t start, 5213 + uint32_t size, uint32_t *dst) 5214 + { 5215 + wave_read_regs( 5216 + adev, simd, wave, 0, 5217 + start + SQIND_WAVE_SGPRS_OFFSET, size, dst); 5218 + } 5219 + 5226 5220 5227 5221 static const struct amdgpu_gfx_funcs gfx_v8_0_gfx_funcs = { 5228 5222 .get_gpu_clock_counter = &gfx_v8_0_get_gpu_clock_counter, 5229 5223 .select_se_sh = &gfx_v8_0_select_se_sh, 5230 5224 .read_wave_data = &gfx_v8_0_read_wave_data, 5225 + .read_wave_sgprs = &gfx_v8_0_read_wave_sgprs, 5231 5226 }; 5232 5227 5233 5228 static int gfx_v8_0_early_init(void *handle)