test: allproc.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# allproc.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1990  Microsoft Corporation
    00004 Copyright (c) 1993  Digital Equipment Corporation
    00005
    00006 Module Name:
    00007
    00008     allproc.c
    00009
    00010 Abstract:
    00011
    00012     This module allocates and initializes kernel resources required
    00013     to start a new processor, and passes a complete processor state
    00014     structure to the HAL to obtain a new processor.
    00015
    00016 Author:
    00017
    00018     David N. Cutler 29-Apr-1993
    00019     Joe Notarangelo 30-Nov-1993
    00020
    00021 Environment:
    00022
    00023     Kernel mode only.
    00024
    00025 Revision History:
    00026
    00027 --*/
    00028
    00029
    00030 #include "ki.h"
    00031
    00032 #ifdef ALLOC_PRAGMA
    00033
    00034 #pragma alloc_text(INIT, KeStartAllProcessors)
    00035
    00036 #endif
    00037
    00038 //
    00039 // Define macro to round up to 64-byte boundary and define block sizes.
    00040 //
    00041
    00042 #define ROUND_UP(x) ((sizeof(x) + 64) & (~64))
    00043 #define BLOCK1_SIZE ((3 * KERNEL_STACK_SIZE) + PAGE_SIZE)
    00044 #define BLOCK2_SIZE (ROUND_UP(KPRCB) + ROUND_UP(ETHREAD) + 64)
    00045
    00046 //
    00047 // Macros to compute whether an address is physically addressable.
    00048 //
    00049
    00050 #if defined(_AXP64_)
    00051
    00052 #define IS_KSEG_ADDRESS(v)                                      \
    00053     (((v) >= KSEG43_BASE) &&                                    \
    00054      ((v) < KSEG43_LIMIT) &&                                    \
    00055      (KSEG_PFN(v) < ((KSEG2_BASE - KSEG0_BASE) >> PAGE_SHIFT)))
    00056
    00057 #define KSEG_PFN(v) ((ULONG)(((v) - KSEG43_BASE) >> PAGE_SHIFT))
    00058 #define KSEG0_ADDRESS(v) (KSEG0_BASE | ((v) - KSEG43_BASE))
    00059
    00060 #else
    00061
    00062 #define IS_KSEG_ADDRESS(v) (((v) >= KSEG0_BASE) && ((v) < KSEG2_BASE))
    00063 #define KSEG_PFN(v) ((ULONG)(((v) - KSEG0_BASE) >> PAGE_SHIFT))
    00064 #define KSEG0_ADDRESS(v) (v)
    00065
    00066 #endif
    00067
    00068 //
    00069 // Define forward referenced prototypes.
    00070 //
    00071
    00072 VOID
    00073 KiStartProcessor (
    00074     IN PLOADER_PARAMETER_BLOCK Loaderblock
    00075     );
    00076
    00077 VOID
    00078 KeStartAllProcessors(
    00079     VOID
    00080     )
    00081
    00082 /*++
    00083
    00084 Routine Description:
    00085
    00086     This function is called during phase 1 initialization on the master boot
    00087     processor to start all of the other registered processors.
    00088
    00089 Arguments:
    00090
    00091     None.
    00092
    00093 Return Value:
    00094
    00095     None.
    00096
    00097 --*/
    00098
    00099 {
    00100
    00101     ULONG_PTR MemoryBlock1;
    00102     ULONG_PTR MemoryBlock2;
    00103     ULONG Number;
    00104     ULONG PcrPage;
    00105     PKPRCB Prcb;
    00106     KPROCESSOR_STATE ProcessorState;
    00107     struct _RESTART_BLOCK *RestartBlock;
    00108     BOOLEAN Started;
    00109     LOGICAL SpecialPoolState;
    00110
    00111 #if !defined(NT_UP)
    00112
    00113     //
    00114     // If the registered number of processors is greater than the maximum
    00115     // number of processors supported, then only allow the maximum number
    00116     // of supported processors.
    00117     //
    00118
    00119     if (KeRegisteredProcessors > MAXIMUM_PROCESSORS) {
    00120         KeRegisteredProcessors = MAXIMUM_PROCESSORS;
    00121     }
    00122
    00123     //
    00124     // Initialize the processor state that will be used to start each of
    00125     // processors. Each processor starts in the system initialization code
    00126     // with address of the loader parameter block as an argument.
    00127     //
    00128
    00129     RtlZeroMemory(&ProcessorState, sizeof(KPROCESSOR_STATE));
    00130     ProcessorState.ContextFrame.IntA0 = (ULONGLONG)(LONG_PTR)KeLoaderBlock;
    00131     ProcessorState.ContextFrame.Fir = (ULONGLONG)(LONG_PTR)KiStartProcessor;
    00132     Number = 1;
    00133     while (Number < KeRegisteredProcessors) {
    00134
    00135         //
    00136         // Allocate a DPC stack, an idle thread kernel stack, a panic
    00137         // stack, a PCR page, a processor block, and an executive thread
    00138         // object. If the allocation fails or the allocation cannot be
    00139         // made from unmapped nonpaged pool, then stop starting processors.
    00140         //
    00141         // Disable any special pooling that the user may have set in the
    00142         // registry as the next couple of allocations must come from KSEG0.
    00143         //
    00144
    00145         SpecialPoolState = MmSetSpecialPool(FALSE);
    00146         MemoryBlock1 = (ULONG_PTR)ExAllocatePool(NonPagedPool, BLOCK1_SIZE);
    00147         if (IS_KSEG_ADDRESS(MemoryBlock1) == FALSE) {
    00148             MmSetSpecialPool(SpecialPoolState);
    00149             if ((PVOID)MemoryBlock1 != NULL) {
    00150                 ExFreePool((PVOID)MemoryBlock1);
    00151             }
    00152
    00153             break;
    00154         }
    00155
    00156         MemoryBlock2 = (ULONG_PTR)ExAllocatePool(NonPagedPool, BLOCK2_SIZE);
    00157         if (IS_KSEG_ADDRESS(MemoryBlock2) == FALSE) {
    00158             MmSetSpecialPool(SpecialPoolState);
    00159             ExFreePool((PVOID)MemoryBlock1);
    00160             if ((PVOID)MemoryBlock2 != NULL) {
    00161                 ExFreePool((PVOID)MemoryBlock2);
    00162             }
    00163
    00164             break;
    00165         }
    00166
    00167         MmSetSpecialPool(SpecialPoolState);
    00168
    00169         //
    00170         // Zero both blocks of allocated memory.
    00171         //
    00172
    00173         RtlZeroMemory((PVOID)MemoryBlock1, BLOCK1_SIZE);
    00174         RtlZeroMemory((PVOID)MemoryBlock2, BLOCK2_SIZE);
    00175
    00176         //
    00177         // Set address of interrupt stack in loader parameter block.
    00178         //
    00179
    00180         KeLoaderBlock->u.Alpha.PanicStack =
    00181                         KSEG0_ADDRESS(MemoryBlock1 + (1 * KERNEL_STACK_SIZE));
    00182
    00183         //
    00184         // Set address of idle thread kernel stack in loader parameter block.
    00185         //
    00186
    00187         KeLoaderBlock->KernelStack =
    00188                         KSEG0_ADDRESS(MemoryBlock1 + (2 * KERNEL_STACK_SIZE));
    00189
    00190         ProcessorState.ContextFrame.IntSp =
    00191                             (ULONGLONG)(LONG_PTR)KeLoaderBlock->KernelStack;
    00192
    00193         //
    00194         // Set address of panic stack in loader parameter block.
    00195         //
    00196
    00197         KeLoaderBlock->u.Alpha.DpcStack =
    00198                         KSEG0_ADDRESS(MemoryBlock1 + (3 * KERNEL_STACK_SIZE));
    00199
    00200         //
    00201         // Set the page frame of the PCR page in the loader parameter block.
    00202         //
    00203
    00204         PcrPage = KSEG_PFN(MemoryBlock1 + (3 * KERNEL_STACK_SIZE));
    00205         KeLoaderBlock->u.Alpha.PcrPage = PcrPage;
    00206
    00207         //
    00208         // Set the address of the processor block and executive thread in the
    00209         // loader parameter block.
    00210         //
    00211
    00212         KeLoaderBlock->Prcb = KSEG0_ADDRESS((MemoryBlock2  + 63) & ~63);
    00213         KeLoaderBlock->Thread = KeLoaderBlock->Prcb + ROUND_UP(KPRCB);
    00214
    00215         //
    00216         // Attempt to start the next processor. If attempt is successful,
    00217         // then wait for the processor to get initialized. Otherwise,
    00218         // deallocate the processor resources and terminate the loop.
    00219         //
    00220
    00221         Started = HalStartNextProcessor(KeLoaderBlock, &ProcessorState);
    00222         if (Started == FALSE) {
    00223             ExFreePool((PVOID)MemoryBlock1);
    00224             ExFreePool((PVOID)MemoryBlock2);
    00225             break;
    00226
    00227         } else {
    00228
    00229             //
    00230             // Wait until boot is finished on the target processor before
    00231             // starting the next processor. Booting is considered to be
    00232             // finished when a processor completes its initialization and
    00233             // drops into the idle loop.
    00234             //
    00235
    00236             Prcb = (PKPRCB)(KeLoaderBlock->Prcb);
    00237             RestartBlock = Prcb->RestartBlock;
    00238             while (RestartBlock->BootStatus.BootFinished == 0) {
    00239                 KiMb();
    00240             }
    00241         }
    00242
    00243         Number += 1;
    00244     }
    00245
    00246 #endif
    00247
    00248     //
    00249     // Reset and synchronize the performance counters of all processors, by
    00250     // applying a null adjustment to the interrupt time
    00251     //
    00252
    00253     KiAdjustInterruptTime(0);
    00254     return;
    00255 }
    00256