:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / ntoskrnl / mm / mminit.c
1 /* $Id$
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 <internal/pool.h>
22
23 #define NDEBUG
24 #include <internal/debug.h>
25
26 /* GLOBALS *****************************************************************/
27
28 /*
29  * Size of extended memory (kb) (fixed for now)
30  */
31 #define EXTENDED_MEMORY_SIZE  (3*1024*1024)
32
33 /*
34  * Compiler defined symbols
35  */
36 extern unsigned int _text_start__;
37 extern unsigned int _text_end__;
38
39 static BOOLEAN IsThisAnNtAsSystem = FALSE;
40 static MM_SYSTEM_SIZE MmSystemSize = MmSmallSystem;
41
42 extern unsigned int _bss_end__;
43
44 static MEMORY_AREA* kernel_text_desc = NULL;
45 static MEMORY_AREA* kernel_data_desc = NULL;
46 static MEMORY_AREA* kernel_param_desc = NULL;
47 static MEMORY_AREA* kernel_pool_desc = NULL;
48 static MEMORY_AREA* kernel_shared_data_desc = NULL;
49 static MEMORY_AREA* MiPagedPoolDescriptor = NULL;
50
51 PHYSICAL_ADDRESS MmSharedDataPagePhysicalAddress;
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    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 * 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