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
++)
160 PageFrameIndex
= MmAllocPage(MC_NPPOOL
);
161 TempPte
.u
.Hard
.PageFrameNumber
= PageFrameIndex
;
166 ASSERT(PointerPte
->u
.Hard
.Valid
== 0);
167 ASSERT(TempPte
.u
.Hard
.Valid
== 1);
168 *PointerPte
= TempPte
;
172 (VOID
)InterlockedExchangeAddUL(&MiMemoryConsumers
[MC_NPPOOL
].PagesUsed
, StackPages
);
175 // Release the PFN lock
177 KeReleaseQueuedSpinLock(LockQueuePfnLock
, OldIrql
);
180 // Return the stack address
187 MmGrowKernelStackEx(IN PVOID StackPointer
,
190 PKTHREAD Thread
= KeGetCurrentThread();
191 PMMPTE LimitPte
, NewLimitPte
, LastPte
;
192 PFN_NUMBER StackPages
;
195 PFN_NUMBER PageFrameIndex
;
198 // Make sure the stack did not overflow
200 ASSERT(((ULONG_PTR
)Thread
->StackBase
- (ULONG_PTR
)Thread
->StackLimit
) <=
201 (KERNEL_LARGE_STACK_SIZE
+ PAGE_SIZE
));
204 // Get the current stack limit
206 LimitPte
= MiAddressToPte(Thread
->StackLimit
);
207 ASSERT(LimitPte
->u
.Hard
.Valid
== 1);
210 // Get the new one and make sure this isn't a retarded request
212 NewLimitPte
= MiAddressToPte((PVOID
)((ULONG_PTR
)StackPointer
- GrowSize
));
213 if (NewLimitPte
== LimitPte
) return STATUS_SUCCESS
;
216 // Now make sure you're not going past the reserved space
218 LastPte
= MiAddressToPte((PVOID
)((ULONG_PTR
)Thread
->StackBase
-
219 KERNEL_LARGE_STACK_SIZE
));
220 if (NewLimitPte
< LastPte
)
225 DPRINT1("Thread wants too much stack\n");
226 return STATUS_STACK_OVERFLOW
;
230 // Calculate the number of new pages
233 StackPages
= (LimitPte
- NewLimitPte
+ 1);
236 // Setup the template stack PTE
238 TempPte
= ValidKernelPte
;
239 MI_MAKE_LOCAL_PAGE(&TempPte
);
240 MI_MAKE_DIRTY_PAGE(&TempPte
);
241 TempPte
.u
.Hard
.PageFrameNumber
= 0;
244 // Acquire the PFN DB lock
246 OldIrql
= KeAcquireQueuedSpinLock(LockQueuePfnLock
);
249 // Loop each stack page
251 while (LimitPte
>= NewLimitPte
)
256 PageFrameIndex
= MmAllocPage(MC_NPPOOL
);
257 TempPte
.u
.Hard
.PageFrameNumber
= PageFrameIndex
;
259 /* Write the valid PTE */
260 ASSERT(LimitPte
->u
.Hard
.Valid
== 0);
261 ASSERT(TempPte
.u
.Hard
.Valid
== 1);
262 *LimitPte
-- = TempPte
;
266 // Release the PFN lock
268 KeReleaseQueuedSpinLock(LockQueuePfnLock
, OldIrql
);
273 Thread
->StackLimit
= (ULONG_PTR
)MiPteToAddress(NewLimitPte
);
274 return STATUS_SUCCESS
;
279 MmGrowKernelStack(IN PVOID StackPointer
)
282 // Call the extended version
284 return MmGrowKernelStackEx(StackPointer
, KERNEL_LARGE_STACK_COMMIT
);
289 MmSetMemoryPriorityProcess(IN PEPROCESS Process
,
290 IN UCHAR MemoryPriority
)
295 // Check if we have less then 16MB of Physical Memory
297 if ((MmSystemSize
== MmSmallSystem
) &&
298 (MmNumberOfPhysicalPages
< ((15 * 1024 * 1024) / PAGE_SIZE
)))
301 // Always use background priority
303 MemoryPriority
= MEMORY_PRIORITY_BACKGROUND
;
307 // Save the old priority and update it
309 OldPriority
= (UCHAR
)Process
->Vm
.Flags
.MemoryPriority
;
310 Process
->Vm
.Flags
.MemoryPriority
= MemoryPriority
;
313 // Return the old priority
320 MmGetSessionLocaleId(VOID
)
326 // Get the current process
328 Process
= PsGetCurrentProcess();
331 // Check if it's the Session Leader
333 if (Process
->Vm
.Flags
.SessionLeader
)
336 // Make sure it has a valid Session
338 if (Process
->Session
)
344 return ((PMM_SESSION_SPACE
)Process
->Session
)->LocaleId
;
350 // Not a session leader, return the default
352 return PsDefaultThreadLocaleId
;
357 MmCreatePeb(IN PEPROCESS Process
,
358 IN PINITIAL_PEB InitialPeb
,
362 LARGE_INTEGER SectionOffset
;
364 PVOID TableBase
= NULL
;
365 PIMAGE_NT_HEADERS NtHeaders
;
366 PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigData
;
368 USHORT Characteristics
;
369 KAFFINITY ProcessAffinityMask
= 0;
370 SectionOffset
.QuadPart
= (ULONGLONG
)0;
376 KeAttachProcess(&Process
->Pcb
);
381 Peb
= MiCreatePebOrTeb(Process
,
382 (PVOID
)((ULONG_PTR
)MM_HIGHEST_VAD_ADDRESS
+ 1));
383 ASSERT(Peb
== (PVOID
)0x7FFDF000);
388 Status
= MmMapViewOfSection(ExpNlsSectionPointer
,
398 if (!NT_SUCCESS(Status
)) return Status
;
401 // Use SEH in case we can't load the PEB
406 // Initialize the PEB
408 RtlZeroMemory(Peb
, sizeof(PEB
));
413 Peb
->ImageBaseAddress
= Process
->SectionBaseAddress
;
414 Peb
->InheritedAddressSpace
= InitialPeb
->InheritedAddressSpace
;
415 Peb
->Mutant
= InitialPeb
->Mutant
;
416 Peb
->ImageUsesLargePages
= InitialPeb
->ImageUsesLargePages
;
421 Peb
->AnsiCodePageData
= (PCHAR
)TableBase
+ ExpAnsiCodePageDataOffset
;
422 Peb
->OemCodePageData
= (PCHAR
)TableBase
+ ExpOemCodePageDataOffset
;
423 Peb
->UnicodeCaseTableData
= (PCHAR
)TableBase
+ ExpUnicodeCaseTableDataOffset
;
426 // Default Version Data (could get changed below)
428 Peb
->OSMajorVersion
= NtMajorVersion
;
429 Peb
->OSMinorVersion
= NtMinorVersion
;
430 Peb
->OSBuildNumber
= (USHORT
)(NtBuildNumber
& 0x3FFF);
431 Peb
->OSPlatformId
= 2; /* VER_PLATFORM_WIN32_NT */
432 Peb
->OSCSDVersion
= (USHORT
)CmNtCSDVersion
;
435 // Heap and Debug Data
437 Peb
->NumberOfProcessors
= KeNumberProcessors
;
438 Peb
->BeingDebugged
= (BOOLEAN
)(Process
->DebugPort
!= NULL
? TRUE
: FALSE
);
439 Peb
->NtGlobalFlag
= NtGlobalFlag
;
440 /*Peb->HeapSegmentReserve = MmHeapSegmentReserve;
441 Peb->HeapSegmentCommit = MmHeapSegmentCommit;
442 Peb->HeapDeCommitTotalFreeThreshold = MmHeapDeCommitTotalFreeThreshold;
443 Peb->HeapDeCommitFreeBlockThreshold = MmHeapDeCommitFreeBlockThreshold;
444 Peb->CriticalSectionTimeout = MmCriticalSectionTimeout;
445 Peb->MinimumStackCommit = MmMinimumStackCommitInBytes;
447 Peb
->MaximumNumberOfHeaps
= (PAGE_SIZE
- sizeof(PEB
)) / sizeof(PVOID
);
448 Peb
->ProcessHeaps
= (PVOID
*)(Peb
+ 1);
453 if (Process
->Session
) Peb
->SessionId
= 0; // MmGetSessionId(Process);
455 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
461 _SEH2_YIELD(return _SEH2_GetExceptionCode());
466 // Use SEH in case we can't load the image
473 NtHeaders
= RtlImageNtHeader(Peb
->ImageBaseAddress
);
474 Characteristics
= NtHeaders
->FileHeader
.Characteristics
;
476 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
482 _SEH2_YIELD(return STATUS_INVALID_IMAGE_PROTECT
);
492 // Use SEH in case we can't load the headers
497 // Get the Image Config Data too
499 ImageConfigData
= RtlImageDirectoryEntryToData(Peb
->ImageBaseAddress
,
501 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
,
508 ProbeForRead(ImageConfigData
,
509 sizeof(IMAGE_LOAD_CONFIG_DIRECTORY
),
514 // Write subsystem data
516 Peb
->ImageSubsystem
= NtHeaders
->OptionalHeader
.Subsystem
;
517 Peb
->ImageSubsystemMajorVersion
= NtHeaders
->OptionalHeader
.MajorSubsystemVersion
;
518 Peb
->ImageSubsystemMinorVersion
= NtHeaders
->OptionalHeader
.MinorSubsystemVersion
;
521 // Check for version data
523 if (NtHeaders
->OptionalHeader
.Win32VersionValue
)
526 // Extract values and write them
528 Peb
->OSMajorVersion
= NtHeaders
->OptionalHeader
.Win32VersionValue
& 0xFF;
529 Peb
->OSMinorVersion
= (NtHeaders
->OptionalHeader
.Win32VersionValue
>> 8) & 0xFF;
530 Peb
->OSBuildNumber
= (NtHeaders
->OptionalHeader
.Win32VersionValue
>> 16) & 0x3FFF;
531 Peb
->OSPlatformId
= (NtHeaders
->OptionalHeader
.Win32VersionValue
>> 30) ^ 2;
535 // Process the image config data overrides if specfied
537 if (ImageConfigData
!= NULL
)
540 // Process CSD version override
542 if (ImageConfigData
->CSDVersion
)
547 Peb
->OSCSDVersion
= ImageConfigData
->CSDVersion
;
551 // Process affinity mask ovverride
553 if (ImageConfigData
->ProcessAffinityMask
)
558 ProcessAffinityMask
= ImageConfigData
->ProcessAffinityMask
;
563 // Check if this is a UP image
564 if (Characteristics
& IMAGE_FILE_UP_SYSTEM_ONLY
)
567 // Force it to use CPU 0
569 Peb
->ImageProcessAffinityMask
= 0;
574 // Whatever was configured
576 Peb
->ImageProcessAffinityMask
= ProcessAffinityMask
;
579 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
585 _SEH2_YIELD(return STATUS_INVALID_IMAGE_PROTECT
);
591 // Detach from the Process
595 return STATUS_SUCCESS
;
600 MmCreateTeb(IN PEPROCESS Process
,
601 IN PCLIENT_ID ClientId
,
602 IN PINITIAL_TEB InitialTeb
,
606 NTSTATUS Status
= STATUS_SUCCESS
;
612 KeAttachProcess(&Process
->Pcb
);
617 Teb
= MiCreatePebOrTeb(Process
,
618 (PVOID
)((ULONG_PTR
)MM_HIGHEST_VAD_ADDRESS
+ 1));
619 if (!Teb
) return STATUS_INSUFFICIENT_RESOURCES
;
622 // Use SEH in case we can't load the TEB
627 // Initialize the PEB
629 RtlZeroMemory(Teb
, sizeof(TEB
));
634 Teb
->NtTib
.ExceptionList
= EXCEPTION_CHAIN_END
;
635 Teb
->NtTib
.Self
= (PNT_TIB
)Teb
;
638 // Identify this as an OS/2 V3.0 ("Cruiser") TIB
640 Teb
->NtTib
.Version
= 30 << 8;
645 Teb
->ClientId
= *ClientId
;
646 Teb
->RealClientId
= *ClientId
;
647 Teb
->ProcessEnvironmentBlock
= Process
->Peb
;
648 Teb
->CurrentLocale
= PsDefaultThreadLocaleId
;
651 // Check if we have a grandparent TEB
653 if ((InitialTeb
->PreviousStackBase
== NULL
) &&
654 (InitialTeb
->PreviousStackLimit
== NULL
))
657 // Use initial TEB values
659 Teb
->NtTib
.StackBase
= InitialTeb
->StackBase
;
660 Teb
->NtTib
.StackLimit
= InitialTeb
->StackLimit
;
661 Teb
->DeallocationStack
= InitialTeb
->AllocatedStackBase
;
666 // Use grandparent TEB values
668 Teb
->NtTib
.StackBase
= InitialTeb
->PreviousStackBase
;
669 Teb
->NtTib
.StackLimit
= InitialTeb
->PreviousStackLimit
;
673 // Initialize the static unicode string
675 Teb
->StaticUnicodeString
.MaximumLength
= sizeof(Teb
->StaticUnicodeBuffer
);
676 Teb
->StaticUnicodeString
.Buffer
= Teb
->StaticUnicodeBuffer
;
678 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
683 Status
= _SEH2_GetExceptionCode();
695 /* SYSTEM CALLS ***************************************************************/
699 NtAllocateUserPhysicalPages(IN HANDLE ProcessHandle
,
700 IN OUT PULONG_PTR NumberOfPages
,
701 IN OUT PULONG_PTR UserPfnArray
)
704 return STATUS_NOT_IMPLEMENTED
;
709 NtMapUserPhysicalPages(IN PVOID VirtualAddresses
,
710 IN ULONG_PTR NumberOfPages
,
711 IN OUT PULONG_PTR UserPfnArray
)
714 return STATUS_NOT_IMPLEMENTED
;
719 NtMapUserPhysicalPagesScatter(IN PVOID
*VirtualAddresses
,
720 IN ULONG_PTR NumberOfPages
,
721 IN OUT PULONG_PTR UserPfnArray
)
724 return STATUS_NOT_IMPLEMENTED
;
729 NtFreeUserPhysicalPages(IN HANDLE ProcessHandle
,
730 IN OUT PULONG_PTR NumberOfPages
,
731 IN OUT PULONG_PTR UserPfnArray
)
734 return STATUS_NOT_IMPLEMENTED
;