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

kernlini.c File Reference

#include "ki.h"
#include "ki386.h"
#include "fastsys.inc"

Go to the source code of this file.

Defines

#define TRAP332_GATE   0xEF00
#define RET   0xc3
#define CRC_NDX   (PUCHAR)0x22
#define CRC_DAT   (CRC_NDX + 1)
#define CCR1   0xc1
#define CPUID_REG_COUNT   4
#define MAX_ATTEMPTS   10
#define IDT_SKIP   (7 * sizeof (KIDTENTRY))

Enumerations

enum  CPU_VENDORS {
  CPU_NONE, CPU_INTEL, CPU_AMD, CPU_CYRIX,
  CPU_UNKNOWN
}

Functions

VOID KiSetProcessorType (VOID)
VOID KiSetCR0Bits (VOID)
BOOLEAN KiIsNpxPresent (VOID)
VOID KiI386PentiumLockErrataFixup (VOID)
VOID KiInitializeDblFaultTSS (IN PKTSS Tss, IN ULONG Stack, IN PKGDTENTRY TssDescriptor)
VOID KiInitializeTSS2 (IN PKTSS Tss, IN PKGDTENTRY TssDescriptor)
VOID KiSwapIDT (VOID)
VOID KeSetup80387OrEmulate (IN PVOID *R3EmulatorTable)
VOID KiGetCacheInformation (VOID)
ULONG KiGetCpuVendor (VOID)
ULONG KiGetFeatureBits (VOID)
NTSTATUS KiMoveRegTree (HANDLE Source, HANDLE Dest)
VOID Ki386EnableFxsr (IN volatile PLONG Number)
VOID Ki386EnableXMMIExceptions (IN volatile PLONG Number)
VOID Ki386EnableGlobalPage (IN volatile PLONG Number)
VOID Ki386UseSynchronousTbFlush (IN volatile PLONG Number)
BOOLEAN KiInitMachineDependent (VOID)
VOID KiInitializeMTRR (IN BOOLEAN LastProcessor)
VOID KiInitializePAT (VOID)
VOID KiAmdK6InitializeMTRR (VOID)
VOID FASTCALL KiZeroPage (PVOID PageBase)
VOID FASTCALL KiXMMIZeroPage (PVOID PageBase)
VOID FASTCALL KiXMMIZeroPageNoSave (PVOID PageBase)
VOID KiInitializeKernel (IN PKPROCESS Process, IN PKTHREAD Thread, IN PVOID IdleStack, IN PKPRCB Prcb, IN CCHAR Number, PLOADER_PARAMETER_BLOCK LoaderBlock)
VOID KiInitializePcr (IN ULONG Processor, IN PKPCR Pcr, IN PKIDTENTRY Idt, IN PKGDTENTRY Gdt, IN PKTSS Tss, IN PKTHREAD Thread, IN PVOID DpcStack)
VOID KiInitializeTSS (IN PKTSS Tss)
VOID KiSwapIDT ()
VOID KeOptimizeProcessorControlState (VOID)

Variables

KSPIN_LOCK CcMasterSpinLock
KSPIN_LOCK CcVacbSpinLock
KSPIN_LOCK MmPfnLock
KSPIN_LOCK MmSystemSpaceLock
BOOLEAN KiI386PentiumLockErrataPresent = FALSE
BOOLEAN KiIgnoreUnexpectedTrap07 = FALSE
PVOID Ki387RoundModeTable
PVOID Ki386IopmSaveArea
ULONG KeI386ForceNpxEmulation
WCHAR CmDisabledFloatingPointProcessor []
UCHAR CmpCyrixID []
UCHAR CmpIntelID []
UCHAR CmpAmdID []
PVOID ScPatchFxb
PVOID ScPatchFxe
BOOLEAN KeI386XMMIPresent
KE_ZERO_PAGE_ROUTINE KeZeroPage = KiZeroPage
KE_ZERO_PAGE_ROUTINE KeZeroPageFromIdleThread = KiZeroPage
ULONG Ki486CompatibilityLock
KIDTENTRY IDT []


Define Documentation

#define CCR1   0xc1
 

#define CPUID_REG_COUNT   4
 

Referenced by KiGetCacheInformation().

#define CRC_DAT   (CRC_NDX + 1)
 

#define CRC_NDX   (PUCHAR)0x22
 

#define IDT_SKIP   (7 * sizeof (KIDTENTRY))
 

Referenced by KiI386PentiumLockErrataFixup().

#define MAX_ATTEMPTS   10
 

Definition at line 1688 of file kernlini.c.

Referenced by KiInitMachineDependent(), and WinHelpA().

#define RET   0xc3
 

Referenced by KiInitializeKernel().

#define TRAP332_GATE   0xEF00
 

Definition at line 41 of file kernlini.c.

Referenced by KeSetup80387OrEmulate().


Enumeration Type Documentation

enum CPU_VENDORS
 

Enumeration values:
CPU_NONE 
CPU_INTEL 
CPU_AMD 
CPU_CYRIX 
CPU_UNKNOWN 

Definition at line 194 of file kernlini.c.

00194 { 00195 CPU_NONE, 00196 CPU_INTEL, 00197 CPU_AMD, 00198 CPU_CYRIX, 00199 CPU_UNKNOWN 00200 } CPU_VENDORS;


Function Documentation

VOID KeOptimizeProcessorControlState VOID   ) 
 

Definition at line 1998 of file kernlini.c.

References Ke386ConfigureCyrixProcessor().

Referenced by CmpConfigureProcessors().

02001 { 02002 Ke386ConfigureCyrixProcessor (); 02003 }

VOID KeSetup80387OrEmulate IN PVOID *  R3EmulatorTable  ) 
 

Definition at line 2008 of file kernlini.c.

References CmDisabledFloatingPointProcessor, CmRegistryMachineHardwareDescriptionSystemName, CmTypeName, Compare(), FALSE, FloatingPointProcessor, is, it, KeActiveProcessors, KeFeatureBits, KeGetPcr, KeI386ForceNpxEmulation, KeI386NpxPresent, KeRevertToUserAffinityThread(), KeSetSystemAffinityThread(), KF_FXSR, KF_MMX, KF_XMMI, Ki387RoundModeTable, KiLockDispatcherDatabase, KiMoveRegTree(), KiUnlockDispatcherDatabase(), move, NT_SUCCESS, NTSTATUS(), NULL, ObjectAttributes, RtlInitUnicodeString(), Status, the, TRAP332_GATE, and TRUE.

Referenced by PspInitializeSystemDll().

02014 : 02015 02016 This routine is called by PS initialization after loading NTDLL. 02017 02018 If this is a 386 system without 387s (all processors must be 02019 symmetrical) then this function will set the trap 07 vector on all 02020 processors to point to the address passed in (which should be the 02021 entry point of the 80387 emulator in NTDLL, NPXNPHandler). 02022 02023 Arguments: 02024 02025 HandlerAddress - Supplies the address of the trap07 handler. 02026 02027 Return Value: 02028 02029 None. 02030 02031 --*/ 02032 02033 { 02034 PKINTERRUPT_ROUTINE HandlerAddress; 02035 KAFFINITY ActiveProcessors, CurrentAffinity; 02036 KIRQL OldIrql; 02037 ULONG disposition; 02038 HANDLE SystemHandle, SourceHandle, DestHandle; 02039 NTSTATUS Status; 02040 UNICODE_STRING unicodeString; 02041 OBJECT_ATTRIBUTES ObjectAttributes; 02042 double Dividend, Divisor; 02043 BOOLEAN PrecisionErrata; 02044 02045 if (KeI386NpxPresent) { 02046 02047 // 02048 // A coprocessor is present - check to see if the precision errata exists 02049 // 02050 02051 PrecisionErrata = FALSE; 02052 02053 ActiveProcessors = KeActiveProcessors; 02054 for (CurrentAffinity = 1; ActiveProcessors; CurrentAffinity <<= 1) { 02055 02056 if (ActiveProcessors & CurrentAffinity) { 02057 ActiveProcessors &= ~CurrentAffinity; 02058 02059 // 02060 // Run calculation on each processor. 02061 // 02062 02063 KeSetSystemAffinityThread(CurrentAffinity); 02064 _asm { 02065 02066 ; 02067 ; This is going to destroy the state in the coprocesssor, 02068 ; but we know that there's no state currently in it. 02069 ; 02070 02071 cli 02072 mov eax, cr0 02073 mov ecx, eax ; hold original cr0 value 02074 and eax, not (CR0_TS+CR0_MP+CR0_EM) 02075 mov cr0, eax 02076 02077 fninit ; to known state 02078 } 02079 02080 Dividend = 4195835.0; 02081 Divisor = 3145727.0; 02082 02083 _asm { 02084 fld Dividend 02085 fdiv Divisor ; test known faulty divison 02086 fmul Divisor ; Multiple quotient by divisor 02087 fcomp Dividend ; Compare product and dividend 02088 fstsw ax ; Move float conditions to ax 02089 sahf ; move to eflags 02090 02091 mov cr0, ecx ; restore cr0 02092 sti 02093 02094 jc short em10 02095 jz short em20 02096 em10: mov PrecisionErrata, TRUE 02097 em20: 02098 } 02099 } 02100 } 02101 02102 02103 // 02104 // Check to see if the emulator should be used anyway 02105 // 02106 02107 switch (KeI386ForceNpxEmulation) { 02108 case 0: 02109 // 02110 // Use the emulator based on the value in KeI386NpxPresent 02111 // 02112 02113 break; 02114 02115 case 1: 02116 // 02117 // Only use the emulator if any processor has the known 02118 // Pentium floating point division problem. 02119 // 02120 02121 if (PrecisionErrata) { 02122 KeI386NpxPresent = FALSE; 02123 } 02124 break; 02125 02126 default: 02127 02128 // 02129 // Unknown setting - use the emulator 02130 // 02131 02132 KeI386NpxPresent = FALSE; 02133 break; 02134 } 02135 } 02136 02137 // 02138 // Setup processor features, and install emulator if needed 02139 // 02140 02141 SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] = !KeI386NpxPresent; 02142 SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = PrecisionErrata; 02143 02144 if (!KeI386NpxPresent) { 02145 02146 // 02147 // MMx not available when emulator is used 02148 // 02149 02150 KeFeatureBits &= ~(KF_MMX|KF_FXSR|KF_XMMI); 02151 SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = FALSE; 02152 SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] = FALSE; 02153 SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] = FALSE; 02154 02155 // 02156 // Errata not present when using emulator 02157 // 02158 02159 SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = FALSE; 02160 02161 // 02162 // Use the user mode floating point emulator 02163 // 02164 02165 HandlerAddress = (PKINTERRUPT_ROUTINE) ((PULONG) R3EmulatorTable)[0]; 02166 Ki387RoundModeTable = (PVOID) ((PULONG) R3EmulatorTable)[1]; 02167 02168 ActiveProcessors = KeActiveProcessors; 02169 for (CurrentAffinity = 1; ActiveProcessors; CurrentAffinity <<= 1) { 02170 02171 if (ActiveProcessors & CurrentAffinity) { 02172 ActiveProcessors &= ~CurrentAffinity; 02173 02174 // 02175 // Run this code on each processor. 02176 // 02177 02178 KeSetSystemAffinityThread(CurrentAffinity); 02179 02180 // 02181 // Raise IRQL and lock dispatcher database. 02182 // 02183 02184 KiLockDispatcherDatabase(&OldIrql); 02185 02186 // 02187 // Make the trap 07 IDT entry point at the passed-in handler 02188 // 02189 02190 KiSetHandlerAddressToIDT(I386_80387_NP_VECTOR, HandlerAddress); 02191 KeGetPcr()->IDT[I386_80387_NP_VECTOR].Selector = KGDT_R3_CODE; 02192 KeGetPcr()->IDT[I386_80387_NP_VECTOR].Access = TRAP332_GATE; 02193 02194 02195 // 02196 // Unlock dispatcher database and lower IRQL to its previous value. 02197 // 02198 02199 KiUnlockDispatcherDatabase(OldIrql); 02200 } 02201 } 02202 02203 // 02204 // Move any entries from ..\System\FloatingPointProcessor to 02205 // ..\System\DisabledFloatingPointProcessor. 02206 // 02207 02208 // 02209 // Open system tree 02210 // 02211 02212 InitializeObjectAttributes( 02213 &ObjectAttributes, 02214 &CmRegistryMachineHardwareDescriptionSystemName, 02215 OBJ_CASE_INSENSITIVE, 02216 NULL, 02217 NULL 02218 ); 02219 02220 Status = ZwOpenKey( &SystemHandle, 02221 KEY_ALL_ACCESS, 02222 &ObjectAttributes 02223 ); 02224 02225 if (NT_SUCCESS(Status)) { 02226 02227 // 02228 // Open FloatingPointProcessor key 02229 // 02230 02231 InitializeObjectAttributes( 02232 &ObjectAttributes, 02233 &CmTypeName[FloatingPointProcessor], 02234 OBJ_CASE_INSENSITIVE, 02235 SystemHandle, 02236 NULL 02237 ); 02238 02239 Status = ZwOpenKey ( &SourceHandle, 02240 KEY_ALL_ACCESS, 02241 &ObjectAttributes 02242 ); 02243 02244 if (NT_SUCCESS(Status)) { 02245 02246 // 02247 // Create DisabledFloatingPointProcessor key 02248 // 02249 02250 RtlInitUnicodeString ( 02251 &unicodeString, 02252 CmDisabledFloatingPointProcessor 02253 ); 02254 02255 InitializeObjectAttributes( 02256 &ObjectAttributes, 02257 &unicodeString, 02258 OBJ_CASE_INSENSITIVE, 02259 SystemHandle, 02260 NULL 02261 ); 02262 02263 Status = ZwCreateKey( &DestHandle, 02264 KEY_ALL_ACCESS, 02265 &ObjectAttributes, 02266 0, 02267 NULL, 02268 REG_OPTION_VOLATILE, 02269 &disposition 02270 ); 02271 02272 if (NT_SUCCESS(Status)) { 02273 02274 // 02275 // Move it 02276 // 02277 02278 KiMoveRegTree (SourceHandle, DestHandle); 02279 ZwClose (DestHandle); 02280 } 02281 ZwClose (SourceHandle); 02282 } 02283 ZwClose (SystemHandle); 02284 } 02285 } 02286 02287 // 02288 // Set affinity back to the original value. 02289 // 02290 02291 KeRevertToUserAffinityThread(); 02292 }

VOID Ki386EnableFxsr IN volatile PLONG  Number  ) 
 

Referenced by KiInitMachineDependent().

VOID Ki386EnableGlobalPage IN volatile PLONG  Number  ) 
 

