3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 ULONG AllocationCount
= 0;
32 VOID
VerifyHeap(VOID
);
33 VOID
DumpMemoryAllocMap(VOID
);
34 VOID
IncrementAllocationCount(VOID
);
35 VOID
DecrementAllocationCount(VOID
);
36 VOID
MemAllocTest(VOID
);
39 PVOID
MmAllocateMemory(ULONG MemorySize
)
42 ULONG FirstFreePageFromEnd
;
47 DbgPrint((DPRINT_MEMORY
, "MmAllocateMemory() called for 0 bytes. Returning NULL.\n"));
48 UiMessageBoxCritical("Memory allocation failed: MmAllocateMemory() called for 0 bytes.");
52 // Find out how many blocks it will take to
53 // satisfy this allocation
54 PagesNeeded
= ROUND_UP(MemorySize
, MM_PAGE_SIZE
) / MM_PAGE_SIZE
;
56 // If we don't have enough available mem
58 if (FreePagesInLookupTable
< PagesNeeded
)
60 DbgPrint((DPRINT_MEMORY
, "Memory allocation failed. Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize
, AllocationCount
));
61 UiMessageBoxCritical("Memory allocation failed: out of memory.");
65 FirstFreePageFromEnd
= MmFindAvailablePagesFromEnd(PageLookupTableAddress
, TotalPagesInLookupTable
, PagesNeeded
);
67 if (FirstFreePageFromEnd
== 0)
69 DbgPrint((DPRINT_MEMORY
, "Memory allocation failed. Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize
, AllocationCount
));
70 UiMessageBoxCritical("Memory allocation failed: out of memory.");
74 MmAllocatePagesInLookupTable(PageLookupTableAddress
, FirstFreePageFromEnd
, PagesNeeded
);
76 FreePagesInLookupTable
-= PagesNeeded
;
77 MemPointer
= (PVOID
)(FirstFreePageFromEnd
* MM_PAGE_SIZE
);
80 IncrementAllocationCount();
81 DbgPrint((DPRINT_MEMORY
, "Allocated %d bytes (%d pages) of memory starting at page %d. AllocCount: %d\n", MemorySize
, PagesNeeded
, FirstFreePageFromEnd
, AllocationCount
));
82 DbgPrint((DPRINT_MEMORY
, "Memory allocation pointer: 0x%x\n", MemPointer
));
86 // Now return the pointer
90 PVOID
MmAllocateMemoryAtAddress(ULONG MemorySize
, PVOID DesiredAddress
)
93 ULONG StartPageNumber
;
98 DbgPrint((DPRINT_MEMORY
, "MmAllocateMemoryAtAddress() called for 0 bytes. Returning NULL.\n"));
99 UiMessageBoxCritical("Memory allocation failed: MmAllocateMemoryAtAddress() called for 0 bytes.");
103 // Find out how many blocks it will take to
104 // satisfy this allocation
105 PagesNeeded
= ROUND_UP(MemorySize
, MM_PAGE_SIZE
) / MM_PAGE_SIZE
;
107 // Get the starting page number
108 StartPageNumber
= MmGetPageNumberFromAddress(DesiredAddress
);
110 // If we don't have enough available mem
112 if (FreePagesInLookupTable
< PagesNeeded
)
114 DbgPrint((DPRINT_MEMORY
, "Memory allocation failed. Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize
, AllocationCount
));
115 UiMessageBoxCritical("Memory allocation failed: out of memory.");
119 if (MmAreMemoryPagesAvailable(PageLookupTableAddress
, TotalPagesInLookupTable
, DesiredAddress
, PagesNeeded
) == FALSE
)
121 DbgPrint((DPRINT_MEMORY
, "Memory allocation failed. Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize
, AllocationCount
));
122 UiMessageBoxCritical("Memory allocation failed: out of memory.");
126 MmAllocatePagesInLookupTable(PageLookupTableAddress
, StartPageNumber
, PagesNeeded
);
128 FreePagesInLookupTable
-= PagesNeeded
;
129 MemPointer
= (PVOID
)(StartPageNumber
* MM_PAGE_SIZE
);
132 IncrementAllocationCount();
133 DbgPrint((DPRINT_MEMORY
, "Allocated %d bytes (%d pages) of memory starting at page %d. AllocCount: %d\n", MemorySize
, PagesNeeded
, StartPageNumber
, AllocationCount
));
134 DbgPrint((DPRINT_MEMORY
, "Memory allocation pointer: 0x%x\n", MemPointer
));
138 // Now return the pointer
142 PVOID
MmAllocateHighestMemoryBelowAddress(ULONG MemorySize
, PVOID DesiredAddress
)
145 ULONG FirstFreePageFromEnd
;
146 ULONG DesiredAddressPageNumber
;
151 DbgPrint((DPRINT_MEMORY
, "MmAllocateHighestMemoryBelowAddress() called for 0 bytes. Returning NULL.\n"));
152 UiMessageBoxCritical("Memory allocation failed: MmAllocateHighestMemoryBelowAddress() called for 0 bytes.");
156 // Find out how many blocks it will take to
157 // satisfy this allocation
158 PagesNeeded
= ROUND_UP(MemorySize
, MM_PAGE_SIZE
) / MM_PAGE_SIZE
;
160 // Get the page number for their desired address
161 DesiredAddressPageNumber
= (ULONG
)DesiredAddress
/ MM_PAGE_SIZE
;
163 // If we don't have enough available mem
165 if (FreePagesInLookupTable
< PagesNeeded
)
167 DbgPrint((DPRINT_MEMORY
, "Memory allocation failed. Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize
, AllocationCount
));
168 UiMessageBoxCritical("Memory allocation failed: out of memory.");
172 FirstFreePageFromEnd
= MmFindAvailablePagesBeforePage(PageLookupTableAddress
, TotalPagesInLookupTable
, PagesNeeded
, DesiredAddressPageNumber
);
174 if (FirstFreePageFromEnd
== 0)
176 DbgPrint((DPRINT_MEMORY
, "Memory allocation failed. Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize
, AllocationCount
));
177 UiMessageBoxCritical("Memory allocation failed: out of memory.");
181 MmAllocatePagesInLookupTable(PageLookupTableAddress
, FirstFreePageFromEnd
, PagesNeeded
);
183 FreePagesInLookupTable
-= PagesNeeded
;
184 MemPointer
= (PVOID
)(FirstFreePageFromEnd
* MM_PAGE_SIZE
);
187 IncrementAllocationCount();
188 DbgPrint((DPRINT_MEMORY
, "Allocated %d bytes (%d pages) of memory starting at page %d. AllocCount: %d\n", MemorySize
, PagesNeeded
, FirstFreePageFromEnd
, AllocationCount
));
189 DbgPrint((DPRINT_MEMORY
, "Memory allocation pointer: 0x%x\n", MemPointer
));
193 // Now return the pointer
197 VOID
MmFreeMemory(PVOID MemoryPointer
)
202 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable
= (PPAGE_LOOKUP_TABLE_ITEM
)PageLookupTableAddress
;
206 // Make sure we didn't get a bogus pointer
207 if (MemoryPointer
>= (PVOID
)(TotalPagesInLookupTable
* MM_PAGE_SIZE
))
209 BugCheck((DPRINT_MEMORY
, "Bogus memory pointer (0x%x) passed to MmFreeMemory()\n", MemoryPointer
));
213 // Find out the page number of the first
214 // page of memory they allocated
215 PageNumber
= MmGetPageNumberFromAddress(MemoryPointer
);
216 PageCount
= RealPageLookupTable
[PageNumber
].PageAllocationLength
;
219 // Make sure we didn't get a bogus pointer
220 if ((PageCount
< 1) || (PageCount
> (TotalPagesInLookupTable
- PageNumber
)))
222 BugCheck((DPRINT_MEMORY
, "Invalid page count in lookup table. PageLookupTable[%d].PageAllocationLength = %d\n", PageNumber
, RealPageLookupTable
[PageNumber
].PageAllocationLength
));
225 // Loop through our array check all the pages
226 // to make sure they are allocated with a length of 0
227 for (Idx
=PageNumber
+1; Idx
<(PageNumber
+ PageCount
); Idx
++)
229 if ((RealPageLookupTable
[Idx
].PageAllocated
!= 1) ||
230 (RealPageLookupTable
[Idx
].PageAllocationLength
!= 0))
232 BugCheck((DPRINT_MEMORY
, "Invalid page entry in lookup table, PageAllocated should = 1 and PageAllocationLength should = 0 because this is not the first block in the run. PageLookupTable[%d].PageAllocated = %d PageLookupTable[%d].PageAllocationLength = %d\n", PageNumber
, RealPageLookupTable
[PageNumber
].PageAllocated
, PageNumber
, RealPageLookupTable
[PageNumber
].PageAllocationLength
));
238 // Loop through our array and mark all the
240 for (Idx
=PageNumber
; Idx
<(PageNumber
+ PageCount
); Idx
++)
242 RealPageLookupTable
[Idx
].PageAllocated
= 0;
243 RealPageLookupTable
[Idx
].PageAllocationLength
= 0;
246 FreePagesInLookupTable
+= PageCount
;
249 DecrementAllocationCount();
250 DbgPrint((DPRINT_MEMORY
, "Freed %d pages of memory starting at page %d. AllocationCount: %d\n", PageCount
, PageNumber
, AllocationCount
));
256 VOID
VerifyHeap(VOID
)
261 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable
= (PPAGE_LOOKUP_TABLE_ITEM
)PageLookupTableAddress
;
263 if (DUMP_MEM_MAP_ON_VERIFY
)
265 DumpMemoryAllocMap();
268 // Loop through the array and verify that
269 // everything is kosher
270 for (Idx
=0; Idx
<TotalPagesInLookupTable
; Idx
++)
272 // Check if this block is allocated
273 if (RealPageLookupTable
[Idx
].PageAllocated
!= 0)
275 // This is the first block in the run so it
276 // had better have a length that is within range
277 if ((RealPageLookupTable
[Idx
].PageAllocationLength
< 1) || (RealPageLookupTable
[Idx
].PageAllocationLength
> (TotalPagesInLookupTable
- Idx
)))
279 BugCheck((DPRINT_MEMORY
, "Allocation length out of range in heap table. PageLookupTable[Idx].PageAllocationLength = %d\n", RealPageLookupTable
[Idx
].PageAllocationLength
));
282 // Now go through and verify that the rest of
283 // this run has the blocks marked allocated
284 // with a length of zero but don't check the
285 // first one because we already did
286 Count
= RealPageLookupTable
[Idx
].PageAllocationLength
;
287 for (Idx2
=1; Idx2
<Count
; Idx2
++)
289 // Make sure it's allocated
290 if (RealPageLookupTable
[Idx
+ Idx2
].PageAllocated
== 0)
292 BugCheck((DPRINT_MEMORY
, "Lookup table indicates hole in memory allocation. RealPageLookupTable[Idx + Idx2].PageAllocated == 0\n"));
295 // Make sure the length is zero
296 if (RealPageLookupTable
[Idx
+ Idx2
].PageAllocationLength
!= 0)
298 BugCheck((DPRINT_MEMORY
, "Allocation chain has non-zero value in non-first block in lookup table. RealPageLookupTable[Idx + Idx2].PageAllocationLength != 0\n"));
302 // Move on to the next run
307 // Nope, not allocated so make sure the length is zero
308 if (RealPageLookupTable
[Idx
].PageAllocationLength
!= 0)
310 BugCheck((DPRINT_MEMORY
, "Free block is start of memory allocation. RealPageLookupTable[Idx].PageAllocationLength != 0\n"));
316 VOID
DumpMemoryAllocMap(VOID
)
319 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable
= (PPAGE_LOOKUP_TABLE_ITEM
)PageLookupTableAddress
;
321 DbgPrint((DPRINT_MEMORY
, "----------- Memory Allocation Bitmap -----------\n"));
323 for (Idx
=0; Idx
<TotalPagesInLookupTable
; Idx
++)
327 DbgPrint((DPRINT_MEMORY
, "\n"));
328 DbgPrint((DPRINT_MEMORY
, "%x:\t", (Idx
* MM_PAGE_SIZE
)));
330 else if ((Idx
% 4) == 0)
332 DbgPrint((DPRINT_MEMORY
, " "));
335 switch (RealPageLookupTable
[Idx
].PageAllocated
)
338 DbgPrint((DPRINT_MEMORY
, "*"));
341 DbgPrint((DPRINT_MEMORY
, "A"));
343 case MEMTYPE_RESERVED
:
344 DbgPrint((DPRINT_MEMORY
, "R"));
346 case MEMTYPE_ACPI_RECLAIM
:
347 DbgPrint((DPRINT_MEMORY
, "M"));
349 case MEMTYPE_ACPI_NVS
:
350 DbgPrint((DPRINT_MEMORY
, "N"));
353 DbgPrint((DPRINT_MEMORY
, "X"));
358 DbgPrint((DPRINT_MEMORY
, "\n"));
361 VOID
IncrementAllocationCount(VOID
)
366 VOID
DecrementAllocationCount(VOID
)
371 VOID
MemAllocTest(VOID
)
379 MemPtr1
= MmAllocateMemory(4096);
380 printf("MemPtr1: 0x%x\n", (int)MemPtr1
);
382 MemPtr2
= MmAllocateMemory(4096);
383 printf("MemPtr2: 0x%x\n", (int)MemPtr2
);
385 MemPtr3
= MmAllocateMemory(4096);
386 printf("MemPtr3: 0x%x\n", (int)MemPtr3
);
387 DumpMemoryAllocMap();
391 MmFreeMemory(MemPtr2
);
394 MemPtr4
= MmAllocateMemory(2048);
395 printf("MemPtr4: 0x%x\n", (int)MemPtr4
);
397 MemPtr5
= MmAllocateMemory(4096);
398 printf("MemPtr5: 0x%x\n", (int)MemPtr5
);
403 ULONG
GetSystemMemorySize(VOID
)
405 return (TotalPagesInLookupTable
* MM_PAGE_SIZE
);