windows-nt/Source/XPSP1/NT/base/ntos/ke/ia64/initkr.c
2020-09-26 16:20:57 +08:00

1111 lines
28 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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;
}