Referenced by KiInitMachineDependent().

VOID Ki386EnableXMMIExceptions IN volatile PLONG  Number  ) 
 

Referenced by KiInitMachineDependent().

VOID Ki386UseSynchronousTbFlush IN volatile PLONG  Number  ) 
 

VOID KiAmdK6InitializeMTRR VOID   ) 
 

Definition at line 168 of file mtrramd.c.

References AMDK6_MTRR_MSR, AMDK6_MTRR_TYPE_DISABLED, AMDK6_REGION_UNUSED, AmdK6RegionCount, AmdK6Regions, AmdMtrrHwUsageCount, _AMDK6_MTRR_REGION::BaseAddress, DBGMSG, KeAcquireSpinLock, KeInitializeSpinLock(), KeReleaseSpinLock(), KiAmdK6Mtrr, KiAmdK6MTRRAddRegionFromHW(), KiRangeLock, MAX_K6_REGIONS, RDMSR(), _AMDK6_MTRR_REGION::RegionFlags, and _AMDK6_MTRR_MSR_IMAGE::u.

00171 { 00172 ULONG i; 00173 KIRQL OldIrql; 00174 00175 DBGMSG("KiAmdK6InitializeMTRR: Initializing K6 MTRR support\n"); 00176 00177 KiAmdK6Mtrr.u.hw.mtrr0.type = AMDK6_MTRR_TYPE_DISABLED; 00178 KiAmdK6Mtrr.u.hw.mtrr1.type = AMDK6_MTRR_TYPE_DISABLED; 00179 AmdK6RegionCount = MAX_K6_REGIONS; 00180 AmdMtrrHwUsageCount = 0; 00181 00182 // 00183 // Set all regions to free. 00184 // 00185 00186 for (i = 0; i < AmdK6RegionCount; i++) { 00187 AmdK6Regions[i].BaseAddress = AMDK6_REGION_UNUSED; 00188 AmdK6Regions[i].RegionFlags = 0; 00189 } 00190 00191 // 00192 // Initialize the spin lock. 00193 // 00194 // N.B. Normally this is done by KiInitializeMTRR but that 00195 // routine is not called in the AMD K6 case. 00196 // 00197 00198 KeInitializeSpinLock (&KiRangeLock); 00199 00200 // 00201 // Read the MTRR registers to see if the BIOS has set them up. 00202 // If so, add entries to the region table and adjust the usage 00203 // count. Serialize the region table. 00204 // 00205 00206 KeAcquireSpinLock (&KiRangeLock, &OldIrql); 00207 00208 KiAmdK6Mtrr.u.QuadPart = RDMSR (AMDK6_MTRR_MSR); 00209 00210 // 00211 // Check MTRR0 first. 00212 // 00213 00214 KiAmdK6MTRRAddRegionFromHW(KiAmdK6Mtrr.u.hw.mtrr0); 00215 00216 // 00217 // Now check MTRR1. 00218 // 00219 00220 KiAmdK6MTRRAddRegionFromHW(KiAmdK6Mtrr.u.hw.mtrr1); 00221 00222 // 00223 // Release the locks. 00224 // 00225 00226 KeReleaseSpinLock (&KiRangeLock, OldIrql); 00227 }

VOID KiGetCacheInformation VOID   ) 
 

Definition at line 1509 of file kernlini.c.

References ASSERT, CPU_AMD, CPU_INTEL, CPU_NONE, CPUID(), CPUID_REG_COUNT, FALSE, KeGetPcr, KiGetCpuVendor(), and TRUE.

Referenced by KiInitializeKernel().

01512 { 01513 #define CPUID_REG_COUNT 4 01514 ULONG CpuidData[CPUID_REG_COUNT]; 01515 01516 ULONG CpuVendor; 01517 PKPCR Pcr; 01518 01519 // 01520 // Set default. 01521 // 01522 01523 Pcr = KeGetPcr(); 01524 01525 Pcr->SecondLevelCacheSize = 0; 01526 01527 // 01528 // Determine the processor manufacturer 01529 // 01530 01531 CpuVendor = KiGetCpuVendor(); 01532 01533 if (CpuVendor == CPU_NONE) { 01534 return; 01535 } 01536 01537 // 01538 // Obtain Cache size information for those processors on which 01539 // we know how. 01540 // 01541 01542 switch (CpuVendor) { 01543 case CPU_INTEL: 01544 01545 CPUID(0, CpuidData, CpuidData+1, CpuidData+2, CpuidData+3); 01546 01547 // 01548 // Check this processor supports CPUID function 2 which is the 01549 // one that returns cache size info. 01550 // 01551 01552 if (CpuidData[0] >= 2) { 01553 01554 // 01555 // The above returns a series of bytes. (In EAX, EBX, ECX 01556 // and EDX). The least significant byte (of EAX) gives the 01557 // number of times CPUID(2 ...) should be issued to return 01558 // the complete set of data. The bytes are self describing 01559 // data. 01560 // 01561 // In particular, the bytes describing the L2 cache size 01562 // will be in the following set (and meaning) 01563 // 01564 // 0x40 0 bytes 01565 // 0x41 128K bytes 01566 // 0x42 256K bytes 01567 // 0x43 512K bytes 01568 // 0x44 1024K bytes 01569 // 0x45 2048K bytes 01570 // 0x46 4096K bytes 01571 // 01572 // I am extrapolating the above as anything in the range 01573 // 0x41 thru 0x4f can be computed as 01574 // 01575 // 128KB << (descriptor - 0x41) 01576 // 01577 // The Intel folks say keep it to a reasonable upper bound, 01578 // eg 49. 01579 // 01580 // N.B. the range 0x80 .. 0x86 indicates the same cache 01581 // sizes but 8 way associative. 01582 // 01583 // Also, the most significant bit of each register indicates 01584 // whether not the register contains valid information. 01585 // 0 == Valid, 1 == InValid. 01586 // 01587 01588 ULONG CpuidIterations; 01589 ULONG i; 01590 ULONG CpuidReg; 01591 01592 BOOLEAN FirstPass = TRUE; 01593 01594 do { 01595 CPUID(2, CpuidData, CpuidData+1, CpuidData+2, CpuidData+3); 01596 01597 if (FirstPass) { 01598 01599 // 01600 // Get the iteration count from the first byte 01601 // of the returned data then replace that byte 01602 // with 0 (a null descriptor). 01603 // 01604 01605 CpuidIterations = CpuidData[0] & 0xff; 01606 CpuidData[0] &= 0xffffff00; 01607 01608 FirstPass = FALSE; 01609 } 01610 01611 for (i = 0; i < CPUID_REG_COUNT; i++) { 01612 01613 CpuidReg = CpuidData[i]; 01614 01615 if (CpuidReg & 0x80000000) { 01616 01617 // 01618 // Register doesn't contain valid data, 01619 // skip it. 01620 // 01621 01622 continue; 01623 } 01624 01625 while (CpuidReg) { 01626 01627 // 01628 // Get LS Byte from this DWORD and remove the 01629 // byte. 01630 // 01631 01632 UCHAR Descriptor = (UCHAR)(CpuidReg & 0xff); 01633 CpuidReg >>= 8; 01634 01635 if (Descriptor == 0) { 01636 01637 // 01638 // NULL descriptor 01639 // 01640 01641 continue; 01642 } 01643 01644 if (((Descriptor > 0x40) && (Descriptor <= 0x49)) || 01645 ((Descriptor > 0x80) && (Descriptor <= 0x89))) { 01646 01647 // 01648 // L2 descriptor. 01649 // 01650 01651 Descriptor &= 0x0f; 01652 01653 // 01654 // Assert the descriptor is in the range we 01655 // officially know about. If this hits on 01656 // a checked build, check with Intel about 01657 // the interpretation. 01658 // 01659 01660 ASSERT(Descriptor <= 0x6); 01661 01662 Pcr->SecondLevelCacheSize = 0x10000 << Descriptor; 01663 } 01664 01665 // 01666 // else if (do other descriptors) 01667 // 01668 01669 } // while more bytes in this register 01670 01671 } // for each register 01672 01673 // 01674 // Note: Always run thru all iterations indicated by 01675 // the first to ensure a subsequent call won't start 01676 // part way thru. 01677 // 01678 01679 } while (--CpuidIterations); 01680 } 01681 break; 01682 case CPU_AMD: 01683 break; 01684 } 01685 #undef CPUID_REG_COUNT 01686 }

ULONG KiGetCpuVendor VOID   ) 
 

