On 9/13/19 11:32 AM, Thomas Hellström (VMware) wrote:
From: Thomas Hellstrom thellstrom@vmware.com
Add two utilities to a) write-protect and b) clean all ptes pointing into a range of an address space. The utilities are intended to aid in tracking dirty pages (either driver-allocated system memory or pci device memory). The write-protect utility should be used in conjunction with page_mkwrite() and pfn_mkwrite() to trigger write page-faults on page accesses. Typically one would want to use this on sparse accesses into large memory regions. The clean utility should be used to utilize hardware dirtying functionality and avoid the overhead of page-faults, typically on large accesses into small memory regions.
The added file "as_dirty_helpers.c" is initially listed as maintained by VMware under our DRM driver. If somebody would like it elsewhere, that's of course no problem.
Cc: Andrew Morton akpm@linux-foundation.org Cc: Matthew Wilcox willy@infradead.org Cc: Will Deacon will.deacon@arm.com Cc: Peter Zijlstra peterz@infradead.org Cc: Rik van Riel riel@surriel.com Cc: Minchan Kim minchan@kernel.org Cc: Michal Hocko mhocko@suse.com Cc: Huang Ying ying.huang@intel.com Cc: Souptick Joarder jrdr.linux@gmail.com Cc: "Jérôme Glisse" jglisse@redhat.com Cc: linux-mm@kvack.org Cc: linux-kernel@vger.kernel.org
Signed-off-by: Thomas Hellstrom thellstrom@vmware.com Reviewed-by: Ralph Campbell rcampbell@nvidia.com #v1
MAINTAINERS | 1 + include/linux/mm.h | 13 +- mm/Kconfig | 3 + mm/Makefile | 1 + mm/as_dirty_helpers.c | 392 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 409 insertions(+), 1 deletion(-) create mode 100644 mm/as_dirty_helpers.c
diff --git a/MAINTAINERS b/MAINTAINERS index c2d975da561f..b596c7cf4a85 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5287,6 +5287,7 @@ T: git git://people.freedesktop.org/~thomash/linux S: Supported F: drivers/gpu/drm/vmwgfx/ F: include/uapi/drm/vmwgfx_drm.h +F: mm/as_dirty_helpers.c
DRM DRIVERS M: David Airlie airlied@linux.ie diff --git a/include/linux/mm.h b/include/linux/mm.h index 0334ca97c584..27ff341ecbdc 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2657,7 +2657,6 @@ typedef int (*pte_fn_t)(pte_t *pte, unsigned long addr, void *data); extern int apply_to_page_range(struct mm_struct *mm, unsigned long address, unsigned long size, pte_fn_t fn, void *data);
- #ifdef CONFIG_PAGE_POISONING extern bool page_poisoning_enabled(void); extern void kernel_poison_pages(struct page *page, int numpages, int enable);
@@ -2891,5 +2890,17 @@ void __init setup_nr_node_ids(void); static inline void setup_nr_node_ids(void) {} #endif
+#ifdef CONFIG_AS_DIRTY_HELPERS +unsigned long apply_as_clean(struct address_space *mapping,
pgoff_t first_index, pgoff_t nr,
pgoff_t bitmap_pgoff,
unsigned long *bitmap,
pgoff_t *start,
pgoff_t *end);
+unsigned long apply_as_wrprotect(struct address_space *mapping,
pgoff_t first_index, pgoff_t nr);
+#endif
- #endif /* __KERNEL__ */ #endif /* _LINUX_MM_H */
diff --git a/mm/Kconfig b/mm/Kconfig index 56cec636a1fc..594350e9d78e 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -736,4 +736,7 @@ config ARCH_HAS_PTE_SPECIAL config ARCH_HAS_HUGEPD bool
+config AS_DIRTY_HELPERS
bool
- endmenu
diff --git a/mm/Makefile b/mm/Makefile index d0b295c3b764..4086f1eefbc6 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -105,3 +105,4 @@ obj-$(CONFIG_PERCPU_STATS) += percpu-stats.o obj-$(CONFIG_ZONE_DEVICE) += memremap.o obj-$(CONFIG_HMM_MIRROR) += hmm.o obj-$(CONFIG_MEMFD_CREATE) += memfd.o +obj-$(CONFIG_AS_DIRTY_HELPERS) += as_dirty_helpers.o diff --git a/mm/as_dirty_helpers.c b/mm/as_dirty_helpers.c new file mode 100644 index 000000000000..3be06fe8f1d2 --- /dev/null +++ b/mm/as_dirty_helpers.c @@ -0,0 +1,392 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <linux/mm.h> +#include <linux/mm_types.h> +#include <linux/hugetlb.h> +#include <linux/bitops.h> +#include <linux/mmu_notifier.h> +#include <asm/cacheflush.h> +#include <asm/tlbflush.h>
+/**
- struct as_walk - Argument to as_pte_fn_t
Argument to struct as_walk_ops callbacks
- @vma: Pointer to the struct vmw_area_struct currently being walked.
- Embeddable argument to struct as__pte_fn_t
Here as well.
- */
+struct as_walk {
- struct vm_area_struct *vma;
+};
+/**
- struct as_walk_ops - Callbacks for entries of various page table levels.
- extend for additional level support.
- */
+struct as_walk_ops {
- /**
* pte-entry: Callback for PTEs
* @pte: Pointer to the PTE.
* @addr: Virtual address.
* @asw: Struct as_walk argument for the walk. Embed for additional
* data.
*/
- void (*const pte_entry) (pte_t *pte, unsigned long addr,
struct as_walk *asw);
+};