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
;
38 // This should be the guard page, so decrement by one
40 PointerPte
= MiAddressToPte(StackBase
);
44 // Calculate pages used
46 StackPages
= BYTES_TO_PAGES(GuiStack
?
47 KERNEL_LARGE_STACK_SIZE
: KERNEL_STACK_SIZE
);
52 for (i
= 0; i
< StackPages
; i
++)
55 // Check if this is a valid PTE
57 if (PointerPte
->u
.Hard
.Valid
== 1)
62 MmReleasePageMemoryConsumer(MC_NPPOOL
, PFN_FROM_PTE(PointerPte
));
72 // We should be at the guard page now
74 ASSERT(PointerPte
->u
.Hard
.Valid
== 0);
79 MiReleaseSystemPtes(PointerPte
, StackPages
+ 1, SystemPteSpace
);
84 MmCreateKernelStack(IN BOOLEAN GuiStack
,
87 PFN_NUMBER StackPtes
, StackPages
;
88 PMMPTE PointerPte
, StackPte
;
92 PFN_NUMBER PageFrameIndex
;
96 // Calculate pages needed
101 // We'll allocate 64KB stack, but only commit 12K
103 StackPtes
= BYTES_TO_PAGES(KERNEL_LARGE_STACK_SIZE
);
104 StackPages
= BYTES_TO_PAGES(KERNEL_LARGE_STACK_COMMIT
);
110 // We'll allocate 12K and that's it
112 StackPtes
= BYTES_TO_PAGES(KERNEL_STACK_SIZE
);
113 StackPages
= StackPtes
;
117 // Reserve stack pages, plus a guard page
119 StackPte
= MiReserveSystemPtes(StackPtes
+ 1, SystemPteSpace
);
120 if (!StackPte
) return NULL
;
123 // Get the stack address
125 BaseAddress
= MiPteToAddress(StackPte
+ StackPtes
+ 1);
128 // Select the right PTE address where we actually start committing pages
130 PointerPte
= StackPte
;
131 if (GuiStack
) PointerPte
+= BYTES_TO_PAGES(KERNEL_LARGE_STACK_SIZE
-
132 KERNEL_LARGE_STACK_COMMIT
);
135 // Setup the template stack PTE
137 TempPte
= ValidKernelPte
;
138 MI_MAKE_LOCAL_PAGE(&TempPte
);
139 MI_MAKE_DIRTY_PAGE(&TempPte
);
140 TempPte
.u
.Hard
.PageFrameNumber
= 0;
143 // Acquire the PFN DB lock
145 OldIrql
= KeAcquireQueuedSpinLock(LockQueuePfnLock
);
148 // Loop each stack page
150 for (i
= 0; i
< StackPages
; i
++)
156 ASSERT(PointerPte
->u
.Hard
.Valid
== 0);
161 PageFrameIndex
= MmAllocPage(MC_NPPOOL
);
162 TempPte
.u
.Hard
.PageFrameNumber
= PageFrameIndex
;
167 *PointerPte
= TempPte
;
171 (VOID
)InterlockedExchangeAddUL(&MiMemoryConsumers
[MC_NPPOOL
].PagesUsed
, StackPages
);
174 // Release the PFN lock
176 KeReleaseQueuedSpinLock(LockQueuePfnLock
, OldIrql
);
179 // Return the stack address
186 MmGrowKernelStackEx(IN PVOID StackPointer
,
189 PKTHREAD Thread
= KeGetCurrentThread();
190 PMMPTE LimitPte
, NewLimitPte
, LastPte
;
191 PFN_NUMBER StackPages
;
194 PFN_NUMBER PageFrameIndex
;
197 // Make sure the stack did not overflow
199 ASSERT(((ULONG_PTR
)Thread
->StackBase
- (ULONG_PTR
)Thread
->StackLimit
) <=
200 (KERNEL_LARGE_STACK_SIZE
+ PAGE_SIZE
));
203 // Get the current stack limit
205 LimitPte
= MiAddressToPte(Thread
->StackLimit
);
206 ASSERT(LimitPte
->u
.Hard
.Valid
== 1);
209 // Get the new one and make sure this isn't a retarded request
211 NewLimitPte
= MiAddressToPte((PVOID
)((ULONG_PTR
)StackPointer
- GrowSize
));
212 if (NewLimitPte
== LimitPte
) return STATUS_SUCCESS
;
215 // Now make sure you're not going past the reserved space
217 LastPte
= MiAddressToPte((PVOID
)((ULONG_PTR
)Thread
->StackBase
-
218 KERNEL_LARGE_STACK_SIZE
));
219 if (NewLimitPte
< LastPte
)
224 DPRINT1("Thread wants too much stack\n");
225 return STATUS_STACK_OVERFLOW
;
229 // Calculate the number of new pages
232 StackPages
= (LimitPte
- NewLimitPte
+ 1);
235 // Setup the template stack PTE
237 TempPte
= ValidKernelPte
;
238 MI_MAKE_LOCAL_PAGE(&TempPte
);
239 MI_MAKE_DIRTY_PAGE(&TempPte
);
240 TempPte
.u
.Hard
.PageFrameNumber
= 0;
243 // Acquire the PFN DB lock
245 OldIrql
= KeAcquireQueuedSpinLock(LockQueuePfnLock
);
248 // Loop each stack page
250 while (LimitPte
>= NewLimitPte
)
255 ASSERT(LimitPte
->u
.Hard
.Valid
== 0);
260 PageFrameIndex
= MmAllocPage(MC_NPPOOL
);
261 TempPte
.u
.Hard
.PageFrameNumber
= PageFrameIndex
;
266 *LimitPte
-- = TempPte
;
270 // Release the PFN lock
272 KeReleaseQueuedSpinLock(LockQueuePfnLock
, OldIrql
);
277 Thread
->StackLimit
= (ULONG_PTR
)MiPteToAddress(NewLimitPte
);
278 return STATUS_SUCCESS
;
283 MmGrowKernelStack(IN PVOID StackPointer
)
286 // Call the extended version
288 return MmGrowKernelStackEx(StackPointer
, KERNEL_LARGE_STACK_COMMIT
);
293 MmSetMemoryPriorityProcess(IN PEPROCESS Process
,
294 IN UCHAR MemoryPriority
)
299 // Check if we have less then 16MB of Physical Memory
301 if ((MmSystemSize
== MmSmallSystem
) &&
302 (MmNumberOfPhysicalPages
< ((15 * 1024 * 1024) / PAGE_SIZE
)))
305 // Always use background priority
307 MemoryPriority
= MEMORY_PRIORITY_BACKGROUND
;
311 // Save the old priority and update it
313 OldPriority
= (UCHAR
)Process
->Vm
.Flags
.MemoryPriority
;
314 Process
->Vm
.Flags
.MemoryPriority
= MemoryPriority
;
317 // Return the old priority
324 MmGetSessionLocaleId(VOID
)
330 // Get the current process
332 Process
= PsGetCurrentProcess();
335 // Check if it's the Session Leader
337 if (Process
->Vm
.Flags
.SessionLeader
)
340 // Make sure it has a valid Session
342 if (Process
->Session
)
348 return ((PMM_SESSION_SPACE
)Process
->Session
)->LocaleId
;
354 // Not a session leader, return the default
356 return PsDefaultThreadLocaleId
;
361 MmCreatePeb(IN PEPROCESS Process
,
362 IN PINITIAL_PEB InitialPeb
,
366 LARGE_INTEGER SectionOffset
;
368 PVOID TableBase
= NULL
;
369 PIMAGE_NT_HEADERS NtHeaders
;
370 PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigData
;
372 USHORT Characteristics
;
373 KAFFINITY ProcessAffinityMask
= 0;
374 SectionOffset
.QuadPart
= (ULONGLONG
)0;
380 KeAttachProcess(&Process
->Pcb
);
385 Peb
= MiCreatePebOrTeb(Process
,
386 (PVOID
)((ULONG_PTR
)MM_HIGHEST_VAD_ADDRESS
+ 1));
387 ASSERT(Peb
== (PVOID
)0x7FFDF000);
392 Status
= MmMapViewOfSection(ExpNlsSectionPointer
,
402 if (!NT_SUCCESS(Status
)) return Status
;
405 // Use SEH in case we can't load the PEB
410 // Initialize the PEB
412 RtlZeroMemory(Peb
, sizeof(PEB
));
417 Peb
->ImageBaseAddress
= Process
->SectionBaseAddress
;
418 Peb
->InheritedAddressSpace
= InitialPeb
->InheritedAddressSpace
;
419 Peb
->Mutant
= InitialPeb
->Mutant
;
420 Peb
->ImageUsesLargePages
= InitialPeb
->ImageUsesLargePages
;
425 Peb
->AnsiCodePageData
= (PCHAR
)TableBase
+ ExpAnsiCodePageDataOffset
;
426 Peb
->OemCodePageData
= (PCHAR
)TableBase
+ ExpOemCodePageDataOffset
;
427 Peb
->UnicodeCaseTableData
= (PCHAR
)TableBase
+ ExpUnicodeCaseTableDataOffset
;
430 // Default Version Data (could get changed below)
432 Peb
->OSMajorVersion
= NtMajorVersion
;
433 Peb
->OSMinorVersion
= NtMinorVersion
;
434 Peb
->OSBuildNumber
= (USHORT
)(NtBuildNumber
& 0x3FFF);
435 Peb
->OSPlatformId
= 2; /* VER_PLATFORM_WIN32_NT */
436 Peb
->OSCSDVersion
= (USHORT
)CmNtCSDVersion
;
439 // Heap and Debug Data
441 Peb
->NumberOfProcessors
= KeNumberProcessors
;
442 Peb
->BeingDebugged
= (BOOLEAN
)(Process
->DebugPort
!= NULL
? TRUE
: FALSE
);
443 Peb
->NtGlobalFlag
= NtGlobalFlag
;
444 /*Peb->HeapSegmentReserve = MmHeapSegmentReserve;
445 Peb->HeapSegmentCommit = MmHeapSegmentCommit;
446 Peb->HeapDeCommitTotalFreeThreshold = MmHeapDeCommitTotalFreeThreshold;
447 Peb->HeapDeCommitFreeBlockThreshold = MmHeapDeCommitFreeBlockThreshold;
448 Peb->CriticalSectionTimeout = MmCriticalSectionTimeout;
449 Peb->MinimumStackCommit = MmMinimumStackCommitInBytes;
451 Peb
->MaximumNumberOfHeaps
= (PAGE_SIZE
- sizeof(PEB
)) / sizeof(PVOID
);
452 Peb
->ProcessHeaps
= (PVOID
*)(Peb
+ 1);
457 if (Process
->Session
) Peb
->SessionId
= 0; // MmGetSessionId(Process);
459 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
465 _SEH2_YIELD(return _SEH2_GetExceptionCode());
470 // Use SEH in case we can't load the image
477 NtHeaders
= RtlImageNtHeader(Peb
->ImageBaseAddress
);
478 Characteristics
= NtHeaders
->FileHeader
.Characteristics
;
480 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
486 _SEH2_YIELD(return STATUS_INVALID_IMAGE_PROTECT
);
496 // Use SEH in case we can't load the headers
501 // Get the Image Config Data too
503 ImageConfigData
= RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
505 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
512 ProbeForRead(ImageConfigData
,
513 sizeof(IMAGE_LOAD_CONFIG_DIRECTORY
),
518 // Write subsystem data
520 Peb
->ImageSubsystem
= NtHeaders
->OptionalHeader
.Subsystem
;
521 Peb
->ImageSubsystemMajorVersion
= NtHeaders
->OptionalHeader
.MajorSubsystemVersion
;
522 Peb
->ImageSubsystemMinorVersion
= NtHeaders
->OptionalHeader
.MinorSubsystemVersion
;
525 // Check for version data
527 if (NtHeaders
->OptionalHeader
.Win32VersionValue
)
530 // Extract values and write them
532 Peb
->OSMajorVersion
= NtHeaders
->OptionalHeader
.Win32VersionValue
& 0xFF;
533 Peb
->OSMinorVersion
= (NtHeaders
->OptionalHeader
.Win32VersionValue
>> 8) & 0xFF;
534 Peb
->OSBuildNumber
= (NtHeaders
->OptionalHeader
.Win32VersionValue
>> 16) & 0x3FFF;
535 Peb
->OSPlatformId
= (NtHeaders
->OptionalHeader
.Win32VersionValue
>> 30) ^ 2;
539 // Process the image config data overrides if specfied
541 if (ImageConfigData
!= NULL
)
544 // Process CSD version override
546 if (ImageConfigData
->CSDVersion
)
551 Peb
->OSCSDVersion
= ImageConfigData
->CSDVersion
;
555 // Process affinity mask ovverride
557 if (ImageConfigData
->ProcessAffinityMask
)
562 ProcessAffinityMask
= ImageConfigData
->ProcessAffinityMask
;
567 // Check if this is a UP image
568 if (Characteristics
& IMAGE_FILE_UP_SYSTEM_ONLY
)
571 // Force it to use CPU 0
573 Peb
->ImageProcessAffinityMask
= 0;
578 // Whatever was configured
580 Peb
->ImageProcessAffinityMask
= ProcessAffinityMask
;
583 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
589 _SEH2_YIELD(return STATUS_INVALID_IMAGE_PROTECT
);
595 // Detach from the Process
599 return STATUS_SUCCESS
;
604 MmCreateTeb(IN PEPROCESS Process
,
605 IN PCLIENT_ID ClientId
,
606 IN PINITIAL_TEB InitialTeb
,
610 NTSTATUS Status
= STATUS_SUCCESS
;
616 KeAttachProcess(&Process
->Pcb
);
621 Teb
= MiCreatePebOrTeb(Process
,
622 (PVOID
)((ULONG_PTR
)MM_HIGHEST_VAD_ADDRESS
+ 1));
623 if (!Teb
) return STATUS_INSUFFICIENT_RESOURCES
;
626 // Use SEH in case we can't load the TEB
631 // Initialize the PEB
633 RtlZeroMemory(Teb
, sizeof(TEB
));
638 Teb
->NtTib
.ExceptionList
= EXCEPTION_CHAIN_END
;
639 Teb
->NtTib
.Self
= (PNT_TIB
)Teb
;
642 // Identify this as an OS/2 V3.0 ("Cruiser") TIB
644 Teb
->NtTib
.Version
= 30 << 8;
649 Teb
->ClientId
= *ClientId
;
650 Teb
->RealClientId
= *ClientId
;
651 Teb
->ProcessEnvironmentBlock
= Process
->Peb
;
652 Teb
->CurrentLocale
= PsDefaultThreadLocaleId
;
655 // Check if we have a grandparent TEB
657 if ((InitialTeb
->PreviousStackBase
== NULL
) &&
658 (InitialTeb
->PreviousStackLimit
== NULL
))
661 // Use initial TEB values
663 Teb
->NtTib
.StackBase
= InitialTeb
->StackBase
;
664 Teb
->NtTib
.StackLimit
= InitialTeb
->StackLimit
;
665 Teb
->DeallocationStack
= InitialTeb
->AllocatedStackBase
;
670 // Use grandparent TEB values
672 Teb
->NtTib
.StackBase
= InitialTeb
->PreviousStackBase
;
673 Teb
->NtTib
.StackLimit
= InitialTeb
->PreviousStackLimit
;
677 // Initialize the static unicode string
679 Teb
->StaticUnicodeString
.MaximumLength
= sizeof(Teb
->StaticUnicodeBuffer
);
680 Teb
->StaticUnicodeString
.Buffer
= Teb
->StaticUnicodeBuffer
;
682 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
687 Status
= _SEH2_GetExceptionCode();
699 /* SYSTEM CALLS ***************************************************************/
703 NtAllocateUserPhysicalPages(IN HANDLE ProcessHandle
,
704 IN OUT PULONG_PTR NumberOfPages
,
705 IN OUT PULONG_PTR UserPfnArray
)
708 return STATUS_NOT_IMPLEMENTED
;
713 NtMapUserPhysicalPages(IN PVOID VirtualAddresses
,
714 IN ULONG_PTR NumberOfPages
,
715 IN OUT PULONG_PTR UserPfnArray
)
718 return STATUS_NOT_IMPLEMENTED
;
723 NtMapUserPhysicalPagesScatter(IN PVOID
*VirtualAddresses
,
724 IN ULONG_PTR NumberOfPages
,
725 IN OUT PULONG_PTR UserPfnArray
)
728 return STATUS_NOT_IMPLEMENTED
;
733 NtFreeUserPhysicalPages(IN HANDLE ProcessHandle
,
734 IN OUT PULONG_PTR NumberOfPages
,
735 IN OUT PULONG_PTR UserPfnArray
)
738 return STATUS_NOT_IMPLEMENTED
;