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?rev... ============================================================================== --- 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=43... ============================================================================== --- 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();