Author: tkreuzer
Date: Sat Feb 4 12:13:53 2012
New Revision: 55407
URL:
http://svn.reactos.org/svn/reactos?rev=55407&view=rev
Log:
[NTOSKRNL/MM/AMD64]
- Implement more of MmCreateProcessAddressSpace
- Acquire pfn lock and use MiRemoveZeroPage in MiGetPteForProcess
Modified:
trunk/reactos/ntoskrnl/mm/amd64/page.c
Modified: trunk/reactos/ntoskrnl/mm/amd64/page.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/amd64/page.c?r…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/amd64/page.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/amd64/page.c [iso-8859-1] Sat Feb 4 12:13:53 2012
@@ -28,7 +28,7 @@
/* GLOBALS *****************************************************************/
const
-ULONG
+ULONG64
MmProtectToPteMask[32] =
{
//
@@ -151,37 +151,48 @@
Process && Process != PsGetCurrentProcess())
{
UNIMPLEMENTED;
+ __debugbreak();
return NULL;
}
else if (Create)
{
+ KIRQL OldIrql;
TmplPte.u.Long = 0;
TmplPte.u.Flush.Valid = 1;
TmplPte.u.Flush.Write = 1;
+
+ /* All page table levels of user pages are user owned */
+ TmplPte.u.Flush.Owner = (Address < MmHighestUserAddress) ? 1 : 0;
+
+ /* Lock the PFN database */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
/* Get the PXE */
Pte = MiAddressToPxe(Address);
if (!Pte->u.Hard.Valid)
{
-// TmplPte.u.Hard.PageFrameNumber = MiAllocPage(TRUE);
- InterlockedExchangePte(Pte, TmplPte);
+ TmplPte.u.Hard.PageFrameNumber = MiRemoveZeroPage(0);
+ MI_WRITE_VALID_PTE(Pte, TmplPte);
}
/* Get the PPE */
Pte = MiAddressToPpe(Address);
if (!Pte->u.Hard.Valid)
{
-// TmplPte.u.Hard.PageFrameNumber = MiAllocPage(TRUE);
- InterlockedExchangePte(Pte, TmplPte);
+ TmplPte.u.Hard.PageFrameNumber = MiRemoveZeroPage(1);
+ MI_WRITE_VALID_PTE(Pte, TmplPte);
}
/* Get the PDE */
Pte = MiAddressToPde(Address);
if (!Pte->u.Hard.Valid)
{
-// TmplPte.u.Hard.PageFrameNumber = MiAllocPage(TRUE);
- InterlockedExchangePte(Pte, TmplPte);
+ TmplPte.u.Hard.PageFrameNumber = MiRemoveZeroPage(2);
+ MI_WRITE_VALID_PTE(Pte, TmplPte);
}
+
+ /* Unlock PFN database */
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
}
else
{
@@ -529,6 +540,8 @@
TmplPte.u.Hard.Valid = 1;
MiSetPteProtection(&TmplPte, PageProtection);
+ TmplPte.u.Flush.Owner = (Address < MmHighestUserAddress) ? 1 : 0;
+
//__debugbreak();
for (i = 0; i < PageCount; i++)
@@ -537,7 +550,7 @@
Pte = MiGetPteForProcess(Process, Address, TRUE);
-DPRINT1("MmCreateVirtualMappingUnsafe, Address=%p, TmplPte=%p, Pte=%p\n",
+DPRINT("MmCreateVirtualMappingUnsafe, Address=%p, TmplPte=%p, Pte=%p\n",
Address, TmplPte.u.Long, Pte);
if (InterlockedExchangePte(Pte, TmplPte))
@@ -577,6 +590,44 @@
return MmCreateVirtualMappingUnsafe(Process, Address, Protect, Pages, PageCount);
}
+static PMMPTE
+MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create)
+{
+ __debugbreak();
+ return 0;
+}
+
+BOOLEAN MmUnmapPageTable(PMMPTE Pt)
+{
+ ASSERT(FALSE);
+ return 0;
+}
+
+static ULONG64 MmGetPageEntryForProcess(PEPROCESS Process, PVOID Address)
+{
+ MMPTE Pte, *PointerPte;
+
+ PointerPte = MmGetPageTableForProcess(Process, Address, FALSE);
+ if (PointerPte)
+ {
+ Pte = *PointerPte;
+ MmUnmapPageTable(PointerPte);
+ return Pte.u.Long;
+ }
+ return 0;
+}
+
+VOID
+NTAPI
+MmGetPageFileMapping(
+ PEPROCESS Process,
+ PVOID Address,
+ SWAPENTRY* SwapEntry)
+{
+ ULONG64 Entry = MmGetPageEntryForProcess(Process, Address);
+ *SwapEntry = Entry >> 1;
+}
+
BOOLEAN
NTAPI
MmCreateProcessAddressSpace(IN ULONG MinWs,
@@ -584,14 +635,19 @@
OUT PULONG_PTR DirectoryTableBase)
{
KIRQL OldIrql;
- PFN_NUMBER TableBasePfn, HyperPfn;
- PMMPTE PointerPte;
+ PFN_NUMBER TableBasePfn, HyperPfn, HyperPdPfn, HyperPtPfn, WorkingSetPfn;
+ PMMPTE SystemPte;
MMPTE TempPte, PdePte;
ULONG TableIndex;
- PMMPTE SystemTable;
-
- /* No page colors yet */
- Process->NextPageColor = 0;
+ PMMPTE PageTablePointer;
+
+ /* Make sure we don't already have a page directory setup */
+ ASSERT(Process->Pcb.DirectoryTableBase[0] == 0);
+ ASSERT(Process->Pcb.DirectoryTableBase[1] == 0);
+ ASSERT(Process->WorkingSetPage == 0);
+
+ /* Choose a process color */
+ Process->NextPageColor = (USHORT)RtlRandom(&MmProcessColorSeed);
/* Setup the hyperspace lock */
KeInitializeSpinLock(&Process->HyperSpaceLock);
@@ -599,67 +655,97 @@
/* Lock PFN database */
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
- /* Get a page for the table base and for hyperspace */
- TableBasePfn = MiRemoveAnyPage(0);
- HyperPfn = MiRemoveAnyPage(0);
+ /* Get a page for the table base and one for hyper space. The PFNs for
+ these pages will be initialized in MmInitializeProcessAddressSpace,
+ when we are already attached to the process. */
+ TableBasePfn = MiRemoveAnyPage(MI_GET_NEXT_PROCESS_COLOR(Process));
+ HyperPfn = MiRemoveAnyPage(MI_GET_NEXT_PROCESS_COLOR(Process));
+ HyperPdPfn = MiRemoveAnyPage(MI_GET_NEXT_PROCESS_COLOR(Process));
+ HyperPtPfn = MiRemoveAnyPage(MI_GET_NEXT_PROCESS_COLOR(Process));
+ WorkingSetPfn = MiRemoveAnyPage(MI_GET_NEXT_PROCESS_COLOR(Process));
/* Release PFN lock */
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
- /* Zero both pages */
- MiZeroPhysicalPage(TableBasePfn);
+ /* Zero pages */ /// FIXME:
MiZeroPhysicalPage(HyperPfn);
+ MiZeroPhysicalPage(WorkingSetPfn);
/* Set the base directory pointers */
+ Process->WorkingSetPage = WorkingSetPfn;
DirectoryTableBase[0] = TableBasePfn << PAGE_SHIFT;
DirectoryTableBase[1] = HyperPfn << PAGE_SHIFT;
- /* Make sure we don't already have a page directory setup */
- ASSERT(Process->Pcb.DirectoryTableBase[0] == 0);
-
- /* Insert us into the Mm process list */
- InsertTailList(&MmProcessList, &Process->MmProcessLinks);
-
/* Get a PTE to map the page directory */
- PointerPte = MiReserveSystemPtes(1, SystemPteSpace);
- ASSERT(PointerPte != NULL);
-
- /* Build it */
- MI_MAKE_HARDWARE_PTE_KERNEL(&PdePte,
- PointerPte,
- MM_READWRITE,
- TableBasePfn);
-
- /* Set it dirty and map it */
- PdePte.u.Hard.Dirty = TRUE;
- MI_WRITE_VALID_PTE(PointerPte, PdePte);
-
- /* Now get the page directory (which we'll double map, so call it a page table
*/
- SystemTable = MiPteToAddress(PointerPte);
-
- /* Copy all the kernel mappings */
- TableIndex = MiAddressToPxi(MmSystemRangeStart);
-
- RtlCopyMemory(&SystemTable[TableIndex],
- MiAddressToPxe(MmSystemRangeStart),
+ SystemPte = MiReserveSystemPtes(1, SystemPteSpace);
+ ASSERT(SystemPte != NULL);
+
+ /* Get its address */
+ PageTablePointer = MiPteToAddress(SystemPte);
+
+ /* Build the PTE for the page directory and map it */
+ PdePte = ValidKernelPte;
+ PdePte.u.Hard.PageFrameNumber = TableBasePfn;
+ *SystemPte = PdePte;
+
+/// architecture specific
+ //MiInitializePageDirectoryForProcess(
+
+ /* Copy the kernel mappings and zero out the rest */
+ TableIndex = PXE_PER_PAGE / 2;
+ RtlZeroMemory(PageTablePointer, TableIndex * sizeof(MMPTE));
+ RtlCopyMemory(PageTablePointer + TableIndex,
+ MiAddressToPxe(0) + TableIndex,
PAGE_SIZE - TableIndex * sizeof(MMPTE));
- /* Now write the PTE/PDE entry for hyperspace itself */
+ /* Sanity check */
+ ASSERT(MiAddressToPxi(MmHyperSpaceEnd) >= TableIndex);
+
+ /* Setup a PTE for the page directory mappings */
TempPte = ValidKernelPte;
+
+ /* Update the self mapping of the PML4 */
+ TableIndex = MiAddressToPxi((PVOID)PXE_SELFMAP);
+ TempPte.u.Hard.PageFrameNumber = TableBasePfn;
+ PageTablePointer[TableIndex] = TempPte;
+
+ /* Write the PML4 entry for hyperspace */
+ TableIndex = MiAddressToPxi((PVOID)HYPER_SPACE);
TempPte.u.Hard.PageFrameNumber = HyperPfn;
- TableIndex = MiAddressToPxi((PVOID)HYPER_SPACE);
- SystemTable[TableIndex] = TempPte;
-
- /* Sanity check */
- ASSERT(MiAddressToPxi(MmHyperSpaceEnd) > TableIndex);
-
- /* Now do the x86 trick of making the PDE a page table itself */
- TableIndex = MiAddressToPxi((PVOID)PTE_BASE);
- TempPte.u.Hard.PageFrameNumber = TableBasePfn;
- SystemTable[TableIndex] = TempPte;
-
- /* Let go of the system PTE */
- MiReleaseSystemPtes(PointerPte, 1, SystemPteSpace);
+ PageTablePointer[TableIndex] = TempPte;
+
+ /* Map the hyperspace PDPT to the system PTE */
+ PdePte.u.Hard.PageFrameNumber = HyperPfn;
+ *SystemPte = PdePte;
+ __invlpg(PageTablePointer);
+
+ /* Write the hyperspace entry for the first PD */
+ TempPte.u.Hard.PageFrameNumber = HyperPdPfn;
+ PageTablePointer[0] = TempPte;
+
+ /* Map the hyperspace PD to the system PTE */
+ PdePte.u.Hard.PageFrameNumber = HyperPdPfn;
+ *SystemPte = PdePte;
+ __invlpg(PageTablePointer);
+
+ /* Write the hyperspace entry for the first PT */
+ TempPte.u.Hard.PageFrameNumber = HyperPtPfn;
+ PageTablePointer[0] = TempPte;
+
+ /* Map the hyperspace PT to the system PTE */
+ PdePte.u.Hard.PageFrameNumber = HyperPtPfn;
+ *SystemPte = PdePte;
+ __invlpg(PageTablePointer);
+
+ /* Write the hyperspace PTE for the working set list index */
+ TempPte.u.Hard.PageFrameNumber = WorkingSetPfn;
+ TableIndex = MiAddressToPti(MmWorkingSetList);
+ PageTablePointer[TableIndex] = TempPte;
+
+/// end architecture specific
+
+ /* Release the system PTE */
+ MiReleaseSystemPtes(SystemPte, 1, SystemPteSpace);
/* Switch to phase 1 initialization */
ASSERT(Process->AddressSpaceInitialized == 0);