Author: jgardou
Date: Mon Sep 22 17:20:43 2014
New Revision: 64229
URL:
http://svn.reactos.org/svn/reactos?rev=64229&view=rev
Log:
Try to repair catastrophic merge attempt from r64223, part 2 of 2
[NTOS/MM]
- Implement reading and writing for copy-on-write sections. Only for user space now.
CORE-8541
Modified:
branches/TransitionPte/ntoskrnl/mm/ARM3/miarm.h
branches/TransitionPte/ntoskrnl/mm/ARM3/pagfault.c
branches/TransitionPte/ntoskrnl/mm/balance.c
branches/TransitionPte/ntoskrnl/mm/marea.c
Modified: branches/TransitionPte/ntoskrnl/mm/ARM3/miarm.h
URL:
http://svn.reactos.org/svn/reactos/branches/TransitionPte/ntoskrnl/mm/ARM3/…
==============================================================================
--- branches/TransitionPte/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] (original)
+++ branches/TransitionPte/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] Mon Sep 22 17:20:43 2014
@@ -2248,6 +2248,15 @@
IN PMMVAD Vad
);
+VOID
+NTAPI
+MiDeletePte(
+ IN PMMPTE PointerPte,
+ IN PVOID VirtualAddress,
+ IN PEPROCESS CurrentProcess,
+ IN PMMPTE PrototypePte
+);
+
ULONG
NTAPI
MiMakeSystemAddressValid(
Modified: branches/TransitionPte/ntoskrnl/mm/ARM3/pagfault.c
URL:
http://svn.reactos.org/svn/reactos/branches/TransitionPte/ntoskrnl/mm/ARM3/…
==============================================================================
--- branches/TransitionPte/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] (original)
+++ branches/TransitionPte/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] Mon Sep 22 17:20:43
2014
@@ -519,6 +519,71 @@
/* Now get rid of it */
MiReleaseSystemPtes(ZeroPte, 1, SystemPteSpace);
+}
+
+VOID
+NTAPI
+MiCopyPfn(
+ _In_ PFN_NUMBER DestPage,
+ _In_ PFN_NUMBER SrcPage)
+{
+ PMMPTE SysPtes;
+ MMPTE TempPte;
+ PMMPFN DestPfn, SrcPfn;
+ PVOID DestAddress;
+ const VOID* SrcAddress;
+
+ /* Get the PFNs */
+ DestPfn = MiGetPfnEntry(DestPage);
+ ASSERT(DestPfn);
+ SrcPfn = MiGetPfnEntry(SrcPage);
+ ASSERT(SrcPfn);
+
+ /* Grab 2 system PTEs */
+ SysPtes = MiReserveSystemPtes(2, SystemPteSpace);
+ ASSERT(SysPtes);
+
+ /* Initialize the destination PTE */
+ TempPte = ValidKernelPte;
+ TempPte.u.Hard.PageFrameNumber = DestPage;
+
+ /* Setup caching */
+ if (DestPfn->u3.e1.CacheAttribute == MiWriteCombined)
+ {
+ /* Write combining, no caching */
+ MI_PAGE_DISABLE_CACHE(&TempPte);
+ MI_PAGE_WRITE_COMBINED(&TempPte);
+ }
+ else if (DestPfn->u3.e1.CacheAttribute == MiNonCached)
+ {
+ /* Write through, no caching */
+ MI_PAGE_DISABLE_CACHE(&TempPte);
+ MI_PAGE_WRITE_THROUGH(&TempPte);
+ }
+
+ /* Make the system PTE valid with our PFN */
+ MI_WRITE_VALID_PTE(&SysPtes[0], TempPte);
+
+ /* Initialize the source PTE */
+ TempPte = ValidKernelPte;
+ TempPte.u.Hard.PageFrameNumber = SrcPage;
+
+ /* Setup caching */
+ if (SrcPfn->u3.e1.CacheAttribute == MiNonCached)
+ {
+ MI_PAGE_DISABLE_CACHE(&TempPte);
+ }
+
+ /* Make the system PTE valid with our PFN */
+ MI_WRITE_VALID_PTE(&SysPtes[1], TempPte);
+
+ /* Get the addresses and perform the copy */
+ DestAddress = MiPteToAddress(&SysPtes[0]);
+ SrcAddress = MiPteToAddress(&SysPtes[1]);
+ RtlCopyMemory(DestAddress, SrcAddress, PAGE_SIZE);
+
+ /* Now get rid of it */
+ MiReleaseSystemPtes(SysPtes, 2, SystemPteSpace);
}
NTSTATUS
@@ -1109,6 +1174,7 @@
PFN_NUMBER PageFrameIndex;
NTSTATUS Status;
PVOID InPageBlock = NULL;
+ ULONG Protection;
/* Must be called with an invalid, prototype PTE, with the PFN lock held */
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
@@ -1155,31 +1221,95 @@
{
if (!PteContents.u.Proto.ReadOnly)
{
- /* Check for page acess in software */
- Status = MiAccessCheck(PointerProtoPte,
- StoreInstruction,
- KernelMode,
- TempPte.u.Soft.Protection,
- TrapInformation,
- TRUE);
- ASSERT(Status == STATUS_SUCCESS);
-
- /* Check for copy on write page */
- if ((TempPte.u.Soft.Protection & MM_WRITECOPY) == MM_WRITECOPY)
- {
- /* Not yet supported */
- ASSERT(FALSE);
- }
- }
+ Protection = TempPte.u.Soft.Protection;
+ }
+ else
+ {
+ Protection = MM_READONLY;
+ }
+ /* Check for page acess in software */
+ Status = MiAccessCheck(PointerProtoPte,
+ StoreInstruction,
+ KernelMode,
+ TempPte.u.Soft.Protection,
+ TrapInformation,
+ TRUE);
+ ASSERT(Status == STATUS_SUCCESS);
}
else
{
- /* Check for copy on write page */
- if ((PteContents.u.Soft.Protection & MM_WRITECOPY) == MM_WRITECOPY)
- {
- /* Not yet supported */
- ASSERT(FALSE);
- }
+ Protection = PteContents.u.Soft.Protection;
+ }
+
+ /* Check for writing copy on write page */
+ if (((Protection & MM_WRITECOPY) == MM_WRITECOPY) && StoreInstruction)
+ {
+ PFN_NUMBER PageFrameIndex, ProtoPageFrameIndex;
+ ULONG Color;
+
+ /* Resolve the proto fault as if it was a read operation */
+ Status = MiResolveProtoPteFault(FALSE,
+ Address,
+ PointerPte,
+ PointerProtoPte,
+ OutPfn,
+ PageFileData,
+ PteValue,
+ Process,
+ OldIrql,
+ TrapInformation);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Lock again the PFN lock, MiResolveProtoPteFault unlocked it */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ /* And re-read the proto PTE */
+ TempPte = *PointerProtoPte;
+ ASSERT(TempPte.u.Hard.Valid == 1);
+ ProtoPageFrameIndex = PFN_FROM_PTE(&TempPte);
+
+ /* Get a new page for the private copy */
+ if (Process > HYDRA_PROCESS)
+ Color = MI_GET_NEXT_PROCESS_COLOR(Process);
+ else
+ Color = MI_GET_NEXT_COLOR();
+
+ PageFrameIndex = MiRemoveAnyPage(Color);
+
+ /* Perform the copy */
+ MiCopyPfn(PageFrameIndex, ProtoPageFrameIndex);
+
+ /* This will drop everything MiResolveProtoPteFault referenced */
+ MiDeletePte(PointerPte, Address, Process, PointerProtoPte);
+
+ /* Because now we use this */
+ Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
+ MiInitializePfn(PageFrameIndex, PointerPte, TRUE);
+
+ /* Fix the protection */
+ Protection &= ~MM_WRITECOPY;
+ Protection |= MM_READWRITE;
+ if (Address < MmSystemRangeStart)
+ {
+ /* Build the user PTE */
+ MI_MAKE_HARDWARE_PTE_USER(&PteContents, PointerPte, Protection,
PageFrameIndex);
+ }
+ else
+ {
+ /* Build the kernel PTE */
+ MI_MAKE_HARDWARE_PTE(&PteContents, PointerPte, Protection,
PageFrameIndex);
+ }
+
+ /* And finally, write the valid PTE */
+ MI_WRITE_VALID_PTE(PointerPte, PteContents);
+
+ /* The caller expects us to release the PFN lock */
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ return Status;
}
/* Check for clone PTEs */
@@ -2104,8 +2234,39 @@
/* Is this a copy on write PTE? */
if (TempPte.u.Hard.CopyOnWrite)
{
- /* Not supported yet */
- ASSERT(FALSE);
+ PFN_NUMBER PageFrameIndex, OldPageFrameIndex;
+ PMMPFN Pfn1;
+
+ LockIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ ASSERT(MmAvailablePages > 0);
+
+ /* Allocate a new page and copy it */
+ PageFrameIndex =
MiRemoveAnyPage(MI_GET_NEXT_PROCESS_COLOR(CurrentProcess));
+ OldPageFrameIndex = PFN_FROM_PTE(&TempPte);
+
+ MiCopyPfn(PageFrameIndex, OldPageFrameIndex);
+
+ /* Dereference whatever this PTE is referencing */
+ Pfn1 = MI_PFN_ELEMENT(OldPageFrameIndex);
+ ASSERT(Pfn1->u3.e1.PrototypePte == 1);
+ ASSERT(!MI_IS_PFN_DELETED(Pfn1));
+ ProtoPte = Pfn1->PteAddress;
+ MiDeletePte(PointerPte, Address, CurrentProcess, ProtoPte);
+
+ /* And make a new shiny one with our page */
+ MiInitializePfn(PageFrameIndex, PointerPte, TRUE);
+ TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
+ TempPte.u.Hard.Write = 1;
+ TempPte.u.Hard.CopyOnWrite = 0;
+
+ MI_WRITE_VALID_PTE(PointerPte, TempPte);
+
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, LockIrql);
+
+ /* Return the status */
+ MiUnlockProcessWorkingSet(CurrentProcess, CurrentThread);
+ return STATUS_PAGE_FAULT_COPY_ON_WRITE;
}
/* Is this a read-only PTE? */
Modified: branches/TransitionPte/ntoskrnl/mm/balance.c
URL:
http://svn.reactos.org/svn/reactos/branches/TransitionPte/ntoskrnl/mm/balan…
==============================================================================
--- branches/TransitionPte/ntoskrnl/mm/balance.c [iso-8859-1] (original)
+++ branches/TransitionPte/ntoskrnl/mm/balance.c [iso-8859-1] Mon Sep 22 17:20:43 2014
@@ -196,13 +196,6 @@
return (MiBalancerThreadHandle != NULL) &&
(PsGetCurrentThreadId() == MiBalancerThreadId.UniqueThread);
}
-
-VOID
-NTAPI
-MiDeletePte(IN PMMPTE PointerPte,
- IN PVOID VirtualAddress,
- IN PEPROCESS CurrentProcess,
- IN PMMPTE PrototypePte);
VOID
NTAPI
Modified: branches/TransitionPte/ntoskrnl/mm/marea.c
URL:
http://svn.reactos.org/svn/reactos/branches/TransitionPte/ntoskrnl/mm/marea…
==============================================================================
--- branches/TransitionPte/ntoskrnl/mm/marea.c [iso-8859-1] (original)
+++ branches/TransitionPte/ntoskrnl/mm/marea.c [iso-8859-1] Mon Sep 22 17:20:43 2014
@@ -787,12 +787,6 @@
*
* @remarks Lock the address space before calling this function.
*/
-VOID
-NTAPI
-MiDeletePte(IN PMMPTE PointerPte,
- IN PVOID VirtualAddress,
- IN PEPROCESS CurrentProcess,
- IN PMMPTE PrototypePte);
NTSTATUS NTAPI
MmFreeMemoryArea(