2 Page table management support.
4 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Library/BaseLib.h>
18 #include <Library/CpuLib.h>
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/MemoryAllocationLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/UefiBootServicesTableLib.h>
23 #include <Protocol/MpService.h>
24 #include "CpuPageTable.h"
29 #define IA32_PG_P BIT0
30 #define IA32_PG_RW BIT1
31 #define IA32_PG_U BIT2
32 #define IA32_PG_WT BIT3
33 #define IA32_PG_CD BIT4
34 #define IA32_PG_A BIT5
35 #define IA32_PG_D BIT6
36 #define IA32_PG_PS BIT7
37 #define IA32_PG_PAT_2M BIT12
38 #define IA32_PG_PAT_4K IA32_PG_PS
39 #define IA32_PG_PMNT BIT62
40 #define IA32_PG_NX BIT63
42 #define PAGE_ATTRIBUTE_BITS (IA32_PG_D | IA32_PG_A | IA32_PG_U | IA32_PG_RW | IA32_PG_P)
44 // Bits 1, 2, 5, 6 are reserved in the IA32 PAE PDPTE
45 // X64 PAE PDPTE does not have such restriction
47 #define IA32_PAE_PDPTE_ATTRIBUTE_BITS (IA32_PG_P)
49 #define PAGE_PROGATE_BITS (IA32_PG_NX | PAGE_ATTRIBUTE_BITS)
51 #define PAGING_4K_MASK 0xFFF
52 #define PAGING_2M_MASK 0x1FFFFF
53 #define PAGING_1G_MASK 0x3FFFFFFF
55 #define PAGING_PAE_INDEX_MASK 0x1FF
57 #define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull
58 #define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull
59 #define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
69 PAGE_ATTRIBUTE Attribute
;
72 } PAGE_ATTRIBUTE_TABLE
;
80 PAGE_ATTRIBUTE_TABLE mPageAttributeTable
[] = {
81 {Page4K
, SIZE_4KB
, PAGING_4K_ADDRESS_MASK_64
},
82 {Page2M
, SIZE_2MB
, PAGING_2M_ADDRESS_MASK_64
},
83 {Page1G
, SIZE_1GB
, PAGING_1G_ADDRESS_MASK_64
},
87 Enable write protection function for AP.
89 @param[in,out] Buffer The pointer to private data buffer.
93 SyncCpuEnableWriteProtection (
97 AsmWriteCr0 (AsmReadCr0 () | BIT16
);
101 CpuFlushTlb function for AP.
103 @param[in,out] Buffer The pointer to private data buffer.
115 Sync memory page attributes for AP.
117 @param[in] Procedure A pointer to the function to be run on enabled APs of
121 SyncMemoryPageAttributesAp (
122 IN EFI_AP_PROCEDURE Procedure
126 EFI_MP_SERVICES_PROTOCOL
*MpService
;
128 Status
= gBS
->LocateProtocol (
129 &gEfiMpServiceProtocolGuid
,
134 // Synchronize the update with all APs
136 if (!EFI_ERROR (Status
)) {
137 Status
= MpService
->StartupAllAPs (
139 Procedure
, // Procedure
140 FALSE
, // SingleThread
142 0, // TimeoutInMicrosecsond
143 NULL
, // ProcedureArgument
144 NULL
// FailedCpuList
146 ASSERT (Status
== EFI_SUCCESS
|| Status
== EFI_NOT_STARTED
|| Status
== EFI_NOT_READY
);
151 Return current paging context.
153 @param[in,out] PagingContext The paging context.
156 GetCurrentPagingContext (
157 IN OUT PAGE_TABLE_LIB_PAGING_CONTEXT
*PagingContext
163 ZeroMem(PagingContext
, sizeof(*PagingContext
));
164 if (sizeof(UINTN
) == sizeof(UINT64
)) {
165 PagingContext
->MachineType
= IMAGE_FILE_MACHINE_X64
;
167 PagingContext
->MachineType
= IMAGE_FILE_MACHINE_I386
;
169 if ((AsmReadCr0 () & BIT31
) != 0) {
170 PagingContext
->ContextData
.X64
.PageTableBase
= (AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64
);
171 if ((AsmReadCr0 () & BIT16
) == 0) {
172 AsmWriteCr0 (AsmReadCr0 () | BIT16
);
173 SyncMemoryPageAttributesAp (SyncCpuEnableWriteProtection
);
176 PagingContext
->ContextData
.X64
.PageTableBase
= 0;
179 if ((AsmReadCr4 () & BIT4
) != 0) {
180 PagingContext
->ContextData
.Ia32
.Attributes
|= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PSE
;
182 if ((AsmReadCr4 () & BIT5
) != 0) {
183 PagingContext
->ContextData
.Ia32
.Attributes
|= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAE
;
185 if ((AsmReadCr0 () & BIT16
) != 0) {
186 PagingContext
->ContextData
.Ia32
.Attributes
|= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_WP_ENABLE
;
189 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
190 if (RegEax
> 0x80000000) {
191 AsmCpuid (0x80000001, NULL
, NULL
, NULL
, &RegEdx
);
192 if ((RegEdx
& BIT20
) != 0) {
194 if ((AsmReadMsr64 (0x000001A0) & BIT34
) == 0) {
196 if ((AsmReadMsr64 (0xC0000080) & BIT11
) != 0) {
198 PagingContext
->ContextData
.Ia32
.Attributes
|= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_XD_ACTIVATED
;
202 if ((RegEdx
& BIT26
) != 0) {
203 PagingContext
->ContextData
.Ia32
.Attributes
|= PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAGE_1G_SUPPORT
;
209 Return length according to page attributes.
211 @param[in] PageAttributes The page attribute of the page entry.
213 @return The length of page entry.
216 PageAttributeToLength (
217 IN PAGE_ATTRIBUTE PageAttribute
221 for (Index
= 0; Index
< sizeof(mPageAttributeTable
)/sizeof(mPageAttributeTable
[0]); Index
++) {
222 if (PageAttribute
== mPageAttributeTable
[Index
].Attribute
) {
223 return (UINTN
)mPageAttributeTable
[Index
].Length
;
230 Return address mask according to page attributes.
232 @param[in] PageAttributes The page attribute of the page entry.
234 @return The address mask of page entry.
237 PageAttributeToMask (
238 IN PAGE_ATTRIBUTE PageAttribute
242 for (Index
= 0; Index
< sizeof(mPageAttributeTable
)/sizeof(mPageAttributeTable
[0]); Index
++) {
243 if (PageAttribute
== mPageAttributeTable
[Index
].Attribute
) {
244 return (UINTN
)mPageAttributeTable
[Index
].AddressMask
;
251 Return page table entry to match the address.
253 @param[in] PagingContext The paging context.
254 @param[in] Address The address to be checked.
255 @param[out] PageAttributes The page attribute of the page entry.
257 @return The page entry.
261 IN PAGE_TABLE_LIB_PAGING_CONTEXT
*PagingContext
,
262 IN PHYSICAL_ADDRESS Address
,
263 OUT PAGE_ATTRIBUTE
*PageAttribute
275 ASSERT (PagingContext
!= NULL
);
277 Index4
= ((UINTN
)RShiftU64 (Address
, 39)) & PAGING_PAE_INDEX_MASK
;
278 Index3
= ((UINTN
)Address
>> 30) & PAGING_PAE_INDEX_MASK
;
279 Index2
= ((UINTN
)Address
>> 21) & PAGING_PAE_INDEX_MASK
;
280 Index1
= ((UINTN
)Address
>> 12) & PAGING_PAE_INDEX_MASK
;
282 if (PagingContext
->MachineType
== IMAGE_FILE_MACHINE_X64
) {
283 L4PageTable
= (UINT64
*)(UINTN
)PagingContext
->ContextData
.X64
.PageTableBase
;
284 if (L4PageTable
[Index4
] == 0) {
285 *PageAttribute
= PageNone
;
289 L3PageTable
= (UINT64
*)(UINTN
)(L4PageTable
[Index4
] & PAGING_4K_ADDRESS_MASK_64
);
291 ASSERT((PagingContext
->ContextData
.Ia32
.Attributes
& PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAE
) != 0);
292 L3PageTable
= (UINT64
*)(UINTN
)PagingContext
->ContextData
.Ia32
.PageTableBase
;
294 if (L3PageTable
[Index3
] == 0) {
295 *PageAttribute
= PageNone
;
298 if ((L3PageTable
[Index3
] & IA32_PG_PS
) != 0) {
300 *PageAttribute
= Page1G
;
301 return &L3PageTable
[Index3
];
304 L2PageTable
= (UINT64
*)(UINTN
)(L3PageTable
[Index3
] & PAGING_4K_ADDRESS_MASK_64
);
305 if (L2PageTable
[Index2
] == 0) {
306 *PageAttribute
= PageNone
;
309 if ((L2PageTable
[Index2
] & IA32_PG_PS
) != 0) {
311 *PageAttribute
= Page2M
;
312 return &L2PageTable
[Index2
];
316 L1PageTable
= (UINT64
*)(UINTN
)(L2PageTable
[Index2
] & PAGING_4K_ADDRESS_MASK_64
);
317 if ((L1PageTable
[Index1
] == 0) && (Address
!= 0)) {
318 *PageAttribute
= PageNone
;
321 *PageAttribute
= Page4K
;
322 return &L1PageTable
[Index1
];
326 Return memory attributes of page entry.
328 @param[in] PageEntry The page entry.
330 @return Memory attributes of page entry.
333 GetAttributesFromPageEntry (
339 if ((*PageEntry
& IA32_PG_P
) == 0) {
340 Attributes
|= EFI_MEMORY_RP
;
342 if ((*PageEntry
& IA32_PG_RW
) == 0) {
343 Attributes
|= EFI_MEMORY_RO
;
345 if ((*PageEntry
& IA32_PG_NX
) != 0) {
346 Attributes
|= EFI_MEMORY_XP
;
352 Modify memory attributes of page entry.
354 @param[in] PagingContext The paging context.
355 @param[in] PageEntry The page entry.
356 @param[in] Attributes The bit mask of attributes to modify for the memory region.
357 @param[in] PageAction The page action.
358 @param[out] IsModified TRUE means page table modified. FALSE means page table not modified.
361 ConvertPageEntryAttribute (
362 IN PAGE_TABLE_LIB_PAGING_CONTEXT
*PagingContext
,
363 IN UINT64
*PageEntry
,
364 IN UINT64 Attributes
,
365 IN PAGE_ACTION PageAction
,
366 OUT BOOLEAN
*IsModified
369 UINT64 CurrentPageEntry
;
372 CurrentPageEntry
= *PageEntry
;
373 NewPageEntry
= CurrentPageEntry
;
374 if ((Attributes
& EFI_MEMORY_RP
) != 0) {
375 switch (PageAction
) {
376 case PageActionAssign
:
378 NewPageEntry
&= ~(UINT64
)IA32_PG_P
;
380 case PageActionClear
:
381 NewPageEntry
|= IA32_PG_P
;
385 switch (PageAction
) {
386 case PageActionAssign
:
387 NewPageEntry
|= IA32_PG_P
;
390 case PageActionClear
:
394 if ((Attributes
& EFI_MEMORY_RO
) != 0) {
395 switch (PageAction
) {
396 case PageActionAssign
:
398 NewPageEntry
&= ~(UINT64
)IA32_PG_RW
;
400 case PageActionClear
:
401 NewPageEntry
|= IA32_PG_RW
;
405 switch (PageAction
) {
406 case PageActionAssign
:
407 NewPageEntry
|= IA32_PG_RW
;
410 case PageActionClear
:
414 if ((PagingContext
->ContextData
.Ia32
.Attributes
& PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_XD_ACTIVATED
) != 0) {
415 if ((Attributes
& EFI_MEMORY_XP
) != 0) {
416 switch (PageAction
) {
417 case PageActionAssign
:
419 NewPageEntry
|= IA32_PG_NX
;
421 case PageActionClear
:
422 NewPageEntry
&= ~IA32_PG_NX
;
426 switch (PageAction
) {
427 case PageActionAssign
:
428 NewPageEntry
&= ~IA32_PG_NX
;
431 case PageActionClear
:
436 *PageEntry
= NewPageEntry
;
437 if (CurrentPageEntry
!= NewPageEntry
) {
439 DEBUG ((DEBUG_INFO
, "ConvertPageEntryAttribute 0x%lx", CurrentPageEntry
));
440 DEBUG ((DEBUG_INFO
, "->0x%lx\n", NewPageEntry
));
447 This function returns if there is need to split page entry.
449 @param[in] BaseAddress The base address to be checked.
450 @param[in] Length The length to be checked.
451 @param[in] PageEntry The page entry to be checked.
452 @param[in] PageAttribute The page attribute of the page entry.
454 @retval SplitAttributes on if there is need to split page entry.
458 IN PHYSICAL_ADDRESS BaseAddress
,
460 IN UINT64
*PageEntry
,
461 IN PAGE_ATTRIBUTE PageAttribute
464 UINT64 PageEntryLength
;
466 PageEntryLength
= PageAttributeToLength (PageAttribute
);
468 if (((BaseAddress
& (PageEntryLength
- 1)) == 0) && (Length
>= PageEntryLength
)) {
472 if (((BaseAddress
& PAGING_2M_MASK
) != 0) || (Length
< SIZE_2MB
)) {
480 This function splits one page entry to small page entries.
482 @param[in] PageEntry The page entry to be splitted.
483 @param[in] PageAttribute The page attribute of the page entry.
484 @param[in] SplitAttribute How to split the page entry.
485 @param[in] AllocatePagesFunc If page split is needed, this function is used to allocate more pages.
487 @retval RETURN_SUCCESS The page entry is splitted.
488 @retval RETURN_UNSUPPORTED The page entry does not support to be splitted.
489 @retval RETURN_OUT_OF_RESOURCES No resource to split page entry.
493 IN UINT64
*PageEntry
,
494 IN PAGE_ATTRIBUTE PageAttribute
,
495 IN PAGE_ATTRIBUTE SplitAttribute
,
496 IN PAGE_TABLE_LIB_ALLOCATE_PAGES AllocatePagesFunc
500 UINT64
*NewPageEntry
;
503 ASSERT (PageAttribute
== Page2M
|| PageAttribute
== Page1G
);
505 ASSERT (AllocatePagesFunc
!= NULL
);
507 if (PageAttribute
== Page2M
) {
511 ASSERT (SplitAttribute
== Page4K
);
512 if (SplitAttribute
== Page4K
) {
513 NewPageEntry
= AllocatePagesFunc (1);
514 DEBUG ((DEBUG_INFO
, "Split - 0x%x\n", NewPageEntry
));
515 if (NewPageEntry
== NULL
) {
516 return RETURN_OUT_OF_RESOURCES
;
518 BaseAddress
= *PageEntry
& PAGING_2M_ADDRESS_MASK_64
;
519 for (Index
= 0; Index
< SIZE_4KB
/ sizeof(UINT64
); Index
++) {
520 NewPageEntry
[Index
] = BaseAddress
+ SIZE_4KB
* Index
+ ((*PageEntry
) & PAGE_PROGATE_BITS
);
522 (*PageEntry
) = (UINT64
)(UINTN
)NewPageEntry
+ ((*PageEntry
) & PAGE_PROGATE_BITS
);
523 return RETURN_SUCCESS
;
525 return RETURN_UNSUPPORTED
;
527 } else if (PageAttribute
== Page1G
) {
530 // No need support 1G->4K directly, we should use 1G->2M, then 2M->4K to get more compact page table.
532 ASSERT (SplitAttribute
== Page2M
|| SplitAttribute
== Page4K
);
533 if ((SplitAttribute
== Page2M
|| SplitAttribute
== Page4K
)) {
534 NewPageEntry
= AllocatePagesFunc (1);
535 DEBUG ((DEBUG_INFO
, "Split - 0x%x\n", NewPageEntry
));
536 if (NewPageEntry
== NULL
) {
537 return RETURN_OUT_OF_RESOURCES
;
539 BaseAddress
= *PageEntry
& PAGING_1G_ADDRESS_MASK_64
;
540 for (Index
= 0; Index
< SIZE_4KB
/ sizeof(UINT64
); Index
++) {
541 NewPageEntry
[Index
] = BaseAddress
+ SIZE_2MB
* Index
+ IA32_PG_PS
+ ((*PageEntry
) & PAGE_PROGATE_BITS
);
543 (*PageEntry
) = (UINT64
)(UINTN
)NewPageEntry
+ ((*PageEntry
) & PAGE_PROGATE_BITS
);
544 return RETURN_SUCCESS
;
546 return RETURN_UNSUPPORTED
;
549 return RETURN_UNSUPPORTED
;
554 This function modifies the page attributes for the memory region specified by BaseAddress and
555 Length from their current attributes to the attributes specified by Attributes.
557 Caller should make sure BaseAddress and Length is at page boundary.
559 @param[in] PagingContext The paging context. NULL means get page table from current CPU context.
560 @param[in] BaseAddress The physical address that is the start address of a memory region.
561 @param[in] Length The size in bytes of the memory region.
562 @param[in] Attributes The bit mask of attributes to modify for the memory region.
563 @param[in] PageAction The page action.
564 @param[in] AllocatePagesFunc If page split is needed, this function is used to allocate more pages.
565 NULL mean page split is unsupported.
566 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.
567 @param[out] IsModified TRUE means page table modified. FALSE means page table not modified.
569 @retval RETURN_SUCCESS The attributes were modified for the memory region.
570 @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
571 BaseAddress and Length cannot be modified.
572 @retval RETURN_INVALID_PARAMETER Length is zero.
573 Attributes specified an illegal combination of attributes that
574 cannot be set together.
575 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
576 the memory resource range.
577 @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the memory
578 resource range specified by BaseAddress and Length.
579 The bit mask of attributes is not support for the memory resource
580 range specified by BaseAddress and Length.
583 ConvertMemoryPageAttributes (
584 IN PAGE_TABLE_LIB_PAGING_CONTEXT
*PagingContext OPTIONAL
,
585 IN PHYSICAL_ADDRESS BaseAddress
,
587 IN UINT64 Attributes
,
588 IN PAGE_ACTION PageAction
,
589 IN PAGE_TABLE_LIB_ALLOCATE_PAGES AllocatePagesFunc OPTIONAL
,
590 OUT BOOLEAN
*IsSplitted
, OPTIONAL
591 OUT BOOLEAN
*IsModified OPTIONAL
594 PAGE_TABLE_LIB_PAGING_CONTEXT CurrentPagingContext
;
596 PAGE_ATTRIBUTE PageAttribute
;
597 UINTN PageEntryLength
;
598 PAGE_ATTRIBUTE SplitAttribute
;
599 RETURN_STATUS Status
;
600 BOOLEAN IsEntryModified
;
602 if ((BaseAddress
& (SIZE_4KB
- 1)) != 0) {
603 DEBUG ((DEBUG_ERROR
, "BaseAddress(0x%lx) is not aligned!\n", BaseAddress
));
604 return EFI_UNSUPPORTED
;
606 if ((Length
& (SIZE_4KB
- 1)) != 0) {
607 DEBUG ((DEBUG_ERROR
, "Length(0x%lx) is not aligned!\n", Length
));
608 return EFI_UNSUPPORTED
;
611 DEBUG ((DEBUG_ERROR
, "Length is 0!\n"));
612 return RETURN_INVALID_PARAMETER
;
615 if ((Attributes
& ~(EFI_MEMORY_RP
| EFI_MEMORY_RO
| EFI_MEMORY_XP
)) != 0) {
616 DEBUG ((DEBUG_ERROR
, "Attributes(0x%lx) has unsupported bit\n", Attributes
));
617 return EFI_UNSUPPORTED
;
620 if (PagingContext
== NULL
) {
621 GetCurrentPagingContext (&CurrentPagingContext
);
623 CopyMem (&CurrentPagingContext
, PagingContext
, sizeof(CurrentPagingContext
));
625 switch(CurrentPagingContext
.MachineType
) {
626 case IMAGE_FILE_MACHINE_I386
:
627 if (CurrentPagingContext
.ContextData
.Ia32
.PageTableBase
== 0) {
628 DEBUG ((DEBUG_ERROR
, "PageTable is 0!\n"));
629 if (Attributes
== 0) {
632 return EFI_UNSUPPORTED
;
635 if ((CurrentPagingContext
.ContextData
.Ia32
.Attributes
& PAGE_TABLE_LIB_PAGING_CONTEXT_IA32_X64_ATTRIBUTES_PAE
) == 0) {
636 DEBUG ((DEBUG_ERROR
, "Non-PAE Paging!\n"));
637 return EFI_UNSUPPORTED
;
640 case IMAGE_FILE_MACHINE_X64
:
641 ASSERT (CurrentPagingContext
.ContextData
.X64
.PageTableBase
!= 0);
645 return EFI_UNSUPPORTED
;
649 // DEBUG ((DEBUG_ERROR, "ConvertMemoryPageAttributes(%x) - %016lx, %016lx, %02lx\n", IsSet, BaseAddress, Length, Attributes));
651 if (IsSplitted
!= NULL
) {
654 if (IsModified
!= NULL
) {
659 // Below logic is to check 2M/4K page to make sure we donot waist memory.
661 while (Length
!= 0) {
662 PageEntry
= GetPageTableEntry (&CurrentPagingContext
, BaseAddress
, &PageAttribute
);
663 if (PageEntry
== NULL
) {
664 return RETURN_UNSUPPORTED
;
666 PageEntryLength
= PageAttributeToLength (PageAttribute
);
667 SplitAttribute
= NeedSplitPage (BaseAddress
, Length
, PageEntry
, PageAttribute
);
668 if (SplitAttribute
== PageNone
) {
669 ConvertPageEntryAttribute (&CurrentPagingContext
, PageEntry
, Attributes
, PageAction
, &IsEntryModified
);
670 if (IsEntryModified
) {
671 if (IsModified
!= NULL
) {
676 // Convert success, move to next
678 BaseAddress
+= PageEntryLength
;
679 Length
-= PageEntryLength
;
681 if (AllocatePagesFunc
== NULL
) {
682 return RETURN_UNSUPPORTED
;
684 Status
= SplitPage (PageEntry
, PageAttribute
, SplitAttribute
, AllocatePagesFunc
);
685 if (RETURN_ERROR (Status
)) {
686 return RETURN_UNSUPPORTED
;
688 if (IsSplitted
!= NULL
) {
691 if (IsModified
!= NULL
) {
695 // Just split current page
696 // Convert success in next around
701 return RETURN_SUCCESS
;
705 This function assigns the page attributes for the memory region specified by BaseAddress and
706 Length from their current attributes to the attributes specified by Attributes.
708 Caller should make sure BaseAddress and Length is at page boundary.
710 Caller need guarentee the TPL <= TPL_NOTIFY, if there is split page request.
712 @param[in] PagingContext The paging context. NULL means get page table from current CPU context.
713 @param[in] BaseAddress The physical address that is the start address of a memory region.
714 @param[in] Length The size in bytes of the memory region.
715 @param[in] Attributes The bit mask of attributes to set for the memory region.
716 @param[in] AllocatePagesFunc If page split is needed, this function is used to allocate more pages.
717 NULL mean page split is unsupported.
719 @retval RETURN_SUCCESS The attributes were cleared for the memory region.
720 @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
721 BaseAddress and Length cannot be modified.
722 @retval RETURN_INVALID_PARAMETER Length is zero.
723 Attributes specified an illegal combination of attributes that
724 cannot be set together.
725 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
726 the memory resource range.
727 @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the memory
728 resource range specified by BaseAddress and Length.
729 The bit mask of attributes is not support for the memory resource
730 range specified by BaseAddress and Length.
734 AssignMemoryPageAttributes (
735 IN PAGE_TABLE_LIB_PAGING_CONTEXT
*PagingContext OPTIONAL
,
736 IN PHYSICAL_ADDRESS BaseAddress
,
738 IN UINT64 Attributes
,
739 IN PAGE_TABLE_LIB_ALLOCATE_PAGES AllocatePagesFunc OPTIONAL
742 RETURN_STATUS Status
;
746 // DEBUG((DEBUG_INFO, "AssignMemoryPageAttributes: 0x%lx - 0x%lx (0x%lx)\n", BaseAddress, Length, Attributes));
747 Status
= ConvertMemoryPageAttributes (PagingContext
, BaseAddress
, Length
, Attributes
, PageActionAssign
, AllocatePagesFunc
, &IsSplitted
, &IsModified
);
748 if (!EFI_ERROR(Status
)) {
749 if ((PagingContext
== NULL
) && IsModified
) {
751 // Flush TLB as last step
754 SyncMemoryPageAttributesAp (SyncCpuFlushTlb
);
762 Initialize the Page Table lib.
765 InitializePageTableLib (
769 PAGE_TABLE_LIB_PAGING_CONTEXT CurrentPagingContext
;
771 GetCurrentPagingContext (&CurrentPagingContext
);
772 DEBUG ((DEBUG_INFO
, "CurrentPagingContext:\n", CurrentPagingContext
.MachineType
));
773 DEBUG ((DEBUG_INFO
, " MachineType - 0x%x\n", CurrentPagingContext
.MachineType
));
774 DEBUG ((DEBUG_INFO
, " PageTableBase - 0x%x\n", CurrentPagingContext
.ContextData
.X64
.PageTableBase
));
775 DEBUG ((DEBUG_INFO
, " Attributes - 0x%x\n", CurrentPagingContext
.ContextData
.X64
.Attributes
));