Merge tag 'for-linus-5.4-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / mm / migrate.c
index a42858d..4fe45d1 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/hugetlb.h>
 #include <linux/hugetlb_cgroup.h>
 #include <linux/gfp.h>
+#include <linux/pagewalk.h>
 #include <linux/pfn_t.h>
 #include <linux/memremap.h>
 #include <linux/userfaultfd_k.h>
@@ -459,7 +460,7 @@ int migrate_page_move_mapping(struct address_space *mapping,
 
                for (i = 1; i < HPAGE_PMD_NR; i++) {
                        xas_next(&xas);
-                       xas_store(&xas, newpage + i);
+                       xas_store(&xas, newpage);
                }
        }
 
@@ -1611,7 +1612,7 @@ static int do_pages_move(struct mm_struct *mm, nodemask_t task_nodes,
                        goto out_flush;
                if (get_user(node, nodes + i))
                        goto out_flush;
-               addr = (unsigned long)p;
+               addr = (unsigned long)untagged_addr(p);
 
                err = -ENODEV;
                if (node < 0 || node >= MAX_NUMNODES)
@@ -1891,7 +1892,7 @@ static int numamigrate_isolate_page(pg_data_t *pgdat, struct page *page)
        VM_BUG_ON_PAGE(compound_order(page) && !PageTransHuge(page), page);
 
        /* Avoid migrating to a node that is nearly full */
-       if (!migrate_balanced_pgdat(pgdat, 1UL << compound_order(page)))
+       if (!migrate_balanced_pgdat(pgdat, compound_nr(page)))
                return 0;
 
        if (isolate_lru_page(page))
@@ -2119,17 +2120,7 @@ out_unlock:
 
 #endif /* CONFIG_NUMA */
 
-#if defined(CONFIG_MIGRATE_VMA_HELPER)
-struct migrate_vma {
-       struct vm_area_struct   *vma;
-       unsigned long           *dst;
-       unsigned long           *src;
-       unsigned long           cpages;
-       unsigned long           npages;
-       unsigned long           start;
-       unsigned long           end;
-};
-
+#ifdef CONFIG_DEVICE_PRIVATE
 static int migrate_vma_collect_hole(unsigned long start,
                                    unsigned long end,
                                    struct mm_walk *walk)
@@ -2227,17 +2218,15 @@ again:
                pte_t pte;
 
                pte = *ptep;
-               pfn = pte_pfn(pte);
 
                if (pte_none(pte)) {
                        mpfn = MIGRATE_PFN_MIGRATE;
                        migrate->cpages++;
-                       pfn = 0;
                        goto next;
                }
 
                if (!pte_present(pte)) {
-                       mpfn = pfn = 0;
+                       mpfn = 0;
 
                        /*
                         * Only care about unaddressable device page special
@@ -2249,15 +2238,15 @@ again:
                                goto next;
 
                        page = device_private_entry_to_page(entry);
-                       mpfn = migrate_pfn(page_to_pfn(page))|
-                               MIGRATE_PFN_DEVICE | MIGRATE_PFN_MIGRATE;
+                       mpfn = migrate_pfn(page_to_pfn(page)) |
+                                       MIGRATE_PFN_MIGRATE;
                        if (is_write_device_private_entry(entry))
                                mpfn |= MIGRATE_PFN_WRITE;
                } else {
+                       pfn = pte_pfn(pte);
                        if (is_zero_pfn(pfn)) {
                                mpfn = MIGRATE_PFN_MIGRATE;
                                migrate->cpages++;
-                               pfn = 0;
                                goto next;
                        }
                        page = vm_normal_page(migrate->vma, addr, pte);
@@ -2267,10 +2256,9 @@ again:
 
                /* FIXME support THP */
                if (!page || !page->mapping || PageTransCompound(page)) {
-                       mpfn = pfn = 0;
+                       mpfn = 0;
                        goto next;
                }
-               pfn = page_to_pfn(page);
 
                /*
                 * By getting a reference on the page we pin it and that blocks
@@ -2329,6 +2317,11 @@ next:
        return 0;
 }
 
+static const struct mm_walk_ops migrate_vma_walk_ops = {
+       .pmd_entry              = migrate_vma_collect_pmd,
+       .pte_hole               = migrate_vma_collect_hole,
+};
+
 /*
  * migrate_vma_collect() - collect pages over a range of virtual addresses
  * @migrate: migrate struct containing all migration information
@@ -2340,21 +2333,15 @@ next:
 static void migrate_vma_collect(struct migrate_vma *migrate)
 {
        struct mmu_notifier_range range;
-       struct mm_walk mm_walk = {
-               .pmd_entry = migrate_vma_collect_pmd,
-               .pte_hole = migrate_vma_collect_hole,
-               .vma = migrate->vma,
-               .mm = migrate->vma->vm_mm,
-               .private = migrate,
-       };
 
-       mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, NULL, mm_walk.mm,
-                               migrate->start,
-                               migrate->end);
+       mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, NULL,
+                       migrate->vma->vm_mm, migrate->start, migrate->end);
        mmu_notifier_invalidate_range_start(&range);
-       walk_page_range(migrate->start, migrate->end, &mm_walk);
-       mmu_notifier_invalidate_range_end(&range);
 
+       walk_page_range(migrate->vma->vm_mm, migrate->start, migrate->end,
+                       &migrate_vma_walk_ops, migrate);
+
+       mmu_notifier_invalidate_range_end(&range);
        migrate->end = migrate->start + (migrate->npages << PAGE_SHIFT);
 }
 
@@ -2577,6 +2564,110 @@ restore:
        }
 }
 
+/**
+ * migrate_vma_setup() - prepare to migrate a range of memory
+ * @args: contains the vma, start, and and pfns arrays for the migration
+ *
+ * Returns: negative errno on failures, 0 when 0 or more pages were migrated
+ * without an error.
+ *
+ * Prepare to migrate a range of memory virtual address range by collecting all
+ * the pages backing each virtual address in the range, saving them inside the
+ * src array.  Then lock those pages and unmap them. Once the pages are locked
+ * and unmapped, check whether each page is pinned or not.  Pages that aren't
+ * pinned have the MIGRATE_PFN_MIGRATE flag set (by this function) in the
+ * corresponding src array entry.  Then restores any pages that are pinned, by
+ * remapping and unlocking those pages.
+ *
+ * The caller should then allocate destination memory and copy source memory to
+ * it for all those entries (ie with MIGRATE_PFN_VALID and MIGRATE_PFN_MIGRATE
+ * flag set).  Once these are allocated and copied, the caller must update each
+ * corresponding entry in the dst array with the pfn value of the destination
+ * page and with the MIGRATE_PFN_VALID and MIGRATE_PFN_LOCKED flags set
+ * (destination pages must have their struct pages locked, via lock_page()).
+ *
+ * Note that the caller does not have to migrate all the pages that are marked
+ * with MIGRATE_PFN_MIGRATE flag in src array unless this is a migration from
+ * device memory to system memory.  If the caller cannot migrate a device page
+ * back to system memory, then it must return VM_FAULT_SIGBUS, which has severe
+ * consequences for the userspace process, so it must be avoided if at all
+ * possible.
+ *
+ * For empty entries inside CPU page table (pte_none() or pmd_none() is true) we
+ * do set MIGRATE_PFN_MIGRATE flag inside the corresponding source array thus
+ * allowing the caller to allocate device memory for those unback virtual
+ * address.  For this the caller simply has to allocate device memory and
+ * properly set the destination entry like for regular migration.  Note that
+ * this can still fails and thus inside the device driver must check if the
+ * migration was successful for those entries after calling migrate_vma_pages()
+ * just like for regular migration.
+ *
+ * After that, the callers must call migrate_vma_pages() to go over each entry
+ * in the src array that has the MIGRATE_PFN_VALID and MIGRATE_PFN_MIGRATE flag
+ * set. If the corresponding entry in dst array has MIGRATE_PFN_VALID flag set,
+ * then migrate_vma_pages() to migrate struct page information from the source
+ * struct page to the destination struct page.  If it fails to migrate the
+ * struct page information, then it clears the MIGRATE_PFN_MIGRATE flag in the
+ * src array.
+ *
+ * At this point all successfully migrated pages have an entry in the src
+ * array with MIGRATE_PFN_VALID and MIGRATE_PFN_MIGRATE flag set and the dst
+ * array entry with MIGRATE_PFN_VALID flag set.
+ *
+ * Once migrate_vma_pages() returns the caller may inspect which pages were
+ * successfully migrated, and which were not.  Successfully migrated pages will
+ * have the MIGRATE_PFN_MIGRATE flag set for their src array entry.
+ *
+ * It is safe to update device page table after migrate_vma_pages() because
+ * both destination and source page are still locked, and the mmap_sem is held
+ * in read mode (hence no one can unmap the range being migrated).
+ *
+ * Once the caller is done cleaning up things and updating its page table (if it
+ * chose to do so, this is not an obligation) it finally calls
+ * migrate_vma_finalize() to update the CPU page table to point to new pages
+ * for successfully migrated pages or otherwise restore the CPU page table to
+ * point to the original source pages.
+ */
+int migrate_vma_setup(struct migrate_vma *args)
+{
+       long nr_pages = (args->end - args->start) >> PAGE_SHIFT;
+
+       args->start &= PAGE_MASK;
+       args->end &= PAGE_MASK;
+       if (!args->vma || is_vm_hugetlb_page(args->vma) ||
+           (args->vma->vm_flags & VM_SPECIAL) || vma_is_dax(args->vma))
+               return -EINVAL;
+       if (nr_pages <= 0)
+               return -EINVAL;
+       if (args->start < args->vma->vm_start ||
+           args->start >= args->vma->vm_end)
+               return -EINVAL;
+       if (args->end <= args->vma->vm_start || args->end > args->vma->vm_end)
+               return -EINVAL;
+       if (!args->src || !args->dst)
+               return -EINVAL;
+
+       memset(args->src, 0, sizeof(*args->src) * nr_pages);
+       args->cpages = 0;
+       args->npages = 0;
+
+       migrate_vma_collect(args);
+
+       if (args->cpages)
+               migrate_vma_prepare(args);
+       if (args->cpages)
+               migrate_vma_unmap(args);
+
+       /*
+        * At this point pages are locked and unmapped, and thus they have
+        * stable content and can safely be copied to destination memory that
+        * is allocated by the drivers.
+        */
+       return 0;
+
+}
+EXPORT_SYMBOL(migrate_vma_setup);
+
 static void migrate_vma_insert_page(struct migrate_vma *migrate,
                                    unsigned long addr,
                                    struct page *page,
@@ -2708,7 +2799,7 @@ abort:
        *src &= ~MIGRATE_PFN_MIGRATE;
 }
 
-/*
+/**
  * migrate_vma_pages() - migrate meta-data from src page to dst page
  * @migrate: migrate struct containing all migration information
  *
@@ -2716,7 +2807,7 @@ abort:
  * struct page. This effectively finishes the migration from source page to the
  * destination page.
  */
-static void migrate_vma_pages(struct migrate_vma *migrate)
+void migrate_vma_pages(struct migrate_vma *migrate)
 {
        const unsigned long npages = migrate->npages;
        const unsigned long start = migrate->start;
@@ -2790,8 +2881,9 @@ static void migrate_vma_pages(struct migrate_vma *migrate)
        if (notified)
                mmu_notifier_invalidate_range_only_end(&range);
 }
+EXPORT_SYMBOL(migrate_vma_pages);
 
-/*
+/**
  * migrate_vma_finalize() - restore CPU page table entry
  * @migrate: migrate struct containing all migration information
  *
@@ -2802,7 +2894,7 @@ static void migrate_vma_pages(struct migrate_vma *migrate)
  * This also unlocks the pages and puts them back on the lru, or drops the extra
  * refcount, for device pages.
  */
-static void migrate_vma_finalize(struct migrate_vma *migrate)
+void migrate_vma_finalize(struct migrate_vma *migrate)
 {
        const unsigned long npages = migrate->npages;
        unsigned long i;
@@ -2845,124 +2937,5 @@ static void migrate_vma_finalize(struct migrate_vma *migrate)
                }
        }
 }
