diff options
Diffstat (limited to 'arch/arm/include/asm/pgalloc.h')
-rw-r--r-- | arch/arm/include/asm/pgalloc.h | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/arch/arm/include/asm/pgalloc.h b/arch/arm/include/asm/pgalloc.h new file mode 100644 index 000000000000..3dcd64bf1824 --- /dev/null +++ b/arch/arm/include/asm/pgalloc.h | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | * arch/arm/include/asm/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(mm, 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(struct mm_struct *mm, pgd_t *pgd); | ||
35 | |||
36 | #define pgd_alloc(mm) get_pgd_slow(mm) | ||
37 | #define pgd_free(mm, pgd) free_pgd_slow(mm, 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 pgtable_t | ||
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 | pgtable_page_ctor(pte); | ||
79 | } | ||
80 | |||
81 | return pte; | ||
82 | } | ||
83 | |||
84 | /* | ||
85 | * Free one PTE table. | ||
86 | */ | ||
87 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | ||
88 | { | ||
89 | if (pte) { | ||
90 | pte -= PTRS_PER_PTE; | ||
91 | free_page((unsigned long)pte); | ||
92 | } | ||
93 | } | ||
94 | |||
95 | static inline void pte_free(struct mm_struct *mm, pgtable_t pte) | ||
96 | { | ||
97 | pgtable_page_dtor(pte); | ||
98 | __free_page(pte); | ||
99 | } | ||
100 | |||
101 | static inline void __pmd_populate(pmd_t *pmdp, unsigned long pmdval) | ||
102 | { | ||
103 | pmdp[0] = __pmd(pmdval); | ||
104 | pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); | ||
105 | flush_pmd_entry(pmdp); | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | * Populate the pmdp entry with a pointer to the pte. This pmd is part | ||
110 | * of the mm address space. | ||
111 | * | ||
112 | * Ensure that we always set both PMD entries. | ||
113 | */ | ||
114 | static inline void | ||
115 | pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) | ||
116 | { | ||
117 | unsigned long pte_ptr = (unsigned long)ptep; | ||
118 | |||
119 | /* | ||
120 | * The pmd must be loaded with the physical | ||
121 | * address of the PTE table | ||
122 | */ | ||
123 | pte_ptr -= PTRS_PER_PTE * sizeof(void *); | ||
124 | __pmd_populate(pmdp, __pa(pte_ptr) | _PAGE_KERNEL_TABLE); | ||
125 | } | ||
126 | |||
127 | static inline void | ||
128 | pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep) | ||
129 | { | ||
130 | __pmd_populate(pmdp, page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE); | ||
131 | } | ||
132 | #define pmd_pgtable(pmd) pmd_page(pmd) | ||
133 | |||
134 | #endif /* CONFIG_MMU */ | ||
135 | |||
136 | #endif | ||