Windows2000/private/ntos/ke/ia64/allproc.c
2020-09-30 17:12:32 +02:00

250 lines
5.4 KiB
C

/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
allproc.c
Abstract:
This module allocates and intializes kernel resources required
to start a new processor, and passes a complete processor state
structure to the HAL to obtain a new processor.
Author:
Bernard Lint 31-Jul-96
Environment:
Kernel mode only.
Revision History:
Based on MIPS original (David N. Cutler 29-Apr-1993)
--*/
#include "ki.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, KeStartAllProcessors)
#endif
// Define macro to round up to 64-byte boundary and define block sizes.
#define ROUND_UP(x) ((sizeof(x) + 63) & (~63))
#define BLOCK1_SIZE (2 * (KERNEL_BSTORE_SIZE + KERNEL_STACK_SIZE) + PAGE_SIZE)
#define BLOCK2_SIZE (ROUND_UP(KPRCB) + ROUND_UP(ETHREAD) + 64)
#if !defined(NT_UP)
// Define barrier wait static data.
ULONG KiBarrierWait = 0;
#endif
extern ULONG_PTR KiUserSharedDataPage;
extern ULONG_PTR KiKernelPcrPage;
// Define forward referenced prototypes.
VOID
KiCalibratePerformanceCounter(
VOID
);
VOID
KiCalibratePerformanceCounterTarget (
IN PULONG SignalDone,
IN PVOID Count,
IN PVOID Parameter2,
IN PVOID Parameter3
);
VOID
KiOSRendezvous (
VOID
);
VOID
KeStartAllProcessors(
VOID
)
/*++
Routine Description:
This function is called during phase 1 initialize on the master boot
processor to start all of the other registered processors.
Arguments:
None.
Return Value:
None.
--*/
{
ULONG_PTR MemoryBlock1;
ULONG_PTR MemoryBlock2;
ULONG_PTR MemoryBlock3;
ULONG_PTR PcrAddress;
ULONG Number;
PHYSICAL_ADDRESS PcrPage;
PKPRCB Prcb;
BOOLEAN Started;
KPROCESSOR_STATE ProcessorState;
#if !defined(NT_UP)
// If the registered number of processors is greater than the maximum
// number of processors supported, then only allow the maximum number
// of supported processors.
if (KeRegisteredProcessors > MAXIMUM_PROCESSORS) {
KeRegisteredProcessors = MAXIMUM_PROCESSORS;
}
// Set barrier that will prevent any other processor from entering the
// idle loop until all processors have been started.
KiBarrierWait = 1;
// Initialize the processor state that will be used to start each of
// processors. Each processor starts in the system initialization code
// with address of the loader parameter block as an argument.
Number = 1;
RtlZeroMemory(&ProcessorState, sizeof(KPROCESSOR_STATE));
ProcessorState.ContextFrame.StIIP = ((PPLABEL_DESCRIPTOR)KiOSRendezvous)->EntryPoint;
while (Number < KeRegisteredProcessors) {
// **** TBD check this for MP case
// Allocate a DPC stack, an idle thread kernel stack, a panic
// stack, a PCR page, a processor block, and an executive thread
// object. If the allocation fails or the allocation cannot be
// made from unmapped nonpaged pool, then stop starting processors.
MemoryBlock1 = (ULONG_PTR)ExAllocatePool(NonPagedPool, BLOCK1_SIZE);
if ((PVOID)MemoryBlock1 == NULL) {
break;
}
MemoryBlock2 = (ULONG_PTR)ExAllocatePool(NonPagedPool, BLOCK2_SIZE);
if ((PVOID)MemoryBlock2 == NULL) {
ExFreePool((PVOID)MemoryBlock1);
break;
}
// Zero both blocks of allocated memory.
RtlZeroMemory((PVOID)MemoryBlock1, BLOCK1_SIZE);
RtlZeroMemory((PVOID)MemoryBlock2, BLOCK2_SIZE);
// Set address of idle thread kernel stack in loader parameter block.
KeLoaderBlock->KernelStack = MemoryBlock1 + KERNEL_STACK_SIZE;
// Set address of panic stack in loader parameter block.
KeLoaderBlock->u.Ia64.PanicStack = MemoryBlock1 + KERNEL_BSTORE_SIZE +
(2 * KERNEL_STACK_SIZE);
// Set the address of the processor block and executive thread in the
// loader parameter block.
KeLoaderBlock->Prcb = MemoryBlock2;
KeLoaderBlock->Thread = KeLoaderBlock->Prcb + ROUND_UP(KPRCB);
((PKPRCB)KeLoaderBlock->Prcb)->Number = (UCHAR)Number;
// Set the page frame of the PCR page in the loader parameter block.
PcrAddress = MemoryBlock1 + KERNEL_BSTORE_SIZE + (2*KERNEL_STACK_SIZE);
PcrPage = MmGetPhysicalAddress((PVOID)PcrAddress);
KeLoaderBlock->u.Ia64.PcrPage = PcrPage.QuadPart >> PAGE_SHIFT;
KeLoaderBlock->u.Ia64.PcrPage2 = KiUserSharedDataPage;
KiKernelPcrPage = KeLoaderBlock->u.Ia64.PcrPage;
// Attempt to start the next processor. If attempt is successful,
// then wait for the processor to get initialized. Otherwise,
// deallocate the processor resources and terminate the loop.
Started = HalStartNextProcessor(KeLoaderBlock, &ProcessorState);
if (Started) {
// Wait for processor to initialize in kernel,
// then loop for another
while (*((volatile ULONG_PTR *) &KeLoaderBlock->Prcb) != 0) {
KeYieldProcessor();
}
} else {
ExFreePool((PVOID)MemoryBlock1);
ExFreePool((PVOID)MemoryBlock2);
break;
}
Number += 1;
}
// Allow all processor that were started to enter the idle loop and
// begin execution.
KiBarrierWait = 0;
#endif
// Reset and synchronize the performance counters of all processors.
KiAdjustInterruptTime (0);
return;
}