2 * COPYRIGHT: See COPYING in the top directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/mm/mm.c
5 * PURPOSE: kernel memory managment functions
6 * PROGRAMMER: David Welch (welch@cwcom.net)
11 /* INCLUDES *****************************************************************/
13 #include <internal/hal/io.h>
14 #include <internal/i386/segment.h>
15 #include <internal/stddef.h>
16 #include <internal/mm.h>
18 #include <internal/string.h>
19 #include <internal/ntoskrnl.h>
20 #include <internal/bitops.h>
21 #include <internal/string.h>
22 #include <internal/io.h>
24 #include <internal/mmhal.h>
27 #include <internal/debug.h>
29 /* GLOBALS *****************************************************************/
32 * Size of extended memory (kb) (fixed for now)
34 #define EXTENDED_MEMORY_SIZE (3*1024*1024)
37 * Compiler defined symbol
39 extern unsigned int stext
;
40 extern unsigned int etext
;
41 extern unsigned int end
;
43 static BOOLEAN IsThisAnNtAsSystem
= FALSE
;
44 static MM_SYSTEM_SIZE MmSystemSize
= MmSmallSystem
;
46 extern unsigned int etext
;
47 extern unsigned int _bss_end__
;
49 static MEMORY_AREA
* kernel_text_desc
= NULL
;
50 static MEMORY_AREA
* kernel_data_desc
= NULL
;
51 static MEMORY_AREA
* kernel_param_desc
= NULL
;
52 static MEMORY_AREA
* kernel_pool_desc
= NULL
;
54 /* FUNCTIONS ****************************************************************/
56 VOID
MmInitVirtualMemory(boot_param
* bp
)
58 * FUNCTION: Intialize the memory areas list
60 * bp = Pointer to the boot parameters
61 * kernel_len = Length of the kernel
64 unsigned int kernel_len
= bp
->end_mem
- bp
->start_mem
;
67 ULONG ParamLength
= kernel_len
;
69 DPRINT("MmInitVirtualMemory(%x)\n",bp
);
72 ExInitNonPagedPool(KERNEL_BASE
+ PAGE_ROUND_UP(kernel_len
) + PAGESIZE
);
76 * Setup the system area descriptor list
78 BaseAddress
= (PVOID
)KERNEL_BASE
;
79 Length
= PAGE_ROUND_UP(((ULONG
)&etext
)) - KERNEL_BASE
;
80 ParamLength
= ParamLength
- Length
;
81 MmCreateMemoryArea(KernelMode
,NULL
,MEMORY_AREA_SYSTEM
,&BaseAddress
,
82 Length
,0,&kernel_text_desc
);
84 Length
= PAGE_ROUND_UP(((ULONG
)&_bss_end__
)) -
85 PAGE_ROUND_UP(((ULONG
)&etext
));
86 ParamLength
= ParamLength
- Length
;
87 DPRINT("Length %x\n",Length
);
88 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG
)&etext
));
89 DPRINT("BaseAddress %x\n",BaseAddress
);
90 MmCreateMemoryArea(KernelMode
,
98 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG
)&end
));
100 MmCreateMemoryArea(KernelMode
,NULL
,MEMORY_AREA_SYSTEM
,&BaseAddress
,
101 Length
,0,&kernel_param_desc
);
103 BaseAddress
= (PVOID
)(KERNEL_BASE
+ PAGE_ROUND_UP(kernel_len
) + PAGESIZE
);
104 Length
= NONPAGED_POOL_SIZE
;
105 MmCreateMemoryArea(KernelMode
,NULL
,MEMORY_AREA_SYSTEM
,&BaseAddress
,
106 Length
,0,&kernel_pool_desc
);
108 // MmDumpMemoryAreas();
111 // while (inb_p(0x60)!=0x1); inb_p(0x60);
113 MmInitSectionImplementation();
116 NTSTATUS
MmCommitedSectionHandleFault(MEMORY_AREA
* MemoryArea
, PVOID Address
)
118 MmSetPage(PsGetCurrentProcess(),
120 MemoryArea
->Attributes
,
121 (ULONG
)MmAllocPage());
122 return(STATUS_SUCCESS
);
125 NTSTATUS
MmSectionHandleFault(MEMORY_AREA
* MemoryArea
, PVOID Address
)
127 LARGE_INTEGER Offset
;
128 IO_STATUS_BLOCK IoStatus
;
130 DPRINT("MmSectionHandleFault(MemoryArea %x, Address %x)\n",
135 MemoryArea
->Attributes
,
136 (ULONG
)MmAllocPage());
138 Offset
.QuadPart
= (Address
- MemoryArea
->BaseAddress
) +
139 MemoryArea
->Data
.SectionData
.ViewOffset
;
141 DPRINT("MemoryArea->Data.SectionData.Section->FileObject %x\n",
142 MemoryArea
->Data
.SectionData
.Section
->FileObject
);
144 if (MemoryArea
->Data
.SectionData
.Section
->FileObject
== NULL
)
146 return(STATUS_UNSUCCESSFUL
);
149 IoPageRead(MemoryArea
->Data
.SectionData
.Section
->FileObject
,
154 DPRINT("Returning from MmSectionHandleFault()\n");
156 return(STATUS_SUCCESS
);
159 asmlinkage
int page_fault_handler(unsigned int cs
,
162 * FUNCTION: Handle a page fault
165 KPROCESSOR_MODE FaultMode
;
166 MEMORY_AREA
* MemoryArea
;
171 * Get the address for the page fault
174 __asm__("movl %%cr2,%0\n\t" : "=d" (cr2
));
175 DPRINT("Page fault at address %x with eip %x in process %x\n",cr2
,eip
,
176 PsGetCurrentProcess());
178 cr2
= PAGE_ROUND_DOWN(cr2
);
180 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
182 DbgPrint("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
187 KeRaiseIrql(DISPATCH_LEVEL
, &oldlvl
);
190 * Find the memory area for the faulting address
192 if (cr2
>= KERNEL_BASE
)
199 printk("%s:%d\n",__FILE__
,__LINE__
);
202 FaultMode
= UserMode
;
206 FaultMode
= KernelMode
;
209 MemoryArea
= MmOpenMemoryAreaByAddress(PsGetCurrentProcess(),(PVOID
)cr2
);
210 if (MemoryArea
== NULL
)
212 printk("%s:%d\n",__FILE__
,__LINE__
);
216 switch (MemoryArea
->Type
)
218 case MEMORY_AREA_SYSTEM
:
219 Status
= STATUS_UNSUCCESSFUL
;
222 case MEMORY_AREA_SECTION_VIEW_COMMIT
:
223 Status
= MmSectionHandleFault(MemoryArea
, (PVOID
)cr2
);
226 case MEMORY_AREA_COMMIT
:
227 Status
= MmCommitedSectionHandleFault(MemoryArea
,(PVOID
)cr2
);
231 Status
= STATUS_UNSUCCESSFUL
;
234 DPRINT("Completed page fault handling\n");
235 if (NT_SUCCESS(Status
))
239 return(NT_SUCCESS(Status
));
242 BOOLEAN
MmIsThisAnNtAsSystem(VOID
)
244 return(IsThisAnNtAsSystem
);
247 MM_SYSTEM_SIZE
MmQuerySystemSize(VOID
)
249 return(MmSystemSize
);
252 void MmInitialize(boot_param
* bp
, ULONG LastKernelAddress
)
254 * FUNCTION: Initalize memory managment
257 unsigned int first_krnl_phys_addr
;
258 unsigned int last_krnl_phys_addr
;
260 unsigned int kernel_len
;
262 DPRINT("MmInitialize(bp %x, LastKernelAddress %x)\n", bp
,
268 MmDeletePageTable(NULL
, 0);
271 * Free all pages not used for kernel memory
272 * (we assume the kernel occupies a continuous range of physical
275 first_krnl_phys_addr
= bp
->start_mem
;
276 last_krnl_phys_addr
= bp
->end_mem
;
277 DPRINT("first krnl %x\nlast krnl %x\n",first_krnl_phys_addr
,
278 last_krnl_phys_addr
);
281 * Free physical memory not used by the kernel
283 LastKernelAddress
= (ULONG
)MmInitializePageList(
284 (PVOID
)first_krnl_phys_addr
,
285 (PVOID
)last_krnl_phys_addr
,
287 PAGE_ROUND_UP(LastKernelAddress
));
288 kernel_len
= last_krnl_phys_addr
- first_krnl_phys_addr
;
291 * Create a trap for null pointer references and protect text
295 DPRINT("stext %x etext %x\n",(int)&stext
,(int)&etext
);
296 for (i
=PAGE_ROUND_UP(((int)&stext
));
297 i
<PAGE_ROUND_DOWN(((int)&etext
));i
=i
+PAGESIZE
)
299 MmSetPageProtect(NULL
,
304 DPRINT("Invalidating between %x and %x\n",
306 KERNEL_BASE
+ PAGE_TABLE_SIZE
);
307 for (i
=(LastKernelAddress
);
308 i
<(KERNEL_BASE
+ PAGE_TABLE_SIZE
);
311 MmSetPage(NULL
, (PVOID
)(i
), PAGE_NOACCESS
, 0);
313 DPRINT("Almost done MmInit()\n");
316 * Intialize memory areas
318 MmInitVirtualMemory(bp
);