Author: arty Date: Thu May 3 21:05:06 2012 New Revision: 56488
URL: http://svn.reactos.org/svn/reactos?rev=56488&view=rev Log: [NTOSKRNL] Account for wait entries delaying a view attribute change and interacting with the machinery in CoW copying code, specifically making CoW insert and revoke a wait while copying the page, and make the CoW copy function take both pages as arguments rather than relying on the address space.
Also alter the MM_WAIT_ENTRY value a bit to take into account an assert that it must have bit 0x800 set.
Modified: trunk/reactos/ntoskrnl/cache/section/newmm.h trunk/reactos/ntoskrnl/include/internal/mm.h trunk/reactos/ntoskrnl/mm/i386/page.c trunk/reactos/ntoskrnl/mm/section.c
Modified: trunk/reactos/ntoskrnl/cache/section/newmm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cache/section/newm... ============================================================================== --- trunk/reactos/ntoskrnl/cache/section/newmm.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/cache/section/newmm.h [iso-8859-1] Thu May 3 21:05:06 2012 @@ -4,7 +4,7 @@
/* TYPES *********************************************************************/
-#define MM_WAIT_ENTRY 0x7ffff800 +#define MM_WAIT_ENTRY 0x7ffffc00 #define PFN_FROM_SSE(E) ((PFN_NUMBER)((E) >> PAGE_SHIFT)) #define IS_SWAP_FROM_SSE(E) ((E) & 0x00000001) #define MM_IS_WAIT_PTE(E) \
Modified: trunk/reactos/ntoskrnl/include/internal/mm.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/m... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/mm.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/mm.h [iso-8859-1] Thu May 3 21:05:06 2012 @@ -955,8 +955,8 @@ NTSTATUS NTAPI MiCopyFromUserPage( - PFN_NUMBER Page, - PVOID SourceAddress + PFN_NUMBER NewPage, + PFN_NUMBER OldPage );
NTSTATUS
Modified: trunk/reactos/ntoskrnl/mm/i386/page.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/i386/page.c?rev... ============================================================================== --- trunk/reactos/ntoskrnl/mm/i386/page.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/i386/page.c [iso-8859-1] Thu May 3 21:05:06 2012 @@ -558,6 +558,7 @@
if ((Pte & PA_PRESENT) || !(Pte & 0x800)) { + DPRINT1("Pte %x (want not 1 and 0x800)\n", Pte); KeBugCheck(MEMORY_MANAGEMENT); }
Modified: trunk/reactos/ntoskrnl/mm/section.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/section.c?rev=5... ============================================================================== --- trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] Thu May 3 21:05:06 2012 @@ -959,22 +959,24 @@
NTSTATUS NTAPI -MiCopyFromUserPage(PFN_NUMBER DestPage, PVOID SourceAddress) +MiCopyFromUserPage(PFN_NUMBER DestPage, PFN_NUMBER SrcPage) { PEPROCESS Process; - KIRQL Irql; - PVOID TempAddress; - - ASSERT((ULONG_PTR)SourceAddress % PAGE_SIZE == 0); + KIRQL Irql, Irql2; + PVOID DestAddress, SrcAddress; + Process = PsGetCurrentProcess(); - TempAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql); - if (TempAddress == NULL) + DestAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql); + SrcAddress = MiMapPageInHyperSpace(Process, SrcPage, &Irql2); + if (DestAddress == NULL || SrcAddress == NULL) { return(STATUS_NO_MEMORY); } - ASSERT((ULONG_PTR)TempAddress % PAGE_SIZE == 0); - RtlCopyMemory(TempAddress, SourceAddress, PAGE_SIZE); - MiUnmapPageInHyperSpace(Process, TempAddress, Irql); + ASSERT((ULONG_PTR)DestAddress % PAGE_SIZE == 0); + ASSERT((ULONG_PTR)SrcAddress % PAGE_SIZE == 0); + RtlCopyMemory(DestAddress, SrcAddress, PAGE_SIZE); + MiUnmapPageInHyperSpace(Process, SrcAddress, Irql2); + MiUnmapPageInHyperSpace(Process, DestAddress, Irql); return(STATUS_SUCCESS); }
@@ -1620,6 +1622,7 @@ PMM_REGION Region; ULONG_PTR Entry; PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace); + SWAPENTRY SwapEntry;
DPRINT("MmAccessFaultSectionView(%x, %x, %x, %x)\n", AddressSpace, MemoryArea, Address);
@@ -1699,6 +1702,10 @@ return(STATUS_MM_RESTART_OPERATION); }
+ MmDeleteRmap(OldPage, Process, PAddress); + MmDeleteVirtualMapping(Process, PAddress, FALSE, NULL, NULL); + MmCreatePageFileMapping(Process, PAddress, MM_WAIT_ENTRY); + /* * Release locks now we have the pageop */ @@ -1720,17 +1727,14 @@ /* * Copy the old page */ - MiCopyFromUserPage(NewPage, PAddress); + MiCopyFromUserPage(NewPage, OldPage);
MmLockAddressSpace(AddressSpace); - /* - * Delete the old entry. - */ - MmDeleteVirtualMapping(Process, Address, FALSE, NULL, NULL);
/* * Set the PTE to point to the new page */ + MmDeletePageFileMapping(Process, PAddress, &SwapEntry); Status = MmCreateVirtualMapping(Process, PAddress, Region->Protect, @@ -1751,7 +1755,7 @@ /* * Unshare the old page. */ - MmDeleteRmap(OldPage, Process, PAddress); + DPRINT("Swapping page (Old %x New %x)\n", OldPage, NewPage); MmInsertRmap(NewPage, Process, PAddress); MmLockSectionSegment(Segment); MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, FALSE, FALSE, NULL); @@ -2388,8 +2392,17 @@ { for (i = 0; i < PAGE_ROUND_UP(RegionSize) / PAGE_SIZE; i++) { + SWAPENTRY SwapEntry; PVOID Address = (char*)BaseAddress + (i * PAGE_SIZE); ULONG Protect = NewProtect; + + /* Wait for a wait entry to disappear */ + do { + MmGetPageFileMapping(Process, Address, &SwapEntry); + if (SwapEntry != MM_WAIT_ENTRY) + break; + MiWaitForPageEvent(Process, Address); + } while (TRUE);
/* * If we doing COW for this segment then check if the page is @@ -2404,6 +2417,10 @@ Offset.QuadPart = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress + MemoryArea->Data.SectionData.ViewOffset.QuadPart; Entry = MmGetPageEntrySectionSegment(Segment, &Offset); + /* + * An MM_WAIT_ENTRY is ok in this case... It'll just count as + * IS_SWAP_FROM_SSE and we'll do the right thing. + */ Page = MmGetPfnForProcess(Process, Address);
Protect = PAGE_READONLY;