Definition at line 1110 of file kernlini.c.

References Buffer, CmpAmdID, CmpCyrixID, CmpIntelID, CPU_AMD, CPU_CYRIX, CPU_INTEL, CPU_NONE, CPU_UNKNOWN, CPUID(), and KeGetCurrentPrcb.

Referenced by KiGetCacheInformation().

01116 : 01117 01118 (Try to) Determine the manufacturer of this processor based on 01119 data returned by the CPUID instruction (if present). 01120 01121 Arguments: 01122 01123 None. 01124 01125 Return Value: 01126 01127 One of the members of the enumeration CPU_VENDORS (defined above). 01128 01129 --*/ 01130 { 01131 PKPRCB Prcb; 01132 ULONG Junk; 01133 ULONG Buffer[4]; 01134 01135 Prcb = KeGetCurrentPrcb(); 01136 Prcb->VendorString[0] = 0; 01137 01138 if (!Prcb->CpuID) { 01139 return CPU_NONE; 01140 } 01141 01142 CPUID(0, &Junk, Buffer+0, Buffer+2, Buffer+1); 01143 Buffer[3] = 0; 01144 01145 // 01146 // Copy vendor string to Prcb for debugging (ensure it's NULL 01147 // terminated). 01148 // 01149 01150 RtlCopyMemory( 01151 Prcb->VendorString, 01152 Buffer, 01153 sizeof(Prcb->VendorString) - 1 01154 ); 01155 01156 Prcb->VendorString[sizeof(Prcb->VendorString) - 1] = '\0'; 01157 01158 if (strcmp((PVOID)Buffer, CmpIntelID) == 0) { 01159 return CPU_INTEL; 01160 } else if (strcmp((PVOID)Buffer, CmpAmdID) == 0) { 01161 return CPU_AMD; 01162 } else if (strcmp((PVOID)Buffer, CmpCyrixID) == 0) { 01163 return CPU_CYRIX; 01164 } 01165 return CPU_UNKNOWN; 01166 }

ULONG KiGetFeatureBits VOID   ) 
 

Referenced by KiInitializeKernel().

VOID KiI386PentiumLockErrataFixup VOID   ) 
 

Definition at line 2460 of file kernlini.c.

References ASSERT, IDT_SKIP, KeGetPcr, KiDisableInterrupts(), KiRestoreInterrupts(), MmAllocateIndependentPages(), MmSetPageProtection(), PAGE_SIZE, and Status.

Referenced by KiInitMachineDependent().

