Use free Windows DDK and compile with latest MinGW releases.
[reactos.git] / reactos / ntoskrnl / mm / mminit.c
1 /* $Id: mminit.c,v 1.39 2002/09/07 15:13:00 chorns Exp $
2 *
3 * COPYRIGHT: See COPYING in the top directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/mm/mminit.c
6 * PURPOSE: kernel memory managment initialization functions
7 * PROGRAMMER: David Welch (welch@cwcom.net)
8 * UPDATE HISTORY:
9 * Created 9/4/98
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ntoskrnl.h>
15
16 #define NDEBUG
17 #include <internal/debug.h>
18
19
20 /* GLOBALS *****************************************************************/
21
22 /*
23 * Size of extended memory (kb) (fixed for now)
24 */
25 #define EXTENDED_MEMORY_SIZE (3*1024*1024)
26
27 /*
28 * Compiler defined symbols
29 */
30 extern unsigned int _text_start__;
31 extern unsigned int _text_end__;
32
33 static BOOLEAN IsThisAnNtAsSystem = FALSE;
34 static MM_SYSTEM_SIZE MmSystemSize = MmSmallSystem;
35
36 extern unsigned int _bss_end__;
37
38 static MEMORY_AREA* kernel_text_desc = NULL;
39 static MEMORY_AREA* kernel_data_desc = NULL;
40 static MEMORY_AREA* kernel_param_desc = NULL;
41 static MEMORY_AREA* kernel_pool_desc = NULL;
42 static MEMORY_AREA* kernel_shared_data_desc = NULL;
43 static MEMORY_AREA* MiPagedPoolDescriptor = NULL;
44
45 PHYSICAL_ADDRESS MmSharedDataPagePhysicalAddress;
46
47 PVOID MiHighestUserAddress = NULL;
48 PVOID * MmHighestUserAddress = &MiHighestUserAddress;
49 ULONG MiUserProbeAddress = 0;
50 ULONG * MmUserProbeAddress = &MiUserProbeAddress;
51
52
53 /* FUNCTIONS ****************************************************************/
54
55 BOOLEAN STDCALL MmIsThisAnNtAsSystem(VOID)
56 {
57 return(IsThisAnNtAsSystem);
58 }
59
60 MM_SYSTEM_SIZE STDCALL MmQuerySystemSize(VOID)
61 {
62 return(MmSystemSize);
63 }
64
65 VOID MiShutdownMemoryManager(VOID)
66 {
67 }
68
69 VOID MmInitVirtualMemory(ULONG LastKernelAddress,
70 ULONG KernelLength)
71 /*
72 * FUNCTION: Intialize the memory areas list
73 * ARGUMENTS:
74 * bp = Pointer to the boot parameters
75 * kernel_len = Length of the kernel
76 */
77 {
78 PVOID BaseAddress;
79 ULONG Length;
80 ULONG ParamLength = KernelLength;
81 NTSTATUS Status;
82 //ULONG i;
83
84 DPRINT("MmInitVirtualMemory(%x, %x)\n",LastKernelAddress, KernelLength);
85
86 LastKernelAddress = PAGE_ROUND_UP(LastKernelAddress);
87
88 MmInitMemoryAreas();
89 ExInitNonPagedPool(LastKernelAddress + PAGE_SIZE);
90
91 /*
92 * Setup the system area descriptor list
93 */
94 BaseAddress = (PVOID)KERNEL_BASE;
95 Length = PAGE_ROUND_UP(((ULONG)&_text_end__)) - KERNEL_BASE;
96 ParamLength = ParamLength - Length;
97
98 /*
99 * No need to lock the address space at this point since no
100 * other threads are running.
101 */
102 MmCreateMemoryArea(NULL,
103 MmGetKernelAddressSpace(),
104 MEMORY_AREA_SYSTEM,
105 &BaseAddress,
106 Length,
107 0,
108 &kernel_text_desc,
109 FALSE);
110
111 Length = PAGE_ROUND_UP(((ULONG)&_bss_end__)) -
112 PAGE_ROUND_UP(((ULONG)&_text_end__));
113 ParamLength = ParamLength - Length;
114 DPRINT("Length %x\n",Length);
115 BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG)&_text_end__));
116 DPRINT("BaseAddress %x\n",BaseAddress);
117
118 /*
119 * No need to lock the address space at this point since we are
120 * the only thread running.
121 */
122 MmCreateMemoryArea(NULL,
123 MmGetKernelAddressSpace(),
124 MEMORY_AREA_SYSTEM,
125 &BaseAddress,
126 Length,
127 0,
128 &kernel_data_desc,
129 FALSE);
130
131 BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG)&_bss_end__));
132 // Length = ParamLength;
133 Length = LastKernelAddress - (ULONG)BaseAddress;
134 MmCreateMemoryArea(NULL,
135 MmGetKernelAddressSpace(),
136 MEMORY_AREA_SYSTEM,
137 &BaseAddress,
138 Length,
139 0,
140 &kernel_param_desc,
141 FALSE);
142
143 BaseAddress = (PVOID)(LastKernelAddress + PAGE_SIZE);
144 Length = NONPAGED_POOL_SIZE;
145 MmCreateMemoryArea(NULL,
146 MmGetKernelAddressSpace(),
147 MEMORY_AREA_SYSTEM,
148 &BaseAddress,
149 Length,
150 0,
151 &kernel_pool_desc,
152 FALSE);
153
154 MmPagedPoolSize = MM_PAGED_POOL_SIZE;
155 BaseAddress = (PVOID)(LastKernelAddress + PAGE_SIZE + NONPAGED_POOL_SIZE +
156 PAGE_SIZE);
157 MmPagedPoolBase = BaseAddress;
158 Length = MM_PAGED_POOL_SIZE;
159 MmCreateMemoryArea(NULL,
160 MmGetKernelAddressSpace(),
161 MEMORY_AREA_PAGED_POOL,
162 &BaseAddress,
163 Length,
164 0,
165 &MiPagedPoolDescriptor,
166 FALSE);
167 MmInitializePagedPool();
168
169 /*
170 * Create the kernel mapping of the user/kernel shared memory.
171 */
172 BaseAddress = (PVOID)KI_USER_SHARED_DATA;
173 Length = PAGE_SIZE;
174 MmCreateMemoryArea(NULL,
175 MmGetKernelAddressSpace(),
176 MEMORY_AREA_SYSTEM,
177 &BaseAddress,
178 Length,
179 0,
180 &kernel_shared_data_desc,
181 FALSE);
182 Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE,
183 &MmSharedDataPagePhysicalAddress);
184 Status = MmCreateVirtualMapping(NULL,
185 (PVOID)KI_USER_SHARED_DATA,
186 PAGE_READWRITE,
187 MmSharedDataPagePhysicalAddress,
188 TRUE);
189 if (!NT_SUCCESS(Status))
190 {
191 DbgPrint("Unable to create virtual mapping\n");
192 KeBugCheck(0);
193 }
194 RtlZeroMemory(BaseAddress, Length);
195
196 /*
197 *
198 */
199 MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
200 }
201
202 VOID MmInit1(ULONG FirstKrnlPhysAddr,
203 ULONG LastKrnlPhysAddr,
204 ULONG LastKernelAddress,
205 PADDRESS_RANGE BIOSMemoryMap,
206 ULONG AddressRangeCount)
207 /*
208 * FUNCTION: Initalize memory managment
209 */
210 {
211 ULONG i;
212 ULONG kernel_len;
213 #ifndef MP
214 extern unsigned int unmap_me, unmap_me2, unmap_me3;
215 #endif
216
217 DPRINT("MmInit1(FirstKrnlPhysAddr, %x, LastKrnlPhysAddr %x, LastKernelAddress %x)\n",
218 FirstKrnlPhysAddr,
219 LastKrnlPhysAddr,
220 LastKernelAddress);
221
222 if ((BIOSMemoryMap != NULL) && (AddressRangeCount > 0))
223 {
224 // If we have a bios memory map, recalulate the the memory size
225 ULONG last = 0;
226 for (i = 0; i < AddressRangeCount; i++)
227 {
228 if (BIOSMemoryMap[i].Type == 1
229 && (BIOSMemoryMap[i].BaseAddrLow + BIOSMemoryMap[i].LengthLow + PAGE_SIZE -1) / PAGE_SIZE > last)
230 {
231 last = (BIOSMemoryMap[i].BaseAddrLow + BIOSMemoryMap[i].LengthLow + PAGE_SIZE -1) / PAGE_SIZE;
232 }
233 }
234 if ((last - 256) * 4 > KeLoaderBlock.MemHigher)
235 {
236 KeLoaderBlock.MemHigher = (last - 256) * 4;
237 }
238 }
239
240 /*
241 * FIXME: Set this based on the system command line
242 */
243 MiUserProbeAddress = (ULONG)0x7fff0000;
244 MiHighestUserAddress = (PVOID)0x7ffeffff;
245
246 /*
247 * Initialize memory managment statistics
248 */
249 MmStats.NrTotalPages = 0;
250 MmStats.NrSystemPages = 0;
251 MmStats.NrUserPages = 0;
252 MmStats.NrReservedPages = 0;
253 MmStats.NrUserPages = 0;
254 MmStats.NrFreePages = 0;
255 MmStats.NrLockedPages = 0;
256 MmStats.PagingRequestsInLastMinute = 0;
257 MmStats.PagingRequestsInLastFiveMinutes = 0;
258 MmStats.PagingRequestsInLastFifteenMinutes = 0;
259
260 /*
261 * Initialize the kernel address space
262 */
263 MmInitializeKernelAddressSpace();
264
265 /*
266 * Unmap low memory
267 */
268 #ifndef MP
269 /* FIXME: This is broken in SMP mode */
270 MmDeletePageTable(NULL, 0);
271 #endif
272 /*
273 * Free all pages not used for kernel memory
274 * (we assume the kernel occupies a continuous range of physical
275 * memory)
276 */
277 DPRINT("first krnl %x\nlast krnl %x\n",FirstKrnlPhysAddr,
278 LastKrnlPhysAddr);
279
280 /*
281 * Free physical memory not used by the kernel
282 */
283 MmStats.NrTotalPages = KeLoaderBlock.MemHigher/4;
284 if (!MmStats.NrTotalPages)
285 {
286 DbgPrint("Memory not detected, default to 8 MB\n");
287 MmStats.NrTotalPages = 2048;
288 }
289 else
290 {
291 /* add 1MB for standard memory (not extended) */
292 MmStats.NrTotalPages += 256;
293 }
294 #ifdef BIOS_MEM_FIX
295 MmStats.NrTotalPages += 16;
296 #endif
297 DbgPrint("Used memory %dKb\n", (MmStats.NrTotalPages * PAGE_SIZE) / 1024);
298
299 LastKernelAddress = (ULONG)MmInitializePageList(
300 (PVOID)FirstKrnlPhysAddr,
301 (PVOID)LastKrnlPhysAddr,
302 MmStats.NrTotalPages,
303 PAGE_ROUND_UP(LastKernelAddress),
304 BIOSMemoryMap,
305 AddressRangeCount);
306 kernel_len = LastKrnlPhysAddr - FirstKrnlPhysAddr;
307
308 /*
309 * Create a trap for null pointer references and protect text
310 * segment
311 */
312 CHECKPOINT;
313 DPRINT("_text_start__ %x _text_end__ %x\n",(int)&_text_start__,(int)&_text_end__);
314 for (i=PAGE_ROUND_UP(((int)&_text_start__));
315 i<PAGE_ROUND_DOWN(((int)&_text_end__));i=i+PAGE_SIZE)
316 {
317 MmSetPageProtect(NULL,
318 (PVOID)i,
319 PAGE_EXECUTE_READ);
320 }
321
322 DPRINT("Invalidating between %x and %x\n",
323 LastKernelAddress,
324 KERNEL_BASE + 2 * PAGE_TABLE_SIZE);
325 for (i=(LastKernelAddress);
326 i<(KERNEL_BASE + 2 * PAGE_TABLE_SIZE);
327 i=i+PAGE_SIZE)
328 {
329 MmDeleteVirtualMapping(NULL, (PVOID)(i), FALSE, NULL, NULL);
330 }
331 DPRINT("Almost done MmInit()\n");
332 #ifndef MP
333 /* FIXME: This is broken in SMP mode */
334 MmDeleteVirtualMapping(NULL, (PVOID)&unmap_me, FALSE, NULL, NULL);
335 MmDeleteVirtualMapping(NULL, (PVOID)&unmap_me2, FALSE, NULL, NULL);
336 MmDeleteVirtualMapping(NULL, (PVOID)&unmap_me3, FALSE, NULL, NULL);
337 #endif
338 /*
339 * Intialize memory areas
340 */
341 MmInitVirtualMemory(LastKernelAddress, kernel_len);
342
343 MmInitializeMdlImplementation();
344 }
345
346 VOID MmInit2(VOID)
347 {
348 MmInitSectionImplementation();
349 MmInitPagingFile();
350 }
351
352 VOID MmInit3(VOID)
353 {
354 MmInitPagerThread();
355 MmCreatePhysicalMemorySection();
356 MmInitializeRmapList();
357
358 /*
359 * Initialise the modified page writer.
360 */
361 MmInitMpwThread();
362
363 /* FIXME: Read parameters from memory */
364 }
365