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
;
23 MiCreatePebOrTeb(PEPROCESS Process
,
26 /* PRIVATE FUNCTIONS **********************************************************/
30 MmDeleteKernelStack(IN PVOID StackBase
,
34 PFN_NUMBER StackPages
, PageFrameNumber
;//, PageTableFrameNumber;
40 // This should be the guard page, so decrement by one
42 PointerPte
= MiAddressToPte(StackBase
);
46 // Calculate pages used
48 StackPages
= BYTES_TO_PAGES(GuiStack
?
49 KERNEL_LARGE_STACK_SIZE
: KERNEL_STACK_SIZE
);
51 /* Acquire the PFN lock */
52 OldIrql
= KeAcquireQueuedSpinLock(LockQueuePfnLock
);
57 for (i
= 0; i
< StackPages
; i
++)
60 // Check if this is a valid PTE
62 if (PointerPte
->u
.Hard
.Valid
== 1)
64 /* Get the PTE's page */
65 PageFrameNumber
= PFN_FROM_PTE(PointerPte
);
66 Pfn1
= MiGetPfnEntry(PageFrameNumber
);
67 #if 0 // ARM3 might not own the page table, so don't take this risk. Leak it instead!
68 /* Now get the page of the page table mapping it */
69 PageTableFrameNumber
= Pfn1
->u4
.PteFrame
;
70 Pfn2
= MiGetPfnEntry(PageTableFrameNumber
);
72 /* Remove a shared reference, since the page is going away */
73 MiDecrementShareCount(Pfn2
, PageTableFrameNumber
);
75 /* Set the special pending delete marker */
76 Pfn1
->PteAddress
= (PMMPTE
)((ULONG_PTR
)Pfn1
->PteAddress
| 1);
78 /* And now delete the actual stack page */
79 MiDecrementShareCount(Pfn1
, PageFrameNumber
);
89 // We should be at the guard page now
91 ASSERT(PointerPte
->u
.Hard
.Valid
== 0);
93 /* Release the PFN lock */
94 KeReleaseQueuedSpinLock(LockQueuePfnLock
, OldIrql
);
99 MiReleaseSystemPtes(PointerPte
, StackPages
+ 1, SystemPteSpace
);
104 MmCreateKernelStack(IN BOOLEAN GuiStack
,
107 PFN_NUMBER StackPtes
, StackPages
;
108 PMMPTE PointerPte
, StackPte
;
110 MMPTE TempPte
, InvalidPte
;
112 PFN_NUMBER PageFrameIndex
;
116 // Calculate pages needed
121 // We'll allocate 64KB stack, but only commit 12K
123 StackPtes
= BYTES_TO_PAGES(KERNEL_LARGE_STACK_SIZE
);
124 StackPages
= BYTES_TO_PAGES(KERNEL_LARGE_STACK_COMMIT
);
130 // We'll allocate 12K and that's it
132 StackPtes
= BYTES_TO_PAGES(KERNEL_STACK_SIZE
);
133 StackPages
= StackPtes
;
137 // Reserve stack pages, plus a guard page
139 StackPte
= MiReserveSystemPtes(StackPtes
+ 1, SystemPteSpace
);
140 if (!StackPte
) return NULL
;
143 // Get the stack address
145 BaseAddress
= MiPteToAddress(StackPte
+ StackPtes
+ 1);
148 // Select the right PTE address where we actually start committing pages
150 PointerPte
= StackPte
;
151 if (GuiStack
) PointerPte
+= BYTES_TO_PAGES(KERNEL_LARGE_STACK_SIZE
-
152 KERNEL_LARGE_STACK_COMMIT
);
155 /* Setup the temporary invalid PTE */
156 MI_MAKE_SOFTWARE_PTE(&InvalidPte
, MM_NOACCESS
);
158 /* Setup the template stack PTE */
159 MI_MAKE_HARDWARE_PTE(&TempPte
, PointerPte
+ 1, MM_READWRITE
, 0);
162 // Acquire the PFN DB lock
164 OldIrql
= KeAcquireQueuedSpinLock(LockQueuePfnLock
);
167 // Loop each stack page
169 for (i
= 0; i
< StackPages
; i
++)
176 /* Get a page and write the current invalid PTE */
177 PageFrameIndex
= MiRemoveAnyPage(0);
178 MI_WRITE_INVALID_PTE(PointerPte
, InvalidPte
);
180 /* Initialize the PFN entry for this page */
181 MiInitializePfn(PageFrameIndex
, PointerPte
, 1);
183 /* Write the valid PTE */
184 TempPte
.u
.Hard
.PageFrameNumber
= PageFrameIndex
;
185 MI_WRITE_VALID_PTE(PointerPte
, TempPte
);
189 (VOID
)InterlockedExchangeAddUL(&MiMemoryConsumers
[MC_NPPOOL
].PagesUsed
, StackPages
);
192 // Release the PFN lock
194 KeReleaseQueuedSpinLock(LockQueuePfnLock
, OldIrql
);
197 // Return the stack address
204 MmGrowKernelStackEx(IN PVOID StackPointer
,
207 PKTHREAD Thread
= KeGetCurrentThread();
208 PMMPTE LimitPte
, NewLimitPte
, LastPte
;
209 PFN_NUMBER StackPages
;
211 MMPTE TempPte
, InvalidPte
;
212 PFN_NUMBER PageFrameIndex
;
215 // Make sure the stack did not overflow
217 ASSERT(((ULONG_PTR
)Thread
->StackBase
- (ULONG_PTR
)Thread
->StackLimit
) <=
218 (KERNEL_LARGE_STACK_SIZE
+ PAGE_SIZE
));
221 // Get the current stack limit
223 LimitPte
= MiAddressToPte(Thread
->StackLimit
);
224 ASSERT(LimitPte
->u
.Hard
.Valid
== 1);
227 // Get the new one and make sure this isn't a retarded request
229 NewLimitPte
= MiAddressToPte((PVOID
)((ULONG_PTR
)StackPointer
- GrowSize
));
230 if (NewLimitPte
== LimitPte
) return STATUS_SUCCESS
;
233 // Now make sure you're not going past the reserved space
235 LastPte
= MiAddressToPte((PVOID
)((ULONG_PTR
)Thread
->StackBase
-
236 KERNEL_LARGE_STACK_SIZE
));
237 if (NewLimitPte
< LastPte
)
242 DPRINT1("Thread wants too much stack\n");
243 return STATUS_STACK_OVERFLOW
;
247 // Calculate the number of new pages
250 StackPages
= (LimitPte
- NewLimitPte
+ 1);
252 /* Setup the temporary invalid PTE */
253 MI_MAKE_SOFTWARE_PTE(&InvalidPte
, MM_NOACCESS
);
256 // Acquire the PFN DB lock
258 OldIrql
= KeAcquireQueuedSpinLock(LockQueuePfnLock
);
261 // Loop each stack page
263 while (LimitPte
>= NewLimitPte
)
265 /* Get a page and write the current invalid PTE */
266 PageFrameIndex
= MiRemoveAnyPage(0);
267 MI_WRITE_INVALID_PTE(LimitPte
, InvalidPte
);
269 /* Initialize the PFN entry for this page */
270 MiInitializePfn(PageFrameIndex
, LimitPte
, 1);
272 /* Setup the template stack PTE */
273 MI_MAKE_HARDWARE_PTE(&TempPte
, LimitPte
, MM_READWRITE
, PageFrameIndex
);
275 /* Write the valid PTE */
276 MI_WRITE_VALID_PTE(LimitPte
--, TempPte
);
280 // Release the PFN lock
282 KeReleaseQueuedSpinLock(LockQueuePfnLock
, OldIrql
);
287 Thread
->StackLimit
= (ULONG_PTR
)MiPteToAddress(NewLimitPte
);
288 return STATUS_SUCCESS
;
293 MmGrowKernelStack(IN PVOID StackPointer
)
296 // Call the extended version
298 return MmGrowKernelStackEx(StackPointer
, KERNEL_LARGE_STACK_COMMIT
);
303 MmSetMemoryPriorityProcess(IN PEPROCESS Process
,
304 IN UCHAR MemoryPriority
)
309 // Check if we have less then 16MB of Physical Memory
311 if ((MmSystemSize
== MmSmallSystem
) &&
312 (MmNumberOfPhysicalPages
< ((15 * 1024 * 1024) / PAGE_SIZE
)))
315 // Always use background priority
317 MemoryPriority
= MEMORY_PRIORITY_BACKGROUND
;
321 // Save the old priority and update it
323 OldPriority
= (UCHAR
)Process
->Vm
.Flags
.MemoryPriority
;
324 Process
->Vm
.Flags
.MemoryPriority
= MemoryPriority
;
327 // Return the old priority
334 MmGetSessionLocaleId(VOID
)
340 // Get the current process
342 Process
= PsGetCurrentProcess();
345 // Check if it's the Session Leader
347 if (Process
->Vm
.Flags
.SessionLeader
)
350 // Make sure it has a valid Session
352 if (Process
->Session
)
358 return ((PMM_SESSION_SPACE
)Process
->Session
)->LocaleId
;
364 // Not a session leader, return the default
366 return PsDefaultThreadLocaleId
;
371 MmCreatePeb(IN PEPROCESS Process
,
372 IN PINITIAL_PEB InitialPeb
,
376 LARGE_INTEGER SectionOffset
;
378 PVOID TableBase
= NULL
;
379 PIMAGE_NT_HEADERS NtHeaders
;
380 PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigData
;
382 USHORT Characteristics
;
383 KAFFINITY ProcessAffinityMask
= 0;
384 SectionOffset
.QuadPart
= (ULONGLONG
)0;
390 KeAttachProcess(&Process
->Pcb
);
395 Peb
= MiCreatePebOrTeb(Process
,
396 (PVOID
)((ULONG_PTR
)MM_HIGHEST_VAD_ADDRESS
+ 1));
397 ASSERT(Peb
== (PVOID
)0x7FFDF000);
402 Status
= MmMapViewOfSection(ExpNlsSectionPointer
,
412 if (!NT_SUCCESS(Status
)) return Status
;
415 // Use SEH in case we can't load the PEB
420 // Initialize the PEB
422 RtlZeroMemory(Peb
, sizeof(PEB
));
427 Peb
->ImageBaseAddress
= Process
->SectionBaseAddress
;
428 Peb
->InheritedAddressSpace
= InitialPeb
->InheritedAddressSpace
;
429 Peb
->Mutant
= InitialPeb
->Mutant
;
430 Peb
->ImageUsesLargePages
= InitialPeb
->ImageUsesLargePages
;
435 Peb
->AnsiCodePageData
= (PCHAR
)TableBase
+ ExpAnsiCodePageDataOffset
;
436 Peb
->OemCodePageData
= (PCHAR
)TableBase
+ ExpOemCodePageDataOffset
;
437 Peb
->UnicodeCaseTableData
= (PCHAR
)TableBase
+ ExpUnicodeCaseTableDataOffset
;
440 // Default Version Data (could get changed below)
442 Peb
->OSMajorVersion
= NtMajorVersion
;
443 Peb
->OSMinorVersion
= NtMinorVersion
;
444 Peb
->OSBuildNumber
= (USHORT
)(NtBuildNumber
& 0x3FFF);
445 Peb
->OSPlatformId
= 2; /* VER_PLATFORM_WIN32_NT */
446 Peb
->OSCSDVersion
= (USHORT
)CmNtCSDVersion
;
449 // Heap and Debug Data
451 Peb
->NumberOfProcessors
= KeNumberProcessors
;
452 Peb
->BeingDebugged
= (BOOLEAN
)(Process
->DebugPort
!= NULL
? TRUE
: FALSE
);
453 Peb
->NtGlobalFlag
= NtGlobalFlag
;
454 /*Peb->HeapSegmentReserve = MmHeapSegmentReserve;
455 Peb->HeapSegmentCommit = MmHeapSegmentCommit;
456 Peb->HeapDeCommitTotalFreeThreshold = MmHeapDeCommitTotalFreeThreshold;
457 Peb->HeapDeCommitFreeBlockThreshold = MmHeapDeCommitFreeBlockThreshold;
458 Peb->CriticalSectionTimeout = MmCriticalSectionTimeout;
459 Peb->MinimumStackCommit = MmMinimumStackCommitInBytes;
461 Peb
->MaximumNumberOfHeaps
= (PAGE_SIZE
- sizeof(PEB
)) / sizeof(PVOID
);
462 Peb
->ProcessHeaps
= (PVOID
*)(Peb
+ 1);
467 if (Process
->Session
) Peb
->SessionId
= 0; // MmGetSessionId(Process);
469 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
475 _SEH2_YIELD(return _SEH2_GetExceptionCode());
480 // Use SEH in case we can't load the image
487 NtHeaders
= RtlImageNtHeader(Peb
->ImageBaseAddress
);
488 Characteristics
= NtHeaders
->FileHeader
.Characteristics
;
490 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
496 _SEH2_YIELD(return STATUS_INVALID_IMAGE_PROTECT
);
506 // Use SEH in case we can't load the headers
511 // Get the Image Config Data too
513 ImageConfigData
= RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
515 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
522 ProbeForRead(ImageConfigData
,
523 sizeof(IMAGE_LOAD_CONFIG_DIRECTORY
),
528 // Write subsystem data
530 Peb
->ImageSubsystem
= NtHeaders
->OptionalHeader
.Subsystem
;
531 Peb
->ImageSubsystemMajorVersion
= NtHeaders
->OptionalHeader
.MajorSubsystemVersion
;
532 Peb
->ImageSubsystemMinorVersion
= NtHeaders
->OptionalHeader
.MinorSubsystemVersion
;
535 // Check for version data
537 if (NtHeaders
->OptionalHeader
.Win32VersionValue
)
540 // Extract values and write them
542 Peb
->OSMajorVersion
= NtHeaders
->OptionalHeader
.Win32VersionValue
& 0xFF;
543 Peb
->OSMinorVersion
= (NtHeaders
->OptionalHeader
.Win32VersionValue
>> 8) & 0xFF;
544 Peb
->OSBuildNumber
= (NtHeaders
->OptionalHeader
.Win32VersionValue
>> 16) & 0x3FFF;
545 Peb
->OSPlatformId
= (NtHeaders
->OptionalHeader
.Win32VersionValue
>> 30) ^ 2;
549 // Process the image config data overrides if specfied
551 if (ImageConfigData
!= NULL
)
554 // Process CSD version override
556 if (ImageConfigData
->CSDVersion
)
561 Peb
->OSCSDVersion
= ImageConfigData
->CSDVersion
;
565 // Process affinity mask ovverride
567 if (ImageConfigData
->ProcessAffinityMask
)
572 ProcessAffinityMask
= ImageConfigData
->ProcessAffinityMask
;
577 // Check if this is a UP image
578 if (Characteristics
& IMAGE_FILE_UP_SYSTEM_ONLY
)
581 // Force it to use CPU 0
583 Peb
->ImageProcessAffinityMask
= 0;
588 // Whatever was configured
590 Peb
->ImageProcessAffinityMask
= ProcessAffinityMask
;
593 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
599 _SEH2_YIELD(return STATUS_INVALID_IMAGE_PROTECT
);
605 // Detach from the Process
609 return STATUS_SUCCESS
;
614 MmCreateTeb(IN PEPROCESS Process
,
615 IN PCLIENT_ID ClientId
,
616 IN PINITIAL_TEB InitialTeb
,
620 NTSTATUS Status
= STATUS_SUCCESS
;
626 KeAttachProcess(&Process
->Pcb
);
631 Teb
= MiCreatePebOrTeb(Process
,
632 (PVOID
)((ULONG_PTR
)MM_HIGHEST_VAD_ADDRESS
+ 1));
633 if (!Teb
) return STATUS_INSUFFICIENT_RESOURCES
;
636 // Use SEH in case we can't load the TEB
641 // Initialize the PEB
643 RtlZeroMemory(Teb
, sizeof(TEB
));
648 Teb
->NtTib
.ExceptionList
= EXCEPTION_CHAIN_END
;
649 Teb
->NtTib
.Self
= (PNT_TIB
)Teb
;
652 // Identify this as an OS/2 V3.0 ("Cruiser") TIB
654 Teb
->NtTib
.Version
= 30 << 8;
659 Teb
->ClientId
= *ClientId
;
660 Teb
->RealClientId
= *ClientId
;
661 Teb
->ProcessEnvironmentBlock
= Process
->Peb
;
662 Teb
->CurrentLocale
= PsDefaultThreadLocaleId
;
665 // Check if we have a grandparent TEB
667 if ((InitialTeb
->PreviousStackBase
== NULL
) &&
668 (InitialTeb
->PreviousStackLimit
== NULL
))
671 // Use initial TEB values
673 Teb
->NtTib
.StackBase
= InitialTeb
->StackBase
;
674 Teb
->NtTib
.StackLimit
= InitialTeb
->StackLimit
;
675 Teb
->DeallocationStack
= InitialTeb
->AllocatedStackBase
;
680 // Use grandparent TEB values
682 Teb
->NtTib
.StackBase
= InitialTeb
->PreviousStackBase
;
683 Teb
->NtTib
.StackLimit
= InitialTeb
->PreviousStackLimit
;
687 // Initialize the static unicode string
689 Teb
->StaticUnicodeString
.MaximumLength
= sizeof(Teb
->StaticUnicodeBuffer
);
690 Teb
->StaticUnicodeString
.Buffer
= Teb
->StaticUnicodeBuffer
;
692 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
697 Status
= _SEH2_GetExceptionCode();
709 /* SYSTEM CALLS ***************************************************************/
713 NtAllocateUserPhysicalPages(IN HANDLE ProcessHandle
,
714 IN OUT PULONG_PTR NumberOfPages
,
715 IN OUT PULONG_PTR UserPfnArray
)
718 return STATUS_NOT_IMPLEMENTED
;
723 NtMapUserPhysicalPages(IN PVOID VirtualAddresses
,
724 IN ULONG_PTR NumberOfPages
,
725 IN OUT PULONG_PTR UserPfnArray
)
728 return STATUS_NOT_IMPLEMENTED
;
733 NtMapUserPhysicalPagesScatter(IN PVOID
*VirtualAddresses
,
734 IN ULONG_PTR NumberOfPages
,
735 IN OUT PULONG_PTR UserPfnArray
)
738 return STATUS_NOT_IMPLEMENTED
;
743 NtFreeUserPhysicalPages(IN HANDLE ProcessHandle
,
744 IN OUT PULONG_PTR NumberOfPages
,
745 IN OUT PULONG_PTR UserPfnArray
)
748 return STATUS_NOT_IMPLEMENTED
;