mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 07:53:07 +00:00
[NTOSKRNL/MM/AMD64]
- Implement more of MmCreateProcessAddressSpace - Acquire pfn lock and use MiRemoveZeroPage in MiGetPteForProcess svn path=/trunk/; revision=55407
This commit is contained in:
parent
775cef8b4c
commit
afd88373ce
1 changed files with 139 additions and 53 deletions
|
@ -28,7 +28,7 @@ extern MMPTE HyperTemplatePte;
|
||||||
/* GLOBALS *****************************************************************/
|
/* GLOBALS *****************************************************************/
|
||||||
|
|
||||||
const
|
const
|
||||||
ULONG
|
ULONG64
|
||||||
MmProtectToPteMask[32] =
|
MmProtectToPteMask[32] =
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -151,37 +151,48 @@ MiGetPteForProcess(
|
||||||
Process && Process != PsGetCurrentProcess())
|
Process && Process != PsGetCurrentProcess())
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
|
__debugbreak();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else if (Create)
|
else if (Create)
|
||||||
{
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
TmplPte.u.Long = 0;
|
TmplPte.u.Long = 0;
|
||||||
TmplPte.u.Flush.Valid = 1;
|
TmplPte.u.Flush.Valid = 1;
|
||||||
TmplPte.u.Flush.Write = 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 */
|
/* Get the PXE */
|
||||||
Pte = MiAddressToPxe(Address);
|
Pte = MiAddressToPxe(Address);
|
||||||
if (!Pte->u.Hard.Valid)
|
if (!Pte->u.Hard.Valid)
|
||||||
{
|
{
|
||||||
// TmplPte.u.Hard.PageFrameNumber = MiAllocPage(TRUE);
|
TmplPte.u.Hard.PageFrameNumber = MiRemoveZeroPage(0);
|
||||||
InterlockedExchangePte(Pte, TmplPte);
|
MI_WRITE_VALID_PTE(Pte, TmplPte);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the PPE */
|
/* Get the PPE */
|
||||||
Pte = MiAddressToPpe(Address);
|
Pte = MiAddressToPpe(Address);
|
||||||
if (!Pte->u.Hard.Valid)
|
if (!Pte->u.Hard.Valid)
|
||||||
{
|
{
|
||||||
// TmplPte.u.Hard.PageFrameNumber = MiAllocPage(TRUE);
|
TmplPte.u.Hard.PageFrameNumber = MiRemoveZeroPage(1);
|
||||||
InterlockedExchangePte(Pte, TmplPte);
|
MI_WRITE_VALID_PTE(Pte, TmplPte);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the PDE */
|
/* Get the PDE */
|
||||||
Pte = MiAddressToPde(Address);
|
Pte = MiAddressToPde(Address);
|
||||||
if (!Pte->u.Hard.Valid)
|
if (!Pte->u.Hard.Valid)
|
||||||
{
|
{
|
||||||
// TmplPte.u.Hard.PageFrameNumber = MiAllocPage(TRUE);
|
TmplPte.u.Hard.PageFrameNumber = MiRemoveZeroPage(2);
|
||||||
InterlockedExchangePte(Pte, TmplPte);
|
MI_WRITE_VALID_PTE(Pte, TmplPte);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Unlock PFN database */
|
||||||
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -529,6 +540,8 @@ MmCreateVirtualMappingUnsafe(
|
||||||
TmplPte.u.Hard.Valid = 1;
|
TmplPte.u.Hard.Valid = 1;
|
||||||
MiSetPteProtection(&TmplPte, PageProtection);
|
MiSetPteProtection(&TmplPte, PageProtection);
|
||||||
|
|
||||||
|
TmplPte.u.Flush.Owner = (Address < MmHighestUserAddress) ? 1 : 0;
|
||||||
|
|
||||||
//__debugbreak();
|
//__debugbreak();
|
||||||
|
|
||||||
for (i = 0; i < PageCount; i++)
|
for (i = 0; i < PageCount; i++)
|
||||||
|
@ -537,7 +550,7 @@ MmCreateVirtualMappingUnsafe(
|
||||||
|
|
||||||
Pte = MiGetPteForProcess(Process, Address, TRUE);
|
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);
|
Address, TmplPte.u.Long, Pte);
|
||||||
|
|
||||||
if (InterlockedExchangePte(Pte, TmplPte))
|
if (InterlockedExchangePte(Pte, TmplPte))
|
||||||
|
@ -577,6 +590,44 @@ MmCreateVirtualMapping(PEPROCESS Process,
|
||||||
return MmCreateVirtualMappingUnsafe(Process, Address, Protect, Pages, PageCount);
|
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
|
BOOLEAN
|
||||||
NTAPI
|
NTAPI
|
||||||
MmCreateProcessAddressSpace(IN ULONG MinWs,
|
MmCreateProcessAddressSpace(IN ULONG MinWs,
|
||||||
|
@ -584,14 +635,19 @@ MmCreateProcessAddressSpace(IN ULONG MinWs,
|
||||||
OUT PULONG_PTR DirectoryTableBase)
|
OUT PULONG_PTR DirectoryTableBase)
|
||||||
{
|
{
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
PFN_NUMBER TableBasePfn, HyperPfn;
|
PFN_NUMBER TableBasePfn, HyperPfn, HyperPdPfn, HyperPtPfn, WorkingSetPfn;
|
||||||
PMMPTE PointerPte;
|
PMMPTE SystemPte;
|
||||||
MMPTE TempPte, PdePte;
|
MMPTE TempPte, PdePte;
|
||||||
ULONG TableIndex;
|
ULONG TableIndex;
|
||||||
PMMPTE SystemTable;
|
PMMPTE PageTablePointer;
|
||||||
|
|
||||||
/* No page colors yet */
|
/* Make sure we don't already have a page directory setup */
|
||||||
Process->NextPageColor = 0;
|
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 */
|
/* Setup the hyperspace lock */
|
||||||
KeInitializeSpinLock(&Process->HyperSpaceLock);
|
KeInitializeSpinLock(&Process->HyperSpaceLock);
|
||||||
|
@ -599,67 +655,97 @@ MmCreateProcessAddressSpace(IN ULONG MinWs,
|
||||||
/* Lock PFN database */
|
/* Lock PFN database */
|
||||||
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
|
||||||
|
|
||||||
/* Get a page for the table base and for hyperspace */
|
/* Get a page for the table base and one for hyper space. The PFNs for
|
||||||
TableBasePfn = MiRemoveAnyPage(0);
|
these pages will be initialized in MmInitializeProcessAddressSpace,
|
||||||
HyperPfn = MiRemoveAnyPage(0);
|
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 */
|
/* Release PFN lock */
|
||||||
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
|
||||||
|
|
||||||
/* Zero both pages */
|
/* Zero pages */ /// FIXME:
|
||||||
MiZeroPhysicalPage(TableBasePfn);
|
|
||||||
MiZeroPhysicalPage(HyperPfn);
|
MiZeroPhysicalPage(HyperPfn);
|
||||||
|
MiZeroPhysicalPage(WorkingSetPfn);
|
||||||
|
|
||||||
/* Set the base directory pointers */
|
/* Set the base directory pointers */
|
||||||
|
Process->WorkingSetPage = WorkingSetPfn;
|
||||||
DirectoryTableBase[0] = TableBasePfn << PAGE_SHIFT;
|
DirectoryTableBase[0] = TableBasePfn << PAGE_SHIFT;
|
||||||
DirectoryTableBase[1] = HyperPfn << 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 */
|
/* Get a PTE to map the page directory */
|
||||||
PointerPte = MiReserveSystemPtes(1, SystemPteSpace);
|
SystemPte = MiReserveSystemPtes(1, SystemPteSpace);
|
||||||
ASSERT(PointerPte != NULL);
|
ASSERT(SystemPte != NULL);
|
||||||
|
|
||||||
/* Build it */
|
/* Get its address */
|
||||||
MI_MAKE_HARDWARE_PTE_KERNEL(&PdePte,
|
PageTablePointer = MiPteToAddress(SystemPte);
|
||||||
PointerPte,
|
|
||||||
MM_READWRITE,
|
|
||||||
TableBasePfn);
|
|
||||||
|
|
||||||
/* Set it dirty and map it */
|
/* Build the PTE for the page directory and map it */
|
||||||
PdePte.u.Hard.Dirty = TRUE;
|
PdePte = ValidKernelPte;
|
||||||
MI_WRITE_VALID_PTE(PointerPte, PdePte);
|
PdePte.u.Hard.PageFrameNumber = TableBasePfn;
|
||||||
|
*SystemPte = PdePte;
|
||||||
|
|
||||||
/* Now get the page directory (which we'll double map, so call it a page table */
|
/// architecture specific
|
||||||
SystemTable = MiPteToAddress(PointerPte);
|
//MiInitializePageDirectoryForProcess(
|
||||||
|
|
||||||
/* Copy all the kernel mappings */
|
/* Copy the kernel mappings and zero out the rest */
|
||||||
TableIndex = MiAddressToPxi(MmSystemRangeStart);
|
TableIndex = PXE_PER_PAGE / 2;
|
||||||
|
RtlZeroMemory(PageTablePointer, TableIndex * sizeof(MMPTE));
|
||||||
RtlCopyMemory(&SystemTable[TableIndex],
|
RtlCopyMemory(PageTablePointer + TableIndex,
|
||||||
MiAddressToPxe(MmSystemRangeStart),
|
MiAddressToPxe(0) + TableIndex,
|
||||||
PAGE_SIZE - TableIndex * sizeof(MMPTE));
|
PAGE_SIZE - TableIndex * sizeof(MMPTE));
|
||||||
|
|
||||||
/* Now write the PTE/PDE entry for hyperspace itself */
|
|
||||||
TempPte = ValidKernelPte;
|
|
||||||
TempPte.u.Hard.PageFrameNumber = HyperPfn;
|
|
||||||
TableIndex = MiAddressToPxi((PVOID)HYPER_SPACE);
|
|
||||||
SystemTable[TableIndex] = TempPte;
|
|
||||||
|
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
ASSERT(MiAddressToPxi(MmHyperSpaceEnd) > TableIndex);
|
ASSERT(MiAddressToPxi(MmHyperSpaceEnd) >= TableIndex);
|
||||||
|
|
||||||
/* Now do the x86 trick of making the PDE a page table itself */
|
/* Setup a PTE for the page directory mappings */
|
||||||
TableIndex = MiAddressToPxi((PVOID)PTE_BASE);
|
TempPte = ValidKernelPte;
|
||||||
|
|
||||||
|
/* Update the self mapping of the PML4 */
|
||||||
|
TableIndex = MiAddressToPxi((PVOID)PXE_SELFMAP);
|
||||||
TempPte.u.Hard.PageFrameNumber = TableBasePfn;
|
TempPte.u.Hard.PageFrameNumber = TableBasePfn;
|
||||||
SystemTable[TableIndex] = TempPte;
|
PageTablePointer[TableIndex] = TempPte;
|
||||||
|
|
||||||
/* Let go of the system PTE */
|
/* Write the PML4 entry for hyperspace */
|
||||||
MiReleaseSystemPtes(PointerPte, 1, SystemPteSpace);
|
TableIndex = MiAddressToPxi((PVOID)HYPER_SPACE);
|
||||||
|
TempPte.u.Hard.PageFrameNumber = HyperPfn;
|
||||||
|
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 */
|
/* Switch to phase 1 initialization */
|
||||||
ASSERT(Process->AddressSpaceInitialized == 0);
|
ASSERT(Process->AddressSpaceInitialized == 0);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue