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

drm/amdkfd: fix stack size in svm_range_validate_and_map

Allocate large local variable on heap to avoid exceeding the
stack size:
drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_svm.c: In function ‘svm_range_validate_and_map’:
drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_svm.c:1690:1: warning: the frame size of 2360 bytes is larger than 2048 bytes [-Wframe-larger-than=]

Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

+33 -23
+33 -23
drivers/gpu/drm/amd/amdkfd/kfd_svm.c
··· 1554 1554 struct svm_range *prange, int32_t gpuidx, 1555 1555 bool intr, bool wait, bool flush_tlb) 1556 1556 { 1557 - struct svm_validate_context ctx; 1557 + struct svm_validate_context *ctx; 1558 1558 unsigned long start, end, addr; 1559 1559 struct kfd_process *p; 1560 1560 void *owner; 1561 1561 int32_t idx; 1562 1562 int r = 0; 1563 1563 1564 - ctx.process = container_of(prange->svms, struct kfd_process, svms); 1565 - ctx.prange = prange; 1566 - ctx.intr = intr; 1564 + ctx = kzalloc(sizeof(struct svm_validate_context), GFP_KERNEL); 1565 + if (!ctx) 1566 + return -ENOMEM; 1567 + ctx->process = container_of(prange->svms, struct kfd_process, svms); 1568 + ctx->prange = prange; 1569 + ctx->intr = intr; 1567 1570 1568 1571 if (gpuidx < MAX_GPU_INSTANCE) { 1569 - bitmap_zero(ctx.bitmap, MAX_GPU_INSTANCE); 1570 - bitmap_set(ctx.bitmap, gpuidx, 1); 1571 - } else if (ctx.process->xnack_enabled) { 1572 - bitmap_copy(ctx.bitmap, prange->bitmap_aip, MAX_GPU_INSTANCE); 1572 + bitmap_zero(ctx->bitmap, MAX_GPU_INSTANCE); 1573 + bitmap_set(ctx->bitmap, gpuidx, 1); 1574 + } else if (ctx->process->xnack_enabled) { 1575 + bitmap_copy(ctx->bitmap, prange->bitmap_aip, MAX_GPU_INSTANCE); 1573 1576 1574 1577 /* If prefetch range to GPU, or GPU retry fault migrate range to 1575 1578 * GPU, which has ACCESS attribute to the range, create mapping 1576 1579 * on that GPU. 1577 1580 */ 1578 1581 if (prange->actual_loc) { 1579 - gpuidx = kfd_process_gpuidx_from_gpuid(ctx.process, 1582 + gpuidx = kfd_process_gpuidx_from_gpuid(ctx->process, 1580 1583 prange->actual_loc); 1581 1584 if (gpuidx < 0) { 1582 1585 WARN_ONCE(1, "failed get device by id 0x%x\n", 1583 1586 prange->actual_loc); 1584 - return -EINVAL; 1587 + r = -EINVAL; 1588 + goto free_ctx; 1585 1589 } 1586 1590 if (test_bit(gpuidx, prange->bitmap_access)) 1587 - bitmap_set(ctx.bitmap, gpuidx, 1); 1591 + bitmap_set(ctx->bitmap, gpuidx, 1); 1588 1592 } 1589 1593 } else { 1590 - bitmap_or(ctx.bitmap, prange->bitmap_access, 1594 + bitmap_or(ctx->bitmap, prange->bitmap_access, 1591 1595 prange->bitmap_aip, MAX_GPU_INSTANCE); 1592 1596 } 1593 1597 1594 - if (bitmap_empty(ctx.bitmap, MAX_GPU_INSTANCE)) { 1595 - if (!prange->mapped_to_gpu) 1596 - return 0; 1598 + if (bitmap_empty(ctx->bitmap, MAX_GPU_INSTANCE)) { 1599 + if (!prange->mapped_to_gpu) { 1600 + r = 0; 1601 + goto free_ctx; 1602 + } 1597 1603 1598 - bitmap_copy(ctx.bitmap, prange->bitmap_access, MAX_GPU_INSTANCE); 1604 + bitmap_copy(ctx->bitmap, prange->bitmap_access, MAX_GPU_INSTANCE); 1599 1605 } 1600 1606 1601 1607 if (prange->actual_loc && !prange->ttm_res) { ··· 1609 1603 * svm_migrate_ram_to_vram after allocating a BO. 1610 1604 */ 1611 1605 WARN_ONCE(1, "VRAM BO missing during validation\n"); 1612 - return -EINVAL; 1606 + r = -EINVAL; 1607 + goto free_ctx; 1613 1608 } 1614 1609 1615 - svm_range_reserve_bos(&ctx); 1610 + svm_range_reserve_bos(ctx); 1616 1611 1617 1612 p = container_of(prange->svms, struct kfd_process, svms); 1618 - owner = kfd_svm_page_owner(p, find_first_bit(ctx.bitmap, 1613 + owner = kfd_svm_page_owner(p, find_first_bit(ctx->bitmap, 1619 1614 MAX_GPU_INSTANCE)); 1620 - for_each_set_bit(idx, ctx.bitmap, MAX_GPU_INSTANCE) { 1615 + for_each_set_bit(idx, ctx->bitmap, MAX_GPU_INSTANCE) { 1621 1616 if (kfd_svm_page_owner(p, idx) != owner) { 1622 1617 owner = NULL; 1623 1618 break; ··· 1655 1648 } 1656 1649 1657 1650 offset = (addr - start) >> PAGE_SHIFT; 1658 - r = svm_range_dma_map(prange, ctx.bitmap, offset, npages, 1651 + r = svm_range_dma_map(prange, ctx->bitmap, offset, npages, 1659 1652 hmm_range->hmm_pfns); 1660 1653 if (r) { 1661 1654 pr_debug("failed %d to dma map range\n", r); ··· 1675 1668 } 1676 1669 1677 1670 r = svm_range_map_to_gpus(prange, offset, npages, readonly, 1678 - ctx.bitmap, wait, flush_tlb); 1671 + ctx->bitmap, wait, flush_tlb); 1679 1672 1680 1673 unlock_out: 1681 1674 svm_range_unlock(prange); ··· 1689 1682 } 1690 1683 1691 1684 unreserve_out: 1692 - svm_range_unreserve_bos(&ctx); 1685 + svm_range_unreserve_bos(ctx); 1693 1686 1694 1687 if (!r) 1695 1688 prange->validate_timestamp = ktime_get_boottime(); 1689 + 1690 + free_ctx: 1691 + kfree(ctx); 1696 1692 1697 1693 return r; 1698 1694 }