.. | .. |
---|
1 | 1 | // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note |
---|
2 | 2 | /* |
---|
3 | 3 | * |
---|
4 | | - * (C) COPYRIGHT 2010-2014, 2016-2021 ARM Limited. All rights reserved. |
---|
| 4 | + * (C) COPYRIGHT 2010-2014, 2016-2022 ARM Limited. All rights reserved. |
---|
5 | 5 | * |
---|
6 | 6 | * This program is free software and is provided to you under the terms of the |
---|
7 | 7 | * GNU General Public License version 2 as published by the Free Software |
---|
.. | .. |
---|
35 | 35 | #define ENTRY_IS_INVAL 2ULL |
---|
36 | 36 | #define ENTRY_IS_PTE 3ULL |
---|
37 | 37 | |
---|
38 | | -#define ENTRY_ATTR_BITS (7ULL << 2) /* bits 4:2 */ |
---|
39 | 38 | #define ENTRY_ACCESS_RW (1ULL << 6) /* bits 6:7 */ |
---|
40 | 39 | #define ENTRY_ACCESS_RO (3ULL << 6) |
---|
41 | | -#define ENTRY_SHARE_BITS (3ULL << 8) /* bits 9:8 */ |
---|
42 | 40 | #define ENTRY_ACCESS_BIT (1ULL << 10) |
---|
43 | 41 | #define ENTRY_NX_BIT (1ULL << 54) |
---|
| 42 | + |
---|
| 43 | +#define UNUSED_BIT_POSITION_IN_PAGE_DESCRIPTOR (55) |
---|
| 44 | +#define VALID_ENTRY_MASK ((u64)0xF << UNUSED_BIT_POSITION_IN_PAGE_DESCRIPTOR) |
---|
44 | 45 | |
---|
45 | 46 | /* Helper Function to perform assignment of page table entries, to |
---|
46 | 47 | * ensure the use of strd, which is required on LPAE systems. |
---|
.. | .. |
---|
85 | 86 | if (!(entry & 1)) |
---|
86 | 87 | return 0; |
---|
87 | 88 | |
---|
| 89 | + entry &= ~VALID_ENTRY_MASK; |
---|
88 | 90 | return entry & ~0xFFF; |
---|
89 | 91 | } |
---|
90 | 92 | |
---|
.. | .. |
---|
151 | 153 | ENTRY_ACCESS_BIT | ENTRY_IS_ATE_L02); |
---|
152 | 154 | } |
---|
153 | 155 | |
---|
| 156 | +static unsigned int get_num_valid_entries(u64 *pgd) |
---|
| 157 | +{ |
---|
| 158 | + register unsigned int num_of_valid_entries; |
---|
| 159 | + |
---|
| 160 | + num_of_valid_entries = |
---|
| 161 | + (unsigned int)((pgd[2] & VALID_ENTRY_MASK) >> |
---|
| 162 | + (UNUSED_BIT_POSITION_IN_PAGE_DESCRIPTOR - 8)); |
---|
| 163 | + num_of_valid_entries |= |
---|
| 164 | + (unsigned int)((pgd[1] & VALID_ENTRY_MASK) >> |
---|
| 165 | + (UNUSED_BIT_POSITION_IN_PAGE_DESCRIPTOR - 4)); |
---|
| 166 | + num_of_valid_entries |= |
---|
| 167 | + (unsigned int)((pgd[0] & VALID_ENTRY_MASK) >> |
---|
| 168 | + (UNUSED_BIT_POSITION_IN_PAGE_DESCRIPTOR)); |
---|
| 169 | + |
---|
| 170 | + return num_of_valid_entries; |
---|
| 171 | +} |
---|
| 172 | + |
---|
| 173 | +static void set_num_valid_entries(u64 *pgd, unsigned int num_of_valid_entries) |
---|
| 174 | +{ |
---|
| 175 | + WARN_ON_ONCE(num_of_valid_entries > KBASE_MMU_PAGE_ENTRIES); |
---|
| 176 | + |
---|
| 177 | + pgd[0] &= ~VALID_ENTRY_MASK; |
---|
| 178 | + pgd[0] |= ((u64)(num_of_valid_entries & 0xF) |
---|
| 179 | + << UNUSED_BIT_POSITION_IN_PAGE_DESCRIPTOR); |
---|
| 180 | + |
---|
| 181 | + pgd[1] &= ~VALID_ENTRY_MASK; |
---|
| 182 | + pgd[1] |= ((u64)((num_of_valid_entries >> 4) & 0xF) |
---|
| 183 | + << UNUSED_BIT_POSITION_IN_PAGE_DESCRIPTOR); |
---|
| 184 | + |
---|
| 185 | + pgd[2] &= ~VALID_ENTRY_MASK; |
---|
| 186 | + pgd[2] |= ((u64)((num_of_valid_entries >> 8) & 0xF) |
---|
| 187 | + << UNUSED_BIT_POSITION_IN_PAGE_DESCRIPTOR); |
---|
| 188 | +} |
---|
| 189 | + |
---|
154 | 190 | static void entry_set_pte(u64 *entry, phys_addr_t phy) |
---|
155 | 191 | { |
---|
156 | | - page_table_entry_set(entry, (phy & PAGE_MASK) | |
---|
157 | | - ENTRY_ACCESS_BIT | ENTRY_IS_PTE); |
---|
| 192 | + page_table_entry_set(entry, (phy & PAGE_MASK) | ENTRY_ACCESS_BIT | ENTRY_IS_PTE); |
---|
158 | 193 | } |
---|
159 | 194 | |
---|
160 | | -static void entry_invalidate(u64 *entry) |
---|
| 195 | +static void entries_invalidate(u64 *entry, u32 count) |
---|
161 | 196 | { |
---|
162 | | - page_table_entry_set(entry, ENTRY_IS_INVAL); |
---|
| 197 | + u32 i; |
---|
| 198 | + |
---|
| 199 | + for (i = 0; i < count; i++) |
---|
| 200 | + page_table_entry_set(entry + i, ENTRY_IS_INVAL); |
---|
163 | 201 | } |
---|
164 | 202 | |
---|
165 | | -static struct kbase_mmu_mode const aarch64_mode = { |
---|
166 | | - .update = mmu_update, |
---|
167 | | - .get_as_setup = kbase_mmu_get_as_setup, |
---|
168 | | - .disable_as = mmu_disable_as, |
---|
169 | | - .pte_to_phy_addr = pte_to_phy_addr, |
---|
170 | | - .ate_is_valid = ate_is_valid, |
---|
171 | | - .pte_is_valid = pte_is_valid, |
---|
172 | | - .entry_set_ate = entry_set_ate, |
---|
173 | | - .entry_set_pte = entry_set_pte, |
---|
174 | | - .entry_invalidate = entry_invalidate, |
---|
175 | | - .flags = KBASE_MMU_MODE_HAS_NON_CACHEABLE |
---|
176 | | -}; |
---|
| 203 | +static const struct kbase_mmu_mode aarch64_mode = { .update = mmu_update, |
---|
| 204 | + .get_as_setup = kbase_mmu_get_as_setup, |
---|
| 205 | + .disable_as = mmu_disable_as, |
---|
| 206 | + .pte_to_phy_addr = pte_to_phy_addr, |
---|
| 207 | + .ate_is_valid = ate_is_valid, |
---|
| 208 | + .pte_is_valid = pte_is_valid, |
---|
| 209 | + .entry_set_ate = entry_set_ate, |
---|
| 210 | + .entry_set_pte = entry_set_pte, |
---|
| 211 | + .entries_invalidate = entries_invalidate, |
---|
| 212 | + .get_num_valid_entries = get_num_valid_entries, |
---|
| 213 | + .set_num_valid_entries = set_num_valid_entries, |
---|
| 214 | + .flags = KBASE_MMU_MODE_HAS_NON_CACHEABLE }; |
---|
177 | 215 | |
---|
178 | 216 | struct kbase_mmu_mode const *kbase_mmu_mode_get_aarch64(void) |
---|
179 | 217 | { |
---|