[PATCH v3 13/21] clear_page: add generic clear_user_pages_incoherent()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add generic primitives for clear_user_pages_incoherent() and
clear_page_make_coherent().

To ensure that callers don't mix accesses to different types
of address_spaces, annotate clear_user_pages_incoherent()
as taking an __incoherent pointer as argument.

Also add clear_user_highpages_incoherent() which either calls
clear_user_pages_incoherent() or falls back to clear_user_highpages()

Signed-off-by: Ankur Arora <ankur.a.arora@xxxxxxxxxx>
---

Notes:
    clear_user_highpages_incoherent() operates on an __incoherent region
    and expects the caller to call clear_page_make_coherent().
    
    It should, however be taking an __incoherent * as argument -- this it
    does not do because I couldn't see a clean way of doing that with
    highmem. Suggestions?

 include/asm-generic/clear_page.h | 21 +++++++++++++++++++++
 include/linux/highmem.h          | 23 +++++++++++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/include/asm-generic/clear_page.h b/include/asm-generic/clear_page.h
index f827d661519c..0ebff70a60a9 100644
--- a/include/asm-generic/clear_page.h
+++ b/include/asm-generic/clear_page.h
@@ -16,6 +16,9 @@
 #if defined(CONFIG_HIGHMEM) && defined(__HAVE_ARCH_CLEAR_USER_PAGES)
 #error CONFIG_HIGHMEM is incompatible with __HAVE_ARCH_CLEAR_USER_PAGES
 #endif
+#if defined(CONFIG_HIGHMEM) && defined(__HAVE_ARCH_CLEAR_USER_PAGES_INCOHERENT)
+#error CONFIG_HIGHMEM is incompatible with __HAVE_ARCH_CLEAR_USER_PAGES_INCOHERENT
+#endif
 
 #ifndef __HAVE_ARCH_CLEAR_USER_PAGES
 
@@ -41,4 +44,22 @@ static inline void clear_user_pages(void *page, unsigned long vaddr,
 
 #define ARCH_MAX_CLEAR_PAGES	(1 << ARCH_MAX_CLEAR_PAGES_ORDER)
 
+#ifndef __HAVE_ARCH_CLEAR_USER_PAGES_INCOHERENT
+#ifndef __ASSEMBLY__
+/*
+ * Fallback path (via clear_user_pages()) if the architecture does not
+ * support incoherent clearing.
+ */
+static inline void clear_user_pages_incoherent(__incoherent void *page,
+					       unsigned long vaddr,
+					       struct page *pg,
+					       unsigned int npages)
+{
+	clear_user_pages((__force void *)page, vaddr, pg, npages);
+}
+
+static inline void clear_page_make_coherent(void) { }
+#endif /* __ASSEMBLY__ */
+#endif /* __HAVE_ARCH_CLEAR_USER_PAGES_INCOHERENT */
+
 #endif /* __ASM_GENERIC_CLEAR_PAGE_H */
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index 08781d7693e7..90179f623c3b 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -231,6 +231,29 @@ static inline void clear_user_highpages(struct page *page, unsigned long vaddr,
 }
 #endif /* __HAVE_ARCH_CLEAR_USER_PAGES */
 
+#ifdef __HAVE_ARCH_CLEAR_USER_PAGES_INCOHERENT
+static inline void clear_user_highpages_incoherent(struct page *page,
+						   unsigned long vaddr,
+						   unsigned int npages)
+{
+	__incoherent void *addr = (__incoherent void *) page_address(page);
+
+	clear_user_pages_incoherent(addr, vaddr, page, npages);
+}
+#else
+static inline void clear_user_highpages_incoherent(struct page *page,
+						   unsigned long vaddr,
+						   unsigned int npages)
+{
+	/*
+	 * We fallback to clear_user_highpages() for the CONFIG_HIGHMEM
+	 * configs.
+	 * For !CONFIG_HIGHMEM, this will get translated to clear_user_pages().
+	 */
+	clear_user_highpages(page, vaddr, npages);
+}
+#endif /* __HAVE_ARCH_CLEAR_USER_PAGES_INCOHERENT */
+
 #ifndef __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE_MOVABLE
 /**
  * alloc_zeroed_user_highpage_movable - Allocate a zeroed HIGHMEM page for a VMA that the caller knows can move
-- 
2.31.1





[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux