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 <ddk/ntddk.h>
14 #include <internal/hal/io.h>
15 #include <internal/i386/segment.h>
16 #include <internal/stddef.h>
17 #include <internal/mm.h>
19 #include <internal/string.h>
20 #include <internal/ntoskrnl.h>
21 #include <internal/bitops.h>
22 #include <internal/string.h>
23 #include <internal/io.h>
25 #include <internal/mmhal.h>
28 #include <internal/debug.h>
30 /* GLOBALS *****************************************************************/
33 * Size of extended memory (kb) (fixed for now)
35 #define EXTENDED_MEMORY_SIZE (3*1024*1024)
38 * Compiler defined symbol
40 extern unsigned int stext
;
41 extern unsigned int etext
;
42 extern unsigned int end
;
44 static BOOLEAN IsThisAnNtAsSystem
= FALSE
;
45 static MM_SYSTEM_SIZE MmSystemSize
= MmSmallSystem
;
47 extern unsigned int etext
;
48 extern unsigned int _bss_end__
;
50 static MEMORY_AREA
* kernel_text_desc
= NULL
;
51 static MEMORY_AREA
* kernel_data_desc
= NULL
;
52 static MEMORY_AREA
* kernel_param_desc
= NULL
;
53 static MEMORY_AREA
* kernel_pool_desc
= NULL
;
55 /* FUNCTIONS ****************************************************************/
57 VOID
MmInitVirtualMemory(boot_param
* bp
)
59 * FUNCTION: Intialize the memory areas list
61 * bp = Pointer to the boot parameters
62 * kernel_len = Length of the kernel
65 unsigned int kernel_len
= bp
->end_mem
- bp
->start_mem
;
68 ULONG ParamLength
= kernel_len
;
70 DPRINT("MmInitVirtualMemory(%x)\n",bp
);
73 ExInitNonPagedPool(KERNEL_BASE
+ PAGE_ROUND_UP(kernel_len
) + PAGESIZE
);
77 * Setup the system area descriptor list
79 BaseAddress
= (PVOID
)KERNEL_BASE
;
80 Length
= PAGE_ROUND_UP(((ULONG
)&etext
)) - KERNEL_BASE
;
81 ParamLength
= ParamLength
- Length
;
82 MmCreateMemoryArea(KernelMode
,NULL
,MEMORY_AREA_SYSTEM
,&BaseAddress
,
83 Length
,0,&kernel_text_desc
);
85 Length
= PAGE_ROUND_UP(((ULONG
)&_bss_end__
)) -
86 PAGE_ROUND_UP(((ULONG
)&etext
));
87 ParamLength
= ParamLength
- Length
;
88 DPRINT("Length %x\n",Length
);
89 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG
)&etext
));
90 DPRINT("BaseAddress %x\n",BaseAddress
);
91 MmCreateMemoryArea(KernelMode
,
99 BaseAddress
= (PVOID
)PAGE_ROUND_UP(((ULONG
)&end
));
100 Length
= ParamLength
;
101 MmCreateMemoryArea(KernelMode
,NULL
,MEMORY_AREA_SYSTEM
,&BaseAddress
,
102 Length
,0,&kernel_param_desc
);
104 BaseAddress
= (PVOID
)(KERNEL_BASE
+ PAGE_ROUND_UP(kernel_len
) + PAGESIZE
);
105 Length
= NONPAGED_POOL_SIZE
;
106 MmCreateMemoryArea(KernelMode
,NULL
,MEMORY_AREA_SYSTEM
,&BaseAddress
,
107 Length
,0,&kernel_pool_desc
);
109 // MmDumpMemoryAreas();
112 // while (inb_p(0x60)!=0x1); inb_p(0x60);
114 MmInitSectionImplementation();
117 NTSTATUS
MmCommitedSectionHandleFault(MEMORY_AREA
* MemoryArea
, PVOID Address
)
119 MmSetPage(PsGetCurrentProcess(),
121 MemoryArea
->Attributes
,
122 (ULONG
)MmAllocPage());
123 return(STATUS_SUCCESS
);
126 NTSTATUS
MmSectionHandleFault(MEMORY_AREA
* MemoryArea
, PVOID Address
)
128 LARGE_INTEGER Offset
;
129 IO_STATUS_BLOCK IoStatus
;
131 DPRINT("MmSectionHandleFault(MemoryArea %x, Address %x)\n",
136 MemoryArea
->Attributes
,
137 (ULONG
)MmAllocPage());
139 Offset
.QuadPart
= (Address
- MemoryArea
->BaseAddress
) +
140 MemoryArea
->Data
.SectionData
.ViewOffset
;
142 DPRINT("MemoryArea->Data.SectionData.Section->FileObject %x\n",
143 MemoryArea
->Data
.SectionData
.Section
->FileObject
);
145 if (MemoryArea
->Data
.SectionData
.Section
->FileObject
== NULL
)
147 return(STATUS_UNSUCCESSFUL
);
150 IoPageRead(MemoryArea
->Data
.SectionData
.Section
->FileObject
,
155 DPRINT("Returning from MmSectionHandleFault()\n");
157 return(STATUS_SUCCESS
);
160 asmlinkage
int page_fault_handler(unsigned int cs
,
163 * FUNCTION: Handle a page fault
166 KPROCESSOR_MODE FaultMode
;
167 MEMORY_AREA
* MemoryArea
;
172 * Get the address for the page fault
175 __asm__("movl %%cr2,%0\n\t" : "=d" (cr2
));
176 DPRINT("Page fault at address %x with eip %x in process %x\n",cr2
,eip
,
177 PsGetCurrentProcess());
179 cr2
= PAGE_ROUND_DOWN(cr2
);
181 if (KeGetCurrentIrql() >= DISPATCH_LEVEL
)
183 DbgPrint("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
188 KeRaiseIrql(DISPATCH_LEVEL
, &oldlvl
);
191 * Find the memory area for the faulting address
193 if (cr2
>= KERNEL_BASE
)
200 printk("%s:%d\n",__FILE__
,__LINE__
);
203 FaultMode
= UserMode
;
207 FaultMode
= KernelMode
;
210 MemoryArea
= MmOpenMemoryAreaByAddress(PsGetCurrentProcess(),(PVOID
)cr2
);
211 if (MemoryArea
== NULL
)
213 printk("%s:%d\n",__FILE__
,__LINE__
);
217 switch (MemoryArea
->Type
)
219 case MEMORY_AREA_SYSTEM
:
220 Status
= STATUS_UNSUCCESSFUL
;
223 case MEMORY_AREA_SECTION_VIEW_COMMIT
:
224 Status
= MmSectionHandleFault(MemoryArea
, (PVOID
)cr2
);
227 case MEMORY_AREA_COMMIT
:
228 Status
= MmCommitedSectionHandleFault(MemoryArea
,(PVOID
)cr2
);
232 Status
= STATUS_UNSUCCESSFUL
;
235 DPRINT("Completed page fault handling\n");
236 if (NT_SUCCESS(Status
))
240 return(NT_SUCCESS(Status
));
243 BOOLEAN
MmIsThisAnNtAsSystem(VOID
)
245 return(IsThisAnNtAsSystem
);
248 MM_SYSTEM_SIZE
MmQuerySystemSize(VOID
)
250 return(MmSystemSize
);
253 void MmInitialize(boot_param
* bp
, ULONG LastKernelAddress
)
255 * FUNCTION: Initalize memory managment
258 unsigned int first_krnl_phys_addr
;
259 unsigned int last_krnl_phys_addr
;
261 unsigned int kernel_len
;
263 DPRINT("MmInitialize(bp %x, LastKernelAddress %x)\n", bp
,
269 MmDeletePageTable(NULL
, 0);
272 * Free all pages not used for kernel memory
273 * (we assume the kernel occupies a continuous range of physical
276 first_krnl_phys_addr
= bp
->start_mem
;
277 last_krnl_phys_addr
= bp
->end_mem
;
278 DPRINT("first krnl %x\nlast krnl %x\n",first_krnl_phys_addr
,
279 last_krnl_phys_addr
);
282 * Free physical memory not used by the kernel
284 LastKernelAddress
= (ULONG
)MmInitializePageList(
285 (PVOID
)first_krnl_phys_addr
,
286 (PVOID
)last_krnl_phys_addr
,
288 PAGE_ROUND_UP(LastKernelAddress
));
289 kernel_len
= last_krnl_phys_addr
- first_krnl_phys_addr
;
292 * Create a trap for null pointer references and protect text
296 DPRINT("stext %x etext %x\n",(int)&stext
,(int)&etext
);
297 for (i
=PAGE_ROUND_UP(((int)&stext
));
298 i
<PAGE_ROUND_DOWN(((int)&etext
));i
=i
+PAGESIZE
)
300 MmSetPageProtect(NULL
,
305 DPRINT("Invalidating between %x and %x\n",
307 KERNEL_BASE
+ PAGE_TABLE_SIZE
);
308 for (i
=(LastKernelAddress
);
309 i
<(KERNEL_BASE
+ PAGE_TABLE_SIZE
);
312 MmSetPage(NULL
, (PVOID
)(i
), PAGE_NOACCESS
, 0);
314 DPRINT("Almost done MmInit()\n");
317 * Intialize memory areas
319 MmInitVirtualMemory(bp
);