X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=ntoskrnl%2Fmm%2FARM3%2Fprocsup.c;h=857a181fefd5724217560c8b6074cc5d4a1a0b5a;hp=e12ad48fe59dfc00901e39d62a93beced7b1a6ac;hb=82822656c3b240860ac8d5db139c56285634e8a5;hpb=c16ad873a687c7fc3ec343b972e038e153a75e8b diff --git a/ntoskrnl/mm/ARM3/procsup.c b/ntoskrnl/mm/ARM3/procsup.c index e12ad48fe59..857a181fefd 100644 --- a/ntoskrnl/mm/ARM3/procsup.c +++ b/ntoskrnl/mm/ARM3/procsup.c @@ -18,12 +18,189 @@ extern MM_SYSTEMSIZE MmSystemSize; -PVOID +/* PRIVATE FUNCTIONS **********************************************************/ + +VOID NTAPI -MiCreatePebOrTeb(PEPROCESS Process, - PVOID BaseAddress); +MiRosTakeOverPebTebRanges(IN PEPROCESS Process) +{ + NTSTATUS Status; + PMEMORY_AREA MemoryArea; + PHYSICAL_ADDRESS BoundaryAddressMultiple; + PVOID AllocatedBase = (PVOID)MI_LOWEST_VAD_ADDRESS; + BoundaryAddressMultiple.QuadPart = 0; -/* PRIVATE FUNCTIONS **********************************************************/ + Status = MmCreateMemoryArea(&Process->Vm, + MEMORY_AREA_OWNED_BY_ARM3, + &AllocatedBase, + ((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - 1) - + (ULONG_PTR)MI_LOWEST_VAD_ADDRESS, + PAGE_READWRITE, + &MemoryArea, + TRUE, + 0, + BoundaryAddressMultiple); + ASSERT(NT_SUCCESS(Status)); +} + +NTSTATUS +NTAPI +MiCreatePebOrTeb(IN PEPROCESS Process, + IN ULONG Size, + OUT PULONG_PTR Base) +{ + PETHREAD Thread = PsGetCurrentThread(); + PMMVAD_LONG Vad; + NTSTATUS Status; + ULONG RandomCoeff; + ULONG_PTR StartAddress, EndAddress; + LARGE_INTEGER CurrentTime; + + /* Allocate a VAD */ + Vad = ExAllocatePoolWithTag(NonPagedPool, sizeof(MMVAD_LONG), 'ldaV'); + if (!Vad) return STATUS_NO_MEMORY; + + /* Setup the primary flags with the size, and make it commited, private, RW */ + Vad->u.LongFlags = 0; + Vad->u.VadFlags.CommitCharge = BYTES_TO_PAGES(Size); + Vad->u.VadFlags.MemCommit = TRUE; + Vad->u.VadFlags.PrivateMemory = TRUE; + Vad->u.VadFlags.Protection = MM_READWRITE; + Vad->u.VadFlags.NoChange = TRUE; + + /* Setup the secondary flags to make it a secured, writable, long VAD */ + Vad->u2.LongFlags2 = 0; + Vad->u2.VadFlags2.OneSecured = TRUE; + Vad->u2.VadFlags2.LongVad = TRUE; + Vad->u2.VadFlags2.ReadOnly = FALSE; + + /* Lock the process address space */ + KeAcquireGuardedMutex(&Process->AddressCreationLock); + + /* Check if this is a PEB creation */ + if (Size == sizeof(PEB)) + { + /* Start at the highest valid address */ + StartAddress = (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1; + + /* Select the random coefficient */ + KeQueryTickCount(&CurrentTime); + CurrentTime.LowPart &= ((64 * _1KB) >> PAGE_SHIFT) - 1; + if (CurrentTime.LowPart <= 1) CurrentTime.LowPart = 2; + RandomCoeff = CurrentTime.LowPart << PAGE_SHIFT; + + /* Select the highest valid address minus the random coefficient */ + StartAddress -= RandomCoeff; + EndAddress = StartAddress + ROUND_TO_PAGES(Size) - 1; + + /* See if this VA range can be obtained */ + if (!MiCheckForConflictingNode(StartAddress >> PAGE_SHIFT, + EndAddress >> PAGE_SHIFT, + &Process->VadRoot)) + { + /* No conflict, use this address */ + *Base = StartAddress; + goto AfterFound; + } + } + + /* For TEBs, or if a PEB location couldn't be found, scan the VAD root */ + Status = MiFindEmptyAddressRangeDownTree(ROUND_TO_PAGES(Size), + (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1, + PAGE_SIZE, + &Process->VadRoot, + Base); + ASSERT(NT_SUCCESS(Status)); + +AfterFound: + /* Validate that it came from the VAD ranges */ + ASSERT(*Base >= (ULONG_PTR)MI_LOWEST_VAD_ADDRESS); + + /* Build the rest of the VAD now */ + Vad->StartingVpn = (*Base) >> PAGE_SHIFT; + Vad->EndingVpn = ((*Base) + Size - 1) >> PAGE_SHIFT; + Vad->u3.Secured.StartVpn = *Base; + Vad->u3.Secured.EndVpn = (Vad->EndingVpn << PAGE_SHIFT) | (PAGE_SIZE - 1); + + /* FIXME: Should setup VAD bitmap */ + Status = STATUS_SUCCESS; + + /* Pretend as if we own the working set */ + MiLockProcessWorkingSet(Process, Thread); + + /* Insert the VAD */ + ASSERT(Vad->EndingVpn >= Vad->StartingVpn); + Process->VadRoot.NodeHint = Vad; + MiInsertNode((PVOID)Vad, &Process->VadRoot); + + /* Release the working set */ + MiUnlockProcessWorkingSet(Process, Thread); + + /* Release the address space lock */ + KeReleaseGuardedMutex(&Process->AddressCreationLock); + + /* Return the status */ + DPRINT("Allocated PEB/TEB at: 0x%p for %16s\n", *Base, Process->ImageFileName); + return Status; +} + +VOID +NTAPI +MmDeleteTeb(IN PEPROCESS Process, + IN PTEB Teb) +{ + ULONG_PTR TebEnd; + PETHREAD Thread = PsGetCurrentThread(); + PMMVAD Vad; + PMM_AVL_TABLE VadTree = &Process->VadRoot; + DPRINT("Deleting TEB: %p in %16s\n", Teb, Process->ImageFileName); + + /* TEB is one page */ + TebEnd = (ULONG_PTR)Teb + ROUND_TO_PAGES(sizeof(TEB)) - 1; + + /* Attach to the process */ + KeAttachProcess(&Process->Pcb); + + /* Lock the process address space */ + KeAcquireGuardedMutex(&Process->AddressCreationLock); + + /* Find the VAD, make sure it's a TEB VAD */ + Vad = MiLocateAddress(Teb); + DPRINT("Removing node for VAD: %lx %lx\n", Vad->StartingVpn, Vad->EndingVpn); + ASSERT(Vad != NULL); + if (Vad->StartingVpn != ((ULONG_PTR)Teb >> PAGE_SHIFT)) + { + /* Bug in the AVL code? */ + DPRINT1("Corrupted VAD!\n"); + } + else + { + /* Sanity checks for a valid TEB VAD */ + ASSERT((Vad->StartingVpn == ((ULONG_PTR)Teb >> PAGE_SHIFT) && + (Vad->EndingVpn == (TebEnd >> PAGE_SHIFT)))); + ASSERT(Vad->u.VadFlags.NoChange == TRUE); + ASSERT(Vad->u2.VadFlags2.MultipleSecured == FALSE); + + /* Lock the working set */ + MiLockProcessWorkingSet(Process, Thread); + + /* Remove this VAD from the tree */ + ASSERT(VadTree->NumberGenericTableElements >= 1); + MiRemoveNode((PMMADDRESS_NODE)Vad, VadTree); + + /* Release the working set */ + MiUnlockProcessWorkingSet(Process, Thread); + + /* Remove the VAD */ + ExFreePool(Vad); + } + + /* Release the address space lock */ + KeReleaseGuardedMutex(&Process->AddressCreationLock); + + /* Detach */ + KeDetachProcess(); +} VOID NTAPI @@ -31,8 +208,10 @@ MmDeleteKernelStack(IN PVOID StackBase, IN BOOLEAN GuiStack) { PMMPTE PointerPte; - PFN_NUMBER StackPages; + PFN_NUMBER StackPages, PageFrameNumber;//, PageTableFrameNumber; + PMMPFN Pfn1;//, Pfn2; ULONG i; + KIRQL OldIrql; // // This should be the guard page, so decrement by one @@ -46,6 +225,9 @@ MmDeleteKernelStack(IN PVOID StackBase, StackPages = BYTES_TO_PAGES(GuiStack ? KERNEL_LARGE_STACK_SIZE : KERNEL_STACK_SIZE); + /* Acquire the PFN lock */ + OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); + // // Loop them // @@ -56,10 +238,22 @@ MmDeleteKernelStack(IN PVOID StackBase, // if (PointerPte->u.Hard.Valid == 1) { - // - // Nuke it - // - MmReleasePageMemoryConsumer(MC_NPPOOL, PFN_FROM_PTE(PointerPte)); + /* Get the PTE's page */ + PageFrameNumber = PFN_FROM_PTE(PointerPte); + Pfn1 = MiGetPfnEntry(PageFrameNumber); +#if 0 // ARM3 might not own the page table, so don't take this risk. Leak it instead! + /* Now get the page of the page table mapping it */ + PageTableFrameNumber = Pfn1->u4.PteFrame; + Pfn2 = MiGetPfnEntry(PageTableFrameNumber); + + /* Remove a shared reference, since the page is going away */ + MiDecrementShareCount(Pfn2, PageTableFrameNumber); +#endif + /* Set the special pending delete marker */ + Pfn1->PteAddress = (PMMPTE)((ULONG_PTR)Pfn1->PteAddress | 1); + + /* And now delete the actual stack page */ + MiDecrementShareCount(Pfn1, PageFrameNumber); } // @@ -73,6 +267,9 @@ MmDeleteKernelStack(IN PVOID StackBase, // ASSERT(PointerPte->u.Hard.Valid == 0); + /* Release the PFN lock */ + KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); + // // Release the PTEs // @@ -87,7 +284,7 @@ MmCreateKernelStack(IN BOOLEAN GuiStack, PFN_NUMBER StackPtes, StackPages; PMMPTE PointerPte, StackPte; PVOID BaseAddress; - MMPTE TempPte; + MMPTE TempPte, InvalidPte; KIRQL OldIrql; PFN_NUMBER PageFrameIndex; ULONG i; @@ -131,13 +328,12 @@ MmCreateKernelStack(IN BOOLEAN GuiStack, if (GuiStack) PointerPte += BYTES_TO_PAGES(KERNEL_LARGE_STACK_SIZE - KERNEL_LARGE_STACK_COMMIT); - // - // Setup the template stack PTE - // - TempPte = ValidKernelPte; - MI_MAKE_LOCAL_PAGE(&TempPte); - MI_MAKE_DIRTY_PAGE(&TempPte); - TempPte.u.Hard.PageFrameNumber = 0; + + /* Setup the temporary invalid PTE */ + MI_MAKE_SOFTWARE_PTE(&InvalidPte, MM_NOACCESS); + + /* Setup the template stack PTE */ + MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte, PointerPte + 1, MM_READWRITE, 0); // // Acquire the PFN DB lock @@ -153,18 +349,17 @@ MmCreateKernelStack(IN BOOLEAN GuiStack, // Next PTE // PointerPte++; - ASSERT(PointerPte->u.Hard.Valid == 0); - // - // Get a page - // - PageFrameIndex = MmAllocPage(MC_NPPOOL); - TempPte.u.Hard.PageFrameNumber = PageFrameIndex; + /* Get a page and write the current invalid PTE */ + PageFrameIndex = MiRemoveAnyPage(0); + MI_WRITE_INVALID_PTE(PointerPte, InvalidPte); + + /* Initialize the PFN entry for this page */ + MiInitializePfn(PageFrameIndex, PointerPte, 1); - // - // Write it - // - *PointerPte = TempPte; + /* Write the valid PTE */ + TempPte.u.Hard.PageFrameNumber = PageFrameIndex; + MI_WRITE_VALID_PTE(PointerPte, TempPte); } // Bug #4835 @@ -190,7 +385,7 @@ MmGrowKernelStackEx(IN PVOID StackPointer, PMMPTE LimitPte, NewLimitPte, LastPte; PFN_NUMBER StackPages; KIRQL OldIrql; - MMPTE TempPte; + MMPTE TempPte, InvalidPte; PFN_NUMBER PageFrameIndex; // @@ -231,39 +426,31 @@ MmGrowKernelStackEx(IN PVOID StackPointer, LimitPte--; StackPages = (LimitPte - NewLimitPte + 1); - // - // Setup the template stack PTE - // - TempPte = ValidKernelPte; - MI_MAKE_LOCAL_PAGE(&TempPte); - MI_MAKE_DIRTY_PAGE(&TempPte); - TempPte.u.Hard.PageFrameNumber = 0; + /* Setup the temporary invalid PTE */ + MI_MAKE_SOFTWARE_PTE(&InvalidPte, MM_NOACCESS); // // Acquire the PFN DB lock // OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); - + // // Loop each stack page // while (LimitPte >= NewLimitPte) { - // - // Sanity check - // - ASSERT(LimitPte->u.Hard.Valid == 0); + /* Get a page and write the current invalid PTE */ + PageFrameIndex = MiRemoveAnyPage(0); + MI_WRITE_INVALID_PTE(LimitPte, InvalidPte); + + /* Initialize the PFN entry for this page */ + MiInitializePfn(PageFrameIndex, LimitPte, 1); - // - // Get a page - // - PageFrameIndex = MmAllocPage(MC_NPPOOL); - TempPte.u.Hard.PageFrameNumber = PageFrameIndex; + /* Setup the template stack PTE */ + MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte, LimitPte, MM_READWRITE, PageFrameIndex); - // - // Write it - // - *LimitPte-- = TempPte; + /* Write the valid PTE */ + MI_WRITE_VALID_PTE(LimitPte--, TempPte); } // @@ -382,10 +569,9 @@ MmCreatePeb(IN PEPROCESS Process, // // Allocate the PEB // - Peb = MiCreatePebOrTeb(Process, - (PVOID)((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1)); - ASSERT(Peb == (PVOID)0x7FFDF000); - + Status = MiCreatePebOrTeb(Process, sizeof(PEB), (PULONG_PTR)&Peb); + ASSERT(NT_SUCCESS(Status)); + // // Map NLS Tables // @@ -503,7 +689,7 @@ MmCreatePeb(IN PEPROCESS Process, ImageConfigData = RtlImageDirectoryEntryToData(Peb->ImageBaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, - &ViewSize); + (PULONG)&ViewSize); if (ImageConfigData) { // @@ -517,9 +703,9 @@ MmCreatePeb(IN PEPROCESS Process, // // Write subsystem data // - Peb->ImageSubSystem = NtHeaders->OptionalHeader.Subsystem; - Peb->ImageSubSystemMajorVersion = NtHeaders->OptionalHeader.MajorSubsystemVersion; - Peb->ImageSubSystemMinorVersion = NtHeaders->OptionalHeader.MinorSubsystemVersion; + Peb->ImageSubsystem = NtHeaders->OptionalHeader.Subsystem; + Peb->ImageSubsystemMajorVersion = NtHeaders->OptionalHeader.MajorSubsystemVersion; + Peb->ImageSubsystemMinorVersion = NtHeaders->OptionalHeader.MinorSubsystemVersion; // // Check for version data @@ -618,9 +804,8 @@ MmCreateTeb(IN PEPROCESS Process, // // Allocate the TEB // - Teb = MiCreatePebOrTeb(Process, - (PVOID)((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1)); - if (!Teb) return STATUS_INSUFFICIENT_RESOURCES; + Status = MiCreatePebOrTeb(Process, sizeof(TEB), (PULONG_PTR)&Teb); + ASSERT(NT_SUCCESS(Status)); // // Use SEH in case we can't load the TEB @@ -635,13 +820,13 @@ MmCreateTeb(IN PEPROCESS Process, // // Set TIB Data // - Teb->Tib.ExceptionList = EXCEPTION_CHAIN_END; - Teb->Tib.Self = (PNT_TIB)Teb; + Teb->NtTib.ExceptionList = EXCEPTION_CHAIN_END; + Teb->NtTib.Self = (PNT_TIB)Teb; // // Identify this as an OS/2 V3.0 ("Cruiser") TIB // - Teb->Tib.Version = 30 << 8; + Teb->NtTib.Version = 30 << 8; // // Set TEB Data @@ -660,8 +845,8 @@ MmCreateTeb(IN PEPROCESS Process, // // Use initial TEB values // - Teb->Tib.StackBase = InitialTeb->StackBase; - Teb->Tib.StackLimit = InitialTeb->StackLimit; + Teb->NtTib.StackBase = InitialTeb->StackBase; + Teb->NtTib.StackLimit = InitialTeb->StackLimit; Teb->DeallocationStack = InitialTeb->AllocatedStackBase; } else @@ -669,8 +854,8 @@ MmCreateTeb(IN PEPROCESS Process, // // Use grandparent TEB values // - Teb->Tib.StackBase = InitialTeb->PreviousStackBase; - Teb->Tib.StackLimit = InitialTeb->PreviousStackLimit; + Teb->NtTib.StackBase = InitialTeb->PreviousStackBase; + Teb->NtTib.StackLimit = InitialTeb->PreviousStackLimit; } // @@ -696,6 +881,308 @@ MmCreateTeb(IN PEPROCESS Process, return Status; } +NTSTATUS +NTAPI +MmInitializeProcessAddressSpace(IN PEPROCESS Process, + IN PEPROCESS ProcessClone OPTIONAL, + IN PVOID Section OPTIONAL, + IN OUT PULONG Flags, + IN POBJECT_NAME_INFORMATION *AuditName OPTIONAL) +{ + NTSTATUS Status = STATUS_SUCCESS; + SIZE_T ViewSize = 0; + PVOID ImageBase = 0; + PROS_SECTION_OBJECT SectionObject = Section; + PMMPTE PointerPte; + KIRQL OldIrql; + PMMPDE PointerPde; + PFN_NUMBER PageFrameNumber; + UNICODE_STRING FileName; + PWCHAR Source; + PCHAR Destination; + USHORT Length = 0; + + /* We should have a PDE */ + ASSERT(Process->Pcb.DirectoryTableBase[0] != 0); + ASSERT(Process->PdeUpdateNeeded == FALSE); + + /* Attach to the process */ + KeAttachProcess(&Process->Pcb); + + /* The address space should now been in phase 1 or 0 */ + ASSERT(Process->AddressSpaceInitialized <= 1); + Process->AddressSpaceInitialized = 2; + + /* Initialize the Addresss Space lock */ + KeInitializeGuardedMutex(&Process->AddressCreationLock); + Process->Vm.WorkingSetExpansionLinks.Flink = NULL; + + /* Initialize AVL tree */ + ASSERT(Process->VadRoot.NumberGenericTableElements == 0); + Process->VadRoot.BalancedRoot.u1.Parent = &Process->VadRoot.BalancedRoot; + + /* Lock PFN database */ + OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); + + /* Setup the PFN for the PDE base of this process */ + PointerPte = MiAddressToPte(PDE_BASE); + PageFrameNumber = PFN_FROM_PTE(PointerPte); + MiInitializePfn(PageFrameNumber, PointerPte, TRUE); + + /* Do the same for hyperspace */ + PointerPde = MiAddressToPde(HYPER_SPACE); + PageFrameNumber = PFN_FROM_PTE(PointerPde); + MiInitializePfn(PageFrameNumber, PointerPde, TRUE); + + /* Release PFN lock */ + KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); + + /* Lock the VAD, ARM3-owned ranges away */ + MiRosTakeOverPebTebRanges(Process); + + /* Check if there's a Section Object */ + if (SectionObject) + { + /* Determine the image file name and save it to EPROCESS */ + FileName = SectionObject->FileObject->FileName; + Source = (PWCHAR)((PCHAR)FileName.Buffer + FileName.Length); + if (FileName.Buffer) + { + /* Loop the file name*/ + while (Source > FileName.Buffer) + { + /* Make sure this isn't a backslash */ + if (*--Source == OBJ_NAME_PATH_SEPARATOR) + { + /* If so, stop it here */ + Source++; + break; + } + else + { + /* Otherwise, keep going */ + Length++; + } + } + } + + /* Copy the to the process and truncate it to 15 characters if necessary */ + Destination = Process->ImageFileName; + Length = min(Length, sizeof(Process->ImageFileName) - 1); + while (Length--) *Destination++ = (UCHAR)*Source++; + *Destination = ANSI_NULL; + + /* Check if caller wants an audit name */ + if (AuditName) + { + /* Setup the audit name */ + Status = SeInitializeProcessAuditName(SectionObject->FileObject, + FALSE, + AuditName); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + KeDetachProcess(); + return Status; + } + } + + /* Map the section */ + Status = MmMapViewOfSection(Section, + Process, + (PVOID*)&ImageBase, + 0, + 0, + NULL, + &ViewSize, + 0, + MEM_COMMIT, + PAGE_READWRITE); + + /* Save the pointer */ + Process->SectionBaseAddress = ImageBase; + } + + /* Be nice and detach */ + KeDetachProcess(); + + /* Return status to caller */ + return Status; +} + +NTSTATUS +NTAPI +MmInitializeHandBuiltProcess(IN PEPROCESS Process, + IN PULONG_PTR DirectoryTableBase) +{ + /* Share the directory base with the idle process */ + DirectoryTableBase[0] = PsGetCurrentProcess()->Pcb.DirectoryTableBase[0]; + DirectoryTableBase[1] = PsGetCurrentProcess()->Pcb.DirectoryTableBase[1]; + + /* Initialize the Addresss Space */ + KeInitializeGuardedMutex(&Process->AddressCreationLock); + KeInitializeSpinLock(&Process->HyperSpaceLock); + Process->Vm.WorkingSetExpansionLinks.Flink = NULL; + ASSERT(Process->VadRoot.NumberGenericTableElements == 0); + Process->VadRoot.BalancedRoot.u1.Parent = &Process->VadRoot.BalancedRoot; + + /* Done */ + Process->HasAddressSpace = TRUE;//?? + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +MmInitializeHandBuiltProcess2(IN PEPROCESS Process) +{ + /* Lock the VAD, ARM3-owned ranges away */ + MiRosTakeOverPebTebRanges(Process); + return STATUS_SUCCESS; +} + +/* FIXME: Evaluate ways to make this portable yet arch-specific */ +BOOLEAN +NTAPI +MmCreateProcessAddressSpace(IN ULONG MinWs, + IN PEPROCESS Process, + OUT PULONG_PTR DirectoryTableBase) +{ + KIRQL OldIrql; + PFN_NUMBER PdeIndex, HyperIndex; + PMMPTE PointerPte; + MMPTE TempPte, PdePte; + ULONG PdeOffset; + PMMPTE SystemTable; + + /* No page colors yet */ + Process->NextPageColor = 0; + + /* Setup the hyperspace lock */ + KeInitializeSpinLock(&Process->HyperSpaceLock); + + /* Lock PFN database */ + OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); + + /* Get a page for the PDE */ + PdeIndex = MiRemoveAnyPage(0); + KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); + MiZeroPhysicalPage(PdeIndex); + OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); + + /* Get a page for hyperspace */ + HyperIndex = MiRemoveAnyPage(0); + KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); + MiZeroPhysicalPage(HyperIndex); + + /* Switch to phase 1 initialization */ + ASSERT(Process->AddressSpaceInitialized == 0); + Process->AddressSpaceInitialized = 1; + + /* Set the base directory pointers */ + 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); + + /* 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, + PdeIndex); + + /* 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 */ + PdeOffset = MiGetPdeOffset(MmSystemRangeStart); + + RtlCopyMemory(&SystemTable[PdeOffset], + MiAddressToPde(MmSystemRangeStart), + PAGE_SIZE - PdeOffset * sizeof(MMPTE)); + + /* Now write the PTE/PDE entry for hyperspace itself */ + TempPte = ValidKernelPte; + TempPte.u.Hard.PageFrameNumber = HyperIndex; + PdeOffset = MiGetPdeOffset(HYPER_SPACE); + SystemTable[PdeOffset] = TempPte; + + /* Sanity check */ + PdeOffset++; + ASSERT(MiGetPdeOffset(MmHyperSpaceEnd) >= PdeOffset); + + /* Now do the x86 trick of making the PDE a page table itself */ + PdeOffset = MiGetPdeOffset(PTE_BASE); + TempPte.u.Hard.PageFrameNumber = PdeIndex; + SystemTable[PdeOffset] = TempPte; + + /* Let go of the system PTE */ + MiReleaseSystemPtes(PointerPte, 1, SystemPteSpace); + return TRUE; +} + +VOID +NTAPI +MmCleanProcessAddressSpace(IN PEPROCESS Process) +{ + PMMVAD Vad; + PMM_AVL_TABLE VadTree; + PETHREAD Thread = PsGetCurrentThread(); + + /* Lock the process address space from changes */ + MmLockAddressSpace(&Process->Vm); + + /* Enumerate the VADs */ + VadTree = &Process->VadRoot; + DPRINT("Cleaning up VADs: %d\n", VadTree->NumberGenericTableElements); + while (VadTree->NumberGenericTableElements) + { + /* Grab the current VAD */ + Vad = (PMMVAD)VadTree->BalancedRoot.RightChild; + + /* Lock the working set */ + MiLockProcessWorkingSet(Process, Thread); + + /* Remove this VAD from the tree */ + ASSERT(VadTree->NumberGenericTableElements >= 1); + DPRINT("Removing node for VAD: %lx %lx\n", Vad->StartingVpn, Vad->EndingVpn); + MiRemoveNode((PMMADDRESS_NODE)Vad, VadTree); + DPRINT("Moving on: %d\n", VadTree->NumberGenericTableElements); + + /* Check if this VAD was the hint */ + if (VadTree->NodeHint == Vad) + { + /* Get a new hint, unless we're empty now, in which case nothing */ + VadTree->NodeHint = VadTree->BalancedRoot.RightChild; + if (!VadTree->NumberGenericTableElements) VadTree->NodeHint = NULL; + } + + /* Only PEB/TEB VADs supported for now */ + ASSERT(Vad->u.VadFlags.PrivateMemory == 1); + ASSERT(Vad->u.VadFlags.VadType == VadNone); + + /* Release the working set */ + MiUnlockProcessWorkingSet(Process, Thread); + + /* Free the VAD memory */ + ExFreePool(Vad); + } + + /* Release the address space */ + MmUnlockAddressSpace(&Process->Vm); +} + /* SYSTEM CALLS ***************************************************************/ NTSTATUS