]>
Commit | Line | Data |
---|---|---|
eaaaece4 AB |
1 | /** @file\r |
2 | * File managing the MMU for ARMv7 architecture\r | |
3 | *\r | |
a9e51860 | 4 | * Copyright (c) 2011-2021, Arm Limited. All rights reserved.<BR>\r |
eaaaece4 AB |
5 | *\r |
6 | * SPDX-License-Identifier: BSD-2-Clause-Patent\r | |
7 | *\r | |
8 | **/\r | |
9 | \r | |
10 | #include <Uefi.h>\r | |
11 | \r | |
12 | #include <Library/ArmLib.h>\r | |
13 | #include <Library/BaseLib.h>\r | |
14 | #include <Library/BaseMemoryLib.h>\r | |
15 | #include <Library/DebugLib.h>\r | |
16 | #include <Library/CacheMaintenanceLib.h>\r | |
17 | #include <Library/MemoryAllocationLib.h>\r | |
18 | \r | |
19 | #include <Chipset/ArmV7.h>\r | |
20 | \r | |
429309e0 | 21 | #define __EFI_MEMORY_RWX 0 // no restrictions\r |
eaaaece4 | 22 | \r |
429309e0 | 23 | #define CACHE_ATTRIBUTE_MASK (EFI_MEMORY_UC | \\r |
eaaaece4 AB |
24 | EFI_MEMORY_WC | \\r |
25 | EFI_MEMORY_WT | \\r | |
26 | EFI_MEMORY_WB | \\r | |
27 | EFI_MEMORY_UCE | \\r | |
28 | EFI_MEMORY_WP)\r | |
29 | \r | |
30 | STATIC\r | |
31 | EFI_STATUS\r | |
32 | ConvertSectionToPages (\r | |
33 | IN EFI_PHYSICAL_ADDRESS BaseAddress\r | |
34 | )\r | |
35 | {\r | |
429309e0 MK |
36 | UINT32 FirstLevelIdx;\r |
37 | UINT32 SectionDescriptor;\r | |
38 | UINT32 PageTableDescriptor;\r | |
39 | UINT32 PageDescriptor;\r | |
40 | UINT32 Index;\r | |
eaaaece4 | 41 | \r |
429309e0 MK |
42 | volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;\r |
43 | volatile ARM_PAGE_TABLE_ENTRY *PageTable;\r | |
eaaaece4 AB |
44 | \r |
45 | DEBUG ((DEBUG_PAGE, "Converting section at 0x%x to pages\n", (UINTN)BaseAddress));\r | |
46 | \r | |
47 | // Obtain page table base\r | |
48 | FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();\r | |
49 | \r | |
50 | // Calculate index into first level translation table for start of modification\r | |
429309e0 | 51 | FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;\r |
eaaaece4 AB |
52 | ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);\r |
53 | \r | |
54 | // Get section attributes and convert to page attributes\r | |
55 | SectionDescriptor = FirstLevelTable[FirstLevelIdx];\r | |
429309e0 | 56 | PageDescriptor = TT_DESCRIPTOR_PAGE_TYPE_PAGE | ConvertSectionAttributesToPageAttributes (SectionDescriptor, FALSE);\r |
eaaaece4 AB |
57 | \r |
58 | // Allocate a page table for the 4KB entries (we use up a full page even though we only need 1KB)\r | |
59 | PageTable = (volatile ARM_PAGE_TABLE_ENTRY *)AllocatePages (1);\r | |
60 | if (PageTable == NULL) {\r | |
61 | return EFI_OUT_OF_RESOURCES;\r | |
62 | }\r | |
63 | \r | |
64 | // Write the page table entries out\r | |
65 | for (Index = 0; Index < TRANSLATION_TABLE_PAGE_COUNT; Index++) {\r | |
429309e0 | 66 | PageTable[Index] = TT_DESCRIPTOR_PAGE_BASE_ADDRESS (BaseAddress + (Index << 12)) | PageDescriptor;\r |
eaaaece4 AB |
67 | }\r |
68 | \r | |
69 | // Formulate page table entry, Domain=0, NS=0\r | |
70 | PageTableDescriptor = (((UINTN)PageTable) & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK) | TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE;\r | |
71 | \r | |
72 | // Write the page table entry out, replacing section entry\r | |
73 | FirstLevelTable[FirstLevelIdx] = PageTableDescriptor;\r | |
74 | \r | |
75 | return EFI_SUCCESS;\r | |
76 | }\r | |
77 | \r | |
78 | STATIC\r | |
79 | EFI_STATUS\r | |
80 | UpdatePageEntries (\r | |
429309e0 MK |
81 | IN EFI_PHYSICAL_ADDRESS BaseAddress,\r |
82 | IN UINT64 Length,\r | |
83 | IN UINT64 Attributes,\r | |
84 | OUT BOOLEAN *FlushTlbs OPTIONAL\r | |
eaaaece4 AB |
85 | )\r |
86 | {\r | |
429309e0 MK |
87 | EFI_STATUS Status;\r |
88 | UINT32 EntryValue;\r | |
89 | UINT32 EntryMask;\r | |
90 | UINT32 FirstLevelIdx;\r | |
91 | UINT32 Offset;\r | |
92 | UINT32 NumPageEntries;\r | |
93 | UINT32 Descriptor;\r | |
94 | UINT32 p;\r | |
95 | UINT32 PageTableIndex;\r | |
96 | UINT32 PageTableEntry;\r | |
97 | UINT32 CurrentPageTableEntry;\r | |
98 | VOID *Mva;\r | |
99 | \r | |
100 | volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;\r | |
101 | volatile ARM_PAGE_TABLE_ENTRY *PageTable;\r | |
eaaaece4 AB |
102 | \r |
103 | Status = EFI_SUCCESS;\r | |
104 | \r | |
105 | // EntryMask: bitmask of values to change (1 = change this value, 0 = leave alone)\r | |
106 | // EntryValue: values at bit positions specified by EntryMask\r | |
107 | EntryMask = TT_DESCRIPTOR_PAGE_TYPE_MASK | TT_DESCRIPTOR_PAGE_AP_MASK;\r | |
a9e51860 | 108 | if ((Attributes & EFI_MEMORY_XP) != 0) {\r |
eaaaece4 AB |
109 | EntryValue = TT_DESCRIPTOR_PAGE_TYPE_PAGE_XN;\r |
110 | } else {\r | |
111 | EntryValue = TT_DESCRIPTOR_PAGE_TYPE_PAGE;\r | |
112 | }\r | |
113 | \r | |
114 | // Although the PI spec is unclear on this, the GCD guarantees that only\r | |
115 | // one Attribute bit is set at a time, so the order of the conditionals below\r | |
116 | // is irrelevant. If no memory attribute is specified, we preserve whatever\r | |
117 | // memory type is set in the page tables, and update the permission attributes\r | |
118 | // only.\r | |
a9e51860 | 119 | if ((Attributes & EFI_MEMORY_UC) != 0) {\r |
eaaaece4 AB |
120 | // modify cacheability attributes\r |
121 | EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;\r | |
122 | // map to strongly ordered\r | |
123 | EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0\r | |
a9e51860 | 124 | } else if ((Attributes & EFI_MEMORY_WC) != 0) {\r |
eaaaece4 AB |
125 | // modify cacheability attributes\r |
126 | EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;\r | |
b8de64be | 127 | // map to normal non-cacheable\r |
eaaaece4 | 128 | EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0\r |
a9e51860 | 129 | } else if ((Attributes & EFI_MEMORY_WT) != 0) {\r |
eaaaece4 AB |
130 | // modify cacheability attributes\r |
131 | EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;\r | |
132 | // write through with no-allocate\r | |
133 | EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0\r | |
a9e51860 | 134 | } else if ((Attributes & EFI_MEMORY_WB) != 0) {\r |
eaaaece4 AB |
135 | // modify cacheability attributes\r |
136 | EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;\r | |
137 | // write back (with allocate)\r | |
138 | EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1\r | |
a9e51860 | 139 | } else if ((Attributes & CACHE_ATTRIBUTE_MASK) != 0) {\r |
eaaaece4 AB |
140 | // catch unsupported memory type attributes\r |
141 | ASSERT (FALSE);\r | |
142 | return EFI_UNSUPPORTED;\r | |
143 | }\r | |
144 | \r | |
a9e51860 | 145 | if ((Attributes & EFI_MEMORY_RO) != 0) {\r |
eaaaece4 AB |
146 | EntryValue |= TT_DESCRIPTOR_PAGE_AP_RO_RO;\r |
147 | } else {\r | |
148 | EntryValue |= TT_DESCRIPTOR_PAGE_AP_RW_RW;\r | |
149 | }\r | |
150 | \r | |
151 | // Obtain page table base\r | |
152 | FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();\r | |
153 | \r | |
154 | // Calculate number of 4KB page table entries to change\r | |
2bdc9042 | 155 | NumPageEntries = (UINT32)(Length / TT_DESCRIPTOR_PAGE_SIZE);\r |
eaaaece4 AB |
156 | \r |
157 | // Iterate for the number of 4KB pages to change\r | |
158 | Offset = 0;\r | |
429309e0 | 159 | for (p = 0; p < NumPageEntries; p++) {\r |
eaaaece4 AB |
160 | // Calculate index into first level translation table for page table value\r |
161 | \r | |
429309e0 | 162 | FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (BaseAddress + Offset) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;\r |
eaaaece4 AB |
163 | ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);\r |
164 | \r | |
165 | // Read the descriptor from the first level page table\r | |
166 | Descriptor = FirstLevelTable[FirstLevelIdx];\r | |
167 | \r | |
168 | // Does this descriptor need to be converted from section entry to 4K pages?\r | |
429309e0 | 169 | if (!TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE (Descriptor)) {\r |
eaaaece4 | 170 | Status = ConvertSectionToPages (FirstLevelIdx << TT_DESCRIPTOR_SECTION_BASE_SHIFT);\r |
429309e0 | 171 | if (EFI_ERROR (Status)) {\r |
eaaaece4 AB |
172 | // Exit for loop\r |
173 | break;\r | |
174 | }\r | |
175 | \r | |
176 | // Re-read descriptor\r | |
177 | Descriptor = FirstLevelTable[FirstLevelIdx];\r | |
178 | if (FlushTlbs != NULL) {\r | |
179 | *FlushTlbs = TRUE;\r | |
180 | }\r | |
181 | }\r | |
182 | \r | |
183 | // Obtain page table base address\r | |
429309e0 | 184 | PageTable = (ARM_PAGE_TABLE_ENTRY *)TT_DESCRIPTOR_PAGE_BASE_ADDRESS (Descriptor);\r |
eaaaece4 AB |
185 | \r |
186 | // Calculate index into the page table\r | |
187 | PageTableIndex = ((BaseAddress + Offset) & TT_DESCRIPTOR_PAGE_INDEX_MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT;\r | |
188 | ASSERT (PageTableIndex < TRANSLATION_TABLE_PAGE_COUNT);\r | |
189 | \r | |
190 | // Get the entry\r | |
191 | CurrentPageTableEntry = PageTable[PageTableIndex];\r | |
192 | \r | |
193 | // Mask off appropriate fields\r | |
194 | PageTableEntry = CurrentPageTableEntry & ~EntryMask;\r | |
195 | \r | |
196 | // Mask in new attributes and/or permissions\r | |
197 | PageTableEntry |= EntryValue;\r | |
198 | \r | |
199 | if (CurrentPageTableEntry != PageTableEntry) {\r | |
200 | Mva = (VOID *)(UINTN)((((UINTN)FirstLevelIdx) << TT_DESCRIPTOR_SECTION_BASE_SHIFT) + (PageTableIndex << TT_DESCRIPTOR_PAGE_BASE_SHIFT));\r | |
201 | \r | |
202 | // Only need to update if we are changing the entry\r | |
203 | PageTable[PageTableIndex] = PageTableEntry;\r | |
204 | ArmUpdateTranslationTableEntry ((VOID *)&PageTable[PageTableIndex], Mva);\r | |
205 | }\r | |
206 | \r | |
429309e0 | 207 | Status = EFI_SUCCESS;\r |
eaaaece4 | 208 | Offset += TT_DESCRIPTOR_PAGE_SIZE;\r |
eaaaece4 AB |
209 | } // End first level translation table loop\r |
210 | \r | |
211 | return Status;\r | |
212 | }\r | |
213 | \r | |
214 | STATIC\r | |
215 | EFI_STATUS\r | |
216 | UpdateSectionEntries (\r | |
429309e0 MK |
217 | IN EFI_PHYSICAL_ADDRESS BaseAddress,\r |
218 | IN UINT64 Length,\r | |
219 | IN UINT64 Attributes\r | |
eaaaece4 AB |
220 | )\r |
221 | {\r | |
429309e0 MK |
222 | EFI_STATUS Status;\r |
223 | UINT32 EntryMask;\r | |
224 | UINT32 EntryValue;\r | |
225 | UINT32 FirstLevelIdx;\r | |
226 | UINT32 NumSections;\r | |
227 | UINT32 i;\r | |
228 | UINT32 CurrentDescriptor;\r | |
229 | UINT32 Descriptor;\r | |
230 | VOID *Mva;\r | |
231 | volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;\r | |
eaaaece4 | 232 | \r |
146af6a4 PG |
233 | Status = EFI_SUCCESS;\r |
234 | \r | |
eaaaece4 AB |
235 | // EntryMask: bitmask of values to change (1 = change this value, 0 = leave alone)\r |
236 | // EntryValue: values at bit positions specified by EntryMask\r | |
237 | \r | |
238 | // Make sure we handle a section range that is unmapped\r | |
239 | EntryMask = TT_DESCRIPTOR_SECTION_TYPE_MASK | TT_DESCRIPTOR_SECTION_XN_MASK |\r | |
240 | TT_DESCRIPTOR_SECTION_AP_MASK;\r | |
241 | EntryValue = TT_DESCRIPTOR_SECTION_TYPE_SECTION;\r | |
242 | \r | |
243 | // Although the PI spec is unclear on this, the GCD guarantees that only\r | |
244 | // one Attribute bit is set at a time, so the order of the conditionals below\r | |
245 | // is irrelevant. If no memory attribute is specified, we preserve whatever\r | |
246 | // memory type is set in the page tables, and update the permission attributes\r | |
247 | // only.\r | |
a9e51860 | 248 | if ((Attributes & EFI_MEMORY_UC) != 0) {\r |
eaaaece4 AB |
249 | // modify cacheability attributes\r |
250 | EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;\r | |
251 | // map to strongly ordered\r | |
252 | EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0\r | |
a9e51860 | 253 | } else if ((Attributes & EFI_MEMORY_WC) != 0) {\r |
eaaaece4 AB |
254 | // modify cacheability attributes\r |
255 | EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;\r | |
b8de64be | 256 | // map to normal non-cacheable\r |
eaaaece4 | 257 | EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0\r |
a9e51860 | 258 | } else if ((Attributes & EFI_MEMORY_WT) != 0) {\r |
eaaaece4 AB |
259 | // modify cacheability attributes\r |
260 | EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;\r | |
261 | // write through with no-allocate\r | |
262 | EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0\r | |
a9e51860 | 263 | } else if ((Attributes & EFI_MEMORY_WB) != 0) {\r |
eaaaece4 AB |
264 | // modify cacheability attributes\r |
265 | EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;\r | |
266 | // write back (with allocate)\r | |
267 | EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1\r | |
a9e51860 | 268 | } else if ((Attributes & CACHE_ATTRIBUTE_MASK) != 0) {\r |
eaaaece4 AB |
269 | // catch unsupported memory type attributes\r |
270 | ASSERT (FALSE);\r | |
271 | return EFI_UNSUPPORTED;\r | |
272 | }\r | |
273 | \r | |
a9e51860 | 274 | if ((Attributes & EFI_MEMORY_RO) != 0) {\r |
eaaaece4 AB |
275 | EntryValue |= TT_DESCRIPTOR_SECTION_AP_RO_RO;\r |
276 | } else {\r | |
277 | EntryValue |= TT_DESCRIPTOR_SECTION_AP_RW_RW;\r | |
278 | }\r | |
279 | \r | |
a9e51860 | 280 | if ((Attributes & EFI_MEMORY_XP) != 0) {\r |
eaaaece4 AB |
281 | EntryValue |= TT_DESCRIPTOR_SECTION_XN_MASK;\r |
282 | }\r | |
283 | \r | |
284 | // obtain page table base\r | |
285 | FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();\r | |
286 | \r | |
287 | // calculate index into first level translation table for start of modification\r | |
429309e0 | 288 | FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;\r |
eaaaece4 AB |
289 | ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);\r |
290 | \r | |
291 | // calculate number of 1MB first level entries this applies to\r | |
2bdc9042 | 292 | NumSections = (UINT32)(Length / TT_DESCRIPTOR_SECTION_SIZE);\r |
eaaaece4 AB |
293 | \r |
294 | // iterate through each descriptor\r | |
429309e0 | 295 | for (i = 0; i < NumSections; i++) {\r |
eaaaece4 AB |
296 | CurrentDescriptor = FirstLevelTable[FirstLevelIdx + i];\r |
297 | \r | |
298 | // has this descriptor already been converted to pages?\r | |
429309e0 | 299 | if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE (CurrentDescriptor)) {\r |
eaaaece4 AB |
300 | // forward this 1MB range to page table function instead\r |
301 | Status = UpdatePageEntries (\r | |
302 | (FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT,\r | |
303 | TT_DESCRIPTOR_SECTION_SIZE,\r | |
304 | Attributes,\r | |
429309e0 MK |
305 | NULL\r |
306 | );\r | |
eaaaece4 AB |
307 | } else {\r |
308 | // still a section entry\r | |
309 | \r | |
310 | if (CurrentDescriptor != 0) {\r | |
311 | // mask off appropriate fields\r | |
312 | Descriptor = CurrentDescriptor & ~EntryMask;\r | |
313 | } else {\r | |
314 | Descriptor = ((UINTN)FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT;\r | |
315 | }\r | |
316 | \r | |
317 | // mask in new attributes and/or permissions\r | |
318 | Descriptor |= EntryValue;\r | |
319 | \r | |
320 | if (CurrentDescriptor != Descriptor) {\r | |
321 | Mva = (VOID *)(UINTN)(((UINTN)FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT);\r | |
322 | \r | |
323 | // Only need to update if we are changing the descriptor\r | |
324 | FirstLevelTable[FirstLevelIdx + i] = Descriptor;\r | |
325 | ArmUpdateTranslationTableEntry ((VOID *)&FirstLevelTable[FirstLevelIdx + i], Mva);\r | |
326 | }\r | |
327 | \r | |
328 | Status = EFI_SUCCESS;\r | |
329 | }\r | |
330 | }\r | |
331 | \r | |
332 | return Status;\r | |
333 | }\r | |
334 | \r | |
335 | EFI_STATUS\r | |
336 | ArmSetMemoryAttributes (\r | |
429309e0 MK |
337 | IN EFI_PHYSICAL_ADDRESS BaseAddress,\r |
338 | IN UINT64 Length,\r | |
339 | IN UINT64 Attributes\r | |
eaaaece4 AB |
340 | )\r |
341 | {\r | |
429309e0 MK |
342 | EFI_STATUS Status;\r |
343 | UINT64 ChunkLength;\r | |
344 | BOOLEAN FlushTlbs;\r | |
eaaaece4 AB |
345 | \r |
346 | if (BaseAddress > (UINT64)MAX_ADDRESS) {\r | |
347 | return EFI_UNSUPPORTED;\r | |
348 | }\r | |
349 | \r | |
350 | Length = MIN (Length, (UINT64)MAX_ADDRESS - BaseAddress + 1);\r | |
351 | if (Length == 0) {\r | |
352 | return EFI_SUCCESS;\r | |
353 | }\r | |
354 | \r | |
355 | FlushTlbs = FALSE;\r | |
356 | while (Length > 0) {\r | |
357 | if ((BaseAddress % TT_DESCRIPTOR_SECTION_SIZE == 0) &&\r | |
429309e0 MK |
358 | (Length >= TT_DESCRIPTOR_SECTION_SIZE))\r |
359 | {\r | |
eaaaece4 AB |
360 | ChunkLength = Length - Length % TT_DESCRIPTOR_SECTION_SIZE;\r |
361 | \r | |
429309e0 MK |
362 | DEBUG ((\r |
363 | DEBUG_PAGE,\r | |
eaaaece4 | 364 | "SetMemoryAttributes(): MMU section 0x%lx length 0x%lx to %lx\n",\r |
429309e0 MK |
365 | BaseAddress,\r |
366 | ChunkLength,\r | |
367 | Attributes\r | |
368 | ));\r | |
eaaaece4 AB |
369 | \r |
370 | Status = UpdateSectionEntries (BaseAddress, ChunkLength, Attributes);\r | |
371 | \r | |
372 | FlushTlbs = TRUE;\r | |
373 | } else {\r | |
eaaaece4 AB |
374 | //\r |
375 | // Process page by page until the next section boundary, but only if\r | |
376 | // we have more than a section's worth of area to deal with after that.\r | |
377 | //\r | |
378 | ChunkLength = TT_DESCRIPTOR_SECTION_SIZE -\r | |
379 | (BaseAddress % TT_DESCRIPTOR_SECTION_SIZE);\r | |
380 | if (ChunkLength + TT_DESCRIPTOR_SECTION_SIZE > Length) {\r | |
381 | ChunkLength = Length;\r | |
382 | }\r | |
383 | \r | |
429309e0 MK |
384 | DEBUG ((\r |
385 | DEBUG_PAGE,\r | |
eaaaece4 | 386 | "SetMemoryAttributes(): MMU page 0x%lx length 0x%lx to %lx\n",\r |
429309e0 MK |
387 | BaseAddress,\r |
388 | ChunkLength,\r | |
389 | Attributes\r | |
390 | ));\r | |
eaaaece4 | 391 | \r |
429309e0 MK |
392 | Status = UpdatePageEntries (\r |
393 | BaseAddress,\r | |
394 | ChunkLength,\r | |
395 | Attributes,\r | |
396 | &FlushTlbs\r | |
397 | );\r | |
eaaaece4 AB |
398 | }\r |
399 | \r | |
400 | if (EFI_ERROR (Status)) {\r | |
401 | break;\r | |
402 | }\r | |
403 | \r | |
404 | BaseAddress += ChunkLength;\r | |
429309e0 | 405 | Length -= ChunkLength;\r |
eaaaece4 AB |
406 | }\r |
407 | \r | |
408 | if (FlushTlbs) {\r | |
409 | ArmInvalidateTlb ();\r | |
410 | }\r | |
429309e0 | 411 | \r |
eaaaece4 AB |
412 | return Status;\r |
413 | }\r | |
414 | \r | |
415 | EFI_STATUS\r | |
416 | ArmSetMemoryRegionNoExec (\r | |
429309e0 MK |
417 | IN EFI_PHYSICAL_ADDRESS BaseAddress,\r |
418 | IN UINT64 Length\r | |
eaaaece4 AB |
419 | )\r |
420 | {\r | |
421 | return ArmSetMemoryAttributes (BaseAddress, Length, EFI_MEMORY_XP);\r | |
422 | }\r | |
423 | \r | |
424 | EFI_STATUS\r | |
425 | ArmClearMemoryRegionNoExec (\r | |
429309e0 MK |
426 | IN EFI_PHYSICAL_ADDRESS BaseAddress,\r |
427 | IN UINT64 Length\r | |
eaaaece4 AB |
428 | )\r |
429 | {\r | |
430 | return ArmSetMemoryAttributes (BaseAddress, Length, __EFI_MEMORY_RWX);\r | |
431 | }\r | |
432 | \r | |
433 | EFI_STATUS\r | |
434 | ArmSetMemoryRegionReadOnly (\r | |
429309e0 MK |
435 | IN EFI_PHYSICAL_ADDRESS BaseAddress,\r |
436 | IN UINT64 Length\r | |
eaaaece4 AB |
437 | )\r |
438 | {\r | |
439 | return ArmSetMemoryAttributes (BaseAddress, Length, EFI_MEMORY_RO);\r | |
440 | }\r | |
441 | \r | |
442 | EFI_STATUS\r | |
443 | ArmClearMemoryRegionReadOnly (\r | |
429309e0 MK |
444 | IN EFI_PHYSICAL_ADDRESS BaseAddress,\r |
445 | IN UINT64 Length\r | |
eaaaece4 AB |
446 | )\r |
447 | {\r | |
448 | return ArmSetMemoryAttributes (BaseAddress, Length, __EFI_MEMORY_RWX);\r | |
449 | }\r |