xref: /reactos/ntoskrnl/mm/mminit.c (revision 8a92b556)
1 /*
2  * PROJECT:         ReactOS Kernel
3  * LICENSE:         GPL - See COPYING in the top level directory
4  * FILE:            ntoskrnl/mm/mminit.c
5  * PURPOSE:         Memory Manager Initialization
6  * PROGRAMMERS:
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 #define MODULE_INVOLVED_IN_ARM3
16 #include "ARM3/miarm.h"
17 
18 /* GLOBALS *******************************************************************/
19 
20 VOID NTAPI MiInitializeUserPfnBitmap(VOID);
21 
22 BOOLEAN Mm64BitPhysicalAddress = FALSE;
23 ULONG MmReadClusterSize;
24 //
25 // 0 | 1 is on/off paging, 2 is undocumented
26 //
27 UCHAR MmDisablePagingExecutive = 1; // Forced to off
28 PMMPTE MmSharedUserDataPte;
29 PMMSUPPORT MmKernelAddressSpace;
30 
31 extern KEVENT MmWaitPageEvent;
32 extern FAST_MUTEX MiGlobalPageOperation;
33 extern LIST_ENTRY MiSegmentList;
34 extern NTSTATUS MiRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed);
35 
36 /* PRIVATE FUNCTIONS *********************************************************/
37 
38 //
39 // Helper function to create initial memory areas.
40 // The created area is always read/write.
41 //
42 CODE_SEG("INIT")
43 VOID
44 NTAPI
45 MiCreateArm3StaticMemoryArea(PVOID BaseAddress, SIZE_T Size, BOOLEAN Executable)
46 {
47     const ULONG Protection = Executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
48     PVOID pBaseAddress = BaseAddress;
49     PMEMORY_AREA MArea;
50     NTSTATUS Status;
51 
52     Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
53                                 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
54                                 &pBaseAddress,
55                                 Size,
56                                 Protection,
57                                 &MArea,
58                                 0,
59                                 PAGE_SIZE);
60     ASSERT(Status == STATUS_SUCCESS);
61     // TODO: Perhaps it would be  prudent to bugcheck here, not only assert?
62 }
63 
64 CODE_SEG("INIT")
65 VOID
66 NTAPI
67 MiInitSystemMemoryAreas(VOID)
68 {
69     //
70     // Create all the static memory areas.
71     //
72 
73 #ifdef _M_AMD64
74     // Reserved range FFFF800000000000 - FFFFF68000000000
75     MiCreateArm3StaticMemoryArea((PVOID)MI_REAL_SYSTEM_RANGE_START, PTE_BASE - MI_REAL_SYSTEM_RANGE_START, FALSE);
76 #endif /* _M_AMD64 */
77 
78     // The loader mappings. The only Executable area.
79     MiCreateArm3StaticMemoryArea((PVOID)KSEG0_BASE, MmBootImageSize, TRUE);
80 
81     // The PTE base
82     MiCreateArm3StaticMemoryArea((PVOID)PTE_BASE, PTE_TOP - PTE_BASE + 1, FALSE);
83 
84     // Hyperspace
85     MiCreateArm3StaticMemoryArea((PVOID)HYPER_SPACE, HYPER_SPACE_END - HYPER_SPACE + 1, FALSE);
86 
87     // Protect the PFN database
88     MiCreateArm3StaticMemoryArea(MmPfnDatabase, (MxPfnAllocation << PAGE_SHIFT), FALSE);
89 
90     // ReactOS requires a memory area to keep the initial NP area off-bounds
91     MiCreateArm3StaticMemoryArea(MmNonPagedPoolStart, MmSizeOfNonPagedPoolInBytes, FALSE);
92 
93     // System PTE space
94     MiCreateArm3StaticMemoryArea(MmNonPagedSystemStart, (MmNumberOfSystemPtes + 1) * PAGE_SIZE, FALSE);
95 
96     // Nonpaged pool expansion space
97     MiCreateArm3StaticMemoryArea(MmNonPagedPoolExpansionStart, (ULONG_PTR)MmNonPagedPoolEnd - (ULONG_PTR)MmNonPagedPoolExpansionStart, FALSE);
98 
99     // System view space
100     MiCreateArm3StaticMemoryArea(MiSystemViewStart, MmSystemViewSize, FALSE);
101 
102     // Session space
103     MiCreateArm3StaticMemoryArea(MmSessionBase, (ULONG_PTR)MiSessionSpaceEnd - (ULONG_PTR)MmSessionBase, FALSE);
104 
105     // Paged pool
106     MiCreateArm3StaticMemoryArea(MmPagedPoolStart, MmSizeOfPagedPoolInBytes, FALSE);
107 
108     // Debugger mapping
109     MiCreateArm3StaticMemoryArea(MI_DEBUG_MAPPING, PAGE_SIZE, FALSE);
110 
111 #if defined(_X86_)
112     // Reserved HAL area (includes KUSER_SHARED_DATA and KPCR)
113     MiCreateArm3StaticMemoryArea((PVOID)MM_HAL_VA_START, MM_HAL_VA_END - MM_HAL_VA_START + 1, FALSE);
114 #else /* _X86_ */
115 #ifndef _M_AMD64
116     // KPCR, one page per CPU. Only for 32-bit kernel.
117     MiCreateArm3StaticMemoryArea(PCR, PAGE_SIZE * KeNumberProcessors, FALSE);
118 #endif /* _M_AMD64 */
119 
120     // KUSER_SHARED_DATA
121     MiCreateArm3StaticMemoryArea((PVOID)KI_USER_SHARED_DATA, PAGE_SIZE, FALSE);
122 #endif /* _X86_ */
123 }
124 
125 CODE_SEG("INIT")
126 VOID
127 NTAPI
128 MiDbgDumpAddressSpace(VOID)
129 {
130     //
131     // Print the memory layout
132     //
133     DPRINT1("          0x%p - 0x%p\t%s\n",
134             KSEG0_BASE,
135             (ULONG_PTR)KSEG0_BASE + MmBootImageSize,
136             "Boot Loaded Image");
137     DPRINT1("          0x%p - 0x%p\t%s\n",
138             MmPfnDatabase,
139             (ULONG_PTR)MmPfnDatabase + (MxPfnAllocation << PAGE_SHIFT),
140             "PFN Database");
141     DPRINT1("          0x%p - 0x%p\t%s\n",
142             MmNonPagedPoolStart,
143             (ULONG_PTR)MmNonPagedPoolStart + MmSizeOfNonPagedPoolInBytes,
144             "ARM3 Non Paged Pool");
145     DPRINT1("          0x%p - 0x%p\t%s\n",
146             MiSystemViewStart,
147             (ULONG_PTR)MiSystemViewStart + MmSystemViewSize,
148             "System View Space");
149     DPRINT1("          0x%p - 0x%p\t%s\n",
150             MmSessionBase,
151             MiSessionSpaceEnd,
152             "Session Space");
153     DPRINT1("          0x%p - 0x%p\t%s\n",
154             PTE_BASE, PTE_TOP,
155             "Page Tables");
156     DPRINT1("          0x%p - 0x%p\t%s\n",
157             PDE_BASE, PDE_TOP,
158             "Page Directories");
159     DPRINT1("          0x%p - 0x%p\t%s\n",
160             HYPER_SPACE, HYPER_SPACE_END,
161             "Hyperspace");
162     DPRINT1("          0x%p - 0x%p\t%s\n",
163             MmSystemCacheStart, MmSystemCacheEnd,
164             "System Cache");
165     DPRINT1("          0x%p - 0x%p\t%s\n",
166             MmPagedPoolStart,
167             (ULONG_PTR)MmPagedPoolStart + MmSizeOfPagedPoolInBytes,
168             "ARM3 Paged Pool");
169     DPRINT1("          0x%p - 0x%p\t%s\n",
170             MmNonPagedSystemStart, MmNonPagedPoolExpansionStart,
171             "System PTE Space");
172     DPRINT1("          0x%p - 0x%p\t%s\n",
173             MmNonPagedPoolExpansionStart, MmNonPagedPoolEnd,
174             "Non Paged Pool Expansion PTE Space");
175 }
176 
177 CODE_SEG("INIT")
178 NTSTATUS
179 NTAPI
180 MmInitBsmThread(VOID)
181 {
182     NTSTATUS Status;
183     OBJECT_ATTRIBUTES ObjectAttributes;
184     HANDLE ThreadHandle;
185 
186     /* Create the thread */
187     InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
188     Status = PsCreateSystemThread(&ThreadHandle,
189                                   THREAD_ALL_ACCESS,
190                                   &ObjectAttributes,
191                                   NULL,
192                                   NULL,
193                                   KeBalanceSetManager,
194                                   NULL);
195 
196     /* Close the handle and return status */
197     ZwClose(ThreadHandle);
198     return Status;
199 }
200 
201 CODE_SEG("INIT")
202 BOOLEAN
203 NTAPI
204 MmInitSystem(IN ULONG Phase,
205              IN PLOADER_PARAMETER_BLOCK LoaderBlock)
206 {
207     extern MMPTE ValidKernelPte;
208     PMMPTE PointerPte;
209     MMPTE TempPte = ValidKernelPte;
210     PFN_NUMBER PageFrameNumber;
211     PLIST_ENTRY ListEntry;
212     PLDR_DATA_TABLE_ENTRY DataTableEntry;
213 
214     /* Initialize the kernel address space */
215     ASSERT(Phase == 1);
216 
217     InitializeListHead(&MiSegmentList);
218     ExInitializeFastMutex(&MiGlobalPageOperation);
219     KeInitializeEvent(&MmWaitPageEvent, SynchronizationEvent, FALSE);
220     // Until we're fully demand paged, we can do things the old way through
221     // the balance manager
222     MmInitializeMemoryConsumer(MC_CACHE, MiRosTrimCache);
223 
224     MmKernelAddressSpace = &PsIdleProcess->Vm;
225 
226     /* Intialize system memory areas */
227     MiInitSystemMemoryAreas();
228 
229     /* Dump the address space */
230     MiDbgDumpAddressSpace();
231 
232     MmInitGlobalKernelPageDirectory();
233     MiInitializeUserPfnBitmap();
234     MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
235     MmInitializeRmapList();
236     MmInitSectionImplementation();
237     MmInitPagingFile();
238 
239     //
240     // Create a PTE to double-map the shared data section. We allocate it
241     // from paged pool so that we can't fault when trying to touch the PTE
242     // itself (to map it), since paged pool addresses will already be mapped
243     // by the fault handler.
244     //
245     MmSharedUserDataPte = ExAllocatePoolWithTag(PagedPool,
246                           sizeof(MMPTE),
247                           TAG_MM);
248     if (!MmSharedUserDataPte) return FALSE;
249 
250     //
251     // Now get the PTE for shared data, and read the PFN that holds it
252     //
253     PointerPte = MiAddressToPte((PVOID)KI_USER_SHARED_DATA);
254     ASSERT(PointerPte->u.Hard.Valid == 1);
255     PageFrameNumber = PFN_FROM_PTE(PointerPte);
256 
257     /* Build the PTE and write it */
258     MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte,
259                                 PointerPte,
260                                 MM_READONLY,
261                                 PageFrameNumber);
262     *MmSharedUserDataPte = TempPte;
263 
264     /* Initialize session working set support */
265     MiInitializeSessionWsSupport();
266 
267     /* Setup session IDs */
268     MiInitializeSessionIds();
269 
270     /* Setup the memory threshold events */
271     if (!MiInitializeMemoryEvents()) return FALSE;
272 
273     /*
274      * Unmap low memory
275      */
276     MiInitBalancerThread();
277 
278     /* Initialize the balance set manager */
279     MmInitBsmThread();
280 
281     /* Loop the boot loaded images (under lock) */
282     ExAcquireResourceExclusiveLite(&PsLoadedModuleResource, TRUE);
283     for (ListEntry = PsLoadedModuleList.Flink;
284          ListEntry != &PsLoadedModuleList;
285          ListEntry = ListEntry->Flink)
286     {
287         /* Get the data table entry */
288         DataTableEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
289 
290         /* Set up the image protection */
291         MiWriteProtectSystemImage(DataTableEntry->DllBase);
292     }
293     ExReleaseResourceLite(&PsLoadedModuleResource);
294 
295     return TRUE;
296 }
297 
298