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

mm: handle multiple owners of device private pages in migrate_vma

Add a new src_owner field to struct migrate_vma. If the field is set,
only device private pages with page->pgmap->owner equal to that field are
migrated. If the field is not set only "normal" pages are migrated.

Fixes: df6ad69838fc ("mm/device-public-memory: device memory cache coherent with CPU")
Link: https://lore.kernel.org/r/20200316193216.920734-3-hch@lst.de
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Ralph Campbell <rcampbell@nvidia.com>
Tested-by: Bharata B Rao <bharata@linux.ibm.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>

authored by

Christoph Hellwig and committed by
Jason Gunthorpe
800bb1c8 f894ddd5

+16 -3
+1
arch/powerpc/kvm/book3s_hv_uvmem.c
··· 563 563 mig.end = end; 564 564 mig.src = &src_pfn; 565 565 mig.dst = &dst_pfn; 566 + mig.src_owner = &kvmppc_uvmem_pgmap; 566 567 567 568 mutex_lock(&kvm->arch.uvmem_lock); 568 569 /* The requested page is already paged-out, nothing to do */
+1
drivers/gpu/drm/nouveau/nouveau_dmem.c
··· 176 176 .end = vmf->address + PAGE_SIZE, 177 177 .src = &src, 178 178 .dst = &dst, 179 + .src_owner = drm->dev, 179 180 }; 180 181 181 182 /*
+8
include/linux/migrate.h
··· 196 196 unsigned long npages; 197 197 unsigned long start; 198 198 unsigned long end; 199 + 200 + /* 201 + * Set to the owner value also stored in page->pgmap->owner for 202 + * migrating out of device private memory. If set only device 203 + * private pages with this owner are migrated. If not set 204 + * device private pages are not migrated at all. 205 + */ 206 + void *src_owner; 199 207 }; 200 208 201 209 int migrate_vma_setup(struct migrate_vma *args);
+6 -3
mm/migrate.c
··· 2241 2241 arch_enter_lazy_mmu_mode(); 2242 2242 2243 2243 for (; addr < end; addr += PAGE_SIZE, ptep++) { 2244 - unsigned long mpfn, pfn; 2244 + unsigned long mpfn = 0, pfn; 2245 2245 struct page *page; 2246 2246 swp_entry_t entry; 2247 2247 pte_t pte; ··· 2255 2255 } 2256 2256 2257 2257 if (!pte_present(pte)) { 2258 - mpfn = 0; 2259 - 2260 2258 /* 2261 2259 * Only care about unaddressable device page special 2262 2260 * page table entry. Other special swap entries are not ··· 2265 2267 goto next; 2266 2268 2267 2269 page = device_private_entry_to_page(entry); 2270 + if (page->pgmap->owner != migrate->src_owner) 2271 + goto next; 2272 + 2268 2273 mpfn = migrate_pfn(page_to_pfn(page)) | 2269 2274 MIGRATE_PFN_MIGRATE; 2270 2275 if (is_write_device_private_entry(entry)) 2271 2276 mpfn |= MIGRATE_PFN_WRITE; 2272 2277 } else { 2278 + if (migrate->src_owner) 2279 + goto next; 2273 2280 pfn = pte_pfn(pte); 2274 2281 if (is_zero_pfn(pfn)) { 2275 2282 mpfn = MIGRATE_PFN_MIGRATE;