x86, mm: simplify get_user_pages() PTE bit handling
The bit checking code is repetitive and does not realistically
need to be looking at raw PTE bits. The pte_* accessors work
eust fine.
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index 61f0f62..5056b9e 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -446,6 +446,11 @@
return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE);
}
+static inline int pte_user(pte_t a)
+{
+ return pte_flags(a) & _PAGE_USER;
+}
+
#define pte_accessible pte_accessible
static inline bool pte_accessible(struct mm_struct *mm, pte_t a)
{
diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c
index 81bf3d2..52a3927 100644
--- a/arch/x86/mm/gup.c
+++ b/arch/x86/mm/gup.c
@@ -63,6 +63,17 @@
#endif
}
+static inline int pte_allows_gup(pte_t pte, int write)
+{
+ if (!pte_present(pte))
+ return 0;
+ if (!pte_user(pte))
+ return 0;
+ if (write && !pte_write(pte))
+ return 0;
+ return 1;
+}
+
/*
* The performance critical leaf functions are made noinline otherwise gcc
* inlines everything into a single function which results in too much
@@ -71,13 +82,8 @@
static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
unsigned long end, int write, struct page **pages, int *nr)
{
- unsigned long mask;
pte_t *ptep;
- mask = _PAGE_PRESENT|_PAGE_USER;
- if (write)
- mask |= _PAGE_RW;
-
ptep = pte_offset_map(&pmd, addr);
do {
pte_t pte = gup_get_pte(ptep);
@@ -89,7 +95,7 @@
return 0;
}
- if ((pte_flags(pte) & (mask | _PAGE_SPECIAL)) != mask) {
+ if (pte_special(pte)) {
pte_unmap(ptep);
return 0;
}
@@ -194,15 +200,11 @@
static noinline int gup_huge_pud(pud_t pud, unsigned long addr,
unsigned long end, int write, struct page **pages, int *nr)
{
- unsigned long mask;
pte_t pte = *(pte_t *)&pud;
struct page *head, *page;
int refs;
- mask = _PAGE_PRESENT|_PAGE_USER;
- if (write)
- mask |= _PAGE_RW;
- if ((pte_flags(pte) & mask) != mask)
+ if (!pte_allows_gup(pte, write))
return 0;
/* hugepages are never "special" */
VM_BUG_ON(pte_flags(pte) & _PAGE_SPECIAL);