mirror of
https://github.com/reactos/reactos.git
synced 2024-08-21 19:03:01 +00:00
![Timo Kreuzer](/assets/img/avatar_default.png)
* Add an NDK header to define INIT_FUNCTION/INIT_SECTION globally * Use _declspec(allocate(x)) and _declspec(code_seg(x)) on MSVC versions that support it * Use INIT_FUNCTION on functions only and INIT_SECTION on data only (required by MSVC) * Place INIT_FUNCTION before the return type (required by MSVC) * Make sure declarations and implementations share the same modifiers (required by MSVC) * Add a global linker option to suppress warnings about defined but unused INIT section * Merge INIT section into .text in freeldr
306 lines
10 KiB
C
306 lines
10 KiB
C
/*
|
|
* PROJECT: ReactOS Kernel
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: ntoskrnl/ke/krnlinit.c
|
|
* PURPOSE: Portable part of kernel initialization
|
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
|
*/
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#include <ntoskrnl.h>
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
#include <internal/napi.h>
|
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
/* Portable CPU Features and Flags */
|
|
USHORT KeProcessorArchitecture;
|
|
USHORT KeProcessorLevel;
|
|
USHORT KeProcessorRevision;
|
|
ULONG KeFeatureBits;
|
|
KAFFINITY KeActiveProcessors = 1;
|
|
|
|
/* System call count */
|
|
ULONG KiServiceLimit = NUMBER_OF_SYSCALLS;
|
|
|
|
/* ARC Loader Block */
|
|
PLOADER_PARAMETER_BLOCK KeLoaderBlock;
|
|
|
|
/* PRCB Array */
|
|
PKPRCB KiProcessorBlock[MAXIMUM_PROCESSORS];
|
|
|
|
/* Number of processors */
|
|
CCHAR KeNumberProcessors = 0;
|
|
|
|
/* NUMA Node Support */
|
|
KNODE KiNode0;
|
|
PKNODE KeNodeBlock[1];
|
|
UCHAR KeNumberNodes = 1;
|
|
UCHAR KeProcessNodeSeed;
|
|
|
|
/* Initial Process and Thread */
|
|
ETHREAD KiInitialThread;
|
|
EPROCESS KiInitialProcess;
|
|
|
|
/* System-defined Spinlocks */
|
|
KSPIN_LOCK KiDispatcherLock;
|
|
KSPIN_LOCK MmPfnLock;
|
|
KSPIN_LOCK MmSystemSpaceLock;
|
|
KSPIN_LOCK CcBcbSpinLock;
|
|
KSPIN_LOCK CcMasterSpinLock;
|
|
KSPIN_LOCK CcVacbSpinLock;
|
|
KSPIN_LOCK CcWorkQueueSpinLock;
|
|
KSPIN_LOCK NonPagedPoolLock;
|
|
KSPIN_LOCK MmNonPagedPoolLock;
|
|
KSPIN_LOCK IopCancelSpinLock;
|
|
KSPIN_LOCK IopVpbSpinLock;
|
|
KSPIN_LOCK IopDatabaseLock;
|
|
KSPIN_LOCK IopCompletionLock;
|
|
KSPIN_LOCK NtfsStructLock;
|
|
KSPIN_LOCK AfdWorkQueueSpinLock;
|
|
KSPIN_LOCK KiTimerTableLock[16];
|
|
KSPIN_LOCK KiReverseStallIpiLock;
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
INIT_FUNCTION
|
|
VOID
|
|
NTAPI
|
|
KiInitSystem(VOID)
|
|
{
|
|
ULONG i;
|
|
|
|
/* Initialize Bugcheck Callback data */
|
|
InitializeListHead(&KeBugcheckCallbackListHead);
|
|
InitializeListHead(&KeBugcheckReasonCallbackListHead);
|
|
KeInitializeSpinLock(&BugCheckCallbackLock);
|
|
|
|
/* Initialize the Timer Expiration DPC */
|
|
KeInitializeDpc(&KiTimerExpireDpc, KiTimerExpiration, NULL);
|
|
KeSetTargetProcessorDpc(&KiTimerExpireDpc, 0);
|
|
|
|
/* Initialize Profiling data */
|
|
KeInitializeSpinLock(&KiProfileLock);
|
|
InitializeListHead(&KiProfileListHead);
|
|
InitializeListHead(&KiProfileSourceListHead);
|
|
|
|
/* Loop the timer table */
|
|
for (i = 0; i < TIMER_TABLE_SIZE; i++)
|
|
{
|
|
/* Initialize the list and entries */
|
|
InitializeListHead(&KiTimerTableListHead[i].Entry);
|
|
KiTimerTableListHead[i].Time.HighPart = 0xFFFFFFFF;
|
|
KiTimerTableListHead[i].Time.LowPart = 0;
|
|
}
|
|
|
|
/* Initialize the Swap event and all swap lists */
|
|
KeInitializeEvent(&KiSwapEvent, SynchronizationEvent, FALSE);
|
|
InitializeListHead(&KiProcessInSwapListHead);
|
|
InitializeListHead(&KiProcessOutSwapListHead);
|
|
InitializeListHead(&KiStackInSwapListHead);
|
|
|
|
/* Initialize the mutex for generic DPC calls */
|
|
ExInitializeFastMutex(&KiGenericCallDpcMutex);
|
|
|
|
/* Initialize the syscall table */
|
|
KeServiceDescriptorTable[0].Base = MainSSDT;
|
|
KeServiceDescriptorTable[0].Count = NULL;
|
|
KeServiceDescriptorTable[0].Limit = KiServiceLimit;
|
|
KeServiceDescriptorTable[1].Limit = 0;
|
|
KeServiceDescriptorTable[0].Number = MainSSPT;
|
|
|
|
/* Copy the the current table into the shadow table for win32k */
|
|
RtlCopyMemory(KeServiceDescriptorTableShadow,
|
|
KeServiceDescriptorTable,
|
|
sizeof(KeServiceDescriptorTable));
|
|
}
|
|
|
|
INIT_FUNCTION
|
|
LARGE_INTEGER
|
|
NTAPI
|
|
KiComputeReciprocal(IN LONG Divisor,
|
|
OUT PUCHAR Shift)
|
|
{
|
|
LARGE_INTEGER Reciprocal = {{0, 0}};
|
|
LONG BitCount = 0, Remainder = 1;
|
|
|
|
/* Start by calculating the remainder */
|
|
while (Reciprocal.HighPart >= 0)
|
|
{
|
|
/* Increase the loop (bit) count */
|
|
BitCount++;
|
|
|
|
/* Calculate the current fraction */
|
|
Reciprocal.HighPart = (Reciprocal.HighPart << 1) |
|
|
(Reciprocal.LowPart >> 31);
|
|
Reciprocal.LowPart <<= 1;
|
|
|
|
/* Double the remainder and see if we went past the divisor */
|
|
Remainder <<= 1;
|
|
if (Remainder >= Divisor)
|
|
{
|
|
/* Set the low-bit and calculate the new remainder */
|
|
Remainder -= Divisor;
|
|
Reciprocal.LowPart |= 1;
|
|
}
|
|
}
|
|
|
|
/* Check if we have a remainder */
|
|
if (Remainder)
|
|
{
|
|
/* Check if the current fraction value is too large */
|
|
if ((Reciprocal.LowPart == 0xFFFFFFFF) &&
|
|
(Reciprocal.HighPart == (LONG)0xFFFFFFFF))
|
|
{
|
|
/* Set the high bit and reduce the bit count */
|
|
Reciprocal.LowPart = 0;
|
|
Reciprocal.HighPart = 0x80000000;
|
|
BitCount--;
|
|
}
|
|
else
|
|
{
|
|
/* Check if only the lowest bits got too large */
|
|
if (Reciprocal.LowPart == 0xFFFFFFFF)
|
|
{
|
|
/* Reset them and increase the high bits instead */
|
|
Reciprocal.LowPart = 0;
|
|
Reciprocal.HighPart++;
|
|
}
|
|
else
|
|
{
|
|
/* All is well, increase the low bits */
|
|
Reciprocal.LowPart++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Now calculate the actual shift and return the reciprocal */
|
|
*Shift = (UCHAR)BitCount - 64;
|
|
return Reciprocal;
|
|
}
|
|
|
|
INIT_FUNCTION
|
|
VOID
|
|
NTAPI
|
|
KiInitSpinLocks(IN PKPRCB Prcb,
|
|
IN CCHAR Number)
|
|
{
|
|
ULONG i;
|
|
|
|
/* Initialize Dispatcher Fields */
|
|
Prcb->QueueIndex = 1;
|
|
Prcb->ReadySummary = 0;
|
|
Prcb->DeferredReadyListHead.Next = NULL;
|
|
for (i = 0; i < MAXIMUM_PRIORITY; i++)
|
|
{
|
|
/* Initialize the ready list */
|
|
InitializeListHead(&Prcb->DispatcherReadyListHead[i]);
|
|
}
|
|
|
|
/* Initialize DPC Fields */
|
|
InitializeListHead(&Prcb->DpcData[DPC_NORMAL].DpcListHead);
|
|
KeInitializeSpinLock(&Prcb->DpcData[DPC_NORMAL].DpcLock);
|
|
Prcb->DpcData[DPC_NORMAL].DpcQueueDepth = 0;
|
|
Prcb->DpcData[DPC_NORMAL].DpcCount = 0;
|
|
Prcb->DpcRoutineActive = FALSE;
|
|
Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
|
|
Prcb->MinimumDpcRate = KiMinimumDpcRate;
|
|
Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
|
|
KeInitializeDpc(&Prcb->CallDpc, NULL, NULL);
|
|
KeSetTargetProcessorDpc(&Prcb->CallDpc, Number);
|
|
KeSetImportanceDpc(&Prcb->CallDpc, HighImportance);
|
|
|
|
/* Initialize the Wait List Head */
|
|
InitializeListHead(&Prcb->WaitListHead);
|
|
|
|
/* Initialize Queued Spinlocks */
|
|
Prcb->LockQueue[LockQueueDispatcherLock].Next = NULL;
|
|
Prcb->LockQueue[LockQueueDispatcherLock].Lock = &KiDispatcherLock;
|
|
Prcb->LockQueue[LockQueueExpansionLock].Next = NULL;
|
|
Prcb->LockQueue[LockQueueExpansionLock].Lock = NULL;
|
|
Prcb->LockQueue[LockQueuePfnLock].Next = NULL;
|
|
Prcb->LockQueue[LockQueuePfnLock].Lock = &MmPfnLock;
|
|
Prcb->LockQueue[LockQueueSystemSpaceLock].Next = NULL;
|
|
Prcb->LockQueue[LockQueueSystemSpaceLock].Lock = &MmSystemSpaceLock;
|
|
Prcb->LockQueue[LockQueueBcbLock].Next = NULL;
|
|
Prcb->LockQueue[LockQueueBcbLock].Lock = &CcBcbSpinLock;
|
|
Prcb->LockQueue[LockQueueMasterLock].Next = NULL;
|
|
Prcb->LockQueue[LockQueueMasterLock].Lock = &CcMasterSpinLock;
|
|
Prcb->LockQueue[LockQueueVacbLock].Next = NULL;
|
|
Prcb->LockQueue[LockQueueVacbLock].Lock = &CcVacbSpinLock;
|
|
Prcb->LockQueue[LockQueueWorkQueueLock].Next = NULL;
|
|
Prcb->LockQueue[LockQueueWorkQueueLock].Lock = &CcWorkQueueSpinLock;
|
|
Prcb->LockQueue[LockQueueNonPagedPoolLock].Next = NULL;
|
|
Prcb->LockQueue[LockQueueNonPagedPoolLock].Lock = &NonPagedPoolLock;
|
|
Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Next = NULL;
|
|
Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Lock = &MmNonPagedPoolLock;
|
|
Prcb->LockQueue[LockQueueIoCancelLock].Next = NULL;
|
|
Prcb->LockQueue[LockQueueIoCancelLock].Lock = &IopCancelSpinLock;
|
|
Prcb->LockQueue[LockQueueIoVpbLock].Next = NULL;
|
|
Prcb->LockQueue[LockQueueIoVpbLock].Lock = &IopVpbSpinLock;
|
|
Prcb->LockQueue[LockQueueIoDatabaseLock].Next = NULL;
|
|
Prcb->LockQueue[LockQueueIoDatabaseLock].Lock = &IopDatabaseLock;
|
|
Prcb->LockQueue[LockQueueIoCompletionLock].Next = NULL;
|
|
Prcb->LockQueue[LockQueueIoCompletionLock].Lock = &IopCompletionLock;
|
|
Prcb->LockQueue[LockQueueNtfsStructLock].Next = NULL;
|
|
Prcb->LockQueue[LockQueueNtfsStructLock].Lock = &NtfsStructLock;
|
|
Prcb->LockQueue[LockQueueAfdWorkQueueLock].Next = NULL;
|
|
Prcb->LockQueue[LockQueueAfdWorkQueueLock].Lock = &AfdWorkQueueSpinLock;
|
|
Prcb->LockQueue[LockQueueUnusedSpare16].Next = NULL;
|
|
Prcb->LockQueue[LockQueueUnusedSpare16].Lock = NULL;
|
|
|
|
/* Loop timer locks */
|
|
for (i = 0; i < LOCK_QUEUE_TIMER_TABLE_LOCKS; i++)
|
|
{
|
|
/* Initialize the lock and setup the Queued Spinlock */
|
|
KeInitializeSpinLock(&KiTimerTableLock[i]);
|
|
Prcb->LockQueue[LockQueueTimerTableLock + i].Next = NULL;
|
|
Prcb->LockQueue[LockQueueTimerTableLock + i].Lock =
|
|
&KiTimerTableLock[i];
|
|
}
|
|
|
|
/* Initialize the PRCB lock */
|
|
KeInitializeSpinLock(&Prcb->PrcbLock);
|
|
|
|
/* Check if this is the boot CPU */
|
|
if (!Number)
|
|
{
|
|
/* Initialize the lock themselves */
|
|
KeInitializeSpinLock(&KiDispatcherLock);
|
|
KeInitializeSpinLock(&KiReverseStallIpiLock);
|
|
KeInitializeSpinLock(&MmPfnLock);
|
|
KeInitializeSpinLock(&MmSystemSpaceLock);
|
|
KeInitializeSpinLock(&CcBcbSpinLock);
|
|
KeInitializeSpinLock(&CcMasterSpinLock);
|
|
KeInitializeSpinLock(&CcVacbSpinLock);
|
|
KeInitializeSpinLock(&CcWorkQueueSpinLock);
|
|
KeInitializeSpinLock(&IopCancelSpinLock);
|
|
KeInitializeSpinLock(&IopCompletionLock);
|
|
KeInitializeSpinLock(&IopDatabaseLock);
|
|
KeInitializeSpinLock(&IopVpbSpinLock);
|
|
KeInitializeSpinLock(&NonPagedPoolLock);
|
|
KeInitializeSpinLock(&MmNonPagedPoolLock);
|
|
KeInitializeSpinLock(&NtfsStructLock);
|
|
KeInitializeSpinLock(&AfdWorkQueueSpinLock);
|
|
}
|
|
}
|
|
|
|
INIT_FUNCTION
|
|
BOOLEAN
|
|
NTAPI
|
|
KeInitSystem(VOID)
|
|
{
|
|
/* Check if Threaded DPCs are enabled */
|
|
if (KeThreadDpcEnable)
|
|
{
|
|
/* FIXME: TODO */
|
|
DPRINT1("Threaded DPCs not yet supported\n");
|
|
}
|
|
|
|
/* Initialize non-portable parts of the kernel */
|
|
KiInitMachineDependent();
|
|
return TRUE;
|
|
}
|