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

drm/amdgpu: Fix for drm buddy memory corruption

User reported gpu page fault when running graphics applications
and in some cases garbaged graphics are observed as soon as X
starts. This patch fixes all the issues.

Fixed the typecast issue for fpfn and lpfn variables, thus
preventing the overflow problem which resolves the memory
corruption.

Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com>
Reported-by: Mike Lothian <mike@fireburn.co.uk>
Tested-by: Mike Lothian <mike@fireburn.co.uk>
Link: https://patchwork.freedesktop.org/patch/msgid/20220714101214.7620-1-Arunpravin.PaneerSelvam@amd.com
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Christian König <christian.koenig@amd.com>

authored by

Arunpravin Paneer Selvam and committed by
Christian König
6f2c8d5f c96cfaf8

+9 -9
+8 -8
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
··· 395 395 unsigned long pages_per_block; 396 396 int r; 397 397 398 - lpfn = place->lpfn << PAGE_SHIFT; 398 + lpfn = (u64)place->lpfn << PAGE_SHIFT; 399 399 if (!lpfn) 400 400 lpfn = man->size; 401 401 402 - fpfn = place->fpfn << PAGE_SHIFT; 402 + fpfn = (u64)place->fpfn << PAGE_SHIFT; 403 403 404 404 max_bytes = adev->gmc.mc_vram_size; 405 405 if (tbo->type != ttm_bo_type_kernel) ··· 439 439 /* Allocate blocks in desired range */ 440 440 vres->flags |= DRM_BUDDY_RANGE_ALLOCATION; 441 441 442 - remaining_size = vres->base.num_pages << PAGE_SHIFT; 442 + remaining_size = (u64)vres->base.num_pages << PAGE_SHIFT; 443 443 444 444 mutex_lock(&mgr->lock); 445 445 while (remaining_size) { 446 446 if (tbo->page_alignment) 447 - min_block_size = tbo->page_alignment << PAGE_SHIFT; 447 + min_block_size = (u64)tbo->page_alignment << PAGE_SHIFT; 448 448 else 449 449 min_block_size = mgr->default_page_size; 450 450 ··· 453 453 /* Limit maximum size to 2GiB due to SG table limitations */ 454 454 size = min(remaining_size, 2ULL << 30); 455 455 456 - if (size >= pages_per_block << PAGE_SHIFT) 457 - min_block_size = pages_per_block << PAGE_SHIFT; 456 + if (size >= (u64)pages_per_block << PAGE_SHIFT) 457 + min_block_size = (u64)pages_per_block << PAGE_SHIFT; 458 458 459 459 cur_size = size; 460 460 461 - if (fpfn + size != place->lpfn << PAGE_SHIFT) { 461 + if (fpfn + size != (u64)place->lpfn << PAGE_SHIFT) { 462 462 /* 463 463 * Except for actual range allocation, modify the size and 464 464 * min_block_size conforming to continuous flag enablement ··· 498 498 LIST_HEAD(temp); 499 499 500 500 trim_list = &vres->blocks; 501 - original_size = vres->base.num_pages << PAGE_SHIFT; 501 + original_size = (u64)vres->base.num_pages << PAGE_SHIFT; 502 502 503 503 /* 504 504 * If size value is rounded up to min_block_size, trim the last
+1 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h
··· 50 50 51 51 static inline u64 amdgpu_vram_mgr_block_size(struct drm_buddy_block *block) 52 52 { 53 - return PAGE_SIZE << drm_buddy_block_order(block); 53 + return (u64)PAGE_SIZE << drm_buddy_block_order(block); 54 54 } 55 55 56 56 static inline struct amdgpu_vram_mgr_resource *