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