Home | History | Annotate | Download | only in asm-arm
      1 /*
      2  *  linux/include/asm-arm/pgalloc.h
      3  *
      4  *  Copyright (C) 2000-2001 Russell King
      5  *
      6  * This program is free software; you can redistribute it and/or modify
      7  * it under the terms of the GNU General Public License version 2 as
      8  * published by the Free Software Foundation.
      9  */
     10 #ifndef _ASMARM_PGALLOC_H
     11 #define _ASMARM_PGALLOC_H
     12 
     13 #include <asm/domain.h>
     14 #include <asm/pgtable-hwdef.h>
     15 #include <asm/processor.h>
     16 #include <asm/cacheflush.h>
     17 #include <asm/tlbflush.h>
     18 
     19 #define check_pgt_cache()		do { } while (0)
     20 
     21 #ifdef CONFIG_MMU
     22 
     23 #define _PAGE_USER_TABLE	(PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_USER))
     24 #define _PAGE_KERNEL_TABLE	(PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_KERNEL))
     25 
     26 /*
     27  * Since we have only two-level page tables, these are trivial
     28  */
     29 #define pmd_alloc_one(mm,addr)		({ BUG(); ((pmd_t *)2); })
     30 #define pmd_free(pmd)			do { } while (0)
     31 #define pgd_populate(mm,pmd,pte)	BUG()
     32 
     33 extern pgd_t *get_pgd_slow(struct mm_struct *mm);
     34 extern void free_pgd_slow(pgd_t *pgd);
     35 
     36 #define pgd_alloc(mm)			get_pgd_slow(mm)
     37 #define pgd_free(pgd)			free_pgd_slow(pgd)
     38 
     39 /*
     40  * Allocate one PTE table.
     41  *
     42  * This actually allocates two hardware PTE tables, but we wrap this up
     43  * into one table thus:
     44  *
     45  *  +------------+
     46  *  |  h/w pt 0  |
     47  *  +------------+
     48  *  |  h/w pt 1  |
     49  *  +------------+
     50  *  | Linux pt 0 |
     51  *  +------------+
     52  *  | Linux pt 1 |
     53  *  +------------+
     54  */
     55 static inline pte_t *
     56 pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
     57 {
     58 	pte_t *pte;
     59 
     60 	pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
     61 	if (pte) {
     62 		clean_dcache_area(pte, sizeof(pte_t) * PTRS_PER_PTE);
     63 		pte += PTRS_PER_PTE;
     64 	}
     65 
     66 	return pte;
     67 }
     68 
     69 static inline struct page *
     70 pte_alloc_one(struct mm_struct *mm, unsigned long addr)
     71 {
     72 	struct page *pte;
     73 
     74 	pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
     75 	if (pte) {
     76 		void *page = page_address(pte);
     77 		clean_dcache_area(page, sizeof(pte_t) * PTRS_PER_PTE);
     78 	}
     79 
     80 	return pte;
     81 }
     82 
     83 /*
     84  * Free one PTE table.
     85  */
     86 static inline void pte_free_kernel(pte_t *pte)
     87 {
     88 	if (pte) {
     89 		pte -= PTRS_PER_PTE;
     90 		free_page((unsigned long)pte);
     91 	}
     92 }
     93 
     94 static inline void pte_free(struct page *pte)
     95 {
     96 	__free_page(pte);
     97 }
     98 
     99 static inline void __pmd_populate(pmd_t *pmdp, unsigned long pmdval)
    100 {
    101 	pmdp[0] = __pmd(pmdval);
    102 	pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
    103 	flush_pmd_entry(pmdp);
    104 }
    105 
    106 /*
    107  * Populate the pmdp entry with a pointer to the pte.  This pmd is part
    108  * of the mm address space.
    109  *
    110  * Ensure that we always set both PMD entries.
    111  */
    112 static inline void
    113 pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
    114 {
    115 	unsigned long pte_ptr = (unsigned long)ptep;
    116 
    117 	/*
    118 	 * The pmd must be loaded with the physical
    119 	 * address of the PTE table
    120 	 */
    121 	pte_ptr -= PTRS_PER_PTE * sizeof(void *);
    122 	__pmd_populate(pmdp, __pa(pte_ptr) | _PAGE_KERNEL_TABLE);
    123 }
    124 
    125 static inline void
    126 pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *ptep)
    127 {
    128 	__pmd_populate(pmdp, page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE);
    129 }
    130 
    131 #endif /* CONFIG_MMU */
    132 
    133 #endif
    134