-
-/*
- * migrate_vma() - migrate a range of memory inside vma
- *
- * @ops: migration callback for allocating destination memory and copying
- * @vma: virtual memory area containing the range to be migrated
- * @start: start address of the range to migrate (inclusive)
- * @end: end address of the range to migrate (exclusive)
- * @src: array of hmm_pfn_t containing source pfns
- * @dst: array of hmm_pfn_t containing destination pfns
- * @private: pointer passed back to each of the callback
- * Returns: 0 on success, error code otherwise
- *
- * This function tries to migrate a range of memory virtual address range, using
- * callbacks to allocate and copy memory from source to destination. First it
- * collects all the pages backing each virtual address in the range, saving this
- * inside the src array. Then it locks those pages and unmaps them. Once the pages
- * are locked and unmapped, it checks whether each page is pinned or not. Pages
- * that aren't pinned have the MIGRATE_PFN_MIGRATE flag set (by this function)
- * in the corresponding src array entry. It then restores any pages that are
- * pinned, by remapping and unlocking those pages.
- *
- * At this point it calls the alloc_and_copy() callback. For documentation on
- * what is expected from that callback, see struct migrate_vma_ops comments in
- * include/linux/migrate.h
- *
- * After the alloc_and_copy() callback, this function goes over each entry in
- * the src array that has the MIGRATE_PFN_VALID and MIGRATE_PFN_MIGRATE flag
- * set. If the corresponding entry in dst array has MIGRATE_PFN_VALID flag set,
- * then the function tries to migrate struct page information from the source
- * struct page to the destination struct page. If it fails to migrate the struct
- * page information, then it clears the MIGRATE_PFN_MIGRATE flag in the src
- * array.
- *
- * At this point all successfully migrated pages have an entry in the src
- * array with MIGRATE_PFN_VALID and MIGRATE_PFN_MIGRATE flag set and the dst
- * array entry with MIGRATE_PFN_VALID flag set.
- *
- * It then calls the finalize_and_map() callback. See comments for "struct
- * migrate_vma_ops", in include/linux/migrate.h for details about
- * finalize_and_map() behavior.
- *
- * After the finalize_and_map() callback, for successfully migrated pages, this
- * function updates the CPU page table to point to new pages, otherwise it
- * restores the CPU page table to point to the original source pages.
- *
- * Function returns 0 after the above steps, even if no pages were migrated
- * (The function only returns an error if any of the arguments are invalid.)
- *
- * Both src and dst array must be big enough for (end - start) >> PAGE_SHIFT
- * unsigned long entries.
- */
-int migrate_vma(const struct migrate_vma_ops *ops,
-               struct vm_area_struct *vma,
-               unsigned long start,
-               unsigned long end,
-               unsigned long *src,
-               unsigned long *dst,
-               void *private)
-{
-       struct migrate_vma migrate;
-
-       /* Sanity check the arguments */
-       start &= PAGE_MASK;
-       end &= PAGE_MASK;
-       if (!vma || is_vm_hugetlb_page(vma) || (vma->vm_flags & VM_SPECIAL) ||
-                       vma_is_dax(vma))
-               return -EINVAL;
-       if (start < vma->vm_start || start >= vma->vm_end)
-               return -EINVAL;
-       if (end <= vma->vm_start || end > vma->vm_end)
-               return -EINVAL;
-       if (!ops || !src || !dst || start >= end)
-               return -EINVAL;
-
-       memset(src, 0, sizeof(*src) * ((end - start) >> PAGE_SHIFT));
-       migrate.src = src;
-       migrate.dst = dst;
-       migrate.start = start;
-       migrate.npages = 0;
-       migrate.cpages = 0;
-       migrate.end = end;
-       migrate.vma = vma;
-
-       /* Collect, and try to unmap source pages */
-       migrate_vma_collect(&migrate);
-       if (!migrate.cpages)
-               return 0;
-
-       /* Lock and isolate page */
-       migrate_vma_prepare(&migrate);
-       if (!migrate.cpages)
-               return 0;
-
-       /* Unmap pages */
-       migrate_vma_unmap(&migrate);
-       if (!migrate.cpages)
-               return 0;
-
-       /*
-        * At this point pages are locked and unmapped, and thus they have
-        * stable content and can safely be copied to destination memory that
-        * is allocated by the callback.
-        *
-        * Note that migration can fail in migrate_vma_struct_page() for each
-        * individual page.
-        */
-       ops->alloc_and_copy(vma, src, dst, start, end, private);
-
-       /* This does the real migration of struct page */
-       migrate_vma_pages(&migrate);
-
-       ops->finalize_and_map(vma, src, dst, start, end, private);
-
-       /* Unlock and remap pages */
-       migrate_vma_finalize(&migrate);
-
-       return 0;
-}
-EXPORT_SYMBOL(migrate_vma);
-#endif /* defined(MIGRATE_VMA_HELPER) */
+EXPORT_SYMBOL(migrate_vma_finalize);
+#endif /* CONFIG_DEVICE_PRIVATE */