Fixed some swapping bugs and deadlocks
[reactos.git] / reactos / ntoskrnl / mm / mminit.c
1 /* $Id: mminit.c,v 1.30 2002/01/01 00:21:56 dwelch 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 <ddk/ntddk.h>
15 #include <roscfg.h>
16 #include <internal/i386/segment.h>
17 #include <internal/mm.h>
18 #include <internal/ntoskrnl.h>
19 #include <internal/io.h>
20 #include <internal/ps.h>
21 #include <napi/shared_data.h>
22 #include <internal/pool.h>
23
24 #define NDEBUG
25 #include <internal/debug.h>
26
27 /* GLOBALS *****************************************************************/
28
29 /*
30 * Size of extended memory (kb) (fixed for now)
31 */
32 #define EXTENDED_MEMORY_SIZE (3*1024*1024)
33
34 /*
35 * Compiler defined symbols
36 */
37 extern unsigned int _text_start__;
38 extern unsigned int _text_end__;
39
40 static BOOLEAN IsThisAnNtAsSystem = FALSE;
41 static MM_SYSTEM_SIZE MmSystemSize = MmSmallSystem;
42
43 extern unsigned int _bss_end__;
44
45 static MEMORY_AREA* kernel_text_desc = NULL;
46 static MEMORY_AREA* kernel_data_desc = NULL;
47 static MEMORY_AREA* kernel_param_desc = NULL;
48 static MEMORY_AREA* kernel_pool_desc = NULL;
49 static MEMORY_AREA* kernel_shared_data_desc = NULL;
50 static MEMORY_AREA* MiPagedPoolDescriptor = NULL;
51
52 PVOID MmSharedDataPagePhysicalAddress = NULL;
53
54 /* FUNCTIONS ****************************************************************/
55
56 BOOLEAN STDCALL MmIsThisAnNtAsSystem(VOID)
57 {
58 return(IsThisAnNtAsSystem);
59 }
60
61 MM_SYSTEM_SIZE STDCALL MmQuerySystemSize(VOID)
62 {
63 return(MmSystemSize);
64 }
65
66 VOID MiShutdownMemoryManager(VOID)
67 {
68 }
69
70 VOID MmInitVirtualMemory(ULONG LastKernelAddress,
71 ULONG KernelLength)
72 /*
73 * FUNCTION: Intialize the memory areas list
74 * ARGUMENTS:
75 * bp = Pointer to the boot parameters
76 * kernel_len = Length of the kernel
77 */
78 {
79 PVOID BaseAddress;
80 ULONG Length;
81 ULONG ParamLength = KernelLength;
82 NTSTATUS Status;
83 //ULONG i;
84
85 DPRINT("MmInitVirtualMemory(%x, %x)\n",LastKernelAddress, KernelLength);
86
87 LastKernelAddress = PAGE_ROUND_UP(LastKernelAddress);
88
89 MmInitMemoryAreas();
90 ExInitNonPagedPool(LastKernelAddress + PAGESIZE);
91
92 /*
93 * Setup the system area descriptor list
94 */
95 BaseAddress = (PVOID)KERNEL_BASE;
96 Length = PAGE_ROUND_UP(((ULONG)&_text_end__)) - KERNEL_BASE;
97 ParamLength = ParamLength - Length;
98
99 /*
100 * No need to lock the address space at this point since no
101 * other threads are running.
102 */
103 MmCreateMemoryArea(NULL,
104 MmGetKernelAddressSpace(),
105 MEMORY_AREA_SYSTEM,
106 &BaseAddress,
107 Length,
108 0,
109 &kernel_text_desc,
110 FALSE);
111
112 Length = PAGE_ROUND_UP(((ULONG)&_bss_end__)) -
113 PAGE_ROUND_UP(((ULONG)&_text_end__));
114 ParamLength = ParamLength - Length;
115 DPRINT("Length %x\n",Length);
116 BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG)&_text_end__));
117 DPRINT("BaseAddress %x\n",BaseAddress);
118
119 /*
120 * No need to lock the address space at this point since we are
121 * the only thread running.
122 */
123 MmCreateMemoryArea(NULL,
124 MmGetKernelAddressSpace(),
125 MEMORY_AREA_SYSTEM,
126 &BaseAddress,
127 Length,
128 0,
129 &kernel_data_desc,
130 FALSE);
131
132 BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG)&_bss_end__));
133 // Length = ParamLength;
134 Length = LastKernelAddress - (ULONG)BaseAddress;
135 MmCreateMemoryArea(NULL,
136 MmGetKernelAddressSpace(),
137 MEMORY_AREA_SYSTEM,
138 &BaseAddress,
139 Length,
140 0,
141 &kernel_param_desc,
142 FALSE);
143
144 BaseAddress = (PVOID)(LastKernelAddress + PAGESIZE);
145 Length = NONPAGED_POOL_SIZE;
146 MmCreateMemoryArea(NULL,
147 MmGetKernelAddressSpace(),
148 MEMORY_AREA_SYSTEM,
149 &BaseAddress,
150 Length,
151 0,
152 &kernel_pool_desc,
153 FALSE);
154
155 MmPagedPoolSize = MM_PAGED_POOL_SIZE;
156 BaseAddress = (PVOID)(LastKernelAddress + PAGESIZE + NONPAGED_POOL_SIZE +
157 PAGESIZE);
158 MmPagedPoolBase = BaseAddress;
159 Length = MM_PAGED_POOL_SIZE;
160 MmCreateMemoryArea(NULL,
161 MmGetKernelAddressSpace(),
162 MEMORY_AREA_PAGED_POOL,
163 &BaseAddress,
164 Length,
165 0,
166 &MiPagedPoolDescriptor,
167 FALSE);
168 MmInitializePagedPool();
169
170 /*
171 * Create the kernel mapping of the user/kernel shared memory.
172 */
173 BaseAddress = (PVOID)KERNEL_SHARED_DATA_BASE;
174 Length = PAGESIZE;
175 MmCreateMemoryArea(NULL,
176 MmGetKernelAddressSpace(),
177 MEMORY_AREA_SYSTEM,
178 &BaseAddress,
179 Length,
180 0,
181 &kernel_shared_data_desc,
182 FALSE);
183 Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &MmSharedDataPagePhysicalAddress);
184 Status = MmCreateVirtualMapping(NULL,
185 (PVOID)KERNEL_SHARED_DATA_BASE,
186 PAGE_READWRITE,
187 (ULONG)MmSharedDataPagePhysicalAddress,
188 TRUE);
189 if (!NT_SUCCESS(Status))
190 {
191 DbgPrint("Unable to create virtual mapping\n");
192 KeBugCheck(0);
193 }
194 ((PKUSER_SHARED_DATA)KERNEL_SHARED_DATA_BASE)->TickCountLow = 0xdeadbeef;
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 + PAGESIZE -1) / PAGESIZE > last)
230 {
231 last = (BIOSMemoryMap[i].BaseAddrLow + BIOSMemoryMap[i].LengthLow + PAGESIZE -1) / PAGESIZE;
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 MmUserProbeAddress = (PVOID)0x7fff0000;
244 MmHighestUserAddress = (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 * PAGESIZE) / 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+PAGESIZE)
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 + PAGE_TABLE_SIZE);
325 for (i=(LastKernelAddress);
326 i<(KERNEL_BASE + PAGE_TABLE_SIZE);
327 i=i+PAGESIZE)
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
344 VOID MmInit2(VOID)
345 {
346 MmInitSectionImplementation();
347 MmInitPagingFile();
348 }
349
350 VOID MmInit3(VOID)
351 {
352 MmInitPagerThread();
353 MmCreatePhysicalMemorySection();
354 MmInitializeRmapList();
355
356 /* FIXME: Read parameters from memory */
357 }
358