1 /** @file
2   x64 Long Mode Virtual Memory Management Definitions
3 
4   References:
5     1) IA-32 Intel(R) Architecture Software Developer's Manual Volume 1:Basic Architecture, Intel
6     2) IA-32 Intel(R) Architecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel
7     3) IA-32 Intel(R) Architecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel
8     4) AMD64 Architecture Programmer's Manual Volume 2: System Programming
9 
10 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
11 Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
12 
13 SPDX-License-Identifier: BSD-2-Clause-Patent
14 
15 **/
16 #ifndef _VIRTUAL_MEMORY_H_
17 #define _VIRTUAL_MEMORY_H_
18 
19 
20 #define SYS_CODE64_SEL 0x38
21 
22 
23 #pragma pack(1)
24 
25 typedef union {
26   struct {
27     UINT32  LimitLow    : 16;
28     UINT32  BaseLow     : 16;
29     UINT32  BaseMid     : 8;
30     UINT32  Type        : 4;
31     UINT32  System      : 1;
32     UINT32  Dpl         : 2;
33     UINT32  Present     : 1;
34     UINT32  LimitHigh   : 4;
35     UINT32  Software    : 1;
36     UINT32  Reserved    : 1;
37     UINT32  DefaultSize : 1;
38     UINT32  Granularity : 1;
39     UINT32  BaseHigh    : 8;
40   } Bits;
41   UINT64  Uint64;
42 } IA32_GDT;
43 
44 typedef struct {
45   IA32_IDT_GATE_DESCRIPTOR  Ia32IdtEntry;
46   UINT32                    Offset32To63;
47   UINT32                    Reserved;
48 } X64_IDT_GATE_DESCRIPTOR;
49 
50 //
51 // Page-Map Level-4 Offset (PML4) and
52 // Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB
53 //
54 
55 typedef union {
56   struct {
57     UINT64  Present:1;                // 0 = Not present in memory, 1 = Present in memory
58     UINT64  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write
59     UINT64  UserSupervisor:1;         // 0 = Supervisor, 1=User
60     UINT64  WriteThrough:1;           // 0 = Write-Back caching, 1=Write-Through caching
61     UINT64  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached
62     UINT64  Accessed:1;               // 0 = Not accessed, 1 = Accessed (set by CPU)
63     UINT64  Reserved:1;               // Reserved
64     UINT64  MustBeZero:2;             // Must Be Zero
65     UINT64  Available:3;              // Available for use by system software
66     UINT64  PageTableBaseAddress:40;  // Page Table Base Address
67     UINT64  AvabilableHigh:11;        // Available for use by system software
68     UINT64  Nx:1;                     // No Execute bit
69   } Bits;
70   UINT64    Uint64;
71 } PAGE_MAP_AND_DIRECTORY_POINTER;
72 
73 //
74 // Page Table Entry 4KB
75 //
76 typedef union {
77   struct {
78     UINT64  Present:1;                // 0 = Not present in memory, 1 = Present in memory
79     UINT64  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write
80     UINT64  UserSupervisor:1;         // 0 = Supervisor, 1=User
81     UINT64  WriteThrough:1;           // 0 = Write-Back caching, 1=Write-Through caching
82     UINT64  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached
83     UINT64  Accessed:1;               // 0 = Not accessed, 1 = Accessed (set by CPU)
84     UINT64  Dirty:1;                  // 0 = Not Dirty, 1 = written by processor on access to page
85     UINT64  PAT:1;                    //
86     UINT64  Global:1;                 // 0 = Not global page, 1 = global page TLB not cleared on CR3 write
87     UINT64  Available:3;              // Available for use by system software
88     UINT64  PageTableBaseAddress:40;  // Page Table Base Address
89     UINT64  AvabilableHigh:11;        // Available for use by system software
90     UINT64  Nx:1;                     // 0 = Execute Code, 1 = No Code Execution
91   } Bits;
92   UINT64    Uint64;
93 } PAGE_TABLE_4K_ENTRY;
94 
95 //
96 // Page Table Entry 2MB
97 //
98 typedef union {
99   struct {
100     UINT64  Present:1;                // 0 = Not present in memory, 1 = Present in memory
101     UINT64  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write
102     UINT64  UserSupervisor:1;         // 0 = Supervisor, 1=User
103     UINT64  WriteThrough:1;           // 0 = Write-Back caching, 1=Write-Through caching
104     UINT64  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached
105     UINT64  Accessed:1;               // 0 = Not accessed, 1 = Accessed (set by CPU)
106     UINT64  Dirty:1;                  // 0 = Not Dirty, 1 = written by processor on access to page
107     UINT64  MustBe1:1;                // Must be 1
108     UINT64  Global:1;                 // 0 = Not global page, 1 = global page TLB not cleared on CR3 write
109     UINT64  Available:3;              // Available for use by system software
110     UINT64  PAT:1;                    //
111     UINT64  MustBeZero:8;             // Must be zero;
112     UINT64  PageTableBaseAddress:31;  // Page Table Base Address
113     UINT64  AvabilableHigh:11;        // Available for use by system software
114     UINT64  Nx:1;                     // 0 = Execute Code, 1 = No Code Execution
115   } Bits;
116   UINT64    Uint64;
117 } PAGE_TABLE_ENTRY;
118 
119 //
120 // Page Table Entry 1GB
121 //
122 typedef union {
123   struct {
124     UINT64  Present:1;                // 0 = Not present in memory, 1 = Present in memory
125     UINT64  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write
126     UINT64  UserSupervisor:1;         // 0 = Supervisor, 1=User
127     UINT64  WriteThrough:1;           // 0 = Write-Back caching, 1=Write-Through caching
128     UINT64  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached
129     UINT64  Accessed:1;               // 0 = Not accessed, 1 = Accessed (set by CPU)
130     UINT64  Dirty:1;                  // 0 = Not Dirty, 1 = written by processor on access to page
131     UINT64  MustBe1:1;                // Must be 1
132     UINT64  Global:1;                 // 0 = Not global page, 1 = global page TLB not cleared on CR3 write
133     UINT64  Available:3;              // Available for use by system software
134     UINT64  PAT:1;                    //
135     UINT64  MustBeZero:17;            // Must be zero;
136     UINT64  PageTableBaseAddress:22;  // Page Table Base Address
137     UINT64  AvabilableHigh:11;        // Available for use by system software
138     UINT64  Nx:1;                     // 0 = Execute Code, 1 = No Code Execution
139   } Bits;
140   UINT64    Uint64;
141 } PAGE_TABLE_1G_ENTRY;
142 
143 #pragma pack()
144 
145 #define CR0_WP                      BIT16
146 
147 #define IA32_PG_P                   BIT0
148 #define IA32_PG_RW                  BIT1
149 #define IA32_PG_PS                  BIT7
150 
151 #define PAGING_PAE_INDEX_MASK       0x1FF
152 
153 #define PAGING_4K_ADDRESS_MASK_64   0x000FFFFFFFFFF000ull
154 #define PAGING_2M_ADDRESS_MASK_64   0x000FFFFFFFE00000ull
155 #define PAGING_1G_ADDRESS_MASK_64   0x000FFFFFC0000000ull
156 
157 #define PAGING_L1_ADDRESS_SHIFT     12
158 #define PAGING_L2_ADDRESS_SHIFT     21
159 #define PAGING_L3_ADDRESS_SHIFT     30
160 #define PAGING_L4_ADDRESS_SHIFT     39
161 
162 #define PAGING_PML4E_NUMBER         4
163 
164 #define PAGE_TABLE_POOL_ALIGNMENT   BASE_2MB
165 #define PAGE_TABLE_POOL_UNIT_SIZE   SIZE_2MB
166 #define PAGE_TABLE_POOL_UNIT_PAGES  EFI_SIZE_TO_PAGES (PAGE_TABLE_POOL_UNIT_SIZE)
167 #define PAGE_TABLE_POOL_ALIGN_MASK  \
168   (~(EFI_PHYSICAL_ADDRESS)(PAGE_TABLE_POOL_ALIGNMENT - 1))
169 
170 typedef struct {
171   VOID            *NextPool;
172   UINTN           Offset;
173   UINTN           FreePages;
174 } PAGE_TABLE_POOL;
175 
176 /**
177   Check if Execute Disable Bit (IA32_EFER.NXE) should be enabled or not.
178 
179   @retval TRUE    IA32_EFER.NXE should be enabled.
180   @retval FALSE   IA32_EFER.NXE should not be enabled.
181 
182 **/
183 BOOLEAN
184 IsEnableNonExecNeeded (
185   VOID
186   );
187 
188 /**
189   Enable Execute Disable Bit.
190 
191 **/
192 VOID
193 EnableExecuteDisableBit (
194   VOID
195   );
196 
197 /**
198   Split 2M page to 4K.
199 
200   @param[in]      PhysicalAddress       Start physical address the 2M page covered.
201   @param[in, out] PageEntry2M           Pointer to 2M page entry.
202   @param[in]      StackBase             Stack base address.
203   @param[in]      StackSize             Stack size.
204   @param[in]      GhcbBase              GHCB page area base address.
205   @param[in]      GhcbSize              GHCB page area size.
206 
207 **/
208 VOID
209 Split2MPageTo4K (
210   IN EFI_PHYSICAL_ADDRESS               PhysicalAddress,
211   IN OUT UINT64                         *PageEntry2M,
212   IN EFI_PHYSICAL_ADDRESS               StackBase,
213   IN UINTN                              StackSize,
214   IN EFI_PHYSICAL_ADDRESS               GhcbBase,
215   IN UINTN                              GhcbSize
216   );
217 
218 /**
219   Allocates and fills in the Page Directory and Page Table Entries to
220   establish a 1:1 Virtual to Physical mapping.
221 
222   @param[in] StackBase  Stack base address.
223   @param[in] StackSize  Stack size.
224   @param[in] GhcbBase   GHCB page area base address.
225   @param[in] GhcbSize   GHCB page area size.
226 
227   @return The address of 4 level page map.
228 
229 **/
230 UINTN
231 CreateIdentityMappingPageTables (
232   IN EFI_PHYSICAL_ADDRESS   StackBase,
233   IN UINTN                  StackSize,
234   IN EFI_PHYSICAL_ADDRESS   GhcbBase,
235   IN UINTN                  GhcbkSize
236   );
237 
238 
239 /**
240 
241   Fix up the vector number in the vector code.
242 
243   @param VectorBase   Base address of the vector handler.
244   @param VectorNum    Index of vector.
245 
246 **/
247 VOID
248 EFIAPI
249 AsmVectorFixup (
250   VOID    *VectorBase,
251   UINT8   VectorNum
252   );
253 
254 
255 /**
256 
257   Get the information of vector template.
258 
259   @param TemplateBase   Base address of the template code.
260 
261   @return               Size of the Template code.
262 
263 **/
264 UINTN
265 EFIAPI
266 AsmGetVectorTemplatInfo (
267   OUT   VOID  **TemplateBase
268   );
269 
270 /**
271   Clear legacy memory located at the first 4K-page.
272 
273   This function traverses the whole HOB list to check if memory from 0 to 4095
274   exists and has not been allocated, and then clear it if so.
275 
276   @param HobStart         The start of HobList passed to DxeCore.
277 
278 **/
279 VOID
280 ClearFirst4KPage (
281   IN  VOID *HobStart
282   );
283 
284 /**
285   Return configure status of NULL pointer detection feature.
286 
287   @return TRUE   NULL pointer detection feature is enabled
288   @return FALSE  NULL pointer detection feature is disabled
289 **/
290 BOOLEAN
291 IsNullDetectionEnabled (
292   VOID
293   );
294 
295 /**
296   Prevent the memory pages used for page table from been overwritten.
297 
298   @param[in] PageTableBase    Base address of page table (CR3).
299   @param[in] Level4Paging     Level 4 paging flag.
300 
301 **/
302 VOID
303 EnablePageTableProtection (
304   IN  UINTN     PageTableBase,
305   IN  BOOLEAN   Level4Paging
306   );
307 
308 /**
309   This API provides a way to allocate memory for page table.
310 
311   This API can be called more than once to allocate memory for page tables.
312 
313   Allocates the number of 4KB pages and returns a pointer to the allocated
314   buffer. The buffer returned is aligned on a 4KB boundary.
315 
316   If Pages is 0, then NULL is returned.
317   If there is not enough memory remaining to satisfy the request, then NULL is
318   returned.
319 
320   @param  Pages                 The number of 4 KB pages to allocate.
321 
322   @return A pointer to the allocated buffer or NULL if allocation fails.
323 
324 **/
325 VOID *
326 AllocatePageTableMemory (
327   IN UINTN           Pages
328   );
329 
330 #endif
331