2005-04-17 02:20:36 +04:00
/*
2008-08-02 13:55:55 +04:00
* arch / arm / include / asm / pgalloc . h
2005-04-17 02:20:36 +04:00
*
* Copyright ( C ) 2000 - 2001 Russell King
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# ifndef _ASMARM_PGALLOC_H
# define _ASMARM_PGALLOC_H
2006-03-16 17:44:36 +03:00
# include <asm/domain.h>
# include <asm/pgtable-hwdef.h>
2005-04-17 02:20:36 +04:00
# include <asm/processor.h>
# include <asm/cacheflush.h>
# include <asm/tlbflush.h>
2006-06-20 23:46:52 +04:00
# define check_pgt_cache() do { } while (0)
# ifdef CONFIG_MMU
2006-03-16 17:44:36 +03:00
# define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_USER))
# define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_KERNEL))
2005-04-17 02:20:36 +04:00
/*
* Since we have only two - level page tables , these are trivial
*/
# define pmd_alloc_one(mm,addr) ({ BUG(); ((pmd_t *)2); })
2008-02-05 09:29:14 +03:00
# define pmd_free(mm, pmd) do { } while (0)
2005-04-17 02:20:36 +04:00
# define pgd_populate(mm,pmd,pte) BUG()
extern pgd_t * get_pgd_slow ( struct mm_struct * mm ) ;
2008-02-05 09:29:14 +03:00
extern void free_pgd_slow ( struct mm_struct * mm , pgd_t * pgd ) ;
2005-04-17 02:20:36 +04:00
# define pgd_alloc(mm) get_pgd_slow(mm)
2008-02-05 09:29:14 +03:00
# define pgd_free(mm, pgd) free_pgd_slow(mm, pgd)
2005-04-17 02:20:36 +04:00
2009-08-17 23:02:06 +04:00
# define PGALLOC_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO)
2005-04-17 02:20:36 +04:00
/*
* Allocate one PTE table .
*
* This actually allocates two hardware PTE tables , but we wrap this up
* into one table thus :
*
* + - - - - - - - - - - - - +
* | h / w pt 0 |
* + - - - - - - - - - - - - +
* | h / w pt 1 |
* + - - - - - - - - - - - - +
* | Linux pt 0 |
* + - - - - - - - - - - - - +
* | Linux pt 1 |
* + - - - - - - - - - - - - +
*/
static inline pte_t *
pte_alloc_one_kernel ( struct mm_struct * mm , unsigned long addr )
{
pte_t * pte ;
2009-08-17 23:02:06 +04:00
pte = ( pte_t * ) __get_free_page ( PGALLOC_GFP ) ;
2005-04-17 02:20:36 +04:00
if ( pte ) {
clean_dcache_area ( pte , sizeof ( pte_t ) * PTRS_PER_PTE ) ;
pte + = PTRS_PER_PTE ;
}
return pte ;
}
2008-02-08 15:22:04 +03:00
static inline pgtable_t
2005-04-17 02:20:36 +04:00
pte_alloc_one ( struct mm_struct * mm , unsigned long addr )
{
struct page * pte ;
2009-08-17 23:02:06 +04:00
# ifdef CONFIG_HIGHPTE
pte = alloc_pages ( PGALLOC_GFP | __GFP_HIGHMEM , 0 ) ;
# else
pte = alloc_pages ( PGALLOC_GFP , 0 ) ;
# endif
2005-04-17 02:20:36 +04:00
if ( pte ) {
2009-08-17 23:02:06 +04:00
if ( ! PageHighMem ( pte ) ) {
void * page = page_address ( pte ) ;
clean_dcache_area ( page , sizeof ( pte_t ) * PTRS_PER_PTE ) ;
}
2008-02-08 15:22:04 +03:00
pgtable_page_ctor ( pte ) ;
2005-04-17 02:20:36 +04:00
}
return pte ;
}
/*
* Free one PTE table .
*/
2008-02-05 09:29:14 +03:00
static inline void pte_free_kernel ( struct mm_struct * mm , pte_t * pte )
2005-04-17 02:20:36 +04:00
{
if ( pte ) {
pte - = PTRS_PER_PTE ;
free_page ( ( unsigned long ) pte ) ;
}
}
2008-02-08 15:22:04 +03:00
static inline void pte_free ( struct mm_struct * mm , pgtable_t pte )
2005-04-17 02:20:36 +04:00
{
2008-02-08 15:22:04 +03:00
pgtable_page_dtor ( pte ) ;
2005-04-17 02:20:36 +04:00
__free_page ( pte ) ;
}
2005-06-22 23:58:29 +04:00
static inline void __pmd_populate ( pmd_t * pmdp , unsigned long pmdval )
{
pmdp [ 0 ] = __pmd ( pmdval ) ;
pmdp [ 1 ] = __pmd ( pmdval + 256 * sizeof ( pte_t ) ) ;
flush_pmd_entry ( pmdp ) ;
}
2005-04-17 02:20:36 +04:00
/*
* Populate the pmdp entry with a pointer to the pte . This pmd is part
* of the mm address space .
*
* Ensure that we always set both PMD entries .
*/
static inline void
pmd_populate_kernel ( struct mm_struct * mm , pmd_t * pmdp , pte_t * ptep )
{
unsigned long pte_ptr = ( unsigned long ) ptep ;
/*
* The pmd must be loaded with the physical
* address of the PTE table
*/
pte_ptr - = PTRS_PER_PTE * sizeof ( void * ) ;
2005-06-22 23:58:29 +04:00
__pmd_populate ( pmdp , __pa ( pte_ptr ) | _PAGE_KERNEL_TABLE ) ;
2005-04-17 02:20:36 +04:00
}
static inline void
2008-02-08 15:22:04 +03:00
pmd_populate ( struct mm_struct * mm , pmd_t * pmdp , pgtable_t ptep )
2005-04-17 02:20:36 +04:00
{
2005-06-22 23:58:29 +04:00
__pmd_populate ( pmdp , page_to_pfn ( ptep ) < < PAGE_SHIFT | _PAGE_USER_TABLE ) ;
2005-04-17 02:20:36 +04:00
}
2008-02-08 15:22:04 +03:00
# define pmd_pgtable(pmd) pmd_page(pmd)
2005-04-17 02:20:36 +04:00
2006-06-20 23:46:52 +04:00
# endif /* CONFIG_MMU */
2005-04-17 02:20:36 +04:00
# endif