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?re... ============================================================================== --- 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);