/* GLOBALS ********************************************************************/
ULONG MmProcessColorSeed = 0x12345678;
+PMMWSL MmWorkingSetList;
/* PRIVATE FUNCTIONS **********************************************************/
ASSERT((Vad->StartingVpn == ((ULONG_PTR)Teb >> PAGE_SHIFT) &&
(Vad->EndingVpn == (TebEnd >> PAGE_SHIFT))));
ASSERT(Vad->u.VadFlags.NoChange == TRUE);
+ ASSERT(Vad->u2.VadFlags2.OneSecured == TRUE);
ASSERT(Vad->u2.VadFlags2.MultipleSecured == FALSE);
/* Lock the working set */
PointerPte++;
/* Get a page and write the current invalid PTE */
+ MI_SET_USAGE(MI_USAGE_KERNEL_STACK);
+ MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
PageFrameIndex = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
MI_WRITE_INVALID_PTE(PointerPte, InvalidPte);
while (LimitPte >= NewLimitPte)
{
/* Get a page and write the current invalid PTE */
+ MI_SET_USAGE(MI_USAGE_KERNEL_STACK_EXPANSION);
+ MI_SET_PROCESS2(PsGetCurrentProcess()->ImageFileName);
PageFrameIndex = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
MI_WRITE_INVALID_PTE(LimitPte, InvalidPte);
return Status;
}
+VOID
+NTAPI
+MiInitializeWorkingSetList(IN PEPROCESS CurrentProcess)
+{
+ PMMPFN Pfn1;
+
+ /* Setup some bogus list data */
+ MmWorkingSetList->LastEntry = CurrentProcess->Vm.MinimumWorkingSetSize;
+ MmWorkingSetList->HashTable = NULL;
+ MmWorkingSetList->HashTableSize = 0;
+ MmWorkingSetList->NumberOfImageWaiters = 0;
+ MmWorkingSetList->Wsle = (PVOID)0xDEADBABE;
+ MmWorkingSetList->VadBitMapHint = 1;
+ MmWorkingSetList->HashTableStart = (PVOID)0xBADAB00B;
+ MmWorkingSetList->HighestPermittedHashAddress = (PVOID)0xCAFEBABE;
+ MmWorkingSetList->FirstFree = 1;
+ MmWorkingSetList->FirstDynamic = 2;
+ MmWorkingSetList->NextSlot = 3;
+ MmWorkingSetList->LastInitializedWsle = 4;
+
+ /* The rule is that the owner process is always in the FLINK of the PDE's PFN entry */
+ Pfn1 = MiGetPfnEntry(MiAddressToPte(PDE_BASE)->u.Hard.PageFrameNumber);
+ ASSERT(Pfn1->u4.PteFrame == MiGetPfnEntryIndex(Pfn1));
+ Pfn1->u1.Event = (PKEVENT)CurrentProcess;
+}
+
NTSTATUS
NTAPI
MmInitializeProcessAddressSpace(IN PEPROCESS Process,
PWCHAR Source;
PCHAR Destination;
USHORT Length = 0;
+ MMPTE TempPte;
/* We should have a PDE */
ASSERT(Process->Pcb.DirectoryTableBase[0] != 0);
PointerPde = MiAddressToPde(HYPER_SPACE);
PageFrameNumber = PFN_FROM_PTE(PointerPde);
MiInitializePfn(PageFrameNumber, PointerPde, TRUE);
+
+ /* Setup the PFN for the PTE for the working set */
+ PointerPte = MiAddressToPte(MI_WORKING_SET_LIST);
+ MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, MM_READWRITE, 0);
+ ASSERT(PointerPte->u.Long != 0);
+ PageFrameNumber = PFN_FROM_PTE(PointerPte);
+ MI_WRITE_INVALID_PTE(PointerPte, DemandZeroPte);
+ MiInitializePfn(PageFrameNumber, PointerPte, TRUE);
+ TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
+ MI_WRITE_VALID_PTE(PointerPte, TempPte);
+
+ /* Now initialize the working set list */
+ MiInitializeWorkingSetList(Process);
+
+ /* Sanity check */
+ ASSERT(Process->PhysicalVadRoot == NULL);
/* Release PFN lock */
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
NTSTATUS
NTAPI
+INIT_FUNCTION
MmInitializeHandBuiltProcess(IN PEPROCESS Process,
IN PULONG_PTR DirectoryTableBase)
{
NTSTATUS
NTAPI
+INIT_FUNCTION
MmInitializeHandBuiltProcess2(IN PEPROCESS Process)
{
/* Lock the VAD, ARM3-owned ranges away */
OUT PULONG_PTR DirectoryTableBase)
{
KIRQL OldIrql;
- PFN_NUMBER PdeIndex, HyperIndex;
+ PFN_NUMBER PdeIndex, HyperIndex, WsListIndex;
PMMPTE PointerPte;
MMPTE TempPte, PdePte;
ULONG PdeOffset;
- PMMPTE SystemTable;
+ PMMPTE SystemTable, HyperTable;
ULONG Color;
+ PMMPFN Pfn1;
/* Choose a process color */
Process->NextPageColor = RtlRandom(&MmProcessColorSeed);
/* Get a zero page for the PDE, if possible */
Color = MI_GET_NEXT_PROCESS_COLOR(Process);
+ MI_SET_USAGE(MI_USAGE_PAGE_DIRECTORY);
PdeIndex = MiRemoveZeroPageSafe(Color);
if (!PdeIndex)
{
}
/* Get a zero page for hyperspace, if possible */
+ MI_SET_USAGE(MI_USAGE_PAGE_DIRECTORY);
Color = MI_GET_NEXT_PROCESS_COLOR(Process);
HyperIndex = MiRemoveZeroPageSafe(Color);
if (!HyperIndex)
/* Zero it outside the PFN lock */
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
MiZeroPhysicalPage(HyperIndex);
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ }
+
+ /* Get a zero page for the woring set list, if possible */
+ MI_SET_USAGE(MI_USAGE_PAGE_TABLE);
+ Color = MI_GET_NEXT_PROCESS_COLOR(Process);
+ WsListIndex = MiRemoveZeroPageSafe(Color);
+ if (!WsListIndex)
+ {
+ /* No zero pages, grab a free one */
+ WsListIndex = MiRemoveAnyPage(Color);
+
+ /* Zero it outside the PFN lock */
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ MiZeroPhysicalPage(WsListIndex);
}
else
{
Process->AddressSpaceInitialized = 1;
/* Set the base directory pointers */
+ Process->WorkingSetPage = WsListIndex;
DirectoryTableBase[0] = PdeIndex << PAGE_SHIFT;
DirectoryTableBase[1] = HyperIndex << PAGE_SHIFT;
/* Make sure we don't already have a page directory setup */
ASSERT(Process->Pcb.DirectoryTableBase[0] == 0);
+
+ /* Get a PTE to map hyperspace */
+ PointerPte = MiReserveSystemPtes(1, SystemPteSpace);
+ ASSERT(PointerPte != NULL);
+
+ /* Build it */
+ MI_MAKE_HARDWARE_PTE_KERNEL(&PdePte,
+ PointerPte,
+ MM_READWRITE,
+ HyperIndex);
+
+ /* Set it dirty and map it */
+ PdePte.u.Hard.Dirty = TRUE;
+ MI_WRITE_VALID_PTE(PointerPte, PdePte);
+
+ /* Now get hyperspace's page table */
+ HyperTable = MiPteToAddress(PointerPte);
+
+ /* Now write the PTE/PDE entry for the working set list index itself */
+ TempPte = ValidKernelPte;
+ TempPte.u.Hard.PageFrameNumber = WsListIndex;
+ PdeOffset = MiAddressToPteOffset(MmWorkingSetList);
+ HyperTable[PdeOffset] = TempPte;
+
+ /* Let go of the system PTE */
+ MiReleaseSystemPtes(PointerPte, 1, SystemPteSpace);
+
+ /* Save the PTE address of the page directory itself */
+ Pfn1 = MiGetPfnEntry(PdeIndex);
+ Pfn1->PteAddress = (PMMPTE)PDE_BASE;
/* Insert us into the Mm process list */
InsertTailList(&MmProcessList, &Process->MmProcessLinks);
PMM_AVL_TABLE VadTree;
PETHREAD Thread = PsGetCurrentThread();
+ /* Only support this */
+ ASSERT(Process->AddressSpaceInitialized == 2);
+
/* Lock the process address space from changes */
MmLockAddressSpace(&Process->Vm);
+ /* VM is deleted now */
+ Process->VmDeleted = TRUE;
+
/* Enumerate the VADs */
VadTree = &Process->VadRoot;
while (VadTree->NumberGenericTableElements)