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) 1989  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     allproc.c
    00008
    00009 Abstract:
    00010
    00011     This module allocates and initializes kernel resources required
    00012     to start a new processor, and passes a complete process_state
    00013     structre to the hal to obtain a new processor.  This is done
    00014     for every processor.
    00015
    00016 Author:
    00017
    00018     Ken Reneris (kenr) 22-Jan-92
    00019
    00020 Environment:
    00021
    00022     Kernel mode only.
    00023     Phase 1 of bootup
    00024
    00025 Revision History:
    00026
    00027 --*/
    00028
    00029
    00030 #include "ki.h"
    00031
    00032 #ifdef NT_UP
    00033
    00034 VOID
    00035 KeStartAllProcessors (
    00036     VOID
    00037     )
    00038 {
    00039         // UP Build - this function is a nop
    00040 }
    00041
    00042 #else
    00043
    00044 extern ULONG KeRegisteredProcessors;
    00045
    00046 static VOID
    00047 KiCloneDescriptor (
    00048    IN PKDESCRIPTOR  pSrcDescriptorInfo,
    00049    IN PKDESCRIPTOR  pDestDescriptorInfo
    00050    );
    00051
    00052 static VOID
    00053 KiCloneSelector (
    00054    IN ULONG    SrcSelector,
    00055    IN PKGDTENTRY    pNGDT,
    00056    IN PKDESCRIPTOR  pDestDescriptor
    00057    );
    00058
    00059
    00060 #ifdef ALLOC_PRAGMA
    00061 #pragma alloc_text(INIT,KeStartAllProcessors)
    00062 #pragma alloc_text(INIT,KiCloneDescriptor)
    00063 #pragma alloc_text(INIT,KiCloneSelector)
    00064 #endif
    00065
    00066 #if !defined(NT_UP)
    00067
    00068 ULONG KiBarrierWait = 0;
    00069
    00070 #endif
    00071
    00072
    00073
    00074 VOID
    00075 KeStartAllProcessors (
    00076     VOID
    00077     )
    00078 /*++
    00079
    00080 Routine Description:
    00081
    00082     Called by p0 during phase 1 of bootup.  This function implements
    00083     the x86 specific code to contact the hal for each system processor.
    00084
    00085 Arguments:
    00086
    00087 Return Value:
    00088
    00089     All available processors are sent to KiSystemStartup.
    00090
    00091 --*/
    00092 {
    00093     KPROCESSOR_STATE    ProcessorState;
    00094     KDESCRIPTOR         Descriptor;
    00095     KDESCRIPTOR         TSSDesc, DFTSSDesc, NMITSSDesc, PCRDesc;
    00096     PKGDTENTRY          pGDT;
    00097     PVOID               pStack;
    00098     PVOID               pDpcStack;
    00099     ULONG               DFStack;
    00100     PUCHAR              pThreadObject;
    00101     PULONG              pTopOfStack;
    00102     ULONG               NewProcessorNumber;
    00103     BOOLEAN             NewProcessor;
    00104     PKPROCESS           Process;
    00105     PKTHREAD            Thread;
    00106     PKTSS               pTSS;
    00107     PLIST_ENTRY         NextEntry;
    00108     LONG                NumberProcessors;
    00109
    00110     //
    00111     // If the registered number of processors is greater than the maximum
    00112     // number of processors supported, then only allow the maximum number
    00113     // of supported processors.
    00114     //
    00115
    00116     if (KeRegisteredProcessors > MAXIMUM_PROCESSORS) {
    00117         KeRegisteredProcessors = MAXIMUM_PROCESSORS;
    00118     }
    00119
    00120     //
    00121     // Set barrier that will prevent any other processor from entering the
    00122     // idle loop until all processors have been started.
    00123     //
    00124
    00125     KiBarrierWait = 1;
    00126
    00127
    00128     while ((ULONG)KeNumberProcessors < KeRegisteredProcessors) {
    00129         //
    00130         //  Build up a processor state for new processor
    00131         //
    00132
    00133         RtlZeroMemory ((PVOID) &ProcessorState, sizeof ProcessorState);
    00134
    00135
    00136         //
    00137         //  Give the new processor its own GDT
    00138         //
    00139
    00140         _asm {
    00141             sgdt    Descriptor.Limit
    00142         }
    00143
    00144         KiCloneDescriptor (&Descriptor,
    00145                          &ProcessorState.SpecialRegisters.Gdtr);
    00146
    00147         pGDT = (PKGDTENTRY) ProcessorState.SpecialRegisters.Gdtr.Base;
    00148
    00149
    00150         //
    00151         //  Give new processor its own IDT
    00152         //
    00153
    00154         _asm {
    00155             sidt    Descriptor.Limit
    00156         }
    00157         KiCloneDescriptor (&Descriptor,
    00158                          &ProcessorState.SpecialRegisters.Idtr);
    00159
    00160
    00161         //
    00162         //  Give new processor its own TSS and PCR
    00163         //
    00164
    00165         KiCloneSelector   (KGDT_TSS, pGDT, &TSSDesc);
    00166         KiCloneSelector   (KGDT_R0_PCR, pGDT, &PCRDesc);
    00167
    00168         //
    00169         // Allocate double-fault TSS & stack, and NMI TSS
    00170         //
    00171
    00172         KiCloneSelector (KGDT_DF_TSS, pGDT, &DFTSSDesc);
    00173         DFStack = (ULONG)ExAllocatePoolWithTag(NonPagedPool, DOUBLE_FAULT_STACK_SIZE, '  eK');
    00174         pTSS = (PKTSS)DFTSSDesc.Base;
    00175         pTSS->Esp0 = DFStack + DOUBLE_FAULT_STACK_SIZE;
    00176         pTSS->NotUsed2[5] = DFStack + DOUBLE_FAULT_STACK_SIZE;
    00177
    00178         KiCloneSelector (KGDT_NMI_TSS, pGDT, &NMITSSDesc);
    00179         pTSS = (PKTSS)NMITSSDesc.Base;
    00180         pTSS->Esp0 = DFStack + DOUBLE_FAULT_STACK_SIZE;
    00181         pTSS->NotUsed2[5] = DFStack + DOUBLE_FAULT_STACK_SIZE;
    00182
    00183
    00184         //
    00185         //  Set other SpecialRegisters in processor state
    00186         //
    00187
    00188         _asm {
    00189             mov     eax, cr0
    00190             and     eax, NOT (CR0_AM or CR0_WP)
    00191             mov     ProcessorState.SpecialRegisters.Cr0, eax
    00192             mov     eax, cr3
    00193             mov     ProcessorState.SpecialRegisters.Cr3, eax
    00194
    00195             pushfd
    00196             pop     ProcessorState.ContextFrame.EFlags
    00197             and     ProcessorState.ContextFrame.EFlags, NOT EFLAGS_INTERRUPT_MASK
    00198         }
    00199
    00200         ProcessorState.SpecialRegisters.Tr  = KGDT_TSS;
    00201         pGDT[KGDT_TSS>>3].HighWord.Bytes.Flags1 = 0x89;
    00202
    00203 #if defined(_X86PAE_)
    00204         ProcessorState.SpecialRegisters.Cr4 = CR4_PAE;
    00205 #endif
    00206
    00207         //
    00208         // Allocate a DPC stack, idle thread stack and ThreadObject for
    00209         // the new processor.
    00210         //
    00211
    00212         pStack = MmCreateKernelStack (FALSE);
    00213         pDpcStack = MmCreateKernelStack (FALSE);
    00214         pThreadObject = (PUCHAR)ExAllocatePoolWithTag (NonPagedPool, sizeof(ETHREAD), '  eK');
    00215
    00216         //
    00217         //  Zero initialize these...
    00218         //
    00219
    00220         RtlZeroMemory ((PVOID) PCRDesc.Base, sizeof (KPCR));
    00221         RtlZeroMemory ((PVOID) pThreadObject, sizeof (KTHREAD));
    00222
    00223
    00224         //
    00225         //  Setup context
    00226         //  Push variables onto new stack
    00227         //
    00228
    00229         pTopOfStack = (PULONG) pStack;
    00230         pTopOfStack[-1] = (ULONG) KeLoaderBlock;
    00231         ProcessorState.ContextFrame.Esp = (ULONG) (pTopOfStack-2);
    00232         ProcessorState.ContextFrame.Eip = (ULONG) KiSystemStartup;
    00233
    00234         ProcessorState.ContextFrame.SegCs = KGDT_R0_CODE;
    00235         ProcessorState.ContextFrame.SegDs = KGDT_R3_DATA;
    00236         ProcessorState.ContextFrame.SegEs = KGDT_R3_DATA;
    00237         ProcessorState.ContextFrame.SegFs = KGDT_R0_PCR;
    00238         ProcessorState.ContextFrame.SegSs = KGDT_R0_DATA;
    00239
    00240
    00241         //
    00242         //  Initialize new processor's PCR & Prcb
    00243         //
    00244
    00245         NewProcessorNumber = KeNumberProcessors;
    00246         KiInitializePcr (
    00247             (ULONG)       NewProcessorNumber,
    00248             (PKPCR)       PCRDesc.Base,
    00249             (PKIDTENTRY)  ProcessorState.SpecialRegisters.Idtr.Base,
    00250             (PKGDTENTRY)  ProcessorState.SpecialRegisters.Gdtr.Base,
    00251             (PKTSS)       TSSDesc.Base,
    00252             (PKTHREAD)    pThreadObject,
    00253             (PVOID)       pDpcStack
    00254         );
    00255
    00256
    00257         //
    00258         //  Adjust LoaderBlock so it has the next processors state
    00259         //
    00260
    00261         KeLoaderBlock->KernelStack = (ULONG) pTopOfStack;
    00262         KeLoaderBlock->Thread = (ULONG) pThreadObject;
    00263         KeLoaderBlock->Prcb = (ULONG) ((PKPCR) PCRDesc.Base)->Prcb;
    00264
    00265
    00266         //
    00267         //  Contact hal to start new processor
    00268         //
    00269
    00270         NewProcessor = HalStartNextProcessor (KeLoaderBlock, &ProcessorState);
    00271
    00272
    00273         if (!NewProcessor) {
    00274
    00275             //
    00276             //  There wasn't another processor, so free resources and
    00277             //  break
    00278             //
    00279
    00280             KiProcessorBlock[NewProcessorNumber] = NULL;
    00281             ExFreePool ((PVOID) ProcessorState.SpecialRegisters.Gdtr.Base);
    00282             ExFreePool ((PVOID) ProcessorState.SpecialRegisters.Idtr.Base);
    00283             ExFreePool ((PVOID) TSSDesc.Base);
    00284             ExFreePool ((PVOID) DFTSSDesc.Base);
    00285             ExFreePool ((PVOID) NMITSSDesc.Base);
    00286             ExFreePool ((PVOID) PCRDesc.Base);
    00287             ExFreePool ((PVOID) pThreadObject);
    00288             ExFreePool ((PVOID) DFStack);
    00289             MmDeleteKernelStack ( pStack, FALSE);
    00290             MmDeleteKernelStack ( pDpcStack, FALSE);
    00291             break;
    00292         }
    00293
    00294
    00295         //
    00296         //  Wait for processor to initialize in kernel, then loop for another
    00297         //
    00298
    00299         while (*((volatile ULONG *) &KeLoaderBlock->Prcb) != 0) {
    00300             KeYieldProcessor();
    00301         }
    00302     }
    00303
    00304     //
    00305     // Reset and synchronize the performance counters of all processors, by
    00306     // applying a null adjustment to the interrupt time
    00307     //
    00308
    00309     KiAdjustInterruptTime (0);
    00310
    00311     //
    00312     // Allow all processors that were started to enter the idle loop and
    00313     // begin execution.
    00314     //
    00315
    00316     KiBarrierWait = 0;
    00317 }
    00318
    00319
    00320
    00321 static VOID
    00322 KiCloneSelector (
    00323    IN ULONG    SrcSelector,
    00324    IN PKGDTENTRY    pNGDT,
    00325    IN PKDESCRIPTOR  pDestDescriptor
    00326 /*++
    00327
    00328 Routine Description:
    00329
    00330     Makes a copy of the current selector's data, and update the new
    00331     gdt's linear address to point to the new copy.
    00332
    00333 Arguments:
    00334     SrcSelector     -   Selector value to clone
    00335     pNGDT           -   New gdt table which is being built
    00336     DescDescriptor  -   descriptor structure to fill in with resulting memory
    00337
    00338 Return Value:
    00339
    00340 --*/
    00341    )
    00342 {
    00343     KDESCRIPTOR Descriptor;
    00344     PKGDTENTRY  pGDT;
    00345     ULONG       CurrentBase;
    00346     ULONG       NewBase;
    00347
    00348     _asm {
    00349         sgdt    fword ptr [Descriptor.Limit]    ; Get GDT's addr
    00350     }
    00351
    00352     pGDT   = (PKGDTENTRY) Descriptor.Base;
    00353     pGDT  += SrcSelector >> 3;
    00354     pNGDT += SrcSelector >> 3;
    00355
    00356     CurrentBase = pGDT->BaseLow | (pGDT->HighWord.Bits.BaseMid << 16) |
    00357                  (pGDT->HighWord.Bits.BaseHi << 24);
    00358
    00359     Descriptor.Base  = CurrentBase;
    00360     Descriptor.Limit = pGDT->LimitLow;
    00361     if (pGDT->HighWord.Bits.Granularity & GRAN_PAGE)
    00362         Descriptor.Limit = (Descriptor.Limit << PAGE_SHIFT) -1;
    00363
    00364     KiCloneDescriptor (&Descriptor, pDestDescriptor);
    00365     NewBase = pDestDescriptor->Base;
    00366
    00367     pNGDT->BaseLow = (USHORT) NewBase & 0xffff;
    00368     pNGDT->HighWord.Bits.BaseMid = (UCHAR) (NewBase >> 16) & 0xff;
    00369     pNGDT->HighWord.Bits.BaseHi  = (UCHAR) (NewBase >> 24) & 0xff;
    00370 }
    00371
    00372
    00373
    00374 static VOID
    00375 KiCloneDescriptor (
    00376    IN PKDESCRIPTOR  pSrcDescriptor,
    00377    IN PKDESCRIPTOR  pDestDescriptor
    00378    )
    00379 /*++
    00380
    00381 Routine Description:
    00382
    00383     Makes a copy of the specified descriptor, and supplies a return
    00384     descriptor for the new copy
    00385
    00386 Arguments:
    00387     pSrcDescriptor  - descriptor to clone
    00388     pDescDescriptor - the cloned descriptor
    00389
    00390 Return Value:
    00391
    00392 --*/
    00393 {
    00394     ULONG   Size;
    00395
    00396     Size = pSrcDescriptor->Limit + 1;
    00397     pDestDescriptor->Limit = (USHORT) Size -1;
    00398     pDestDescriptor->Base  = (ULONG)  ExAllocatePoolWithTag (NonPagedPool, Size, '  eK');
    00399
    00400     RtlMoveMemory ((PVOID) pDestDescriptor->Base,
    00401                    (PVOID) pSrcDescriptor->Base, Size);
    00402 }
    00403
    00404
    00405 #endif      // !NT_UP