Commit | Line | Data |
---|---|---|
d2912cb1 | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
1da177e4 | 2 | /* |
4baa9922 | 3 | * arch/arm/include/asm/pgalloc.h |
1da177e4 LT |
4 | * |
5 | * Copyright (C) 2000-2001 Russell King | |
1da177e4 LT |
6 | */ |
7 | #ifndef _ASMARM_PGALLOC_H | |
8 | #define _ASMARM_PGALLOC_H | |
9 | ||
97594b0f UKK |
10 | #include <linux/pagemap.h> |
11 | ||
74945c86 RK |
12 | #include <asm/domain.h> |
13 | #include <asm/pgtable-hwdef.h> | |
1da177e4 LT |
14 | #include <asm/processor.h> |
15 | #include <asm/cacheflush.h> | |
16 | #include <asm/tlbflush.h> | |
17 | ||
002547b4 RK |
18 | #ifdef CONFIG_MMU |
19 | ||
74945c86 RK |
20 | #define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_USER)) |
21 | #define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_KERNEL)) | |
22 | ||
da028779 CM |
23 | #ifdef CONFIG_ARM_LPAE |
24 | ||
da028779 CM |
25 | static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) |
26 | { | |
27 | set_pud(pud, __pud(__pa(pmd) | PMD_TYPE_TABLE)); | |
28 | } | |
29 | ||
30 | #else /* !CONFIG_ARM_LPAE */ | |
31 | ||
1da177e4 LT |
32 | /* |
33 | * Since we have only two-level page tables, these are trivial | |
34 | */ | |
35 | #define pmd_alloc_one(mm,addr) ({ BUG(); ((pmd_t *)2); }) | |
5e541973 | 36 | #define pmd_free(mm, pmd) do { } while (0) |
a32618d2 | 37 | #define pud_populate(mm,pmd,pte) BUG() |
1da177e4 | 38 | |
da028779 CM |
39 | #endif /* CONFIG_ARM_LPAE */ |
40 | ||
b0d03745 RK |
41 | extern pgd_t *pgd_alloc(struct mm_struct *mm); |
42 | extern void pgd_free(struct mm_struct *mm, pgd_t *pgd); | |
1da177e4 | 43 | |
d30e45ee RK |
44 | static inline void clean_pte_table(pte_t *pte) |
45 | { | |
46 | clean_dcache_area(pte + PTE_HWTABLE_PTRS, PTE_HWTABLE_SIZE); | |
47 | } | |
48 | ||
1da177e4 LT |
49 | /* |
50 | * Allocate one PTE table. | |
51 | * | |
52 | * This actually allocates two hardware PTE tables, but we wrap this up | |
53 | * into one table thus: | |
54 | * | |
55 | * +------------+ | |
1da177e4 LT |
56 | * | Linux pt 0 | |
57 | * +------------+ | |
58 | * | Linux pt 1 | | |
59 | * +------------+ | |
d30e45ee RK |
60 | * | h/w pt 0 | |
61 | * +------------+ | |
62 | * | h/w pt 1 | | |
63 | * +------------+ | |
1da177e4 | 64 | */ |
28bcf593 MR |
65 | |
66 | #define __HAVE_ARCH_PTE_ALLOC_ONE_KERNEL | |
67 | #define __HAVE_ARCH_PTE_ALLOC_ONE | |
f9cb654c | 68 | #define __HAVE_ARCH_PGD_FREE |
28bcf593 MR |
69 | #include <asm-generic/pgalloc.h> |
70 | ||
1da177e4 | 71 | static inline pte_t * |
4cf58924 | 72 | pte_alloc_one_kernel(struct mm_struct *mm) |
1da177e4 | 73 | { |
28bcf593 | 74 | pte_t *pte = __pte_alloc_one_kernel(mm); |
1da177e4 | 75 | |
d30e45ee RK |
76 | if (pte) |
77 | clean_pte_table(pte); | |
1da177e4 LT |
78 | |
79 | return pte; | |
80 | } | |
81 | ||
28bcf593 MR |
82 | #ifdef CONFIG_HIGHPTE |
83 | #define PGTABLE_HIGHMEM __GFP_HIGHMEM | |
84 | #else | |
85 | #define PGTABLE_HIGHMEM 0 | |
86 | #endif | |
87 | ||
2f569afd | 88 | static inline pgtable_t |
4cf58924 | 89 | pte_alloc_one(struct mm_struct *mm) |
1da177e4 LT |
90 | { |
91 | struct page *pte; | |
92 | ||
28bcf593 | 93 | pte = __pte_alloc_one(mm, GFP_PGTABLE_USER | PGTABLE_HIGHMEM); |
affce508 KS |
94 | if (!pte) |
95 | return NULL; | |
96 | if (!PageHighMem(pte)) | |
97 | clean_pte_table(page_address(pte)); | |
1da177e4 LT |
98 | return pte; |
99 | } | |
100 | ||
97092e0c | 101 | static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte, |
442e70c0 | 102 | pmdval_t prot) |
bdf04248 | 103 | { |
442e70c0 | 104 | pmdval_t pmdval = (pte + PTE_HWTABLE_OFF) | prot; |
bdf04248 | 105 | pmdp[0] = __pmd(pmdval); |
da028779 | 106 | #ifndef CONFIG_ARM_LPAE |
bdf04248 | 107 | pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); |
da028779 | 108 | #endif |
bdf04248 RK |
109 | flush_pmd_entry(pmdp); |
110 | } | |
111 | ||
1da177e4 LT |
112 | /* |
113 | * Populate the pmdp entry with a pointer to the pte. This pmd is part | |
114 | * of the mm address space. | |
115 | * | |
116 | * Ensure that we always set both PMD entries. | |
117 | */ | |
118 | static inline void | |
119 | pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) | |
120 | { | |
1da177e4 | 121 | /* |
d30e45ee | 122 | * The pmd must be loaded with the physical address of the PTE table |
1da177e4 | 123 | */ |
d30e45ee | 124 | __pmd_populate(pmdp, __pa(ptep), _PAGE_KERNEL_TABLE); |
1da177e4 LT |
125 | } |
126 | ||
127 | static inline void | |
2f569afd | 128 | pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep) |
1da177e4 | 129 | { |
1d4d3715 JL |
130 | extern pmdval_t user_pmd_table; |
131 | pmdval_t prot; | |
132 | ||
133 | if (__LINUX_ARM_ARCH__ >= 6 && !IS_ENABLED(CONFIG_ARM_LPAE)) | |
134 | prot = user_pmd_table; | |
135 | else | |
136 | prot = _PAGE_USER_TABLE; | |
137 | ||
138 | __pmd_populate(pmdp, page_to_phys(ptep), prot); | |
1da177e4 | 139 | } |
2f569afd | 140 | #define pmd_pgtable(pmd) pmd_page(pmd) |
1da177e4 | 141 | |
002547b4 RK |
142 | #endif /* CONFIG_MMU */ |
143 | ||
1da177e4 | 144 | #endif |