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