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
,
102 PLIST_ENTRY current_entry
;
103 MEMORY_AREA
* current
;
106 DPRINT("MmOpenMemoryByRegion(AddressSpace %x, Address %x, Length %x)\n",
107 AddressSpace
, Address
, Length
);
109 current_entry
= AddressSpace
->MAreaListHead
.Flink
;
110 while (current_entry
!= &AddressSpace
->MAreaListHead
)
112 current
= CONTAINING_RECORD(current_entry
,
115 DPRINT("current->BaseAddress %x current->Length %x\n",
116 current
->BaseAddress
,current
->Length
);
117 if (current
->BaseAddress
>= Address
&&
118 current
->BaseAddress
< (Address
+Length
))
120 DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
124 Extent
= (ULONG
)current
->BaseAddress
+ current
->Length
;
125 if (Extent
> (ULONG
)Address
&&
126 Extent
< (ULONG
)(Address
+Length
))
128 DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
132 if (current
->BaseAddress
<= Address
&&
133 Extent
>= (ULONG
)(Address
+Length
))
135 DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
139 if (current
->BaseAddress
>= (Address
+Length
))
141 DPRINT("Finished MmOpenMemoryAreaByRegion()= NULL\n",0);
144 current_entry
= current_entry
->Flink
;
146 DPRINT("Finished MmOpenMemoryAreaByRegion() = NULL\n",0);
152 static VOID
MmInsertMemoryArea(PMADDRESS_SPACE AddressSpace
,
155 PLIST_ENTRY ListHead
;
156 PLIST_ENTRY current_entry
;
157 PLIST_ENTRY inserted_entry
= &marea
->Entry
;
158 MEMORY_AREA
* current
;
161 DPRINT("MmInsertMemoryArea(marea %x)\n", marea
);
162 DPRINT("marea->BaseAddress %x\n", marea
->BaseAddress
);
163 DPRINT("marea->Length %x\n", marea
->Length
);
165 ListHead
= &AddressSpace
->MAreaListHead
;
167 current_entry
= ListHead
->Flink
;
169 if (IsListEmpty(ListHead
))
172 InsertHeadList(ListHead
,&marea
->Entry
);
173 DPRINT("Inserting at list head\n");
178 current
= CONTAINING_RECORD(current_entry
,MEMORY_AREA
,Entry
);
180 if (current
->BaseAddress
> marea
->BaseAddress
)
183 InsertHeadList(ListHead
,&marea
->Entry
);
184 DPRINT("Inserting at list head\n");
189 while (current_entry
->Flink
!=ListHead
)
192 current
= CONTAINING_RECORD(current_entry
,MEMORY_AREA
,Entry
);
193 next
= CONTAINING_RECORD(current_entry
->Flink
,MEMORY_AREA
,Entry
);
194 // assert(current->BaseAddress != marea->BaseAddress);
195 // assert(next->BaseAddress != marea->BaseAddress);
196 if (current
->BaseAddress
< marea
->BaseAddress
&&
197 current
->Entry
.Flink
==ListHead
)
199 DPRINT("Insert after %x\n", current_entry
);
200 current_entry
->Flink
= inserted_entry
;
201 inserted_entry
->Flink
=ListHead
;
202 inserted_entry
->Blink
=current_entry
;
203 ListHead
->Blink
= inserted_entry
;
206 if (current
->BaseAddress
< marea
->BaseAddress
&&
207 next
->BaseAddress
> marea
->BaseAddress
)
209 DPRINT("Inserting before %x\n", current_entry
);
210 inserted_entry
->Flink
= current_entry
->Flink
;
211 inserted_entry
->Blink
= current_entry
;
212 inserted_entry
->Flink
->Blink
= inserted_entry
;
213 current_entry
->Flink
=inserted_entry
;
216 current_entry
= current_entry
->Flink
;
219 DPRINT("Inserting at list tail\n");
220 InsertTailList(ListHead
,inserted_entry
);
223 static PVOID
MmFindGap(PMADDRESS_SPACE AddressSpace
,
226 PLIST_ENTRY ListHead
;
227 PLIST_ENTRY current_entry
;
228 MEMORY_AREA
* current
;
232 DPRINT("MmFindGap(Length %x)\n",Length
);
234 ListHead
= &AddressSpace
->MAreaListHead
;
236 current_entry
= ListHead
->Flink
;
237 while (current_entry
->Flink
!=ListHead
)
239 current
= CONTAINING_RECORD(current_entry
,MEMORY_AREA
,Entry
);
240 next
= CONTAINING_RECORD(current_entry
->Flink
,MEMORY_AREA
,Entry
);
241 DPRINT("current %x current->BaseAddress %x ",current
,
242 current
->BaseAddress
);
243 DPRINT("current->Length %x\n",current
->Length
);
244 DPRINT("next %x next->BaseAddress %x ",next
,next
->BaseAddress
);
245 Gap
= (next
->BaseAddress
) -(current
->BaseAddress
+ current
->Length
);
246 DPRINT("Base %x Gap %x\n",current
->BaseAddress
,Gap
);
249 return(current
->BaseAddress
+ PAGE_ROUND_UP(current
->Length
));
251 current_entry
= current_entry
->Flink
;
254 if (current_entry
== ListHead
)
256 return((PVOID
)AddressSpace
->LowestAddress
);
259 current
= CONTAINING_RECORD(current_entry
,MEMORY_AREA
,Entry
);
260 //DbgPrint("current %x returning %x\n",current,current->BaseAddress+
262 return(current
->BaseAddress
+ PAGE_ROUND_UP(current
->Length
));
265 NTSTATUS
MmInitMemoryAreas(VOID
)
267 * FUNCTION: Initialize the memory area list
270 DPRINT("MmInitMemoryAreas()\n",0);
271 return(STATUS_SUCCESS
);
274 NTSTATUS
MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace
,
279 MEMORY_AREA
* MemoryArea
;
281 LARGE_INTEGER PhysicalAddr
;
283 DPRINT("MmFreeMemoryArea(AddressSpace %x, BaseAddress %x, Length %x,"
284 "FreePages %d)\n",AddressSpace
,BaseAddress
,Length
,FreePages
);
286 MemoryArea
= MmOpenMemoryAreaByAddress(AddressSpace
,
288 if (MemoryArea
== NULL
)
291 return(STATUS_UNSUCCESSFUL
);
295 for (i
=0;i
<=(MemoryArea
->Length
/PAGESIZE
);i
++)
297 PhysicalAddr
= MmGetPhysicalAddress(MemoryArea
->BaseAddress
+
299 MmDereferencePage((PVOID
)(ULONG
)(PhysicalAddr
.u
.LowPart
));
302 for (i
=0; i
<=(MemoryArea
->Length
/PAGESIZE
); i
++)
304 if (AddressSpace
->Process
!= NULL
)
306 DPRINT("Freeing %x in %d\n",
307 MemoryArea
->BaseAddress
+ (i
*PAGESIZE
),
308 AddressSpace
->Process
->UniqueProcessId
);
312 // DPRINT("Freeing %x in kernel address space\n");
314 MmSetPage(AddressSpace
->Process
,
315 MemoryArea
->BaseAddress
+ (i
*PAGESIZE
),
320 RemoveEntryList(&(MemoryArea
->Entry
));
321 ExFreePool(MemoryArea
);
323 DPRINT("MmFreeMemoryArea() succeeded\n");
325 return(STATUS_SUCCESS
);
328 PMEMORY_AREA
MmSplitMemoryArea(PEPROCESS Process
,
329 PMADDRESS_SPACE AddressSpace
,
330 PMEMORY_AREA OriginalMemoryArea
,
339 Result
= ExAllocatePool(NonPagedPool
,sizeof(MEMORY_AREA
));
340 RtlZeroMemory(Result
,sizeof(MEMORY_AREA
));
341 Result
->Type
= NewType
;
342 Result
->BaseAddress
= BaseAddress
;
343 Result
->Length
= Length
;
344 Result
->Attributes
= NewAttributes
;
345 Result
->LockCount
= 0;
346 Result
->Process
= Process
;
348 if (BaseAddress
== OriginalMemoryArea
->BaseAddress
)
350 OriginalMemoryArea
->BaseAddress
= BaseAddress
+ Length
;
351 OriginalMemoryArea
->Length
= OriginalMemoryArea
->Length
- Length
;
352 MmInsertMemoryArea(AddressSpace
, Result
);
355 if ((BaseAddress
+ Length
) ==
356 (OriginalMemoryArea
->BaseAddress
+ OriginalMemoryArea
->Length
))
358 OriginalMemoryArea
->Length
= OriginalMemoryArea
->Length
- Length
;
359 MmInsertMemoryArea(AddressSpace
, Result
);
364 Split
= ExAllocatePool(NonPagedPool
,sizeof(MEMORY_AREA
));
365 RtlCopyMemory(Split
,OriginalMemoryArea
,sizeof(MEMORY_AREA
));
366 Split
->BaseAddress
= BaseAddress
+ Length
;
367 Split
->Length
= OriginalMemoryArea
->Length
- (((ULONG
)BaseAddress
)
370 OriginalMemoryArea
->Length
= BaseAddress
- OriginalMemoryArea
->BaseAddress
;
375 NTSTATUS
MmCreateMemoryArea(PEPROCESS Process
,
376 PMADDRESS_SPACE AddressSpace
,
381 MEMORY_AREA
** Result
)
383 * FUNCTION: Create a memory area
385 * AddressSpace = Address space to create the area in
386 * Type = Type of the address space
388 * Length = Length to allocate
389 * Attributes = Protection attributes for the memory area
390 * Result = Receives a pointer to the memory area on exit
392 * NOTES: Lock the address space before calling this function
395 DPRINT("MmCreateMemoryArea(Type %d, BaseAddress %x,"
396 "*BaseAddress %x, Length %x, Attributes %x, Result %x)\n",
397 Type
,BaseAddress
,*BaseAddress
,Length
,Attributes
,Result
);
399 if ((*BaseAddress
)==0)
401 *BaseAddress
= MmFindGap(AddressSpace
,
402 PAGE_ROUND_UP(Length
) +(PAGESIZE
*2));
403 if ((*BaseAddress
)==0)
405 DPRINT("No suitable gap\n");
406 return(STATUS_UNSUCCESSFUL
);
408 (*BaseAddress
)=(*BaseAddress
)+PAGESIZE
;
412 (*BaseAddress
) = (PVOID
)PAGE_ROUND_DOWN((*BaseAddress
));
413 if (MmOpenMemoryAreaByRegion(AddressSpace
,
417 DPRINT("Memory area already occupied\n");
418 return(STATUS_UNSUCCESSFUL
);
422 *Result
= ExAllocatePool(NonPagedPool
,sizeof(MEMORY_AREA
));
423 RtlZeroMemory(*Result
,sizeof(MEMORY_AREA
));
424 (*Result
)->Type
= Type
;
425 (*Result
)->BaseAddress
= *BaseAddress
;
426 (*Result
)->Length
= Length
;
427 (*Result
)->Attributes
= Attributes
;
428 (*Result
)->LockCount
= 0;
429 (*Result
)->Process
= Process
;
431 MmInsertMemoryArea(AddressSpace
, *Result
);
433 DPRINT("MmCreateMemoryArea() succeeded\n");
434 return(STATUS_SUCCESS
);