Author: ros-arm-bringup
Date: Thu Oct 15 23:23:24 2009
New Revision: 43503
URL:
http://svn.reactos.org/svn/reactos?rev=43503&view=rev
Log:
- Add some simple code to handle paged pool page allocation and freeing in
MiAllocatePoolPages and MiFreePoolPages.
- Allocation does not support paged pool expansion yet, so we're limited to the
initial 4MB that are initialized on startup.
- This only tests the raw page allocation routines so touching memory will fail as we
don't handle paged pool faults yet.
- Nothing excercises this code path other than some simple tests while booting.
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/pool.c
trunk/reactos/ntoskrnl/mm/mminit.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/pool.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/pool.c?re…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/pool.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/pool.c [iso-8859-1] Thu Oct 15 23:23:24 2009
@@ -149,6 +149,83 @@
SizeInPages = BYTES_TO_PAGES(SizeInBytes);
//
+ // Handle paged pool
+ //
+ if (PoolType == PagedPool)
+ {
+ //
+ // Lock the paged pool mutex
+ //
+ KeAcquireGuardedMutex(&MmPagedPoolMutex);
+
+ //
+ // Find some empty allocation space
+ //
+ i = RtlFindClearBitsAndSet(MmPagedPoolInfo.PagedPoolAllocationMap,
+ SizeInPages,
+ MmPagedPoolInfo.PagedPoolHint);
+ if (i == 0xFFFFFFFF)
+ {
+ //
+ // Out of memory!
+ //
+ DPRINT1("OUT OF PAGED POOL!!!\n");
+ KeReleaseGuardedMutex(&MmPagedPoolMutex);
+ return NULL;
+ }
+
+ //
+ // Update the pool hint if the request was just one page
+ //
+ if (SizeInPages == 1) MmPagedPoolInfo.PagedPoolHint = i + 1;
+
+ //
+ // Update the end bitmap so we know the bounds of this allocation when
+ // the time comes to free it
+ //
+ RtlSetBit(MmPagedPoolInfo.EndOfPagedPoolBitmap, i + SizeInPages - 1);
+
+ //
+ // Now we can release the lock (it mainly protects the bitmap)
+ //
+ KeReleaseGuardedMutex(&MmPagedPoolMutex);
+
+ //
+ // Now figure out where this allocation starts
+ //
+ BaseVa = (PVOID)((ULONG_PTR)MmPagedPoolStart + (i << PAGE_SHIFT));
+
+ //
+ // Flush the TLB
+ //
+ KeFlushEntireTb(TRUE, TRUE);
+
+ //
+ // Setup a demand-zero writable PTE
+ //
+ TempPte.u.Long = 0;
+ MI_MAKE_WRITE_PAGE(&TempPte);
+
+ //
+ // Find the first and last PTE, then loop them all
+ //
+ PointerPte = MiAddressToPte(BaseVa);
+ StartPte = PointerPte + SizeInPages;
+ do
+ {
+ //
+ // Write the demand zero PTE and keep going
+ //
+ *PointerPte++ = TempPte;
+ } while (PointerPte < StartPte);
+
+ //
+ // Return the allocation address to the caller
+ //
+ return BaseVa;
+ }
+
+ //
// Allocations of less than 4 pages go into their individual buckets
//
i = SizeInPages - 1;
@@ -346,7 +423,57 @@
PFN_NUMBER FreePages, NumberOfPages;
KIRQL OldIrql;
PMMFREE_POOL_ENTRY FreeEntry, NextEntry, LastEntry;
- ULONG i;
+ ULONG i, End;
+
+ //
+ // Handle paged pool
+ //
+ if ((StartingVa >= MmPagedPoolStart) && (StartingVa <=
MmPagedPoolEnd))
+ {
+ //
+ // Calculate the offset from the beginning of paged pool, and convert it
+ // into pages
+ //
+ i = ((ULONG_PTR)StartingVa - (ULONG_PTR)MmPagedPoolStart) >> PAGE_SHIFT;
+ End = i;
+
+ //
+ // Now use the end bitmap to scan until we find a set bit, meaning that
+ // this allocation finishes here
+ //
+ while (!RtlTestBit(MmPagedPoolInfo.EndOfPagedPoolBitmap, End)) End++;
+
+ //
+ // Now calculate the total number of pages this allocation spans
+ //
+ NumberOfPages = End - i + 1;
+
+ //
+ // Acquire the paged pool lock
+ //
+ KeAcquireGuardedMutex(&MmPagedPoolMutex);
+
+ //
+ // Clear the allocation and free bits
+ //
+ RtlClearBit(MmPagedPoolInfo.EndOfPagedPoolBitmap, i);
+ RtlClearBits(MmPagedPoolInfo.PagedPoolAllocationMap, i, NumberOfPages);
+
+ //
+ // Update the hint if we need to
+ //
+ if (i < MmPagedPoolInfo.PagedPoolHint) MmPagedPoolInfo.PagedPoolHint = i;
+
+ //
+ // Release the lock protecting the bitmaps
+ //
+ KeReleaseGuardedMutex(&MmPagedPoolMutex);
+
+ //
+ // And finally return the number of pages freed
+ //
+ return NumberOfPages;
+ }
//
// Get the first PTE and its corresponding PFN entry
Modified: trunk/reactos/ntoskrnl/mm/mminit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/mminit.c?rev=4…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/mminit.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/mminit.c [iso-8859-1] Thu Oct 15 23:23:24 2009
@@ -353,6 +353,65 @@
/* Intialize system memory areas */
MiInitSystemMemoryAreas();
+ //
+ // STEP 1: Allocate and free a single page, repeatedly
+ // We should always get the same address back
+ //
+ if (1)
+ {
+ PULONG Test, OldTest;
+ ULONG i;
+
+ OldTest = Test = MiAllocatePoolPages(PagedPool, PAGE_SIZE);
+ ASSERT(Test);
+ for (i = 0; i < 16; i++)
+ {
+ MiFreePoolPages(Test);
+ Test = MiAllocatePoolPages(PagedPool, PAGE_SIZE);
+ ASSERT(OldTest == Test);
+ }
+ MiFreePoolPages(Test);
+ }
+
+ //
+ // STEP 2: Allocate 2048 pages without freeing them
+ // We should run out of space at 1024 pages, since we don't support
+ // expansion yet.
+ //
+ if (1)
+ {
+ PULONG Test[2048];
+ ULONG i;
+
+ for (i = 0; i < 2048; i++)
+ {
+ Test[i] = MiAllocatePoolPages(PagedPool, PAGE_SIZE);
+ if (!Test[i])
+ {
+ ASSERT(i == 1024);
+ break;
+ }
+ }
+
+ //
+ // Cleanup
+ //
+ while (--i) if (Test[i]) MiFreePoolPages(Test[i]);
+ }
+
+ //
+ // STEP 3: Allocate a page and touch it.
+ // We should get an ARM3 page fault and it should handle the fault
+ //
+ if (0) // NOT YET IMPLEMENTED
+ {
+ PULONG Test;
+
+ Test = MiAllocatePoolPages(PagedPool, PAGE_SIZE);
+ DPRINT1("Value: %lx", *Test);
+ MiFreePoolPages(Test);
+ }
+
/* Dump the address space */
MiDbgDumpAddressSpace();