1111 lines
28 KiB
C
1111 lines
28 KiB
C
/*++
|
||
|
||
Copyright (c) 1990 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
initkr.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the code to initialize the kernel data structures
|
||
and to initialize the idle thread, its process, and the processor control
|
||
block.
|
||
|
||
Author:
|
||
|
||
Bernard Lint 8-Aug-1996
|
||
|
||
Environment:
|
||
|
||
Kernel mode only.
|
||
|
||
Revision History:
|
||
|
||
Based on MIPS version (David N. Cutler (davec) 11-Apr-1990)
|
||
--*/
|
||
|
||
#include "ki.h"
|
||
|
||
|
||
//
|
||
// Put all code for kernel initialization in the INIT section. It will be
|
||
// deallocated by memory management when phase 1 initialization is completed.
|
||
//
|
||
|
||
VOID
|
||
KiInitializeProcessorIds(
|
||
IN PKPRCB Prcb
|
||
);
|
||
|
||
ULONG
|
||
KiGetFeatureBits(
|
||
IN PKPRCB Prcb
|
||
);
|
||
|
||
VOID
|
||
FASTCALL
|
||
KiZeroPage (
|
||
PVOID PageBase
|
||
);
|
||
|
||
#if defined(ALLOC_PRAGMA)
|
||
|
||
#pragma alloc_text(INIT, KiGetFeatureBits)
|
||
#pragma alloc_text(INIT, KiInitializeProcessorIds)
|
||
#pragma alloc_text(INIT, KiInitializeKernel)
|
||
#pragma alloc_text(INIT, KiInitMachineDependent)
|
||
|
||
#endif
|
||
|
||
KE_ZERO_PAGE_ROUTINE KeZeroPage = KiZeroPage;
|
||
KE_ZERO_PAGE_ROUTINE KeZeroPageFromIdleThread = KiZeroPage;
|
||
|
||
//
|
||
// KiTbBroadcastLock - This is the spin lock that prevents the other processors
|
||
// from issuing PTC.G (TB purge broadcast) operations.
|
||
//
|
||
|
||
KSPIN_LOCK KiTbBroadcastLock;
|
||
|
||
//
|
||
// KiMasterRidLock - This is the spin lock that prevents the other processors
|
||
// from updating KiMasterRid.
|
||
//
|
||
|
||
KSPIN_LOCK KiMasterRidLock;
|
||
|
||
//
|
||
// KiCacheFlushLock - This is the spin lock that ensures cache flush is only
|
||
// done on one processor at a time. (SAL cache flush not yet MP safe).
|
||
//
|
||
|
||
KSPIN_LOCK KiCacheFlushLock;
|
||
|
||
//
|
||
// KiUserSharedDataPage - This holds the page number of UserSharedDataPage for
|
||
// MP boot
|
||
//
|
||
|
||
ULONG_PTR KiUserSharedDataPage;
|
||
|
||
//
|
||
// KiKernelPcrPage - This holds the page number of per-processor PCR page for
|
||
// MP boot
|
||
//
|
||
|
||
ULONG_PTR KiKernelPcrPage = 0i64;
|
||
|
||
//
|
||
// VHPT configuation variables
|
||
//
|
||
|
||
IA64_VM_SUMMARY1 KiIA64VmSummary1;
|
||
IA64_VM_SUMMARY2 KiIA64VmSummary2;
|
||
IA64_PTCE_INFO KiIA64PtceInfo;
|
||
ULONG_PTR KiIA64PtaContents;
|
||
ULONG_PTR KiIA64PtaHpwEnabled = 1;
|
||
ULONG_PTR KiIA64VaSign;
|
||
ULONG_PTR KiIA64VaSignedFill;
|
||
ULONG_PTR KiIA64PtaBase;
|
||
ULONG_PTR KiIA64PtaSign;
|
||
ULONG KiIA64ImpVirtualMsb;
|
||
extern ULONG KiMaximumRid;
|
||
|
||
//
|
||
// KiExceptionDeferralMode - This holds the mode for the exception deferral
|
||
// policy
|
||
//
|
||
|
||
ULONG KiExceptionDeferralMode;
|
||
|
||
//
|
||
// Initial DCR value
|
||
//
|
||
|
||
ULONGLONG KiIA64DCR = DCR_INITIAL;
|
||
|
||
//
|
||
// KiVectorLogMask - bitmap for enable/disable the interruption logging
|
||
//
|
||
|
||
LONGLONG KiVectorLogMask;
|
||
|
||
|
||
ULONG
|
||
KiGetFeatureBits(
|
||
PKPRCB Prcb
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function returns the NT Feature Bits supported by the specified
|
||
processor control block.
|
||
|
||
Arguments:
|
||
|
||
Prcb - Supplies a pointer to a processor control block for the specified
|
||
processor.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
Comments:
|
||
|
||
This function is called after the initialization of the IA64 processor
|
||
control block ProcessorFeatureBits field and after HalInitializeProcessor().
|
||
|
||
--*/
|
||
|
||
{
|
||
// WARNING: NT system wide feature bits is a 32-bit type.
|
||
ULONG features = (ULONG) Prcb->ProcessorFeatureBits;
|
||
|
||
//
|
||
// Check for Long Branch instruction support.
|
||
//
|
||
|
||
if ( features & 0x1 ) {
|
||
features |= KF_BRL;
|
||
}
|
||
|
||
return features;
|
||
|
||
} // KiGetFeatureBits()
|
||
|
||
|
||
|
||
VOID
|
||
KiInitializeProcessorIds(
|
||
IN PKPRCB Prcb
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is called early in the initialization of the kernel
|
||
to initialize the processor indentification registers located
|
||
in the processor control block.
|
||
This function is called for each processor and should be called b
|
||
before the HAL is called.
|
||
|
||
Arguments:
|
||
|
||
Prcb - Supplies a pointer to a processor control block for the specified
|
||
processor.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
Comments:
|
||
|
||
This function simply deals with IA64 architected CPUID registers.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONGLONG val;
|
||
|
||
// IA64 architected CPUID3: Version information.
|
||
// BUGBUG - thierry 02/01/00.
|
||
// NT!Ke and NT!Config are expecting non-zeroed processor model and revision.
|
||
// The current A* steppings have these values zeroed.
|
||
// Increment these values by 1, until we are getting B steppings.
|
||
|
||
val = __getReg( CV_IA64_CPUID3 );
|
||
Prcb->ProcessorModel = (ULONG)(((val >> 16) & 0xFF) + 1);
|
||
Prcb->ProcessorRevision = (ULONG)(((val >> 8 ) & 0xFF) + 1);
|
||
Prcb->ProcessorFamily = (ULONG) ((val >> 24) & 0xFF);
|
||
Prcb->ProcessorArchRev = (ULONG) ((val >> 32) & 0xFF);
|
||
|
||
// IA64 architected CPUID0 & CPUID1: Vendor Information.
|
||
|
||
val = __getReg( CV_IA64_CPUID0 );
|
||
strncpy( Prcb->ProcessorVendorString , (PUCHAR)&val, 8 );
|
||
val = __getReg( CV_IA64_CPUID1 );
|
||
strncpy( &Prcb->ProcessorVendorString[8], (PUCHAR)&val, 8 );
|
||
|
||
// IA64 architected CPUID2: Processor Serial Number.
|
||
|
||
Prcb->ProcessorSerialNumber = __getReg( CV_IA64_CPUID2 );
|
||
|
||
// IA64 architected CPUID4: General Features / Capability bits.
|
||
|
||
Prcb->ProcessorFeatureBits = __getReg( CV_IA64_CPUID4 );
|
||
|
||
return;
|
||
|
||
} // KiInitializeProcessorIds()
|
||
|
||
#if defined(_MERCED_A0_)
|
||
VOID
|
||
KiProcessorWorkAround(
|
||
);
|
||
|
||
VOID
|
||
KiSwitchToLogVector(
|
||
VOID
|
||
);
|
||
|
||
extern BOOLEAN KiIpiTbShootdown;
|
||
|
||
ULONGLONG KiConfigFlag;
|
||
|
||
//
|
||
// Process the boot loader configuration flags.
|
||
//
|
||
|
||
VOID
|
||
KiProcessorConfigFlag(
|
||
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
||
)
|
||
{
|
||
PUCHAR ConfigFlag;
|
||
ULONG ConfigFlagValue=0;
|
||
ULONGLONG Cpuid3;
|
||
ULONGLONG ItaniumId;
|
||
|
||
Cpuid3 = __getReg( CV_IA64_CPUID3 );
|
||
|
||
ConfigFlag = strstr(LoaderBlock->LoadOptions, "CONFIGFLAG");
|
||
if (ConfigFlag != NULL) {
|
||
|
||
ConfigFlag = strstr(ConfigFlag, "=");
|
||
if (ConfigFlag != NULL) {
|
||
ConfigFlagValue = atol(ConfigFlag+1);
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// Set the recommened ConfigFlagValue for Itanium, B1/B2
|
||
// if there is no CONFIGFLAG keyword
|
||
//
|
||
|
||
ItaniumId = 0xFFFFFF0000I64 & Cpuid3;
|
||
|
||
if (ItaniumId == 0x0007000000) {
|
||
|
||
switch (Cpuid3) {
|
||
case 0x0007000004: // Itanium, A stepping
|
||
case 0x0007000104: // Itanium, B0 stepping
|
||
ConfigFlagValue = 0;
|
||
break;
|
||
case 0x0007000204: // Itanium, B1 stepping
|
||
case 0x0007000304: // Itanium, B2 stepping
|
||
ConfigFlagValue = 1054;
|
||
break;
|
||
case 0x0007000404: // Itanium, B3 stepping
|
||
case 0x0007000504: // Itanium, B4 stepping
|
||
ConfigFlagValue = 19070;
|
||
break;
|
||
case 0x0007000604: // Itanium, C0 or later stepping
|
||
ConfigFlagValue = 11135;
|
||
break;
|
||
default:
|
||
ConfigFlagValue = 43903;
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// Save config flag value.
|
||
//
|
||
|
||
KiConfigFlag = ConfigFlagValue;
|
||
|
||
//
|
||
// do the processor MSR workarounds
|
||
//
|
||
|
||
KiProcessorWorkAround(ConfigFlagValue);
|
||
|
||
//
|
||
// For Conditional Interrupt Logging
|
||
// switch to shadow IVT depending on ConfigFlag
|
||
//
|
||
|
||
if (ConfigFlagValue & (1 << DISABLE_INTERRUPTION_LOG)) {
|
||
KiVectorLogMask = 0;
|
||
} else {
|
||
|
||
//
|
||
// By default disable logging of:
|
||
// KiAltInstTlbVectorBit 3
|
||
// KiAltDataTlbVectorBit 4
|
||
//
|
||
|
||
KiVectorLogMask = 0xffffffffffffffffI64;
|
||
KiSwitchToLogVector();
|
||
}
|
||
|
||
//
|
||
// check to see if the VHPT walker should be disabled
|
||
//
|
||
|
||
if (ConfigFlagValue & (1 << DISABLE_VHPT_WALKER)) {
|
||
KiIA64PtaHpwEnabled = 0;
|
||
}
|
||
|
||
}
|
||
#endif
|
||
|
||
|
||
VOID
|
||
KiInitializeKernel (
|
||
IN PKPROCESS Process,
|
||
IN PKTHREAD Thread,
|
||
IN PVOID IdleStack,
|
||
IN PKPRCB Prcb,
|
||
IN CCHAR Number,
|
||
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function gains control after the system has been bootstrapped and
|
||
before the system has been initialized. Its function is to initialize
|
||
the kernel data structures, initialize the idle thread and process objects,
|
||
initialize the processor control block, call the executive initialization
|
||
routine, and then return to the system startup routine. This routine is
|
||
also called to initialize the processor specific structures when a new
|
||
processor is brought on line.
|
||
|
||
Arguments:
|
||
|
||
Process - Supplies a pointer to a control object of type process for
|
||
the specified processor.
|
||
|
||
Thread - Supplies a pointer to a dispatcher object of type thread for
|
||
the specified processor.
|
||
|
||
IdleStack - Supplies a pointer the base of the real kernel stack for
|
||
idle thread on the specified processor.
|
||
|
||
Prcb - Supplies a pointer to a processor control block for the specified
|
||
processor.
|
||
|
||
Number - Supplies the number of the processor that is being
|
||
initialized.
|
||
|
||
LoaderBlock - Supplies a pointer to the loader parameter block.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
LONG Index;
|
||
KIRQL OldIrql;
|
||
ULONG featureBits;
|
||
ULONG_PTR DirectoryTableBase[2];
|
||
|
||
#if defined(_MERCED_A0_)
|
||
KiProcessorConfigFlag(LoaderBlock);
|
||
#endif
|
||
|
||
//
|
||
// Perform Processor Identification Registers update.
|
||
//
|
||
// This has to be done before HalInitializeProcessor to offer
|
||
// a possibility for the HAL to look at them.
|
||
//
|
||
|
||
KiInitializeProcessorIds( Prcb );
|
||
|
||
//
|
||
// Perform platform dependent processor initialization.
|
||
//
|
||
|
||
HalInitializeProcessor(Number, LoaderBlock);
|
||
|
||
//
|
||
// Save the address of the loader parameter block.
|
||
//
|
||
|
||
KeLoaderBlock = LoaderBlock;
|
||
|
||
//
|
||
// Initialize the processor block.
|
||
//
|
||
|
||
Prcb->MinorVersion = PRCB_MINOR_VERSION;
|
||
Prcb->MajorVersion = PRCB_MAJOR_VERSION;
|
||
Prcb->BuildType = 0;
|
||
|
||
#if DBG
|
||
|
||
Prcb->BuildType |= PRCB_BUILD_DEBUG;
|
||
|
||
#endif
|
||
|
||
#if defined(NT_UP)
|
||
|
||
Prcb->BuildType |= PRCB_BUILD_UNIPROCESSOR;
|
||
|
||
#endif
|
||
|
||
Prcb->CurrentThread = Thread;
|
||
Prcb->NextThread = (PKTHREAD)NULL;
|
||
Prcb->IdleThread = Thread;
|
||
Prcb->Number = Number;
|
||
Prcb->SetMember = AFFINITY_MASK(Number);
|
||
Prcb->PcrPage = LoaderBlock->u.Ia64.PcrPage;
|
||
|
||
//
|
||
// initialize the per processor lock queue entry for implemented locks.
|
||
//
|
||
|
||
KiInitQueuedSpinLocks(Prcb, Number);
|
||
|
||
//
|
||
// Initialize the interprocessor communication packet.
|
||
//
|
||
|
||
#if !defined(NT_UP)
|
||
|
||
Prcb->TargetSet = 0;
|
||
Prcb->WorkerRoutine = NULL;
|
||
Prcb->RequestSummary = 0;
|
||
Prcb->IpiFrozen = 0;
|
||
|
||
#if NT_INST
|
||
|
||
Prcb->IpiCounts = &KiIpiCounts[Number];
|
||
|
||
#endif
|
||
|
||
#endif
|
||
|
||
Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
|
||
Prcb->MinimumDpcRate = KiMinimumDpcRate;
|
||
Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
|
||
|
||
//
|
||
// Initialize DPC listhead and lock.
|
||
//
|
||
|
||
InitializeListHead(&Prcb->DpcListHead);
|
||
KeInitializeSpinLock(&Prcb->DpcLock);
|
||
|
||
//
|
||
// Set address of processor block.
|
||
//
|
||
|
||
KiProcessorBlock[Number] = Prcb;
|
||
|
||
//
|
||
// Initialize processors PowerState
|
||
//
|
||
|
||
PoInitializePrcb (Prcb);
|
||
|
||
//
|
||
// Set global processor architecture, level and revision. The
|
||
// latter two are the least common denominator on an MP system.
|
||
//
|
||
|
||
KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_IA64;
|
||
|
||
if ((KeProcessorLevel == 0) ||
|
||
(KeProcessorLevel > (USHORT) Prcb->ProcessorModel)) {
|
||
KeProcessorLevel = (USHORT) Prcb->ProcessorModel;
|
||
}
|
||
|
||
if ((KeProcessorRevision == 0) ||
|
||
(KeProcessorRevision > (USHORT) Prcb->ProcessorRevision)) {
|
||
KeProcessorRevision = (USHORT) Prcb->ProcessorRevision;
|
||
}
|
||
|
||
//
|
||
// Initialize the address of the bus error routines / machine check
|
||
//
|
||
// **** TBD
|
||
|
||
//
|
||
// Initialize the idle thread initial kernel stack and limit address value.
|
||
//
|
||
|
||
PCR->InitialStack = (ULONGLONG)IdleStack;
|
||
PCR->InitialBStore = (ULONGLONG)IdleStack;
|
||
PCR->StackLimit = (ULONGLONG)((ULONG_PTR)IdleStack - KERNEL_STACK_SIZE);
|
||
PCR->BStoreLimit = (ULONGLONG)((ULONG_PTR)IdleStack + KERNEL_BSTORE_SIZE);
|
||
|
||
//
|
||
// Initialize pointers to the SAL event resource structures.
|
||
//
|
||
|
||
PCR->OsMcaResourcePtr = (PSAL_EVENT_RESOURCES) &PCR->OsMcaResource;
|
||
PCR->OsInitResourcePtr = (PSAL_EVENT_RESOURCES) &PCR->OsInitResource;
|
||
|
||
//
|
||
// Initialize all interrupt vectors to transfer control to the unexpected
|
||
// interrupt routine.
|
||
//
|
||
// N.B. This interrupt object is never actually "connected" to an interrupt
|
||
// vector via KeConnectInterrupt. It is initialized and then connected
|
||
// by simply storing the address of the dispatch code in the interrupt
|
||
// vector.
|
||
//
|
||
|
||
if (Number == 0) {
|
||
|
||
//
|
||
// Set default node. Used in non-multinode systems and in
|
||
// multinode systems until the node topology is available.
|
||
//
|
||
|
||
extern KNODE KiNode0;
|
||
|
||
KeNodeBlock[0] = &KiNode0;
|
||
|
||
#if defined(KE_MULTINODE)
|
||
|
||
for (Index = 1; Index < MAXIMUM_CCNUMA_NODES; Index++) {
|
||
|
||
extern KNODE KiNodeInit[];
|
||
|
||
//
|
||
// Set temporary node.
|
||
//
|
||
|
||
KeNodeBlock[Index] = &KiNodeInit[Index];
|
||
}
|
||
|
||
#endif
|
||
|
||
Prcb->ParentNode = KeNodeBlock[0];
|
||
KeNodeBlock[0]->ProcessorMask = Prcb->SetMember;
|
||
|
||
//
|
||
// Initialize system wide FeatureBits with BSP processor feature bits.
|
||
//
|
||
|
||
KeFeatureBits = KiGetFeatureBits( Prcb ) ;
|
||
|
||
//
|
||
// Initialize the Tb Broadcast spinlock.
|
||
//
|
||
|
||
KeInitializeSpinLock(&KiTbBroadcastLock);
|
||
|
||
//
|
||
// Initialize the Master Rid spinlock.
|
||
//
|
||
|
||
KeInitializeSpinLock(&KiMasterRidLock);
|
||
|
||
//
|
||
// Initialize the cache flush spinlock.
|
||
//
|
||
|
||
KeInitializeSpinLock(&KiCacheFlushLock);
|
||
|
||
//
|
||
// Initial the address of the interrupt dispatch routine.
|
||
//
|
||
|
||
KxUnexpectedInterrupt.DispatchAddress = KiUnexpectedInterrupt;
|
||
|
||
//
|
||
// Copy the interrupt dispatch function descriptor into the interrupt
|
||
// object.
|
||
//
|
||
|
||
for (Index = 0; Index < DISPATCH_LENGTH; Index += 1) {
|
||
KxUnexpectedInterrupt.DispatchCode[Index] =
|
||
*(((PULONG)(KxUnexpectedInterrupt.DispatchAddress))+Index);
|
||
}
|
||
|
||
//
|
||
// Set the default DMA I/O coherency attributes. IA64
|
||
// architecture dictates that the D-Cache is fully coherent.
|
||
//
|
||
|
||
KiDmaIoCoherency = DMA_READ_DCACHE_INVALIDATE | DMA_WRITE_DCACHE_SNOOP;
|
||
|
||
//
|
||
// Set KiSharedUserData for MP boot
|
||
//
|
||
|
||
KiUserSharedDataPage = LoaderBlock->u.Ia64.PcrPage2;
|
||
|
||
//
|
||
// Get implementatoin specific VM info
|
||
//
|
||
|
||
KiIA64VmSummary1 = LoaderBlock->u.Ia64.ProcessorConfigInfo.VmSummaryInfo1;
|
||
KiIA64VmSummary2 = LoaderBlock->u.Ia64.ProcessorConfigInfo.VmSummaryInfo2;
|
||
KiIA64PtceInfo = LoaderBlock->u.Ia64.ProcessorConfigInfo.PtceInfo;
|
||
KiMaximumRid = ((ULONG)1 << KiIA64VmSummary2.RidSize) - 1;
|
||
|
||
//
|
||
// Initialize the VHPT variables
|
||
//
|
||
|
||
KiIA64ImpVirtualMsb = (ULONG)KiIA64VmSummary2.ImplVaMsb;
|
||
KiIA64VaSign = (ULONGLONG)1 << KiIA64ImpVirtualMsb;
|
||
KiIA64PtaSign = KiIA64VaSign >> (PAGE_SHIFT - PTE_SHIFT);
|
||
KiIA64VaSignedFill =
|
||
(ULONGLONG)((LONGLONG)VRN_MASK >> (60-KiIA64ImpVirtualMsb)) & ~VRN_MASK;
|
||
KiIA64PtaBase =
|
||
(ULONGLONG)((LONGLONG)(VRN_MASK|KiIA64VaSignedFill)
|
||
>> (PAGE_SHIFT - PTE_SHIFT)) & ~VRN_MASK;
|
||
|
||
KiIA64PtaContents =
|
||
KiIA64PtaBase |
|
||
((KiIA64ImpVirtualMsb - PAGE_SHIFT + PTE_SHIFT + 1) << PS_SHIFT) |
|
||
KiIA64PtaHpwEnabled;
|
||
|
||
//
|
||
// enable the VHPT
|
||
//
|
||
|
||
__setReg(CV_IA64_ApPTA, KiIA64PtaContents);
|
||
__isrlz();
|
||
|
||
//
|
||
// Set up the NT page base addresses
|
||
//
|
||
|
||
PCR->PteUbase = UADDRESS_BASE | KiIA64PtaBase;
|
||
PCR->PteKbase = KADDRESS_BASE | KiIA64PtaBase;
|
||
PCR->PteSbase = SADDRESS_BASE | KiIA64PtaBase;
|
||
PCR->PdeUbase = PCR->PteUbase | (PCR->PteUbase >> (PTI_SHIFT-PTE_SHIFT));
|
||
PCR->PdeKbase = PCR->PteKbase | (PCR->PteKbase >> (PTI_SHIFT-PTE_SHIFT));
|
||
PCR->PdeSbase = PCR->PteSbase | (PCR->PteSbase >> (PTI_SHIFT-PTE_SHIFT));
|
||
PCR->PdeUtbase = PCR->PteUbase | (PCR->PdeUbase >> (PTI_SHIFT-PTE_SHIFT));
|
||
PCR->PdeKtbase = PCR->PteKbase | (PCR->PdeKbase >> (PTI_SHIFT-PTE_SHIFT));
|
||
PCR->PdeStbase = PCR->PteSbase | (PCR->PdeSbase >> (PTI_SHIFT-PTE_SHIFT));
|
||
|
||
}
|
||
else {
|
||
|
||
//
|
||
// Mask off feature bits that are not supported on all processors.
|
||
//
|
||
|
||
KeFeatureBits &= KiGetFeatureBits( Prcb );
|
||
|
||
}
|
||
|
||
//
|
||
// Point to UnexpectedInterrupt function pointer
|
||
//
|
||
|
||
for (Index = 0; Index < MAXIMUM_VECTOR; Index += 1) {
|
||
PCR->InterruptRoutine[Index] =
|
||
(PKINTERRUPT_ROUTINE)(&KxUnexpectedInterrupt.DispatchCode);
|
||
}
|
||
|
||
//
|
||
// Initialize the profile count and interval.
|
||
//
|
||
|
||
PCR->ProfileCount = 0;
|
||
PCR->ProfileInterval = 0x200000;
|
||
|
||
//
|
||
// Initialize the passive release, APC, and DPC interrupt vectors.
|
||
//
|
||
|
||
PCR->InterruptRoutine[0] = KiPassiveRelease;
|
||
PCR->InterruptRoutine[APC_VECTOR] = KiApcInterrupt;
|
||
PCR->InterruptRoutine[DISPATCH_VECTOR] = KiDispatchInterrupt;
|
||
|
||
//
|
||
// N.B. Reserve levels, not vectors
|
||
//
|
||
|
||
PCR->ReservedVectors = (1 << PASSIVE_LEVEL) | (1 << APC_LEVEL) | (1 << DISPATCH_LEVEL);
|
||
|
||
//
|
||
// Initialize the set member for the current processor, set IRQL to
|
||
// APC_LEVEL, and set the processor number.
|
||
//
|
||
|
||
KeLowerIrql(APC_LEVEL);
|
||
PCR->SetMember = AFFINITY_MASK(Number);
|
||
PCR->NotMember = ~PCR->SetMember;
|
||
PCR->Number = Number;
|
||
|
||
//
|
||
// Set the initial stall execution scale factor. This value will be
|
||
// recomputed later by the HAL.
|
||
//
|
||
|
||
PCR->StallScaleFactor = 50;
|
||
|
||
//
|
||
// Set address of process object in thread object.
|
||
//
|
||
|
||
Thread->ApcState.Process = Process;
|
||
PCR->Pcb = (PVOID)Process;
|
||
|
||
//
|
||
// Initialize the idle process region id. Session ids are initialized
|
||
// in memory management.
|
||
//
|
||
|
||
Process->ProcessRegion.RegionId = START_PROCESS_RID;
|
||
Process->ProcessRegion.SequenceNumber = START_SEQUENCE;
|
||
|
||
//
|
||
// Set the appropriate member in the active processors set.
|
||
//
|
||
|
||
KeActiveProcessors |= AFFINITY_MASK(Number);
|
||
|
||
//
|
||
// Set the number of processors based on the maximum of the current
|
||
// number of processors and the current processor number.
|
||
//
|
||
|
||
if ((Number + 1) > KeNumberProcessors) {
|
||
KeNumberProcessors = (CCHAR)(Number + 1);
|
||
}
|
||
|
||
//
|
||
// If the initial processor is being initialized, then initialize the
|
||
// per system data structures.
|
||
//
|
||
|
||
if (Number == 0) {
|
||
|
||
Prcb->RestartBlock = NULL;
|
||
|
||
//
|
||
// Initialize the kernel debugger.
|
||
//
|
||
|
||
if (KdInitSystem(0, LoaderBlock) == FALSE) {
|
||
KeBugCheck(PHASE0_INITIALIZATION_FAILED);
|
||
}
|
||
|
||
//
|
||
// Initialize processor block array.
|
||
//
|
||
|
||
for (Index = 1; Index < MAXIMUM_PROCESSORS; Index += 1) {
|
||
KiProcessorBlock[Index] = (PKPRCB)NULL;
|
||
}
|
||
|
||
//
|
||
// Perform architecture independent initialization.
|
||
//
|
||
|
||
KiInitSystem();
|
||
|
||
//
|
||
// Initialize idle thread process object and then set:
|
||
//
|
||
// 1. all the quantum values to the maximum possible.
|
||
// 2. the process in the balance set.
|
||
// 3. the active processor mask to the specified processor.
|
||
//
|
||
|
||
DirectoryTableBase[0] = 0;
|
||
DirectoryTableBase[1] = 0;
|
||
|
||
KeInitializeProcess(Process,
|
||
(KPRIORITY)0,
|
||
(KAFFINITY)(-1),
|
||
&DirectoryTableBase[0],
|
||
FALSE);
|
||
|
||
Process->ThreadQuantum = MAXCHAR;
|
||
|
||
}
|
||
|
||
// Update processor features.
|
||
// This assumes an iVE exists or other ability to emulate the ia32
|
||
// instruction set at the ability of the iVE on Merced (Itanium).
|
||
//
|
||
|
||
SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = TRUE;
|
||
SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
|
||
SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
|
||
SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
|
||
|
||
|
||
//
|
||
//
|
||
// Initialize idle thread object and then set:
|
||
//
|
||
// 1. the initial kernel stack to the specified idle stack.
|
||
// 2. the next processor number to the specified processor.
|
||
// 3. the thread priority to the highest possible value.
|
||
// 4. the state of the thread to running.
|
||
// 5. the thread affinity to the specified processor.
|
||
// 6. the specified processor member in the process active processors
|
||
// set.
|
||
//
|
||
|
||
KeInitializeThread(Thread, (PVOID)((ULONG_PTR)IdleStack - PAGE_SIZE),
|
||
(PKSYSTEM_ROUTINE)KeBugCheck,
|
||
(PKSTART_ROUTINE)NULL,
|
||
(PVOID)NULL, (PCONTEXT)NULL, (PVOID)NULL, Process);
|
||
|
||
Thread->InitialStack = IdleStack;
|
||
Thread->InitialBStore = IdleStack;
|
||
Thread->StackBase = IdleStack;
|
||
Thread->StackLimit = (PVOID)((ULONG_PTR)IdleStack - KERNEL_STACK_SIZE);
|
||
Thread->BStoreLimit = (PVOID)((ULONG_PTR)IdleStack + KERNEL_BSTORE_SIZE);
|
||
Thread->NextProcessor = Number;
|
||
Thread->Priority = HIGH_PRIORITY;
|
||
Thread->State = Running;
|
||
Thread->Affinity = AFFINITY_MASK(Number);
|
||
Thread->WaitIrql = DISPATCH_LEVEL;
|
||
|
||
//
|
||
// If the current processor is 0, then set the appropriate bit in the
|
||
// active summary of the idle process.
|
||
//
|
||
|
||
if (Number == 0) {
|
||
Process->ActiveProcessors |= AFFINITY_MASK(Number);
|
||
}
|
||
|
||
//
|
||
// Execute the executive initialization.
|
||
//
|
||
|
||
try {
|
||
ExpInitializeExecutive(Number, LoaderBlock);
|
||
|
||
} except (EXCEPTION_EXECUTE_HANDLER) {
|
||
KeBugCheck (PHASE0_EXCEPTION);
|
||
}
|
||
|
||
#if 0
|
||
if (Number == 0) {
|
||
RUNTIME_FUNCTION LocalEntry;
|
||
PRUNTIME_FUNCTION FunctionTable, FunctionEntry = NULL;
|
||
ULONGLONG ControlPc;
|
||
ULONG SizeOfExceptionTable;
|
||
ULONG Size;
|
||
LONG High;
|
||
LONG Middle;
|
||
LONG Low;
|
||
extern VOID KiNormalSystemCall(VOID);
|
||
|
||
FunctionTable = (PRUNTIME_FUNCTION)RtlImageDirectoryEntryToData(
|
||
(PVOID) PsNtosImageBase,
|
||
TRUE,
|
||
IMAGE_DIRECTORY_ENTRY_EXCEPTION,
|
||
&SizeOfExceptionTable);
|
||
|
||
if (FunctionTable != NULL) {
|
||
|
||
Low = 0;
|
||
High = (SizeOfExceptionTable / sizeof(RUNTIME_FUNCTION)) - 1;
|
||
ControlPc = ((PPLABEL_DESCRIPTOR)KiNormalSystemCall)->EntryPoint - (ULONG_PTR)PsNtosImageBase;
|
||
|
||
while (High >= Low) {
|
||
|
||
Middle = (Low + High) >> 1;
|
||
FunctionEntry = &FunctionTable[Middle];
|
||
|
||
if (ControlPc < FunctionEntry->BeginAddress) {
|
||
High = Middle - 1;
|
||
} else if (ControlPc >= FunctionEntry->EndAddress) {
|
||
Low = Middle + 1;
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
LocalEntry = *FunctionEntry;
|
||
ControlPc = MM_EPC_VA - ((PPLABEL_DESCRIPTOR)KiNormalSystemCall)->EntryPoint;
|
||
LocalEntry.BeginAddress += (ULONG)ControlPc;
|
||
LocalEntry.EndAddress += (ULONG)ControlPc;
|
||
Size = SizeOfExceptionTable - (ULONG)((ULONG_PTR)FunctionEntry - (ULONG_PTR)FunctionTable) - sizeof(RUNTIME_FUNCTION);
|
||
|
||
RtlMoveMemory((PVOID)FunctionEntry, (PVOID)(FunctionEntry+1), Size);
|
||
FunctionEntry = (PRUNTIME_FUNCTION)((ULONG_PTR)FunctionTable + SizeOfExceptionTable - sizeof(RUNTIME_FUNCTION));
|
||
*FunctionEntry = LocalEntry;
|
||
}
|
||
#endif // 0
|
||
|
||
//
|
||
// check for the exception deferral mode
|
||
//
|
||
|
||
if (KiExceptionDeferralMode != 0) {
|
||
KiIA64DCR = 0x0000000000007e05;
|
||
}
|
||
|
||
//
|
||
// initialize the DCR deferral bits
|
||
//
|
||
|
||
__setReg(CV_IA64_ApDCR, KiIA64DCR);
|
||
|
||
//
|
||
// If the initial processor is being initialized, then compute the
|
||
// timer table reciprocal value and reset the PRCB values for the
|
||
// controllable DPC behavior in order to reflect any registry
|
||
// overrides.
|
||
//
|
||
|
||
if (Number == 0) {
|
||
KiTimeIncrementReciprocal = KiComputeReciprocal((LONG)KeMaximumIncrement,
|
||
&KiTimeIncrementShiftCount);
|
||
|
||
Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
|
||
Prcb->MinimumDpcRate = KiMinimumDpcRate;
|
||
Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
|
||
}
|
||
|
||
//
|
||
// Raise IRQL to dispatch level and set the priority of the idle thread
|
||
// to zero. This will have the effect of immediately causing the phase
|
||
// one initialization thread to get scheduled for execution. The idle
|
||
// thread priority is then set to the lowest realtime priority. This is
|
||
// necessary so that mutexes aquired at DPC level do not cause the active
|
||
// matrix to get corrupted.
|
||
//
|
||
|
||
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
||
KeSetPriorityThread(Thread, (KPRIORITY)0);
|
||
Thread->Priority = LOW_REALTIME_PRIORITY;
|
||
|
||
//
|
||
// Raise IRQL to the highest level.
|
||
//
|
||
|
||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||
|
||
#if !defined(NT_UP)
|
||
|
||
//
|
||
// Indicate boot complete on secondary processor
|
||
//
|
||
|
||
LoaderBlock->Prcb = 0;
|
||
|
||
//
|
||
// If the current processor is not 0, then set the appropriate bit in
|
||
// idle summary.
|
||
//
|
||
|
||
if (Number != 0) {
|
||
KiIdleSummary |= AFFINITY_MASK(Number);
|
||
}
|
||
|
||
#endif
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
KiInitMachineDependent (
|
||
VOID
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function performs machine-specific initialization by querying the HAL.
|
||
|
||
N.B. This function is only called during phase1 initialization.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
A value of TRUE is returned if initialization is successful. Otherwise,
|
||
a value of FALSE is returned.
|
||
|
||
--*/
|
||
|
||
{
|
||
HAL_PLATFORM_INFORMATION PlatformInfo;
|
||
HAL_PROCESSOR_SPEED_INFORMATION ProcessorSpeedInfo;
|
||
NTSTATUS Status;
|
||
BOOLEAN UseFrameBufferCaching;
|
||
ULONG Size;
|
||
|
||
//
|
||
// check to see if we should switch to PTC.G-based TB shootdown
|
||
//
|
||
|
||
Status = HalQuerySystemInformation(HalPlatformInformation,
|
||
sizeof(PlatformInfo),
|
||
&PlatformInfo,
|
||
&Size);
|
||
if (NT_SUCCESS(Status) &&
|
||
(PlatformInfo.PlatformFlags & HAL_PLATFORM_DISABLE_PTCG)) {
|
||
//
|
||
// Will continue not to use PTC.G
|
||
//
|
||
}
|
||
else {
|
||
//
|
||
// Use PTC.G if processor support is there.
|
||
//
|
||
|
||
if (KiConfigFlag & (1 << ENABLE_TB_BROADCAST)) {
|
||
KiIpiTbShootdown = FALSE;
|
||
}
|
||
}
|
||
|
||
//
|
||
// If the HAL indicates write combining is not supported, drop it.
|
||
//
|
||
|
||
Status = HalQuerySystemInformation(HalFrameBufferCachingInformation,
|
||
sizeof(UseFrameBufferCaching),
|
||
&UseFrameBufferCaching,
|
||
&Size);
|
||
|
||
if (NT_SUCCESS(Status) && (UseFrameBufferCaching == FALSE)) {
|
||
|
||
//
|
||
// Hal says don't use.
|
||
//
|
||
|
||
NOTHING;
|
||
}
|
||
else {
|
||
MmEnablePAT ();
|
||
}
|
||
|
||
//
|
||
// Ask HAL for Processor Speed
|
||
//
|
||
|
||
Status = HalQuerySystemInformation(HalProcessorSpeedInformation,
|
||
sizeof(ProcessorSpeedInfo),
|
||
&ProcessorSpeedInfo,
|
||
&Size);
|
||
if (NT_SUCCESS(Status)) {
|
||
PKPRCB Prcb;
|
||
ULONG i;
|
||
|
||
//
|
||
// Put the Processor Speed into the Prcb structure so others
|
||
// can reference it later.
|
||
//
|
||
for (i = 0; i < (ULONG)KeNumberProcessors; i++ ) {
|
||
Prcb = KiProcessorBlock[i];
|
||
Prcb->MHz = (USHORT)ProcessorSpeedInfo.ProcessorSpeed;
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|