2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/mm/ARM3/procsup.c
5 * PURPOSE: ARM Memory Manager Process Related Management
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
15 #line 15 "ARMĀ³::PROCSUP"
16 #define MODULE_INVOLVED_IN_ARM3
17 #include "../ARM3/miarm.h"
19 extern MM_SYSTEMSIZE MmSystemSize
;
21 /* PRIVATE FUNCTIONS **********************************************************/
25 MiRosTakeOverPebTebRanges(IN PEPROCESS Process
)
28 PMEMORY_AREA MemoryArea
;
29 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
30 PVOID AllocatedBase
= (PVOID
)MI_LOWEST_VAD_ADDRESS
;
31 BoundaryAddressMultiple
.QuadPart
= 0;
33 Status
= MmCreateMemoryArea(&Process
->Vm
,
34 MEMORY_AREA_OWNED_BY_ARM3
,
36 ((ULONG_PTR
)MM_HIGHEST_USER_ADDRESS
- 1) -
37 (ULONG_PTR
)MI_LOWEST_VAD_ADDRESS
,
42 BoundaryAddressMultiple
);
43 ASSERT(NT_SUCCESS(Status
));
48 MiCreatePebOrTeb(IN PEPROCESS Process
,
52 PETHREAD Thread
= PsGetCurrentThread();
56 ULONG_PTR StartAddress
, EndAddress
;
57 LARGE_INTEGER CurrentTime
;
60 Vad
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(MMVAD_LONG
), 'ldaV');
61 if (!Vad
) return STATUS_NO_MEMORY
;
63 /* Setup the primary flags with the size, and make it commited, private, RW */
65 Vad
->u
.VadFlags
.CommitCharge
= BYTES_TO_PAGES(Size
);
66 Vad
->u
.VadFlags
.MemCommit
= TRUE
;
67 Vad
->u
.VadFlags
.PrivateMemory
= TRUE
;
68 Vad
->u
.VadFlags
.Protection
= MM_READWRITE
;
69 Vad
->u
.VadFlags
.NoChange
= TRUE
;
71 /* Setup the secondary flags to make it a secured, writable, long VAD */
72 Vad
->u2
.LongFlags2
= 0;
73 Vad
->u2
.VadFlags2
.OneSecured
= TRUE
;
74 Vad
->u2
.VadFlags2
.LongVad
= TRUE
;
75 Vad
->u2
.VadFlags2
.ReadOnly
= FALSE
;
77 /* Lock the process address space */
78 KeAcquireGuardedMutex(&Process
->AddressCreationLock
);
80 /* Check if this is a PEB creation */
81 if (Size
== sizeof(PEB
))
83 /* Start at the highest valid address */
84 StartAddress
= (ULONG_PTR
)MM_HIGHEST_VAD_ADDRESS
+ 1;
86 /* Select the random coefficient */
87 KeQueryTickCount(&CurrentTime
);
88 CurrentTime
.LowPart
&= ((64 * _1KB
) >> PAGE_SHIFT
) - 1;
89 if (CurrentTime
.LowPart
<= 1) CurrentTime
.LowPart
= 2;
90 RandomCoeff
= CurrentTime
.LowPart
<< PAGE_SHIFT
;
92 /* Select the highest valid address minus the random coefficient */
93 StartAddress
-= RandomCoeff
;
94 EndAddress
= StartAddress
+ ROUND_TO_PAGES(Size
) - 1;
96 /* See if this VA range can be obtained */
97 if (!MiCheckForConflictingNode(StartAddress
>> PAGE_SHIFT
,
98 EndAddress
>> PAGE_SHIFT
,
101 /* No conflict, use this address */
102 *Base
= StartAddress
;
107 /* For TEBs, or if a PEB location couldn't be found, scan the VAD root */
108 Status
= MiFindEmptyAddressRangeDownTree(ROUND_TO_PAGES(Size
),
109 (ULONG_PTR
)MM_HIGHEST_VAD_ADDRESS
+ 1,
113 ASSERT(NT_SUCCESS(Status
));
116 /* Validate that it came from the VAD ranges */
117 ASSERT(*Base
>= (ULONG_PTR
)MI_LOWEST_VAD_ADDRESS
);
119 /* Build the rest of the VAD now */
120 Vad
->StartingVpn
= (*Base
) >> PAGE_SHIFT
;
121 Vad
->EndingVpn
= ((*Base
) + Size
- 1) >> PAGE_SHIFT
;
122 Vad
->u3
.Secured
.StartVpn
= *Base
;
123 Vad
->u3
.Secured
.EndVpn
= (Vad
->EndingVpn
<< PAGE_SHIFT
) | (PAGE_SIZE
- 1);
125 /* FIXME: Should setup VAD bitmap */
126 Status
= STATUS_SUCCESS
;
128 /* Pretend as if we own the working set */
129 MiLockProcessWorkingSet(Process
, Thread
);
132 ASSERT(Vad
->EndingVpn
>= Vad
->StartingVpn
);
133 Process
->VadRoot
.NodeHint
= Vad
;
134 MiInsertNode((PVOID
)Vad
, &Process
->VadRoot
);
136 /* Release the working set */
137 MiUnlockProcessWorkingSet(Process
, Thread
);
139 /* Release the address space lock */
140 KeReleaseGuardedMutex(&Process
->AddressCreationLock
);
142 /* Return the status */
143 DPRINT("Allocated PEB/TEB at: 0x%p for %16s\n", *Base
, Process
->ImageFileName
);
149 MmDeleteTeb(IN PEPROCESS Process
,
153 PETHREAD Thread
= PsGetCurrentThread();
155 PMM_AVL_TABLE VadTree
= &Process
->VadRoot
;
156 DPRINT("Deleting TEB: %p in %16s\n", Teb
, Process
->ImageFileName
);
158 /* TEB is one page */
159 TebEnd
= (ULONG_PTR
)Teb
+ ROUND_TO_PAGES(sizeof(TEB
)) - 1;
161 /* Attach to the process */
162 KeAttachProcess(&Process
->Pcb
);
164 /* Lock the process address space */
165 KeAcquireGuardedMutex(&Process
->AddressCreationLock
);
167 /* Find the VAD, make sure it's a TEB VAD */
168 Vad
= MiLocateAddress(Teb
);
169 DPRINT("Removing node for VAD: %lx %lx\n", Vad
->StartingVpn
, Vad
->EndingVpn
);
171 if (Vad
->StartingVpn
!= ((ULONG_PTR
)Teb
>> PAGE_SHIFT
))
173 /* Bug in the AVL code? */
174 DPRINT1("Corrupted VAD!\n");
178 /* Sanity checks for a valid TEB VAD */
179 ASSERT((Vad
->StartingVpn
== ((ULONG_PTR
)Teb
>> PAGE_SHIFT
) &&
180 (Vad
->EndingVpn
== (TebEnd
>> PAGE_SHIFT
))));
181 ASSERT(Vad
->u
.VadFlags
.NoChange
== TRUE
);
182 ASSERT(Vad
->u2
.VadFlags2
.MultipleSecured
== FALSE
);
184 /* Lock the working set */
185 MiLockProcessWorkingSet(Process
, Thread
);
187 /* Remove this VAD from the tree */
188 ASSERT(VadTree
->NumberGenericTableElements
>= 1);
189 MiRemoveNode((PMMADDRESS_NODE
)Vad
, VadTree
);
191 /* Release the working set */
192 MiUnlockProcessWorkingSet(Process
, Thread
);
198 /* Release the address space lock */
199 KeReleaseGuardedMutex(&Process
->AddressCreationLock
);
207 MmDeleteKernelStack(IN PVOID StackBase
,
211 PFN_NUMBER StackPages
, PageFrameNumber
;//, PageTableFrameNumber;
212 PMMPFN Pfn1
;//, Pfn2;
217 // This should be the guard page, so decrement by one
219 PointerPte
= MiAddressToPte(StackBase
);
223 // Calculate pages used
225 StackPages
= BYTES_TO_PAGES(GuiStack
?
226 KERNEL_LARGE_STACK_SIZE
: KERNEL_STACK_SIZE
);
228 /* Acquire the PFN lock */
229 OldIrql
= KeAcquireQueuedSpinLock(LockQueuePfnLock
);
234 for (i
= 0; i
< StackPages
; i
++)
237 // Check if this is a valid PTE
239 if (PointerPte
->u
.Hard
.Valid
== 1)
241 /* Get the PTE's page */
242 PageFrameNumber
= PFN_FROM_PTE(PointerPte
);
243 Pfn1
= MiGetPfnEntry(PageFrameNumber
);
244 #if 0 // ARM3 might not own the page table, so don't take this risk. Leak it instead!
245 /* Now get the page of the page table mapping it */
246 PageTableFrameNumber
= Pfn1
->u4
.PteFrame
;
247 Pfn2
= MiGetPfnEntry(PageTableFrameNumber
);
249 /* Remove a shared reference, since the page is going away */
250 MiDecrementShareCount(Pfn2
, PageTableFrameNumber
);
252 /* Set the special pending delete marker */
253 Pfn1
->PteAddress
= (PMMPTE
)((ULONG_PTR
)Pfn1
->PteAddress
| 1);
255 /* And now delete the actual stack page */
256 MiDecrementShareCount(Pfn1
, PageFrameNumber
);
266 // We should be at the guard page now
268 ASSERT(PointerPte
->u
.Hard
.Valid
== 0);
270 /* Release the PFN lock */
271 KeReleaseQueuedSpinLock(LockQueuePfnLock
, OldIrql
);
276 MiReleaseSystemPtes(PointerPte
, StackPages
+ 1, SystemPteSpace
);
281 MmCreateKernelStack(IN BOOLEAN GuiStack
,
284 PFN_NUMBER StackPtes
, StackPages
;
285 PMMPTE PointerPte
, StackPte
;
287 MMPTE TempPte
, InvalidPte
;
289 PFN_NUMBER PageFrameIndex
;
293 // Calculate pages needed
298 // We'll allocate 64KB stack, but only commit 12K
300 StackPtes
= BYTES_TO_PAGES(KERNEL_LARGE_STACK_SIZE
);
301 StackPages
= BYTES_TO_PAGES(KERNEL_LARGE_STACK_COMMIT
);
307 // We'll allocate 12K and that's it
309 StackPtes
= BYTES_TO_PAGES(KERNEL_STACK_SIZE
);
310 StackPages
= StackPtes
;
314 // Reserve stack pages, plus a guard page
316 StackPte
= MiReserveSystemPtes(StackPtes
+ 1, SystemPteSpace
);
317 if (!StackPte
) return NULL
;
320 // Get the stack address
322 BaseAddress
= MiPteToAddress(StackPte
+ StackPtes
+ 1);
325 // Select the right PTE address where we actually start committing pages
327 PointerPte
= StackPte
;
328 if (GuiStack
) PointerPte
+= BYTES_TO_PAGES(KERNEL_LARGE_STACK_SIZE
-
329 KERNEL_LARGE_STACK_COMMIT
);
332 /* Setup the temporary invalid PTE */
333 MI_MAKE_SOFTWARE_PTE(&InvalidPte
, MM_NOACCESS
);
335 /* Setup the template stack PTE */
336 MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte
, PointerPte
+ 1, MM_READWRITE
, 0);
339 // Acquire the PFN DB lock
341 OldIrql
= KeAcquireQueuedSpinLock(LockQueuePfnLock
);
344 // Loop each stack page
346 for (i
= 0; i
< StackPages
; i
++)
353 /* Get a page and write the current invalid PTE */
354 PageFrameIndex
= MiRemoveAnyPage(0);
355 MI_WRITE_INVALID_PTE(PointerPte
, InvalidPte
);
357 /* Initialize the PFN entry for this page */
358 MiInitializePfn(PageFrameIndex
, PointerPte
, 1);
360 /* Write the valid PTE */
361 TempPte
.u
.Hard
.PageFrameNumber
= PageFrameIndex
;
362 MI_WRITE_VALID_PTE(PointerPte
, TempPte
);
366 (VOID
)InterlockedExchangeAddUL(&MiMemoryConsumers
[MC_NPPOOL
].PagesUsed
, StackPages
);
369 // Release the PFN lock
371 KeReleaseQueuedSpinLock(LockQueuePfnLock
, OldIrql
);
374 // Return the stack address
381 MmGrowKernelStackEx(IN PVOID StackPointer
,
384 PKTHREAD Thread
= KeGetCurrentThread();
385 PMMPTE LimitPte
, NewLimitPte
, LastPte
;
386 PFN_NUMBER StackPages
;
388 MMPTE TempPte
, InvalidPte
;
389 PFN_NUMBER PageFrameIndex
;
392 // Make sure the stack did not overflow
394 ASSERT(((ULONG_PTR
)Thread
->StackBase
- (ULONG_PTR
)Thread
->StackLimit
) <=
395 (KERNEL_LARGE_STACK_SIZE
+ PAGE_SIZE
));
398 // Get the current stack limit
400 LimitPte
= MiAddressToPte(Thread
->StackLimit
);
401 ASSERT(LimitPte
->u
.Hard
.Valid
== 1);
404 // Get the new one and make sure this isn't a retarded request
406 NewLimitPte
= MiAddressToPte((PVOID
)((ULONG_PTR
)StackPointer
- GrowSize
));
407 if (NewLimitPte
== LimitPte
) return STATUS_SUCCESS
;
410 // Now make sure you're not going past the reserved space
412 LastPte
= MiAddressToPte((PVOID
)((ULONG_PTR
)Thread
->StackBase
-
413 KERNEL_LARGE_STACK_SIZE
));
414 if (NewLimitPte
< LastPte
)
419 DPRINT1("Thread wants too much stack\n");
420 return STATUS_STACK_OVERFLOW
;
424 // Calculate the number of new pages
427 StackPages
= (LimitPte
- NewLimitPte
+ 1);
429 /* Setup the temporary invalid PTE */
430 MI_MAKE_SOFTWARE_PTE(&InvalidPte
, MM_NOACCESS
);
433 // Acquire the PFN DB lock
435 OldIrql
= KeAcquireQueuedSpinLock(LockQueuePfnLock
);
438 // Loop each stack page
440 while (LimitPte
>= NewLimitPte
)
442 /* Get a page and write the current invalid PTE */
443 PageFrameIndex
= MiRemoveAnyPage(0);
444 MI_WRITE_INVALID_PTE(LimitPte
, InvalidPte
);
446 /* Initialize the PFN entry for this page */
447 MiInitializePfn(PageFrameIndex
, LimitPte
, 1);
449 /* Setup the template stack PTE */
450 MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte
, LimitPte
, MM_READWRITE
, PageFrameIndex
);
452 /* Write the valid PTE */
453 MI_WRITE_VALID_PTE(LimitPte
--, TempPte
);
457 // Release the PFN lock
459 KeReleaseQueuedSpinLock(LockQueuePfnLock
, OldIrql
);
464 Thread
->StackLimit
= (ULONG_PTR
)MiPteToAddress(NewLimitPte
);
465 return STATUS_SUCCESS
;
470 MmGrowKernelStack(IN PVOID StackPointer
)
473 // Call the extended version
475 return MmGrowKernelStackEx(StackPointer
, KERNEL_LARGE_STACK_COMMIT
);
480 MmSetMemoryPriorityProcess(IN PEPROCESS Process
,
481 IN UCHAR MemoryPriority
)
486 // Check if we have less then 16MB of Physical Memory
488 if ((MmSystemSize
== MmSmallSystem
) &&
489 (MmNumberOfPhysicalPages
< ((15 * 1024 * 1024) / PAGE_SIZE
)))
492 // Always use background priority
494 MemoryPriority
= MEMORY_PRIORITY_BACKGROUND
;
498 // Save the old priority and update it
500 OldPriority
= (UCHAR
)Process
->Vm
.Flags
.MemoryPriority
;
501 Process
->Vm
.Flags
.MemoryPriority
= MemoryPriority
;
504 // Return the old priority
511 MmGetSessionLocaleId(VOID
)
517 // Get the current process
519 Process
= PsGetCurrentProcess();
522 // Check if it's the Session Leader
524 if (Process
->Vm
.Flags
.SessionLeader
)
527 // Make sure it has a valid Session
529 if (Process
->Session
)
535 return ((PMM_SESSION_SPACE
)Process
->Session
)->LocaleId
;
541 // Not a session leader, return the default
543 return PsDefaultThreadLocaleId
;
548 MmCreatePeb(IN PEPROCESS Process
,
549 IN PINITIAL_PEB InitialPeb
,
553 LARGE_INTEGER SectionOffset
;
555 PVOID TableBase
= NULL
;
556 PIMAGE_NT_HEADERS NtHeaders
;
557 PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigData
;
559 USHORT Characteristics
;
560 KAFFINITY ProcessAffinityMask
= 0;
561 SectionOffset
.QuadPart
= (ULONGLONG
)0;
567 KeAttachProcess(&Process
->Pcb
);
572 Status
= MiCreatePebOrTeb(Process
, sizeof(PEB
), (PULONG_PTR
)&Peb
);
573 ASSERT(NT_SUCCESS(Status
));
578 Status
= MmMapViewOfSection(ExpNlsSectionPointer
,
588 if (!NT_SUCCESS(Status
)) return Status
;
591 // Use SEH in case we can't load the PEB
596 // Initialize the PEB
598 RtlZeroMemory(Peb
, sizeof(PEB
));
603 Peb
->ImageBaseAddress
= Process
->SectionBaseAddress
;
604 Peb
->InheritedAddressSpace
= InitialPeb
->InheritedAddressSpace
;
605 Peb
->Mutant
= InitialPeb
->Mutant
;
606 Peb
->ImageUsesLargePages
= InitialPeb
->ImageUsesLargePages
;
611 Peb
->AnsiCodePageData
= (PCHAR
)TableBase
+ ExpAnsiCodePageDataOffset
;
612 Peb
->OemCodePageData
= (PCHAR
)TableBase
+ ExpOemCodePageDataOffset
;
613 Peb
->UnicodeCaseTableData
= (PCHAR
)TableBase
+ ExpUnicodeCaseTableDataOffset
;
616 // Default Version Data (could get changed below)
618 Peb
->OSMajorVersion
= NtMajorVersion
;
619 Peb
->OSMinorVersion
= NtMinorVersion
;
620 Peb
->OSBuildNumber
= (USHORT
)(NtBuildNumber
& 0x3FFF);
621 Peb
->OSPlatformId
= 2; /* VER_PLATFORM_WIN32_NT */
622 Peb
->OSCSDVersion
= (USHORT
)CmNtCSDVersion
;
625 // Heap and Debug Data
627 Peb
->NumberOfProcessors
= KeNumberProcessors
;
628 Peb
->BeingDebugged
= (BOOLEAN
)(Process
->DebugPort
!= NULL
? TRUE
: FALSE
);
629 Peb
->NtGlobalFlag
= NtGlobalFlag
;
630 /*Peb->HeapSegmentReserve = MmHeapSegmentReserve;
631 Peb->HeapSegmentCommit = MmHeapSegmentCommit;
632 Peb->HeapDeCommitTotalFreeThreshold = MmHeapDeCommitTotalFreeThreshold;
633 Peb->HeapDeCommitFreeBlockThreshold = MmHeapDeCommitFreeBlockThreshold;
634 Peb->CriticalSectionTimeout = MmCriticalSectionTimeout;
635 Peb->MinimumStackCommit = MmMinimumStackCommitInBytes;
637 Peb
->MaximumNumberOfHeaps
= (PAGE_SIZE
- sizeof(PEB
)) / sizeof(PVOID
);
638 Peb
->ProcessHeaps
= (PVOID
*)(Peb
+ 1);
643 if (Process
->Session
) Peb
->SessionId
= 0; // MmGetSessionId(Process);
645 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
651 _SEH2_YIELD(return _SEH2_GetExceptionCode());
656 // Use SEH in case we can't load the image
663 NtHeaders
= RtlImageNtHeader(Peb
->ImageBaseAddress
);
664 Characteristics
= NtHeaders
->FileHeader
.Characteristics
;
666 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
672 _SEH2_YIELD(return STATUS_INVALID_IMAGE_PROTECT
);
682 // Use SEH in case we can't load the headers
687 // Get the Image Config Data too
689 ImageConfigData
= RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
691 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
698 ProbeForRead(ImageConfigData
,
699 sizeof(IMAGE_LOAD_CONFIG_DIRECTORY
),
704 // Write subsystem data
706 Peb
->ImageSubsystem
= NtHeaders
->OptionalHeader
.Subsystem
;
707 Peb
->ImageSubsystemMajorVersion
= NtHeaders
->OptionalHeader
.MajorSubsystemVersion
;
708 Peb
->ImageSubsystemMinorVersion
= NtHeaders
->OptionalHeader
.MinorSubsystemVersion
;
711 // Check for version data
713 if (NtHeaders
->OptionalHeader
.Win32VersionValue
)
716 // Extract values and write them
718 Peb
->OSMajorVersion
= NtHeaders
->OptionalHeader
.Win32VersionValue
& 0xFF;
719 Peb
->OSMinorVersion
= (NtHeaders
->OptionalHeader
.Win32VersionValue
>> 8) & 0xFF;
720 Peb
->OSBuildNumber
= (NtHeaders
->OptionalHeader
.Win32VersionValue
>> 16) & 0x3FFF;
721 Peb
->OSPlatformId
= (NtHeaders
->OptionalHeader
.Win32VersionValue
>> 30) ^ 2;
725 // Process the image config data overrides if specfied
727 if (ImageConfigData
!= NULL
)
730 // Process CSD version override
732 if (ImageConfigData
->CSDVersion
)
737 Peb
->OSCSDVersion
= ImageConfigData
->CSDVersion
;
741 // Process affinity mask ovverride
743 if (ImageConfigData
->ProcessAffinityMask
)
748 ProcessAffinityMask
= ImageConfigData
->ProcessAffinityMask
;
753 // Check if this is a UP image
754 if (Characteristics
& IMAGE_FILE_UP_SYSTEM_ONLY
)
757 // Force it to use CPU 0
759 Peb
->ImageProcessAffinityMask
= 0;
764 // Whatever was configured
766 Peb
->ImageProcessAffinityMask
= ProcessAffinityMask
;
769 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
775 _SEH2_YIELD(return STATUS_INVALID_IMAGE_PROTECT
);
781 // Detach from the Process
785 return STATUS_SUCCESS
;
790 MmCreateTeb(IN PEPROCESS Process
,
791 IN PCLIENT_ID ClientId
,
792 IN PINITIAL_TEB InitialTeb
,
796 NTSTATUS Status
= STATUS_SUCCESS
;
802 KeAttachProcess(&Process
->Pcb
);
807 Status
= MiCreatePebOrTeb(Process
, sizeof(TEB
), (PULONG_PTR
)&Teb
);
808 ASSERT(NT_SUCCESS(Status
));
811 // Use SEH in case we can't load the TEB
816 // Initialize the PEB
818 RtlZeroMemory(Teb
, sizeof(TEB
));
823 Teb
->NtTib
.ExceptionList
= EXCEPTION_CHAIN_END
;
824 Teb
->NtTib
.Self
= (PNT_TIB
)Teb
;
827 // Identify this as an OS/2 V3.0 ("Cruiser") TIB
829 Teb
->NtTib
.Version
= 30 << 8;
834 Teb
->ClientId
= *ClientId
;
835 Teb
->RealClientId
= *ClientId
;
836 Teb
->ProcessEnvironmentBlock
= Process
->Peb
;
837 Teb
->CurrentLocale
= PsDefaultThreadLocaleId
;
840 // Check if we have a grandparent TEB
842 if ((InitialTeb
->PreviousStackBase
== NULL
) &&
843 (InitialTeb
->PreviousStackLimit
== NULL
))
846 // Use initial TEB values
848 Teb
->NtTib
.StackBase
= InitialTeb
->StackBase
;
849 Teb
->NtTib
.StackLimit
= InitialTeb
->StackLimit
;
850 Teb
->DeallocationStack
= InitialTeb
->AllocatedStackBase
;
855 // Use grandparent TEB values
857 Teb
->NtTib
.StackBase
= InitialTeb
->PreviousStackBase
;
858 Teb
->NtTib
.StackLimit
= InitialTeb
->PreviousStackLimit
;
862 // Initialize the static unicode string
864 Teb
->StaticUnicodeString
.MaximumLength
= sizeof(Teb
->StaticUnicodeBuffer
);
865 Teb
->StaticUnicodeString
.Buffer
= Teb
->StaticUnicodeBuffer
;
867 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
872 Status
= _SEH2_GetExceptionCode();
886 MmInitializeProcessAddressSpace(IN PEPROCESS Process
,
887 IN PEPROCESS ProcessClone OPTIONAL
,
888 IN PVOID Section OPTIONAL
,
890 IN POBJECT_NAME_INFORMATION
*AuditName OPTIONAL
)
892 NTSTATUS Status
= STATUS_SUCCESS
;
895 PROS_SECTION_OBJECT SectionObject
= Section
;
899 PFN_NUMBER PageFrameNumber
;
900 UNICODE_STRING FileName
;
905 /* We should have a PDE */
906 ASSERT(Process
->Pcb
.DirectoryTableBase
[0] != 0);
907 ASSERT(Process
->PdeUpdateNeeded
== FALSE
);
909 /* Attach to the process */
910 KeAttachProcess(&Process
->Pcb
);
912 /* The address space should now been in phase 1 or 0 */
913 ASSERT(Process
->AddressSpaceInitialized
<= 1);
914 Process
->AddressSpaceInitialized
= 2;
916 /* Initialize the Addresss Space lock */
917 KeInitializeGuardedMutex(&Process
->AddressCreationLock
);
918 Process
->Vm
.WorkingSetExpansionLinks
.Flink
= NULL
;
920 /* Initialize AVL tree */
921 ASSERT(Process
->VadRoot
.NumberGenericTableElements
== 0);
922 Process
->VadRoot
.BalancedRoot
.u1
.Parent
= &Process
->VadRoot
.BalancedRoot
;
924 /* Lock PFN database */
925 OldIrql
= KeAcquireQueuedSpinLock(LockQueuePfnLock
);
927 /* Setup the PFN for the PDE base of this process */
928 PointerPte
= MiAddressToPte(PDE_BASE
);
929 PageFrameNumber
= PFN_FROM_PTE(PointerPte
);
930 MiInitializePfn(PageFrameNumber
, PointerPte
, TRUE
);
932 /* Do the same for hyperspace */
933 PointerPde
= MiAddressToPde(HYPER_SPACE
);
934 PageFrameNumber
= PFN_FROM_PTE(PointerPde
);
935 MiInitializePfn(PageFrameNumber
, PointerPde
, TRUE
);
937 /* Release PFN lock */
938 KeReleaseQueuedSpinLock(LockQueuePfnLock
, OldIrql
);
940 /* Lock the VAD, ARM3-owned ranges away */
941 MiRosTakeOverPebTebRanges(Process
);
943 /* Check if there's a Section Object */
946 /* Determine the image file name and save it to EPROCESS */
947 FileName
= SectionObject
->FileObject
->FileName
;
948 Source
= (PWCHAR
)((PCHAR
)FileName
.Buffer
+ FileName
.Length
);
951 /* Loop the file name*/
952 while (Source
> FileName
.Buffer
)
954 /* Make sure this isn't a backslash */
955 if (*--Source
== OBJ_NAME_PATH_SEPARATOR
)
957 /* If so, stop it here */
963 /* Otherwise, keep going */
969 /* Copy the to the process and truncate it to 15 characters if necessary */
970 Destination
= Process
->ImageFileName
;
971 Length
= min(Length
, sizeof(Process
->ImageFileName
) - 1);
972 while (Length
--) *Destination
++ = (UCHAR
)*Source
++;
973 *Destination
= ANSI_NULL
;
975 /* Check if caller wants an audit name */
978 /* Setup the audit name */
979 Status
= SeInitializeProcessAuditName(SectionObject
->FileObject
,
982 if (!NT_SUCCESS(Status
))
990 /* Map the section */
991 Status
= MmMapViewOfSection(Section
,
1002 /* Save the pointer */
1003 Process
->SectionBaseAddress
= ImageBase
;
1006 /* Be nice and detach */
1009 /* Return status to caller */
1015 MmInitializeHandBuiltProcess(IN PEPROCESS Process
,
1016 IN PULONG_PTR DirectoryTableBase
)
1018 /* Share the directory base with the idle process */
1019 DirectoryTableBase
[0] = PsGetCurrentProcess()->Pcb
.DirectoryTableBase
[0];
1020 DirectoryTableBase
[1] = PsGetCurrentProcess()->Pcb
.DirectoryTableBase
[1];
1022 /* Initialize the Addresss Space */
1023 KeInitializeGuardedMutex(&Process
->AddressCreationLock
);
1024 KeInitializeSpinLock(&Process
->HyperSpaceLock
);
1025 Process
->Vm
.WorkingSetExpansionLinks
.Flink
= NULL
;
1026 ASSERT(Process
->VadRoot
.NumberGenericTableElements
== 0);
1027 Process
->VadRoot
.BalancedRoot
.u1
.Parent
= &Process
->VadRoot
.BalancedRoot
;
1030 Process
->HasAddressSpace
= TRUE
;//??
1031 return STATUS_SUCCESS
;
1036 MmInitializeHandBuiltProcess2(IN PEPROCESS Process
)
1038 /* Lock the VAD, ARM3-owned ranges away */
1039 MiRosTakeOverPebTebRanges(Process
);
1040 return STATUS_SUCCESS
;
1043 /* FIXME: Evaluate ways to make this portable yet arch-specific */
1046 MmCreateProcessAddressSpace(IN ULONG MinWs
,
1047 IN PEPROCESS Process
,
1048 OUT PULONG_PTR DirectoryTableBase
)
1051 PFN_NUMBER PdeIndex
, HyperIndex
;
1053 MMPTE TempPte
, PdePte
;
1057 /* No page colors yet */
1058 Process
->NextPageColor
= 0;
1060 /* Setup the hyperspace lock */
1061 KeInitializeSpinLock(&Process
->HyperSpaceLock
);
1063 /* Lock PFN database */
1064 OldIrql
= KeAcquireQueuedSpinLock(LockQueuePfnLock
);
1066 /* Get a page for the PDE */
1067 PdeIndex
= MiRemoveAnyPage(0);
1068 KeReleaseQueuedSpinLock(LockQueuePfnLock
, OldIrql
);
1069 MiZeroPhysicalPage(PdeIndex
);
1070 OldIrql
= KeAcquireQueuedSpinLock(LockQueuePfnLock
);
1072 /* Get a page for hyperspace */
1073 HyperIndex
= MiRemoveAnyPage(0);
1074 KeReleaseQueuedSpinLock(LockQueuePfnLock
, OldIrql
);
1075 MiZeroPhysicalPage(HyperIndex
);
1077 /* Switch to phase 1 initialization */
1078 ASSERT(Process
->AddressSpaceInitialized
== 0);
1079 Process
->AddressSpaceInitialized
= 1;
1081 /* Set the base directory pointers */
1082 DirectoryTableBase
[0] = PdeIndex
<< PAGE_SHIFT
;
1083 DirectoryTableBase
[1] = HyperIndex
<< PAGE_SHIFT
;
1085 /* Make sure we don't already have a page directory setup */
1086 ASSERT(Process
->Pcb
.DirectoryTableBase
[0] == 0);
1088 /* Insert us into the Mm process list */
1089 InsertTailList(&MmProcessList
, &Process
->MmProcessLinks
);
1091 /* Get a PTE to map the page directory */
1092 PointerPte
= MiReserveSystemPtes(1, SystemPteSpace
);
1093 ASSERT(PointerPte
!= NULL
);
1096 MI_MAKE_HARDWARE_PTE_KERNEL(&PdePte
,
1101 /* Set it dirty and map it */
1102 PdePte
.u
.Hard
.Dirty
= TRUE
;
1103 MI_WRITE_VALID_PTE(PointerPte
, PdePte
);
1105 /* Now get the page directory (which we'll double map, so call it a page table */
1106 SystemTable
= MiPteToAddress(PointerPte
);
1108 /* Copy all the kernel mappings */
1109 PdeOffset
= MiGetPdeOffset(MmSystemRangeStart
);
1111 RtlCopyMemory(&SystemTable
[PdeOffset
],
1112 MiAddressToPde(MmSystemRangeStart
),
1113 PAGE_SIZE
- PdeOffset
* sizeof(MMPTE
));
1115 /* Now write the PTE/PDE entry for hyperspace itself */
1116 TempPte
= ValidKernelPte
;
1117 TempPte
.u
.Hard
.PageFrameNumber
= HyperIndex
;
1118 PdeOffset
= MiGetPdeOffset(HYPER_SPACE
);
1119 SystemTable
[PdeOffset
] = TempPte
;
1123 ASSERT(MiGetPdeOffset(MmHyperSpaceEnd
) >= PdeOffset
);
1125 /* Now do the x86 trick of making the PDE a page table itself */
1126 PdeOffset
= MiGetPdeOffset(PTE_BASE
);
1127 TempPte
.u
.Hard
.PageFrameNumber
= PdeIndex
;
1128 SystemTable
[PdeOffset
] = TempPte
;
1130 /* Let go of the system PTE */
1131 MiReleaseSystemPtes(PointerPte
, 1, SystemPteSpace
);
1137 MmCleanProcessAddressSpace(IN PEPROCESS Process
)
1140 PMM_AVL_TABLE VadTree
;
1141 PETHREAD Thread
= PsGetCurrentThread();
1143 /* Lock the process address space from changes */
1144 MmLockAddressSpace(&Process
->Vm
);
1146 /* Enumerate the VADs */
1147 VadTree
= &Process
->VadRoot
;
1148 DPRINT("Cleaning up VADs: %d\n", VadTree
->NumberGenericTableElements
);
1149 while (VadTree
->NumberGenericTableElements
)
1151 /* Grab the current VAD */
1152 Vad
= (PMMVAD
)VadTree
->BalancedRoot
.RightChild
;
1154 /* Lock the working set */
1155 MiLockProcessWorkingSet(Process
, Thread
);
1157 /* Remove this VAD from the tree */
1158 ASSERT(VadTree
->NumberGenericTableElements
>= 1);
1159 DPRINT("Removing node for VAD: %lx %lx\n", Vad
->StartingVpn
, Vad
->EndingVpn
);
1160 MiRemoveNode((PMMADDRESS_NODE
)Vad
, VadTree
);
1161 DPRINT("Moving on: %d\n", VadTree
->NumberGenericTableElements
);
1163 /* Check if this VAD was the hint */
1164 if (VadTree
->NodeHint
== Vad
)
1166 /* Get a new hint, unless we're empty now, in which case nothing */
1167 VadTree
->NodeHint
= VadTree
->BalancedRoot
.RightChild
;
1168 if (!VadTree
->NumberGenericTableElements
) VadTree
->NodeHint
= NULL
;
1171 /* Only PEB/TEB VADs supported for now */
1172 ASSERT(Vad
->u
.VadFlags
.PrivateMemory
== 1);
1173 ASSERT(Vad
->u
.VadFlags
.VadType
== VadNone
);
1175 /* Release the working set */
1176 MiUnlockProcessWorkingSet(Process
, Thread
);
1178 /* Free the VAD memory */
1182 /* Release the address space */
1183 MmUnlockAddressSpace(&Process
->Vm
);
1186 /* SYSTEM CALLS ***************************************************************/
1190 NtAllocateUserPhysicalPages(IN HANDLE ProcessHandle
,
1191 IN OUT PULONG_PTR NumberOfPages
,
1192 IN OUT PULONG_PTR UserPfnArray
)
1195 return STATUS_NOT_IMPLEMENTED
;
1200 NtMapUserPhysicalPages(IN PVOID VirtualAddresses
,
1201 IN ULONG_PTR NumberOfPages
,
1202 IN OUT PULONG_PTR UserPfnArray
)
1205 return STATUS_NOT_IMPLEMENTED
;
1210 NtMapUserPhysicalPagesScatter(IN PVOID
*VirtualAddresses
,
1211 IN ULONG_PTR NumberOfPages
,
1212 IN OUT PULONG_PTR UserPfnArray
)
1215 return STATUS_NOT_IMPLEMENTED
;
1220 NtFreeUserPhysicalPages(IN HANDLE ProcessHandle
,
1221 IN OUT PULONG_PTR NumberOfPages
,
1222 IN OUT PULONG_PTR UserPfnArray
)
1225 return STATUS_NOT_IMPLEMENTED
;