2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/mm/amd64/init.c
5 * PURPOSE: Memory Manager Initialization for amd64
7 * PROGRAMMERS: Timo kreuzer (timo.kreuzer@reactos.org)
8 * ReactOS Portable Systems Group
11 /* INCLUDES ***************************************************************/
17 #include "../ARM3/miarm.h"
19 extern PMMPTE MmDebugPte
;
21 /* GLOBALS *****************************************************************/
23 ULONG64 MmUserProbeAddress
= 0x7FFFFFF0000ULL
;
24 PVOID MmHighestUserAddress
= (PVOID
)0x7FFFFFEFFFFULL
;
25 PVOID MmSystemRangeStart
= (PVOID
)0xFFFF080000000000ULL
;
27 /* Size of session view, pool, and image */
28 ULONG64 MmSessionSize
= MI_SESSION_SIZE
;
29 ULONG64 MmSessionViewSize
= MI_SESSION_VIEW_SIZE
;
30 ULONG64 MmSessionPoolSize
= MI_SESSION_POOL_SIZE
;
31 ULONG64 MmSessionImageSize
= MI_SESSION_IMAGE_SIZE
;
33 /* Session space addresses */
34 PVOID MiSessionSpaceEnd
= MI_SESSION_SPACE_END
; // FFFFF98000000000
35 PVOID MiSessionImageEnd
; // FFFFF98000000000 = MiSessionSpaceEnd
36 PVOID MiSessionImageStart
; // ?FFFFF97FFF000000 = MiSessionImageEnd - MmSessionImageSize
37 PVOID MiSessionViewEnd
; // FFFFF97FFF000000
38 PVOID MiSessionViewStart
; // = MiSessionViewEnd - MmSessionViewSize
39 PVOID MiSessionPoolEnd
; // = MiSessionViewStart
40 PVOID MiSessionPoolStart
; // FFFFF90000000000 = MiSessionPoolEnd - MmSessionPoolSize
41 PVOID MmSessionBase
; // FFFFF90000000000 = MiSessionPoolStart
44 ULONG64 MmSystemViewSize
= MI_SYSTEM_VIEW_SIZE
;
45 PVOID MiSystemViewStart
;
47 ULONG64 MmMinimumNonPagedPoolSize
= 256 * 1024;
48 ULONG64 MmSizeOfNonPagedPoolInBytes
;
49 ULONG64 MmMaximumNonPagedPoolInBytes
;
50 ULONG64 MmMaximumNonPagedPoolPercent
;
51 ULONG64 MmMinAdditionNonPagedPoolPerMb
= 32 * 1024;
52 ULONG64 MmMaxAdditionNonPagedPoolPerMb
= 400 * 1024;
53 ULONG64 MmDefaultMaximumNonPagedPool
= 1024 * 1024;
54 PVOID MmNonPagedSystemStart
;
55 PVOID MmNonPagedPoolStart
;
56 PVOID MmNonPagedPoolExpansionStart
;
57 PVOID MmNonPagedPoolEnd
= MI_NONPAGED_POOL_END
;
59 ULONG64 MmSizeOfPagedPoolInBytes
= MI_MIN_INIT_PAGED_POOLSIZE
;
60 PVOID MmPagedPoolStart
= MI_PAGED_POOL_START
;
64 ULONG64 MmBootImageSize
;
65 PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock
;
66 RTL_BITMAP MiPfnBitMap
;
67 ULONG MmNumberOfPhysicalPages
, MmHighestPhysicalPage
, MmLowestPhysicalPage
= -1; // FIXME: ULONG64
68 ULONG64 MmNumberOfSystemPtes
;
69 PMMPTE MmSystemPagePtes
;
70 ULONG64 MxPfnAllocation
;
71 ULONG64 MxPfnSizeInBytes
;
73 PVOID MmSystemCacheStart
;
74 PVOID MmSystemCacheEnd
;
75 MMSUPPORT MmSystemCacheWs
;
77 ULONG MiNumberDescriptors
= 0;
78 BOOLEAN MiIncludeType
[LoaderMaximum
];
80 ///////////////////////////////////////////////
82 PMEMORY_ALLOCATION_DESCRIPTOR MxFreeDescriptor
;
83 MEMORY_ALLOCATION_DESCRIPTOR MxOldFreeDescriptor
;
85 PFN_NUMBER MxFreePageBase
;
86 ULONG64 MxFreePageCount
= 0;
89 NoDbgPrint(const char *Format
, ...)
96 MiEvaluateMemoryDescriptors(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
98 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock
;
99 PLIST_ENTRY ListEntry
;
103 /* Instantiate memory that we don't consider RAM/usable */
104 for (i
= 0; i
< LoaderMaximum
; i
++) MiIncludeType
[i
] = TRUE
;
105 MiIncludeType
[LoaderBad
] = FALSE
;
106 MiIncludeType
[LoaderFirmwarePermanent
] = FALSE
;
107 MiIncludeType
[LoaderSpecialMemory
] = FALSE
;
108 MiIncludeType
[LoaderBBTMemory
] = FALSE
;
110 /* Loop the memory descriptors */
111 for (ListEntry
= LoaderBlock
->MemoryDescriptorListHead
.Flink
;
112 ListEntry
!= &LoaderBlock
->MemoryDescriptorListHead
;
113 ListEntry
= ListEntry
->Flink
)
115 /* Get the memory descriptor */
116 MdBlock
= CONTAINING_RECORD(ListEntry
,
117 MEMORY_ALLOCATION_DESCRIPTOR
,
121 MiNumberDescriptors
++;
123 /* Skip pages that are not part of the PFN database */
124 if (!MiIncludeType
[MdBlock
->MemoryType
])
129 /* Add this to the total of pages */
130 MmNumberOfPhysicalPages
+= MdBlock
->PageCount
;
132 /* Check if this is the new lowest page */
133 if (MdBlock
->BasePage
< MmLowestPhysicalPage
)
135 /* Update the lowest page */
136 MmLowestPhysicalPage
= MdBlock
->BasePage
;
139 /* Check if this is the new highest page */
140 LastPage
= MdBlock
->BasePage
+ MdBlock
->PageCount
- 1;
141 if (LastPage
> MmHighestPhysicalPage
)
143 /* Update the highest page */
144 MmHighestPhysicalPage
= LastPage
;
147 /* Check if this is currently free memory */
148 if ((MdBlock
->MemoryType
== LoaderFree
) ||
149 (MdBlock
->MemoryType
== LoaderLoadedProgram
) ||
150 (MdBlock
->MemoryType
== LoaderFirmwareTemporary
) ||
151 (MdBlock
->MemoryType
== LoaderOsloaderStack
))
153 /* Check if this is the largest memory descriptor */
154 if (MdBlock
->PageCount
> MxFreePageCount
)
157 MxFreeDescriptor
= MdBlock
;
158 MxFreePageBase
= MdBlock
->BasePage
;
159 MxFreePageCount
= MdBlock
->PageCount
;
167 MxGetNextPage(IN PFN_NUMBER PageCount
)
171 /* Make sure we have enough pages */
172 if (PageCount
> MxFreePageCount
)
174 /* Crash the system */
175 KeBugCheckEx(INSTALL_MORE_MEMORY
,
176 MmNumberOfPhysicalPages
,
177 MxFreeDescriptor
->PageCount
,
178 MxOldFreeDescriptor
.PageCount
,
182 /* Use our lowest usable free pages */
183 Pfn
= MxFreePageBase
;
184 MxFreePageBase
+= PageCount
;
185 MxFreePageCount
-= PageCount
;
191 MxGetPte(PVOID Address
)
196 /* Setup template pte */
198 TmpPte
.u
.Flush
.Valid
= 1;
199 TmpPte
.u
.Flush
.Write
= 1;
201 /* Get a pointer to the PXE */
202 Pte
= MiAddressToPxe(Address
);
203 if (!Pte
->u
.Hard
.Valid
)
205 /* It's not valid, map it! */
206 TmpPte
.u
.Hard
.PageFrameNumber
= MxGetNextPage(1);
210 /* Get a pointer to the PPE */
211 Pte
= MiAddressToPpe(Address
);
212 if (!Pte
->u
.Hard
.Valid
)
214 /* It's not valid, map it! */
215 TmpPte
.u
.Hard
.PageFrameNumber
= MxGetNextPage(1);
219 /* Get a pointer to the PDE */
220 Pte
= MiAddressToPde(Address
);
221 if (!Pte
->u
.Hard
.Valid
)
223 /* It's not valid, map it! */
224 TmpPte
.u
.Hard
.PageFrameNumber
= MxGetNextPage(1);
228 /* Get a pointer to the PTE */
229 Pte
= MiAddressToPte(Address
);
234 MxMapPageRange(PVOID Address
, ULONG64 PageCount
)
238 /* Setup template pte */
240 TmpPte
.u
.Flush
.Valid
= 1;
241 TmpPte
.u
.Flush
.Write
= 1;
245 /* Get the PTE for that page */
246 Pte
= MxGetPte(Address
);
247 ASSERT(Pte
->u
.Hard
.Valid
== 0);
249 /* Map a physical page */
250 TmpPte
.u
.Hard
.PageFrameNumber
= MxGetNextPage(1);
254 Address
= (PVOID
)((ULONG64
)Address
+ PAGE_SIZE
);
260 MiArmConfigureMemorySizes(IN PLOADER_PARAMETER_BLOCK LoaderBloc
)
262 /* Get the size of the boot loader's image allocations */
263 MmBootImageSize
= KeLoaderBlock
->Extension
->LoaderPagesSpanned
* PAGE_SIZE
;
264 MmBootImageSize
= ROUND_UP(MmBootImageSize
, 4 * 1024 * 1024);
266 /* Check if this is a machine with less than 256MB of RAM, and no overide */
267 if ((MmNumberOfPhysicalPages
<= MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING
) &&
268 !(MmSizeOfNonPagedPoolInBytes
))
270 /* Force the non paged pool to be 2MB so we can reduce RAM usage */
271 MmSizeOfNonPagedPoolInBytes
= 2 * 1024 * 1024;
274 /* Check if the user gave a ridicuously large nonpaged pool RAM size */
275 if ((MmSizeOfNonPagedPoolInBytes
>> PAGE_SHIFT
) >
276 (MmNumberOfPhysicalPages
* 7 / 8))
278 /* More than 7/8ths of RAM was dedicated to nonpaged pool, ignore! */
279 MmSizeOfNonPagedPoolInBytes
= 0;
282 /* Check if no registry setting was set, or if the setting was too low */
283 if (MmSizeOfNonPagedPoolInBytes
< MmMinimumNonPagedPoolSize
)
285 /* Start with the minimum (256 KB) and add 32 KB for each MB above 4 */
286 MmSizeOfNonPagedPoolInBytes
= MmMinimumNonPagedPoolSize
;
287 MmSizeOfNonPagedPoolInBytes
+= (MmNumberOfPhysicalPages
- 1024) /
288 256 * MmMinAdditionNonPagedPoolPerMb
;
291 /* Check if the registy setting or our dynamic calculation was too high */
292 if (MmSizeOfNonPagedPoolInBytes
> MI_MAX_INIT_NONPAGED_POOL_SIZE
)
294 // Set it to the maximum */
295 MmSizeOfNonPagedPoolInBytes
= MI_MAX_INIT_NONPAGED_POOL_SIZE
;
298 /* Check if a percentage cap was set through the registry */
299 if (MmMaximumNonPagedPoolPercent
)
301 /* Don't feel like supporting this right now */
305 /* Page-align the nonpaged pool size */
306 MmSizeOfNonPagedPoolInBytes
&= ~(PAGE_SIZE
- 1);
308 /* Now, check if there was a registry size for the maximum size */
309 if (!MmMaximumNonPagedPoolInBytes
)
311 /* Start with the default (1MB) and add 400 KB for each MB above 4 */
312 MmMaximumNonPagedPoolInBytes
= MmDefaultMaximumNonPagedPool
;
313 MmMaximumNonPagedPoolInBytes
+= (MmNumberOfPhysicalPages
- 1024) /
314 256 * MmMaxAdditionNonPagedPoolPerMb
;
317 /* Don't let the maximum go too high */
318 if (MmMaximumNonPagedPoolInBytes
> MI_MAX_NONPAGED_POOL_SIZE
)
320 /* Set it to the upper limit */
321 MmMaximumNonPagedPoolInBytes
= MI_MAX_NONPAGED_POOL_SIZE
;
324 // MmSessionImageSize
329 MiArmInitializeMemoryLayout(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
331 /* Set up session space */
332 MiSessionSpaceEnd
= (PVOID
)MI_SESSION_SPACE_END
;
334 /* This is where we will load Win32k.sys and the video driver */
335 MiSessionImageEnd
= MiSessionSpaceEnd
;
336 MiSessionImageStart
= (PVOID
)((ULONG_PTR
)MiSessionImageEnd
-
339 /* The view starts right below the session working set (itself below
341 MiSessionViewEnd
= MI_SESSION_VIEW_END
;
342 MiSessionViewStart
= (PVOID
)((ULONG_PTR
)MiSessionViewStart
-
345 /* Session pool follows */
346 MiSessionPoolEnd
= MiSessionViewStart
;
347 MiSessionPoolStart
= (PVOID
)((ULONG_PTR
)MiSessionPoolEnd
-
350 /* And it all begins here */
351 MmSessionBase
= MiSessionPoolStart
;
353 /* System view space ends at session space, so now that we know where
354 * this is, we can compute the base address of system view space itself. */
355 MiSystemViewStart
= (PVOID
)((ULONG_PTR
)MmSessionBase
-
358 /* Use the default */
359 MmNumberOfSystemPtes
= MI_NUMBER_SYSTEM_PTES
;
361 ASSERT(MiSessionViewEnd
<= MiSessionImageStart
);
362 ASSERT(MmSessionBase
<= MiSessionPoolStart
);
367 MiArmInitializePageTable()
369 ULONG64 PageFrameOffset
;
370 PMMPTE Pte
, StartPte
, EndPte
;
373 /* HACK: don't use freeldr debug print anymore */
374 FrLdrDbgPrint
= NoDbgPrint
;
376 /* Get current directory base */
377 PageFrameOffset
= ((PMMPTE
)PXE_SELFMAP
)->u
.Hard
.PageFrameNumber
<< PAGE_SHIFT
;
378 ASSERT(PageFrameOffset
== __readcr3());
380 /* Set directory base for the system process */
381 PsGetCurrentProcess()->Pcb
.DirectoryTableBase
[0] = PageFrameOffset
;
383 /* Enable global pages */
384 __writecr4(__readcr4() | CR4_PGE
);
385 ASSERT(__readcr4() & CR4_PGE
);
387 /* Set user mode address range */
388 StartPte
= MiAddressToPxe(0);
389 EndPte
= MiAddressToPxe(MmHighestUserAddress
);
391 /* Loop the user mode PXEs */
392 for (Pte
= StartPte
; Pte
<= EndPte
; Pte
++)
394 /* Zero the PXE, clear all mappings */
398 /* Set up a template PTE */
400 TmplPte
.u
.Flush
.Valid
= 1;
401 TmplPte
.u
.Flush
.Write
= 1;
402 HyperTemplatePte
= TmplPte
;
404 /* Create PDPTs (72 KB) for shared system address space,
405 * skip page tables and hyperspace */
408 StartPte
= MiAddressToPxe((PVOID
)(HYPER_SPACE_END
+ 1));
409 EndPte
= MiAddressToPxe(MI_HIGHEST_SYSTEM_ADDRESS
);
412 for (Pte
= StartPte
; Pte
<= EndPte
; Pte
++)
414 /* Is the PXE already valid? */
415 if (!Pte
->u
.Hard
.Valid
)
417 /* It's not Initialize it */
418 TmplPte
.u
.Flush
.PageFrameNumber
= MxGetNextPage(1);
421 /* Zero the page. The PXE is the PTE for the PDPT. */
422 RtlZeroMemory(MiPteToAddress(Pte
), PAGE_SIZE
);
426 /* Set the range of system PTEs */
427 StartPte
= MiAddressToPte(MI_SYSTEM_PTE_START
);
428 EndPte
= StartPte
+ MmNumberOfSystemPtes
- 1;
430 /* Loop the system PTEs */
431 for (Pte
= StartPte
; Pte
<= EndPte
; Pte
++)
433 /* Make sure the PTE is valid */
434 MxGetPte(MiPteToAddress(Pte
));
440 /* Setup the mapping PTEs */
441 MmFirstReservedMappingPte
= MxGetPte((PVOID
)MI_MAPPING_RANGE_START
);
442 MmFirstReservedMappingPte
->u
.Hard
.PageFrameNumber
= MI_HYPERSPACE_PTES
;
443 MmLastReservedMappingPte
= MiAddressToPte((PVOID
)MI_MAPPING_RANGE_END
);
445 /* Setup debug mapping PTE */
446 MmDebugPte
= MxGetPte(MI_DEBUG_MAPPING
);
452 MiArmPreparePfnDatabse(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
454 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock
;
455 PLIST_ENTRY ListEntry
;
457 PUCHAR Page
, FirstPage
;
459 /* The PFN database is at the start of the non paged region */
460 MmPfnDatabase
= (PVOID
)((ULONG64
)MmNonPagedPoolEnd
- MmMaximumNonPagedPoolInBytes
);
462 /* Loop the memory descriptors */
463 for (ListEntry
= LoaderBlock
->MemoryDescriptorListHead
.Flink
;
464 ListEntry
!= &LoaderBlock
->MemoryDescriptorListHead
;
465 ListEntry
= ListEntry
->Flink
)
467 /* Get the memory descriptor */
468 MdBlock
= CONTAINING_RECORD(ListEntry
,
469 MEMORY_ALLOCATION_DESCRIPTOR
,
472 /* Skip pages that are not part of the PFN database */
473 if (!MiIncludeType
[MdBlock
->MemoryType
])
478 /* Get the base and size of this pfn database entry */
479 FirstPage
= PAGE_ALIGN(&MmPfnDatabase
[MdBlock
->BasePage
]);
480 Size
= ROUND_TO_PAGES(MdBlock
->PageCount
* sizeof(MMPFN
));
482 /* Loop the pages of this Pfn database entry */
483 for (Page
= FirstPage
; Page
< FirstPage
+ Size
; Page
+= PAGE_SIZE
)
485 /* Is the page already mapped? */
486 if (!MmIsAddressValid(Page
))
488 /* It's not, map it now */
489 MxMapPageRange(Page
, 1);
493 /* Zero out the pages */
494 RtlZeroMemory(FirstPage
, Size
);
497 /* Calculate the number of bytes, and then convert to pages */
498 MxPfnSizeInBytes
= ROUND_TO_PAGES(MmHighestPhysicalPage
+ 1) * sizeof(MMPFN
);
499 MxPfnAllocation
= MxPfnSizeInBytes
>> PAGE_SHIFT
;
501 /* Reduce maximum pool size */
502 MmMaximumNonPagedPoolInBytes
-= MxPfnSizeInBytes
;
508 MiArmPrepareNonPagedPool()
510 PFN_NUMBER PageCount
;
513 /* Non paged pool comes after the PFN database */
514 MmNonPagedPoolStart
= (PVOID
)((ULONG64
)MmPfnDatabase
+
516 ASSERT((ULONG64
)MmNonPagedPoolEnd
== (ULONG64
)MmNonPagedPoolStart
+
517 MmMaximumNonPagedPoolInBytes
);
519 /* Calculate the nonpaged pool expansion start region */
520 MmNonPagedPoolExpansionStart
= (PVOID
)((ULONG_PTR
)MmNonPagedPoolEnd
-
521 MmMaximumNonPagedPoolInBytes
+
522 MmSizeOfNonPagedPoolInBytes
);
523 MmNonPagedPoolExpansionStart
= (PVOID
)PAGE_ALIGN(MmNonPagedPoolExpansionStart
);
525 /* Now calculate the nonpaged system VA region, which includes the
526 * nonpaged pool expansion (above) and the system PTEs. Note that it is
527 * then aligned to a PDE boundary (4MB). */
528 MmNonPagedSystemStart
= (PVOID
)((ULONG_PTR
)MmNonPagedPoolExpansionStart
-
529 (MmNumberOfSystemPtes
+ 1) * PAGE_SIZE
);
530 MmNonPagedSystemStart
= (PVOID
)((ULONG_PTR
)MmNonPagedSystemStart
&
531 ~((4 * 1024 * 1024) - 1));
533 /* Don't let it go below the minimum */
534 if (MmNonPagedSystemStart
< (PVOID
)MI_NON_PAGED_SYSTEM_START_MIN
)
536 /* This is a hard-coded limit in the Windows NT address space */
537 MmNonPagedSystemStart
= (PVOID
)MI_NON_PAGED_SYSTEM_START_MIN
;
539 /* Reduce the amount of system PTEs to reach this point */
540 MmNumberOfSystemPtes
= ((ULONG_PTR
)MmNonPagedPoolExpansionStart
-
541 (ULONG_PTR
)MmNonPagedSystemStart
) >>
543 MmNumberOfSystemPtes
--;
544 ASSERT(MmNumberOfSystemPtes
> 1000);
547 /* Map the nonpaged pool */
548 PageCount
= (MmSizeOfNonPagedPoolInBytes
+ PAGE_SIZE
- 1) / PAGE_SIZE
;
549 MxMapPageRange(MmNonPagedPoolStart
, PageCount
);
551 /* Create PTEs for the paged pool extension */
552 for (Address
= MmNonPagedPoolExpansionStart
;
553 Address
< MmNonPagedPoolEnd
;
554 Address
= (PVOID
)((ULONG64
)Address
+ PAGE_SIZE
))
556 /* Create PXE, PPE, PDE and set PTE to 0*/
557 MxGetPte(Address
)->u
.Long
= 0;
561 ASSERT(MiAddressToPte(MmNonPagedSystemStart
) <
562 MiAddressToPte(MmNonPagedPoolExpansionStart
));
569 MiBuildPhysicalMemoryBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
571 PPHYSICAL_MEMORY_DESCRIPTOR Buffer
, NewBuffer
;
572 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock
;
573 PLIST_ENTRY ListEntry
;
574 PFN_NUMBER NextPage
= -1;
579 /* Calculate size for the PFN bitmap */
580 Size
= (MmHighestPhysicalPage
+ sizeof(ULONG
)) / sizeof(ULONG
);
582 /* Allocate the PFN bitmap */
583 Bitmap
= ExAllocatePoolWithTag(NonPagedPool
, Size
, ' mM');
585 /* Allocate enough memory for the physical memory block */
586 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
587 sizeof(PHYSICAL_MEMORY_DESCRIPTOR
) +
588 sizeof(PHYSICAL_MEMORY_RUN
) *
589 (MiNumberDescriptors
- 1),
591 if (!Bitmap
|| !Buffer
)
593 /* This is critical */
594 KeBugCheckEx(INSTALL_MORE_MEMORY
,
595 MmNumberOfPhysicalPages
,
596 MmLowestPhysicalPage
,
597 MmHighestPhysicalPage
,
601 /* Initialize the bitmap and clear all bits */
602 RtlInitializeBitMap(&MiPfnBitMap
, Bitmap
, MmHighestPhysicalPage
+ 1);
603 RtlClearAllBits(&MiPfnBitMap
);
605 /* Loop the memory descriptors */
606 for (ListEntry
= LoaderBlock
->MemoryDescriptorListHead
.Flink
;
607 ListEntry
!= &LoaderBlock
->MemoryDescriptorListHead
;
608 ListEntry
= ListEntry
->Flink
)
610 /* Get the memory descriptor */
611 MdBlock
= CONTAINING_RECORD(ListEntry
,
612 MEMORY_ALLOCATION_DESCRIPTOR
,
615 /* Skip pages that are not part of the PFN database */
616 if (!MiIncludeType
[MdBlock
->MemoryType
])
621 /* Does the memory block begin where the last ended? */
622 if (MdBlock
->BasePage
== NextPage
)
624 /* Add it to the current run */
625 Buffer
->Run
[Runs
- 1].PageCount
+= MdBlock
->PageCount
;
629 /* Create a new run */
631 Buffer
->Run
[Runs
- 1].BasePage
= MdBlock
->BasePage
;
632 Buffer
->Run
[Runs
- 1].PageCount
= MdBlock
->PageCount
;
635 /* Set the bits in the PFN bitmap */
636 RtlSetBits(&MiPfnBitMap
, MdBlock
->BasePage
, MdBlock
->PageCount
);
638 /* Set the next page */
639 NextPage
= MdBlock
->BasePage
+ MdBlock
->PageCount
;
642 // FIXME: allocate a buffer of better size
644 Buffer
->NumberOfRuns
= Runs
;
645 Buffer
->NumberOfPages
= MmNumberOfPhysicalPages
;
646 MmPhysicalMemoryBlock
= Buffer
;
651 MiBuildPagedPool(VOID
)
659 MmArmInitSystem(IN ULONG Phase
,
660 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
664 /* Parse memory descriptors */
665 MiEvaluateMemoryDescriptors(LoaderBlock
);
667 /* Configure the memory sizes */
668 MiArmConfigureMemorySizes(LoaderBlock
);
670 /* Initialize the memory layout */
671 MiArmInitializeMemoryLayout(LoaderBlock
);
673 /* Prepare PFN database mappings */
674 MiArmPreparePfnDatabse(LoaderBlock
);
676 /* Prepare paged pool mappings */
677 MiArmPrepareNonPagedPool();
679 /* Initialize some mappings */
680 MiArmInitializePageTable();
682 /* Initialize the ARM3 nonpaged pool */
683 MiInitializeArmPool();
685 /* Update the memory descriptor, to make sure the pages we used
686 won't get inserted into the PFN database */
687 MxOldFreeDescriptor
= *MxFreeDescriptor
;
688 MxFreeDescriptor
->BasePage
= MxFreePageBase
;
689 MxFreeDescriptor
->PageCount
= MxFreePageCount
;
695 PPHYSICAL_MEMORY_RUN Run
;
697 /* The PFN database was created, restore the free descriptor */
698 *MxFreeDescriptor
= MxOldFreeDescriptor
;
700 /* Initialize the nonpaged pool */
701 InitializePool(NonPagedPool
, 0);
703 /* Create the system PTE space */
704 Pte
= MiAddressToPte(MI_SYSTEM_PTE_START
);
705 MiInitializeSystemPtes(Pte
, MmNumberOfSystemPtes
, SystemPteSpace
);
707 /* Reserve system PTEs for zeroing PTEs and clear them */
708 MiFirstReservedZeroingPte
= MiReserveSystemPtes(MI_ZERO_PTES
,
710 RtlZeroMemory(MiFirstReservedZeroingPte
, MI_ZERO_PTES
* sizeof(MMPTE
));
712 /* Set the counter to maximum */
713 MiFirstReservedZeroingPte
->u
.Hard
.PageFrameNumber
= MI_ZERO_PTES
- 1;
715 /* Build the physical memory block */
716 MiBuildPhysicalMemoryBlock(LoaderBlock
);
718 /* Size up paged pool and build the shadow system page directory */
722 return STATUS_SUCCESS
;