mm/memory_hotplug: introduce add_memory_driver_managed()
[linux-2.6-microblaze.git] / include / linux / pagewalk.h
index 6ec82e9..b1cb6b7 100644 (file)
@@ -8,16 +8,19 @@ struct mm_walk;
 
 /**
  * mm_walk_ops - callbacks for walk_page_range
- * @pud_entry:         if set, called for each non-empty PUD (2nd-level) entry
- *                     this handler should only handle pud_trans_huge() puds.
- *                     the pmd_entry or pte_entry callbacks will be used for
- *                     regular PUDs.
- * @pmd_entry:         if set, called for each non-empty PMD (3rd-level) entry
+ * @pgd_entry:         if set, called for each non-empty PGD (top-level) entry
+ * @p4d_entry:         if set, called for each non-empty P4D entry
+ * @pud_entry:         if set, called for each non-empty PUD entry
+ * @pmd_entry:         if set, called for each non-empty PMD entry
  *                     this handler is required to be able to handle
  *                     pmd_trans_huge() pmds.  They may simply choose to
  *                     split_huge_page() instead of handling it explicitly.
- * @pte_entry:         if set, called for each non-empty PTE (4th-level) entry
- * @pte_hole:          if set, called for each hole at all levels
+ * @pte_entry:         if set, called for each non-empty PTE (lowest-level)
+ *                     entry
+ * @pte_hole:          if set, called for each hole at all levels,
+ *                     depth is -1 if not known, 0:PGD, 1:P4D, 2:PUD, 3:PMD
+ *                     4:PTE. Any folded depths (where PTRS_PER_P?D is equal
+ *                     to 1) are skipped.
  * @hugetlb_entry:     if set, called for each hugetlb entry
  * @test_walk:         caller specific callback function to determine whether
  *                     we walk over the current vma or not. Returning 0 means
@@ -27,8 +30,15 @@ struct mm_walk;
  * @pre_vma:            if set, called before starting walk on a non-null vma.
  * @post_vma:           if set, called after a walk on a non-null vma, provided
  *                      that @pre_vma and the vma walk succeeded.
+ *
+ * p?d_entry callbacks are called even if those levels are folded on a
+ * particular architecture/configuration.
  */
 struct mm_walk_ops {
+       int (*pgd_entry)(pgd_t *pgd, unsigned long addr,
+                        unsigned long next, struct mm_walk *walk);
+       int (*p4d_entry)(p4d_t *p4d, unsigned long addr,
+                        unsigned long next, struct mm_walk *walk);
        int (*pud_entry)(pud_t *pud, unsigned long addr,
                         unsigned long next, struct mm_walk *walk);
        int (*pmd_entry)(pmd_t *pmd, unsigned long addr,
@@ -36,7 +46,7 @@ struct mm_walk_ops {
        int (*pte_entry)(pte_t *pte, unsigned long addr,
                         unsigned long next, struct mm_walk *walk);
        int (*pte_hole)(unsigned long addr, unsigned long next,
-                       struct mm_walk *walk);
+                       int depth, struct mm_walk *walk);
        int (*hugetlb_entry)(pte_t *pte, unsigned long hmask,
                             unsigned long addr, unsigned long next,
                             struct mm_walk *walk);
@@ -47,11 +57,27 @@ struct mm_walk_ops {
        void (*post_vma)(struct mm_walk *walk);
 };
 
+/*
+ * Action for pud_entry / pmd_entry callbacks.
+ * ACTION_SUBTREE is the default
+ */
+enum page_walk_action {
+       /* Descend to next level, splitting huge pages if needed and possible */
+       ACTION_SUBTREE = 0,
+       /* Continue to next entry at this level (ignoring any subtree) */
+       ACTION_CONTINUE = 1,
+       /* Call again for this entry */
+       ACTION_AGAIN = 2
+};
+
 /**
  * mm_walk - walk_page_range data
  * @ops:       operation to call during the walk
  * @mm:                mm_struct representing the target process of page table walk
+ * @pgd:       pointer to PGD; only valid with no_vma (otherwise set to NULL)
  * @vma:       vma currently walked (NULL if walking outside vmas)
+ * @action:    next action to perform (see enum page_walk_action)
+ * @no_vma:    walk ignoring vmas (vma will always be NULL)
  * @private:   private data for callbacks' usage
  *
  * (see the comment on walk_page_range() for more details)
@@ -59,13 +85,20 @@ struct mm_walk_ops {
 struct mm_walk {
        const struct mm_walk_ops *ops;
        struct mm_struct *mm;
+       pgd_t *pgd;
        struct vm_area_struct *vma;
+       enum page_walk_action action;
+       bool no_vma;
        void *private;
 };
 
 int walk_page_range(struct mm_struct *mm, unsigned long start,
                unsigned long end, const struct mm_walk_ops *ops,
                void *private);
+int walk_page_range_novma(struct mm_struct *mm, unsigned long start,
+                         unsigned long end, const struct mm_walk_ops *ops,
+                         pgd_t *pgd,
+                         void *private);
 int walk_page_vma(struct vm_area_struct *vma, const struct mm_walk_ops *ops,
                void *private);
 int walk_page_mapping(struct address_space *mapping, pgoff_t first_index,