2a9f22713f72d9e350d5600954b5eb2000d28def
[reactos.git] / reactos / ntoskrnl / mm / mminit.c
1 /* $Id: mminit.c,v 1.25 2001/08/30 20:38:20 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/bitops.h>
20 #include <internal/io.h>
21 #include <internal/ps.h>
22 #include <napi/shared_data.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
51 PVOID MmSharedDataPagePhysicalAddress = NULL;
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(KERNEL_BASE + PAGE_ROUND_UP(kernel_len) + PAGESIZE);
90 ExInitNonPagedPool(LastKernelAddress + PAGESIZE);
91
92
93 /*
94 * Setup the system area descriptor list
95 */
96 BaseAddress = (PVOID)KERNEL_BASE;
97 Length = PAGE_ROUND_UP(((ULONG)&_text_end__)) - KERNEL_BASE;
98 ParamLength = ParamLength - Length;
99
100 MmLockAddressSpace(MmGetKernelAddressSpace());
101 MmCreateMemoryArea(NULL,
102 MmGetKernelAddressSpace(),
103 MEMORY_AREA_SYSTEM,
104 &BaseAddress,
105 Length,
106 0,
107 &kernel_text_desc,
108 FALSE);
109 MmUnlockAddressSpace(MmGetKernelAddressSpace());
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 MmLockAddressSpace(MmGetKernelAddressSpace());
118 MmCreateMemoryArea(NULL,
119 MmGetKernelAddressSpace(),
120 MEMORY_AREA_SYSTEM,
121 &BaseAddress,
122 Length,
123 0,
124 &kernel_data_desc,
125 FALSE);
126
127 BaseAddress = (PVOID)PAGE_ROUND_UP(((ULONG)&_bss_end__));
128 // Length = ParamLength;
129 Length = LastKernelAddress - (ULONG)BaseAddress;
130 MmCreateMemoryArea(NULL,
131 MmGetKernelAddressSpace(),
132 MEMORY_AREA_SYSTEM,
133 &BaseAddress,
134 Length,
135 0,
136 &kernel_param_desc,
137 FALSE);
138
139 BaseAddress = (PVOID)(LastKernelAddress + PAGESIZE);
140 Length = NONPAGED_POOL_SIZE;
141 MmCreateMemoryArea(NULL,
142 MmGetKernelAddressSpace(),
143 MEMORY_AREA_SYSTEM,
144 &BaseAddress,
145 Length,
146 0,
147 &kernel_pool_desc,
148 FALSE);
149
150 BaseAddress = (PVOID)KERNEL_SHARED_DATA_BASE;
151 Length = PAGESIZE;
152 MmCreateMemoryArea(NULL,
153 MmGetKernelAddressSpace(),
154 MEMORY_AREA_SYSTEM,
155 &BaseAddress,
156 Length,
157 0,
158 &kernel_shared_data_desc,
159 FALSE);
160 MmUnlockAddressSpace(MmGetKernelAddressSpace());
161 MmSharedDataPagePhysicalAddress = MmAllocPage(0);
162 Status = MmCreateVirtualMapping(NULL,
163 (PVOID)KERNEL_SHARED_DATA_BASE,
164 PAGE_READWRITE,
165 (ULONG)MmSharedDataPagePhysicalAddress);
166 if (!NT_SUCCESS(Status))
167 {
168 DbgPrint("Unable to create virtual mapping\n");
169 KeBugCheck(0);
170 }
171 ((PKUSER_SHARED_DATA)KERNEL_SHARED_DATA_BASE)->TickCountLow = 0xdeadbeef;
172 #if 0
173 for (i = 0; i < 0x100; i++)
174 {
175 Status = MmCreateVirtualMapping(NULL,
176 (PVOID)(i*PAGESIZE),
177 PAGE_READWRITE,
178 (ULONG)(i*PAGESIZE));
179 if (!NT_SUCCESS(Status))
180 {
181 DbgPrint("Unable to create virtual mapping\n");
182 KeBugCheck(0);
183 }
184 }
185 #endif
186 // MmDumpMemoryAreas();
187 DPRINT("MmInitVirtualMemory() done\n");
188 }
189
190 VOID MmInit1(ULONG FirstKrnlPhysAddr,
191 ULONG LastKrnlPhysAddr,
192 ULONG LastKernelAddress,
193 PADDRESS_RANGE BIOSMemoryMap,
194 ULONG AddressRangeCount)
195 /*
196 * FUNCTION: Initalize memory managment
197 */
198 {
199 ULONG i;
200 ULONG kernel_len;
201 #ifndef MP
202 extern unsigned int unmap_me, unmap_me2, unmap_me3;
203 #endif
204
205 DPRINT("MmInit1(FirstKrnlPhysAddr, %x, LastKrnlPhysAddr %x, LastKernelAddress %x)\n",
206 FirstKrnlPhysAddr,
207 LastKrnlPhysAddr,
208 LastKernelAddress);
209
210 if ((BIOSMemoryMap != NULL) && (AddressRangeCount > 0))
211 {
212 // If we have a bios memory map, recalulate the the memory size
213 ULONG last = 0;
214 for (i = 0; i < AddressRangeCount; i++)
215 {
216 if (BIOSMemoryMap[i].Type == 1
217 && (BIOSMemoryMap[i].BaseAddrLow + BIOSMemoryMap[i].LengthLow + PAGESIZE -1) / PAGESIZE > last)
218 {
219 last = (BIOSMemoryMap[i].BaseAddrLow + BIOSMemoryMap[i].LengthLow + PAGESIZE -1) / PAGESIZE;
220 }
221 }
222 if ((last - 256) * 4 > KeLoaderBlock.MemHigher)
223 {
224 KeLoaderBlock.MemHigher = (last - 256) * 4;
225 }
226 }
227
228 /*
229 * FIXME: Set this based on the system command line
230 */
231 MmUserProbeAddress = (PVOID)0x7fff0000;
232 MmHighestUserAddress = (PVOID)0x7ffeffff;
233
234 /*
235 * Initialize memory managment statistics
236 */
237 MmStats.NrTotalPages = 0;
238 MmStats.NrSystemPages = 0;
239 MmStats.NrUserPages = 0;
240 MmStats.NrReservedPages = 0;
241 MmStats.NrUserPages = 0;
242 MmStats.NrFreePages = 0;
243 MmStats.NrLockedPages = 0;
244 MmStats.PagingRequestsInLastMinute = 0;
245 MmStats.PagingRequestsInLastFiveMinutes = 0;
246 MmStats.PagingRequestsInLastFifteenMinutes = 0;
247
248 /*
249 * Initialize the kernel address space
250 */
251 MmInitializeKernelAddressSpace();
252
253 /*
254 * Unmap low memory
255 */
256 #ifndef MP
257 /* FIXME: This is broken in SMP mode */
258 //MmDeletePageTable(NULL, 0);
259 #endif
260 /*
261 * Free all pages not used for kernel memory
262 * (we assume the kernel occupies a continuous range of physical
263 * memory)
264 */
265 DPRINT("first krnl %x\nlast krnl %x\n",FirstKrnlPhysAddr,
266 LastKrnlPhysAddr);
267
268 /*
269 * Free physical memory not used by the kernel
270 */
271 MmStats.NrTotalPages = KeLoaderBlock.MemHigher/4;
272 if (!MmStats.NrTotalPages)
273 {
274 DbgPrint("Memory not detected, default to 8 MB\n");
275 MmStats.NrTotalPages = 2048;
276 }
277 else
278 {
279 /* add 1MB for standard memory (not extended) */
280 MmStats.NrTotalPages += 256;
281 }
282 #ifdef BIOS_MEM_FIX
283 MmStats.NrTotalPages += 16;
284 #endif
285 DbgPrint("Used memory %dKb\n", (MmStats.NrTotalPages * PAGESIZE) / 1024);
286
287 LastKernelAddress = (ULONG)MmInitializePageList(
288 (PVOID)FirstKrnlPhysAddr,
289 (PVOID)LastKrnlPhysAddr,
290 MmStats.NrTotalPages,
291 PAGE_ROUND_UP(LastKernelAddress),
292 BIOSMemoryMap,
293 AddressRangeCount);
294 kernel_len = LastKrnlPhysAddr - FirstKrnlPhysAddr;
295
296 /*
297 * Create a trap for null pointer references and protect text
298 * segment
299 */
300 CHECKPOINT;
301 DPRINT("_text_start__ %x _text_end__ %x\n",(int)&_text_start__,(int)&_text_end__);
302 for (i=PAGE_ROUND_UP(((int)&_text_start__));
303 i<PAGE_ROUND_DOWN(((int)&_text_end__));i=i+PAGESIZE)
304 {
305 MmSetPageProtect(NULL,
306 (PVOID)i,
307 PAGE_EXECUTE_READ);
308 }
309
310 DPRINT("Invalidating between %x and %x\n",
311 LastKernelAddress,
312 KERNEL_BASE + PAGE_TABLE_SIZE);
313 for (i=(LastKernelAddress);
314 i<(KERNEL_BASE + PAGE_TABLE_SIZE);
315 i=i+PAGESIZE)
316 {
317 MmDeleteVirtualMapping(NULL, (PVOID)(i), FALSE, NULL, NULL);
318 }
319 DPRINT("Almost done MmInit()\n");
320 #ifndef MP
321 /* FIXME: This is broken in SMP mode */
322 MmDeleteVirtualMapping(NULL, (PVOID)&unmap_me, FALSE, NULL, NULL);
323 MmDeleteVirtualMapping(NULL, (PVOID)&unmap_me2, FALSE, NULL, NULL);
324 MmDeleteVirtualMapping(NULL, (PVOID)&unmap_me3, FALSE, NULL, NULL);
325 #endif
326 /*
327 * Intialize memory areas
328 */
329 MmInitVirtualMemory(LastKernelAddress, kernel_len);
330 }
331
332 VOID MmInit2(VOID)
333 {
334 MmInitSectionImplementation();
335 MmInitPagingFile();
336 }
337
338 VOID MmInit3(VOID)
339 {
340 MmInitPagerThread();
341 MmCreatePhysicalMemorySection();
342
343 /* FIXME: Read parameters from memory */
344 }
345