02466 : 02467 02468 This routine is called once on every processor when 02469 KiI386PentiumLockErrataPresent is TRUE. 02470 02471 This routine replaces the local IDT with an IDT that has the first 7 IDT 02472 entries on their own page and returns the first page to the caller to 02473 be marked as read-only. This causes the processor to trap-0e fault when 02474 the errata occurs. Special code in the trap-0e handler detects the 02475 problem and performs the proper fixup. 02476 02477 Arguments: 02478 02479 FixupPage - Returns a virtual address of a page to be marked read-only 02480 02481 Return Value: 02482 02483 None. 02484 02485 --*/ 02486 02487 { 02488 KDESCRIPTOR IdtDescriptor; 02489 ULONG OrginalBase; 02490 PUCHAR NewBase, BasePage; 02491 BOOLEAN Enable; 02492 BOOLEAN Status; 02493 02494 02495 #define IDT_SKIP (7 * sizeof (KIDTENTRY)) 02496 02497 // 02498 // Allocate memory for a new copy of the processors IDT 02499 // 02500 02501 BasePage = MmAllocateIndependentPages (2*PAGE_SIZE); 02502 02503 // 02504 // The IDT base is such that the first 7 entries are on the 02505 // first (read-only) page, and the remaining entries are on the 02506 // second (read-write) page 02507 // 02508 02509 NewBase = BasePage + PAGE_SIZE - IDT_SKIP; 02510 02511 // 02512 // Disable interrupts on this processor while updating the IDT base 02513 // 02514 02515 Enable = KiDisableInterrupts(); 02516 02517 // 02518 // Copy Old IDT to new IDT 02519 // 02520 02521 _asm { 02522 sidt IdtDescriptor.Limit 02523 } 02524 02525 RtlMoveMemory ((PVOID) NewBase, 02526 (PVOID) IdtDescriptor.Base, 02527 IdtDescriptor.Limit + 1 02528 ); 02529 02530 IdtDescriptor.Base = (ULONG) NewBase; 02531 02532 // 02533 // Set the new IDT 02534 // 02535 02536 _asm { 02537 lidt IdtDescriptor.Limit 02538 } 02539 02540 // 02541 // Update the PCR 02542 // 02543 02544 KeGetPcr()->IDT = (PKIDTENTRY) NewBase; 02545 02546 // 02547 // Restore interrupts 02548 // 02549 02550 KiRestoreInterrupts(Enable); 02551 02552 // 02553 // Mark the first page which contains IDT entries 0-6 as read-only 02554 // 02555 02556 Status = MmSetPageProtection (BasePage, PAGE_SIZE, PAGE_READONLY); 02557 ASSERT (Status); 02558 } }

VOID KiInitializeDblFaultTSS IN PKTSS  Tss,
IN ULONG  Stack,
IN PKGDTENTRY  TssDescriptor
 

VOID KiInitializeKernel IN PKPROCESS  Process,
IN PKTHREAD  Thread,
IN PVOID  IdleStack,
IN PKPRCB  Prcb,
IN CCHAR  Number,
PLOADER_PARAMETER_BLOCK  LoaderBlock
 

Definition at line 246 of file kernlini.c.

References APC_LEVEL, CcMasterSpinLock, CcVacbSpinLock, DISPATCH_LEVEL, ExAllocatePoolWithTag, EXCEPTION_EXECUTE_HANDLER, ExpInitializeExecutive(), FALSE, HIGH_LEVEL, Index, KeBugCheck(), KeBugCheckEx(), KeFeatureBits, KeGetPcr, KeI386CpuStep, KeI386CpuType, KeI386FxsrPresent, KeI386NpxPresent, KeI386XMMIPresent, KeInitializeProcess(), KeInitializeSpinLock(), KeInitializeThread(), KeLowerIrql(), KeMaximumIncrement, KeProcessorArchitecture, KeProcessorLevel, KeProcessorRevision, KeRaiseIrql(), KeReleaseSpinLock(), KeSetPriorityThread(), KF_3DNOW, KF_CMPXCHG8B, KF_FXSR, KF_GLOBAL_PAGE, KF_MMX, KF_MTRR, KF_PAT, KF_RDTSC, KF_XMMI, Ki386IopmSaveArea, Ki486CompatibilityLock, KiAdjustDpcThreshold, KiBootFeatureBits, KiComputeReciprocal(), KiContextSwapLock, KiDispatcherLock, KiFreezeExecutionLock, KiGetCacheInformation(), KiGetFeatureBits(), KiIdleSummary, KiInitSystem(), KiIsNpxPresent(), KiMaximumDpcQueueDepth, KiMinimumDpcRate, KiQueuedSpinLockContext, KiSetCR0Bits(), KiSetProcessorType(), KiTimeIncrementReciprocal, KiTimeIncrementShiftCount, KiTryToAcquireQueuedSpinLock(), LockQueueContextSwapLock, LockQueueDispatcherLock, LockQueueMasterLock, LockQueuePfnLock, LockQueueSystemSpaceLock, LockQueueVacbLock, MmCreateKernelStack(), MmPfnLock, MmSystemSpaceLock, NULL, PAGE_SIZE, PagedPool, PKSTART_ROUTINE, PKSYSTEM_ROUTINE, PoInitializePrcb(), _LOADER_PARAMETER_BLOCK::Prcb, RET, Running, SetMember, TRUE, and USHORT.

00257 : 00258 00259 This function gains control after the system has been bootstrapped and 00260 before the system has been initialized. Its function is to initialize 00261 the kernel data structures, initialize the idle thread and process objects, 00262 initialize the processor control block, call the executive initialization 00263 routine, and then return to the system startup routine. This routine is 00264 also called to initialize the processor specific structures when a new 00265 processor is brought on line. 00266 00267 Arguments: 00268 00269 Process - Supplies a pointer to a control object of type process for 00270 the specified processor. 00271 00272 Thread - Supplies a pointer to a dispatcher object of type thread for 00273 the specified processor. 00274 00275 IdleStack - Supplies a pointer the base of the real kernel stack for 00276 idle thread on the specified processor. 00277 00278 Prcb - Supplies a pointer to a processor control block for the specified 00279 processor. 00280 00281 Number - Supplies the number of the processor that is being 00282 initialized. 00283 00284 LoaderBlock - Supplies a pointer to the loader parameter block. 00285 00286 Return Value: 00287 00288 None. 00289 00290 --*/ 00291 00292 { 00293 LONG Index; 00294 ULONG DirectoryTableBase[2]; 00295 KIRQL OldIrql; 00296 PKPCR Pcr; 00297 BOOLEAN NpxFlag; 00298 BOOLEAN FxsrPresent; 00299 BOOLEAN XMMIPresent; 00300 ULONG FeatureBits; 00301 00302 KiSetProcessorType(); 00303 KiSetCR0Bits(); 00304 NpxFlag = KiIsNpxPresent(); 00305 00306 Pcr = KeGetPcr(); 00307 00308 // 00309 // Initialize DPC listhead and lock. 00310 // 00311 00312 InitializeListHead(&Prcb->DpcListHead); 00313 KeInitializeSpinLock(&Prcb->DpcLock); 00314 Prcb->DpcRoutineActive = 0; 00315 Prcb->DpcQueueDepth = 0; 00316 Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth; 00317 Prcb->MinimumDpcRate = KiMinimumDpcRate; 00318 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold; 00319 PoInitializePrcb (Prcb); 00320 00321 // 00322 // Check for unsupported processor revision 00323 // 00324 00325 if (Prcb->CpuType == 3) { 00326 KeBugCheckEx(UNSUPPORTED_PROCESSOR,0x386,0,0,0); 00327 } 00328 00329 // 00330 // Get the processor FeatureBits for this processor. 00331 // 00332 00333 FeatureBits = KiGetFeatureBits(); 00334 Prcb->FeatureBits = FeatureBits; 00335 00336 // 00337 // Get processor Cache Size information. 00338 // 00339 00340 KiGetCacheInformation(); 00341 00342 // 00343 // initialize the per processor lock queue entry for implemented locks. 00344 // 00345 00346 #if !defined(NT_UP) 00347 00348 Prcb->LockQueue[LockQueueDispatcherLock].Next = NULL; 00349 Prcb->LockQueue[LockQueueDispatcherLock].Lock = &KiDispatcherLock; 00350 Prcb->LockQueue[LockQueueContextSwapLock].Next = NULL; 00351 Prcb->LockQueue[LockQueueContextSwapLock].Lock = &KiContextSwapLock; 00352 Prcb->LockQueue[LockQueuePfnLock].Next = NULL; 00353 Prcb->LockQueue[LockQueuePfnLock].Lock = &MmPfnLock; 00354 Prcb->LockQueue[LockQueueSystemSpaceLock].Next = NULL; 00355 Prcb->LockQueue[LockQueueSystemSpaceLock].Lock = &MmSystemSpaceLock; 00356 Prcb->LockQueue[LockQueueMasterLock].Next = NULL; 00357 Prcb->LockQueue[LockQueueMasterLock].Lock = &CcMasterSpinLock; 00358 Prcb->LockQueue[LockQueueVacbLock].Next = NULL; 00359 Prcb->LockQueue[LockQueueVacbLock].Lock = &CcVacbSpinLock; 00360 00361 #endif 00362 00363 // 00364 // If the initial processor is being initialized, then initialize the 00365 // per system data structures. 00366 // 00367 00368 if (Number == 0) { 00369 00370 // 00371 // Initial setting for global Cpu & Stepping levels 00372 // 00373 00374 KeI386NpxPresent = NpxFlag; 00375 KeI386CpuType = Prcb->CpuType; 00376 KeI386CpuStep = Prcb->CpuStep; 00377 00378 KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL; 00379 KeProcessorLevel = (USHORT)Prcb->CpuType; 00380 if (Prcb->CpuID == 0) { 00381 KeProcessorRevision = 0xFF00 | 00382 (((Prcb->CpuStep >> 4) + 0xa0 ) & 0x0F0) | 00383 (Prcb->CpuStep & 0xf); 00384 } else { 00385 KeProcessorRevision = Prcb->CpuStep; 00386 } 00387 00388 KeFeatureBits = FeatureBits; 00389 00390 KeI386FxsrPresent = ((KeFeatureBits & KF_FXSR) ? TRUE:FALSE); 00391 00392 KeI386XMMIPresent = ((KeFeatureBits & KF_XMMI) ? TRUE:FALSE); 00393 00394 // 00395 // If cmpxchg8b was available at boot, verify its still available 00396 // 00397 00398 if ((KiBootFeatureBits & KF_CMPXCHG8B) && !(KeFeatureBits & KF_CMPXCHG8B)) { 00399 KeBugCheckEx (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED, KF_CMPXCHG8B, 0, 0, 0); 00400 } 00401 00402 // 00403 // Lower IRQL to APC level. 00404 // 00405 00406 KeLowerIrql(APC_LEVEL); 00407 00408 00409 // 00410 // Initialize kernel internal spinlocks 00411 // 00412 00413 KeInitializeSpinLock(&KiContextSwapLock); 00414 KeInitializeSpinLock(&KiDispatcherLock); 00415 KeInitializeSpinLock(&KiFreezeExecutionLock); 00416 00417 // 00418 // Initialize 486 compatibility lock 00419 // 00420 00421 KeInitializeSpinLock(&Ki486CompatibilityLock); 00422 00423 #if !defined(NT_UP) 00424 00425 // 00426 // During Text Mode setup, it is possible the system is 00427 // running with an MP kernel and a UP HAL. On X86 systems, 00428 // spinlocks are implemented in both the kernel and the HAL 00429 // with the verisons that alter IRQL in the HAL. If the 00430 // HAL is UP, it will not actually acquire/release locks 00431 // while the MP kernel will which will cause the system to 00432 // hang (or crash). As this can only occur during text 00433 // mode setup, we will detect the situation and disable 00434 // the kernel only versions of queued spinlocks if the HAL 00435 // is UP (and the kernel MP). 00436 // 00437 // We need to patch 3 routines, two of them are void and 00438 // the other returns a boolean (must be true (and ZF must be 00439 // clear) in a UP case). 00440 // 00441 // Determine if the HAL us UP by acquiring the dispatcher 00442 // lock and examining it to see if the HAL actually did 00443 // anything to it. 00444 // 00445 00446 OldIrql = KfAcquireSpinLock(&KiDispatcherLock); 00447 if (KiDispatcherLock == 0) { 00448 00449 // 00450 // KfAcquireSpinLock is in the HAL and it did not 00451 // change the value of the lock. This is a UP HAL. 00452 // 00453 00454 extern UCHAR KiTryToAcquireQueuedSpinLockUP; 00455 PUCHAR PatchTarget, PatchSource; 00456 UCHAR Byte; 00457 00458 #define RET 0xc3 00459 00460 *(PUCHAR)(KiAcquireQueuedSpinLock) = RET; 00461 *(PUCHAR)(KiReleaseQueuedSpinLock) = RET; 00462 00463 // 00464 // Copy the UP version of KiTryToAcquireQueuedSpinLock 00465 // over the top of the MP versin. 00466 // 00467 00468 PatchSource = &(KiTryToAcquireQueuedSpinLockUP); 00469 PatchTarget = (PUCHAR)(KiTryToAcquireQueuedSpinLock); 00470 00471 do { 00472 Byte = *PatchSource++; 00473 *PatchTarget++ = Byte; 00474 } while (Byte != RET); 00475 00476 #undef RET 00477 } 00478 KeReleaseSpinLock(&KiDispatcherLock, OldIrql); 00479 00480 #endif 00481 00482 // 00483 // Performance architecture independent initialization. 00484 // 00485 00486 KiInitSystem(); 00487 00488 // 00489 // Initialize idle thread process object and then set: 00490 // 00491 // 1. all the quantum values to the maximum possible. 00492 // 2. the process in the balance set. 00493 // 3. the active processor mask to the specified process. 00494 // 00495 00496 DirectoryTableBase[0] = 0; 00497 DirectoryTableBase[1] = 0; 00498 KeInitializeProcess(Process, 00499 (KPRIORITY)0, 00500 (KAFFINITY)(0xffffffff), 00501 &DirectoryTableBase[0], 00502 FALSE); 00503 00504 Process->ThreadQuantum = MAXCHAR; 00505 00506 } else { 00507 00508 // 00509 // Adjust global cpu setting to represent lowest of all processors 00510 // 00511 00512 FxsrPresent = ((FeatureBits & KF_FXSR) ? TRUE:FALSE); 00513 if (FxsrPresent != KeI386FxsrPresent) { 00514 // 00515 // FXSR support must be available on all processors or on none 00516 // 00517 KeBugCheckEx (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED, KF_FXSR, 0, 0, 0); 00518 } 00519 00520 XMMIPresent = ((FeatureBits & KF_XMMI) ? TRUE:FALSE); 00521 if (XMMIPresent != KeI386XMMIPresent) { 00522 // 00523 // XMMI support must be available on all processors or on none 00524 // 00525 KeBugCheckEx (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED, KF_XMMI, 0, 0, 0); 00526 } 00527 00528 if (NpxFlag != KeI386NpxPresent) { 00529 // 00530 // NPX support must be available on all processors or on none 00531 // 00532 00533 KeBugCheckEx (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED, 0x387, 0, 0, 0); 00534 } 00535 00536 if ((ULONG)(Prcb->CpuType) != KeI386CpuType) { 00537 00538 if ((ULONG)(Prcb->CpuType) < KeI386CpuType) { 00539 00540 // 00541 // What is the lowest CPU type 00542 // 00543 00544 KeI386CpuType = (ULONG)Prcb->CpuType; 00545 KeProcessorLevel = (USHORT)Prcb->CpuType; 00546 } 00547 } 00548 00549 if ((KiBootFeatureBits & KF_CMPXCHG8B) && !(FeatureBits & KF_CMPXCHG8B)) { 00550 // 00551 // cmpxchg8b must be available on all processors, if installed at boot 00552 // 00553 00554 KeBugCheckEx (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED, KF_CMPXCHG8B, 0, 0, 0); 00555 } 00556 00557 if ((KeFeatureBits & KF_GLOBAL_PAGE) && !(FeatureBits & KF_GLOBAL_PAGE)) { 00558 // 00559 // Global page support must be available on all processors, if on boot processor 00560 // 00561 00562 KeBugCheckEx (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED, KF_GLOBAL_PAGE, 0, 0, 0); 00563 } 00564 00565 if ((KeFeatureBits & KF_PAT) && !(FeatureBits & KF_PAT)) { 00566 // 00567 // PAT must be available on all processors, if on boot processor 00568 // 00569 00570 KeBugCheckEx (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED, KF_PAT, 0, 0, 0); 00571 } 00572 00573 if ((KeFeatureBits & KF_MTRR) && !(FeatureBits & KF_MTRR)) { 00574 // 00575 // MTRR must be available on all processors, if on boot processor 00576 // 00577 00578 KeBugCheckEx (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED, KF_MTRR, 0, 0, 0); 00579 } 00580 00581 // 00582 // Use lowest stepping value 00583 // 00584 00585 if (Prcb->CpuStep < KeI386CpuStep) { 00586 KeI386CpuStep = Prcb->CpuStep; 00587 if (Prcb->CpuID == 0) { 00588 KeProcessorRevision = 0xFF00 | 00589 ((Prcb->CpuStep >> 8) + 'A') | 00590 (Prcb->CpuStep & 0xf); 00591 } else { 00592 KeProcessorRevision = Prcb->CpuStep; 00593 } 00594 } 00595 00596 // 00597 // Use subset of all NT feature bits available on each processor 00598 // 00599 00600 KeFeatureBits &= FeatureBits; 00601 00602 // 00603 // Lower IRQL to DISPATCH level. 00604 // 00605 00606 KeLowerIrql(DISPATCH_LEVEL); 00607 00608 } 00609 00610 // 00611 // Update processor features 00612 // 00613 00614 SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = 00615 (KeFeatureBits & KF_MMX) ? TRUE : FALSE; 00616 00617 SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] = 00618 (KeFeatureBits & KF_CMPXCHG8B) ? TRUE : FALSE; 00619 00620 SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] = 00621 ((KeFeatureBits & KF_FXSR) && (KeFeatureBits & KF_XMMI)) ? TRUE : FALSE; 00622 00623 SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] = 00624 (KeFeatureBits & KF_3DNOW) ? TRUE : FALSE; 00625 00626 SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = 00627 (KeFeatureBits & KF_RDTSC) ? TRUE : FALSE; 00628 // 00629 // Initialize idle thread object and then set: 00630 // 00631 // 1. the initial kernel stack to the specified idle stack. 00632 // 2. the next processor number to the specified processor. 00633 // 3. the thread priority to the highest possible value. 00634 // 4. the state of the thread to running. 00635 // 5. the thread affinity to the specified processor. 00636 // 6. the specified processor member in the process active processors 00637 // set. 00638 // 00639 00640 KeInitializeThread(Thread, (PVOID)((ULONG)IdleStack), 00641 (PKSYSTEM_ROUTINE)NULL, (PKSTART_ROUTINE)NULL, 00642 (PVOID)NULL, (PCONTEXT)NULL, (PVOID)NULL, Process); 00643 Thread->NextProcessor = Number; 00644 Thread->Priority = HIGH_PRIORITY; 00645 Thread->State = Running; 00646 Thread->Affinity = (KAFFINITY)(1<<Number); 00647 Thread->WaitIrql = DISPATCH_LEVEL; 00648 SetMember(Number, Process->ActiveProcessors); 00649 00650 // 00651 // Initialize the processor block. (Note that some fields have been 00652 // initialized at KiInitializePcr(). 00653 // 00654 00655 Prcb->CurrentThread = Thread; 00656 Prcb->NextThread = (PKTHREAD)NULL; 00657 Prcb->IdleThread = Thread; 00658 Pcr->NtTib.StackBase = Thread->InitialStack; 00659 00660 // 00661 // call the executive initialization routine. 00662 // 00663 00664 try { 00665 ExpInitializeExecutive(Number, LoaderBlock); 00666 00667 } except (EXCEPTION_EXECUTE_HANDLER) { 00668 KeBugCheck (PHASE0_EXCEPTION); 00669 } 00670 00671 // 00672 // If the initial processor is being initialized, then compute the 00673 // timer table reciprocal value and reset the PRCB values for the 00674 // controllable DPC behavior in order to reflect any registry 00675 // overrides. 00676 // 00677 00678 if (Number == 0) { 00679 KiTimeIncrementReciprocal = KiComputeReciprocal((LONG)KeMaximumIncrement, 00680 &KiTimeIncrementShiftCount); 00681 00682 Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth; 00683 Prcb->MinimumDpcRate = KiMinimumDpcRate; 00684 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold; 00685 } 00686 00687 if (Number == 0) { 00688 00689 // 00690 // Processor 0's DPC stack was temporarily allocated on 00691 // the Double Fault Stack, switch to a proper kernel 00692 // stack now. 00693 // 00694 00695 PVOID DpcStack; 00696 00697 DpcStack = MmCreateKernelStack(FALSE); 00698 00699 if (DpcStack == NULL) { 00700 KeBugCheckEx(NO_PAGES_AVAILABLE, 1, 0, 0, 0); 00701 } 00702 Prcb->DpcStack = DpcStack; 00703 00704 // 00705 // Allocate 8k IOPM bit map saved area to allow BiosCall swap 00706 // bit maps. 00707 // 00708 00709 Ki386IopmSaveArea = ExAllocatePoolWithTag(PagedPool, 00710 PAGE_SIZE * 2, 00711 ' eK'); 00712 if (Ki386IopmSaveArea == NULL) { 00713 KeBugCheckEx(NO_PAGES_AVAILABLE, 2, PAGE_SIZE * 2, 0, 0); 00714 } 00715 } 00716 00717 // 00718 // Set the priority of the specified idle thread to zero, set appropriate 00719 // member in KiIdleSummary and return to the system start up routine. 00720 // 00721 00722 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 00723 KeSetPriorityThread(Thread, (KPRIORITY)0); 00724 00725 // 00726 // if a thread has not been selected to run on the current processors, 00727 // check to see if there are any ready threads; otherwise add this 00728 // processors to the IdleSummary 00729 // 00730 00731 KiAcquireQueuedSpinLock(KiQueuedSpinLockContext(LockQueueDispatcherLock)); 00732 if (Prcb->NextThread == (PKTHREAD)NULL) { 00733 SetMember(Number, KiIdleSummary); 00734 } 00735 KiReleaseQueuedSpinLock(KiQueuedSpinLockContext(LockQueueDispatcherLock)); 00736 00737 KeRaiseIrql(HIGH_LEVEL, &OldIrql); 00738 00739 // 00740 // This processor has initialized 00741 // 00742 00743 LoaderBlock->Prcb = (ULONG)NULL; 00744 00745 return; 00746 }

VOID KiInitializeMTRR IN BOOLEAN  LastProcessor  ) 
 

Definition at line 275 of file mtrr.c.

References _RANGE_INFO::Capabilities, DBGMSG, _RANGE_INFO::Default, _RANGE_INFO::DefaultCachedType, ExAllocatePoolWithTag, ExFreePool(), FALSE, GROW_RANGE_TABLE, Index, KeFeatureBits, KeGetCurrentPrcb, KeGetPcr, KeInitializeSpinLock(), KF_MTRR, KiAddRange(), KiMaskToLength(), KiRangeInfo, KiRangeLock, MASK_OVERFLOW_MASK, _RANGE_INFO::MaxRange, MTRR_CAPABILITIES, MTRR_DEFAULT, MTRR_MASK_BASE, MTRR_MASK_MASK, MTRR_MSR_CAPABILITIES, MTRR_MSR_DEFAULT, MTRR_MSR_VARIABLE_BASE, MTRR_MSR_VARIABLE_MASK, MTRR_TYPE_MAX, MTRR_TYPE_UC, MTRR_TYPE_WB, MTRR_TYPE_WT, MTRR_VARIABLE_BASE, MTRR_VARIABLE_MASK, _RANGE_INFO::MtrrWorkaround, NonPagedPool, _RANGE_INFO::NoRange, NT_SUCCESS, NTSTATUS(), NULL, ONE_RANGE, _RANGE_INFO::Ranges, _RANGE_INFO::RangesValid, RDMSR(), Size, Status, TRUE, _MTRR_VARIABLE_MASK::u, _MTRR_VARIABLE_BASE::u, _MTRR_DEFAULT::u, and _MTRR_CAPABILITIES::u.

00280 : 00281 00282 Called to incrementally initialize the physical range 00283 database feature. First processor's MTRR set is read into the 00284 physical range database. 00285 00286 Arguments: 00287 00288 LastProcessor - If set this is the last processor to execute this routine 00289 such that when this processor finishes, the initialization is complete. 00290 00291 Return Value: 00292 00293 None - if there was a problem the function 00294 KeSetPhysicalCacheTypeRange type is disabled. 00295 00296 --*/ 00297 { 00298 BOOLEAN Status; 00299 ULONG Index, Size; 00300 MTRR_DEFAULT Default; 00301 MTRR_CAPABILITIES Capabilities; 00302 NEW_RANGE NewRange; 00303 MTRR_VARIABLE_BASE MtrrBase; 00304 MTRR_VARIABLE_MASK MtrrMask; 00305 ULONGLONG Base, Mask, Length; 00306 BOOLEAN RemoveThisType[MTRR_TYPE_MAX]; 00307 NTSTATUS NtStatus; 00308 PKPRCB Prcb; 00309 00310 Status = TRUE; 00311 RtlZeroMemory (&NewRange, sizeof (NewRange)); 00312 NewRange.Status = STATUS_UNSUCCESSFUL; 00313 00314 // 00315 // If this is the first processor, initialize some fields 00316 // 00317 00318 if (KeGetPcr()->Number == 0) { 00319 KeInitializeSpinLock (&KiRangeLock); 00320 00321 KiRangeInfo.Capabilities.u.QuadPart = RDMSR(MTRR_MSR_CAPABILITIES); 00322 KiRangeInfo.Default.u.QuadPart = RDMSR(MTRR_MSR_DEFAULT); 00323 KiRangeInfo.DefaultCachedType = MTRR_TYPE_MAX; 00324 00325 // 00326 // If h/w mtrr support is not enabled, disable OS support 00327 // 00328 00329 if (!KiRangeInfo.Default.u.hw.MtrrEnabled || 00330 KiRangeInfo.Capabilities.u.hw.VarCnt == 0 || 00331 KiRangeInfo.Default.u.hw.Type != MTRR_TYPE_UC) { 00332 00333 DBGMSG("MTRR feature disabled.\n"); 00334 Status = FALSE; 00335 00336 } else { 00337 00338 // 00339 // If USWC type is supported by hardware, but the MTRR 00340 // feature is not set in KeFeatureBits, it is because 00341 // the HAL indicated USWC should not be used on this 00342 // machine. (Possibly due to shared memory clusters). 00343 // 00344 00345 if (KiRangeInfo.Capabilities.u.hw.UswcSupported && 00346 ((KeFeatureBits & KF_MTRR) == 0)) { 00347 00348 DBGMSG("KiInitializeMTRR: MTRR use globally disabled on this machine.\n"); 00349 KiRangeInfo.Capabilities.u.hw.UswcSupported = 0; 00350 } 00351 00352 // 00353 // Allocate initial range type database 00354 // 00355 00356 KiRangeInfo.NoRange = 0; 00357 KiRangeInfo.MaxRange = (UCHAR) KiRangeInfo.Capabilities.u.hw.VarCnt + GROW_RANGE_TABLE; 00358 KiRangeInfo.Ranges = ExAllocatePoolWithTag (NonPagedPool, 00359 sizeof(ONE_RANGE) * KiRangeInfo.MaxRange, 00360 ' eK'); 00361 RtlZeroMemory (KiRangeInfo.Ranges, sizeof(ONE_RANGE) * KiRangeInfo.MaxRange); 00362 } 00363 } 00364 00365 // 00366 // Workaround for cpu signatures 611, 612, 616 and 617 00367 // - if the request for setting a variable MTRR specifies 00368 // an address which is not 4M aligned or length is not 00369 // a multiple of 4M then possible problem for INVLPG inst. 00370 // Detect if workaround is required 00371 // 00372 00373 Prcb = KeGetCurrentPrcb(); 00374 if (Prcb->CpuType == 6 && 00375 (Prcb->CpuStep == 0x0101 || Prcb->CpuStep == 0x0102 || 00376 Prcb->CpuStep == 0x0106 || Prcb->CpuStep == 0x0107 )) { 00377 00378 if (strcmp(Prcb->VendorString, "GenuineIntel") == 0) { 00379 00380 // 00381 // Only do this if it's an Intel part, other 00382 // manufacturers may have the same stepping 00383 // numbers but no bug. 00384 // 00385 00386 KiRangeInfo.MtrrWorkaround = TRUE; 00387 } 00388 } 00389 00390 // 00391 // If MTRR support disabled on first processor or if 00392 // buffer not allocated then fall through 00393 // 00394 00395 if (!KiRangeInfo.Ranges){ 00396 Status = FALSE; 00397 } else { 00398 00399 // 00400 // Verify MTRR support is symmetric 00401 // 00402 00403 Capabilities.u.QuadPart = RDMSR(MTRR_MSR_CAPABILITIES); 00404 00405 if ((Capabilities.u.hw.UswcSupported) && 00406 ((KeFeatureBits & KF_MTRR) == 0)) { 00407 DBGMSG ("KiInitializeMTRR: setting UswcSupported FALSE\n"); 00408 Capabilities.u.hw.UswcSupported = 0; 00409 } 00410 00411 Default.u.QuadPart = RDMSR(MTRR_MSR_DEFAULT); 00412 00413 if (Default.u.QuadPart != KiRangeInfo.Default.u.QuadPart || 00414 Capabilities.u.QuadPart != KiRangeInfo.Capabilities.u.QuadPart) { 00415 DBGMSG ("KiInitializeMTRR: asymmetric mtrr support\n"); 00416 Status = FALSE; 00417 } 00418 } 00419 00420 NewRange.Status = STATUS_SUCCESS; 00421 00422 // 00423 // MTRR registers should be identically set on each processor. 00424 // Ranges should be added to the range database only for one 00425 // processor. 00426 // 00427 00428 if (Status && (KeGetPcr()->Number == 0)) { 00429 #if IDBG 00430 KiDumpMTRR ("Processor MTRR:", NULL); 00431 #endif 00432 00433 // 00434 // Read current MTRR settings for various cached range types 00435 // and add them to the range database 00436 // 00437 00438 for (Index=0; Index < Capabilities.u.hw.VarCnt; Index++) { 00439 00440 MtrrBase.u.QuadPart = RDMSR(MTRR_MSR_VARIABLE_BASE+Index*2); 00441 MtrrMask.u.QuadPart = RDMSR(MTRR_MSR_VARIABLE_MASK+Index*2); 00442 00443 Mask = MtrrMask.u.QuadPart & MTRR_MASK_MASK; 00444 Base = MtrrBase.u.QuadPart & MTRR_MASK_BASE; 00445 00446 // 00447 // Note - the variable MTRR Mask does NOT contain the length 00448 // spanned by the variable MTRR. Thus just checking the Valid 00449 // Bit should be sufficient for identifying a valid MTRR. 00450 // 00451 00452 if (MtrrMask.u.hw.Valid) { 00453 00454 Length = KiMaskToLength(Mask); 00455 00456 // 00457 // Check for non-contiguous MTRR mask. 00458 // 00459 00460 if ((Mask + Length) & MASK_OVERFLOW_MASK) { 00461 DBGMSG ("KiInitializeMTRR: Found non-contiguous MTRR mask!\n"); 00462 Status = FALSE; 00463 } 00464 00465 // 00466 // Add this MTRR to the range database 00467 // 00468 00469 Base &= Mask; 00470 KiAddRange ( 00471 &NewRange, 00472 Base, 00473 Base + Length - 1, 00474 (UCHAR) MtrrBase.u.hw.Type 00475 ); 00476 00477 // 00478 // Check for default cache type 00479 // 00480 00481 if (MtrrBase.u.hw.Type == MTRR_TYPE_WB) { 00482 KiRangeInfo.DefaultCachedType = MTRR_TYPE_WB; 00483 } 00484 00485 if (KiRangeInfo.DefaultCachedType == MTRR_TYPE_MAX && 00486 MtrrBase.u.hw.Type == MTRR_TYPE_WT) { 00487 KiRangeInfo.DefaultCachedType = MTRR_TYPE_WT; 00488 } 00489 } 00490 } 00491 00492 // 00493 // If a default type for "cached" was not found, assume write-back 00494 // 00495 00496 if (KiRangeInfo.DefaultCachedType == MTRR_TYPE_MAX) { 00497 DBGMSG ("KiInitializeMTRR: assume write-back\n"); 00498 KiRangeInfo.DefaultCachedType = MTRR_TYPE_WB; 00499 } 00500 } 00501 00502 // 00503 // Done 00504 // 00505 00506 if (!NT_SUCCESS(NewRange.Status)) { 00507 Status = FALSE; 00508 } 00509 00510 if (!Status) { 00511 DBGMSG ("KiInitializeMTRR: OS support for MTRRs disabled\n"); 00512 if (KiRangeInfo.Ranges != NULL) { 00513 ExFreePool (KiRangeInfo.Ranges); 00514 KiRangeInfo.Ranges = NULL; 00515 } 00516 } else { 00517 00518 // if last processor indicate initialization complete 00519 if (LastProcessor) { 00520 KiRangeInfo.RangesValid = TRUE; 00521 } 00522 } 00523 }

VOID KiInitializePAT VOID   ) 
 

