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 /* GLOBALS *******************************************************************/
22 static LIST_ENTRY SystemAreaList
= {NULL
,NULL
};
23 static KSPIN_LOCK SystemAreaListLock
= {0,};
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 VOID
MmLockMemoryAreaList(PVOID Address
, PKIRQL oldlvl
)
49 if (Address
>= (PVOID
)KERNEL_BASE
)
51 KeAcquireSpinLock(&SystemAreaListLock
,oldlvl
);
55 PKPROCESS CurrentProcess
= KeGetCurrentProcess();
57 KeAcquireSpinLock(&(CurrentProcess
->SpinLock
),oldlvl
);
61 VOID
MmUnlockMemoryAreaList(PVOID Address
, PKIRQL oldlvl
)
63 if (Address
>= (PVOID
)KERNEL_BASE
)
65 KeReleaseSpinLock(&SystemAreaListLock
,*oldlvl
);
69 PKPROCESS CurrentProcess
= KeGetCurrentProcess();
70 KeReleaseSpinLock(&(CurrentProcess
->SpinLock
),*oldlvl
);
75 VOID
MmLockMemoryAreaListByMode(KPROCESSOR_MODE Mode
, PKIRQL oldlvl
)
77 if (Mode
== KernelMode
)
79 KeAcquireSpinLock(&SystemAreaListLock
,oldlvl
);
83 PKPROCESS CurrentProcess
= KeGetCurrentProcess();
85 KeAcquireSpinLock(&(CurrentProcess
->SpinLock
),oldlvl
);
89 VOID
MmUnlockMemoryAreaListByMode(KPROCESSOR_MODE Mode
, PKIRQL oldlvl
)
91 if (Mode
== KernelMode
)
93 KeReleaseSpinLock(&SystemAreaListLock
,*oldlvl
);
97 PKPROCESS CurrentProcess
= KeGetCurrentProcess();
98 KeReleaseSpinLock(&(CurrentProcess
->SpinLock
),*oldlvl
);
104 static PLIST_ENTRY
MmGetRelatedListHead(PEPROCESS Process
, PVOID BaseAddress
)
106 if (BaseAddress
>= (PVOID
)KERNEL_BASE
)
108 return(&SystemAreaList
);
112 return(&(Process
->Pcb
.MemoryAreaList
));
116 static MEMORY_AREA
* MmInternalOpenMemoryAreaByAddress(PLIST_ENTRY ListHead
,
119 PLIST_ENTRY current_entry
;
120 MEMORY_AREA
* current
;
121 PLIST_ENTRY previous_entry
;
123 // MmDumpMemoryAreas();
125 DPRINT("MmInternalOpenMemoryAreaByAddress(ListHead %x, Address %x)\n",
133 previous_entry
= ListHead
;
134 current_entry
= ListHead
->Flink
;
135 while (current_entry
!=ListHead
)
137 current
= CONTAINING_RECORD(current_entry
,MEMORY_AREA
,Entry
);
138 DPRINT("Scanning %x BaseAddress %x Length %x\n",
139 current
, current
->BaseAddress
, current
->Length
);
140 assert(current_entry
->Blink
->Flink
== current_entry
);
141 assert(current_entry
->Flink
->Blink
== current_entry
);
142 assert(previous_entry
->Flink
== current_entry
);
143 if (current
->BaseAddress
<= Address
&&
144 (current
->BaseAddress
+ current
->Length
) > Address
)
146 DPRINT("%s() = %x\n",__FUNCTION__
,current
);
149 if (current
->BaseAddress
> Address
)
151 DPRINT("%s() = NULL\n",__FUNCTION__
);
154 previous_entry
= current_entry
;
155 current_entry
= current_entry
->Flink
;
157 DPRINT("%s() = NULL\n",__FUNCTION__
);
162 MEMORY_AREA
* MmInternalOpenMemoryAreaByRegion(PLIST_ENTRY ListHead
,
166 PLIST_ENTRY current_entry
;
167 MEMORY_AREA
* current
;
170 DPRINT("MmInternalOpenMemoryAreaByRegion(ListHead %x, Address %x, "
171 "Length %x)\n",ListHead
,Address
,Length
);
173 // MmDumpMemoryAreas();
175 current_entry
= ListHead
->Flink
;
176 while (current_entry
!=ListHead
)
178 current
= CONTAINING_RECORD(current_entry
,MEMORY_AREA
,Entry
);
179 DPRINT("current->BaseAddress %x current->Length %x\n",
180 current
->BaseAddress
,current
->Length
);
181 if (current
->BaseAddress
>= Address
&&
182 current
->BaseAddress
<= (Address
+Length
))
184 DPRINT("Finished MmInternalOpenMemoryAreaByRegion() = %x\n",
188 Extent
= (ULONG
)current
->BaseAddress
+ current
->Length
;
189 if (Extent
> (ULONG
)Address
&&
190 Extent
< (ULONG
)(Address
+Length
))
192 DPRINT("Finished MmInternalOpenMemoryAreaByRegion() = %x\n",
196 if (current
->BaseAddress
<= Address
&&
197 Extent
>= (ULONG
)(Address
+Length
))
199 DPRINT("Finished MmInternalOpenMemoryAreaByRegion() = %x\n",
203 if (current
->BaseAddress
>= (Address
+Length
))
205 DPRINT("Finished MmInternalOpenMemoryAreaByRegion()= NULL\n",0);
208 current_entry
= current_entry
->Flink
;
210 DPRINT("Finished MmInternalOpenMemoryAreaByRegion() = NULL\n",0);
214 MEMORY_AREA
* MmOpenMemoryAreaByRegion(PEPROCESS Process
,
220 PLIST_ENTRY ListHead
;
222 DPRINT("MmOpenMemoryByRegion(Process %x, Address %x, Length %x)\n",
223 Process
,Address
,Length
);
225 MmLockMemoryAreaList(Address
,&oldlvl
);
226 ListHead
= MmGetRelatedListHead(Process
,Address
);
227 Result
= MmInternalOpenMemoryAreaByRegion(ListHead
,Address
,Length
);
228 MmUnlockMemoryAreaList(Address
,&oldlvl
);
233 MEMORY_AREA
* MmOpenMemoryAreaByRegionWithoutLock(PEPROCESS Process
,
238 PLIST_ENTRY ListHead
;
240 ListHead
= MmGetRelatedListHead(Process
, Address
);
241 Result
= MmInternalOpenMemoryAreaByRegion(ListHead
,Address
,Length
);
245 MEMORY_AREA
* MmOpenMemoryAreaByAddress(PEPROCESS Process
, PVOID Address
)
249 PLIST_ENTRY ListHead
;
251 DPRINT("MmOpenMemoryAreaByAddress(Address %x)\n",Address
);
253 MmLockMemoryAreaList(Address
,&oldlvl
);
254 ListHead
= MmGetRelatedListHead(Process
, Address
);
255 Result
= MmInternalOpenMemoryAreaByAddress(ListHead
,Address
);
256 MmUnlockMemoryAreaList(Address
,&oldlvl
);
260 MEMORY_AREA
* MmOpenMemoryAreaByAddressWithoutLock(PEPROCESS Process
,
264 PLIST_ENTRY ListHead
;
266 ListHead
= MmGetRelatedListHead(Process
, Address
);
267 Result
= MmInternalOpenMemoryAreaByAddress(ListHead
, Address
);
271 static VOID
MmInsertMemoryAreaWithoutLock(PEPROCESS Process
,
274 PLIST_ENTRY ListHead
;
275 PLIST_ENTRY current_entry
;
276 PLIST_ENTRY inserted_entry
= &(marea
->Entry
);
277 MEMORY_AREA
* current
;
280 DPRINT("MmInsertMemoryAreaWithoutLock(marea %x)\n",marea
);
281 DPRINT("marea->BaseAddress %x\n",marea
->BaseAddress
);
282 DPRINT("marea->Length %x\n",marea
->Length
);
284 ListHead
=MmGetRelatedListHead(Process
,marea
->BaseAddress
);
285 current_entry
= ListHead
->Flink
;
287 if (IsListEmpty(ListHead
))
290 InsertHeadList(ListHead
,&marea
->Entry
);
295 current
= CONTAINING_RECORD(current_entry
,MEMORY_AREA
,Entry
);
297 if (current
->BaseAddress
> marea
->BaseAddress
)
300 InsertHeadList(ListHead
,&marea
->Entry
);
305 while (current_entry
->Flink
!=ListHead
)
308 current
= CONTAINING_RECORD(current_entry
,MEMORY_AREA
,Entry
);
309 next
= CONTAINING_RECORD(current_entry
->Flink
,MEMORY_AREA
,Entry
);
310 assert(current
->BaseAddress
!= marea
->BaseAddress
);
311 assert(next
->BaseAddress
!= marea
->BaseAddress
);
312 if (current
->BaseAddress
< marea
->BaseAddress
&&
313 current
->Entry
.Flink
==ListHead
)
315 current_entry
->Flink
= inserted_entry
;
316 inserted_entry
->Flink
=ListHead
;
317 inserted_entry
->Blink
=current_entry
;
318 ListHead
->Blink
= inserted_entry
;
321 if (current
->BaseAddress
< marea
->BaseAddress
&&
322 next
->BaseAddress
> marea
->BaseAddress
)
324 inserted_entry
->Flink
= current_entry
->Flink
;
325 inserted_entry
->Blink
= current_entry
;
326 inserted_entry
->Flink
->Blink
= inserted_entry
;
327 current_entry
->Flink
=inserted_entry
;
330 current_entry
= current_entry
->Flink
;
333 InsertTailList(ListHead
,inserted_entry
);
336 static PVOID
MmFindGapWithoutLock(PEPROCESS Process
,
337 KPROCESSOR_MODE Mode
, ULONG Length
)
339 PLIST_ENTRY ListHead
;
340 PLIST_ENTRY current_entry
;
341 MEMORY_AREA
* current
;
345 DPRINT("MmFindGapWithoutLock(Mode %x Length %x)\n",Mode
,Length
);
348 if (Mode
== KernelMode
)
350 ListHead
= &SystemAreaList
;
354 ListHead
= &(Process
->Pcb
.MemoryAreaList
);
358 current_entry
= ListHead
->Flink
;
359 while (current_entry
->Flink
!=ListHead
)
361 current
= CONTAINING_RECORD(current_entry
,MEMORY_AREA
,Entry
);
362 next
= CONTAINING_RECORD(current_entry
->Flink
,MEMORY_AREA
,Entry
);
363 DPRINT("current %x current->BaseAddress %x ",current
,
364 current
->BaseAddress
);
365 DPRINT("current->Length %x\n",current
->Length
);
366 DPRINT("next %x next->BaseAddress %x ",next
,next
->BaseAddress
);
367 Gap
= (next
->BaseAddress
) -(current
->BaseAddress
+ current
->Length
);
368 DPRINT("Base %x Gap %x\n",current
->BaseAddress
,Gap
);
371 return(current
->BaseAddress
+ PAGE_ROUND_UP(current
->Length
));
373 current_entry
= current_entry
->Flink
;
376 if (current_entry
== ListHead
)
378 assert(Mode
==UserMode
);
379 return((PVOID
)MM_LOWEST_USER_ADDRESS
);
382 current
= CONTAINING_RECORD(current_entry
,MEMORY_AREA
,Entry
);
383 //DbgPrint("current %x returning %x\n",current,current->BaseAddress+
385 return(current
->BaseAddress
+ PAGE_ROUND_UP(current
->Length
));
388 NTSTATUS
MmInitMemoryAreas(VOID
)
390 * FUNCTION: Initialize the memory area list
393 DPRINT("MmInitMemoryAreas()\n",0);
394 InitializeListHead(&SystemAreaList
);
395 KeInitializeSpinLock(&SystemAreaListLock
);
396 return(STATUS_SUCCESS
);
399 NTSTATUS
MmFreeMemoryArea(PEPROCESS Process
,
404 MEMORY_AREA
* MemoryArea
;
407 LARGE_INTEGER PhysicalAddr
;
409 DPRINT("MmFreeMemoryArea(Process %x, BaseAddress %x, Length %x,"
410 "FreePages %d)\n",Process
,BaseAddress
,Length
,FreePages
);
412 if (SystemAreaList
.Flink
!= (&SystemAreaList
) &&
413 SystemAreaList
.Flink
->Flink
!= (&SystemAreaList
))
416 PMEMORY_AREA Snd
= CONTAINING_RECORD(SystemAreaList
.Flink
->Flink
,
419 DPRINT("SystemAreaList.Flink->Flink->BaseAddress %x\n",
422 // assert(Snd->BaseAddress == (PVOID)0x0c001c000);
425 MmLockMemoryAreaList(BaseAddress
, &oldlvl
);
427 MemoryArea
= MmOpenMemoryAreaByAddressWithoutLock(Process
,
429 if (MemoryArea
==NULL
)
431 MmUnlockMemoryAreaList(BaseAddress
, &oldlvl
);
433 return(STATUS_UNSUCCESSFUL
);
437 for (i
=0;i
<=(MemoryArea
->Length
/PAGESIZE
);i
++)
439 PhysicalAddr
= MmGetPhysicalAddress(MemoryArea
->BaseAddress
+
441 MmFreePage((PVOID
)(ULONG
)(PhysicalAddr
.u
.LowPart
), 1);
444 for (i
=0; i
<=(MemoryArea
->Length
/PAGESIZE
); i
++)
447 MemoryArea
->BaseAddress
+ (i
*PAGESIZE
),
452 RemoveEntryList(&(MemoryArea
->Entry
));
453 ExFreePool(MemoryArea
);
454 MmUnlockMemoryAreaList(BaseAddress
, &oldlvl
);
456 if (SystemAreaList
.Flink
!= (&SystemAreaList
) &&
457 SystemAreaList
.Flink
->Flink
!= (&SystemAreaList
))
460 PMEMORY_AREA Snd
= CONTAINING_RECORD(SystemAreaList
.Flink
->Flink
,
463 DPRINT("SystemAreaList.Flink->Flink->BaseAddress %x\n",
466 // assert(Snd->BaseAddress == (PVOID)0x0c001c000);
469 return(STATUS_SUCCESS
);
472 PMEMORY_AREA
MmSplitMemoryArea(PEPROCESS Process
,
473 PMEMORY_AREA OriginalMemoryArea
,
483 Result
= ExAllocatePool(NonPagedPool
,sizeof(MEMORY_AREA
));
484 RtlZeroMemory(Result
,sizeof(MEMORY_AREA
));
485 Result
->Type
=NewType
;
486 Result
->BaseAddress
=BaseAddress
;
487 Result
->Length
=Length
;
488 Result
->Attributes
=NewAttributes
;
490 Result
->Process
= Process
;
492 MmLockMemoryAreaList(OriginalMemoryArea
->BaseAddress
,&oldlvl
);
494 // MmDumpMemoryAreas(MmGetRelatedListHead(Process,BaseAddress));
496 if (BaseAddress
== OriginalMemoryArea
->BaseAddress
)
498 OriginalMemoryArea
->BaseAddress
= BaseAddress
+ Length
;
499 OriginalMemoryArea
->Length
= OriginalMemoryArea
->Length
- Length
;
500 MmInsertMemoryAreaWithoutLock(Process
,Result
);
501 MmUnlockMemoryAreaList(OriginalMemoryArea
->BaseAddress
,&oldlvl
);
503 // MmDumpMemoryAreas(MmGetRelatedListHead(Process,BaseAddress));
507 if ((BaseAddress
+ Length
) ==
508 (OriginalMemoryArea
->BaseAddress
+ OriginalMemoryArea
->Length
))
510 OriginalMemoryArea
->Length
= OriginalMemoryArea
->Length
- Length
;
511 MmInsertMemoryAreaWithoutLock(Process
,Result
);
512 MmUnlockMemoryAreaList(OriginalMemoryArea
->BaseAddress
,&oldlvl
);
514 // MmDumpMemoryAreas(MmGetRelatedListHead(Process,BaseAddress));
519 Split
= ExAllocatePool(NonPagedPool
,sizeof(MEMORY_AREA
));
520 RtlCopyMemory(Split
,OriginalMemoryArea
,sizeof(MEMORY_AREA
));
521 Split
->BaseAddress
= BaseAddress
+ Length
;
522 Split
->Length
= OriginalMemoryArea
->Length
- (((ULONG
)BaseAddress
)
525 OriginalMemoryArea
->Length
= BaseAddress
- OriginalMemoryArea
->BaseAddress
;
527 MmUnlockMemoryAreaList(OriginalMemoryArea
->BaseAddress
,&oldlvl
);
529 // MmDumpMemoryAreas(MmGetRelatedListHead(Process,BaseAddress));
534 NTSTATUS
MmCreateMemoryArea(KPROCESSOR_MODE Mode
,
540 MEMORY_AREA
** Result
)
544 DPRINT("MmCreateMemoryArea(Mode %x, Type %d, BaseAddress %x,"
545 "*BaseAddress %x, Length %x, Attributes %x, Result %x)\n",
546 Mode
,Type
,BaseAddress
,*BaseAddress
,Length
,Attributes
,Result
);
548 if (SystemAreaList
.Flink
!= (&SystemAreaList
) &&
549 SystemAreaList
.Flink
->Flink
!= (&SystemAreaList
))
552 PMEMORY_AREA Snd
= CONTAINING_RECORD(SystemAreaList
.Flink
->Flink
,
555 DPRINT("SystemAreaList.Flink->Flink->BaseAddress %x\n",
557 // assert(Snd->BaseAddress == (PVOID)0x0c001c000);
561 if ((*BaseAddress
)==0)
563 MmLockMemoryAreaListByMode(Mode
,&oldlvl
);
567 MmLockMemoryAreaList(*BaseAddress
,&oldlvl
);
570 if ((*BaseAddress
)==0)
572 *BaseAddress
= MmFindGapWithoutLock(Process
,Mode
,PAGE_ROUND_UP(Length
)
574 if ((*BaseAddress
)==0)
576 MmUnlockMemoryAreaListByMode(Mode
,&oldlvl
);
577 return(STATUS_UNSUCCESSFUL
);
579 (*BaseAddress
)=(*BaseAddress
)+PAGESIZE
;
583 (*BaseAddress
) = (PVOID
)PAGE_ROUND_DOWN((*BaseAddress
));
584 if (MmOpenMemoryAreaByRegionWithoutLock(Process
,
588 MmUnlockMemoryAreaList(*BaseAddress
,&oldlvl
);
589 return(STATUS_UNSUCCESSFUL
);
593 *Result
= ExAllocatePool(NonPagedPool
,sizeof(MEMORY_AREA
));
594 RtlZeroMemory(*Result
,sizeof(MEMORY_AREA
));
595 (*Result
)->Type
=Type
;
596 (*Result
)->BaseAddress
=*BaseAddress
;
597 (*Result
)->Length
=Length
;
598 (*Result
)->Attributes
=Attributes
;
599 (*Result
)->LockCount
=0;
600 (*Result
)->Process
= Process
;
602 MmInsertMemoryAreaWithoutLock(Process
,*Result
);
603 MmUnlockMemoryAreaList(*BaseAddress
,&oldlvl
);
605 if (SystemAreaList
.Flink
!= (&SystemAreaList
) &&
606 SystemAreaList
.Flink
->Flink
!= (&SystemAreaList
))
609 PMEMORY_AREA Snd
= CONTAINING_RECORD(SystemAreaList
.Flink
->Flink
,
612 DPRINT("SystemAreaList.Flink->Flink->BaseAddress %x\n",
615 // assert(Snd->BaseAddress == (PVOID)0x0c001c000);
618 return(STATUS_SUCCESS
);