3 Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 #include "HobGeneration.h"
22 #include "VirtualMemory.h"
25 // Create 2M-page table
31 #define EFI_2M_PAGE_BITS_NUM 21
32 #define EFI_MAX_ENTRY_BITS_NUM 9
34 #define EFI_PAGE_SIZE_4K 0x1000
35 #define EFI_PAGE_SIZE_2M (1 << EFI_2M_PAGE_BITS_NUM)
38 #define MIN(a, b) ((a) < (b) ? (a) : (b))
40 #define ENTRY_NUM(x) ((UINTN)1 << (x))
50 EnableNullPointerProtection (
54 X64_PAGE_TABLE_ENTRY_4K
*PageTableEntry4KB
;
56 PageTableEntry4KB
= (X64_PAGE_TABLE_ENTRY_4K
*) (PageTable
+ gPageNum2M
* EFI_PAGE_SIZE_4K
);
58 // Fill in the Page Table entries
59 // Mark 0~4K as not present
61 PageTableEntry4KB
->Bits
.Present
= 0;
67 X64Create4KPageTables (
72 Create 4K-Page-Table for the low 2M memory.
73 This will change the previously created 2M-Page-Table-Entry.
78 X64_PAGE_DIRECTORY_ENTRY_4K
*PageDirectoryEntry4KB
;
79 X64_PAGE_TABLE_ENTRY_4K
*PageTableEntry4KB
;
82 // Page Table structure 4 level 4K.
84 // PageMapLevel4Entry : bits 47-39
85 // PageDirectoryPointerEntry : bits 38-30
86 // Page Table 4K : PageDirectoryEntry4K : bits 29-21
87 // PageTableEntry : bits 20-12
90 PageTableEntry4KB
= (X64_PAGE_TABLE_ENTRY_4K
*)(PageTable
+ gPageNum2M
* EFI_PAGE_SIZE_4K
);
92 PageDirectoryEntry4KB
= (X64_PAGE_DIRECTORY_ENTRY_4K
*) (PageTable
+ 2 * EFI_PAGE_SIZE_4K
);
93 PageDirectoryEntry4KB
->Uint64
= (UINT64
)(UINTN
)PageTableEntry4KB
;
94 PageDirectoryEntry4KB
->Bits
.ReadWrite
= 1;
95 PageDirectoryEntry4KB
->Bits
.Present
= 1;
96 PageDirectoryEntry4KB
->Bits
.MustBeZero
= 0;
98 for (PTEIndex
= 0, PageAddress
= 0;
99 PTEIndex
< ENTRY_NUM (EFI_MAX_ENTRY_BITS_NUM
);
100 PTEIndex
++, PageTableEntry4KB
++, PageAddress
+= EFI_PAGE_SIZE_4K
103 // Fill in the Page Table entries
105 PageTableEntry4KB
->Uint64
= (UINT64
)PageAddress
;
106 PageTableEntry4KB
->Bits
.ReadWrite
= 1;
107 PageTableEntry4KB
->Bits
.Present
= 1;
114 X64Create2MPageTables (
119 UINT8
*TempPageTable
;
123 X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*PageMapLevel4Entry
;
124 X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*PageDirectoryPointerEntry
;
125 X64_PAGE_TABLE_ENTRY_2M
*PageDirectoryEntry2MB
;
127 TempPageTable
= PageTable
;
131 // Page Table structure 3 level 2MB.
133 // PageMapLevel4Entry : bits 47-39
134 // PageDirectoryPointerEntry : bits 38-30
135 // Page Table 2MB : PageDirectoryEntry2M : bits 29-21
138 PageMapLevel4Entry
= (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*)TempPageTable
;
140 for (PML4Index
= 0; PML4Index
< ENTRY_NUM (gPML4BitsNum
); PML4Index
++, PageMapLevel4Entry
++) {
142 // Each PML4 entry points to a page of Page Directory Pointer entires.
144 TempPageTable
+= EFI_PAGE_SIZE_4K
;
145 PageDirectoryPointerEntry
= (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K
*)TempPageTable
;
150 PageMapLevel4Entry
->Uint64
= (UINT64
)(UINTN
)(TempPageTable
);
151 PageMapLevel4Entry
->Bits
.ReadWrite
= 1;
152 PageMapLevel4Entry
->Bits
.Present
= 1;
154 for (PDPTEIndex
= 0; PDPTEIndex
< ENTRY_NUM (gPDPTEBitsNum
); PDPTEIndex
++, PageDirectoryPointerEntry
++) {
156 // Each Directory Pointer entries points to a page of Page Directory entires.
158 TempPageTable
+= EFI_PAGE_SIZE_4K
;
159 PageDirectoryEntry2MB
= (X64_PAGE_TABLE_ENTRY_2M
*)TempPageTable
;
162 // Fill in a Page Directory Pointer Entries
164 PageDirectoryPointerEntry
->Uint64
= (UINT64
)(UINTN
)(TempPageTable
);
165 PageDirectoryPointerEntry
->Bits
.ReadWrite
= 1;
166 PageDirectoryPointerEntry
->Bits
.Present
= 1;
168 for (PDEIndex
= 0; PDEIndex
< ENTRY_NUM (gPDEBitsNum
); PDEIndex
++, PageDirectoryEntry2MB
++) {
170 // Fill in the Page Directory entries
172 PageDirectoryEntry2MB
->Uint64
= (UINT64
)PageAddress
;
173 PageDirectoryEntry2MB
->Bits
.ReadWrite
= 1;
174 PageDirectoryEntry2MB
->Bits
.Present
= 1;
175 PageDirectoryEntry2MB
->Bits
.MustBe1
= 1;
177 PageAddress
+= EFI_PAGE_SIZE_2M
;
188 UINT8 SizeOfMemorySpace
192 Generate pagetable below PageNumberTop,
193 and return the bottom address of pagetable for putting other things later.
196 VOID
*PageNumberBase
;
198 SizeOfMemorySpace
-= EFI_2M_PAGE_BITS_NUM
;
199 gPDEBitsNum
= (UINT8
) MIN (SizeOfMemorySpace
, EFI_MAX_ENTRY_BITS_NUM
);
200 SizeOfMemorySpace
= (UINT8
) (SizeOfMemorySpace
- gPDEBitsNum
);
201 gPDPTEBitsNum
= (UINT8
) MIN (SizeOfMemorySpace
, EFI_MAX_ENTRY_BITS_NUM
);
202 SizeOfMemorySpace
= (UINT8
) (SizeOfMemorySpace
- gPDPTEBitsNum
);
203 gPML4BitsNum
= SizeOfMemorySpace
;
204 if (gPML4BitsNum
> EFI_MAX_ENTRY_BITS_NUM
) {
211 // Entry: PML4 -> PDPTE -> PDE -> Page
214 // Occupy4KPage: 1 a a*b
217 // Entry: PTE -> Page
223 gPageNum2M
= 1 + ENTRY_NUM (gPML4BitsNum
) + ENTRY_NUM (gPML4BitsNum
+ gPDPTEBitsNum
);
227 PageNumberBase
= (VOID
*)((UINTN
)PageNumberTop
- (gPageNum2M
+ gPageNum4K
) * EFI_PAGE_SIZE_4K
);
228 ZeroMem (PageNumberBase
, (gPageNum2M
+ gPageNum4K
) * EFI_PAGE_SIZE_4K
);
230 X64Create2MPageTables (PageNumberBase
);
231 X64Create4KPageTables (PageNumberBase
);
233 // Not enable NULL Pointer Protection if using INTx call
235 // EnableNullPointerProtection (PageNumberBase);
237 return PageNumberBase
;