Definition at line 119 of file pat.c.

References ASSERT, _NEW_PAT::Attributes, HIGH_LEVEL, _PAT::hw, KeActiveProcessors, KeFeatureBits, KeGetCurrentPrcb, KeRaiseIrql(), KF_PAT, KiIpiStallOnPacketTargets(), KiLoadPAT(), KiLoadPATTarget(), KiLockContextSwap, KiUnlockContextSwap, MmEnablePAT(), NULL, PAT_TYPE_STRONG_UC, PAT_TYPE_USWC, PAT_TYPE_WB, PAT_TYPE_WEAK_UC, _NEW_PAT::Processor, Size, _NEW_PAT::TargetCount, and _NEW_PAT::TargetPhase.

00124 : 00125 00126 Initialize the Page Attribute Table (PAT) on all processors. PAT 00127 is setup to provide WB, WC, STRONG_UC and WEAK_UC as the memory 00128 types such that mm macros for enabling/disabling/querying caching 00129 (MI_DISABLE_CACHING, MI_ENABLE_CACHING and MI_IS_CACHING_ENABLED) 00130 are unaffected. 00131 00132 PAT_Entry PAT Index PCD PWT Memory Type 00133 0 0 0 0 WB 00134 1 0 0 1 WC * 00135 2 0 1 0 WEAK_UC 00136 3 0 1 1 STRONG_UC 00137 4 1 0 0 WB 00138 5 1 0 1 WC * 00139 6 1 1 0 WEAK_UC 00140 7 1 1 1 STRONG_UC 00141 00142 N.B. The caller must have the PAGELK code locked and ensure that the 00143 PAT feature is supported. 00144 00145 Arguments: 00146 00147 None. 00148 00149 Return Value: 00150 00151 None. 00152 00153 --*/ 00154 { 00155 PAT PatAttributes; 00156 ULONG Size; 00157 KIRQL OldIrql, NewIrql; 00158 PKPRCB Prcb; 00159 NEW_PAT NewPAT; 00160 KAFFINITY TargetProcessors; 00161 00162 ASSERT ((KeFeatureBits & KF_PAT) != 0); 00163 00164 // 00165 // Initialize the PAT 00166 // 00167 00168 PatAttributes.hw.Pat[0] = PAT_TYPE_WB; 00169 PatAttributes.hw.Pat[1] = PAT_TYPE_USWC; 00170 PatAttributes.hw.Pat[2] = PAT_TYPE_WEAK_UC; 00171 PatAttributes.hw.Pat[3] = PAT_TYPE_STRONG_UC; 00172 PatAttributes.hw.Pat[4] = PAT_TYPE_WB; 00173 PatAttributes.hw.Pat[5] = PAT_TYPE_USWC; 00174 PatAttributes.hw.Pat[6] = PAT_TYPE_WEAK_UC; 00175 PatAttributes.hw.Pat[7] = PAT_TYPE_STRONG_UC; 00176 00177 // 00178 // Synchronize with other IPI functions which may stall 00179 // 00180 00181 KiLockContextSwap(&OldIrql); 00182 00183 Prcb = KeGetCurrentPrcb(); 00184 00185 NewPAT.Attributes = PatAttributes; 00186 NewPAT.TargetCount = 0; 00187 NewPAT.TargetPhase = &Prcb->ReverseStall; 00188 NewPAT.Processor = Prcb->Number; 00189 00190 00191 #if !defined(NT_UP) 00192 00193 // 00194 // Collect all the (other) processors 00195 // 00196 00197 TargetProcessors = KeActiveProcessors & ~Prcb->SetMember; 00198 if (TargetProcessors != 0) { 00199 00200 KiIpiSendSynchronousPacket ( 00201 Prcb, 00202 TargetProcessors, 00203 KiLoadPATTarget, 00204 (PVOID) (&NewPAT), 00205 NULL, 00206 NULL 00207 ); 00208 00209 // 00210 // Wait for all processors to be collected 00211 // 00212 00213 KiIpiStallOnPacketTargets(TargetProcessors); 00214 00215 // 00216 // All processors are now waiting. Raise to high level to 00217 // ensure this processor doesn't enter the debugger due to 00218 // some interrupt service routine. 00219 // 00220 00221 KeRaiseIrql (HIGH_LEVEL, &NewIrql); 00222 00223 // 00224 // There's no reason for any debug events now, so signal 00225 // the other processors that they can all begin the PAT update 00226 // 00227 00228 Prcb->ReverseStall += 1; 00229 } 00230 00231 #endif 00232 00233 // 00234 // Update PAT 00235 // 00236 00237 KiLoadPAT(&NewPAT); 00238 00239 // 00240 // Release ContextSwap lock and lower to initial irql 00241 // 00242 00243 KiUnlockContextSwap(OldIrql); 00244 MmEnablePAT(); 00245 return; 00246 }

VOID KiInitializePcr IN ULONG  Processor,
IN PKPCR  Pcr,
IN PKIDTENTRY  Idt,
IN PKGDTENTRY  Gdt,
IN PKTSS  Tss,
IN PKTHREAD  Thread,
IN PVOID  DpcStack
 

Definition at line 749 of file kernlini.c.

References KiProcessorBlock, PCR_MAJOR_VERSION, PCR_MINOR_VERSION, PRCB_MAJOR_VERSION, PRCB_MINOR_VERSION, and TRUE.

Referenced by KeStartAllProcessors().

00761 : 00762 00763 This function is called to initialize the PCR for a processor. It 00764 simply stuffs values into the PCR. (The PCR is not inited statically 00765 because the number varies with the number of processors.) 00766 00767 Note that each processor has its own IDT, GDT, and TSS as well as PCR! 00768 00769 Arguments: 00770 00771 Processor - Processor whose PCR to initialize. 00772 00773 Pcr - Linear address of PCR. 00774 00775 Idt - Linear address of i386 IDT. 00776 00777 Gdt - Linear address of i386 GDT. 00778 00779 Tss - Linear address (NOT SELECTOR!) of the i386 TSS. 00780 00781 Thread - Dummy thread object to use very early on. 00782 00783 Return Value: 00784 00785 None. 00786 00787 --*/ 00788 { 00789 // set version values 00790 00791 Pcr->MajorVersion = PCR_MAJOR_VERSION; 00792 Pcr->MinorVersion = PCR_MINOR_VERSION; 00793 00794 Pcr->PrcbData.MajorVersion = PRCB_MAJOR_VERSION; 00795 Pcr->PrcbData.MinorVersion = PRCB_MINOR_VERSION; 00796 00797 Pcr->PrcbData.BuildType = 0; 00798 00799 #if DBG 00800 Pcr->PrcbData.BuildType |= PRCB_BUILD_DEBUG; 00801 #endif 00802 00803 #ifdef NT_UP 00804 Pcr->PrcbData.BuildType |= PRCB_BUILD_UNIPROCESSOR; 00805 #endif 00806 00807 #if defined (_X86PAE_) 00808 if (Processor == 0) { 00809 // 00810 // PAE feature must be initialized prior to the first HAL call. 00811 // 00812 00813 SharedUserData->ProcessorFeatures[PF_PAE_ENABLED] = TRUE; 00814 } 00815 #endif 00816 00817 // Basic addressing fields 00818 00819 Pcr->SelfPcr = Pcr; 00820 Pcr->Prcb = &(Pcr->PrcbData); 00821 00822 // Thread control fields 00823 00824 Pcr->NtTib.ExceptionList = EXCEPTION_CHAIN_END; 00825 Pcr->NtTib.StackBase = 0; 00826 Pcr->NtTib.StackLimit = 0; 00827 Pcr->NtTib.Self = 0; 00828 00829 Pcr->PrcbData.CurrentThread = Thread; 00830 00831 // 00832 // Init Prcb.Number and ProcessorBlock such that Ipi will work 00833 // as early as possible. 00834 // 00835 00836 Pcr->PrcbData.Number = (UCHAR)Processor; 00837 Pcr->PrcbData.SetMember = 1 << Processor; 00838 KiProcessorBlock[Processor] = Pcr->Prcb; 00839 00840 Pcr->Irql = 0; 00841 00842 // Machine structure addresses 00843 00844 Pcr->GDT = Gdt; 00845 Pcr->IDT = Idt; 00846 Pcr->TSS = Tss; 00847 Pcr->PrcbData.DpcStack = DpcStack; 00848 00849 return; 00850 }

VOID KiInitializeTSS IN PKTSS  Tss  ) 
 

Definition at line 944 of file kernlini.c.

00950 : 00951 00952 This function is called to initialize the TSS for a processor. 00953 It will set the static fields of the TSS. (ie Those fields that 00954 the part reads, and for which NT uses constant values.) 00955 00956 The dynamic fields (Esp0 and CR3) are set in the context swap 00957 code. 00958 00959 Arguments: 00960 00961 Tss - Linear address of the Task State Segment. 00962 00963 Return Value: 00964 00965 None. 00966 00967 --*/ 00968 { 00969 00970 // Set IO Map base address to indicate no IO map present. 00971 00972 // N.B. -1 does not seem to be a valid value for the map base. If this 00973 // value is used, byte immediate in's and out's will actually go 00974 // the hardware when executed in V86 mode. 00975 00976 Tss->IoMapBase = KiComputeIopmOffset(IO_ACCESS_MAP_NONE); 00977 00978 // Set flags to 0, which in particular disables traps on task switches. 00979 00980 Tss->Flags = 0; 00981 00982 00983 // Set LDT and Ss0 to constants used by NT. 00984 00985 Tss->LDT = 0; 00986 Tss->Ss0 = KGDT_R0_DATA; 00987 00988 return; 00989 }

VOID KiInitializeTSS2 IN PKTSS  Tss,
IN PKGDTENTRY  TssDescriptor
 

Definition at line 992 of file kernlini.c.

References NULL.

00999 : 01000 01001 Do part of TSS init we do only once. 01002 01003 Arguments: 01004 01005 Tss - Linear address of the Task State Segment. 01006 01007 TssDescriptor - Linear address of the descriptor for the TSS. 01008 01009 Return Value: 01010 01011 None. 01012 01013 --*/ 01014 { 01015 PUCHAR p; 01016 ULONG i; 01017 ULONG j; 01018 01019 // 01020 // Set limit for TSS 01021 // 01022 01023 if (TssDescriptor != NULL) { 01024 TssDescriptor->LimitLow = sizeof(KTSS) - 1; 01025 TssDescriptor->HighWord.Bits.LimitHi = 0; 01026 } 01027 01028 // 01029 // Initialize IOPMs 01030 // 01031 01032 for (i = 0; i < IOPM_COUNT; i++) { 01033 p = (PUCHAR)(Tss->IoMaps[i].IoMap); 01034 01035 for (j = 0; j < PIOPM_SIZE; j++) { 01036 p[j] = (UCHAR)-1; 01037 } 01038 } 01039 01040 // 01041 // Initialize Software Interrupt Direction Maps 01042 // 01043 01044 for (i = 0; i < IOPM_COUNT; i++) { 01045 p = (PUCHAR)(Tss->IoMaps[i].DirectionMap); 01046 for (j = 0; j < INT_DIRECTION_MAP_SIZE; j++) { 01047 p[j] = 0; 01048 } 01049 // dpmi requires special case for int 2, 1b, 1c, 23, 24 01050 p[0] = 4; 01051 p[3] = 0x18; 01052 p[4] = 0x18; 01053 } 01054 01055 // 01056 // Initialize the map for IO_ACCESS_MAP_NONE 01057 // 01058 p = (PUCHAR)(Tss->IntDirectionMap); 01059 for (j = 0; j < INT_DIRECTION_MAP_SIZE; j++) { 01060 p[j] = 0; 01061 } 01062 01063 // dpmi requires special case for int 2, 1b, 1c, 23, 24 01064 p[0] = 4; 01065 p[3] = 0x18; 01066 p[4] = 0x18; 01067 01068 return; 01069 }

BOOLEAN KiInitMachineDependent VOID   ) 
 

Definition at line 1691 of file kernlini.c.

References ASSERT, CPUID(), FALSE, HalFrameBufferCachingInformation, HalQuerySystemInformation, IDENTITY_MAP, Index, KeActiveProcessors, KeDelayExecutionThread(), KeFeatureBits, KeGetCurrentPrcb, KeNumberProcessors, KeQueryPerformanceCounter(), KeRevertToUserAffinityThread(), KernelMode, KeSetSystemAffinityThread(), KeZeroPage, KeZeroPageFromIdleThread, KF_AMDK6MTRR, KF_FXSR, KF_GLOBAL_PAGE, KF_LARGE_PAGE, KF_MTRR, KF_PAT, KF_RDTSC, KF_WORKING_PTE, KF_XMMI, Ki386ClearIdentityMap(), Ki386CreateIdentityMap(), Ki386EnableCurrentLargePage(), Ki386EnableCurrentLargePageEnd, Ki386EnableFxsr(), Ki386EnableGlobalPage(), Ki386EnableTargetLargePage(), Ki386EnableXMMIExceptions(), Ki386UseSynchronousTbFlush(), KiAmdK6InitializeMTRR(), KiI386PentiumLockErrataFixup(), KiI386PentiumLockErrataPresent, KiInitializeMTRR(), KiInitializePAT(), KiIpiGenericCall(), KiXMMIZeroPage(), KiXMMIZeroPageNoSave(), L, MAX_ATTEMPTS, NT_SUCCESS, NTSTATUS(), NULL, PKIPI_BROADCAST_WORKER, RDTSC(), ScPatchFxb, ScPatchFxe, Size, Status, TRUE, and USHORT.

01694 { 01695 KAFFINITY ActiveProcessors, CurrentAffinity; 01696 ULONG NumberProcessors; 01697 IDENTITY_MAP IdentityMap; 01698 ULONG Index; 01699 ULONG Average; 01700 ULONG Junk; 01701 struct { 01702 LARGE_INTEGER PerfStart; 01703 LARGE_INTEGER PerfEnd; 01704 LONGLONG PerfDelta; 01705 LARGE_INTEGER PerfFreq; 01706 LONGLONG TSCStart; 01707 LONGLONG TSCEnd; 01708 LONGLONG TSCDelta; 01709 ULONG MHz; 01710 } Samples[MAX_ATTEMPTS], *pSamp; 01711 PUCHAR PatchLocation; 01712 01713 // 01714 // If PDE large page is supported, enable it. 01715 // 01716 // We enable large pages before global pages to make TLB invalidation 01717 // easier while turning on large pages. 01718 // 01719 01720 if (KeFeatureBits & KF_LARGE_PAGE) { 01721 if (Ki386CreateIdentityMap(&IdentityMap, 01722 &Ki386EnableCurrentLargePage, 01723 &Ki386EnableCurrentLargePageEnd )) { 01724 01725 KiIpiGenericCall ( 01726 (PKIPI_BROADCAST_WORKER) Ki386EnableTargetLargePage, 01727 (ULONG)(&IdentityMap) 01728 ); 01729 } 01730 01731 // 01732 // Always call Ki386ClearIdentityMap() to free any memory allocated 01733 // 01734 01735 Ki386ClearIdentityMap(&IdentityMap); 01736 } 01737 01738 // 01739 // If PDE/PTE global page is supported, enable it 01740 // 01741 01742 if (KeFeatureBits & KF_GLOBAL_PAGE) { 01743 NumberProcessors = KeNumberProcessors; 01744 KiIpiGenericCall ( 01745 (PKIPI_BROADCAST_WORKER) Ki386EnableGlobalPage, 01746 (ULONG)(&NumberProcessors) 01747 ); 01748 } 01749 01750 #if !defined(NT_UP) 01751 01752 // 01753 // If some processor doesn't have proper MP PTE implementation, 01754 // then use a synchronous TB shoot down handler 01755 // 01756 01757 if (!(KeFeatureBits & KF_WORKING_PTE)) { 01758 NumberProcessors = KeNumberProcessors; 01759 KiIpiGenericCall ( 01760 (PKIPI_BROADCAST_WORKER) Ki386UseSynchronousTbFlush, 01761 (ULONG)(&NumberProcessors) 01762 ); 01763 } 01764 01765 #endif 01766 01767 // 01768 // If PAT or MTRR supported but the HAL indicates it shouldn't 01769 // be used (eg on a Shared Memory Cluster), drop the feature. 01770 // 01771 01772 if (KeFeatureBits & (KF_PAT | KF_MTRR)) { 01773 01774 NTSTATUS Status; 01775 BOOLEAN UseFrameBufferCaching; 01776 ULONG Size; 01777 01778 Status = HalQuerySystemInformation( 01779 HalFrameBufferCachingInformation, 01780 sizeof(UseFrameBufferCaching), 01781 &UseFrameBufferCaching, 01782 &Size 01783 ); 01784 01785 if (NT_SUCCESS(Status) && 01786 (UseFrameBufferCaching == FALSE)) { 01787 01788 // 01789 // Hal says don't use. 01790 // 01791 01792 KeFeatureBits &= ~(KF_PAT | KF_MTRR); 01793 } 01794 } 01795 01796 01797 // 01798 // If PAT is supported then initialize it. 01799 // 01800 01801 if (KeFeatureBits & KF_PAT) { 01802 KiInitializePAT(); 01803 } 01804 01805 // 01806 // Compute each processors approximate mhz 01807 // 01808 01809 // 01810 // If FXSR feature is supported, set OSFXSR (bit 9) in CR4 01811 // 01812 01813 if (KeFeatureBits & KF_FXSR) { 01814 NumberProcessors = KeNumberProcessors; 01815 01816 KiIpiGenericCall ( 01817 (PKIPI_BROADCAST_WORKER) Ki386EnableFxsr, 01818 (ULONG)(&NumberProcessors) 01819 ); 01820 01821 01822 // 01823 // If XMMI feature is supported, 01824 // a. Hook int 19 handler 01825 // b. Set OSXMMEXCPT (bit 10) in CR4 01826 // c. Enable use of fast XMMI based zero page routines. 01827 // 01828 01829 if (KeFeatureBits & KF_XMMI) { 01830 KiIpiGenericCall ( 01831 (PKIPI_BROADCAST_WORKER) Ki386EnableXMMIExceptions, 01832 (ULONG)(&NumberProcessors) 01833 ); 01834 01835 KeZeroPage = KiXMMIZeroPage; 01836 KeZeroPageFromIdleThread = KiXMMIZeroPageNoSave; 01837 } 01838 01839 01840 } else { 01841 #ifndef NT_UP 01842 // 01843 // Patch the fxsave instruction in SwapContext to use 01844 // "fnsave {dd, 31}, fwait {9b}" 01845 // 01846 ASSERT( ((ULONG)&ScPatchFxe-(ULONG)&ScPatchFxb) >= 3); 01847 01848 PatchLocation = (PUCHAR)&ScPatchFxb; 01849 01850 *PatchLocation++ = 0xdd; 01851 *PatchLocation++ = 0x31; 01852 *PatchLocation++ = 0x9b; 01853 01854 while (PatchLocation < (PUCHAR)&ScPatchFxe) { 01855 // 01856 // Put nop's in the remaining bytes 01857 // 01858 *PatchLocation++ = 0x90; 01859 } 01860 #endif 01861 } 01862 01863 ActiveProcessors = KeActiveProcessors; 01864 for (CurrentAffinity=1; ActiveProcessors; CurrentAffinity <<= 1) { 01865 01866 if (ActiveProcessors & CurrentAffinity) { 01867 01868 // 01869 // Switch to that processor, and remove it from the 01870 // remaining set of processors 01871 // 01872 01873 ActiveProcessors &= ~CurrentAffinity; 01874 KeSetSystemAffinityThread(CurrentAffinity); 01875 01876 // 01877 // Determine the MHz for the processor 01878 // 01879 01880 KeGetCurrentPrcb()->MHz = 0; 01881 01882 if (KeFeatureBits & KF_RDTSC) { 01883 01884 Index = 0; 01885 pSamp = Samples; 01886 01887 for (; ;) { 01888 01889 // 01890 // Collect a new sample 01891 // Delay the thread a "long" amount and time it with 01892 // a time source and RDTSC. 01893 // 01894 01895 CPUID (0, &Junk, &Junk, &Junk, &Junk); 01896 pSamp->PerfStart = KeQueryPerformanceCounter (NULL); 01897 pSamp->TSCStart = RDTSC(); 01898 pSamp->PerfFreq.QuadPart = -50000; 01899 01900 KeDelayExecutionThread (KernelMode, FALSE, &pSamp->PerfFreq); 01901 01902 CPUID (0, &Junk, &Junk, &Junk, &Junk); 01903 pSamp->PerfEnd = KeQueryPerformanceCounter (&pSamp->PerfFreq); 01904 pSamp->TSCEnd = RDTSC(); 01905 01906 // 01907 // Calculate processors MHz 01908 // 01909 01910 pSamp->PerfDelta = pSamp->PerfEnd.QuadPart - pSamp->PerfStart.QuadPart; 01911 pSamp->TSCDelta = pSamp->TSCEnd - pSamp->TSCStart; 01912 01913 pSamp->MHz = (ULONG) ((pSamp->TSCDelta * pSamp->PerfFreq.QuadPart + 500000L) / 01914 (pSamp->PerfDelta * 1000000L)); 01915 01916 01917 // 01918 // If last 2 samples matched within a MHz, done 01919 // 01920 01921 if (Index) { 01922 if (pSamp->MHz == pSamp[-1].MHz || 01923 pSamp->MHz == pSamp[-1].MHz + 1 || 01924 pSamp->MHz == pSamp[-1].MHz - 1) { 01925 break; 01926 } 01927 } 01928 01929 // 01930 // Advance to next sample 01931 // 01932 01933 pSamp += 1; 01934 Index += 1; 01935 01936 // 01937 // If too many samples, then something is wrong 01938 // 01939 01940 if (Index >= MAX_ATTEMPTS) { 01941 01942 #if DBG 01943 // 01944 // Temp breakpoint to see where this is failing 01945 // and why 01946 // 01947 01948 DbgBreakPoint(); 01949 #endif 01950 01951 Average = 0; 01952 for (Index = 0; Index < MAX_ATTEMPTS; Index++) { 01953 Average += Samples[Index].MHz; 01954 } 01955 pSamp[-1].MHz = Average / MAX_ATTEMPTS; 01956 break; 01957 } 01958 01959 } 01960 01961 KeGetCurrentPrcb()->MHz = (USHORT) pSamp[-1].MHz; 01962 } 01963 01964 // 01965 // If MTRRs are supported and PAT not supported, initialize MTRRs 01966 // per processor 01967 // 01968 01969 if (!(KeFeatureBits & KF_PAT) && (KeFeatureBits & KF_MTRR)) { 01970 KiInitializeMTRR ( (BOOLEAN) (ActiveProcessors ? FALSE : TRUE)); 01971 } 01972 01973 // 01974 // If the processor is a AMD K6 with MTRR support then 01975 // perform processor specific initialization. 01976 // 01977 01978 if (KeFeatureBits & KF_AMDK6MTRR) { 01979 KiAmdK6InitializeMTRR(); 01980 } 01981 01982 // 01983 // Apply Pentium workaround if needed 01984 // 01985 01986 if (KiI386PentiumLockErrataPresent) { 01987 KiI386PentiumLockErrataFixup (); 01988 } 01989 } 01990 } 01991 01992 KeRevertToUserAffinityThread(); 01993 return TRUE; 01994 }

BOOLEAN KiIsNpxPresent VOID   ) 
 

Referenced by KiInitializeKernel().

NTSTATUS KiMoveRegTree HANDLE  Source,
HANDLE  Dest
 

Definition at line 2297 of file kernlini.c.

References KeyName, NT_SUCCESS, NtDeleteKey(), NTSTATUS(), NULL, ObjectAttributes, Status, USHORT, and ValueName.

Referenced by KeSetup80387OrEmulate().

02301 { 02302 NTSTATUS Status; 02303 PKEY_BASIC_INFORMATION KeyInformation; 02304 PKEY_VALUE_FULL_INFORMATION KeyValue; 02305 OBJECT_ATTRIBUTES ObjectAttributes; 02306 HANDLE SourceChild; 02307 HANDLE DestChild; 02308 ULONG ResultLength; 02309 UCHAR buffer[1024]; // hmm.... 02310 UNICODE_STRING ValueName; 02311 UNICODE_STRING KeyName; 02312 02313 02314 KeyValue = (PKEY_VALUE_FULL_INFORMATION)buffer; 02315 02316 // 02317 // Move values from source node to dest node 02318 // 02319 02320 for (; ;) { 02321 // 02322 // Get first value 02323 // 02324 02325 Status = ZwEnumerateValueKey(Source, 02326 0, 02327 KeyValueFullInformation, 02328 buffer, 02329 sizeof (buffer), 02330 &ResultLength); 02331 02332 if (!NT_SUCCESS(Status)) { 02333 break; 02334 } 02335 02336 02337 // 02338 // Write value to dest node 02339 // 02340 02341 ValueName.Buffer = KeyValue->Name; 02342 ValueName.Length = (USHORT) KeyValue->NameLength; 02343 ZwSetValueKey( Dest, 02344 &ValueName, 02345 KeyValue->TitleIndex, 02346 KeyValue->Type, 02347 buffer+KeyValue->DataOffset, 02348 KeyValue->DataLength 02349 ); 02350 02351 // 02352 // Delete value and get first value again 02353 // 02354 02355 Status = ZwDeleteValueKey (Source, &ValueName); 02356 if (!NT_SUCCESS(Status)) { 02357 break; 02358 } 02359 } 02360 02361 02362 // 02363 // Enumerate node's children and apply ourselves to each one 02364 // 02365 02366 KeyInformation = (PKEY_BASIC_INFORMATION)buffer; 02367 for (; ;) { 02368 02369 // 02370 // Open node's first key 02371 // 02372 02373 Status = ZwEnumerateKey( 02374 Source, 02375 0, 02376 KeyBasicInformation, 02377 KeyInformation, 02378 sizeof (buffer), 02379 &ResultLength 02380 ); 02381 02382 if (!NT_SUCCESS(Status)) { 02383 break; 02384 } 02385 02386 KeyName.Buffer = KeyInformation->Name; 02387 KeyName.Length = (USHORT) KeyInformation->NameLength; 02388 02389 InitializeObjectAttributes( 02390 &ObjectAttributes, 02391 &KeyName, 02392 OBJ_CASE_INSENSITIVE, 02393 Source, 02394 NULL 02395 ); 02396 02397 Status = ZwOpenKey( 02398 &SourceChild, 02399 KEY_ALL_ACCESS, 02400 &ObjectAttributes 02401 ); 02402 02403 if (!NT_SUCCESS(Status)) { 02404 break; 02405 } 02406 02407 // 02408 // Create key in dest tree 02409 // 02410 02411 InitializeObjectAttributes( 02412 &ObjectAttributes, 02413 &KeyName, 02414 OBJ_CASE_INSENSITIVE, 02415 Dest, 02416 NULL 02417 ); 02418 02419 Status = ZwCreateKey( 02420 &DestChild, 02421 KEY_ALL_ACCESS, 02422 &ObjectAttributes, 02423 0, 02424 NULL, 02425 REG_OPTION_VOLATILE, 02426 NULL 02427 ); 02428 02429 if (!NT_SUCCESS(Status)) { 02430 break; 02431 } 02432 02433 // 02434 // Move subtree 02435 // 02436 02437 Status = KiMoveRegTree(SourceChild, DestChild); 02438 02439 ZwClose(DestChild); 02440 ZwClose(SourceChild); 02441 02442 if (!NT_SUCCESS(Status)) { 02443 break; 02444 } 02445 02446 // 02447 // Loop and get first key. (old first key was delete by the 02448 // call to KiMoveRegTree). 02449 // 02450 } 02451 02452 // 02453 // Remove source node 02454 // 02455 02456 return NtDeleteKey (Source); 02457 }

VOID KiSetCR0Bits VOID   ) 
 

Referenced by KiInitializeKernel().

VOID KiSetProcessorType VOID   ) 
 

Referenced by KiInitializeKernel().

VOID KiSwapIDT  ) 
 

