From: Sir Richard Date: Sat, 29 May 2010 18:33:50 +0000 (+0000) Subject: Testers: Please pay attention to this build and test it fully: X-Git-Tag: backups/header-work@57446~11^2~193 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=c916ce9d20b578acd4589e499c50c51271105cfe Testers: Please pay attention to this build and test it fully: [NTOS]: Implement MiDecrementShareCount (to start replacing MmReleasePageMemoryConsumer calls for pages that were grabbed through ARM3, not Mm). [NTOS]: Implement MiInitializePfn (to initialize pages grabbed through ARM3/MiRemoveAnyPage instead of Mm/MmAllocPage). [NTOS]: For stack pages, use new ARM3 PFN alloc/free routines, as a first test/beginning of the new ARM3 ABI. [NTOS]: Implement and start using the Pending-Deletion PFN flag. [NTOS]: As a result, for stack pages, the Transition page state will now be seen, and the new routine for re-inserting pages into the free list will now be used. Tracking of page table references is also done now for these pages (but we don't free the PT since this doesn't seem safe yet). svn path=/trunk/; revision=47424 --- diff --git a/reactos/ntoskrnl/mm/ARM3/contmem.c b/reactos/ntoskrnl/mm/ARM3/contmem.c index 0d7628bf88f..2f3eda954e2 100644 --- a/reactos/ntoskrnl/mm/ARM3/contmem.c +++ b/reactos/ntoskrnl/mm/ARM3/contmem.c @@ -502,6 +502,9 @@ MiFreeContiguousMemory(IN PVOID BaseAddress) ASSERT(Pfn1->u4.VerifierAllocation == 0); ASSERT(Pfn1->u3.e1.PrototypePte == 0); + /* Set the special pending delete marker */ + MI_SET_PFN_DELETED(Pfn1); + /* Keep going for assertions */ PointerPte++; } while (Pfn1++->u3.e1.EndOfAllocation == 0); @@ -531,12 +534,11 @@ MiFreeContiguousMemory(IN PVOID BaseAddress) // Loop all the pages // LastPage = PageFrameIndex + PageCount; + Pfn1 = MiGetPfnEntry(PageFrameIndex); do { - // - // Free each one, and move on - // - MmReleasePageMemoryConsumer(MC_NPPOOL, PageFrameIndex++); + /* Decrement the share count and move on */ + MiDecrementShareCount(Pfn1++, PageFrameIndex++); } while (PageFrameIndex < LastPage); // diff --git a/reactos/ntoskrnl/mm/ARM3/miarm.h b/reactos/ntoskrnl/mm/ARM3/miarm.h index 193eb04e698..4c5e3bc441b 100644 --- a/reactos/ntoskrnl/mm/ARM3/miarm.h +++ b/reactos/ntoskrnl/mm/ARM3/miarm.h @@ -119,6 +119,12 @@ // #define MI_MAKE_SOFTWARE_PTE(p, x) ((p)->u.Long = (x << MM_PTE_SOFTWARE_PROTECTION_BITS)) +// +// Marks a PTE as deleted +// +#define MI_SET_PFN_DELETED(x) ((x)->PteAddress = (PMMPTE)((ULONG_PTR)(x)->PteAddress | 1)) +#define MI_IS_PFN_DELETED(x) ((ULONG_PTR)((x)->PteAddress) & 1) + // // Special values for LoadedImports // @@ -585,6 +591,21 @@ MiAllocatePfn( IN ULONG Protection ); +VOID +NTAPI +MiInitializePfn( + IN PFN_NUMBER PageFrameIndex, + IN PMMPTE PointerPte, + IN BOOLEAN Modified +); + +VOID +NTAPI +MiDecrementShareCount( + IN PMMPFN Pfn1, + IN PFN_NUMBER PageFrameIndex +); + PFN_NUMBER NTAPI MiRemoveAnyPage( diff --git a/reactos/ntoskrnl/mm/ARM3/pagfault.c b/reactos/ntoskrnl/mm/ARM3/pagfault.c index 7455a100af1..ceff13bcc8d 100644 --- a/reactos/ntoskrnl/mm/ARM3/pagfault.c +++ b/reactos/ntoskrnl/mm/ARM3/pagfault.c @@ -91,7 +91,7 @@ MiResolveDemandZeroFault(IN PVOID Address, { PFN_NUMBER PageFrameNumber; MMPTE TempPte; - DPRINT("ARM3 Demand Zero Page Fault Handler for address: %p in process: %p\n", + DPRINT1("ARM3 Demand Zero Page Fault Handler for address: %p in process: %p\n", Address, Process); diff --git a/reactos/ntoskrnl/mm/ARM3/pfnlist.c b/reactos/ntoskrnl/mm/ARM3/pfnlist.c index ff17eb0b3c8..b70e191c030 100644 --- a/reactos/ntoskrnl/mm/ARM3/pfnlist.c +++ b/reactos/ntoskrnl/mm/ARM3/pfnlist.c @@ -561,4 +561,126 @@ MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex) } } +VOID +NTAPI +MiInitializePfn(IN PFN_NUMBER PageFrameIndex, + IN PMMPTE PointerPte, + IN BOOLEAN Modified) +{ + PMMPFN Pfn1; + NTSTATUS Status; + PMMPTE PointerPtePte; + ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); + + /* Setup the PTE */ + Pfn1 = MiGetPfnEntry(PageFrameIndex); + Pfn1->PteAddress = PointerPte; + + /* Check if this PFN is part of a valid address space */ + if (PointerPte->u.Hard.Valid == 1) + { + /* FIXME: TODO */ + ASSERT(FALSE); + } + + /* Otherwise this is a fresh page -- set it up */ + ASSERT(Pfn1->u3.e2.ReferenceCount == 0); + Pfn1->u3.e2.ReferenceCount = 1; + Pfn1->u2.ShareCount = 1; + Pfn1->u3.e1.PageLocation = ActiveAndValid; + ASSERT(Pfn1->u3.e1.Rom == 0); + Pfn1->u3.e1.Modified = Modified; + + /* Get the page table for the PTE */ + PointerPtePte = MiAddressToPte(PointerPte); + if (PointerPtePte->u.Hard.Valid == 0) + { + /* Make sure the PDE gets paged in properly */ + Status = MiCheckPdeForPagedPool(PointerPte); + if (!NT_SUCCESS(Status)) + { + /* Crash */ + KeBugCheckEx(MEMORY_MANAGEMENT, + 0x61940, + (ULONG_PTR)PointerPte, + (ULONG_PTR)PointerPtePte->u.Long, + (ULONG_PTR)MiPteToAddress(PointerPte)); + } + } + + /* Get the PFN for the page table */ + PageFrameIndex = PFN_FROM_PTE(PointerPtePte); + ASSERT(PageFrameIndex != 0); + Pfn1->u4.PteFrame = PageFrameIndex; + + /* Increase its share count so we don't get rid of it */ + Pfn1 = MiGetPfnEntry(PageFrameIndex); + Pfn1->u2.ShareCount++; +} + +VOID +NTAPI +MiDecrementShareCount(IN PMMPFN Pfn1, + IN PFN_NUMBER PageFrameIndex) +{ + ASSERT(PageFrameIndex > 0); + ASSERT(MiGetPfnEntry(PageFrameIndex) != NULL); + ASSERT(Pfn1 == MiGetPfnEntry(PageFrameIndex)); + + /* Page must be in-use */ + if ((Pfn1->u3.e1.PageLocation != ActiveAndValid) && + (Pfn1->u3.e1.PageLocation != StandbyPageList)) + { + /* Otherwise we have PFN corruption */ + KeBugCheckEx(PFN_LIST_CORRUPT, + 0x99, + PageFrameIndex, + Pfn1->u3.e1.PageLocation, + 0); + } + + /* Check if the share count is now 0 */ + ASSERT(Pfn1->u2.ShareCount < 0xF000000); + if (!--Pfn1->u2.ShareCount) + { + /* ReactOS does not handle these */ + ASSERT(Pfn1->u3.e1.PrototypePte == 0); + + /* Put the page in transition */ + Pfn1->u3.e1.PageLocation = TransitionPage; + + /* PFN lock must be held */ + ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); + + /* Page should at least have one reference */ + ASSERT(Pfn1->u3.e2.ReferenceCount != 0); + if (Pfn1->u3.e2.ReferenceCount == 1) + { + /* In ReactOS, this path should always be hit with a deleted PFN */ + ASSERT(MI_IS_PFN_DELETED(Pfn1) == TRUE); + + /* Clear the last reference */ + Pfn1->u3.e2.ReferenceCount = 0; + + /* + * OriginalPte is used by AweReferenceCount in ReactOS, but either + * ways we shouldn't be seeing RMAP entries at this point + */ + ASSERT(Pfn1->OriginalPte.u.Soft.Prototype == 0); + ASSERT(Pfn1->OriginalPte.u.Long == 0); + + /* Mark the page temporarily as valid, we're going to make it free soon */ + Pfn1->u3.e1.PageLocation = ActiveAndValid; + + /* Bring it back into the free list */ + MiInsertPageInFreeList(PageFrameIndex); + } + else + { + /* Otherwise, just drop the reference count */ + InterlockedDecrement16((PSHORT)&Pfn1->u3.e2.ReferenceCount); + } + } +} + /* EOF */ diff --git a/reactos/ntoskrnl/mm/ARM3/procsup.c b/reactos/ntoskrnl/mm/ARM3/procsup.c index 8f1e6b732c1..e82a567d329 100644 --- a/reactos/ntoskrnl/mm/ARM3/procsup.c +++ b/reactos/ntoskrnl/mm/ARM3/procsup.c @@ -31,8 +31,10 @@ MmDeleteKernelStack(IN PVOID StackBase, IN BOOLEAN GuiStack) { PMMPTE PointerPte; - PFN_NUMBER StackPages; + PFN_NUMBER StackPages, PageFrameNumber;//, PageTableFrameNumber; + PMMPFN Pfn1;//, Pfn2; ULONG i; + KIRQL OldIrql; // // This should be the guard page, so decrement by one @@ -46,6 +48,9 @@ MmDeleteKernelStack(IN PVOID StackBase, StackPages = BYTES_TO_PAGES(GuiStack ? KERNEL_LARGE_STACK_SIZE : KERNEL_STACK_SIZE); + /* Acquire the PFN lock */ + OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); + // // Loop them // @@ -56,10 +61,22 @@ MmDeleteKernelStack(IN PVOID StackBase, // if (PointerPte->u.Hard.Valid == 1) { - // - // Nuke it - // - MmReleasePageMemoryConsumer(MC_NPPOOL, PFN_FROM_PTE(PointerPte)); + /* Get the PTE's page */ + PageFrameNumber = PFN_FROM_PTE(PointerPte); + Pfn1 = MiGetPfnEntry(PageFrameNumber); +#if 0 // ARM3 might not own the page table, so don't take this risk. Leak it instead! + /* Now get the page of the page table mapping it */ + PageTableFrameNumber = Pfn1->u4.PteFrame; + Pfn2 = MiGetPfnEntry(PageTableFrameNumber); + + /* Remove a shared reference, since the page is going away */ + MiDecrementShareCount(Pfn2, PageTableFrameNumber); +#endif + /* Set the special pending delete marker */ + Pfn1->PteAddress = (PMMPTE)((ULONG_PTR)Pfn1->PteAddress | 1); + + /* And now delete the actual stack page */ + MiDecrementShareCount(Pfn1, PageFrameNumber); } // @@ -73,6 +90,9 @@ MmDeleteKernelStack(IN PVOID StackBase, // ASSERT(PointerPte->u.Hard.Valid == 0); + /* Release the PFN lock */ + KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); + // // Release the PTEs // @@ -154,15 +174,14 @@ MmCreateKernelStack(IN BOOLEAN GuiStack, // PointerPte++; - // - // Get a page - // - PageFrameIndex = MmAllocPage(MC_NPPOOL); - TempPte.u.Hard.PageFrameNumber = PageFrameIndex; + /* Get a page */ + PageFrameIndex = MiRemoveAnyPage(0); - // - // Write it - // + /* Initialize the PFN entry for this page */ + MiInitializePfn(PageFrameIndex, PointerPte, 1); + + /* Write the valid PTE */ + TempPte.u.Hard.PageFrameNumber = PageFrameIndex; ASSERT(PointerPte->u.Hard.Valid == 0); ASSERT(TempPte.u.Hard.Valid == 1); *PointerPte = TempPte; @@ -250,13 +269,14 @@ MmGrowKernelStackEx(IN PVOID StackPointer, // while (LimitPte >= NewLimitPte) { - // - // Get a page - // - PageFrameIndex = MmAllocPage(MC_NPPOOL); - TempPte.u.Hard.PageFrameNumber = PageFrameIndex; + /* Get a page */ + PageFrameIndex = MiRemoveAnyPage(0); + + /* Initialize the PFN entry for this page */ + MiInitializePfn(PageFrameIndex, LimitPte, 1); /* Write the valid PTE */ + TempPte.u.Hard.PageFrameNumber = PageFrameIndex; ASSERT(LimitPte->u.Hard.Valid == 0); ASSERT(TempPte.u.Hard.Valid == 1); *LimitPte-- = TempPte;