2 * COPYRIGHT: See COPYING.ARM in the top level directory
3 * PROJECT: ReactOS UEFI Boot Library
4 * FILE: boot/environ/lib/mm/i386/mmx86.c
5 * PURPOSE: Boot Library Memory Manager x86-Specific Code
6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
14 /* DATA VARIABLES ************************************************************/
16 ULONG_PTR MmArchKsegBase
;
17 ULONG_PTR MmArchKsegBias
;
18 ULONG MmArchLargePageSize
;
19 BL_ADDRESS_RANGE MmArchKsegAddressRange
;
20 ULONG_PTR MmArchTopOfApplicationAddressSpace
;
21 PHYSICAL_ADDRESS Mmx86SelfMapBase
;
22 ULONG MmDeferredMappingCount
;
24 PVOID MmArchReferencePage
;
26 ULONG MmArchReferencePageSize
;
34 (*PBL_MM_RELOCATE_SELF_MAP
) (
39 (*PBL_MM_MOVE_VIRTUAL_ADDRESS_RANGE
) (
40 _In_ PVOID DestinationAddress
,
41 _In_ PVOID SourceAddress
,
46 (*PBL_MM_ZERO_VIRTUAL_ADDRESS_RANGE
) (
47 _In_ PVOID DestinationAddress
,
52 (*PBL_MM_DESTROY_SELF_MAP
) (
57 (*PBL_MM_FLUSH_TLB_ENTRY
) (
58 _In_ PVOID VirtualAddress
67 (*PBL_MM_UNMAP_VIRTUAL_ADDRESS
) (
68 _In_ PVOID VirtualAddress
,
73 (*PBL_MM_REMAP_VIRTUAL_ADDRESS
) (
74 _In_ PPHYSICAL_ADDRESS PhysicalAddress
,
75 _Out_ PVOID VirtualAddress
,
77 _In_ ULONG CacheAttributes
81 (*PBL_MM_MAP_PHYSICAL_ADDRESS
) (
82 _In_ PPHYSICAL_ADDRESS PhysicalAddress
,
83 _Out_ PVOID VirtualAddress
,
85 _In_ ULONG CacheAttributes
89 (*PBL_MM_TRANSLATE_VIRTUAL_ADDRESS
) (
90 _In_ PVOID VirtualAddress
,
91 _Out_ PPHYSICAL_ADDRESS PhysicalAddress
,
92 _Out_opt_ PULONG CacheAttributes
95 PBL_MM_TRANSLATE_VIRTUAL_ADDRESS Mmx86TranslateVirtualAddress
;
96 PBL_MM_MAP_PHYSICAL_ADDRESS Mmx86MapPhysicalAddress
;
97 PBL_MM_REMAP_VIRTUAL_ADDRESS Mmx86RemapVirtualAddress
;
98 PBL_MM_UNMAP_VIRTUAL_ADDRESS Mmx86UnmapVirtualAddress
;
99 PBL_MM_FLUSH_TLB Mmx86FlushTlb
;
100 PBL_MM_FLUSH_TLB_ENTRY Mmx86FlushTlbEntry
;
101 PBL_MM_DESTROY_SELF_MAP Mmx86DestroySelfMap
;
103 PBL_MM_RELOCATE_SELF_MAP BlMmRelocateSelfMap
;
104 PBL_MM_FLUSH_TLB BlMmFlushTlb
;
105 PBL_MM_MOVE_VIRTUAL_ADDRESS_RANGE BlMmMoveVirtualAddressRange
;
106 PBL_MM_ZERO_VIRTUAL_ADDRESS_RANGE BlMmZeroVirtualAddressRange
;
108 PBL_MM_FLUSH_TLB Mmx86FlushTlb
;
110 #define PTE_BASE (PVOID)0xC0000000
112 /* FUNCTIONS *****************************************************************/
124 MmDefRelocateSelfMap (
128 if (MmPteBase
!= PTE_BASE
)
130 EfiPrintf(L
"Supposed to relocate CR3\r\n");
135 MmDefMoveVirtualAddressRange (
136 _In_ PVOID DestinationAddress
,
137 _In_ PVOID SourceAddress
,
141 EfiPrintf(L
"Supposed to move shit\r\n");
142 return STATUS_NOT_IMPLEMENTED
;
146 MmDefZeroVirtualAddressRange (
147 _In_ PVOID DestinationAddress
,
151 EfiPrintf(L
"Supposed to zero shit\r\n");
152 return STATUS_NOT_IMPLEMENTED
;
156 Mmx86pMapMemoryRegions (
158 _In_ PBL_MEMORY_DATA MemoryData
163 /* In phase 1 we don't initialize deferred mappings*/
170 /* Don't do anything if there's nothing to initialize */
171 if (!MmDeferredMappingCount
)
173 return STATUS_SUCCESS
;
181 EfiPrintf(L
"Deferred todo\r\n");
184 EfiPrintf(L
"Phase 1 TODO\r\n");
185 return STATUS_NOT_IMPLEMENTED
;
189 MmArchTranslateVirtualAddress (
190 _In_ PVOID VirtualAddress
,
191 _Out_opt_ PPHYSICAL_ADDRESS PhysicalAddress
,
192 _Out_opt_ PULONG CachingFlags
195 PBL_MEMORY_DESCRIPTOR Descriptor
;
197 /* Check if paging is on */
198 if ((CurrentExecutionContext
) &&
199 (CurrentExecutionContext
->ContextFlags
& BL_CONTEXT_PAGING_ON
))
201 /* Yes -- we have to translate this from virtual */
202 return Mmx86TranslateVirtualAddress(VirtualAddress
,
207 /* Look in all descriptors except truncated and firmware ones */
208 Descriptor
= MmMdFindDescriptor(BL_MM_INCLUDE_NO_FIRMWARE_MEMORY
&
209 ~BL_MM_INCLUDE_TRUNCATED_MEMORY
,
210 BL_MM_REMOVE_PHYSICAL_REGION_FLAG
,
211 (ULONG_PTR
)VirtualAddress
>> PAGE_SHIFT
);
213 /* Return the virtual address as the physical address */
216 PhysicalAddress
->HighPart
= 0;
217 PhysicalAddress
->LowPart
= (ULONG_PTR
)VirtualAddress
;
220 /* There's no caching on physical memory */
226 /* Success is if we found a descriptor */
227 return Descriptor
!= NULL
;
231 MmDefpDestroySelfMap (
235 EfiPrintf(L
"No destroy\r\n");
239 MmDefpFlushTlbEntry (
240 _In_ PVOID VirtualAddress
244 __invlpg(VirtualAddress
);
253 __writecr3(__readcr3());
257 MmDefpUnmapVirtualAddress (
258 _In_ PVOID VirtualAddress
,
262 EfiPrintf(L
"No unmap\r\n");
263 return STATUS_NOT_IMPLEMENTED
;
267 MmDefpRemapVirtualAddress (
268 _In_ PPHYSICAL_ADDRESS PhysicalAddress
,
269 _Out_ PVOID VirtualAddress
,
271 _In_ ULONG CacheAttributes
274 EfiPrintf(L
"No remap\r\n");
275 return STATUS_NOT_IMPLEMENTED
;
279 MmDefpMapPhysicalAddress (
280 _In_ PPHYSICAL_ADDRESS PhysicalAddress
,
281 _Out_ PVOID VirtualAddress
,
283 _In_ ULONG CacheAttributes
286 EfiPrintf(L
"No map\r\n");
287 return STATUS_NOT_IMPLEMENTED
;
291 MmDefpTranslateVirtualAddress (
292 _In_ PVOID VirtualAddress
,
293 _Out_ PPHYSICAL_ADDRESS PhysicalAddress
,
294 _Out_opt_ PULONG CacheAttributes
297 EfiPrintf(L
"No translate\r\n");
302 MmDefInitializeTranslation (
303 _In_ PBL_MEMORY_DATA MemoryData
,
304 _In_ BL_TRANSLATION_TYPE TranslationType
308 PHYSICAL_ADDRESS PhysicalAddress
;
310 /* Set the global function pointers for memory translation */
311 Mmx86TranslateVirtualAddress
= MmDefpTranslateVirtualAddress
;
312 Mmx86MapPhysicalAddress
= MmDefpMapPhysicalAddress
;
313 Mmx86UnmapVirtualAddress
= MmDefpUnmapVirtualAddress
;
314 Mmx86RemapVirtualAddress
= MmDefpRemapVirtualAddress
;
315 Mmx86FlushTlb
= MmDefpFlushTlb
;
316 Mmx86FlushTlbEntry
= MmDefpFlushTlbEntry
;
317 Mmx86DestroySelfMap
= MmDefpDestroySelfMap
;
319 /* Check what mode we're currently in */
320 if (TranslationType
== BlVirtual
)
322 EfiPrintf(L
"Virtual->Virtual not yet supported\r\n");
323 return STATUS_NOT_IMPLEMENTED
;
325 else if (TranslationType
!= BlNone
)
327 /* Not even Windows supports PAE->Virtual downgrade */
328 return STATUS_NOT_IMPLEMENTED
;
331 /* The None->Virtual case */
333 Mmx86SelfMapBase
.QuadPart
= 0;
334 MmArchReferencePage
= NULL
;
336 /* Truncate all memory above 4GB so that we don't use it @TODO: FIXME */
337 EfiPrintf(L
"Warning: not truncating > 4GB memory. Don't boot with more than 4GB of RAM!\r\n");
338 //Status = MmPaTruncateMemory(0x100000);
339 Status
= STATUS_SUCCESS
;
340 if (!NT_SUCCESS(Status
))
345 /* Allocate a page directory */
346 Status
= MmPapAllocatePhysicalPagesInRange(&PhysicalAddress
,
347 BlLoaderPageDirectory
,
351 &MmMdlUnmappedAllocated
,
354 if (!NT_SUCCESS(Status
))
359 /* Zero out the page directory */
360 MmPdpt
= (PVOID
)PhysicalAddress
.LowPart
;
361 RtlZeroMemory(MmPdpt
, PAGE_SIZE
);
363 /* Set the page size */
364 MmArchReferencePageSize
= PAGE_SIZE
;
366 /* Allocate the self-map page */
367 Status
= MmPapAllocatePhysicalPagesInRange(&PhysicalAddress
,
368 BlLoaderReferencePage
,
372 &MmMdlUnmappedAllocated
,
375 if (!NT_SUCCESS(Status
))
380 /* Set the reference page */
381 MmArchReferencePage
= (PVOID
)PhysicalAddress
.LowPart
;
384 RtlZeroMemory(MmArchReferencePage
, MmArchReferencePageSize
);
386 /* Allocate 4MB worth of self-map pages */
387 Status
= MmPaReserveSelfMapPages(&Mmx86SelfMapBase
,
388 (4 * 1024 * 1024) >> PAGE_SHIFT
,
389 (4 * 1024 * 1024) >> PAGE_SHIFT
);
390 if (!NT_SUCCESS(Status
))
396 RtlZeroMemory((PVOID
)Mmx86SelfMapBase
.LowPart
, 4 * 1024 * 1024);
398 EfiPrintf(L
"PDPT at 0x%p Reference Page at 0x%p Self-map at 0x%p\r\n",
399 MmPdpt
, MmArchReferencePage
, Mmx86SelfMapBase
.LowPart
);
400 Status
= STATUS_NOT_IMPLEMENTED
;
402 //MmPteBase = Mmx86SelfMapBase.LowPart & 0xFFC00000;
405 /* Free reference page if we allocated it */
406 if (MmArchReferencePage
)
408 PhysicalAddress
.QuadPart
= (ULONG_PTR
)MmArchReferencePage
;
409 BlMmFreePhysicalPages(PhysicalAddress
);
412 /* Free page directory if we allocated it */
415 PhysicalAddress
.QuadPart
= (ULONG_PTR
)MmPdpt
;
416 BlMmFreePhysicalPages(PhysicalAddress
);
419 /* Free the self map if we allocated it */
420 if (Mmx86SelfMapBase
.QuadPart
)
422 MmPaReleaseSelfMapPages(Mmx86SelfMapBase
);
432 _In_ PBL_MEMORY_DATA MemoryData
,
433 _In_ BL_TRANSLATION_TYPE TranslationType
,
434 _In_ BL_TRANSLATION_TYPE RequestedTranslationType
438 ULONGLONG IncreaseUserVa
, PerfCounter
, CpuRandom
;
441 /* For phase 2, just map deferred regions */
444 return Mmx86pMapMemoryRegions(2, MemoryData
);
447 /* What translation type are we switching to? */
448 switch (RequestedTranslationType
)
450 /* Physical memory */
453 /* Initialize everything to default/null values */
454 MmArchLargePageSize
= 1;
457 MmArchKsegAddressRange
.Minimum
= 0;
458 MmArchKsegAddressRange
.Maximum
= (ULONGLONG
)~0;
459 MmArchTopOfApplicationAddressSpace
= 0;
460 Mmx86SelfMapBase
.QuadPart
= 0;
462 /* Set stub functions */
463 BlMmRelocateSelfMap
= MmArchNullFunction
;
464 BlMmFlushTlb
= MmArchNullFunction
;
467 Status
= STATUS_SUCCESS
;
472 /* Set the large page size to 1024 pages (4MB) */
473 MmArchLargePageSize
= (4 * 1024 * 1024) / PAGE_SIZE
;
475 /* Check if /USERVA option was used */
476 Status
= BlGetBootOptionInteger(BlpApplicationEntry
.BcdData
,
477 BcdOSLoaderInteger_IncreaseUserVa
,
479 if (NT_SUCCESS(Status
) && (IncreaseUserVa
))
481 /* Yes -- load the kernel at 0xE0000000 instead */
482 MmArchKsegBase
= 0xE0000000;
486 /* Nope, load at the standard 2GB split */
487 MmArchKsegBase
= 0x80000000;
490 /* Check if CPUID 01h is supported */
492 if (BlArchIsCpuIdFunctionSupported(1))
495 BlArchCpuId(1, 0, CpuInfo
);
497 /* Check if RDRAND is supported */
498 if (CpuInfo
[2] & 0x40000000)
500 EfiPrintf(L
"Your CPU can do RDRAND! Good for you!\r\n");
506 PerfCounter
= BlArchGetPerformanceCounter();
508 _rotl16(PerfCounter
, 5);
510 /* Set the address range */
511 MmArchKsegAddressRange
.Minimum
= 0;
512 MmArchKsegAddressRange
.Maximum
= (ULONGLONG
)~0;
514 /* Set the KASLR bias */
515 MmArchKsegBias
= ((PerfCounter
^ CpuRandom
) & 0xFFF) << 12;
517 MmArchKsegBase
+= MmArchKsegBias
;
519 /* Set the kernel range */
520 MmArchKsegAddressRange
.Minimum
= MmArchKsegBase
;
521 MmArchKsegAddressRange
.Maximum
= (ULONGLONG
)~0;
523 /* Set the boot application top maximum */
524 MmArchTopOfApplicationAddressSpace
= 0x70000000;
526 /* Initialize virtual address space translation */
527 Status
= MmDefInitializeTranslation(MemoryData
, TranslationType
);
528 if (NT_SUCCESS(Status
))
530 /* Set stub functions */
531 BlMmRelocateSelfMap
= MmDefRelocateSelfMap
;
532 BlMmFlushTlb
= Mmx86FlushTlb
;
533 BlMmMoveVirtualAddressRange
= MmDefMoveVirtualAddressRange
;
534 BlMmZeroVirtualAddressRange
= MmDefZeroVirtualAddressRange
;
540 Status
= STATUS_NOT_SUPPORTED
;
544 Status
= STATUS_INVALID_PARAMETER
;