Definition at line 1072 of file kernlini.c.

References IDT, Index, and USHORT.

01077 : 01078 01079 This function is called to edit the IDT. It swaps words of the address 01080 and access fields around into the format the part actually needs. 01081 This allows for easy static init of the IDT. 01082 01083 Note that this procedure edits the current IDT. 01084 01085 Arguments: 01086 01087 None. 01088 01089 Return Value: 01090 01091 None. 01092 01093 --*/ 01094 { 01095 LONG Index; 01096 USHORT Temp; 01097 01098 // 01099 // Rearrange the entries of IDT to match i386 interrupt gate structure 01100 // 01101 01102 for (Index = 0; Index <= MAXIMUM_IDTVECTOR; Index += 1) { 01103 Temp = IDT[Index].Selector; 01104 IDT[Index].Selector = IDT[Index].ExtendedOffset; 01105 IDT[Index].ExtendedOffset = Temp; 01106 } 01107 }

VOID KiSwapIDT VOID   ) 
 

VOID FASTCALL KiXMMIZeroPage PVOID  PageBase  ) 
 

Referenced by KiInitMachineDependent().

VOID FASTCALL KiXMMIZeroPageNoSave PVOID  PageBase  ) 
 

Referenced by KiInitMachineDependent().

VOID FASTCALL KiZeroPage PVOID  PageBase  ) 
 


