]> git.proxmox.com Git - mirror_edk2.git/blame - DuetPkg/DxeIpl/X64/Paging.c
BaseTools/CommonLib: drop definition of MAX_UINTN
[mirror_edk2.git] / DuetPkg / DxeIpl / X64 / Paging.c
CommitLineData
18b84857 1/** @file\r
ca162103 2\r
b1f700a8
HT
3Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>\r
4This program and the accompanying materials \r
ca162103 5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13 Paging.c\r
14\r
15Abstract:\r
16\r
17Revision History:\r
18\r
18b84857 19**/\r
ca162103 20\r
21#include "HobGeneration.h"\r
22#include "VirtualMemory.h"\r
23\r
24//\r
25// Create 2M-page table\r
26// PML4 (47:39)\r
27// PDPTE (38:30)\r
28// PDE (29:21)\r
29//\r
30\r
31#define EFI_2M_PAGE_BITS_NUM 21\r
32#define EFI_MAX_ENTRY_BITS_NUM 9\r
33\r
34#define EFI_PAGE_SIZE_4K 0x1000\r
35#define EFI_PAGE_SIZE_2M (1 << EFI_2M_PAGE_BITS_NUM)\r
36\r
37#ifndef MIN\r
38 #define MIN(a, b) ((a) < (b) ? (a) : (b))\r
39#endif\r
40#define ENTRY_NUM(x) ((UINTN)1 << (x))\r
41\r
42UINT8 gPML4BitsNum;\r
43UINT8 gPDPTEBitsNum;\r
44UINT8 gPDEBitsNum;\r
45\r
46UINTN gPageNum2M;\r
47UINTN gPageNum4K;\r
48\r
49VOID\r
50EnableNullPointerProtection (\r
51 UINT8 *PageTable\r
52 )\r
53{\r
54 X64_PAGE_TABLE_ENTRY_4K *PageTableEntry4KB;\r
55\r
56 PageTableEntry4KB = (X64_PAGE_TABLE_ENTRY_4K *) (PageTable + gPageNum2M * EFI_PAGE_SIZE_4K);\r
57 //\r
58 // Fill in the Page Table entries\r
59 // Mark 0~4K as not present\r
60 //\r
61 PageTableEntry4KB->Bits.Present = 0;\r
62\r
63 return ;\r
64}\r
65\r
66VOID\r
67X64Create4KPageTables (\r
68 UINT8 *PageTable\r
69 )\r
70/*++\r
71Routine Description:\r
72 Create 4K-Page-Table for the low 2M memory.\r
73 This will change the previously created 2M-Page-Table-Entry.\r
74--*/\r
75{\r
76 UINT64 PageAddress;\r
77 UINTN PTEIndex;\r
78 X64_PAGE_DIRECTORY_ENTRY_4K *PageDirectoryEntry4KB;\r
79 X64_PAGE_TABLE_ENTRY_4K *PageTableEntry4KB;\r
80\r
81 //\r
82 // Page Table structure 4 level 4K.\r
83 //\r
84 // PageMapLevel4Entry : bits 47-39\r
85 // PageDirectoryPointerEntry : bits 38-30\r
86 // Page Table 4K : PageDirectoryEntry4K : bits 29-21\r
87 // PageTableEntry : bits 20-12\r
88 //\r
89\r
90 PageTableEntry4KB = (X64_PAGE_TABLE_ENTRY_4K *)(PageTable + gPageNum2M * EFI_PAGE_SIZE_4K);\r
91\r
92 PageDirectoryEntry4KB = (X64_PAGE_DIRECTORY_ENTRY_4K *) (PageTable + 2 * EFI_PAGE_SIZE_4K);\r
93 PageDirectoryEntry4KB->Uint64 = (UINT64)(UINTN)PageTableEntry4KB;\r
94 PageDirectoryEntry4KB->Bits.ReadWrite = 1;\r
95 PageDirectoryEntry4KB->Bits.Present = 1;\r
96 PageDirectoryEntry4KB->Bits.MustBeZero = 0;\r
97\r
98 for (PTEIndex = 0, PageAddress = 0; \r
99 PTEIndex < ENTRY_NUM (EFI_MAX_ENTRY_BITS_NUM); \r
100 PTEIndex++, PageTableEntry4KB++, PageAddress += EFI_PAGE_SIZE_4K\r
101 ) {\r
102 //\r
103 // Fill in the Page Table entries\r
104 //\r
105 PageTableEntry4KB->Uint64 = (UINT64)PageAddress;\r
106 PageTableEntry4KB->Bits.ReadWrite = 1;\r
107 PageTableEntry4KB->Bits.Present = 1;\r
108 }\r
109\r
110 return ;\r
111}\r
112\r
113VOID\r
114X64Create2MPageTables (\r
115 UINT8 *PageTable\r
116 )\r
117{\r
118 UINT64 PageAddress;\r
119 UINT8 *TempPageTable;\r
120 UINTN PML4Index;\r
121 UINTN PDPTEIndex;\r
122 UINTN PDEIndex;\r
123 X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMapLevel4Entry;\r
124 X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageDirectoryPointerEntry;\r
125 X64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB;\r
126\r
127 TempPageTable = PageTable;\r
128 PageAddress = 0;\r
129\r
130 //\r
131 // Page Table structure 3 level 2MB.\r
132 //\r
133 // PageMapLevel4Entry : bits 47-39\r
134 // PageDirectoryPointerEntry : bits 38-30\r
135 // Page Table 2MB : PageDirectoryEntry2M : bits 29-21\r
136 //\r
137\r
138 PageMapLevel4Entry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)TempPageTable;\r
139\r
140 for (PML4Index = 0; PML4Index < ENTRY_NUM (gPML4BitsNum); PML4Index++, PageMapLevel4Entry++) {\r
141 //\r
142 // Each PML4 entry points to a page of Page Directory Pointer entires.\r
143 // \r
144 TempPageTable += EFI_PAGE_SIZE_4K;\r
145 PageDirectoryPointerEntry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)TempPageTable;\r
146\r
147 //\r
148 // Make a PML4 Entry\r
149 //\r
150 PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)(TempPageTable);\r
151 PageMapLevel4Entry->Bits.ReadWrite = 1;\r
152 PageMapLevel4Entry->Bits.Present = 1;\r
153\r
154 for (PDPTEIndex = 0; PDPTEIndex < ENTRY_NUM (gPDPTEBitsNum); PDPTEIndex++, PageDirectoryPointerEntry++) {\r
155 //\r
156 // Each Directory Pointer entries points to a page of Page Directory entires.\r
157 // \r
158 TempPageTable += EFI_PAGE_SIZE_4K;\r
159 PageDirectoryEntry2MB = (X64_PAGE_TABLE_ENTRY_2M *)TempPageTable;\r
160\r
161 //\r
162 // Fill in a Page Directory Pointer Entries\r
163 //\r
164 PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)(TempPageTable);\r
165 PageDirectoryPointerEntry->Bits.ReadWrite = 1;\r
166 PageDirectoryPointerEntry->Bits.Present = 1;\r
167\r
168 for (PDEIndex = 0; PDEIndex < ENTRY_NUM (gPDEBitsNum); PDEIndex++, PageDirectoryEntry2MB++) {\r
169 //\r
170 // Fill in the Page Directory entries\r
171 //\r
172 PageDirectoryEntry2MB->Uint64 = (UINT64)PageAddress;\r
173 PageDirectoryEntry2MB->Bits.ReadWrite = 1;\r
174 PageDirectoryEntry2MB->Bits.Present = 1;\r
175 PageDirectoryEntry2MB->Bits.MustBe1 = 1;\r
176\r
177 PageAddress += EFI_PAGE_SIZE_2M;\r
178 }\r
179 }\r
180 }\r
181\r
182 return ;\r
183}\r
184\r
185VOID *\r
186PreparePageTable (\r
187 VOID *PageNumberTop,\r
188 UINT8 SizeOfMemorySpace\r
189 )\r
190/*++\r
191Description:\r
192 Generate pagetable below PageNumberTop, \r
193 and return the bottom address of pagetable for putting other things later.\r
194--*/\r
195{\r
196 VOID *PageNumberBase;\r
197\r
198 SizeOfMemorySpace -= EFI_2M_PAGE_BITS_NUM;\r
3a0a1473 199 gPDEBitsNum = (UINT8) MIN (SizeOfMemorySpace, EFI_MAX_ENTRY_BITS_NUM);\r
200 SizeOfMemorySpace = (UINT8) (SizeOfMemorySpace - gPDEBitsNum);\r
201 gPDPTEBitsNum = (UINT8) MIN (SizeOfMemorySpace, EFI_MAX_ENTRY_BITS_NUM);\r
202 SizeOfMemorySpace = (UINT8) (SizeOfMemorySpace - gPDPTEBitsNum);\r
ca162103 203 gPML4BitsNum = SizeOfMemorySpace;\r
204 if (gPML4BitsNum > EFI_MAX_ENTRY_BITS_NUM) {\r
205 return NULL;\r
206 }\r
207\r
208 //\r
209 // Suppose we have:\r
210 // 2MPage:\r
211 // Entry: PML4 -> PDPTE -> PDE -> Page\r
212 // EntryNum: a b c\r
213 // then\r
214 // Occupy4KPage: 1 a a*b\r
215 // \r
216 // 2M 4KPage:\r
217 // Entry: PTE -> Page\r
218 // EntryNum: 512\r
219 // then\r
220 // Occupy4KPage: 1\r
221 // \r
222\r
223 gPageNum2M = 1 + ENTRY_NUM (gPML4BitsNum) + ENTRY_NUM (gPML4BitsNum + gPDPTEBitsNum);\r
224 gPageNum4K = 1;\r
225\r
226\r
227 PageNumberBase = (VOID *)((UINTN)PageNumberTop - (gPageNum2M + gPageNum4K) * EFI_PAGE_SIZE_4K);\r
228 ZeroMem (PageNumberBase, (gPageNum2M + gPageNum4K) * EFI_PAGE_SIZE_4K);\r
229\r
230 X64Create2MPageTables (PageNumberBase);\r
231 X64Create4KPageTables (PageNumberBase);\r
232 //\r
233 // Not enable NULL Pointer Protection if using INTx call\r
234 //\r
235// EnableNullPointerProtection (PageNumberBase);\r
236\r
237 return PageNumberBase;\r
238}\r