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/ps.h>
16 #include <internal/pool.h>
19 #include <internal/debug.h>
21 /* GLOBALS *******************************************************************/
23 #define TAG_MAREA TAG('M', 'A', 'R', 'E')
25 /* FUNCTIONS *****************************************************************/
27 VOID
MmDumpMemoryAreas(PLIST_ENTRY ListHead
)
29 PLIST_ENTRY current_entry
;
32 DbgPrint("MmDumpMemoryAreas()\n");
34 current_entry
= ListHead
->Flink
;
35 while (current_entry
!=ListHead
)
37 current
= CONTAINING_RECORD(current_entry
,MEMORY_AREA
,Entry
);
38 DbgPrint("Base %x Length %x End %x Attributes %x Flink %x\n",
39 current
->BaseAddress
,current
->Length
,
40 current
->BaseAddress
+current
->Length
,current
->Attributes
,
41 current
->Entry
.Flink
);
42 current_entry
= current_entry
->Flink
;
44 DbgPrint("Finished MmDumpMemoryAreas()\n");
47 MEMORY_AREA
* MmOpenMemoryAreaByAddress(PMADDRESS_SPACE AddressSpace
,
50 PLIST_ENTRY current_entry
;
52 PLIST_ENTRY previous_entry
;
54 DPRINT("MmOpenMemoryAreaByAddress(AddressSpace %x, Address %x)\n",
55 AddressSpace
, Address
);
57 // MmDumpMemoryAreas(&AddressSpace->MAreaListHead);
59 previous_entry
= &AddressSpace
->MAreaListHead
;
60 current_entry
= AddressSpace
->MAreaListHead
.Flink
;
61 while (current_entry
!= &AddressSpace
->MAreaListHead
)
63 current
= CONTAINING_RECORD(current_entry
,
66 DPRINT("Scanning %x BaseAddress %x Length %x\n",
67 current
, current
->BaseAddress
, current
->Length
);
68 assert(current_entry
->Blink
->Flink
== current_entry
);
69 if (current_entry
->Flink
->Blink
!= current_entry
)
71 DPRINT1("BaseAddress %x\n", current
->BaseAddress
);
72 DPRINT1("current_entry->Flink %x ", current_entry
->Flink
);
73 DPRINT1("¤t_entry->Flink %x\n",
74 ¤t_entry
->Flink
);
75 DPRINT1("current_entry->Flink->Blink %x\n",
76 current_entry
->Flink
->Blink
);
77 DPRINT1("¤t_entry->Flink->Blink %x\n",
78 ¤t_entry
->Flink
->Blink
);
79 DPRINT1("¤t_entry->Flink %x\n",
80 ¤t_entry
->Flink
);
82 assert(current_entry
->Flink
->Blink
== current_entry
);
83 assert(previous_entry
->Flink
== current_entry
);
84 if (current
->BaseAddress
<= Address
&&
85 (current
->BaseAddress
+ current
->Length
) > Address
)
87 DPRINT("%s() = %x\n",__FUNCTION__
,current
);
90 if (current
->BaseAddress
> Address
)
92 DPRINT("%s() = NULL\n",__FUNCTION__
);
95 previous_entry
= current_entry
;
96 current_entry
= current_entry
->Flink
;
98 DPRINT("%s() = NULL\n",__FUNCTION__
);
102 MEMORY_AREA
* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace
,
106 PLIST_ENTRY current_entry
;
107 MEMORY_AREA
* current
;
110 DPRINT("MmOpenMemoryByRegion(AddressSpace %x, Address %x, Length %x)\n",
111 AddressSpace
, Address
, Length
);
113 current_entry
= AddressSpace
->MAreaListHead
.Flink
;
114 while (current_entry
!= &AddressSpace
->MAreaListHead
)
116 current
= CONTAINING_RECORD(current_entry
,
119 DPRINT("current->BaseAddress %x current->Length %x\n",
120 current
->BaseAddress
,current
->Length
);
121 if (current
->BaseAddress
>= Address
&&
122 current
->BaseAddress
< (Address
+Length
))
124 DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
128 Extent
= (ULONG
)current
->BaseAddress
+ current
->Length
;
129 if (Extent
> (ULONG
)Address
&&
130 Extent
< (ULONG
)(Address
+Length
))
132 DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
136 if (current
->BaseAddress
<= Address
&&
137 Extent
>= (ULONG
)(Address
+Length
))
139 DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
143 if (current
->BaseAddress
>= (Address
+Length
))
145 DPRINT("Finished MmOpenMemoryAreaByRegion()= NULL\n",0);
148 current_entry
= current_entry
->Flink
;
150 DPRINT("Finished MmOpenMemoryAreaByRegion() = NULL\n",0);
154 static VOID
MmInsertMemoryArea(PMADDRESS_SPACE AddressSpace
,
157 PLIST_ENTRY ListHead
;
158 PLIST_ENTRY current_entry
;
159 PLIST_ENTRY inserted_entry
= &marea
->Entry
;
160 MEMORY_AREA
* current
;
163 DPRINT("MmInsertMemoryArea(marea %x)\n", marea
);
164 DPRINT("marea->BaseAddress %x\n", marea
->BaseAddress
);
165 DPRINT("marea->Length %x\n", marea
->Length
);
167 ListHead
= &AddressSpace
->MAreaListHead
;
169 current_entry
= ListHead
->Flink
;
171 if (IsListEmpty(ListHead
))
174 InsertHeadList(ListHead
,&marea
->Entry
);
175 DPRINT("Inserting at list head\n");
180 current
= CONTAINING_RECORD(current_entry
,MEMORY_AREA
,Entry
);
182 if (current
->BaseAddress
> marea
->BaseAddress
)
185 InsertHeadList(ListHead
,&marea
->Entry
);
186 DPRINT("Inserting at list head\n");
191 while (current_entry
->Flink
!=ListHead
)
194 current
= CONTAINING_RECORD(current_entry
,MEMORY_AREA
,Entry
);
195 next
= CONTAINING_RECORD(current_entry
->Flink
,MEMORY_AREA
,Entry
);
196 // assert(current->BaseAddress != marea->BaseAddress);
197 // assert(next->BaseAddress != marea->BaseAddress);
198 if (current
->BaseAddress
< marea
->BaseAddress
&&
199 current
->Entry
.Flink
==ListHead
)
201 DPRINT("Insert after %x\n", current_entry
);
202 current_entry
->Flink
= inserted_entry
;
203 inserted_entry
->Flink
=ListHead
;
204 inserted_entry
->Blink
=current_entry
;
205 ListHead
->Blink
= inserted_entry
;
208 if (current
->BaseAddress
< marea
->BaseAddress
&&
209 next
->BaseAddress
> marea
->BaseAddress
)
211 DPRINT("Inserting before %x\n", current_entry
);
212 inserted_entry
->Flink
= current_entry
->Flink
;
213 inserted_entry
->Blink
= current_entry
;
214 inserted_entry
->Flink
->Blink
= inserted_entry
;
215 current_entry
->Flink
=inserted_entry
;
218 current_entry
= current_entry
->Flink
;
221 DPRINT("Inserting at list tail\n");
222 InsertTailList(ListHead
,inserted_entry
);
225 static PVOID
MmFindGap(PMADDRESS_SPACE AddressSpace
,
228 PLIST_ENTRY ListHead
;
229 PLIST_ENTRY current_entry
;
230 MEMORY_AREA
* current
;
234 DPRINT("MmFindGap(Length %x)\n",Length
);
236 ListHead
= &AddressSpace
->MAreaListHead
;
238 current_entry
= ListHead
->Flink
;
239 while (current_entry
->Flink
!=ListHead
)
241 current
= CONTAINING_RECORD(current_entry
,MEMORY_AREA
,Entry
);
242 next
= CONTAINING_RECORD(current_entry
->Flink
,MEMORY_AREA
,Entry
);
243 DPRINT("current %x current->BaseAddress %x ",current
,
244 current
->BaseAddress
);
245 DPRINT("current->Length %x\n",current
->Length
);
246 DPRINT("next %x next->BaseAddress %x ",next
,next
->BaseAddress
);
247 Gap
= (next
->BaseAddress
) -(current
->BaseAddress
+ current
->Length
);
248 DPRINT("Base %x Gap %x\n",current
->BaseAddress
,Gap
);
251 return(current
->BaseAddress
+ PAGE_ROUND_UP(current
->Length
));
253 current_entry
= current_entry
->Flink
;
256 if (current_entry
== ListHead
)
258 return((PVOID
)AddressSpace
->LowestAddress
);
261 current
= CONTAINING_RECORD(current_entry
,MEMORY_AREA
,Entry
);
262 //DbgPrint("current %x returning %x\n",current,current->BaseAddress+
264 return(current
->BaseAddress
+ PAGE_ROUND_UP(current
->Length
));
267 NTSTATUS
MmInitMemoryAreas(VOID
)
269 * FUNCTION: Initialize the memory area list
272 DPRINT("MmInitMemoryAreas()\n",0);
273 return(STATUS_SUCCESS
);
277 MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace
,
280 VOID (*FreePage
)(PVOID Context
, PVOID Address
,
282 PVOID FreePageContext
)
284 MEMORY_AREA
* MemoryArea
;
287 DPRINT("MmFreeMemoryArea(AddressSpace %x, BaseAddress %x, Length %x,"
288 "FreePages %d)\n",AddressSpace
,BaseAddress
,Length
,FreePages
);
290 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
,
292 if (MemoryArea
== NULL
)
295 return(STATUS_UNSUCCESSFUL
);
297 for (i
=0; i
<(PAGE_ROUND_UP(MemoryArea
->Length
)/PAGESIZE
); i
++)
302 MmGetPhysicalAddressForProcess(AddressSpace
->Process
,
303 MemoryArea
->BaseAddress
+ (i
*PAGESIZE
));
304 MmDeleteVirtualMapping(AddressSpace
->Process
,
305 MemoryArea
->BaseAddress
+ (i
*PAGESIZE
),
307 if (FreePage
!= NULL
)
309 FreePage(FreePageContext
,
310 MemoryArea
->BaseAddress
+ (i
* PAGESIZE
), PhysAddr
);
314 RemoveEntryList(&MemoryArea
->Entry
);
315 ExFreePool(MemoryArea
);
317 DPRINT("MmFreeMemoryArea() succeeded\n");
319 return(STATUS_SUCCESS
);
322 PMEMORY_AREA
MmSplitMemoryArea(PEPROCESS Process
,
323 PMADDRESS_SPACE AddressSpace
,
324 PMEMORY_AREA OriginalMemoryArea
,
333 Result
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(MEMORY_AREA
),
335 RtlZeroMemory(Result
,sizeof(MEMORY_AREA
));
336 Result
->Type
= NewType
;
337 Result
->BaseAddress
= BaseAddress
;
338 Result
->Length
= Length
;
339 Result
->Attributes
= NewAttributes
;
340 Result
->LockCount
= 0;
341 Result
->Process
= Process
;
343 if (BaseAddress
== OriginalMemoryArea
->BaseAddress
)
345 OriginalMemoryArea
->BaseAddress
= BaseAddress
+ Length
;
346 OriginalMemoryArea
->Length
= OriginalMemoryArea
->Length
- Length
;
347 MmInsertMemoryArea(AddressSpace
, Result
);
350 if ((BaseAddress
+ Length
) ==
351 (OriginalMemoryArea
->BaseAddress
+ OriginalMemoryArea
->Length
))
353 OriginalMemoryArea
->Length
= OriginalMemoryArea
->Length
- Length
;
354 MmInsertMemoryArea(AddressSpace
, Result
);
359 Split
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(MEMORY_AREA
),
361 RtlCopyMemory(Split
,OriginalMemoryArea
,sizeof(MEMORY_AREA
));
362 Split
->BaseAddress
= BaseAddress
+ Length
;
363 Split
->Length
= OriginalMemoryArea
->Length
- (((ULONG
)BaseAddress
)
366 OriginalMemoryArea
->Length
= BaseAddress
- OriginalMemoryArea
->BaseAddress
;
371 NTSTATUS
MmCreateMemoryArea(PEPROCESS Process
,
372 PMADDRESS_SPACE AddressSpace
,
377 MEMORY_AREA
** Result
)
379 * FUNCTION: Create a memory area
381 * AddressSpace = Address space to create the area in
382 * Type = Type of the address space
384 * Length = Length to allocate
385 * Attributes = Protection attributes for the memory area
386 * Result = Receives a pointer to the memory area on exit
388 * NOTES: Lock the address space before calling this function
391 DPRINT("MmCreateMemoryArea(Type %d, BaseAddress %x,"
392 "*BaseAddress %x, Length %x, Attributes %x, Result %x)\n",
393 Type
,BaseAddress
,*BaseAddress
,Length
,Attributes
,Result
);
395 if ((*BaseAddress
)==0)
397 *BaseAddress
= MmFindGap(AddressSpace
,
398 PAGE_ROUND_UP(Length
) +(PAGESIZE
*2));
399 if ((*BaseAddress
)==0)
401 DPRINT("No suitable gap\n");
402 return(STATUS_UNSUCCESSFUL
);
404 (*BaseAddress
)=(*BaseAddress
)+PAGESIZE
;
408 (*BaseAddress
) = (PVOID
)PAGE_ROUND_DOWN((*BaseAddress
));
409 if (MmOpenMemoryAreaByRegion(AddressSpace
,
413 DPRINT("Memory area already occupied\n");
414 return(STATUS_UNSUCCESSFUL
);
418 *Result
= ExAllocatePoolWithTag(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
);