Variable Documentation

KSPIN_LOCK CcMasterSpinLock
 

Definition at line 47 of file kernlini.c.

KSPIN_LOCK CcVacbSpinLock
 

Definition at line 48 of file kernlini.c.

WCHAR CmDisabledFloatingPointProcessor[]
 

Definition at line 184 of file kernlini.c.

UCHAR CmpAmdID[]
 

Definition at line 187 of file kernlini.c.

UCHAR CmpCyrixID[]
 

Definition at line 185 of file kernlini.c.

UCHAR CmpIntelID[]
 

Definition at line 186 of file kernlini.c.

KIDTENTRY IDT[]
 

Definition at line 243 of file kernlini.c.

Referenced by KiSwapIDT().

ULONG KeI386ForceNpxEmulation
 

Definition at line 183 of file kernlini.c.

Referenced by KeSetup80387OrEmulate().

BOOLEAN KeI386XMMIPresent
 

Definition at line 208 of file kernlini.c.

KE_ZERO_PAGE_ROUTINE KeZeroPage = KiZeroPage
 

Definition at line 228 of file kernlini.c.

Referenced by KiInitMachineDependent(), and MiZeroPhysicalPage().

KE_ZERO_PAGE_ROUTINE KeZeroPageFromIdleThread = KiZeroPage
 

