diff -upNr linux-3.5.0.orig/arch/alpha/include/asm/pgalloc.h linux-3.5.0/arch/alpha/include/asm/pgalloc.h --- linux-3.5.0.orig/arch/alpha/include/asm/pgalloc.h 2012-07-29 20:28:15.137626975 -0400 +++ linux-3.5.0/arch/alpha/include/asm/pgalloc.h 2012-07-29 04:44:48.426219000 -0400 @@ -38,10 +38,15 @@ pgd_free(struct mm_struct *mm, pgd_t *pg } 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 *pm } 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 -upNr linux-3.5.0.orig/arch/arm/include/asm/pgalloc.h linux-3.5.0/arch/arm/include/asm/pgalloc.h --- linux-3.5.0.orig/arch/arm/include/asm/pgalloc.h 2012-07-29 20:28:15.137626975 -0400 +++ linux-3.5.0/arch/arm/include/asm/pgalloc.h 2012-07-29 04:44:48.428568000 -0400 @@ -48,6 +48,7 @@ static inline void pud_populate(struct m /* * 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 * +------------+ */ 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 -upNr linux-3.5.0.orig/arch/avr32/include/asm/pgalloc.h linux-3.5.0/arch/avr32/include/asm/pgalloc.h --- linux-3.5.0.orig/arch/avr32/include/asm/pgalloc.h 2012-07-29 20:28:15.137626975 -0400 +++ linux-3.5.0/arch/avr32/include/asm/pgalloc.h 2012-07-29 04:44:48.430967000 -0400 @@ -51,10 +51,16 @@ static inline void pgd_free(struct mm_st 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 -upNr linux-3.5.0.orig/arch/cris/include/asm/pgalloc.h linux-3.5.0/arch/cris/include/asm/pgalloc.h --- linux-3.5.0.orig/arch/cris/include/asm/pgalloc.h 2012-07-29 20:28:15.137626975 -0400 +++ linux-3.5.0/arch/cris/include/asm/pgalloc.h 2012-07-29 04:44:48.433616000 -0400 @@ -22,10 +22,16 @@ static inline void pgd_free(struct mm_st 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 -upNr linux-3.5.0.orig/arch/frv/include/asm/pgalloc.h linux-3.5.0/arch/frv/include/asm/pgalloc.h --- linux-3.5.0.orig/arch/frv/include/asm/pgalloc.h 2012-07-29 20:28:15.137626975 -0400 +++ linux-3.5.0/arch/frv/include/asm/pgalloc.h 2012-07-29 04:44:48.436295000 -0400 @@ -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 -upNr linux-3.5.0.orig/arch/frv/include/asm/pgtable.h linux-3.5.0/arch/frv/include/asm/pgtable.h --- linux-3.5.0.orig/arch/frv/include/asm/pgtable.h 2012-07-29 20:28:15.137626975 -0400 +++ linux-3.5.0/arch/frv/include/asm/pgtable.h 2012-07-29 04:44:48.437111000 -0400 @@ -223,6 +223,7 @@ static inline pud_t *pud_offset(pgd_t *p * 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 -upNr linux-3.5.0.orig/arch/frv/mm/pgalloc.c linux-3.5.0/arch/frv/mm/pgalloc.c --- linux-3.5.0.orig/arch/frv/mm/pgalloc.c 2012-07-29 20:28:15.137626975 -0400 +++ linux-3.5.0/arch/frv/mm/pgalloc.c 2012-07-29 04:44:48.438283000 -0400 @@ -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 -upNr linux-3.5.0.orig/arch/ia64/include/asm/pgalloc.h linux-3.5.0/arch/ia64/include/asm/pgalloc.h --- linux-3.5.0.orig/arch/ia64/include/asm/pgalloc.h 2012-07-29 20:28:15.137626975 -0400 +++ linux-3.5.0/arch/ia64/include/asm/pgalloc.h 2012-07-29 04:44:48.440485000 -0400 @@ -39,9 +39,15 @@ pgd_populate(struct mm_struct *mm, pgd_t 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_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(st 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 -upNr linux-3.5.0.orig/arch/m32r/include/asm/pgalloc.h linux-3.5.0/arch/m32r/include/asm/pgalloc.h --- linux-3.5.0.orig/arch/m32r/include/asm/pgalloc.h 2012-07-29 20:28:15.137626975 -0400 +++ linux-3.5.0/arch/m32r/include/asm/pgalloc.h 2012-07-29 04:44:48.442422000 -0400 @@ -30,12 +30,16 @@ static inline void pgd_free(struct mm_st 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_st * (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 -upNr linux-3.5.0.orig/arch/m68k/include/asm/motorola_pgalloc.h linux-3.5.0/arch/m68k/include/asm/motorola_pgalloc.h --- linux-3.5.0.orig/arch/m68k/include/asm/motorola_pgalloc.h 2012-07-29 20:28:15.137626975 -0400 +++ linux-3.5.0/arch/m68k/include/asm/motorola_pgalloc.h 2012-07-29 04:44:48.444812000 -0400 @@ -5,13 +5,16 @@ #include 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_kerne 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 __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 -upNr linux-3.5.0.orig/arch/m68k/include/asm/sun3_pgalloc.h linux-3.5.0/arch/m68k/include/asm/sun3_pgalloc.h --- linux-3.5.0.orig/arch/m68k/include/asm/sun3_pgalloc.h 2012-07-29 20:28:15.138626975 -0400 +++ linux-3.5.0/arch/m68k/include/asm/sun3_pgalloc.h 2012-07-29 04:44:48.445377000 -0400 @@ -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_kerne 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 -upNr linux-3.5.0.orig/arch/m68k/mm/memory.c linux-3.5.0/arch/m68k/mm/memory.c --- linux-3.5.0.orig/arch/m68k/mm/memory.c 2012-07-29 20:28:15.138626975 -0400 +++ linux-3.5.0/arch/m68k/mm/memory.c 2012-07-29 04:44:48.446994000 -0400 @@ -58,7 +58,7 @@ void __init init_pointer_table(unsigned 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 -upNr linux-3.5.0.orig/arch/microblaze/include/asm/pgalloc.h linux-3.5.0/arch/microblaze/include/asm/pgalloc.h --- linux-3.5.0.orig/arch/microblaze/include/asm/pgalloc.h 2012-07-29 20:28:15.138626975 -0400 +++ linux-3.5.0/arch/microblaze/include/asm/pgalloc.h 2012-07-29 04:44:48.448900000 -0400 @@ -106,9 +106,11 @@ extern inline void free_pgd_slow(pgd_t * * 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_st * 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 -upNr linux-3.5.0.orig/arch/microblaze/mm/pgtable.c linux-3.5.0/arch/microblaze/mm/pgtable.c --- linux-3.5.0.orig/arch/microblaze/mm/pgtable.c 2012-07-29 20:28:15.138626975 -0400 +++ linux-3.5.0/arch/microblaze/mm/pgtable.c 2012-07-29 04:44:48.450057000 -0400 @@ -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 i 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 -upNr linux-3.5.0.orig/arch/mips/include/asm/pgalloc.h linux-3.5.0/arch/mips/include/asm/pgalloc.h --- linux-3.5.0.orig/arch/mips/include/asm/pgalloc.h 2012-07-29 20:28:15.138626975 -0400 +++ linux-3.5.0/arch/mips/include/asm/pgalloc.h 2012-07-29 04:44:48.452077000 -0400 @@ -64,14 +64,16 @@ static inline void pgd_free(struct mm_st 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 -upNr linux-3.5.0.orig/arch/mn10300/include/asm/pgalloc.h linux-3.5.0/arch/mn10300/include/asm/pgalloc.h --- linux-3.5.0.orig/arch/mn10300/include/asm/pgalloc.h 2012-07-29 20:28:15.138626975 -0400 +++ linux-3.5.0/arch/mn10300/include/asm/pgalloc.h 2012-07-29 04:44:48.453539000 -0400 @@ -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 -upNr linux-3.5.0.orig/arch/mn10300/mm/pgtable.c linux-3.5.0/arch/mn10300/mm/pgtable.c --- linux-3.5.0.orig/arch/mn10300/mm/pgtable.c 2012-07-29 20:28:15.138626975 -0400 +++ linux-3.5.0/arch/mn10300/mm/pgtable.c 2012-07-29 04:44:48.454831000 -0400 @@ -61,14 +61,20 @@ void set_pmd_pfn(unsigned long vaddr, un 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 -upNr linux-3.5.0.orig/arch/parisc/include/asm/pgalloc.h linux-3.5.0/arch/parisc/include/asm/pgalloc.h --- linux-3.5.0.orig/arch/parisc/include/asm/pgalloc.h 2012-07-29 20:28:15.138626975 -0400 +++ linux-3.5.0/arch/parisc/include/asm/pgalloc.h 2012-07-29 04:44:48.456989000 -0400 @@ -61,15 +61,20 @@ static inline void pgd_populate(struct m (__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< 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_ty 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_ty 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 m /* * 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 -upNr linux-3.5.0.orig/arch/s390/mm/pgtable.c linux-3.5.0/arch/s390/mm/pgtable.c --- linux-3.5.0.orig/arch/s390/mm/pgtable.c 2012-07-29 20:28:15.139626975 -0400 +++ linux-3.5.0/arch/s390/mm/pgtable.c 2012-07-29 04:44:48.467415000 -0400 @@ -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_bi /* * 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 m } 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 m 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 -upNr linux-3.5.0.orig/arch/score/include/asm/pgalloc.h linux-3.5.0/arch/score/include/asm/pgalloc.h --- linux-3.5.0.orig/arch/score/include/asm/pgalloc.h 2012-07-29 20:28:15.139626975 -0400 +++ linux-3.5.0/arch/score/include/asm/pgalloc.h 2012-07-29 04:44:48.469590000 -0400 @@ -37,15 +37,16 @@ static inline void pgd_free(struct mm_st 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 -upNr linux-3.5.0.orig/arch/sh/include/asm/pgalloc.h linux-3.5.0/arch/sh/include/asm/pgalloc.h --- linux-3.5.0.orig/arch/sh/include/asm/pgalloc.h 2012-07-29 20:28:15.139626975 -0400 +++ linux-3.5.0/arch/sh/include/asm/pgalloc.h 2012-07-29 04:44:48.472723000 -0400 @@ -31,10 +31,16 @@ static inline void pmd_populate(struct m /* * 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 -upNr linux-3.5.0.orig/arch/sh/mm/pgtable.c linux-3.5.0/arch/sh/mm/pgtable.c --- linux-3.5.0.orig/arch/sh/mm/pgtable.c 2012-07-29 20:28:15.139626975 -0400 +++ linux-3.5.0/arch/sh/mm/pgtable.c 2012-07-29 04:44:48.474577000 -0400 @@ -45,9 +45,15 @@ void pud_populate(struct mm_struct *mm, 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 -upNr linux-3.5.0.orig/arch/tile/include/asm/pgalloc.h linux-3.5.0/arch/tile/include/asm/pgalloc.h --- linux-3.5.0.orig/arch/tile/include/asm/pgalloc.h 2012-07-29 20:28:15.139626975 -0400 +++ linux-3.5.0/arch/tile/include/asm/pgalloc.h 2012-07-29 04:44:48.476751000 -0400 @@ -86,9 +86,16 @@ static inline void pte_free(struct mm_st #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 -upNr linux-3.5.0.orig/arch/tile/mm/pgtable.c linux-3.5.0/arch/tile/mm/pgtable.c --- linux-3.5.0.orig/arch/tile/mm/pgtable.c 2012-07-29 20:28:15.139626975 -0400 +++ linux-3.5.0/arch/tile/mm/pgtable.c 2012-07-29 04:44:48.478319000 -0400 @@ -280,10 +280,11 @@ void pgd_free(struct mm_struct *mm, 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 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 -upNr linux-3.5.0.orig/arch/um/include/asm/pgalloc.h linux-3.5.0/arch/um/include/asm/pgalloc.h --- linux-3.5.0.orig/arch/um/include/asm/pgalloc.h 2012-07-29 20:28:15.139626975 -0400 +++ linux-3.5.0/arch/um/include/asm/pgalloc.h 2012-07-29 04:44:48.480044000 -0400 @@ -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 -upNr linux-3.5.0.orig/arch/um/kernel/mem.c linux-3.5.0/arch/um/kernel/mem.c --- linux-3.5.0.orig/arch/um/kernel/mem.c 2012-07-29 20:28:15.139626975 -0400 +++ linux-3.5.0/arch/um/kernel/mem.c 2012-07-29 04:44:48.481537000 -0400 @@ -286,12 +286,15 @@ void pgd_free(struct mm_struct *mm, 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 } #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 -upNr linux-3.5.0.orig/arch/x86/include/asm/pgalloc.h linux-3.5.0/arch/x86/include/asm/pgalloc.h --- linux-3.5.0.orig/arch/x86/include/asm/pgalloc.h 2012-07-29 20:28:15.139626975 -0400 +++ linux-3.5.0/arch/x86/include/asm/pgalloc.h 2012-07-29 04:44:48.483808000 -0400 @@ -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 m #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 m 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 -upNr linux-3.5.0.orig/arch/x86/mm/pgtable.c linux-3.5.0/arch/x86/mm/pgtable.c --- linux-3.5.0.orig/arch/x86/mm/pgtable.c 2012-07-29 20:28:15.139626975 -0400 +++ linux-3.5.0/arch/x86/mm/pgtable.c 2012-07-29 04:44:48.485083000 -0400 @@ -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 -upNr linux-3.5.0.orig/arch/xtensa/include/asm/pgalloc.h linux-3.5.0/arch/xtensa/include/asm/pgalloc.h --- linux-3.5.0.orig/arch/xtensa/include/asm/pgalloc.h 2012-07-29 20:28:15.140626975 -0400 +++ linux-3.5.0/arch/xtensa/include/asm/pgalloc.h 2012-07-29 04:44:48.487259000 -0400 @@ -42,10 +42,17 @@ static inline void pgd_free(struct mm_st 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 -upNr linux-3.5.0.orig/include/asm-generic/4level-fixup.h linux-3.5.0/include/asm-generic/4level-fixup.h --- linux-3.5.0.orig/include/asm-generic/4level-fixup.h 2012-07-29 20:28:15.140626975 -0400 +++ linux-3.5.0/include/asm-generic/4level-fixup.h 2012-07-29 04:44:48.488998000 -0400 @@ -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 -upNr linux-3.5.0.orig/include/asm-generic/pgtable-nopmd.h linux-3.5.0/include/asm-generic/pgtable-nopmd.h --- linux-3.5.0.orig/include/asm-generic/pgtable-nopmd.h 2012-07-29 20:28:15.140626975 -0400 +++ linux-3.5.0/include/asm-generic/pgtable-nopmd.h 2012-07-29 04:44:48.489637000 -0400 @@ -55,7 +55,8 @@ static inline pmd_t * pmd_offset(pud_t * * 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 -upNr linux-3.5.0.orig/include/asm-generic/pgtable-nopud.h linux-3.5.0/include/asm-generic/pgtable-nopud.h --- linux-3.5.0.orig/include/asm-generic/pgtable-nopud.h 2012-07-29 20:28:15.140626975 -0400 +++ linux-3.5.0/include/asm-generic/pgtable-nopud.h 2012-07-29 04:44:48.490151000 -0400 @@ -50,6 +50,7 @@ static inline pud_t * pud_offset(pgd_t * * 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 -upNr linux-3.5.0.orig/include/linux/mm.h linux-3.5.0/include/linux/mm.h --- linux-3.5.0.orig/include/linux/mm.h 2012-07-29 20:28:15.140626975 -0400 +++ linux-3.5.0/include/linux/mm.h 2012-07-29 04:44:48.492309000 -0400 @@ -1149,44 +1149,60 @@ static inline pte_t *get_locked_pte(stru #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(str 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 -upNr linux-3.5.0.orig/mm/memory.c linux-3.5.0/mm/memory.c --- linux-3.5.0.orig/mm/memory.c 2012-07-29 20:28:15.141626975 -0400 +++ linux-3.5.0/mm/memory.c 2012-07-29 04:44:48.497367000 -0400 @@ -608,9 +608,9 @@ int __pte_alloc(struct mm_struct *mm, st 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; @@ -3556,9 +3556,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; @@ -3579,9 +3580,10 @@ int __pud_alloc(struct mm_struct *mm, pg * 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 -upNr linux-3.5.0.orig/mm/vmalloc.c linux-3.5.0/mm/vmalloc.c --- linux-3.5.0.orig/mm/vmalloc.c 2012-07-29 20:28:15.141626975 -0400 +++ linux-3.5.0/mm/vmalloc.c 2012-07-29 04:44:48.499258000 -0400 @@ -87,8 +87,8 @@ static void vunmap_page_range(unsigned l } 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, un * 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, un } 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, un * * 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(unsig 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(unsig 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 ad 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, 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 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;