2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/mm/freelist.c
5 * PURPOSE: Handle the list of free physical pages
6 * PROGRAMMER: David Welch (welch@cwcom.net)
9 * 18/08/98: Added a fix from Robert Bergkvist
12 /* INCLUDES ****************************************************************/
14 #include <internal/stddef.h>
15 #include <internal/mmhal.h>
16 #include <internal/mm.h>
17 #include <internal/ntoskrnl.h>
18 #include <internal/bitops.h>
19 #include <internal/i386/io.h>
20 #include <ddk/ntddk.h>
23 #include <internal/debug.h>
25 /* TYPES *******************************************************************/
27 #define PHYSICAL_PAGE_FREE (0x1)
28 #define PHYSICAL_PAGE_INUSE (0x2)
29 #define PHYSICAL_PAGE_BIOS (0x4)
31 typedef struct _PHYSICAL_PAGE
35 } PHYSICAL_PAGE
, *PPHYSICAL_PAGE
;
37 /* GLOBALS ****************************************************************/
39 static PPHYSICAL_PAGE MmPageArray
;
41 static LIST_ENTRY UsedPageListHead
;
42 static KSPIN_LOCK UsedPageListLock
;
43 static LIST_ENTRY FreePageListHead
;
44 static KSPIN_LOCK FreePageListLock
;
45 static LIST_ENTRY BiosPageListHead
;
46 static KSPIN_LOCK BiosPageListLock
;
48 /* FUNCTIONS *************************************************************/
50 PVOID
MmInitializePageList(PVOID FirstPhysKernelAddress
,
51 PVOID LastPhysKernelAddress
,
52 ULONG MemorySizeInPages
,
53 ULONG LastKernelAddress
)
55 * FUNCTION: Initializes the page list with all pages free
56 * except those known to be reserved and those used by the kernel
58 * PageBuffer = Page sized buffer
59 * FirstKernelAddress = First physical address used by the kernel
60 * LastKernelAddress = Last physical address used by the kernel
66 DPRINT("MmInitializePageList(FirstPhysKernelAddress %x, "
67 "LastPhysKernelAddress %x, "
68 "MemorySizeInPages %x, LastKernelAddress %x)\n",
69 FirstPhysKernelAddress
,
70 LastPhysKernelAddress
,
74 InitializeListHead(&UsedPageListHead
);
75 KeInitializeSpinLock(&UsedPageListLock
);
76 InitializeListHead(&FreePageListHead
);
77 KeInitializeSpinLock(&FreePageListLock
);
78 InitializeListHead(&BiosPageListHead
);
79 KeInitializeSpinLock(&BiosPageListLock
);
81 Reserved
= (MemorySizeInPages
* sizeof(PHYSICAL_PAGE
)) / PAGESIZE
;
82 MmPageArray
= (PHYSICAL_PAGE
*)LastKernelAddress
;
84 DPRINT("Reserved %d\n", Reserved
);
87 if ((ULONG
)FirstPhysKernelAddress
< 0xa0000)
89 for (; i
<((ULONG
)FirstPhysKernelAddress
/PAGESIZE
); i
++)
91 MmPageArray
[i
].Flags
= PHYSICAL_PAGE_FREE
;
92 InsertTailList(&FreePageListHead
,
93 &MmPageArray
[i
].ListEntry
);
95 for (; i
<(0xa0000 / PAGESIZE
); i
++)
97 MmPageArray
[i
].Flags
= PHYSICAL_PAGE_INUSE
;
98 InsertTailList(&UsedPageListHead
,
99 &MmPageArray
[i
].ListEntry
);
101 for (; i
<(0x100000 / PAGESIZE
); i
++)
103 MmPageArray
[i
].Flags
= PHYSICAL_PAGE_BIOS
;
104 InsertTailList(&BiosPageListHead
,
105 &MmPageArray
[i
].ListEntry
);
110 for (; i
<(0xa0000 / PAGESIZE
); i
++)
112 MmPageArray
[i
].Flags
= PHYSICAL_PAGE_FREE
;
113 InsertTailList(&FreePageListHead
,
114 &MmPageArray
[i
].ListEntry
);
116 for (; i
<(0x100000 / PAGESIZE
); i
++)
118 MmPageArray
[i
].Flags
= PHYSICAL_PAGE_BIOS
;
119 InsertTailList(&BiosPageListHead
,
120 &MmPageArray
[i
].ListEntry
);
122 for (; i
<((ULONG
)FirstPhysKernelAddress
/PAGESIZE
); i
++)
124 MmPageArray
[i
].Flags
= PHYSICAL_PAGE_FREE
;
125 InsertTailList(&FreePageListHead
,
126 &MmPageArray
[i
].ListEntry
);
128 for (; i
<((ULONG
)LastPhysKernelAddress
/PAGESIZE
); i
++)
130 MmPageArray
[i
].Flags
= PHYSICAL_PAGE_INUSE
;
131 InsertTailList(&UsedPageListHead
,
132 &MmPageArray
[i
].ListEntry
);
136 for (; i
<MemorySizeInPages
; i
++)
138 MmPageArray
[i
].Flags
= PHYSICAL_PAGE_FREE
;
139 InsertTailList(&FreePageListHead
,
140 &MmPageArray
[i
].ListEntry
);
142 DPRINT("\nMmInitializePageList() = %x\n",
143 LastKernelAddress
+ Reserved
* PAGESIZE
);
144 return((PVOID
)(LastKernelAddress
+ Reserved
* PAGESIZE
));
147 VOID
MmFreePage(PVOID PhysicalAddress
, ULONG Nr
)
150 ULONG Start
= (ULONG
)PhysicalAddress
/ PAGESIZE
;
153 DPRINT("MmFreePage(PhysicalAddress %x, Nr %x)\n", PhysicalAddress
, Nr
);
157 KeAcquireSpinLock(&UsedPageListLock
, &oldIrql
);
158 RemoveEntryList(&MmPageArray
[Start
+ i
].ListEntry
);
159 MmPageArray
[Start
+ i
].Flags
= PHYSICAL_PAGE_FREE
;
160 KeReleaseSpinLock(&UsedPageListLock
, oldIrql
);
162 ExInterlockedInsertTailList(&FreePageListHead
,
163 &MmPageArray
[Start
+ i
].ListEntry
,
169 PVOID
MmAllocPage(VOID
)
172 PLIST_ENTRY ListEntry
;
173 PPHYSICAL_PAGE PageDescriptor
;
175 DPRINT("MmAllocPage()\n");
177 ListEntry
= ExInterlockedRemoveHeadList(&FreePageListHead
,
179 DPRINT("ListEntry %x\n",ListEntry
);
180 if (ListEntry
== NULL
)
182 DbgPrint("MmAllocPage(): Out of memory\n");
185 PageDescriptor
= CONTAINING_RECORD(ListEntry
, PHYSICAL_PAGE
, ListEntry
);
186 DPRINT("PageDescriptor %x\n",PageDescriptor
);
187 PageDescriptor
->Flags
= PHYSICAL_PAGE_INUSE
;
188 ExInterlockedInsertTailList(&UsedPageListHead
, ListEntry
,
191 DPRINT("PageDescriptor %x MmPageArray %x\n", PageDescriptor
, MmPageArray
);
192 offset
= (ULONG
)((ULONG
)PageDescriptor
- (ULONG
)MmPageArray
);
193 DPRINT("offset %x\n",offset
);
194 offset
= offset
/ sizeof(PHYSICAL_PAGE
) * PAGESIZE
;
195 DPRINT("offset %x\n",offset
);
197 DPRINT("MmAllocPage() = %x\n",offset
);
198 return((PVOID
)offset
);