2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/mm/marea.c
5 * PURPOSE: Implements memory areas
6 * PROGRAMMER: David Welch (welch@mcmail.com)
11 /* INCLUDES *****************************************************************/
13 #include <ddk/ntddk.h>
14 #include <internal/mm.h>
15 #include <internal/mmhal.h>
18 #include <internal/debug.h>
20 /* FUNCTIONS *****************************************************************/
22 VOID
MmDumpMemoryAreas(PLIST_ENTRY ListHead
)
24 PLIST_ENTRY current_entry
;
27 DbgPrint("MmDumpMemoryAreas()\n");
29 current_entry
= ListHead
->Flink
;
30 while (current_entry
!=ListHead
)
32 current
= CONTAINING_RECORD(current_entry
,MEMORY_AREA
,Entry
);
33 DbgPrint("Base %x Length %x End %x Attributes %x Flink %x\n",
34 current
->BaseAddress
,current
->Length
,
35 current
->BaseAddress
+current
->Length
,current
->Attributes
,
36 current
->Entry
.Flink
);
37 current_entry
= current_entry
->Flink
;
39 DbgPrint("Finished MmDumpMemoryAreas()\n");
42 MEMORY_AREA
* MmOpenMemoryAreaByAddress(PMADDRESS_SPACE AddressSpace
,
45 PLIST_ENTRY current_entry
;
47 PLIST_ENTRY previous_entry
;
49 DPRINT("MmOpenMemoryAreaByAddress(AddressSpace %x, Address %x)\n",
50 AddressSpace
, Address
);
52 // MmDumpMemoryAreas(&AddressSpace->MAreaListHead);
54 previous_entry
= &AddressSpace
->MAreaListHead
;
55 current_entry
= AddressSpace
->MAreaListHead
.Flink
;
56 while (current_entry
!= &AddressSpace
->MAreaListHead
)
58 current
= CONTAINING_RECORD(current_entry
,
61 DPRINT("Scanning %x BaseAddress %x Length %x\n",
62 current
, current
->BaseAddress
, current
->Length
);
63 assert(current_entry
->Blink
->Flink
== current_entry
);
64 if (current_entry
->Flink
->Blink
!= current_entry
)
66 DPRINT("BaseAddress %x\n", current
->BaseAddress
);
67 DPRINT("current_entry->Flink %x ", current_entry
->Flink
);
68 DPRINT("¤t_entry->Flink %x\n",
69 ¤t_entry
->Flink
);
70 DPRINT("current_entry->Flink->Blink %x\n",
71 current_entry
->Flink
->Blink
);
72 DPRINT("¤t_entry->Flink->Blink %x\n",
73 ¤t_entry
->Flink
->Blink
);
74 DPRINT("¤t_entry->Flink %x\n",
75 ¤t_entry
->Flink
);
77 assert(current_entry
->Flink
->Blink
== current_entry
);
78 assert(previous_entry
->Flink
== current_entry
);
79 if (current
->BaseAddress
<= Address
&&
80 (current
->BaseAddress
+ current
->Length
) > Address
)
82 DPRINT("%s() = %x\n",__FUNCTION__
,current
);
85 if (current
->BaseAddress
> Address
)
87 DPRINT("%s() = NULL\n",__FUNCTION__
);
90 previous_entry
= current_entry
;
91 current_entry
= current_entry
->Flink
;
93 DPRINT("%s() = NULL\n",__FUNCTION__
);
97 MEMORY_AREA
* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace
,
101 PLIST_ENTRY current_entry
;
102 MEMORY_AREA
* current
;
105 DPRINT("MmOpenMemoryByRegion(AddressSpace %x, Address %x, Length %x)\n",
106 AddressSpace
, Address
, Length
);
108 current_entry
= AddressSpace
->MAreaListHead
.Flink
;
109 while (current_entry
!= &AddressSpace
->MAreaListHead
)
111 current
= CONTAINING_RECORD(current_entry
,
114 DPRINT("current->BaseAddress %x current->Length %x\n",
115 current
->BaseAddress
,current
->Length
);
116 if (current
->BaseAddress
>= Address
&&
117 current
->BaseAddress
< (Address
+Length
))
119 DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
123 Extent
= (ULONG
)current
->BaseAddress
+ current
->Length
;
124 if (Extent
> (ULONG
)Address
&&
125 Extent
< (ULONG
)(Address
+Length
))
127 DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
131 if (current
->BaseAddress
<= Address
&&
132 Extent
>= (ULONG
)(Address
+Length
))
134 DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
138 if (current
->BaseAddress
>= (Address
+Length
))
140 DPRINT("Finished MmOpenMemoryAreaByRegion()= NULL\n",0);
143 current_entry
= current_entry
->Flink
;
145 DPRINT("Finished MmOpenMemoryAreaByRegion() = NULL\n",0);
149 static VOID
MmInsertMemoryArea(PMADDRESS_SPACE AddressSpace
,
152 PLIST_ENTRY ListHead
;
153 PLIST_ENTRY current_entry
;
154 PLIST_ENTRY inserted_entry
= &marea
->Entry
;
155 MEMORY_AREA
* current
;
158 DPRINT("MmInsertMemoryArea(marea %x)\n", marea
);
159 DPRINT("marea->BaseAddress %x\n", marea
->BaseAddress
);
160 DPRINT("marea->Length %x\n", marea
->Length
);
162 ListHead
= &AddressSpace
->MAreaListHead
;
164 current_entry
= ListHead
->Flink
;
166 if (IsListEmpty(ListHead
))
169 InsertHeadList(ListHead
,&marea
->Entry
);
170 DPRINT("Inserting at list head\n");
175 current
= CONTAINING_RECORD(current_entry
,MEMORY_AREA
,Entry
);
177 if (current
->BaseAddress
> marea
->BaseAddress
)
180 InsertHeadList(ListHead
,&marea
->Entry
);
181 DPRINT("Inserting at list head\n");
186 while (current_entry
->Flink
!=ListHead
)
189 current
= CONTAINING_RECORD(current_entry
,MEMORY_AREA
,Entry
);
190 next
= CONTAINING_RECORD(current_entry
->Flink
,MEMORY_AREA
,Entry
);
191 // assert(current->BaseAddress != marea->BaseAddress);
192 // assert(next->BaseAddress != marea->BaseAddress);
193 if (current
->BaseAddress
< marea
->BaseAddress
&&
194 current
->Entry
.Flink
==ListHead
)
196 DPRINT("Insert after %x\n", current_entry
);
197 current_entry
->Flink
= inserted_entry
;
198 inserted_entry
->Flink
=ListHead
;
199 inserted_entry
->Blink
=current_entry
;
200 ListHead
->Blink
= inserted_entry
;
203 if (current
->BaseAddress
< marea
->BaseAddress
&&
204 next
->BaseAddress
> marea
->BaseAddress
)
206 DPRINT("Inserting before %x\n", current_entry
);
207 inserted_entry
->Flink
= current_entry
->Flink
;
208 inserted_entry
->Blink
= current_entry
;
209 inserted_entry
->Flink
->Blink
= inserted_entry
;
210 current_entry
->Flink
=inserted_entry
;
213 current_entry
= current_entry
->Flink
;
216 DPRINT("Inserting at list tail\n");
217 InsertTailList(ListHead
,inserted_entry
);
220 static PVOID
MmFindGap(PMADDRESS_SPACE AddressSpace
,
223 PLIST_ENTRY ListHead
;
224 PLIST_ENTRY current_entry
;
225 MEMORY_AREA
* current
;
229 DPRINT("MmFindGap(Length %x)\n",Length
);
231 ListHead
= &AddressSpace
->MAreaListHead
;
233 current_entry
= ListHead
->Flink
;
234 while (current_entry
->Flink
!=ListHead
)
236 current
= CONTAINING_RECORD(current_entry
,MEMORY_AREA
,Entry
);
237 next
= CONTAINING_RECORD(current_entry
->Flink
,MEMORY_AREA
,Entry
);
238 DPRINT("current %x current->BaseAddress %x ",current
,
239 current
->BaseAddress
);
240 DPRINT("current->Length %x\n",current
->Length
);
241 DPRINT("next %x next->BaseAddress %x ",next
,next
->BaseAddress
);
242 Gap
= (next
->BaseAddress
) -(current
->BaseAddress
+ current
->Length
);
243 DPRINT("Base %x Gap %x\n",current
->BaseAddress
,Gap
);
246 return(current
->BaseAddress
+ PAGE_ROUND_UP(current
->Length
));
248 current_entry
= current_entry
->Flink
;
251 if (current_entry
== ListHead
)
253 return((PVOID
)AddressSpace
->LowestAddress
);
256 current
= CONTAINING_RECORD(current_entry
,MEMORY_AREA
,Entry
);
257 //DbgPrint("current %x returning %x\n",current,current->BaseAddress+
259 return(current
->BaseAddress
+ PAGE_ROUND_UP(current
->Length
));
262 NTSTATUS
MmInitMemoryAreas(VOID
)
264 * FUNCTION: Initialize the memory area list
267 DPRINT("MmInitMemoryAreas()\n",0);
268 return(STATUS_SUCCESS
);
271 NTSTATUS
MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace
,
276 MEMORY_AREA
* MemoryArea
;
278 LARGE_INTEGER PhysicalAddr
;
280 DPRINT("MmFreeMemoryArea(AddressSpace %x, BaseAddress %x, Length %x,"
281 "FreePages %d)\n",AddressSpace
,BaseAddress
,Length
,FreePages
);
283 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
,
285 if (MemoryArea
== NULL
)
288 return(STATUS_UNSUCCESSFUL
);
292 for (i
=0;i
<=(MemoryArea
->Length
/PAGESIZE
);i
++)
294 PhysicalAddr
= MmGetPhysicalAddress(MemoryArea
->BaseAddress
+
296 MmDereferencePage((PVOID
)(ULONG
)(PhysicalAddr
.u
.LowPart
));
299 for (i
=0; i
<=(MemoryArea
->Length
/PAGESIZE
); i
++)
301 if (AddressSpace
->Process
!= NULL
)
303 DPRINT("Freeing %x in %d\n",
304 MemoryArea
->BaseAddress
+ (i
*PAGESIZE
),
305 AddressSpace
->Process
->UniqueProcessId
);
309 // DPRINT("Freeing %x in kernel address space\n");
311 MmSetPage(AddressSpace
->Process
,
312 MemoryArea
->BaseAddress
+ (i
*PAGESIZE
),
317 RemoveEntryList(&(MemoryArea
->Entry
));
318 ExFreePool(MemoryArea
);
320 DPRINT("MmFreeMemoryArea() succeeded\n");
322 return(STATUS_SUCCESS
);
325 PMEMORY_AREA
MmSplitMemoryArea(PEPROCESS Process
,
326 PMADDRESS_SPACE AddressSpace
,
327 PMEMORY_AREA OriginalMemoryArea
,
336 Result
= ExAllocatePool(NonPagedPool
,sizeof(MEMORY_AREA
));
337 RtlZeroMemory(Result
,sizeof(MEMORY_AREA
));
338 Result
->Type
= NewType
;
339 Result
->BaseAddress
= BaseAddress
;
340 Result
->Length
= Length
;
341 Result
->Attributes
= NewAttributes
;
342 Result
->LockCount
= 0;
343 Result
->Process
= Process
;
345 if (BaseAddress
== OriginalMemoryArea
->BaseAddress
)
347 OriginalMemoryArea
->BaseAddress
= BaseAddress
+ Length
;
348 OriginalMemoryArea
->Length
= OriginalMemoryArea
->Length
- Length
;
349 MmInsertMemoryArea(AddressSpace
, Result
);
352 if ((BaseAddress
+ Length
) ==
353 (OriginalMemoryArea
->BaseAddress
+ OriginalMemoryArea
->Length
))
355 OriginalMemoryArea
->Length
= OriginalMemoryArea
->Length
- Length
;
356 MmInsertMemoryArea(AddressSpace
, Result
);
361 Split
= ExAllocatePool(NonPagedPool
,sizeof(MEMORY_AREA
));
362 RtlCopyMemory(Split
,OriginalMemoryArea
,sizeof(MEMORY_AREA
));
363 Split
->BaseAddress
= BaseAddress
+ Length
;
364 Split
->Length
= OriginalMemoryArea
->Length
- (((ULONG
)BaseAddress
)
367 OriginalMemoryArea
->Length
= BaseAddress
- OriginalMemoryArea
->BaseAddress
;
372 NTSTATUS
MmCreateMemoryArea(PEPROCESS Process
,
373 PMADDRESS_SPACE AddressSpace
,
378 MEMORY_AREA
** Result
)
380 * FUNCTION: Create a memory area
382 * AddressSpace = Address space to create the area in
383 * Type = Type of the address space
385 * Length = Length to allocate
386 * Attributes = Protection attributes for the memory area
387 * Result = Receives a pointer to the memory area on exit
389 * NOTES: Lock the address space before calling this function
392 DPRINT("MmCreateMemoryArea(Type %d, BaseAddress %x,"
393 "*BaseAddress %x, Length %x, Attributes %x, Result %x)\n",
394 Type
,BaseAddress
,*BaseAddress
,Length
,Attributes
,Result
);
396 if ((*BaseAddress
)==0)
398 *BaseAddress
= MmFindGap(AddressSpace
,
399 PAGE_ROUND_UP(Length
) +(PAGESIZE
*2));
400 if ((*BaseAddress
)==0)
402 DPRINT("No suitable gap\n");
403 return(STATUS_UNSUCCESSFUL
);
405 (*BaseAddress
)=(*BaseAddress
)+PAGESIZE
;
409 (*BaseAddress
) = (PVOID
)PAGE_ROUND_DOWN((*BaseAddress
));
410 if (MmOpenMemoryAreaByRegion(AddressSpace
,
414 DPRINT("Memory area already occupied\n");
415 return(STATUS_UNSUCCESSFUL
);
419 *Result
= ExAllocatePool(NonPagedPool
,sizeof(MEMORY_AREA
));
420 RtlZeroMemory(*Result
,sizeof(MEMORY_AREA
));
421 (*Result
)->Type
= Type
;
422 (*Result
)->BaseAddress
= *BaseAddress
;
423 (*Result
)->Length
= Length
;
424 (*Result
)->Attributes
= Attributes
;
425 (*Result
)->LockCount
= 0;
426 (*Result
)->Process
= Process
;
428 MmInsertMemoryArea(AddressSpace
, *Result
);
430 DPRINT("MmCreateMemoryArea() succeeded\n");
431 return(STATUS_SUCCESS
);