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
= HyperTemplatePte
;
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
, 0);
162 TempPte
.u
.Hard
.PageFrameNumber
= PageFrameIndex
;
167 *PointerPte
= TempPte
;
171 // Release the PFN lock
173 KeReleaseQueuedSpinLock(LockQueuePfnLock
, OldIrql
);
176 // Return the stack address
183 MmGrowKernelStackEx(IN PVOID StackPointer
,
186 PKTHREAD Thread
= KeGetCurrentThread();
187 PMMPTE LimitPte
, NewLimitPte
, LastPte
;
188 PFN_NUMBER StackPages
;
191 PFN_NUMBER PageFrameIndex
;
194 // Make sure the stack did not overflow
196 ASSERT(((ULONG_PTR
)Thread
->StackBase
- (ULONG_PTR
)Thread
->StackLimit
) <=
197 (KERNEL_LARGE_STACK_SIZE
+ PAGE_SIZE
));
200 // Get the current stack limit
202 LimitPte
= MiAddressToPte(Thread
->StackLimit
);
203 ASSERT(LimitPte
->u
.Hard
.Valid
== 1);
206 // Get the new one and make sure this isn't a retarded request
208 NewLimitPte
= MiAddressToPte((PVOID
)((ULONG_PTR
)StackPointer
- GrowSize
));
209 if (NewLimitPte
== LimitPte
) return STATUS_SUCCESS
;
212 // Now make sure you're not going past the reserved space
214 LastPte
= MiAddressToPte((PVOID
)((ULONG_PTR
)Thread
->StackBase
-
215 KERNEL_LARGE_STACK_SIZE
));
216 if (NewLimitPte
< LastPte
)
221 DPRINT1("Thread wants too much stack\n");
222 return STATUS_STACK_OVERFLOW
;
226 // Calculate the number of new pages
229 StackPages
= (LimitPte
- NewLimitPte
+ 1);
232 // Setup the template stack PTE
234 TempPte
= HyperTemplatePte
;
235 MI_MAKE_LOCAL_PAGE(&TempPte
);
236 MI_MAKE_DIRTY_PAGE(&TempPte
);
237 TempPte
.u
.Hard
.PageFrameNumber
= 0;
240 // Acquire the PFN DB lock
242 OldIrql
= KeAcquireQueuedSpinLock(LockQueuePfnLock
);
245 // Loop each stack page
247 while (LimitPte
>= NewLimitPte
)
252 ASSERT(LimitPte
->u
.Hard
.Valid
== 0);
257 PageFrameIndex
= MmAllocPage(MC_NPPOOL
, 0);
258 TempPte
.u
.Hard
.PageFrameNumber
= PageFrameIndex
;
263 *LimitPte
-- = TempPte
;
267 // Release the PFN lock
269 KeReleaseQueuedSpinLock(LockQueuePfnLock
, OldIrql
);
274 Thread
->StackLimit
= (ULONG_PTR
)MiPteToAddress(NewLimitPte
);
275 return STATUS_SUCCESS
;
280 MmGrowKernelStack(IN PVOID StackPointer
)
283 // Call the extended version
285 return MmGrowKernelStackEx(StackPointer
, KERNEL_LARGE_STACK_COMMIT
);
290 MmSetMemoryPriorityProcess(IN PEPROCESS Process
,
291 IN UCHAR MemoryPriority
)
296 // Check if we have less then 16MB of Physical Memory
298 if ((MmSystemSize
== MmSmallSystem
) &&
299 (MmNumberOfPhysicalPages
< ((15 * 1024 * 1024) / PAGE_SIZE
)))
302 // Always use background priority
304 MemoryPriority
= MEMORY_PRIORITY_BACKGROUND
;
308 // Save the old priority and update it
310 OldPriority
= (UCHAR
)Process
->Vm
.Flags
.MemoryPriority
;
311 Process
->Vm
.Flags
.MemoryPriority
= MemoryPriority
;
314 // Return the old priority
321 MmGetSessionLocaleId(VOID
)
327 // Get the current process
329 Process
= PsGetCurrentProcess();
332 // Check if it's the Session Leader
334 if (Process
->Vm
.Flags
.SessionLeader
)
337 // Make sure it has a valid Session
339 if (Process
->Session
)
345 return ((PMM_SESSION_SPACE
)Process
->Session
)->LocaleId
;
351 // Not a session leader, return the default
353 return PsDefaultThreadLocaleId
;
358 MmCreatePeb(IN PEPROCESS Process
,
359 IN PINITIAL_PEB InitialPeb
,
363 LARGE_INTEGER SectionOffset
;
365 PVOID TableBase
= NULL
;
366 PIMAGE_NT_HEADERS NtHeaders
;
367 PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigData
;
369 USHORT Characteristics
;
370 KAFFINITY ProcessAffinityMask
= 0;
371 SectionOffset
.QuadPart
= (ULONGLONG
)0;
377 KeAttachProcess(&Process
->Pcb
);
382 Peb
= MiCreatePebOrTeb(Process
,
383 (PVOID
)((ULONG_PTR
)MM_HIGHEST_VAD_ADDRESS
+ 1));
384 ASSERT(Peb
== (PVOID
)0x7FFDF000);
389 Status
= MmMapViewOfSection(ExpNlsSectionPointer
,
399 if (!NT_SUCCESS(Status
)) return Status
;
402 // Use SEH in case we can't load the PEB
407 // Initialize the PEB
409 RtlZeroMemory(Peb
, sizeof(PEB
));
414 Peb
->ImageBaseAddress
= Process
->SectionBaseAddress
;
415 Peb
->InheritedAddressSpace
= InitialPeb
->InheritedAddressSpace
;
416 Peb
->Mutant
= InitialPeb
->Mutant
;
417 Peb
->ImageUsesLargePages
= InitialPeb
->ImageUsesLargePages
;
422 Peb
->AnsiCodePageData
= (PCHAR
)TableBase
+ ExpAnsiCodePageDataOffset
;
423 Peb
->OemCodePageData
= (PCHAR
)TableBase
+ ExpOemCodePageDataOffset
;
424 Peb
->UnicodeCaseTableData
= (PCHAR
)TableBase
+ ExpUnicodeCaseTableDataOffset
;
427 // Default Version Data (could get changed below)
429 Peb
->OSMajorVersion
= NtMajorVersion
;
430 Peb
->OSMinorVersion
= NtMinorVersion
;
431 Peb
->OSBuildNumber
= (USHORT
)(NtBuildNumber
& 0x3FFF);
432 Peb
->OSPlatformId
= 2; /* VER_PLATFORM_WIN32_NT */
433 Peb
->OSCSDVersion
= (USHORT
)CmNtCSDVersion
;
436 // Heap and Debug Data
438 Peb
->NumberOfProcessors
= KeNumberProcessors
;
439 Peb
->BeingDebugged
= (BOOLEAN
)(Process
->DebugPort
!= NULL
? TRUE
: FALSE
);
440 Peb
->NtGlobalFlag
= NtGlobalFlag
;
441 /*Peb->HeapSegmentReserve = MmHeapSegmentReserve;
442 Peb->HeapSegmentCommit = MmHeapSegmentCommit;
443 Peb->HeapDeCommitTotalFreeThreshold = MmHeapDeCommitTotalFreeThreshold;
444 Peb->HeapDeCommitFreeBlockThreshold = MmHeapDeCommitFreeBlockThreshold;
445 Peb->CriticalSectionTimeout = MmCriticalSectionTimeout;
446 Peb->MinimumStackCommit = MmMinimumStackCommitInBytes;
448 Peb
->MaximumNumberOfHeaps
= (PAGE_SIZE
- sizeof(PEB
)) / sizeof(PVOID
);
449 Peb
->ProcessHeaps
= (PVOID
*)(Peb
+ 1);
454 if (Process
->Session
) Peb
->SessionId
= 0; // MmGetSessionId(Process);
456 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
462 _SEH2_YIELD(return _SEH2_GetExceptionCode());
467 // Use SEH in case we can't load the image
474 NtHeaders
= RtlImageNtHeader(Peb
->ImageBaseAddress
);
475 Characteristics
= NtHeaders
->FileHeader
.Characteristics
;
477 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
483 _SEH2_YIELD(return STATUS_INVALID_IMAGE_PROTECT
);
493 // Use SEH in case we can't load the headers
498 // Get the Image Config Data too
500 ImageConfigData
= RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
502 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
509 ProbeForRead(ImageConfigData
,
510 sizeof(IMAGE_LOAD_CONFIG_DIRECTORY
),
515 // Write subsystem data
517 Peb
->ImageSubSystem
= NtHeaders
->OptionalHeader
.Subsystem
;
518 Peb
->ImageSubSystemMajorVersion
= NtHeaders
->OptionalHeader
.MajorSubsystemVersion
;
519 Peb
->ImageSubSystemMinorVersion
= NtHeaders
->OptionalHeader
.MinorSubsystemVersion
;
522 // Check for version data
524 if (NtHeaders
->OptionalHeader
.Win32VersionValue
)
527 // Extract values and write them
529 Peb
->OSMajorVersion
= NtHeaders
->OptionalHeader
.Win32VersionValue
& 0xFF;
530 Peb
->OSMinorVersion
= (NtHeaders
->OptionalHeader
.Win32VersionValue
>> 8) & 0xFF;
531 Peb
->OSBuildNumber
= (NtHeaders
->OptionalHeader
.Win32VersionValue
>> 16) & 0x3FFF;
532 Peb
->OSPlatformId
= (NtHeaders
->OptionalHeader
.Win32VersionValue
>> 30) ^ 2;
536 // Process the image config data overrides if specfied
538 if (ImageConfigData
!= NULL
)
541 // Process CSD version override
543 if (ImageConfigData
->CSDVersion
)
548 Peb
->OSCSDVersion
= ImageConfigData
->CSDVersion
;
552 // Process affinity mask ovverride
554 if (ImageConfigData
->ProcessAffinityMask
)
559 ProcessAffinityMask
= ImageConfigData
->ProcessAffinityMask
;
564 // Check if this is a UP image
565 if (Characteristics
& IMAGE_FILE_UP_SYSTEM_ONLY
)
568 // Force it to use CPU 0
570 Peb
->ImageProcessAffinityMask
= 0;
575 // Whatever was configured
577 Peb
->ImageProcessAffinityMask
= ProcessAffinityMask
;
580 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
586 _SEH2_YIELD(return STATUS_INVALID_IMAGE_PROTECT
);
592 // Detach from the Process
596 return STATUS_SUCCESS
;
601 MmCreateTeb(IN PEPROCESS Process
,
602 IN PCLIENT_ID ClientId
,
603 IN PINITIAL_TEB InitialTeb
,
607 NTSTATUS Status
= STATUS_SUCCESS
;
613 KeAttachProcess(&Process
->Pcb
);
618 Teb
= MiCreatePebOrTeb(Process
,
619 (PVOID
)((ULONG_PTR
)MM_HIGHEST_VAD_ADDRESS
+ 1));
620 if (!Teb
) return STATUS_INSUFFICIENT_RESOURCES
;
623 // Use SEH in case we can't load the TEB
628 // Initialize the PEB
630 RtlZeroMemory(Teb
, sizeof(TEB
));
635 Teb
->Tib
.ExceptionList
= EXCEPTION_CHAIN_END
;
636 Teb
->Tib
.Self
= (PNT_TIB
)Teb
;
639 // Identify this as an OS/2 V3.0 ("Cruiser") TIB
641 Teb
->Tib
.Version
= 30 << 8;
646 Teb
->ClientId
= *ClientId
;
647 Teb
->RealClientId
= *ClientId
;
648 Teb
->ProcessEnvironmentBlock
= Process
->Peb
;
649 Teb
->CurrentLocale
= PsDefaultThreadLocaleId
;
652 // Check if we have a grandparent TEB
654 if ((InitialTeb
->PreviousStackBase
== NULL
) &&
655 (InitialTeb
->PreviousStackLimit
== NULL
))
658 // Use initial TEB values
660 Teb
->Tib
.StackBase
= InitialTeb
->StackBase
;
661 Teb
->Tib
.StackLimit
= InitialTeb
->StackLimit
;
662 Teb
->DeallocationStack
= InitialTeb
->AllocatedStackBase
;
667 // Use grandparent TEB values
669 Teb
->Tib
.StackBase
= InitialTeb
->PreviousStackBase
;
670 Teb
->Tib
.StackLimit
= InitialTeb
->PreviousStackLimit
;
674 // Initialize the static unicode string
676 Teb
->StaticUnicodeString
.MaximumLength
= sizeof(Teb
->StaticUnicodeBuffer
);
677 Teb
->StaticUnicodeString
.Buffer
= Teb
->StaticUnicodeBuffer
;
679 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
684 Status
= _SEH2_GetExceptionCode();
696 /* SYSTEM CALLS ***************************************************************/
700 NtAllocateUserPhysicalPages(IN HANDLE ProcessHandle
,
701 IN OUT PULONG_PTR NumberOfPages
,
702 IN OUT PULONG_PTR UserPfnArray
)
705 return STATUS_NOT_IMPLEMENTED
;
710 NtMapUserPhysicalPages(IN PVOID VirtualAddresses
,
711 IN ULONG_PTR NumberOfPages
,
712 IN OUT PULONG_PTR UserPfnArray
)
715 return STATUS_NOT_IMPLEMENTED
;
720 NtMapUserPhysicalPagesScatter(IN PVOID
*VirtualAddresses
,
721 IN ULONG_PTR NumberOfPages
,
722 IN OUT PULONG_PTR UserPfnArray
)
725 return STATUS_NOT_IMPLEMENTED
;
730 NtFreeUserPhysicalPages(IN HANDLE ProcessHandle
,
731 IN OUT PULONG_PTR NumberOfPages
,
732 IN OUT PULONG_PTR UserPfnArray
)
735 return STATUS_NOT_IMPLEMENTED
;