]>
Commit | Line | Data |
---|---|---|
18b84857 | 1 | /** @file\r |
ca162103 | 2 | \r |
3 | Copyright (c) 2006 - 2007, Intel Corporation \r | |
4 | All rights reserved. This program and the accompanying materials \r | |
5 | are licensed and made available under the terms and conditions of the BSD License \r | |
6 | which accompanies this distribution. The full text of the license may be found at \r | |
7 | http://opensource.org/licenses/bsd-license.php \r | |
8 | \r | |
9 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r | |
10 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r | |
11 | \r | |
12 | Module Name:\r | |
13 | Paging.c\r | |
14 | \r | |
15 | Abstract:\r | |
16 | \r | |
17 | Revision 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 | |
42 | UINT8 gPML4BitsNum;\r | |
43 | UINT8 gPDPTEBitsNum;\r | |
44 | UINT8 gPDEBitsNum;\r | |
45 | \r | |
46 | UINTN gPageNum2M;\r | |
47 | UINTN gPageNum4K;\r | |
48 | \r | |
49 | VOID\r | |
50 | EnableNullPointerProtection (\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 | |
66 | VOID\r | |
67 | X64Create4KPageTables (\r | |
68 | UINT8 *PageTable\r | |
69 | )\r | |
70 | /*++\r | |
71 | Routine 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 | |
113 | VOID\r | |
114 | X64Create2MPageTables (\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 | |
185 | VOID *\r | |
186 | PreparePageTable (\r | |
187 | VOID *PageNumberTop,\r | |
188 | UINT8 SizeOfMemorySpace\r | |
189 | )\r | |
190 | /*++\r | |
191 | Description:\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 |