2005-11-19 12:17:32 +03:00
# ifndef _ASM_POWERPC_PGALLOC_H
# define _ASM_POWERPC_PGALLOC_H
2005-12-17 00:43:46 +03:00
# ifdef __KERNEL__
2005-11-19 12:17:32 +03:00
# ifndef CONFIG_PPC64
# include <asm-ppc/pgalloc.h>
# else
2005-04-17 02:20:36 +04:00
# include <linux/mm.h>
# include <linux/slab.h>
# include <linux/cpumask.h>
# include <linux/percpu.h>
2006-12-07 07:33:20 +03:00
extern struct kmem_cache * pgtable_cache [ ] ;
2005-08-05 13:39:06 +04:00
2005-11-07 03:06:55 +03:00
# ifdef CONFIG_PPC_64K_PAGES
# define PTE_CACHE_NUM 0
2005-11-10 06:53:16 +03:00
# define PMD_CACHE_NUM 1
# define PGD_CACHE_NUM 2
2006-04-28 09:02:51 +04:00
# define HUGEPTE_CACHE_NUM 3
2005-11-07 03:06:55 +03:00
# else
2005-08-05 13:39:06 +04:00
# define PTE_CACHE_NUM 0
# define PMD_CACHE_NUM 1
# define PUD_CACHE_NUM 1
# define PGD_CACHE_NUM 0
2006-04-28 09:02:51 +04:00
# define HUGEPTE_CACHE_NUM 2
2005-11-07 03:06:55 +03:00
# endif
2005-04-17 02:20:36 +04:00
/*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version
* 2 of the License , or ( at your option ) any later version .
*/
2005-08-05 13:39:06 +04:00
static inline pgd_t * pgd_alloc ( struct mm_struct * mm )
2005-04-17 02:20:36 +04:00
{
2005-08-05 13:39:06 +04:00
return kmem_cache_alloc ( pgtable_cache [ PGD_CACHE_NUM ] , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
}
2005-08-05 13:39:06 +04:00
static inline void pgd_free ( pgd_t * pgd )
2005-04-17 02:20:36 +04:00
{
2005-08-05 13:39:06 +04:00
kmem_cache_free ( pgtable_cache [ PGD_CACHE_NUM ] , pgd ) ;
}
2005-11-07 03:06:55 +03:00
# ifndef CONFIG_PPC_64K_PAGES
2005-08-05 13:39:06 +04:00
# define pgd_populate(MM, PGD, PUD) pgd_set(PGD, PUD)
static inline pud_t * pud_alloc_one ( struct mm_struct * mm , unsigned long addr )
{
return kmem_cache_alloc ( pgtable_cache [ PUD_CACHE_NUM ] ,
GFP_KERNEL | __GFP_REPEAT ) ;
}
static inline void pud_free ( pud_t * pud )
{
kmem_cache_free ( pgtable_cache [ PUD_CACHE_NUM ] , pud ) ;
2005-04-17 02:20:36 +04:00
}
2005-11-07 03:06:55 +03:00
static inline void pud_populate ( struct mm_struct * mm , pud_t * pud , pmd_t * pmd )
{
pud_set ( pud , ( unsigned long ) pmd ) ;
}
# define pmd_populate(mm, pmd, pte_page) \
pmd_populate_kernel ( mm , pmd , page_address ( pte_page ) )
# define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, (unsigned long)(pte))
# else /* CONFIG_PPC_64K_PAGES */
# define pud_populate(mm, pud, pmd) pud_set(pud, (unsigned long)pmd)
static inline void pmd_populate_kernel ( struct mm_struct * mm , pmd_t * pmd ,
pte_t * pte )
{
pmd_set ( pmd , ( unsigned long ) pte ) ;
}
# define pmd_populate(mm, pmd, pte_page) \
pmd_populate_kernel ( mm , pmd , page_address ( pte_page ) )
# endif /* CONFIG_PPC_64K_PAGES */
2005-04-17 02:20:36 +04:00
2005-08-05 13:39:06 +04:00
static inline pmd_t * pmd_alloc_one ( struct mm_struct * mm , unsigned long addr )
2005-04-17 02:20:36 +04:00
{
2005-08-05 13:39:06 +04:00
return kmem_cache_alloc ( pgtable_cache [ PMD_CACHE_NUM ] ,
GFP_KERNEL | __GFP_REPEAT ) ;
2005-04-17 02:20:36 +04:00
}
2005-08-05 13:39:06 +04:00
static inline void pmd_free ( pmd_t * pmd )
2005-04-17 02:20:36 +04:00
{
2005-08-05 13:39:06 +04:00
kmem_cache_free ( pgtable_cache [ PMD_CACHE_NUM ] , pmd ) ;
2005-04-17 02:20:36 +04:00
}
2005-11-07 03:06:55 +03:00
static inline pte_t * pte_alloc_one_kernel ( struct mm_struct * mm ,
unsigned long address )
2005-04-17 02:20:36 +04:00
{
2005-08-05 13:39:06 +04:00
return kmem_cache_alloc ( pgtable_cache [ PTE_CACHE_NUM ] ,
GFP_KERNEL | __GFP_REPEAT ) ;
2005-04-17 02:20:36 +04:00
}
2005-11-07 03:06:55 +03:00
static inline struct page * pte_alloc_one ( struct mm_struct * mm ,
unsigned long address )
2005-04-17 02:20:36 +04:00
{
2005-08-05 13:39:06 +04:00
return virt_to_page ( pte_alloc_one_kernel ( mm , address ) ) ;
2005-04-17 02:20:36 +04:00
}
static inline void pte_free_kernel ( pte_t * pte )
{
2005-08-05 13:39:06 +04:00
kmem_cache_free ( pgtable_cache [ PTE_CACHE_NUM ] , pte ) ;
2005-04-17 02:20:36 +04:00
}
static inline void pte_free ( struct page * ptepage )
{
2005-08-05 13:39:06 +04:00
pte_free_kernel ( page_address ( ptepage ) ) ;
2005-04-17 02:20:36 +04:00
}
2006-08-18 22:22:21 +04:00
# define PGF_CACHENUM_MASK 0x3
2005-08-05 13:39:06 +04:00
typedef struct pgtable_free {
unsigned long val ;
} pgtable_free_t ;
static inline pgtable_free_t pgtable_free_cache ( void * p , int cachenum ,
unsigned long mask )
2005-04-17 02:20:36 +04:00
{
2005-08-05 13:39:06 +04:00
BUG_ON ( cachenum > PGF_CACHENUM_MASK ) ;
2005-04-17 02:20:36 +04:00
2005-08-05 13:39:06 +04:00
return ( pgtable_free_t ) { . val = ( ( unsigned long ) p & ~ mask ) | cachenum } ;
}
2005-04-17 02:20:36 +04:00
2005-08-05 13:39:06 +04:00
static inline void pgtable_free ( pgtable_free_t pgf )
{
void * p = ( void * ) ( pgf . val & ~ PGF_CACHENUM_MASK ) ;
int cachenum = pgf . val & PGF_CACHENUM_MASK ;
2005-04-17 02:20:36 +04:00
2005-08-05 13:39:06 +04:00
kmem_cache_free ( pgtable_cache [ cachenum ] , p ) ;
}
2005-04-17 02:20:36 +04:00
2005-11-07 03:06:55 +03:00
extern void pgtable_free_tlb ( struct mmu_gather * tlb , pgtable_free_t pgf ) ;
2005-08-05 13:39:06 +04:00
# define __pte_free_tlb(tlb, ptepage) \
pgtable_free_tlb ( tlb , pgtable_free_cache ( page_address ( ptepage ) , \
PTE_CACHE_NUM , PTE_TABLE_SIZE - 1 ) )
# define __pmd_free_tlb(tlb, pmd) \
pgtable_free_tlb ( tlb , pgtable_free_cache ( pmd , \
PMD_CACHE_NUM , PMD_TABLE_SIZE - 1 ) )
2005-11-07 03:06:55 +03:00
# ifndef CONFIG_PPC_64K_PAGES
2006-02-18 00:52:56 +03:00
# define __pud_free_tlb(tlb, pud) \
2005-08-05 13:39:06 +04:00
pgtable_free_tlb ( tlb , pgtable_free_cache ( pud , \
PUD_CACHE_NUM , PUD_TABLE_SIZE - 1 ) )
2005-11-07 03:06:55 +03:00
# endif /* CONFIG_PPC_64K_PAGES */
2005-04-17 02:20:36 +04:00
# define check_pgt_cache() do { } while (0)
2005-11-19 12:17:32 +03:00
# endif /* CONFIG_PPC64 */
2005-12-17 00:43:46 +03:00
# endif /* __KERNEL__ */
2005-11-19 12:17:32 +03:00
# endif /* _ASM_POWERPC_PGALLOC_H */