Definition at line 229 of file kernlini.c.

Referenced by KiInitMachineDependent(), and MmZeroPageThread().

PVOID Ki386IopmSaveArea
 

Definition at line 182 of file kernlini.c.

Referenced by Ke386CallBios(), and KiInitializeKernel().

PVOID Ki387RoundModeTable
 

Definition at line 181 of file kernlini.c.

Referenced by KeSetup80387OrEmulate().

ULONG Ki486CompatibilityLock
 

Definition at line 237 of file kernlini.c.

Referenced by KiInitializeKernel().

BOOLEAN KiI386PentiumLockErrataPresent = FALSE
 

Definition at line 173 of file kernlini.c.

Referenced by KiInitMachineDependent().

BOOLEAN KiIgnoreUnexpectedTrap07 = FALSE
 

Definition at line 174 of file kernlini.c.

KSPIN_LOCK MmPfnLock
 

Definition at line 49 of file kernlini.c.

KSPIN_LOCK MmSystemSpaceLock
 

Definition at line 50 of file kernlini.c.

PVOID ScPatchFxb
 

Definition at line 190 of file kernlini.c.

Referenced by KiInitMachineDependent().

PVOID ScPatchFxe
 

Definition at line 191 of file kernlini.c.

Referenced by KiInitMachineDependent().


Generated on Sat May 15 19:44:28 2004 for test by doxygen 1.3.7