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

Generated on Sat May 15 19:39:14 2004 for test by doxygen 1.3.7