TianoCore EDK2 master
Loading...
Searching...
No Matches
CpuPageTableParse.c
Go to the documentation of this file.
1
9#include "CpuPageTable.h"
10
19UINT64
22 IN IA32_MAP_ATTRIBUTE *ParentMapAttribute
23 )
24{
25 IA32_MAP_ATTRIBUTE MapAttribute;
26
27 //
28 // PageTableBaseAddress cannot be assigned field to field
29 // because their bit positions are different in IA32_MAP_ATTRIBUTE and IA32_PAGE_LEAF_ENTRY_BIG_PAGESIZE.
30 //
31 MapAttribute.Uint64 = IA32_PLEB_PAGE_TABLE_BASE_ADDRESS (PleB);
32
33 MapAttribute.Bits.Present = ParentMapAttribute->Bits.Present & PleB->Bits.Present;
34 MapAttribute.Bits.ReadWrite = ParentMapAttribute->Bits.ReadWrite & PleB->Bits.ReadWrite;
35 MapAttribute.Bits.UserSupervisor = ParentMapAttribute->Bits.UserSupervisor & PleB->Bits.UserSupervisor;
36 MapAttribute.Bits.Nx = ParentMapAttribute->Bits.Nx | PleB->Bits.Nx;
37 MapAttribute.Bits.WriteThrough = PleB->Bits.WriteThrough;
38 MapAttribute.Bits.CacheDisabled = PleB->Bits.CacheDisabled;
39 MapAttribute.Bits.Accessed = PleB->Bits.Accessed;
40
41 MapAttribute.Bits.Pat = PleB->Bits.Pat;
42 MapAttribute.Bits.Dirty = PleB->Bits.Dirty;
43 MapAttribute.Bits.Global = PleB->Bits.Global;
44 MapAttribute.Bits.ProtectionKey = PleB->Bits.ProtectionKey;
45
46 return MapAttribute.Uint64;
47}
48
57UINT64
59 IN IA32_PTE_4K *Pte4K,
60 IN IA32_MAP_ATTRIBUTE *ParentMapAttribute
61 )
62{
63 IA32_MAP_ATTRIBUTE MapAttribute;
64
65 MapAttribute.Uint64 = IA32_PTE4K_PAGE_TABLE_BASE_ADDRESS (Pte4K);
66
67 MapAttribute.Bits.Present = ParentMapAttribute->Bits.Present & Pte4K->Bits.Present;
68 MapAttribute.Bits.ReadWrite = ParentMapAttribute->Bits.ReadWrite & Pte4K->Bits.ReadWrite;
69 MapAttribute.Bits.UserSupervisor = ParentMapAttribute->Bits.UserSupervisor & Pte4K->Bits.UserSupervisor;
70 MapAttribute.Bits.Nx = ParentMapAttribute->Bits.Nx | Pte4K->Bits.Nx;
71 MapAttribute.Bits.WriteThrough = Pte4K->Bits.WriteThrough;
72 MapAttribute.Bits.CacheDisabled = Pte4K->Bits.CacheDisabled;
73 MapAttribute.Bits.Accessed = Pte4K->Bits.Accessed;
74
75 MapAttribute.Bits.Pat = Pte4K->Bits.Pat;
76 MapAttribute.Bits.Dirty = Pte4K->Bits.Dirty;
77 MapAttribute.Bits.Global = Pte4K->Bits.Global;
78 MapAttribute.Bits.ProtectionKey = Pte4K->Bits.ProtectionKey;
79
80 return MapAttribute.Uint64;
81}
82
91UINT64
94 IN IA32_MAP_ATTRIBUTE *ParentMapAttribute
95 )
96{
97 IA32_MAP_ATTRIBUTE MapAttribute;
98
99 MapAttribute.Uint64 = Pnle->Uint64;
100
101 MapAttribute.Bits.Present = ParentMapAttribute->Bits.Present & Pnle->Bits.Present;
102 MapAttribute.Bits.ReadWrite = ParentMapAttribute->Bits.ReadWrite & Pnle->Bits.ReadWrite;
103 MapAttribute.Bits.UserSupervisor = ParentMapAttribute->Bits.UserSupervisor & Pnle->Bits.UserSupervisor;
104 MapAttribute.Bits.Nx = ParentMapAttribute->Bits.Nx | Pnle->Bits.Nx;
105 MapAttribute.Bits.WriteThrough = Pnle->Bits.WriteThrough;
106 MapAttribute.Bits.CacheDisabled = Pnle->Bits.CacheDisabled;
107 MapAttribute.Bits.Accessed = Pnle->Bits.Accessed;
108 return MapAttribute.Uint64;
109}
110
121BOOLEAN
123 IN IA32_PAGING_ENTRY *PagingEntry,
124 IN UINTN Level
125 )
126{
127 //
128 // PML5E and PML4E are always non-leaf entries.
129 //
130 if (Level == 1) {
131 return TRUE;
132 }
133
134 if (((Level == 3) || (Level == 2))) {
135 if (PagingEntry->PleB.Bits.MustBeOne == 1) {
136 return TRUE;
137 }
138 }
139
140 return FALSE;
141}
142
157VOID
159 IN UINT64 PageTableBaseAddress,
160 IN UINTN Level,
161 IN UINTN MaxLevel,
162 IN UINT64 RegionStart,
163 IN IA32_MAP_ATTRIBUTE *ParentMapAttribute,
164 IN OUT IA32_MAP_ENTRY *Map,
165 IN OUT UINTN *MapCount,
166 IN UINTN MapCapacity,
167 IN IA32_MAP_ENTRY **LastEntry,
168 IN IA32_MAP_ENTRY *OneEntry
169 )
170{
171 IA32_PAGING_ENTRY *PagingEntry;
172 UINTN Index;
173 IA32_MAP_ATTRIBUTE MapAttribute;
174 UINT64 RegionLength;
175 UINTN PagingEntryNumber;
176
177 ASSERT (OneEntry != NULL);
178
179 PagingEntry = (IA32_PAGING_ENTRY *)(UINTN)PageTableBaseAddress;
180 RegionLength = REGION_LENGTH (Level);
181 PagingEntryNumber = ((MaxLevel == 3) && (Level == 3)) ? MAX_PAE_PDPTE_NUM : 512;
182
183 for (Index = 0; Index < PagingEntryNumber; Index++, RegionStart += RegionLength) {
184 if (PagingEntry[Index].Pce.Present == 0) {
185 continue;
186 }
187
188 if (IsPle (&PagingEntry[Index], Level)) {
189 ASSERT (Level == 1 || Level == 2 || Level == 3);
190
191 if (Level == 1) {
192 MapAttribute.Uint64 = PageTableLibGetPte4KMapAttribute (&PagingEntry[Index].Pte4K, ParentMapAttribute);
193 } else {
194 MapAttribute.Uint64 = PageTableLibGetPleBMapAttribute (&PagingEntry[Index].PleB, ParentMapAttribute);
195 }
196
197 if ((*LastEntry != NULL) &&
198 ((*LastEntry)->LinearAddress + (*LastEntry)->Length == RegionStart) &&
199 (IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (&(*LastEntry)->Attribute) + (*LastEntry)->Length
200 == IA32_MAP_ATTRIBUTE_PAGE_TABLE_BASE_ADDRESS (&MapAttribute)) &&
201 (IA32_MAP_ATTRIBUTE_ATTRIBUTES (&(*LastEntry)->Attribute) == IA32_MAP_ATTRIBUTE_ATTRIBUTES (&MapAttribute))
202 )
203 {
204 //
205 // Extend LastEntry.
206 //
207 (*LastEntry)->Length += RegionLength;
208 } else {
209 if (*MapCount < MapCapacity) {
210 //
211 // LastEntry points to next map entry in the array.
212 //
213 *LastEntry = &Map[*MapCount];
214 } else {
215 //
216 // LastEntry points to library internal map entry.
217 //
218 *LastEntry = OneEntry;
219 }
220
221 //
222 // Set LastEntry.
223 //
224 (*LastEntry)->LinearAddress = RegionStart;
225 (*LastEntry)->Length = RegionLength;
226 (*LastEntry)->Attribute.Uint64 = MapAttribute.Uint64;
227 (*MapCount)++;
228 }
229 } else {
230 MapAttribute.Uint64 = PageTableLibGetPnleMapAttribute (&PagingEntry[Index].Pnle, ParentMapAttribute);
232 IA32_PNLE_PAGE_TABLE_BASE_ADDRESS (&PagingEntry[Index].Pnle),
233 Level - 1,
234 MaxLevel,
235 RegionStart,
236 &MapAttribute,
237 Map,
238 MapCount,
239 MapCapacity,
240 LastEntry,
241 OneEntry
242 );
243 }
244 }
245}
246
262RETURN_STATUS
263EFIAPI
265 IN UINTN PageTable,
266 IN PAGING_MODE PagingMode,
267 OUT IA32_MAP_ENTRY *Map,
268 IN OUT UINTN *MapCount
269 )
270{
271 UINTN MapCapacity;
272 IA32_MAP_ATTRIBUTE NopAttribute;
273 IA32_MAP_ENTRY *LastEntry;
274 IA32_MAP_ENTRY OneEntry;
275 UINTN MaxLevel;
276 UINTN Index;
277 IA32_PAGING_ENTRY BufferInStack[MAX_PAE_PDPTE_NUM];
278
279 if ((PagingMode == Paging32bit) || (PagingMode >= PagingModeMax)) {
280 //
281 // 32bit paging is never supported.
282 //
283 return RETURN_UNSUPPORTED;
284 }
285
286 if (MapCount == NULL) {
288 }
289
290 if ((*MapCount != 0) && (Map == NULL)) {
292 }
293
294 if (PageTable == 0) {
295 *MapCount = 0;
296 return RETURN_SUCCESS;
297 }
298
299 if (PagingMode == PagingPae) {
300 CopyMem (BufferInStack, (VOID *)PageTable, sizeof (BufferInStack));
301 for (Index = 0; Index < MAX_PAE_PDPTE_NUM; Index++) {
302 BufferInStack[Index].Pnle.Bits.ReadWrite = 1;
303 BufferInStack[Index].Pnle.Bits.UserSupervisor = 1;
304 BufferInStack[Index].Pnle.Bits.Nx = 0;
305 }
306
307 PageTable = (UINTN)BufferInStack;
308 }
309
310 //
311 // Page table layout is as below:
312 //
313 // [IA32_CR3]
314 // |
315 // |
316 // V
317 // [IA32_PML5E]
318 // ...
319 // [IA32_PML5E] --> [IA32_PML4E]
320 // ...
321 // [IA32_PML4E] --> [IA32_PDPTE_1G] --> 1G aligned physical address
322 // ...
323 // [IA32_PDPTE] --> [IA32_PDE_2M] --> 2M aligned physical address
324 // ...
325 // [IA32_PDE] --> [IA32_PTE_4K] --> 4K aligned physical address
326 // ...
327 // [IA32_PTE_4K] --> 4K aligned physical address
328 //
329
330 NopAttribute.Uint64 = 0;
331 NopAttribute.Bits.Present = 1;
332 NopAttribute.Bits.ReadWrite = 1;
333 NopAttribute.Bits.UserSupervisor = 1;
334
335 MaxLevel = (UINT8)(PagingMode >> 8);
336 MapCapacity = *MapCount;
337 *MapCount = 0;
338 LastEntry = NULL;
339 PageTableLibParsePnle ((UINT64)PageTable, MaxLevel, MaxLevel, 0, &NopAttribute, Map, MapCount, MapCapacity, &LastEntry, &OneEntry);
340
341 if (*MapCount > MapCapacity) {
343 }
344
345 return RETURN_SUCCESS;
346}
UINT64 UINTN
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
RETURN_STATUS EFIAPI PageTableParse(IN UINTN PageTable, IN PAGING_MODE PagingMode, OUT IA32_MAP_ENTRY *Map, IN OUT UINTN *MapCount)
UINT64 PageTableLibGetPte4KMapAttribute(IN IA32_PTE_4K *Pte4K, IN IA32_MAP_ATTRIBUTE *ParentMapAttribute)
UINT64 PageTableLibGetPnleMapAttribute(IN IA32_PAGE_NON_LEAF_ENTRY *Pnle, IN IA32_MAP_ATTRIBUTE *ParentMapAttribute)
UINT64 PageTableLibGetPleBMapAttribute(IN IA32_PAGE_LEAF_ENTRY_BIG_PAGESIZE *PleB, IN IA32_MAP_ATTRIBUTE *ParentMapAttribute)
VOID PageTableLibParsePnle(IN UINT64 PageTableBaseAddress, IN UINTN Level, IN UINTN MaxLevel, IN UINT64 RegionStart, IN IA32_MAP_ATTRIBUTE *ParentMapAttribute, IN OUT IA32_MAP_ENTRY *Map, IN OUT UINTN *MapCount, IN UINTN MapCapacity, IN IA32_MAP_ENTRY **LastEntry, IN IA32_MAP_ENTRY *OneEntry)
BOOLEAN IsPle(IN IA32_PAGING_ENTRY *PagingEntry, IN UINTN Level)
#define NULL
Definition: Base.h:319
#define RETURN_BUFFER_TOO_SMALL
Definition: Base.h:1093
#define RETURN_UNSUPPORTED
Definition: Base.h:1081
#define RETURN_SUCCESS
Definition: Base.h:1066
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define RETURN_INVALID_PARAMETER
Definition: Base.h:1076