windows-nt/Source/XPSP1/NT/base/hals/halia64/ia64/i64krnl.c
2020-09-26 16:20:57 +08:00

1485 lines
29 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) 1995 Intel Corporation
Module Name:
i64krnl.c
Abstract:
This module implements the kernel support routines for the HAL DLL.
Author:
Bernard Lint
M. Jayakumar (Muthurajan.Jayakumar@intel.com)
14-Apr-1995
Environment:
Kernel mode
Revision History:
--*/
#include "halp.h"
#include "i64fw.h"
#include "check.h"
#include "osmca.h"
#include "iosapic.h"
#include "string.h"
#include "stdlib.h"
#include "stdio.h"
#define GreaterThan4GB 0x100000000
VOID
HalpInitReservedPages(
VOID
);
VOID
HalpRegisterKdSupportFunctions(
IN PLOADER_PARAMETER_BLOCK LoaderBlock
);
extern ADDRESS_USAGE HalpDefaultPcIoSpace;
extern ULONGLONG HalpITCFrequency;
extern ULONGLONG HalpProcessorFrequency;
extern ULONG HalpOsBootRendezVector;
WCHAR HalHardwareIdString[] = L"acpi";
ULONG HalpBusType;
ULONGLONG PhysicalIOBase;
static short HalpOwnDisplay = TRUE;
PKPROCESSOR_STATE HalpProcessorState;
PULONGLONG InterruptBlock;
extern KEVENT HalpNewAdapter;
ULONG HalPxbTcap;
//
// When Accessing IO SAPIC, HalpIoSapicLock is acquired and released
//
KSPIN_LOCK HalpIoSapicLock;
PHYSICAL_ADDRESS INTERRUPT_BLOCK_ADDRESS = { 0x0FEE00000 };
//
// Thierry - 10/01/2000 - Do NOT check the HALP_FIX_KD_HALIA64_MASK related
// code and data in the tree.
//
// This is to allow us to enable HAL_INFO level or other desired mask.
// The current debugger does not allow this and it should.
//
// #define HALP_FIX_KD_HALIA64_MASK 1
ULONG HalpFixKdHalia64Mask = 0;
VOID
HalpInitializeInterruptBlock (
VOID
)
/*++
Routine Description:
Map Interrupt Block used for IPI. The size of the IPI area is 1MB.
Arguements:
None
Return Value:
None
--*/
{
InterruptBlock = (PULONGLONG) HalpMapPhysicalMemory (
INTERRUPT_BLOCK_ADDRESS,
256,
MmNonCached);
return;
}
VOID
HalpCalibrateTB (
)
/*++
Routine Description:
This function calibrates the time base by determining the frequency
that the ITC is running at to determine the interval value for a
100 ns time increment (used by clock and profile).
Arguments:
None.
Return Value:
None.
*/
{
return;
}
VOID
HalpFlushTLB (
VOID
)
{
return;
}
BOOLEAN
HalAllProcessorsStarted (
VOID
)
/**++
Routine Description:
This function returns TRUE if all the processors in the system started
successfully.
Arguments:
None.
Return Value:
Returns TRUE.
--**/
{
return TRUE;
}
VOID
HalpIpiInterruptHandler(
IN PKINTERRUPT_ROUTINE Interrupt,
IN PKTRAP_FRAME TrapFrame
)
/*++
Routine Description:
This routine is entered as the result of an interrupt generated by inter
processor communication.
Arguments:
Interrupt - Interrupt object address
TrapFrame - Trap frame address
Return Value:
None.
--*/
{
KeIpiInterrupt(TrapFrame);
return;
}
VOID
HalpSendIPI(
IN USHORT ProcessorID,
IN ULONGLONG Data
)
/*++
Routine Description:
This function sends IPI to the processor specified.
Arguements:
ProcessorID - Supplies the ID of processor to IPI.
Data - The formatted Data ready to ship it as IPI.
Return Value:
None.
--*/
{
PULONGLONG Address;
ULONG tmp1;
KIRQL OldIrql;
tmp1 = ProcessorID << IPI_ID_SHIFT;
Address = (PULONGLONG)((UINT_PTR)(InterruptBlock) + tmp1);
*(volatile ULONGLONG *)Address = Data;
return;
}
NTSTATUS
HalpSendCrossPartitionIpi(
IN USHORT ProcessorID,
IN UCHAR HardwareVector
)
/*++
Routine Description:
This function sends a cross partition IPI to the processor
specified. The caller must know that this processor is in another
partition and the hardware vector previously reserved for
receiving cross partition IPIs.
Arguements:
ProcessorID - Supplies the ID of processor to IPI.
HardwareVector - Hardware Vector on remote processor that will
receive the interrupt.
Return Value:
NTSTATUS
--*/
{
ULONGLONG Data;
if (HardwareVector < 16) {
return STATUS_INVALID_PARAMETER;
}
Data = HardwareVector | DELIVER_FIXED;
HalpSendIPI(ProcessorID, Data);
return STATUS_SUCCESS;
}
VOID
HalpOSRendez (
IN USHORT ProcessorID
)
/*++
Routine Description:
This function does IPI to start the next processor.
Arguements:
PhysicalNumber - Supplies the physical number of processor to IPI.
Return Value:
None.
--*/
{
HalpSendIPI ( ProcessorID, HalpOsBootRendezVector);
return;
}
BOOLEAN
HalStartNextProcessor (
IN PLOADER_PARAMETER_BLOCK LoaderBlock,
IN PKPROCESSOR_STATE ProcessorState
)
/*++
Routine Description:
This function is called to start the next processor.
Arguments:
LoaderBlock - Supplies a pointer to the loader parameter block.
ProcessorState - Supplies a pointer to the processor state to be
used to start the processor.
Return Value:
If a processor is successfully started, then a value of TRUE is
returned. Otherwise a value of FALSE is returned. If a value of
TRUE is returned, then the logical processor number is stored
in the processor control block specified by the loader block.
--*/
{
ULONG count;
ULONGLONG EntryPoint;
ULONG ProcNumber = ((PKPRCB)LoaderBlock->Prcb)->Number;
SAL_PAL_RETURN_VALUES SalReturn;
SAL_STATUS salStatus;
NTSTATUS ntStatus;
USHORT TargetProcessorID;
if (HalpAcpiNumProcessors() <= ProcNumber) {
return (FALSE);
}
//
// Boot OS rendezvous entry point
//
EntryPoint = ProcessorState->ContextFrame.StIIP;
salStatus = HalpSalCall(SAL_SET_VECTORS,
2 /* Boot rendz */,
(ULONGLONG)(MmGetPhysicalAddress((PUCHAR)EntryPoint).QuadPart),
0,
0,
0,
0,
0,
&SalReturn);
if (salStatus != 0) {
HalDebugPrint(( HAL_ERROR, "HAL: HalStartNextProcessor - Cannot register OS rendezvous with SAL for processor %d\n",
ProcNumber ));
return (FALSE);
}
//
// For ia64, we will assume that the processor is ready and not started
//
//
// Start the next processor, if Processor ID not self
//
ntStatus = HalpGetApicIdByProcessorNumber((UCHAR)ProcNumber, &TargetProcessorID);
if (!NT_SUCCESS(ntStatus)) {
return FALSE;
}
HalpOSRendez(TargetProcessorID);
count = 0;
while (*((volatile ULONG_PTR *)&LoaderBlock->Prcb) != 0 && (count < RENDEZ_TIME_OUT)) {
KeStallExecutionProcessor (1000); // 1000000
count++;
} // end while (count < RENDEZ_TIMEOUT)
if (LoaderBlock->Prcb != 0) {
return (FALSE);
} else {
return (TRUE);
}
}
VOID
HalRequestIpi (
IN KAFFINITY Mask
)
/*++
Routine Description:
This function does nothing on a uni-processor platform.
Arguments:
Mask - A mask that specifies the target processor(s) to which an
IPI is to be sent.
Return Value:
None.
--*/
{
USHORT LogicalCpu;
USHORT ProcessorID;
//
// Make sure we don't try and IPI processors that we don't believe are
// started
//
Mask &= HalpActiveProcessors;
//
// Scan the processor set and request an interprocessor interrupt on
// each of the specified targets.
//
for (LogicalCpu = 0; LogicalCpu < HalpMpInfo.ProcessorCount; LogicalCpu++) {
if ((Mask & (1 << HalpProcessorInfo[LogicalCpu].NtProcessorNumber)) != 0) {
ProcessorID = HalpProcessorInfo[LogicalCpu].LocalApicID;
//
// Request interprocessor interrupt on target physicalCpu.
//
HalpSendIPI(ProcessorID, IPI_VECTOR);
}
}
}
VOID
HalProcessorIdle (
VOID
)
/*++
Routine Description:
This function calls the TAL function to halt the processor.
Arguments:
None.
Return Value:
None.
--*/
{
_enable();
}
#if !defined(NO_LEGACY_DRIVERS)
BOOLEAN
HalMakeBeep (
IN ULONG Frequency
)
/*++
Routine Description:
This function calls SSC function SscMakeBeep() to make a beep sound
when the specified frequency has a non-zero value.
Arguments:
Frequency - the frequency of the sound to be made.
Return Value:
None.
--*/
{
if (Frequency > 0) {
SscMakeBeep(Frequency);
}
return TRUE;
}
#endif // NO_LEGACY_DRIVERS
VOID
KeStallExecutionProcessor (
IN ULONG MicroSeconds
)
/**
Routine Description:
This function stalls the processor.
Arguments:
MicroSeconds - Number of microseconds to stall the processor.
Return Value:
None.
**/
{
ULONGLONG CurrentITC;
ULONGLONG LimitITC;
CurrentITC = __getReg(CV_IA64_ApITC);
#ifndef DISABLE_ITC_WORKAROUND
while ((CurrentITC & 0xFFFFFFFF) == 0xFFFFFFFF) {
CurrentITC = __getReg(CV_IA64_ApITC);
}
#endif
LimitITC = CurrentITC + (ULONGLONG) (HalpITCTicksPer100ns * 10 * MicroSeconds);
while (LimitITC > CurrentITC) {
CurrentITC = __getReg(CV_IA64_ApITC);
#ifndef DISABLE_ITC_WORKAROUND
while ((CurrentITC & 0xFFFFFFFF) == 0xFFFFFFFF) {
CurrentITC = __getReg(CV_IA64_ApITC);
}
#endif
}
return;
}
VOID HalpInitLINT(VOID);
VOID
HalInitializeProcessor (
ULONG Number,
PLOADER_PARAMETER_BLOCK LoaderBlock
)
/*++
Routine Description:
This function is called early in the initialization of the kernel
to perform platform dependent initialization for each processor
before the HAL Is fully functional.
N.B. When this routine is called, the PCR is present but is not
fully initialized.
Arguments:
Number - Supplies the number of the processor to initialize.
Return Value:
None.
--*/
{
extern ULONG HalpDefaultInterruptAffinity;
//
// Add this processor to the interrupt affinity mask
//
HalpDefaultInterruptAffinity |= 1<<Number;
//
// Turn off LINT0 LINT1 (disable 8259)
//
// __setReg(CV_IA64_SaLRR0, 0x10000);
// __setReg(CV_IA64_SaLRR1, 0x10000);
//
HalpInitLINT();
__dsrlz();
//
// No need to Initialize the virtual address mapping for IO port space
// since loader/MM do that
//
PhysicalIOBase = LoaderBlock->u.Ia64.DtrInfo[DTR_IO_PORT_INDEX].PhysicalAddress;
PCR->StallScaleFactor = 0;
//
// Save my processor ID in PCR
//
PCR->HalReserved[PROCESSOR_ID_INDEX] = HalpReadLID() >> 16;
//
// This next call has nothing to do with processor init.
// But this is the only function in the HAL that gets
// called before KdInit.
//
HalpRegisterKdSupportFunctions(LoaderBlock);
//
// Update node tables
//
HalpAddNodeNumber(Number);
return;
}
VOID
HalpRegisterInternalInterrupts(
VOID
)
/*++
Routine Description:
This function reserves the known HAL IA64 resources usage and
registers the IDT vectors usage.
Arguements:
None.
Return Value:
None.
--*/
{
ULONG i;
//
// Make sure all vectors 00-2f, c0-ff are reserved
// 00-0E Passive Reserved by Intel
// 0F SAPIC Spurious Interrupt Vector Reserved
// 10-1F APC priority level Reserved
// 20-2F DPC priority level Reserved
// c0-ff clock, ipi, synch, high
// these are reserved in HalpGetSystemInterruptVector()
// Do not report to IoReportHalResourceUsage()
//
for(i=0; i < PRIMARY_VECTOR_BASE; i++) {
if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
HalpIDTUsage[i].Flags = 0;
HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
}
}
//
// Make sure all the interrupts in the SYNCH IRQL range are
// also reserved.
//
for(i= SYNCH_VECTOR; i < (SYNCH_VECTOR+16); i++) {
if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
HalpIDTUsage[i].Flags = 0;
HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
}
}
//
// Make sure all the interrupts in the IPI IRQL range are also
// reserved.
//
for(i= IPI_VECTOR; i < (IPI_VECTOR+16); i++) {
if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
HalpIDTUsage[i].Flags = 0;
HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
}
}
//
// Make sure all the interrupts in the CLOCK IRQL range are also
// reserved.
//
for(i= CLOCK_VECTOR; i < (CLOCK_VECTOR+16); i++) {
if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
HalpIDTUsage[i].Flags = 0;
HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
}
}
//
// Make sure all interrupts in the PROFILE IRQL range also are
// reserved.
//
for(i= PROFILE_VECTOR; i < (PROFILE_VECTOR+16); i++) {
if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
HalpIDTUsage[i].Flags = 0;
HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
}
}
HalpRegisterVector (
0,
SAPIC_SPURIOUS_VECTOR,
SAPIC_SPURIOUS_VECTOR,
SAPIC_SPURIOUS_LEVEL
);
HalpRegisterVector (
0,
(APC_LEVEL << VECTOR_IRQL_SHIFT),
(APC_LEVEL << VECTOR_IRQL_SHIFT),
APC_LEVEL
);
HalpRegisterVector (
0,
(DPC_LEVEL << VECTOR_IRQL_SHIFT),
(DPC_LEVEL << VECTOR_IRQL_SHIFT),
DPC_LEVEL
);
HalpRegisterVector (
0,
MC_RZ_VECTOR,
MC_RZ_VECTOR,
HIGH_LEVEL
);
HalpRegisterVector (
0,
MC_WKUP_VECTOR,
MC_WKUP_VECTOR,
HIGH_LEVEL
);
//
// Note that it is possible that HAL_CMC_PRESENT is not set.
// With the current implementation, we always register the CMC vector.
//
HalpRegisterVector (
0,
CMCI_VECTOR,
CMCI_VECTOR,
CMCI_LEVEL
);
//
// Note that it is possible that HAL_CPE_PRESENT is not set.
// With the current implementation, we always register the CPE vector.
//
HalpRegisterVector (
0,
CPEI_VECTOR,
CPEI_VECTOR,
CPEI_LEVEL
);
HalpRegisterVector (
0,
SYNCH_VECTOR,
SYNCH_VECTOR,
SYNCH_LEVEL
);
HalpRegisterVector (
0,
IPI_VECTOR,
IPI_VECTOR,
IPI_LEVEL
);
HalpRegisterVector (
0,
CLOCK_VECTOR,
CLOCK_VECTOR,
CLOCK_LEVEL
);
HalpRegisterVector (
0,
PROFILE_VECTOR,
PROFILE_VECTOR,
PROFILE_LEVEL
);
HalpRegisterVector (
0,
PERF_VECTOR,
PERF_VECTOR,
PROFILE_LEVEL
);
return;
} // HalpRegisterInternalInterrupts()
VOID
HalpPerfInterrupt (
IN PKINTERRUPT_ROUTINE Interrupt,
IN PKTRAP_FRAME TrapFrame
)
/*++
Routine Description:
Arguements:
Return Parameters:
--*/
{
// Thierry: This interrupt handler could be used to implement instructions
// tracing based on the overflow interrupts generated by PMU events
// like "retired instructions" or "taken branches".
// This would provide very valuable inputs for hardware performance simulators.
//
// XXTF - not implemented yet...
return;
} // HalpPerfInterrupt()
#if defined(HALP_FIX_KD_HALIA64_MASK)
#if DBG
VOID
HalpSetKdHalia64Mask(
ULONG Mask
)
//
// Mask == 0 should return without modifying Kd_HALIA64_Mask.
//
{
NTSTATUS status;
ULONG level, levelMasked;
int shift;
if ( Mask == (ULONG)-1 ) {
status = DbgSetDebugFilterState( DPFLTR_HALIA64_ID, -1, TRUE );
if ( !NT_SUCCESS(status) ) {
HalDebugPrint(( HAL_ERROR,
"HAL!HalInitSystem: failed to set Kd_HALIA64_Mask to maximum debug spew... 0x%lx\n",
status ));
}
return;
}
level = levelMasked = Mask & HALIA64_DPFLTR_MAXMASK;
shift = 0;
while( level ) {
level &= 0x1;
if ( level ) {
status = DbgSetDebugFilterState( DPFLTR_HALIA64_ID, shift, TRUE );
if ( !NT_SUCCESS(status) ) {
HalDebugPrint(( HAL_ERROR,
"HAL!HalInitSystem: failed to set Kd_HALIA64_Mask to 0x%lx... 0x%lx\n",
shift,
status ));
break;
}
}
shift = shift + 1;
level = levelMasked >> shift;
}
return;
} // HalpSetKdHalia64Mask()
#else // !DBG
#define HalpSetKdHalia64Mask()
#endif // !DBG
#endif // HALP_FIX_KD_HALIA64_MASK
BOOLEAN
HalInitSystem (
IN ULONG Phase,
IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
/*++
Routine Description:
This function initializes the Hardware Architecture Layer (HAL) for an
ia64 system.
Arguments:
None.
Return Value:
A value of TRUE is returned is the initialization was successfully
complete. Otherwise a value of FALSE is returned.
--*/
{
PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
PLIST_ENTRY NextMd;
PKPRCB pPRCB;
volatile KPCR * const pPCR = KeGetPcr();
BOOLEAN Found;
ULONGLONG ITCFrequencyQueried;
ULONGLONG ProcessorFrequencyQueried;
ULONG RTCInti;
KIRQL OldIrql;
NTSTATUS status;
//
// This is for testing RTC clock
//
TIME_FIELDS CurrentTimeFields;
pPRCB = KeGetCurrentPrcb();
if (Phase == 0) {
extern VOID DetectAcpiMP();
BOOLEAN IsMP;
BOOLEAN EnableInterrupts;
//
// Phase 0 initialization only called by P0
//
HalpBusType = LoaderBlock->u.Ia64.MachineType & 0x00ff;
HalpGetParameters (LoaderBlock);
//
// Disable Interrupts before messing around with the APIC etc.
//
EnableInterrupts = HalpDisableInterrupts();
DetectAcpiMP(&IsMP, LoaderBlock);
HalpSetupAcpiPhase0(LoaderBlock);
//
// Verify Prcb version and build flags conform to
// this image
//
if (pPRCB->MajorVersion != PRCB_MAJOR_VERSION) {
KeBugCheckEx (
MISMATCHED_HAL,
1,
pPRCB->MajorVersion,
PRCB_MAJOR_VERSION,
0
);
}
KeInitializeSpinLock(&HalpIoSapicLock);
//
// Fill in handlers for APIs which this hal supports
//
HalQuerySystemInformation = HaliQuerySystemInformation;
HalSetSystemInformation = HaliSetSystemInformation;
HalInitPnpDriver = HaliInitPnpDriver;
//
// HalGetDmaAdapter was commented in previous version
// also. HalInitPowerManagement, HalLocateHiberRanges and
// HalGetInterruptTranslator are added in the latest version
// of Microsoft source code.
//
HalGetDmaAdapter = HaliGetDmaAdapter;
HalHaltSystem = HaliHaltSystem;
HalResetDisplay = HalpBiosDisplayReset;
#if !defined( HAL_SP )
HalGetInterruptTranslator = HalacpiGetInterruptTranslator;
#endif // HAL_SP
#if DBG
//
// Switch from HalDisplayString to DbgPrint.
//
HalpUseDbgPrint++;
#endif // DBG
#if !defined( HAL_SP ) && !(MCA)
HalInitPowerManagement = HaliInitPowerManagement;
HalLocateHiberRanges = HaliLocateHiberRanges;
#endif// HAL_SP and MCA
//
// Register PC style IO space used by hal
//
HalpRegisterAddressUsage (&HalpDefaultPcIoSpace);
HalpInitIntiInfo ();
//
// Initialize CMOS
//
HalpInitializeCmos();
//
// Initialize per processor EOI table
//
HalpInitEOITable();
//
// Initialize the clock for the processor that keeps
// the system time. This uses a stub ISR until Phase 1
//
// Initialize Clock interrupts, profile , APC and DPC interrupts,
HalpInitializeClock();
HalpRegisterInternalInterrupts();
HalpInitializeInterrupts();
//
// Initialize initial processor and NT profiling state
// that should be initialized at Phase 0 and
// do not require to wait for Phase 1.
//
HalpSetInitialProfileState();
//
// Interrupts should be safe now.
//
if (EnableInterrupts) {
HalpEnableInterrupts();
}
//
// Initialize event for serialization of new dma adapter events
//
KeInitializeEvent(&HalpNewAdapter, SynchronizationEvent, TRUE);
//
// Determine if there is physical memory above 4 GB.
//
HalDebugPrint(( HAL_INFO, "HAL: Determine if there is memory above 4 Gb\n" ));
NoMemoryAbove4Gb = TRUE;
NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
Descriptor = CONTAINING_RECORD(
NextMd,
MEMORY_ALLOCATION_DESCRIPTOR,
ListEntry
);
if (Descriptor->MemoryType != LoaderFirmwarePermanent &&
Descriptor->MemoryType != LoaderSpecialMemory) {
//
// Test for 4 GB:
//
if ((Descriptor->BasePage + Descriptor->PageCount) > (GreaterThan4GB >> PAGE_SHIFT)) {
NoMemoryAbove4Gb = FALSE;
HalDebugPrint(( HAL_INFO, "HAL: Memory is present above 4Gb\n" ));
break;
}
}
NextMd = Descriptor->ListEntry.Flink;
}
//
// Determine the size needed for map buffers. If this system has
// memory that requires more than 32 bits to access, then allocate
// a large chunk; otherwise, allocate a small chunk.
//
if (NoMemoryAbove4Gb) {
//
// Allocate a small set of map buffers. They are only need for
// devices which do not function.
//
HalpMapBufferSize = INITIAL_MAP_BUFFER_SMALL_SIZE;
HalDebugPrint(( HAL_INFO, "HAL: No memory beyond 4Gb\n" ));
} else {
//
// Allocate a larger set of map buffers. These are used for
// 32 bit devices to reach memory above 4gb.
//
HalpMapBufferSize = INITIAL_MAP_BUFFER_LARGE_SIZE;
HalDebugPrint(( HAL_INFO, "HAL: Map Buffers for 32 bit devices to reach memory above 4Gb\n" ));
}
//
// Allocate map buffers for the adapter objects
//
HalpMapBufferPhysicalAddress.QuadPart = (ULONGLONG)
HalpAllocPhysicalMemory(LoaderBlock,
MAXIMUM_PHYSICAL_ADDRESS,
HalpMapBufferSize >> PAGE_SHIFT,
TRUE);
HalpMapBufferPhysicalAddress.HighPart = 0;
if (!HalpMapBufferPhysicalAddress.LowPart) {
//
// There was not a satisfactory block. Clear the allocation.
//
HalpMapBufferSize = 0;
}
//
// Set the processor active in the HAL private active processor mask.
//
// For the BSP processor, the specific bit is set at the end of HalInitSystem(Phase0).
HalpActiveProcessors = 1 << pPRCB->Number;
} else {
//
// Phase 1 initialization
//
if ( pPCR->Number == 0) {
//
// Back-pocket some PTEs for DMA during low mem
//
HalpInitReservedPages();
#if defined(HALP_FIX_KD_HALIA64_MASK)
#if DBG
HalpSetKdHalia64Mask( HalpFixKdHalia64Mask );
#endif // DBG
#endif // HALP_FIX_KD_HALIA64_MASK
HalpEfiInitialization(LoaderBlock);
HalpInitIoMemoryBase();
HalpInitializeX86Int10Call();
HalpInitializeInterruptBlock();
//
// Map the APICs so that MM will allow us to access them in the
// debugger.
//
HalpInitApicDebugMappings();
//
// Initialize MCA,INIT parameters and pre-allocate Event records for BSP processor.
//
if ( !HalpInitializeOSMCA( pPCR->Number ) ) {
return FALSE;
}
HalpInitNonBusHandler();
//
// Raise IRQL to the highest level, set the new clock interrupt
// parameters, lower IRQl, and return the new time increment value.
//
status = HalpQueryFrequency( &ITCFrequencyQueried,
&ProcessorFrequencyQueried);
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
if (NT_SUCCESS(status)) {
HalpITCFrequency = ITCFrequencyQueried;
HalpProcessorFrequency = ProcessorFrequencyQueried;
}
HalpSetInitialClockRate();
KeLowerIrql(OldIrql);
//
// Set initial feature bits
//
HalpFeatureBits = HalpGetFeatureBits();
//
// Initialize per-processor profiling
//
// Requires HalpITCTicksPer100ns initialized.
HalpInitializeProfiling( pPCR->Number );
HalpMCAEnable();
HalpCMCEnable();
HalpCPEEnable();
} else {
//
// Initialize per processor EOI table
//
HalpInitEOITable();
//
// Initialization needed only on non BSP processors
//
HalpInitSalPalNonBsp();
HalpInitializeClockPn();
//
// Allocate MCA, INIT stacks on non BSP processors
//
if ( !HalpAllocateMceStacks( pPCR->Number) ) {
return FALSE;
}
//
// Pre-allocate MCA,INIT records on non BSP processors
//
if ( !HalpPreAllocateMceRecords( pPCR->Number) ) {
return FALSE;
}
//
// Reduce feature bits to be a subset
//
HalpFeatureBits &= HalpGetFeatureBits();
HalpInitializeInterrupts();
//
// Initialize per-processor profiling
//
HalpInitializeProfiling( pPCR->Number );
HalpMCAEnable();
HalpCMCEnable();
//
// Set the processor active in the HAL private active processor mask.
//
// For non-BSP processors, the specific bit is set at the end of HalInitSystem(Phase1).
HalpActiveProcessors |= 1 << pPRCB->Number;
}
}
return TRUE;
}
VOID
HalChangeColorPage (
IN PVOID NewColor,
IN PVOID OldColor,
IN ULONG PageFrame
)
/*++
Routine Description:
This function changes the color of a page if the old and new colors
do not match.
Arguments:
NewColor - Supplies the page aligned virtual address of the
new color of the page to change.
OldColor - Supplies the page aligned virtual address of the
old color of the page to change.
pageFrame - Supplies the page frame number of the page that
is changed.
Return Value:
None.
--*/
{
return;
}
//****************************************************************
// T. Kjos Added stuff after this line as part of initial
// APIC, PCMP removal.
// From mpsproc.c
ULONG HalpDontStartProcessors = 0;
//
// Since IA-64 does not support lowest priority interrupts set
// processors per cluster to 1 so that we staically assign interrupts
// in round robin to the processors.
//
UCHAR HalpMaxProcsPerCluster = 1;
// From pmmphal.c:
BOOLEAN HalpStaticIntAffinity = FALSE;
extern UCHAR HalpSzInterruptAffinity[];
extern UCHAR HalpSzOneCpu[];
extern ULONG HalpDontStartProcessors;
extern UCHAR HalpSzPciLock[];
extern UCHAR HalpSzBreak[];
extern UCHAR HalpSzForceClusterMode[];
VOID
HalpGetParameters (
IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
/*++
Routine Description:
This gets any parameters from the boot.ini invocation line.
Arguments:
None.
Return Value:
None
--*/
{
PCHAR Options;
PCHAR p;
if (LoaderBlock != NULL && LoaderBlock->LoadOptions != NULL) {
Options = LoaderBlock->LoadOptions;
//
// Has the user set the debug flag?
//
//
// Has the user requested a particular number of CPU's?
//
if (strstr(Options, HalpSzOneCpu)) {
HalpDontStartProcessors++;
}
//
// Check if user wants device ints to go to highest numbered processor
//
if (strstr(Options, HalpSzInterruptAffinity)) {
HalpStaticIntAffinity = TRUE;
}
//
// Has the user asked for an initial BreakPoint?
//
if (strstr(Options, HalpSzBreak)) {
DbgBreakPoint();
}
//
// Used to define the size of a node = MaxProcsPerCluster
// 0 implies one node for the whole machine
//
p = strstr(Options, HalpSzForceClusterMode);
if (p) {
// skip to value
while (*p && *p != ' ' && (*p < '0' || *p > '9')) {
p++;
}
HalpMaxProcsPerCluster = (UCHAR)atoi(p);
}
}
return ;
}