DF-3698 / fix.diff
diff --git a/sys/dev/drm/amd/amdgpu/gfx_v9_0.c b/sys/dev/drm/amd/amdgpu/gfx_v9_0.c index 1111111..3333333 100644 --- a/sys/dev/drm/amd/amdgpu/gfx_v9_0.c +++ b/sys/dev/drm/amd/amdgpu/gfx_v9_0.c @@ -934,8 +934,10 @@ static void gfx_v9_0_init_always_on_cu_mask(struct amdgpu_device *adev) else always_on_cu_num = 12; + /* cu_info->bitmap / ao_cu_bitmap are [4][4] (amdgpu_gfx.h) */ mutex_lock(&adev->grbm_idx_mutex); - for (i = 0; i < adev->gfx.config.max_shader_engines; i++) { - for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) { + for (i = 0; i < min(adev->gfx.config.max_shader_engines, 4u); i++) { + for (j = 0; j < min(adev->gfx.config.max_sh_per_se, 4u); j++) { mask = 1; cu_bitmap = 0; counter = 0; @@ -1457,6 +1459,15 @@ static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev) break; } + /* + * gfx.config geometry may come from the gpu_info firmware file or the + * VBIOS gfx_info table; neither is bounds-checked at parse time. + * Clamp to the fixed [4][4] dimensions of struct amdgpu_cu_info so the + * cu_info walkers cannot index out of bounds. + */ + adev->gfx.config.max_shader_engines = + min(adev->gfx.config.max_shader_engines, 4u); + adev->gfx.config.max_sh_per_se = + min(adev->gfx.config.max_sh_per_se, 4u); + adev->gfx.config.gb_addr_config = gb_addr_config; adev->gfx.config.gb_addr_config_fields.num_pipes = 1 << @@ -4987,8 +4998,10 @@ static int gfx_v9_0_get_cu_info(struct amdgpu_device *adev, amdgpu_gfx_parse_disable_cu(disable_masks, 4, 2); mutex_lock(&adev->grbm_idx_mutex); - for (i = 0; i < adev->gfx.config.max_shader_engines; i++) { - for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) { + /* cu_info->bitmap / ao_cu_bitmap are [4][4] (amdgpu_gfx.h) */ + for (i = 0; i < min(adev->gfx.config.max_shader_engines, 4u); i++) { + for (j = 0; j < min(adev->gfx.config.max_sh_per_se, 4u); j++) { mask = 1; ao_bitmap = 0; counter = 0; |