1457 lines
50 KiB
Diff
1457 lines
50 KiB
Diff
commit 35906966f3dc93f59957d2933bece603d0a2a57e
|
|
Author: Fabio Erculiani <lxnay@sabayon.org>
|
|
Date: Sun Jul 29 15:04:54 2012 +0200
|
|
|
|
sabayon: add __pte_alloc_kernel() patch as per Gentoo Bug #416685
|
|
|
|
diff --git a/arch/alpha/include/asm/pgalloc.h b/arch/alpha/include/asm/pgalloc.h
|
|
index bc2a0da..d05dfc2 100644
|
|
--- a/arch/alpha/include/asm/pgalloc.h
|
|
+++ b/arch/alpha/include/asm/pgalloc.h
|
|
@@ -38,10 +38,15 @@ pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
|
}
|
|
|
|
static inline pmd_t *
|
|
+__pmd_alloc_one(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
|
|
+{
|
|
+ return (pmd_t *)__get_free_page(gfp_mask | __GFP_ZERO);
|
|
+}
|
|
+
|
|
+static inline pmd_t *
|
|
pmd_alloc_one(struct mm_struct *mm, unsigned long address)
|
|
{
|
|
- pmd_t *ret = (pmd_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
|
|
- return ret;
|
|
+ return __pmd_alloc_one(mm, address, GFP_KERNEL | __GFP_REPEAT);
|
|
}
|
|
|
|
static inline void
|
|
@@ -51,10 +56,15 @@ pmd_free(struct mm_struct *mm, pmd_t *pmd)
|
|
}
|
|
|
|
static inline pte_t *
|
|
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addressi, gfp_t gfp_mask)
|
|
+{
|
|
+ return (pte_t *)__get_free_page(gfp_mask | __GFP_ZERO);
|
|
+}
|
|
+
|
|
+static inline pte_t *
|
|
pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
|
|
{
|
|
- pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
|
|
- return pte;
|
|
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
|
|
}
|
|
|
|
static inline void
|
|
diff --git a/arch/arm/include/asm/pgalloc.h b/arch/arm/include/asm/pgalloc.h
|
|
index 943504f..6052b12 100644
|
|
--- a/arch/arm/include/asm/pgalloc.h
|
|
+++ b/arch/arm/include/asm/pgalloc.h
|
|
@@ -48,6 +48,7 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
|
|
/*
|
|
* Since we have only two-level page tables, these are trivial
|
|
*/
|
|
+#define __pmd_alloc_one(mm,addr,mask) ({ BUG(); ((pmd_t *)2); })
|
|
#define pmd_alloc_one(mm,addr) ({ BUG(); ((pmd_t *)2); })
|
|
#define pmd_free(mm, pmd) do { } while (0)
|
|
#define pud_populate(mm,pmd,pte) BUG()
|
|
@@ -81,17 +82,23 @@ static inline void clean_pte_table(pte_t *pte)
|
|
* +------------+
|
|
*/
|
|
static inline pte_t *
|
|
-pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
|
|
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr, gfp_t gfp_mask)
|
|
{
|
|
pte_t *pte;
|
|
|
|
- pte = (pte_t *)__get_free_page(PGALLOC_GFP);
|
|
+ pte = (pte_t *)__get_free_page(gfp_mask | __GFP_NOTRACK | __GFP_ZERO);
|
|
if (pte)
|
|
clean_pte_table(pte);
|
|
|
|
return pte;
|
|
}
|
|
|
|
+static inline pte_t *
|
|
+pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
|
|
+{
|
|
+ return __pte_alloc_one_kernel(mm, addr, GFP_KERNEL | __GFP_REPEAT);
|
|
+}
|
|
+
|
|
static inline pgtable_t
|
|
pte_alloc_one(struct mm_struct *mm, unsigned long addr)
|
|
{
|
|
diff --git a/arch/avr32/include/asm/pgalloc.h b/arch/avr32/include/asm/pgalloc.h
|
|
index bc7e8ae..cb88080 100644
|
|
--- a/arch/avr32/include/asm/pgalloc.h
|
|
+++ b/arch/avr32/include/asm/pgalloc.h
|
|
@@ -51,10 +51,16 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
|
quicklist_free(QUICK_PGD, NULL, pgd);
|
|
}
|
|
|
|
+static inline pte_t *__pte_alloc_one_kernel(struct mm_struct *mm,
|
|
+ unsigned long address, gfp_t gfp_mask)
|
|
+{
|
|
+ return quicklist_alloc(QUICK_PT, gfp_mask, NULL);
|
|
+}
|
|
+
|
|
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
|
|
unsigned long address)
|
|
{
|
|
- return quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL);
|
|
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
|
|
}
|
|
|
|
static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
|
|
diff --git a/arch/cris/include/asm/pgalloc.h b/arch/cris/include/asm/pgalloc.h
|
|
index 6da975d..20254ee 100644
|
|
--- a/arch/cris/include/asm/pgalloc.h
|
|
+++ b/arch/cris/include/asm/pgalloc.h
|
|
@@ -22,10 +22,16 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
|
free_page((unsigned long)pgd);
|
|
}
|
|
|
|
+static inline pte_t *
|
|
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address,
|
|
+ gfp_t gfp_mask)
|
|
+{
|
|
+ return (pte_t *) __get_free_page(gfp_mask | __GFP_ZERO);
|
|
+}
|
|
+
|
|
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
|
|
{
|
|
- pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
|
|
- return pte;
|
|
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
|
|
}
|
|
|
|
static inline pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
|
|
diff --git a/arch/frv/include/asm/pgalloc.h b/arch/frv/include/asm/pgalloc.h
|
|
index 416d19a..bfc4f7c 100644
|
|
--- a/arch/frv/include/asm/pgalloc.h
|
|
+++ b/arch/frv/include/asm/pgalloc.h
|
|
@@ -35,8 +35,10 @@ extern pgd_t *pgd_alloc(struct mm_struct *);
|
|
extern void pgd_free(struct mm_struct *mm, pgd_t *);
|
|
|
|
extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
|
|
+extern pte_t *__pte_alloc_one_kernel(struct mm_struct *, unsigned long, gfp_t);
|
|
|
|
extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long);
|
|
+extern pgtable_t __pte_alloc_one(struct mm_struct *, unsigned long, gfp_t);
|
|
|
|
static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
|
|
{
|
|
@@ -60,6 +62,7 @@ do { \
|
|
* inside the pgd, so has no extra memory associated with it.
|
|
* (In the PAE case we free the pmds as part of the pgd.)
|
|
*/
|
|
+#define __pmd_alloc_one(mm, addr,mask) ({ BUG(); ((pmd_t *) 2); })
|
|
#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *) 2); })
|
|
#define pmd_free(mm, x) do { } while (0)
|
|
#define __pmd_free_tlb(tlb,x,a) do { } while (0)
|
|
diff --git a/arch/frv/include/asm/pgtable.h b/arch/frv/include/asm/pgtable.h
|
|
index 6bc241e..698e280 100644
|
|
--- a/arch/frv/include/asm/pgtable.h
|
|
+++ b/arch/frv/include/asm/pgtable.h
|
|
@@ -223,6 +223,7 @@ static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address)
|
|
* allocating and freeing a pud is trivial: the 1-entry pud is
|
|
* inside the pgd, so has no extra memory associated with it.
|
|
*/
|
|
+#define __pud_alloc_one(mm, address, mask) NULL
|
|
#define pud_alloc_one(mm, address) NULL
|
|
#define pud_free(mm, x) do { } while (0)
|
|
#define __pud_free_tlb(tlb, x, address) do { } while (0)
|
|
diff --git a/arch/frv/mm/pgalloc.c b/arch/frv/mm/pgalloc.c
|
|
index 4fb63a3..1237a54 100644
|
|
--- a/arch/frv/mm/pgalloc.c
|
|
+++ b/arch/frv/mm/pgalloc.c
|
|
@@ -20,14 +20,19 @@
|
|
|
|
pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((aligned(PAGE_SIZE)));
|
|
|
|
-pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
|
|
+pte_t *__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
|
|
{
|
|
- pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
|
|
+ pte_t *pte = (pte_t *)__get_free_page(gfp_mask);
|
|
if (pte)
|
|
clear_page(pte);
|
|
return pte;
|
|
}
|
|
|
|
+pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
|
|
+{
|
|
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
|
|
+}
|
|
+
|
|
pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
|
|
{
|
|
struct page *page;
|
|
diff --git a/arch/ia64/include/asm/pgalloc.h b/arch/ia64/include/asm/pgalloc.h
|
|
index 96a8d92..0e46e47 100644
|
|
--- a/arch/ia64/include/asm/pgalloc.h
|
|
+++ b/arch/ia64/include/asm/pgalloc.h
|
|
@@ -39,9 +39,15 @@ pgd_populate(struct mm_struct *mm, pgd_t * pgd_entry, pud_t * pud)
|
|
pgd_val(*pgd_entry) = __pa(pud);
|
|
}
|
|
|
|
+static inline pud_t *
|
|
+__pud_alloc_one(struct mm_struct *mm, unsigned long addr, gfp_t gfp_mask)
|
|
+{
|
|
+ return quicklist_alloc(0, gfp_mask, NULL);
|
|
+}
|
|
+
|
|
static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
|
|
{
|
|
- return quicklist_alloc(0, GFP_KERNEL, NULL);
|
|
+ return __pud_alloc_one(mm, addr, GFP_KERNEL);
|
|
}
|
|
|
|
static inline void pud_free(struct mm_struct *mm, pud_t *pud)
|
|
@@ -57,9 +63,15 @@ pud_populate(struct mm_struct *mm, pud_t * pud_entry, pmd_t * pmd)
|
|
pud_val(*pud_entry) = __pa(pmd);
|
|
}
|
|
|
|
+static inline pmd_t *
|
|
+__pmd_alloc_one(struct mm_struct *mm, unsigned long addr, gfp_t gfp_mask)
|
|
+{
|
|
+ return quicklist_alloc(0, gfp_mask, NULL);
|
|
+}
|
|
+
|
|
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
|
|
{
|
|
- return quicklist_alloc(0, GFP_KERNEL, NULL);
|
|
+ return __pmd_alloc_one(mm, addr, GFP_KERNEL);
|
|
}
|
|
|
|
static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
|
|
@@ -95,10 +107,16 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr)
|
|
return page;
|
|
}
|
|
|
|
+static inline pte_t *__pte_alloc_one_kernel(struct mm_struct *mm,
|
|
+ unsigned long addr, gfp_t gfp_mask)
|
|
+{
|
|
+ return quicklist_alloc(0, gfp_mask, NULL);
|
|
+}
|
|
+
|
|
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
|
|
unsigned long addr)
|
|
{
|
|
- return quicklist_alloc(0, GFP_KERNEL, NULL);
|
|
+ return __pte_alloc_one_kernel(mm, addr, GFP_KERNEL);
|
|
}
|
|
|
|
static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
|
|
diff --git a/arch/m32r/include/asm/pgalloc.h b/arch/m32r/include/asm/pgalloc.h
|
|
index 0fc7361..0c1e4ae 100644
|
|
--- a/arch/m32r/include/asm/pgalloc.h
|
|
+++ b/arch/m32r/include/asm/pgalloc.h
|
|
@@ -30,12 +30,16 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
|
free_page((unsigned long)pgd);
|
|
}
|
|
|
|
+static __inline__ pte_t *__pte_alloc_one_kernel(struct mm_struct *mm,
|
|
+ unsigned long address, gfp_t gfp_mask)
|
|
+{
|
|
+ return (pte_t *)__get_free_page(gfp_mask | __GFP_ZERO);
|
|
+}
|
|
+
|
|
static __inline__ pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
|
|
unsigned long address)
|
|
{
|
|
- pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
|
|
-
|
|
- return pte;
|
|
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL);
|
|
}
|
|
|
|
static __inline__ pgtable_t pte_alloc_one(struct mm_struct *mm,
|
|
@@ -66,6 +70,7 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
|
|
* (In the PAE case we free the pmds as part of the pgd.)
|
|
*/
|
|
|
|
+#define __pmd_alloc_one(mm, addr,mask) ({ BUG(); ((pmd_t *)2); })
|
|
#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); })
|
|
#define pmd_free(mm, x) do { } while (0)
|
|
#define __pmd_free_tlb(tlb, x, addr) do { } while (0)
|
|
diff --git a/arch/m68k/include/asm/motorola_pgalloc.h b/arch/m68k/include/asm/motorola_pgalloc.h
|
|
index 2f02f26..0d345e6 100644
|
|
--- a/arch/m68k/include/asm/motorola_pgalloc.h
|
|
+++ b/arch/m68k/include/asm/motorola_pgalloc.h
|
|
@@ -5,13 +5,16 @@
|
|
#include <asm/tlbflush.h>
|
|
|
|
extern pmd_t *get_pointer_table(void);
|
|
+extern pmd_t *__get_pointer_table (gfp_t);
|
|
extern int free_pointer_table(pmd_t *);
|
|
|
|
-static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
|
|
+static inline pte_t *
|
|
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address,
|
|
+ gfp_t gfp_mask)
|
|
{
|
|
pte_t *pte;
|
|
|
|
- pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
|
|
+ pte = (pte_t *)__get_free_page(gfp_mask | __GFP_ZERO);
|
|
if (pte) {
|
|
__flush_page_to_ram(pte);
|
|
flush_tlb_kernel_page(pte);
|
|
@@ -21,6 +24,12 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long ad
|
|
return pte;
|
|
}
|
|
|
|
+static inline pte_t *
|
|
+pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
|
|
+{
|
|
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
|
|
+}
|
|
+
|
|
static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
|
|
{
|
|
cache_page(pte);
|
|
@@ -61,10 +70,15 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t page,
|
|
__free_page(page);
|
|
}
|
|
|
|
+static inline pmd_t *
|
|
+__pmd_alloc_one(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
|
|
+{
|
|
+ return __get_pointer_table(gfp_mask);
|
|
+}
|
|
|
|
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
|
|
{
|
|
- return get_pointer_table();
|
|
+ return __pmd_alloc_one(mm, address, GFP_KERNEL);
|
|
}
|
|
|
|
static inline int pmd_free(struct mm_struct *mm, pmd_t *pmd)
|
|
diff --git a/arch/m68k/include/asm/sun3_pgalloc.h b/arch/m68k/include/asm/sun3_pgalloc.h
|
|
index 48d80d5..29cddb6 100644
|
|
--- a/arch/m68k/include/asm/sun3_pgalloc.h
|
|
+++ b/arch/m68k/include/asm/sun3_pgalloc.h
|
|
@@ -18,6 +18,7 @@
|
|
|
|
extern const char bad_pmd_string[];
|
|
|
|
+#define __pmd_alloc_one(mm,address,mask) ({ BUG(); ((pmd_t *)2); })
|
|
#define pmd_alloc_one(mm,address) ({ BUG(); ((pmd_t *)2); })
|
|
|
|
|
|
@@ -38,10 +39,11 @@ do { \
|
|
tlb_remove_page((tlb), pte); \
|
|
} while (0)
|
|
|
|
-static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
|
|
- unsigned long address)
|
|
+static inline pte_t *
|
|
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address,
|
|
+ gfp_t gfp_mask)
|
|
{
|
|
- unsigned long page = __get_free_page(GFP_KERNEL|__GFP_REPEAT);
|
|
+ unsigned long page = __get_free_page(gfp_mask);
|
|
|
|
if (!page)
|
|
return NULL;
|
|
@@ -50,6 +52,12 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
|
|
return (pte_t *) (page);
|
|
}
|
|
|
|
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
|
|
+ unsigned long address)
|
|
+{
|
|
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
|
|
+}
|
|
+
|
|
static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
|
|
unsigned long address)
|
|
{
|
|
diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c
|
|
index 250b8b7..2a9390e 100644
|
|
--- a/arch/m68k/mm/memory.c
|
|
+++ b/arch/m68k/mm/memory.c
|
|
@@ -58,7 +58,7 @@ void __init init_pointer_table(unsigned long ptable)
|
|
return;
|
|
}
|
|
|
|
-pmd_t *get_pointer_table (void)
|
|
+pmd_t *__get_pointer_table (gfp_t gfp_mask)
|
|
{
|
|
ptable_desc *dp = ptable_list.next;
|
|
unsigned char mask = PD_MARKBITS (dp);
|
|
@@ -75,7 +75,7 @@ pmd_t *get_pointer_table (void)
|
|
void *page;
|
|
ptable_desc *new;
|
|
|
|
- if (!(page = (void *)get_zeroed_page(GFP_KERNEL)))
|
|
+ if (!(page = (void *)get_zeroed_page(gfp_mask)))
|
|
return NULL;
|
|
|
|
flush_tlb_kernel_page(page);
|
|
@@ -98,6 +98,11 @@ pmd_t *get_pointer_table (void)
|
|
return (pmd_t *) (page_address(PD_PAGE(dp)) + off);
|
|
}
|
|
|
|
+pmd_t *get_pointer_table (void)
|
|
+{
|
|
+ return __get_pointer_table(GFP_KERNEL);
|
|
+}
|
|
+
|
|
int free_pointer_table (pmd_t *ptable)
|
|
{
|
|
ptable_desc *dp;
|
|
diff --git a/arch/microblaze/include/asm/pgalloc.h b/arch/microblaze/include/asm/pgalloc.h
|
|
index ebd3579..7df761f 100644
|
|
--- a/arch/microblaze/include/asm/pgalloc.h
|
|
+++ b/arch/microblaze/include/asm/pgalloc.h
|
|
@@ -106,9 +106,11 @@ extern inline void free_pgd_slow(pgd_t *pgd)
|
|
* the pgd will always be present..
|
|
*/
|
|
#define pmd_alloc_one_fast(mm, address) ({ BUG(); ((pmd_t *)1); })
|
|
+#define __pmd_alloc_one(mm, address,mask) ({ BUG(); ((pmd_t *)2); })
|
|
#define pmd_alloc_one(mm, address) ({ BUG(); ((pmd_t *)2); })
|
|
|
|
extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr);
|
|
+extern pte_t *__pte_alloc_one_kernel(struct mm_struct *, unsigned long, gfp_t);
|
|
|
|
static inline struct page *pte_alloc_one(struct mm_struct *mm,
|
|
unsigned long address)
|
|
@@ -175,6 +177,7 @@ extern inline void pte_free(struct mm_struct *mm, struct page *ptepage)
|
|
* We don't have any real pmd's, and this code never triggers because
|
|
* the pgd will always be present..
|
|
*/
|
|
+#define __pmd_alloc_one(mm, address,mask) ({ BUG(); ((pmd_t *)2); })
|
|
#define pmd_alloc_one(mm, address) ({ BUG(); ((pmd_t *)2); })
|
|
#define pmd_free(mm, x) do { } while (0)
|
|
#define __pmd_free_tlb(tlb, x, addr) pmd_free((tlb)->mm, x)
|
|
diff --git a/arch/microblaze/mm/pgtable.c b/arch/microblaze/mm/pgtable.c
|
|
index d1c06d0..a61be2a 100644
|
|
--- a/arch/microblaze/mm/pgtable.c
|
|
+++ b/arch/microblaze/mm/pgtable.c
|
|
@@ -236,13 +236,12 @@ unsigned long iopa(unsigned long addr)
|
|
return pa;
|
|
}
|
|
|
|
-__init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
|
|
- unsigned long address)
|
|
+__init_refok pte_t *__pte_alloc_one_kernel(struct mm_struct *mm,
|
|
+ unsigned long address, gfp_t gfp_mask)
|
|
{
|
|
pte_t *pte;
|
|
if (mem_init_done) {
|
|
- pte = (pte_t *)__get_free_page(GFP_KERNEL |
|
|
- __GFP_REPEAT | __GFP_ZERO);
|
|
+ pte = (pte_t *)__get_free_page(gfp_mask | __GFP_ZERO);
|
|
} else {
|
|
pte = (pte_t *)early_get_page();
|
|
if (pte)
|
|
@@ -260,3 +259,9 @@ void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t flags)
|
|
|
|
map_page(address, phys, pgprot_val(flags));
|
|
}
|
|
+
|
|
+__init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
|
|
+ unsigned long address)
|
|
+{
|
|
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
|
|
+}
|
|
diff --git a/arch/mips/include/asm/pgalloc.h b/arch/mips/include/asm/pgalloc.h
|
|
index 881d18b..f2c5439 100644
|
|
--- a/arch/mips/include/asm/pgalloc.h
|
|
+++ b/arch/mips/include/asm/pgalloc.h
|
|
@@ -64,14 +64,16 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
|
free_pages((unsigned long)pgd, PGD_ORDER);
|
|
}
|
|
|
|
+static inline pte_t *__pte_alloc_one_kernel(struct mm_struct *mm,
|
|
+ unsigned long address, gfp_t gfp_mask)
|
|
+{
|
|
+ return (pte_t *) __get_free_pages(gfp_mask | __GFP_ZERO, PTE_ORDER);
|
|
+}
|
|
+
|
|
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
|
|
unsigned long address)
|
|
{
|
|
- pte_t *pte;
|
|
-
|
|
- pte = (pte_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, PTE_ORDER);
|
|
-
|
|
- return pte;
|
|
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
|
|
}
|
|
|
|
static inline struct page *pte_alloc_one(struct mm_struct *mm,
|
|
@@ -106,16 +108,22 @@ do { \
|
|
|
|
#ifndef __PAGETABLE_PMD_FOLDED
|
|
|
|
-static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
|
|
+static inline pmd_t *
|
|
+__pmd_alloc_one(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
|
|
{
|
|
pmd_t *pmd;
|
|
|
|
- pmd = (pmd_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT, PMD_ORDER);
|
|
+ pmd = (pmd_t *) __get_free_pages(gfp_mask, PMD_ORDER);
|
|
if (pmd)
|
|
pmd_init((unsigned long)pmd, (unsigned long)invalid_pte_table);
|
|
return pmd;
|
|
}
|
|
|
|
+static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
|
|
+{
|
|
+ return __pmd_alloc_one(mm, address, GFP_KERNEL | __GFP_REPEAT);
|
|
+}
|
|
+
|
|
static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
|
|
{
|
|
free_pages((unsigned long)pmd, PMD_ORDER);
|
|
diff --git a/arch/mn10300/include/asm/pgalloc.h b/arch/mn10300/include/asm/pgalloc.h
|
|
index 146bacf..35150ae 100644
|
|
--- a/arch/mn10300/include/asm/pgalloc.h
|
|
+++ b/arch/mn10300/include/asm/pgalloc.h
|
|
@@ -37,6 +37,8 @@ extern pgd_t *pgd_alloc(struct mm_struct *);
|
|
extern void pgd_free(struct mm_struct *, pgd_t *);
|
|
|
|
extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
|
|
+extern pte_t *__pte_alloc_one_kernel(struct mm_struct *, unsigned long, gfp_t);
|
|
+
|
|
extern struct page *pte_alloc_one(struct mm_struct *, unsigned long);
|
|
|
|
static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
|
|
diff --git a/arch/mn10300/mm/pgtable.c b/arch/mn10300/mm/pgtable.c
|
|
index 4ebf117..8ed94e8 100644
|
|
--- a/arch/mn10300/mm/pgtable.c
|
|
+++ b/arch/mn10300/mm/pgtable.c
|
|
@@ -61,14 +61,20 @@ void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
|
|
local_flush_tlb_one(vaddr);
|
|
}
|
|
|
|
-pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
|
|
+pte_t *__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address,
|
|
+ gfp_t gfp_mask)
|
|
{
|
|
- pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
|
|
+ pte_t *pte = (pte_t *)__get_free_page(gfp_mask);
|
|
if (pte)
|
|
clear_page(pte);
|
|
return pte;
|
|
}
|
|
|
|
+pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
|
|
+{
|
|
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
|
|
+}
|
|
+
|
|
struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
|
|
{
|
|
struct page *pte;
|
|
diff --git a/arch/parisc/include/asm/pgalloc.h b/arch/parisc/include/asm/pgalloc.h
|
|
index fc987a1..0284a43 100644
|
|
--- a/arch/parisc/include/asm/pgalloc.h
|
|
+++ b/arch/parisc/include/asm/pgalloc.h
|
|
@@ -61,15 +61,20 @@ static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd)
|
|
(__u32)(__pa((unsigned long)pmd) >> PxD_VALUE_SHIFT));
|
|
}
|
|
|
|
-static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
|
|
+static inline pmd_t *
|
|
+__pmd_alloc_one(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
|
|
{
|
|
- pmd_t *pmd = (pmd_t *)__get_free_pages(GFP_KERNEL|__GFP_REPEAT,
|
|
- PMD_ORDER);
|
|
+ pmd_t *pmd = (pmd_t *)__get_free_pages(gfp_mask, PMD_ORDER);
|
|
if (pmd)
|
|
memset(pmd, 0, PAGE_SIZE<<PMD_ORDER);
|
|
return pmd;
|
|
}
|
|
|
|
+static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
|
|
+{
|
|
+ return __pmd_alloc_one(mm, address, GFP_KERNEL | __GFP_REPEAT);
|
|
+}
|
|
+
|
|
static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
|
|
{
|
|
#ifdef CONFIG_64BIT
|
|
@@ -90,6 +95,7 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
|
|
* inside the pgd, so has no extra memory associated with it.
|
|
*/
|
|
|
|
+#define __pmd_alloc_one(mm, addr, mask) ({ BUG(); ((pmd_t *)2); })
|
|
#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); })
|
|
#define pmd_free(mm, x) do { } while (0)
|
|
#define pgd_populate(mm, pmd, pte) BUG()
|
|
@@ -127,10 +133,15 @@ pte_alloc_one(struct mm_struct *mm, unsigned long address)
|
|
}
|
|
|
|
static inline pte_t *
|
|
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr, gfp_t gfp_mask)
|
|
+{
|
|
+ return (pte_t *)__get_free_page(gfp_mask | __GFP_ZERO);
|
|
+}
|
|
+
|
|
+static inline pte_t *
|
|
pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
|
|
{
|
|
- pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
|
|
- return pte;
|
|
+ return __pte_alloc_one_kernel(mm, addr, GFP_KERNEL | __GFP_REPEAT);
|
|
}
|
|
|
|
static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
|
|
diff --git a/arch/powerpc/include/asm/pgalloc-32.h b/arch/powerpc/include/asm/pgalloc-32.h
|
|
index 580cf73..21b7a94 100644
|
|
--- a/arch/powerpc/include/asm/pgalloc-32.h
|
|
+++ b/arch/powerpc/include/asm/pgalloc-32.h
|
|
@@ -35,6 +35,8 @@ extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
|
|
#endif
|
|
|
|
extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr);
|
|
+extern pte_t *__pte_alloc_one_kernel(struct mm_struct *, unsigned long, gfp_t);
|
|
+
|
|
extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr);
|
|
|
|
static inline void pgtable_free(void *table, unsigned index_size)
|
|
diff --git a/arch/powerpc/include/asm/pgalloc-64.h b/arch/powerpc/include/asm/pgalloc-64.h
|
|
index 292725c..e5ea650 100644
|
|
--- a/arch/powerpc/include/asm/pgalloc-64.h
|
|
+++ b/arch/powerpc/include/asm/pgalloc-64.h
|
|
@@ -51,10 +51,15 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
|
|
|
#define pgd_populate(MM, PGD, PUD) pgd_set(PGD, PUD)
|
|
|
|
+static inline pud_t *
|
|
+__pud_alloc_one(struct mm_struct *mm, unsigned long addr, gfp_t gfp_mask)
|
|
+{
|
|
+ return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE), gfp_mask);
|
|
+}
|
|
+
|
|
static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
|
|
{
|
|
- return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE),
|
|
- GFP_KERNEL|__GFP_REPEAT);
|
|
+ return __pud_alloc_one(mm, addr, GFP_KERNEL | __GFP_REPEAT);
|
|
}
|
|
|
|
static inline void pud_free(struct mm_struct *mm, pud_t *pud)
|
|
@@ -89,10 +94,15 @@ static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
|
|
|
|
#endif /* CONFIG_PPC_64K_PAGES */
|
|
|
|
+static inline pmd_t *
|
|
+__pmd_alloc_one(struct mm_struct *mm, unsigned long addr, gfp_t gfp_mask)
|
|
+{
|
|
+ return kmem_cache_alloc(PGT_CACHE(PMD_INDEX_SIZE), gfp_mask);
|
|
+}
|
|
+
|
|
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
|
|
{
|
|
- return kmem_cache_alloc(PGT_CACHE(PMD_INDEX_SIZE),
|
|
- GFP_KERNEL|__GFP_REPEAT);
|
|
+ return __pmd_alloc_one(mm, addr, GFP_KERNEL | __GFP_REPEAT);
|
|
}
|
|
|
|
static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
|
|
@@ -100,10 +110,17 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
|
|
kmem_cache_free(PGT_CACHE(PMD_INDEX_SIZE), pmd);
|
|
}
|
|
|
|
+static inline pte_t *
|
|
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address,
|
|
+ gfp_t gfp_mask)
|
|
+{
|
|
+ return (pte_t *)__get_free_page(gfp_mask | __GFP_ZERO);
|
|
+}
|
|
+
|
|
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
|
|
unsigned long address)
|
|
{
|
|
- return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
|
|
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
|
|
}
|
|
|
|
static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
|
|
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
|
|
index 6c856fb..262365a 100644
|
|
--- a/arch/powerpc/mm/pgtable_32.c
|
|
+++ b/arch/powerpc/mm/pgtable_32.c
|
|
@@ -96,14 +96,15 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
|
#endif
|
|
}
|
|
|
|
-__init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
|
|
+__init_refok pte_t *
|
|
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
|
|
{
|
|
pte_t *pte;
|
|
extern int mem_init_done;
|
|
extern void *early_get_page(void);
|
|
|
|
if (mem_init_done) {
|
|
- pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
|
|
+ pte = (pte_t *)__get_free_page(gfp_mask | __GFP_ZERO);
|
|
} else {
|
|
pte = (pte_t *)early_get_page();
|
|
if (pte)
|
|
@@ -112,6 +113,11 @@ __init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long add
|
|
return pte;
|
|
}
|
|
|
|
+__init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
|
|
+{
|
|
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
|
|
+}
|
|
+
|
|
pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
|
|
{
|
|
struct page *ptepage;
|
|
diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h
|
|
index 43078c1..94da024 100644
|
|
--- a/arch/s390/include/asm/pgalloc.h
|
|
+++ b/arch/s390/include/asm/pgalloc.h
|
|
@@ -18,9 +18,11 @@
|
|
#include <linux/mm.h>
|
|
|
|
unsigned long *crst_table_alloc(struct mm_struct *);
|
|
+unsigned long * __crst_table_alloc(struct mm_struct *, int , gfp_t);
|
|
void crst_table_free(struct mm_struct *, unsigned long *);
|
|
|
|
unsigned long *page_table_alloc(struct mm_struct *, unsigned long);
|
|
+unsigned long *__page_table_alloc(struct mm_struct *, gfp_t);
|
|
void page_table_free(struct mm_struct *, unsigned long *);
|
|
void page_table_free_rcu(struct mmu_gather *, unsigned long *);
|
|
|
|
@@ -55,9 +57,11 @@ static inline unsigned long pgd_entry_type(struct mm_struct *mm)
|
|
return _SEGMENT_ENTRY_EMPTY;
|
|
}
|
|
|
|
+#define __pud_alloc_one(mm,address,mask) ({ BUG(); ((pud_t *)2); })
|
|
#define pud_alloc_one(mm,address) ({ BUG(); ((pud_t *)2); })
|
|
#define pud_free(mm, x) do { } while (0)
|
|
|
|
+#define __pmd_alloc_one(mm,address,mask) ({ BUG(); ((pmd_t *)2); })
|
|
#define pmd_alloc_one(mm,address) ({ BUG(); ((pmd_t *)2); })
|
|
#define pmd_free(mm, x) do { } while (0)
|
|
|
|
@@ -78,22 +82,34 @@ static inline unsigned long pgd_entry_type(struct mm_struct *mm)
|
|
int crst_table_upgrade(struct mm_struct *, unsigned long limit);
|
|
void crst_table_downgrade(struct mm_struct *, unsigned long limit);
|
|
|
|
-static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
|
|
+static inline pud_t *
|
|
+__pud_alloc_one(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
|
|
{
|
|
- unsigned long *table = crst_table_alloc(mm);
|
|
+ unsigned long *table = __crst_table_alloc(mm, mm->context.noexec, gfp_mask);
|
|
if (table)
|
|
crst_table_init(table, _REGION3_ENTRY_EMPTY);
|
|
return (pud_t *) table;
|
|
}
|
|
+
|
|
+static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
|
|
+{
|
|
+ return __pud_alloc_one(mm, address, GFP_KERNEL);
|
|
+}
|
|
#define pud_free(mm, pud) crst_table_free(mm, (unsigned long *) pud)
|
|
|
|
-static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
|
|
+static inline pmd_t *
|
|
+__pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr, gfp_t gfp_mask)
|
|
{
|
|
- unsigned long *table = crst_table_alloc(mm);
|
|
+ unsigned long *table = __crst_table_alloc(mm, mm->context.noexec, gfp_mask);
|
|
if (table)
|
|
crst_table_init(table, _SEGMENT_ENTRY_EMPTY);
|
|
return (pmd_t *) table;
|
|
}
|
|
+
|
|
+static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
|
|
+{
|
|
+ return __pmd_alloc_one(mm, vmaddr, GFP_KERNEL);
|
|
+}
|
|
#define pmd_free(mm, pmd) crst_table_free(mm, (unsigned long *) pmd)
|
|
|
|
static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
|
|
@@ -131,7 +147,11 @@ static inline void pmd_populate(struct mm_struct *mm,
|
|
/*
|
|
* page table entry allocation/free routines.
|
|
*/
|
|
-#define pte_alloc_one_kernel(mm, vmaddr) ((pte_t *) page_table_alloc(mm, vmaddr))
|
|
+#define __pte_alloc_one_kernel(mm, vmaddr, mask) \
|
|
+ ((pte_t *) __page_table_alloc((mm), (mask)))
|
|
+#define pte_alloc_one_kernel(mm, vmaddr) \
|
|
+ ((pte_t *) __pte_alloc_one_kernel((mm), (vmaddr), GFP_KERNEL|__GFP_REPEAT)
|
|
+
|
|
#define pte_alloc_one(mm, vmaddr) ((pte_t *) page_table_alloc(mm, vmaddr))
|
|
|
|
#define pte_free_kernel(mm, pte) page_table_free(mm, (unsigned long *) pte)
|
|
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
|
|
index a3db5a3..04cbea3 100644
|
|
--- a/arch/s390/mm/pgtable.c
|
|
+++ b/arch/s390/mm/pgtable.c
|
|
@@ -33,15 +33,21 @@
|
|
#endif
|
|
|
|
|
|
-unsigned long *crst_table_alloc(struct mm_struct *mm)
|
|
+unsigned long *
|
|
+__crst_table_alloc(struct mm_struct *mm, int noexec, gfp_t gfp_mask)
|
|
{
|
|
- struct page *page = alloc_pages(GFP_KERNEL, ALLOC_ORDER);
|
|
+ struct page *page = alloc_pages(gfp_mask, ALLOC_ORDER);
|
|
|
|
if (!page)
|
|
return NULL;
|
|
return (unsigned long *) page_to_phys(page);
|
|
}
|
|
|
|
+unsigned long *crst_table_alloc(struct mm_struct *mm, int noexec)
|
|
+{
|
|
+ return __crst_table_alloc(mm, noexec, GFP_KERNEL);
|
|
+}
|
|
+
|
|
void crst_table_free(struct mm_struct *mm, unsigned long *table)
|
|
{
|
|
free_pages((unsigned long) table, ALLOC_ORDER);
|
|
@@ -612,7 +618,7 @@ static inline unsigned int atomic_xor_bits(atomic_t *v, unsigned int bits)
|
|
/*
|
|
* page table entry allocation/free routines.
|
|
*/
|
|
-unsigned long *page_table_alloc(struct mm_struct *mm, unsigned long vmaddr)
|
|
+unsigned long *__page_table_alloc(struct mm_struct *mm, gfp_t gfp_mask)
|
|
{
|
|
struct page *page;
|
|
unsigned long *table;
|
|
@@ -632,7 +638,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm, unsigned long vmaddr)
|
|
}
|
|
if ((mask & FRAG_MASK) == FRAG_MASK) {
|
|
spin_unlock_bh(&mm->context.list_lock);
|
|
- page = alloc_page(GFP_KERNEL|__GFP_REPEAT);
|
|
+ page = alloc_page(gfp_mask);
|
|
if (!page)
|
|
return NULL;
|
|
pgtable_page_ctor(page);
|
|
@@ -652,6 +658,11 @@ unsigned long *page_table_alloc(struct mm_struct *mm, unsigned long vmaddr)
|
|
return table;
|
|
}
|
|
|
|
+unsigned long *page_table_alloc(struct mm_struct *mm)
|
|
+{
|
|
+ return __page_table_alloc(mm, GFP_KERNEL | __GFP_REPEAT);
|
|
+}
|
|
+
|
|
void page_table_free(struct mm_struct *mm, unsigned long *table)
|
|
{
|
|
struct page *page;
|
|
diff --git a/arch/score/include/asm/pgalloc.h b/arch/score/include/asm/pgalloc.h
|
|
index 059a61b..1a0a3a5 100644
|
|
--- a/arch/score/include/asm/pgalloc.h
|
|
+++ b/arch/score/include/asm/pgalloc.h
|
|
@@ -37,15 +37,16 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
|
free_pages((unsigned long)pgd, PGD_ORDER);
|
|
}
|
|
|
|
+static inline pte_t *
|
|
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
|
|
+{
|
|
+ return (pte_t *) __get_free_pages(gfp_mask | __GFP_ZERO, PTE_ORDER);
|
|
+}
|
|
+
|
|
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
|
|
unsigned long address)
|
|
{
|
|
- pte_t *pte;
|
|
-
|
|
- pte = (pte_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO,
|
|
- PTE_ORDER);
|
|
-
|
|
- return pte;
|
|
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
|
|
}
|
|
|
|
static inline struct page *pte_alloc_one(struct mm_struct *mm,
|
|
diff --git a/arch/sh/include/asm/pgalloc.h b/arch/sh/include/asm/pgalloc.h
|
|
index 8c00785..aaed989 100644
|
|
--- a/arch/sh/include/asm/pgalloc.h
|
|
+++ b/arch/sh/include/asm/pgalloc.h
|
|
@@ -31,10 +31,16 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
|
|
/*
|
|
* Allocate and free page tables.
|
|
*/
|
|
+static inline pte_t *__pte_alloc_one_kernel(struct mm_struct *mm,
|
|
+ unsigned long address, gfp_t gfp_mask)
|
|
+{
|
|
+ return quicklist_alloc(QUICK_PT, gfp_mask, NULL);
|
|
+}
|
|
+
|
|
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
|
|
unsigned long address)
|
|
{
|
|
- return quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL);
|
|
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
|
|
}
|
|
|
|
static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
|
|
diff --git a/arch/sh/mm/pgtable.c b/arch/sh/mm/pgtable.c
|
|
index 26e03a1..b938eb8 100644
|
|
--- a/arch/sh/mm/pgtable.c
|
|
+++ b/arch/sh/mm/pgtable.c
|
|
@@ -45,9 +45,15 @@ void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
|
|
set_pud(pud, __pud((unsigned long)pmd));
|
|
}
|
|
|
|
+pmd_t *
|
|
+__pmd_alloc_one(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
|
|
+{
|
|
+ return kmem_cache_alloc(pmd_cachep, gfp_mask | __GFP_ZERO);
|
|
+}
|
|
+
|
|
pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
|
|
{
|
|
- return kmem_cache_alloc(pmd_cachep, PGALLOC_GFP);
|
|
+ return __pmd_alloc_one(mm, address, GFP_KERNEL | __GFP_REPEAT);
|
|
}
|
|
|
|
void pmd_free(struct mm_struct *mm, pmd_t *pmd)
|
|
diff --git a/arch/tile/include/asm/pgalloc.h b/arch/tile/include/asm/pgalloc.h
|
|
index 1b90250..0d12a51 100644
|
|
--- a/arch/tile/include/asm/pgalloc.h
|
|
+++ b/arch/tile/include/asm/pgalloc.h
|
|
@@ -86,9 +86,16 @@ static inline void pte_free(struct mm_struct *mm, struct page *pte)
|
|
#define pmd_pgtable(pmd) pmd_page(pmd)
|
|
|
|
static inline pte_t *
|
|
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address,
|
|
+ gfp_t gfp_mask)
|
|
+{
|
|
+ return pfn_to_kaddr(page_to_pfn(__pte_alloc_one(mm, address, gfp_mask)));
|
|
+}
|
|
+
|
|
+static inline pte_t *
|
|
pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
|
|
{
|
|
- return pfn_to_kaddr(page_to_pfn(pte_alloc_one(mm, address)));
|
|
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
|
|
}
|
|
|
|
static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
|
|
diff --git a/arch/tile/mm/pgtable.c b/arch/tile/mm/pgtable.c
|
|
index 345edfe..6ce0ef6 100644
|
|
--- a/arch/tile/mm/pgtable.c
|
|
+++ b/arch/tile/mm/pgtable.c
|
|
@@ -280,10 +280,11 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
|
|
|
#define L2_USER_PGTABLE_PAGES (1 << L2_USER_PGTABLE_ORDER)
|
|
|
|
-struct page *pgtable_alloc_one(struct mm_struct *mm, unsigned long address,
|
|
- int order)
|
|
+struct page *
|
|
+__pte_alloc_one(struct mm_struct *mm, unsigned long address, int order,
|
|
+ gfp_t gfp_mask)
|
|
{
|
|
- gfp_t flags = GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO;
|
|
+ gfp_t flags = gfp_mask|__GFP_REPEAT|__GFP_ZERO;
|
|
struct page *p;
|
|
int i;
|
|
|
|
@@ -305,6 +306,11 @@ struct page *pgtable_alloc_one(struct mm_struct *mm, unsigned long address,
|
|
return p;
|
|
}
|
|
|
|
+struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address, int order)
|
|
+{
|
|
+ return __pte_alloc_one(mm, address, GFP_KERNEL);
|
|
+}
|
|
+
|
|
/*
|
|
* Free page immediately (used in __pte_alloc if we raced with another
|
|
* process). We have to correct whatever pte_alloc_one() did before
|
|
diff --git a/arch/um/include/asm/pgalloc.h b/arch/um/include/asm/pgalloc.h
|
|
index bf90b2a..8d0507b 100644
|
|
--- a/arch/um/include/asm/pgalloc.h
|
|
+++ b/arch/um/include/asm/pgalloc.h
|
|
@@ -26,6 +26,7 @@ extern pgd_t *pgd_alloc(struct mm_struct *);
|
|
extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
|
|
|
|
extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
|
|
+extern pte_t *__pte_alloc_one_kernel(struct mm_struct *, unsigned long, gfp_t);
|
|
extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long);
|
|
|
|
static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
|
|
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
|
|
index ebb86b2..41be7e8 100644
|
|
--- a/arch/um/kernel/mem.c
|
|
+++ b/arch/um/kernel/mem.c
|
|
@@ -286,12 +286,15 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
|
free_page((unsigned long) pgd);
|
|
}
|
|
|
|
-pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
|
|
+pte_t *
|
|
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
|
|
{
|
|
- pte_t *pte;
|
|
+ return (pte_t *)__get_free_page(gfp_mask | __GFP_ZERO);
|
|
+}
|
|
|
|
- pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
|
|
- return pte;
|
|
+pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
|
|
+{
|
|
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
|
|
}
|
|
|
|
pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
|
|
@@ -305,15 +308,21 @@ pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
|
|
}
|
|
|
|
#ifdef CONFIG_3_LEVEL_PGTABLES
|
|
-pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
|
|
+pmd_t *
|
|
+__pmd_alloc_one(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
|
|
{
|
|
- pmd_t *pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
|
|
+ pmd_t *pmd = (pmd_t *) __get_free_page(gfp_mask);
|
|
|
|
if (pmd)
|
|
memset(pmd, 0, PAGE_SIZE);
|
|
|
|
return pmd;
|
|
}
|
|
+
|
|
+pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
|
|
+{
|
|
+ return __pmd_alloc_one(mm, address, GFP_KERNEL);
|
|
+}
|
|
#endif
|
|
|
|
void *uml_kmalloc(int size, int flags)
|
|
diff --git a/arch/x86/include/asm/pgalloc.h b/arch/x86/include/asm/pgalloc.h
|
|
index b4389a4..db83bd4 100644
|
|
--- a/arch/x86/include/asm/pgalloc.h
|
|
+++ b/arch/x86/include/asm/pgalloc.h
|
|
@@ -34,6 +34,7 @@ extern pgd_t *pgd_alloc(struct mm_struct *);
|
|
extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
|
|
|
|
extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
|
|
+extern pte_t *__pte_alloc_one_kernel(struct mm_struct *, unsigned long, gfp_t);
|
|
extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long);
|
|
|
|
/* Should really implement gc for free page table pages. This could be
|
|
@@ -78,9 +79,15 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
|
|
#define pmd_pgtable(pmd) pmd_page(pmd)
|
|
|
|
#if PAGETABLE_LEVELS > 2
|
|
+static inline pmd_t *
|
|
+__pmd_alloc_one(struct mm_struct *mm, unsigned long addr, gfp_t gfp_mask)
|
|
+{
|
|
+ return (pmd_t *)get_zeroed_page(gfp_mask);
|
|
+}
|
|
+
|
|
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
|
|
{
|
|
- return (pmd_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
|
|
+ return __pmd_alloc_one(mm, addr, GFP_KERNEL | __GFP_REPEAT);
|
|
}
|
|
|
|
static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
|
|
@@ -114,9 +121,15 @@ static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
|
|
set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pud)));
|
|
}
|
|
|
|
+static inline pud_t *
|
|
+__pud_alloc_one(struct mm_struct *mm, unsigned long addr, gfp_t gfp_mask)
|
|
+{
|
|
+ return (pud_t *)get_zeroed_page(gfp_mask);
|
|
+}
|
|
+
|
|
static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
|
|
{
|
|
- return (pud_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
|
|
+ return __pud_alloc_one(mm, addr, GFP_KERNEL | __GFP_REPEAT);
|
|
}
|
|
|
|
static inline void pud_free(struct mm_struct *mm, pud_t *pud)
|
|
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
|
|
index 8573b83..62a4f63 100644
|
|
--- a/arch/x86/mm/pgtable.c
|
|
+++ b/arch/x86/mm/pgtable.c
|
|
@@ -15,9 +15,15 @@
|
|
|
|
gfp_t __userpte_alloc_gfp = PGALLOC_GFP | PGALLOC_USER_GFP;
|
|
|
|
+pte_t *
|
|
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address, gfp_t gfp_mask)
|
|
+{
|
|
+ return (pte_t *)__get_free_page(gfp_mask | __GFP_NOTRACK | __GFP_ZERO);
|
|
+}
|
|
+
|
|
pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
|
|
{
|
|
- return (pte_t *)__get_free_page(PGALLOC_GFP);
|
|
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
|
|
}
|
|
|
|
pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
|
|
diff --git a/arch/xtensa/include/asm/pgalloc.h b/arch/xtensa/include/asm/pgalloc.h
|
|
index 40cf9bc..d5a23ae 100644
|
|
--- a/arch/xtensa/include/asm/pgalloc.h
|
|
+++ b/arch/xtensa/include/asm/pgalloc.h
|
|
@@ -42,10 +42,17 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
|
|
|
extern struct kmem_cache *pgtable_cache;
|
|
|
|
+static inline pte_t *
|
|
+__pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address,
|
|
+ gfp_t gfp_mask)
|
|
+{
|
|
+ return kmem_cache_alloc(pgtable_cache, gfp_mask);
|
|
+}
|
|
+
|
|
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
|
|
unsigned long address)
|
|
{
|
|
- return kmem_cache_alloc(pgtable_cache, GFP_KERNEL|__GFP_REPEAT);
|
|
+ return __pte_alloc_one_kernel(mm, address, GFP_KERNEL | __GFP_REPEAT);
|
|
}
|
|
|
|
static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
|
|
diff --git a/include/asm-generic/4level-fixup.h b/include/asm-generic/4level-fixup.h
|
|
index 77ff547..f638309 100644
|
|
--- a/include/asm-generic/4level-fixup.h
|
|
+++ b/include/asm-generic/4level-fixup.h
|
|
@@ -10,10 +10,14 @@
|
|
|
|
#define pud_t pgd_t
|
|
|
|
-#define pmd_alloc(mm, pud, address) \
|
|
- ((unlikely(pgd_none(*(pud))) && __pmd_alloc(mm, pud, address))? \
|
|
+#define pmd_alloc_with_mask(mm, pud, address, mask) \
|
|
+ ((unlikely(pgd_none(*(pud))) && __pmd_alloc(mm, pud, address, mask))? \
|
|
NULL: pmd_offset(pud, address))
|
|
|
|
+#define pmd_alloc(mm, pud, address) \
|
|
+ pmd_alloc_with_mask(mm, pud, address, GFP_KERNEL)
|
|
+
|
|
+#define pud_alloc_with_mask(mm, pgd, address, mask) (pgd)
|
|
#define pud_alloc(mm, pgd, address) (pgd)
|
|
#define pud_offset(pgd, start) (pgd)
|
|
#define pud_none(pud) 0
|
|
diff --git a/include/asm-generic/pgtable-nopmd.h b/include/asm-generic/pgtable-nopmd.h
|
|
index 725612b..96ca8da 100644
|
|
--- a/include/asm-generic/pgtable-nopmd.h
|
|
+++ b/include/asm-generic/pgtable-nopmd.h
|
|
@@ -55,7 +55,8 @@ static inline pmd_t * pmd_offset(pud_t * pud, unsigned long address)
|
|
* allocating and freeing a pmd is trivial: the 1-entry pmd is
|
|
* inside the pud, so has no extra memory associated with it.
|
|
*/
|
|
-#define pmd_alloc_one(mm, address) NULL
|
|
+#define __pmd_alloc_one(mm, address, mask) NULL
|
|
+#define pmd_alloc_one(mm, address) NULL
|
|
static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
|
|
{
|
|
}
|
|
diff --git a/include/asm-generic/pgtable-nopud.h b/include/asm-generic/pgtable-nopud.h
|
|
index 810431d..5a21868 100644
|
|
--- a/include/asm-generic/pgtable-nopud.h
|
|
+++ b/include/asm-generic/pgtable-nopud.h
|
|
@@ -50,6 +50,7 @@ static inline pud_t * pud_offset(pgd_t * pgd, unsigned long address)
|
|
* allocating and freeing a pud is trivial: the 1-entry pud is
|
|
* inside the pgd, so has no extra memory associated with it.
|
|
*/
|
|
+#define __pud_alloc_one(mm, address, mask) NULL
|
|
#define pud_alloc_one(mm, address) NULL
|
|
#define pud_free(mm, x) do { } while (0)
|
|
#define __pud_free_tlb(tlb, x, a) do { } while (0)
|
|
diff --git a/include/linux/mm.h b/include/linux/mm.h
|
|
index b36d08c..aeda962 100644
|
|
--- a/include/linux/mm.h
|
|
+++ b/include/linux/mm.h
|
|
@@ -1149,44 +1149,60 @@ static inline pte_t *get_locked_pte(struct mm_struct *mm, unsigned long addr,
|
|
|
|
#ifdef __PAGETABLE_PUD_FOLDED
|
|
static inline int __pud_alloc(struct mm_struct *mm, pgd_t *pgd,
|
|
- unsigned long address)
|
|
+ unsigned long address, gfp_t gfp_mask)
|
|
{
|
|
return 0;
|
|
}
|
|
#else
|
|
-int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address);
|
|
+int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address,
|
|
+ gfp_t gfp_mask);
|
|
#endif
|
|
|
|
#ifdef __PAGETABLE_PMD_FOLDED
|
|
static inline int __pmd_alloc(struct mm_struct *mm, pud_t *pud,
|
|
- unsigned long address)
|
|
+ unsigned long address, gfp_t gfp_mask)
|
|
{
|
|
return 0;
|
|
}
|
|
#else
|
|
-int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address);
|
|
+int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address,
|
|
+ gfp_t gfp_mask);
|
|
#endif
|
|
|
|
int __pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma,
|
|
pmd_t *pmd, unsigned long address);
|
|
-int __pte_alloc_kernel(pmd_t *pmd, unsigned long address);
|
|
+int __pte_alloc_kernel(pmd_t *pmd, unsigned long address, gfp_t gfp_mask);
|
|
|
|
/*
|
|
* The following ifdef needed to get the 4level-fixup.h header to work.
|
|
* Remove it when 4level-fixup.h has been removed.
|
|
*/
|
|
#if defined(CONFIG_MMU) && !defined(__ARCH_HAS_4LEVEL_HACK)
|
|
-static inline pud_t *pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
|
|
+static inline pud_t *pud_alloc_with_mask(struct mm_struct *mm, pgd_t *pgd,
|
|
+ unsigned long address, gfp_t gfp_mask)
|
|
{
|
|
- return (unlikely(pgd_none(*pgd)) && __pud_alloc(mm, pgd, address))?
|
|
+ return (unlikely(pgd_none(*pgd)) && __pud_alloc(mm, pgd, address, gfp_mask))?
|
|
NULL: pud_offset(pgd, address);
|
|
}
|
|
|
|
-static inline pmd_t *pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
|
|
+static inline pud_t *pud_alloc(struct mm_struct *mm, pgd_t *pgd,
|
|
+ unsigned long address)
|
|
{
|
|
- return (unlikely(pud_none(*pud)) && __pmd_alloc(mm, pud, address))?
|
|
+ return pud_alloc_with_mask(mm, pgd, address, GFP_KERNEL);
|
|
+}
|
|
+
|
|
+static inline pmd_t *pmd_alloc_with_mask(struct mm_struct *mm, pud_t *pud,
|
|
+ unsigned long address, gfp_t gfp_mask)
|
|
+{
|
|
+ return (unlikely(pud_none(*pud)) && __pmd_alloc(mm, pud, address, gfp_mask))?
|
|
NULL: pmd_offset(pud, address);
|
|
}
|
|
+
|
|
+static inline pmd_t *pmd_alloc(struct mm_struct *mm, pud_t *pud,
|
|
+ unsigned long address)
|
|
+{
|
|
+ return pmd_alloc_with_mask(mm, pud, address, GFP_KERNEL);
|
|
+}
|
|
#endif /* CONFIG_MMU && !__ARCH_HAS_4LEVEL_HACK */
|
|
|
|
#if USE_SPLIT_PTLOCKS
|
|
@@ -1247,8 +1263,12 @@ static inline void pgtable_page_dtor(struct page *page)
|
|
pmd, address))? \
|
|
NULL: pte_offset_map_lock(mm, pmd, address, ptlp))
|
|
|
|
+#define pte_alloc_kernel_with_mask(pmd, address, mask) \
|
|
+ ((unlikely(pmd_none(*(pmd))) && __pte_alloc_kernel(pmd, address, mask))? \
|
|
+ NULL: pte_offset_kernel(pmd, address))
|
|
+
|
|
#define pte_alloc_kernel(pmd, address) \
|
|
- ((unlikely(pmd_none(*(pmd))) && __pte_alloc_kernel(pmd, address))? \
|
|
+ ((unlikely(pmd_none(*(pmd))) && __pte_alloc_kernel(pmd, address, GFP_KERNEL))? \
|
|
NULL: pte_offset_kernel(pmd, address))
|
|
|
|
extern void free_area_init(unsigned long * zones_size);
|
|
diff --git a/mm/memory.c b/mm/memory.c
|
|
index 906bc23..ed06ba2 100644
|
|
--- a/mm/memory.c
|
|
+++ b/mm/memory.c
|
|
@@ -608,9 +608,9 @@ int __pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma,
|
|
return 0;
|
|
}
|
|
|
|
-int __pte_alloc_kernel(pmd_t *pmd, unsigned long address)
|
|
+int __pte_alloc_kernel(pmd_t *pmd, unsigned long address, gfp_t gfp_mask)
|
|
{
|
|
- pte_t *new = pte_alloc_one_kernel(&init_mm, address);
|
|
+ pte_t *new = __pte_alloc_one_kernel(&init_mm, address, gfp_mask);
|
|
if (!new)
|
|
return -ENOMEM;
|
|
|
|
@@ -3560,9 +3560,10 @@ retry:
|
|
* Allocate page upper directory.
|
|
* We've already handled the fast-path in-line.
|
|
*/
|
|
-int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
|
|
+int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address,
|
|
+ gfp_t gfp_mask)
|
|
{
|
|
- pud_t *new = pud_alloc_one(mm, address);
|
|
+ pud_t *new = __pud_alloc_one(mm, address, gfp_mask);
|
|
if (!new)
|
|
return -ENOMEM;
|
|
|
|
@@ -3583,9 +3584,10 @@ int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
|
|
* Allocate page middle directory.
|
|
* We've already handled the fast-path in-line.
|
|
*/
|
|
-int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
|
|
+int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address,
|
|
+ gfp_t gfp_mask)
|
|
{
|
|
- pmd_t *new = pmd_alloc_one(mm, address);
|
|
+ pmd_t *new = __pmd_alloc_one(mm, address, gfp_mask);
|
|
if (!new)
|
|
return -ENOMEM;
|
|
|
|
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
|
|
index 2aad499..85f0e13 100644
|
|
--- a/mm/vmalloc.c
|
|
+++ b/mm/vmalloc.c
|
|
@@ -87,8 +87,8 @@ static void vunmap_page_range(unsigned long addr, unsigned long end)
|
|
} while (pgd++, addr = next, addr != end);
|
|
}
|
|
|
|
-static int vmap_pte_range(pmd_t *pmd, unsigned long addr,
|
|
- unsigned long end, pgprot_t prot, struct page **pages, int *nr)
|
|
+static int vmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
|
|
+ pgprot_t prot, struct page **pages, int *nr, gfp_t gfp_mask)
|
|
{
|
|
pte_t *pte;
|
|
|
|
@@ -97,7 +97,7 @@ static int vmap_pte_range(pmd_t *pmd, unsigned long addr,
|
|
* callers keep track of where we're up to.
|
|
*/
|
|
|
|
- pte = pte_alloc_kernel(pmd, addr);
|
|
+ pte = pte_alloc_kernel_with_mask(pmd, addr, gfp_mask);
|
|
if (!pte)
|
|
return -ENOMEM;
|
|
do {
|
|
@@ -114,34 +114,34 @@ static int vmap_pte_range(pmd_t *pmd, unsigned long addr,
|
|
}
|
|
|
|
static int vmap_pmd_range(pud_t *pud, unsigned long addr,
|
|
- unsigned long end, pgprot_t prot, struct page **pages, int *nr)
|
|
+ unsigned long end, pgprot_t prot, struct page **pages, int *nr, gfp_t gfp_mask)
|
|
{
|
|
pmd_t *pmd;
|
|
unsigned long next;
|
|
|
|
- pmd = pmd_alloc(&init_mm, pud, addr);
|
|
+ pmd = pmd_alloc_with_mask(&init_mm, pud, addr, gfp_mask);
|
|
if (!pmd)
|
|
return -ENOMEM;
|
|
do {
|
|
next = pmd_addr_end(addr, end);
|
|
- if (vmap_pte_range(pmd, addr, next, prot, pages, nr))
|
|
+ if (vmap_pte_range(pmd, addr, next, prot, pages, nr, gfp_mask))
|
|
return -ENOMEM;
|
|
} while (pmd++, addr = next, addr != end);
|
|
return 0;
|
|
}
|
|
|
|
-static int vmap_pud_range(pgd_t *pgd, unsigned long addr,
|
|
- unsigned long end, pgprot_t prot, struct page **pages, int *nr)
|
|
+static int vmap_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end,
|
|
+ pgprot_t prot, struct page **pages, int *nr, gfp_t gfp_mask)
|
|
{
|
|
pud_t *pud;
|
|
unsigned long next;
|
|
|
|
- pud = pud_alloc(&init_mm, pgd, addr);
|
|
+ pud = pud_alloc_with_mask(&init_mm, pgd, addr, gfp_mask);
|
|
if (!pud)
|
|
return -ENOMEM;
|
|
do {
|
|
next = pud_addr_end(addr, end);
|
|
- if (vmap_pmd_range(pud, addr, next, prot, pages, nr))
|
|
+ if (vmap_pmd_range(pud, addr, next, prot, pages, nr, gfp_mask))
|
|
return -ENOMEM;
|
|
} while (pud++, addr = next, addr != end);
|
|
return 0;
|
|
@@ -153,8 +153,8 @@ static int vmap_pud_range(pgd_t *pgd, unsigned long addr,
|
|
*
|
|
* Ie. pte at addr+N*PAGE_SIZE shall point to pfn corresponding to pages[N]
|
|
*/
|
|
-static int vmap_page_range_noflush(unsigned long start, unsigned long end,
|
|
- pgprot_t prot, struct page **pages)
|
|
+static int __vmap_page_range_noflush(unsigned long start, unsigned long end,
|
|
+ pgprot_t prot, struct page **pages, gfp_t gfp_mask)
|
|
{
|
|
pgd_t *pgd;
|
|
unsigned long next;
|
|
@@ -166,7 +166,7 @@ static int vmap_page_range_noflush(unsigned long start, unsigned long end,
|
|
pgd = pgd_offset_k(addr);
|
|
do {
|
|
next = pgd_addr_end(addr, end);
|
|
- err = vmap_pud_range(pgd, addr, next, prot, pages, &nr);
|
|
+ err = vmap_pud_range(pgd, addr, next, prot, pages, &nr, gfp_mask);
|
|
if (err)
|
|
return err;
|
|
} while (pgd++, addr = next, addr != end);
|
|
@@ -174,16 +174,29 @@ static int vmap_page_range_noflush(unsigned long start, unsigned long end,
|
|
return nr;
|
|
}
|
|
|
|
-static int vmap_page_range(unsigned long start, unsigned long end,
|
|
- pgprot_t prot, struct page **pages)
|
|
+
|
|
+static int vmap_page_range_noflush(unsigned long start, unsigned long end,
|
|
+ pgprot_t prot, struct page **pages)
|
|
+{
|
|
+ return __vmap_page_range_noflush(start, end, prot, pages, GFP_KERNEL);
|
|
+}
|
|
+
|
|
+static int __vmap_page_range(unsigned long start, unsigned long end,
|
|
+ pgprot_t prot, struct page **pages, gfp_t gfp_mask)
|
|
{
|
|
int ret;
|
|
|
|
- ret = vmap_page_range_noflush(start, end, prot, pages);
|
|
+ ret = __vmap_page_range_noflush(start, end, prot, pages, gfp_mask);
|
|
flush_cache_vmap(start, end);
|
|
return ret;
|
|
}
|
|
|
|
+static int vmap_page_range(unsigned long start, unsigned long end,
|
|
+ pgprot_t prot, struct page **pages)
|
|
+{
|
|
+ return __vmap_page_range(start, end, prot, pages, GFP_KERNEL);
|
|
+}
|
|
+
|
|
int is_vmalloc_or_module_addr(const void *x)
|
|
{
|
|
/*
|
|
@@ -1259,13 +1272,14 @@ void unmap_kernel_range(unsigned long addr, unsigned long size)
|
|
flush_tlb_kernel_range(addr, end);
|
|
}
|
|
|
|
-int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages)
|
|
+int __map_vm_area(struct vm_struct *area, pgprot_t prot,
|
|
+ struct page ***pages, gfp_t gfp_mask)
|
|
{
|
|
unsigned long addr = (unsigned long)area->addr;
|
|
unsigned long end = addr + area->size - PAGE_SIZE;
|
|
int err;
|
|
|
|
- err = vmap_page_range(addr, end, prot, *pages);
|
|
+ err = __vmap_page_range(addr, end, prot, *pages, gfp_mask);
|
|
if (err > 0) {
|
|
*pages += err;
|
|
err = 0;
|
|
@@ -1273,6 +1287,11 @@ int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages)
|
|
|
|
return err;
|
|
}
|
|
+
|
|
+int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages)
|
|
+{
|
|
+ return __map_vm_area(area, prot, pages, GFP_KERNEL);
|
|
+}
|
|
EXPORT_SYMBOL_GPL(map_vm_area);
|
|
|
|
/*** Old vmalloc interfaces ***/
|
|
@@ -1614,7 +1633,7 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
|
|
area->pages[i] = page;
|
|
}
|
|
|
|
- if (map_vm_area(area, prot, &pages))
|
|
+ if (__map_vm_area(area, prot, &pages, gfp_mask))
|
|
goto fail;
|
|
return area->addr;
|
|
|