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

drm/amdkfd: Use partial migrations in GPU page faults

This patch implements partial migration in gpu page fault according to migration
granularity(default 2MB) and not split svm range in cpu page fault handling.
A svm range may include pages from both system ram and vram of one gpu now.
These chagnes are expected to improve migration performance and reduce mmu
callback and TLB flush workloads.

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

authored by

Xiaogang Chen and committed by
Alex Deucher
dc427a47 de5e73dc

+160 -85
+86 -64
drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
··· 442 442 goto out_free; 443 443 } 444 444 if (cpages != npages) 445 - pr_debug("partial migration, 0x%lx/0x%llx pages migrated\n", 445 + pr_debug("partial migration, 0x%lx/0x%llx pages collected\n", 446 446 cpages, npages); 447 447 else 448 - pr_debug("0x%lx pages migrated\n", cpages); 448 + pr_debug("0x%lx pages collected\n", cpages); 449 449 450 450 r = svm_migrate_copy_to_vram(node, prange, &migrate, &mfence, scratch, ttm_res_offset); 451 451 migrate_vma_pages(&migrate); ··· 479 479 * svm_migrate_ram_to_vram - migrate svm range from system to device 480 480 * @prange: range structure 481 481 * @best_loc: the device to migrate to 482 + * @start_mgr: start page to migrate 483 + * @last_mgr: last page to migrate 482 484 * @mm: the process mm structure 483 485 * @trigger: reason of migration 484 486 * ··· 491 489 */ 492 490 static int 493 491 svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc, 492 + unsigned long start_mgr, unsigned long last_mgr, 494 493 struct mm_struct *mm, uint32_t trigger) 495 494 { 496 495 unsigned long addr, start, end; ··· 501 498 unsigned long cpages = 0; 502 499 long r = 0; 503 500 504 - if (prange->actual_loc == best_loc) { 505 - pr_debug("svms 0x%p [0x%lx 0x%lx] already on best_loc 0x%x\n", 506 - prange->svms, prange->start, prange->last, best_loc); 501 + if (!best_loc) { 502 + pr_debug("svms 0x%p [0x%lx 0x%lx] migrate to sys ram\n", 503 + prange->svms, start_mgr, last_mgr); 507 504 return 0; 505 + } 506 + 507 + if (start_mgr < prange->start || last_mgr > prange->last) { 508 + pr_debug("range [0x%lx 0x%lx] out prange [0x%lx 0x%lx]\n", 509 + start_mgr, last_mgr, prange->start, prange->last); 510 + return -EFAULT; 508 511 } 509 512 510 513 node = svm_range_get_node_by_id(prange, best_loc); ··· 519 510 return -ENODEV; 520 511 } 521 512 522 - pr_debug("svms 0x%p [0x%lx 0x%lx] to gpu 0x%x\n", prange->svms, 523 - prange->start, prange->last, best_loc); 513 + pr_debug("svms 0x%p [0x%lx 0x%lx] in [0x%lx 0x%lx] to gpu 0x%x\n", 514 + prange->svms, start_mgr, last_mgr, prange->start, prange->last, 515 + best_loc); 524 516 525 - start = prange->start << PAGE_SHIFT; 526 - end = (prange->last + 1) << PAGE_SHIFT; 517 + start = start_mgr << PAGE_SHIFT; 518 + end = (last_mgr + 1) << PAGE_SHIFT; 527 519 528 520 r = svm_range_vram_node_new(node, prange, true); 529 521 if (r) { ··· 554 544 555 545 if (cpages) { 556 546 prange->actual_loc = best_loc; 557 - svm_range_dma_unmap(prange); 558 - } else { 547 + prange->vram_pages = prange->vram_pages + cpages; 548 + } else if (!prange->actual_loc) { 549 + /* if no page migrated and all pages from prange are at 550 + * sys ram drop svm_bo got from svm_range_vram_node_new 551 + */ 559 552 svm_range_vram_node_free(prange); 560 553 } 561 554 ··· 676 663 * Context: Process context, caller hold mmap read lock, prange->migrate_mutex 677 664 * 678 665 * Return: 679 - * 0 - success with all pages migrated 680 666 * negative values - indicate error 681 - * positive values - partial migration, number of pages not migrated 667 + * positive values or zero - number of pages got migrated 682 668 */ 683 669 static long 684 670 svm_migrate_vma_to_ram(struct kfd_node *node, struct svm_range *prange, ··· 688 676 uint64_t npages = (end - start) >> PAGE_SHIFT; 689 677 unsigned long upages = npages; 690 678 unsigned long cpages = 0; 679 + unsigned long mpages = 0; 691 680 struct amdgpu_device *adev = node->adev; 692 681 struct kfd_process_device *pdd; 693 682 struct dma_fence *mfence = NULL; ··· 738 725 goto out_free; 739 726 } 740 727 if (cpages != npages) 741 - pr_debug("partial migration, 0x%lx/0x%llx pages migrated\n", 728 + pr_debug("partial migration, 0x%lx/0x%llx pages collected\n", 742 729 cpages, npages); 743 730 else 744 - pr_debug("0x%lx pages migrated\n", cpages); 731 + pr_debug("0x%lx pages collected\n", cpages); 745 732 746 733 r = svm_migrate_copy_to_ram(adev, prange, &migrate, &mfence, 747 734 scratch, npages); ··· 764 751 kvfree(buf); 765 752 out: 766 753 if (!r && cpages) { 754 + mpages = cpages - upages; 767 755 pdd = svm_range_get_pdd_by_node(prange, node); 768 756 if (pdd) 769 - WRITE_ONCE(pdd->page_out, pdd->page_out + cpages); 757 + WRITE_ONCE(pdd->page_out, pdd->page_out + mpages); 770 758 } 771 - return r ? r : upages; 759 + 760 + return r ? r : mpages; 772 761 } 773 762 774 763 /** 775 764 * svm_migrate_vram_to_ram - migrate svm range from device to system 776 765 * @prange: range structure 777 766 * @mm: process mm, use current->mm if NULL 767 + * @start_mgr: start page need be migrated to sys ram 768 + * @last_mgr: last page need be migrated to sys ram 778 769 * @trigger: reason of migration 779 770 * @fault_page: is from vmf->page, svm_migrate_to_ram(), this is CPU page fault callback 780 771 * ··· 788 771 * 0 - OK, otherwise error code 789 772 */ 790 773 int svm_migrate_vram_to_ram(struct svm_range *prange, struct mm_struct *mm, 774 + unsigned long start_mgr, unsigned long last_mgr, 791 775 uint32_t trigger, struct page *fault_page) 792 776 { 793 777 struct kfd_node *node; ··· 796 778 unsigned long addr; 797 779 unsigned long start; 798 780 unsigned long end; 799 - unsigned long upages = 0; 781 + unsigned long mpages = 0; 800 782 long r = 0; 801 783 784 + /* this pragne has no any vram page to migrate to sys ram */ 802 785 if (!prange->actual_loc) { 803 786 pr_debug("[0x%lx 0x%lx] already migrated to ram\n", 804 787 prange->start, prange->last); 805 788 return 0; 789 + } 790 + 791 + if (start_mgr < prange->start || last_mgr > prange->last) { 792 + pr_debug("range [0x%lx 0x%lx] out prange [0x%lx 0x%lx]\n", 793 + start_mgr, last_mgr, prange->start, prange->last); 794 + return -EFAULT; 806 795 } 807 796 808 797 node = svm_range_get_node_by_id(prange, prange->actual_loc); ··· 818 793 return -ENODEV; 819 794 } 820 795 pr_debug("svms 0x%p prange 0x%p [0x%lx 0x%lx] from gpu 0x%x to ram\n", 821 - prange->svms, prange, prange->start, prange->last, 796 + prange->svms, prange, start_mgr, last_mgr, 822 797 prange->actual_loc); 823 798 824 - start = prange->start << PAGE_SHIFT; 825 - end = (prange->last + 1) << PAGE_SHIFT; 799 + start = start_mgr << PAGE_SHIFT; 800 + end = (last_mgr + 1) << PAGE_SHIFT; 826 801 827 802 for (addr = start; addr < end;) { 828 803 unsigned long next; ··· 841 816 pr_debug("failed %ld to migrate prange %p\n", r, prange); 842 817 break; 843 818 } else { 844 - upages += r; 819 + mpages += r; 845 820 } 846 821 addr = next; 847 822 } 848 823 849 - if (r >= 0 && !upages) { 850 - svm_range_vram_node_free(prange); 851 - prange->actual_loc = 0; 824 + if (r >= 0) { 825 + prange->vram_pages -= mpages; 826 + 827 + /* prange does not have vram page set its actual_loc to system 828 + * and drop its svm_bo ref 829 + */ 830 + if (prange->vram_pages == 0 && prange->ttm_res) { 831 + prange->actual_loc = 0; 832 + svm_range_vram_node_free(prange); 833 + } 852 834 } 853 835 854 836 return r < 0 ? r : 0; ··· 865 833 * svm_migrate_vram_to_vram - migrate svm range from device to device 866 834 * @prange: range structure 867 835 * @best_loc: the device to migrate to 836 + * @start: start page need be migrated to sys ram 837 + * @last: last page need be migrated to sys ram 868 838 * @mm: process mm, use current->mm if NULL 869 839 * @trigger: reason of migration 870 840 * 871 841 * Context: Process context, caller hold mmap read lock, svms lock, prange lock 842 + * 843 + * migrate all vram pages in prange to sys ram, then migrate 844 + * [start, last] pages from sys ram to gpu node best_loc. 872 845 * 873 846 * Return: 874 847 * 0 - OK, otherwise error code 875 848 */ 876 849 static int 877 850 svm_migrate_vram_to_vram(struct svm_range *prange, uint32_t best_loc, 878 - struct mm_struct *mm, uint32_t trigger) 851 + unsigned long start, unsigned long last, 852 + struct mm_struct *mm, uint32_t trigger) 879 853 { 880 854 int r, retries = 3; 881 855 ··· 893 855 pr_debug("from gpu 0x%x to gpu 0x%x\n", prange->actual_loc, best_loc); 894 856 895 857 do { 896 - r = svm_migrate_vram_to_ram(prange, mm, trigger, NULL); 858 + r = svm_migrate_vram_to_ram(prange, mm, prange->start, prange->last, 859 + trigger, NULL); 897 860 if (r) 898 861 return r; 899 862 } while (prange->actual_loc && --retries); ··· 902 863 if (prange->actual_loc) 903 864 return -EDEADLK; 904 865 905 - return svm_migrate_ram_to_vram(prange, best_loc, mm, trigger); 866 + return svm_migrate_ram_to_vram(prange, best_loc, start, last, mm, trigger); 906 867 } 907 868 908 869 int 909 870 svm_migrate_to_vram(struct svm_range *prange, uint32_t best_loc, 910 - struct mm_struct *mm, uint32_t trigger) 871 + unsigned long start, unsigned long last, 872 + struct mm_struct *mm, uint32_t trigger) 911 873 { 912 - if (!prange->actual_loc) 913 - return svm_migrate_ram_to_vram(prange, best_loc, mm, trigger); 874 + if (!prange->actual_loc || prange->actual_loc == best_loc) 875 + return svm_migrate_ram_to_vram(prange, best_loc, start, last, 876 + mm, trigger); 877 + 914 878 else 915 - return svm_migrate_vram_to_vram(prange, best_loc, mm, trigger); 879 + return svm_migrate_vram_to_vram(prange, best_loc, start, last, 880 + mm, trigger); 916 881 917 882 } 918 883 ··· 932 889 */ 933 890 static vm_fault_t svm_migrate_to_ram(struct vm_fault *vmf) 934 891 { 892 + unsigned long start, last, size; 935 893 unsigned long addr = vmf->address; 936 894 struct svm_range_bo *svm_bo; 937 - enum svm_work_list_ops op; 938 - struct svm_range *parent; 939 895 struct svm_range *prange; 940 896 struct kfd_process *p; 941 897 struct mm_struct *mm; ··· 971 929 972 930 mutex_lock(&p->svms.lock); 973 931 974 - prange = svm_range_from_addr(&p->svms, addr, &parent); 932 + prange = svm_range_from_addr(&p->svms, addr, NULL); 975 933 if (!prange) { 976 934 pr_debug("failed get range svms 0x%p addr 0x%lx\n", &p->svms, addr); 977 935 r = -EFAULT; 978 936 goto out_unlock_svms; 979 937 } 980 938 981 - mutex_lock(&parent->migrate_mutex); 982 - if (prange != parent) 983 - mutex_lock_nested(&prange->migrate_mutex, 1); 939 + mutex_lock(&prange->migrate_mutex); 984 940 985 941 if (!prange->actual_loc) 986 942 goto out_unlock_prange; 987 943 988 - svm_range_lock(parent); 989 - if (prange != parent) 990 - mutex_lock_nested(&prange->lock, 1); 991 - r = svm_range_split_by_granularity(p, mm, addr, parent, prange); 992 - if (prange != parent) 993 - mutex_unlock(&prange->lock); 994 - svm_range_unlock(parent); 995 - if (r) { 996 - pr_debug("failed %d to split range by granularity\n", r); 997 - goto out_unlock_prange; 998 - } 944 + /* Align migration range start and size to granularity size */ 945 + size = 1UL << prange->granularity; 946 + start = max(ALIGN_DOWN(addr, size), prange->start); 947 + last = min(ALIGN(addr + 1, size) - 1, prange->last); 999 948 1000 - r = svm_migrate_vram_to_ram(prange, vmf->vma->vm_mm, 1001 - KFD_MIGRATE_TRIGGER_PAGEFAULT_CPU, 1002 - vmf->page); 949 + r = svm_migrate_vram_to_ram(prange, vmf->vma->vm_mm, start, last, 950 + KFD_MIGRATE_TRIGGER_PAGEFAULT_CPU, vmf->page); 1003 951 if (r) 1004 952 pr_debug("failed %d migrate svms 0x%p range 0x%p [0x%lx 0x%lx]\n", 1005 - r, prange->svms, prange, prange->start, prange->last); 1006 - 1007 - /* xnack on, update mapping on GPUs with ACCESS_IN_PLACE */ 1008 - if (p->xnack_enabled && parent == prange) 1009 - op = SVM_OP_UPDATE_RANGE_NOTIFIER_AND_MAP; 1010 - else 1011 - op = SVM_OP_UPDATE_RANGE_NOTIFIER; 1012 - svm_range_add_list_work(&p->svms, parent, mm, op); 1013 - schedule_deferred_list_work(&p->svms); 953 + r, prange->svms, prange, start, last); 1014 954 1015 955 out_unlock_prange: 1016 - if (prange != parent) 1017 - mutex_unlock(&prange->migrate_mutex); 1018 - mutex_unlock(&parent->migrate_mutex); 956 + mutex_unlock(&prange->migrate_mutex); 1019 957 out_unlock_svms: 1020 958 mutex_unlock(&p->svms.lock); 1021 959 out_unref_process:
+5 -1
drivers/gpu/drm/amd/amdkfd/kfd_migrate.h
··· 41 41 }; 42 42 43 43 int svm_migrate_to_vram(struct svm_range *prange, uint32_t best_loc, 44 + unsigned long start, unsigned long last, 44 45 struct mm_struct *mm, uint32_t trigger); 46 + 45 47 int svm_migrate_vram_to_ram(struct svm_range *prange, struct mm_struct *mm, 46 - uint32_t trigger, struct page *fault_page); 48 + unsigned long start, unsigned long last, 49 + uint32_t trigger, struct page *fault_page); 50 + 47 51 unsigned long 48 52 svm_migrate_addr_to_pfn(struct amdgpu_device *adev, unsigned long addr); 49 53
+64 -19
drivers/gpu/drm/amd/amdkfd/kfd_svm.c
··· 158 158 static int 159 159 svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange, 160 160 unsigned long offset, unsigned long npages, 161 - unsigned long *hmm_pfns, uint32_t gpuidx) 161 + unsigned long *hmm_pfns, uint32_t gpuidx, uint64_t *vram_pages) 162 162 { 163 163 enum dma_data_direction dir = DMA_BIDIRECTIONAL; 164 164 dma_addr_t *addr = prange->dma_addr[gpuidx]; 165 165 struct device *dev = adev->dev; 166 166 struct page *page; 167 + uint64_t vram_pages_dev; 167 168 int i, r; 168 169 169 170 if (!addr) { ··· 174 173 prange->dma_addr[gpuidx] = addr; 175 174 } 176 175 176 + vram_pages_dev = 0; 177 177 addr += offset; 178 178 for (i = 0; i < npages; i++) { 179 179 if (svm_is_valid_dma_mapping_addr(dev, addr[i])) ··· 184 182 if (is_zone_device_page(page)) { 185 183 struct amdgpu_device *bo_adev = prange->svm_bo->node->adev; 186 184 185 + vram_pages_dev++; 187 186 addr[i] = (hmm_pfns[i] << PAGE_SHIFT) + 188 187 bo_adev->vm_manager.vram_base_offset - 189 188 bo_adev->kfd.pgmap.range.start; ··· 201 198 pr_debug_ratelimited("dma mapping 0x%llx for page addr 0x%lx\n", 202 199 addr[i] >> PAGE_SHIFT, page_to_pfn(page)); 203 200 } 201 + *vram_pages = vram_pages_dev; 204 202 return 0; 205 203 } 206 204 207 205 static int 208 206 svm_range_dma_map(struct svm_range *prange, unsigned long *bitmap, 209 207 unsigned long offset, unsigned long npages, 210 - unsigned long *hmm_pfns) 208 + unsigned long *hmm_pfns, uint64_t *vram_pages) 211 209 { 212 210 struct kfd_process *p; 213 211 uint32_t gpuidx; ··· 227 223 } 228 224 229 225 r = svm_range_dma_map_dev(pdd->dev->adev, prange, offset, npages, 230 - hmm_pfns, gpuidx); 226 + hmm_pfns, gpuidx, vram_pages); 231 227 if (r) 232 228 break; 233 229 } ··· 353 349 INIT_LIST_HEAD(&prange->child_list); 354 350 atomic_set(&prange->invalid, 0); 355 351 prange->validate_timestamp = 0; 352 + prange->vram_pages = 0; 356 353 mutex_init(&prange->migrate_mutex); 357 354 mutex_init(&prange->lock); 358 355 ··· 400 395 prange->start, prange->last); 401 396 mutex_lock(&prange->lock); 402 397 prange->svm_bo = NULL; 398 + /* prange should not hold vram page now */ 399 + WARN_ON(prange->actual_loc); 403 400 mutex_unlock(&prange->lock); 404 401 405 402 spin_lock(&svm_bo->list_lock); ··· 981 974 982 975 new->svm_bo = svm_range_bo_ref(old->svm_bo); 983 976 new->ttm_res = old->ttm_res; 977 + 978 + /* set new's vram_pages as old range's now, the acurate vram_pages 979 + * will be updated during mapping 980 + */ 981 + new->vram_pages = min(old->vram_pages, new->npages); 984 982 985 983 spin_lock(&new->svm_bo->list_lock); 986 984 list_add(&new->svm_bo_list, &new->svm_bo->range_list); ··· 1624 1612 struct svm_validate_context *ctx; 1625 1613 unsigned long start, end, addr; 1626 1614 struct kfd_process *p; 1615 + uint64_t vram_pages; 1627 1616 void *owner; 1628 1617 int32_t idx; 1629 1618 int r = 0; ··· 1693 1680 } 1694 1681 } 1695 1682 1683 + vram_pages = 0; 1696 1684 start = prange->start << PAGE_SHIFT; 1697 1685 end = (prange->last + 1) << PAGE_SHIFT; 1698 1686 for (addr = start; !r && addr < end; ) { 1699 1687 struct hmm_range *hmm_range; 1700 1688 struct vm_area_struct *vma; 1689 + uint64_t vram_pages_vma; 1701 1690 unsigned long next = 0; 1702 1691 unsigned long offset; 1703 1692 unsigned long npages; ··· 1728 1713 if (!r) { 1729 1714 offset = (addr - start) >> PAGE_SHIFT; 1730 1715 r = svm_range_dma_map(prange, ctx->bitmap, offset, npages, 1731 - hmm_range->hmm_pfns); 1716 + hmm_range->hmm_pfns, &vram_pages_vma); 1732 1717 if (r) 1733 1718 pr_debug("failed %d to dma map range\n", r); 1719 + else 1720 + vram_pages += vram_pages_vma; 1734 1721 } 1735 1722 1736 1723 svm_range_lock(prange); ··· 1756 1739 svm_range_unlock(prange); 1757 1740 1758 1741 addr = next; 1742 + } 1743 + 1744 + if (addr == end) { 1745 + prange->vram_pages = vram_pages; 1746 + 1747 + /* if prange does not include any vram page and it 1748 + * has not released svm_bo drop its svm_bo reference 1749 + * and set its actaul_loc to sys ram 1750 + */ 1751 + if (!vram_pages && prange->ttm_res) { 1752 + prange->actual_loc = 0; 1753 + svm_range_vram_node_free(prange); 1754 + } 1759 1755 } 1760 1756 1761 1757 svm_range_unreserve_bos(ctx); ··· 2023 1993 new->actual_loc = old->actual_loc; 2024 1994 new->granularity = old->granularity; 2025 1995 new->mapped_to_gpu = old->mapped_to_gpu; 1996 + new->vram_pages = old->vram_pages; 2026 1997 bitmap_copy(new->bitmap_access, old->bitmap_access, MAX_GPU_INSTANCE); 2027 1998 bitmap_copy(new->bitmap_aip, old->bitmap_aip, MAX_GPU_INSTANCE); 2028 1999 ··· 2932 2901 uint32_t vmid, uint32_t node_id, 2933 2902 uint64_t addr, bool write_fault) 2934 2903 { 2904 + unsigned long start, last, size; 2935 2905 struct mm_struct *mm = NULL; 2936 2906 struct svm_range_list *svms; 2937 2907 struct svm_range *prange; ··· 3068 3036 kfd_smi_event_page_fault_start(node, p->lead_thread->pid, addr, 3069 3037 write_fault, timestamp); 3070 3038 3071 - if (prange->actual_loc != best_loc) { 3039 + if (prange->actual_loc != 0 || best_loc != 0) { 3072 3040 migration = true; 3041 + /* Align migration range start and size to granularity size */ 3042 + size = 1UL << prange->granularity; 3043 + start = max_t(unsigned long, ALIGN_DOWN(addr, size), prange->start); 3044 + last = min_t(unsigned long, ALIGN(addr + 1, size) - 1, prange->last); 3045 + 3073 3046 if (best_loc) { 3074 - r = svm_migrate_to_vram(prange, best_loc, mm, 3075 - KFD_MIGRATE_TRIGGER_PAGEFAULT_GPU); 3047 + r = svm_migrate_to_vram(prange, best_loc, start, last, 3048 + mm, KFD_MIGRATE_TRIGGER_PAGEFAULT_GPU); 3076 3049 if (r) { 3077 3050 pr_debug("svm_migrate_to_vram failed (%d) at %llx, falling back to system memory\n", 3078 3051 r, addr); 3079 3052 /* Fallback to system memory if migration to 3080 3053 * VRAM failed 3081 3054 */ 3082 - if (prange->actual_loc) 3083 - r = svm_migrate_vram_to_ram(prange, mm, 3084 - KFD_MIGRATE_TRIGGER_PAGEFAULT_GPU, 3085 - NULL); 3055 + if (prange->actual_loc && prange->actual_loc != best_loc) 3056 + r = svm_migrate_vram_to_ram(prange, mm, start, last, 3057 + KFD_MIGRATE_TRIGGER_PAGEFAULT_GPU, NULL); 3086 3058 else 3087 3059 r = 0; 3088 3060 } 3089 3061 } else { 3090 - r = svm_migrate_vram_to_ram(prange, mm, 3091 - KFD_MIGRATE_TRIGGER_PAGEFAULT_GPU, 3092 - NULL); 3062 + r = svm_migrate_vram_to_ram(prange, mm, start, last, 3063 + KFD_MIGRATE_TRIGGER_PAGEFAULT_GPU, NULL); 3093 3064 } 3094 3065 if (r) { 3095 3066 pr_debug("failed %d to migrate svms %p [0x%lx 0x%lx]\n", 3096 - r, svms, prange->start, prange->last); 3067 + r, svms, start, last); 3097 3068 goto out_unlock_range; 3098 3069 } 3099 3070 } ··· 3450 3415 *migrated = false; 3451 3416 best_loc = svm_range_best_prefetch_location(prange); 3452 3417 3453 - if (best_loc == KFD_IOCTL_SVM_LOCATION_UNDEFINED || 3454 - best_loc == prange->actual_loc) 3418 + /* when best_loc is a gpu node and same as prange->actual_loc 3419 + * we still need do migration as prange->actual_loc !=0 does 3420 + * not mean all pages in prange are vram. hmm migrate will pick 3421 + * up right pages during migration. 3422 + */ 3423 + if ((best_loc == KFD_IOCTL_SVM_LOCATION_UNDEFINED) || 3424 + (best_loc == 0 && prange->actual_loc == 0)) 3455 3425 return 0; 3456 3426 3457 3427 if (!best_loc) { 3458 - r = svm_migrate_vram_to_ram(prange, mm, 3428 + r = svm_migrate_vram_to_ram(prange, mm, prange->start, prange->last, 3459 3429 KFD_MIGRATE_TRIGGER_PREFETCH, NULL); 3460 3430 *migrated = !r; 3461 3431 return r; 3462 3432 } 3463 3433 3464 - r = svm_migrate_to_vram(prange, best_loc, mm, KFD_MIGRATE_TRIGGER_PREFETCH); 3434 + r = svm_migrate_to_vram(prange, best_loc, prange->start, prange->last, 3435 + mm, KFD_MIGRATE_TRIGGER_PREFETCH); 3465 3436 *migrated = !r; 3466 3437 3467 3438 return r; ··· 3522 3481 3523 3482 mutex_lock(&prange->migrate_mutex); 3524 3483 do { 3484 + /* migrate all vram pages in this prange to sys ram 3485 + * after that prange->actual_loc should be zero 3486 + */ 3525 3487 r = svm_migrate_vram_to_ram(prange, mm, 3488 + prange->start, prange->last, 3526 3489 KFD_MIGRATE_TRIGGER_TTM_EVICTION, NULL); 3527 3490 } while (!r && prange->actual_loc && --retries); 3528 3491
+5 -1
drivers/gpu/drm/amd/amdkfd/kfd_svm.h
··· 78 78 * @update_list:link list node used to add to update_list 79 79 * @mapping: bo_va mapping structure to create and update GPU page table 80 80 * @npages: number of pages 81 + * @vram_pages: vram pages number in this svm_range 81 82 * @dma_addr: dma mapping address on each GPU for system memory physical page 82 83 * @ttm_res: vram ttm resource map 83 84 * @offset: range start offset within mm_nodes ··· 89 88 * @flags: flags defined as KFD_IOCTL_SVM_FLAG_* 90 89 * @perferred_loc: perferred location, 0 for CPU, or GPU id 91 90 * @perfetch_loc: last prefetch location, 0 for CPU, or GPU id 92 - * @actual_loc: the actual location, 0 for CPU, or GPU id 91 + * @actual_loc: this svm_range location. 0: all pages are from sys ram; 92 + * GPU id: this svm_range may include vram pages from GPU with 93 + * id actual_loc. 93 94 * @granularity:migration granularity, log2 num pages 94 95 * @invalid: not 0 means cpu page table is invalidated 95 96 * @validate_timestamp: system timestamp when range is validated ··· 115 112 struct list_head list; 116 113 struct list_head update_list; 117 114 uint64_t npages; 115 + uint64_t vram_pages; 118 116 dma_addr_t *dma_addr[MAX_GPU_INSTANCE]; 119 117 struct ttm_resource *ttm_res; 120 118 uint64_t offset;