00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
#include "ki.h"
00038
#include "ki386.h"
00039
#include "fastsys.inc"
00040
00041 #define TRAP332_GATE 0xEF00
00042
00043
00044
00045
00046
00047 extern KSPIN_LOCK
CcMasterSpinLock;
00048 extern KSPIN_LOCK
CcVacbSpinLock;
00049 extern KSPIN_LOCK
MmPfnLock;
00050 extern KSPIN_LOCK
MmSystemSpaceLock;
00051
00052
VOID
00053
KiSetProcessorType(
00054 VOID
00055 );
00056
00057
VOID
00058
KiSetCR0Bits(
00059 VOID
00060 );
00061
00062 BOOLEAN
00063
KiIsNpxPresent(
00064 VOID
00065 );
00066
00067
VOID
00068
KiI386PentiumLockErrataFixup (
00069 VOID
00070 );
00071
00072
VOID
00073
KiInitializeDblFaultTSS(
00074 IN PKTSS Tss,
00075 IN ULONG Stack,
00076 IN PKGDTENTRY TssDescriptor
00077 );
00078
00079
VOID
00080
KiInitializeTSS2 (
00081 IN PKTSS Tss,
00082 IN PKGDTENTRY TssDescriptor
00083 );
00084
00085
VOID
00086
KiSwapIDT (
00087 VOID
00088 );
00089
00090
VOID
00091
KeSetup80387OrEmulate (
00092 IN PVOID *R3EmulatorTable
00093 );
00094
00095
VOID
00096
KiGetCacheInformation(
00097 VOID
00098 );
00099
00100 ULONG
00101
KiGetCpuVendor(
00102 VOID
00103 );
00104
00105 ULONG
00106
KiGetFeatureBits (
00107 VOID
00108 );
00109
00110
NTSTATUS
00111
KiMoveRegTree(
00112 HANDLE Source,
00113 HANDLE Dest
00114 );
00115
00116
VOID
00117
Ki386EnableFxsr (
00118 IN
volatile PLONG Number
00119 );
00120
00121
00122
VOID
00123
Ki386EnableXMMIExceptions (
00124 IN
volatile PLONG Number
00125 );
00126
00127
00128
VOID
00129
Ki386EnableGlobalPage (
00130 IN
volatile PLONG Number
00131 );
00132
00133
VOID
00134
Ki386UseSynchronousTbFlush (
00135 IN
volatile PLONG Number
00136 );
00137
00138 BOOLEAN
00139
KiInitMachineDependent (
00140 VOID
00141 );
00142
00143
VOID
00144
KiInitializeMTRR (
00145 IN BOOLEAN LastProcessor
00146 );
00147
00148
VOID
00149
KiInitializePAT (
00150 VOID
00151 );
00152
00153
VOID
00154
KiAmdK6InitializeMTRR(
00155 VOID
00156 );
00157
00158
#ifdef ALLOC_PRAGMA
00159
#pragma alloc_text(INIT,KiInitializeKernel)
00160
#pragma alloc_text(INIT,KiInitializePcr)
00161
#pragma alloc_text(INIT,KiInitializeDblFaultTSS)
00162
#pragma alloc_text(INIT,KiInitializeTSS2)
00163
#pragma alloc_text(INIT,KiSwapIDT)
00164
#pragma alloc_text(INIT,KeSetup80387OrEmulate)
00165
#pragma alloc_text(INIT,KiGetFeatureBits)
00166
#pragma alloc_text(INIT,KiGetCacheInformation)
00167
#pragma alloc_text(INIT,KiGetCpuVendor)
00168
#pragma alloc_text(INIT,KiMoveRegTree)
00169
#pragma alloc_text(INIT,KiInitMachineDependent)
00170
#pragma alloc_text(INIT,KiI386PentiumLockErrataFixup)
00171
#endif
00172
00173 BOOLEAN
KiI386PentiumLockErrataPresent =
FALSE;
00174 BOOLEAN
KiIgnoreUnexpectedTrap07 =
FALSE;
00175
00176
00177
#if 0
00178
PVOID KiTrap08;
00179
#endif
00180
00181 extern PVOID
Ki387RoundModeTable;
00182 extern PVOID
Ki386IopmSaveArea;
00183 extern ULONG
KeI386ForceNpxEmulation;
00184 extern WCHAR
CmDisabledFloatingPointProcessor[];
00185 extern UCHAR
CmpCyrixID[];
00186 extern UCHAR
CmpIntelID[];
00187 extern UCHAR
CmpAmdID[];
00188
00189
#ifndef NT_UP
00190 extern PVOID
ScPatchFxb;
00191 extern PVOID
ScPatchFxe;
00192
#endif
00193
00194 typedef enum {
00195
CPU_NONE,
00196
CPU_INTEL,
00197
CPU_AMD,
00198
CPU_CYRIX,
00199
CPU_UNKNOWN
00200 }
CPU_VENDORS;
00201
00202
00203
00204
00205
00206
00207
00208 BOOLEAN
KeI386XMMIPresent;
00209
00210
VOID
00211
FASTCALL
00212
KiZeroPage (
00213 PVOID PageBase
00214 );
00215
00216
VOID
00217
FASTCALL
00218
KiXMMIZeroPage (
00219 PVOID PageBase
00220 );
00221
00222
VOID
00223
FASTCALL
00224
KiXMMIZeroPageNoSave (
00225 PVOID PageBase
00226 );
00227
00228 KE_ZERO_PAGE_ROUTINE
KeZeroPage =
KiZeroPage;
00229 KE_ZERO_PAGE_ROUTINE
KeZeroPageFromIdleThread =
KiZeroPage;
00230
00231
00232
00233
00234
00235
00236
00237 ULONG
Ki486CompatibilityLock;
00238
00239
00240
00241
00242
00243 extern KIDTENTRY
IDT[];
00244
00245
VOID
00246 KiInitializeKernel (
00247 IN
PKPROCESS Process,
00248 IN
PKTHREAD Thread,
00249 IN PVOID IdleStack,
00250 IN PKPRCB Prcb,
00251 IN CCHAR Number,
00252
PLOADER_PARAMETER_BLOCK LoaderBlock
00253 )
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
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
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
00323
00324
00325
if (Prcb->CpuType == 3) {
00326
KeBugCheckEx(UNSUPPORTED_PROCESSOR,0x386,0,0,0);
00327 }
00328
00329
00330
00331
00332
00333 FeatureBits =
KiGetFeatureBits();
00334 Prcb->FeatureBits = FeatureBits;
00335
00336
00337
00338
00339
00340
KiGetCacheInformation();
00341
00342
00343
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
00365
00366
00367
00368
if (Number == 0) {
00369
00370
00371
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
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
00404
00405
00406
KeLowerIrql(
APC_LEVEL);
00407
00408
00409
00410
00411
00412
00413
KeInitializeSpinLock(&
KiContextSwapLock);
00414
KeInitializeSpinLock(&
KiDispatcherLock);
00415
KeInitializeSpinLock(&
KiFreezeExecutionLock);
00416
00417
00418
00419
00420
00421
KeInitializeSpinLock(&
Ki486CompatibilityLock);
00422
00423
#if !defined(NT_UP)
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446 OldIrql = KfAcquireSpinLock(&
KiDispatcherLock);
00447
if (
KiDispatcherLock == 0) {
00448
00449
00450
00451
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
00465
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
00484
00485
00486
KiInitSystem();
00487
00488
00489
00490
00491
00492
00493
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
00510
00511
00512 FxsrPresent = ((FeatureBits &
KF_FXSR) ?
TRUE:
FALSE);
00513
if (FxsrPresent !=
KeI386FxsrPresent) {
00514
00515
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
00524
00525
KeBugCheckEx (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED,
KF_XMMI, 0, 0, 0);
00526 }
00527
00528
if (NpxFlag !=
KeI386NpxPresent) {
00529
00530
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
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
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
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
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
00576
00577
00578
KeBugCheckEx (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED,
KF_MTRR, 0, 0, 0);
00579 }
00580
00581
00582
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
00598
00599
00600
KeFeatureBits &= FeatureBits;
00601
00602
00603
00604
00605
00606
KeLowerIrql(
DISPATCH_LEVEL);
00607
00608 }
00609
00610
00611
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
00630
00631
00632
00633
00634
00635
00636
00637
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
00652
00653
00654
00655 Prcb->CurrentThread = Thread;
00656 Prcb->NextThread = (
PKTHREAD)
NULL;
00657 Prcb->IdleThread = Thread;
00658 Pcr->NtTib.StackBase = Thread->InitialStack;
00659
00660
00661
00662
00663
00664
try {
00665
ExpInitializeExecutive(Number, LoaderBlock);
00666
00667 } except (
EXCEPTION_EXECUTE_HANDLER) {
00668
KeBugCheck (PHASE0_EXCEPTION);
00669 }
00670
00671
00672
00673
00674
00675
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
00691
00692
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
00706
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
00719
00720
00721
00722
KeRaiseIrql(
DISPATCH_LEVEL, &OldIrql);
00723
KeSetPriorityThread(Thread, (KPRIORITY)0);
00724
00725
00726
00727
00728
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
00741
00742
00743 LoaderBlock->
Prcb = (ULONG)
NULL;
00744
00745
return;
00746 }
00747
00748
VOID
00749 KiInitializePcr (
00750 IN ULONG Processor,
00751 IN PKPCR Pcr,
00752 IN PKIDTENTRY Idt,
00753 IN PKGDTENTRY Gdt,
00754 IN PKTSS Tss,
00755 IN
PKTHREAD Thread,
00756 IN PVOID DpcStack
00757 )
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788 {
00789
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
00811
00812
00813 SharedUserData->ProcessorFeatures[PF_PAE_ENABLED] =
TRUE;
00814 }
00815
#endif
00816
00817
00818
00819 Pcr->SelfPcr = Pcr;
00820 Pcr->Prcb = &(Pcr->PrcbData);
00821
00822
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
00833
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
00843
00844 Pcr->GDT = Gdt;
00845 Pcr->IDT = Idt;
00846 Pcr->TSS = Tss;
00847 Pcr->PrcbData.DpcStack = DpcStack;
00848
00849
return;
00850 }
00851
00852
#if 0
00853
VOID
00854
KiInitializeDblFaultTSS(
00855 IN PKTSS Tss,
00856 IN ULONG Stack,
00857 IN PKGDTENTRY TssDescriptor
00858 )
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886 {
00887 PUCHAR p;
00888 ULONG i;
00889 ULONG j;
00890
00891
00892
00893
00894
00895
if (TssDescriptor !=
NULL) {
00896 TssDescriptor->LimitLow =
sizeof(KTSS) - 1;
00897 TssDescriptor->HighWord.Bits.LimitHi = 0;
00898 }
00899
00900
00901
00902
00903
00904
for (i = 0; i < IOPM_COUNT; i++) {
00905 p = (PUCHAR)(Tss->IoMaps[i]);
00906
00907
for (j = 0; j < PIOPM_SIZE; j++) {
00908 p[j] = 0;
00909 }
00910 }
00911
00912
00913
00914
00915
00916
00917
00918 Tss->IoMapBase = KiComputeIopmOffset(IO_ACCESS_MAP_NONE);
00919
00920
00921
00922 Tss->Flags = 0;
00923
00924
00925
00926
00927 Tss->LDT = 0;
00928 Tss->Ss0 = KGDT_R0_DATA;
00929 Tss->Esp0 = Stack;
00930 Tss->Eip = (ULONG)KiTrap08;
00931 Tss->Cs = KGDT_R0_CODE || RPL_MASK;
00932 Tss->Ds = KGDT_R0_DATA;
00933 Tss->Es = KGDT_R0_DATA;
00934 Tss->Fs = KGDT_R0_DATA;
00935
00936
00937
return;
00938
00939 }
00940
#endif
00941
00942
00943
VOID
00944 KiInitializeTSS (
00945 IN PKTSS Tss
00946 )
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968 {
00969
00970
00971
00972
00973
00974
00975
00976 Tss->IoMapBase = KiComputeIopmOffset(IO_ACCESS_MAP_NONE);
00977
00978
00979
00980 Tss->Flags = 0;
00981
00982
00983
00984
00985 Tss->LDT = 0;
00986 Tss->Ss0 = KGDT_R0_DATA;
00987
00988
return;
00989 }
00990
00991
VOID
00992 KiInitializeTSS2 (
00993 IN PKTSS Tss,
00994 IN PKGDTENTRY TssDescriptor
00995 )
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014 {
01015 PUCHAR p;
01016 ULONG i;
01017 ULONG j;
01018
01019
01020
01021
01022
01023
if (TssDescriptor !=
NULL) {
01024 TssDescriptor->LimitLow =
sizeof(KTSS) - 1;
01025 TssDescriptor->HighWord.Bits.LimitHi = 0;
01026 }
01027
01028
01029
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
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
01050 p[0] = 4;
01051 p[3] = 0x18;
01052 p[4] = 0x18;
01053 }
01054
01055
01056
01057
01058 p = (PUCHAR)(Tss->IntDirectionMap);
01059
for (j = 0; j < INT_DIRECTION_MAP_SIZE; j++) {
01060 p[j] = 0;
01061 }
01062
01063
01064 p[0] = 4;
01065 p[3] = 0x18;
01066 p[4] = 0x18;
01067
01068
return;
01069 }
01070
01071
VOID
01072 KiSwapIDT (
01073 )
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094 {
01095 LONG
Index;
01096
USHORT Temp;
01097
01098
01099
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 }
01108
01109 ULONG
01110 KiGetCpuVendor(
01111 VOID
01112 )
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
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
01147
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 }
01167
01168 ULONG
01169
KiGetFeatureBits (
01170 VOID
01171 )
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190 {
01191 ULONG Junk;
01192 ULONG Junk2;
01193 ULONG ProcessorFeatures;
01194 ULONG NtBits;
01195 ULONG ExtendedProcessorFeatures;
01196 ULONG ProcessorSignature;
01197 ULONG CpuVendor;
01198 PKPRCB Prcb;
01199 BOOLEAN ExtendedCPUIDSupport =
TRUE;
01200
01201 Prcb =
KeGetCurrentPrcb();
01202
01203 NtBits =
KF_WORKING_PTE;
01204
01205
01206
01207
01208
01209 CpuVendor =
KiGetCpuVendor();
01210
01211
01212
01213
01214
01215
01216
if (CpuVendor ==
CPU_NONE) {
01217
return NtBits;
01218 }
01219
01220
01221
01222
01223
01224
CPUID (1, &ProcessorSignature, &Junk, &Junk, &ProcessorFeatures);
01225
01226
01227
01228
01229
01230
if (CpuVendor ==
CPU_AMD) {
01231
01232
01233
01234
01235
01236
if ((ProcessorSignature & 0x0F00) >= 0x0500) {
01237
01238
if ((ProcessorSignature & 0x0F00) == 0x0500) {
01239
01240
switch (ProcessorSignature & 0x00F0) {
01241
01242
case 0x0010:
01243
01244
01245
01246
01247
01248
if ((ProcessorSignature & 0x000F) > 0x03) {
01249
01250
01251
01252
01253
01254
break;
01255 }
01256
01257
01258
01259
01260
01261
case 0x0000:
01262
01263
01264
01265
01266
01267 ProcessorFeatures &= ~0x2000;
01268
break;
01269
01270
case 0x0080:
01271
01272
01273
01274
01275
01276
if ((ProcessorSignature & 0x000F) >= 0x8) {
01277 NtBits |=
KF_AMDK6MTRR;
01278 }
01279
break;
01280
01281
case 0x0090:
01282
01283 NtBits |=
KF_AMDK6MTRR;
01284
break;
01285
01286
default:
01287
01288
break;
01289 }
01290 }
01291
01292 }
else {
01293
01294
01295
01296
01297
01298
01299
01300 ProcessorFeatures &= ~(0x08 | 0x2000 | 0x8000);
01301
01302
01303
01304
01305
01306
01307 ExtendedCPUIDSupport =
FALSE;
01308 }
01309 }
01310
01311
01312
01313
01314
01315
if (CpuVendor ==
CPU_INTEL) {
01316
if (Prcb->CpuType == 6) {
01317
WRMSR (0x8B, 0);
01318
CPUID (1, &Junk, &Junk, &Junk, &ProcessorFeatures);
01319 Prcb->UpdateSignature.QuadPart =
RDMSR (0x8B);
01320 }
01321
01322
else if (Prcb->CpuType == 5) {
01323
KiI386PentiumLockErrataPresent =
TRUE;
01324 }
01325
01326
if ( ((ProcessorSignature & 0x0FF0) == 0x0610 &&
01327 (ProcessorSignature & 0x000F) <= 0x9) ||
01328
01329 ((ProcessorSignature & 0x0FF0) == 0x0630 &&
01330 (ProcessorSignature & 0x000F) <= 0x4)) {
01331
01332 NtBits &= ~
KF_WORKING_PTE;
01333 }
01334
01335
if ( (Prcb->CpuType == 6) &&
01336 (Prcb->CpuStep >= 0x0303) &&
01337 (ProcessorFeatures &
KI_FAST_SYSCALL_SUPPORTED) ) {
01338
01339
01340
01341 }
01342 }
01343
01344
01345
01346
01347
01348
if (CpuVendor ==
CPU_CYRIX) {
01349
01350
01351
01352
01353
01354
01355
01356
extern BOOLEAN
KiIgnoreUnexpectedTrap07;
01357
01358
KiIgnoreUnexpectedTrap07 =
TRUE;
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
if ((Prcb->CpuType == 6) &&
01370 (Prcb->CpuStep <= 1)) {
01371
01372
#define CRC_NDX (PUCHAR)0x22
01373
#define CRC_DAT (CRC_NDX + 1)
01374
#define CCR1 0xc1
01375
01376 UCHAR ValueCCR1;
01377
01378
01379
01380
01381
01382 WRITE_PORT_UCHAR(CRC_NDX, CCR1);
01383
01384 ValueCCR1 = READ_PORT_UCHAR(CRC_DAT);
01385
01386
01387
01388
01389
01390 ValueCCR1 |= 0x10;
01391
01392 WRITE_PORT_UCHAR(CRC_NDX, CCR1);
01393 WRITE_PORT_UCHAR(CRC_DAT, ValueCCR1);
01394
01395
#undef CCR1
01396
#undef CRC_DAT
01397
#undef CRC_NDX
01398
}
01399 }
01400
01401
01402
01403
01404
01405
01406
01407
01408
if (ProcessorFeatures & 0x00000002) {
01409 NtBits |=
KF_V86_VIS |
KF_CR4;
01410 }
01411
01412
if (ProcessorFeatures & 0x00000008) {
01413 NtBits |=
KF_LARGE_PAGE |
KF_CR4;
01414 }
01415
01416
if (ProcessorFeatures & 0x00000010) {
01417 NtBits |=
KF_RDTSC;
01418 }
01419
01420
01421
01422
01423
01424
01425
if (ProcessorFeatures & 0x00000100) {
01426 NtBits |=
KF_CMPXCHG8B;
01427 }
01428
01429
if (ProcessorFeatures & 0x00001000) {
01430 NtBits |=
KF_MTRR;
01431 }
01432
01433
if (ProcessorFeatures & 0x00002000) {
01434 NtBits |=
KF_GLOBAL_PAGE |
KF_CR4;
01435 }
01436
01437
if (ProcessorFeatures & 0x00008000) {
01438 NtBits |=
KF_CMOV;
01439 }
01440
01441
if (ProcessorFeatures & 0x00010000) {
01442 NtBits |=
KF_PAT;
01443 }
01444
01445
if (ProcessorFeatures & 0x00800000) {
01446 NtBits |=
KF_MMX;
01447 }
01448
01449
if (ProcessorFeatures & 0x01000000) {
01450 NtBits |=
KF_FXSR;
01451 }
01452
01453
if (ProcessorFeatures & 0x02000000) {
01454 NtBits |=
KF_XMMI;
01455 }
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
if (ExtendedCPUIDSupport !=
FALSE) {
01469
01470
CPUID(0x80000000, &Junk2, &Junk, &Junk, &Junk);
01471
01472
01473
01474
01475
01476
01477
01478
if ((Junk2 & 0xffffff00) == 0x80000000) {
01479
01480
01481
01482
01483
01484
01485
if (Junk2 >= 0x80000001) {
01486
01487
CPUID(0x80000001, &Junk2, &Junk, &Junk, &ExtendedProcessorFeatures);
01488
01489
01490
01491
01492
01493
switch (CpuVendor) {
01494
case CPU_AMD:
01495
01496
if (ExtendedProcessorFeatures & 0x80000000) {
01497 NtBits |=
KF_3DNOW;
01498 }
01499
break;
01500 }
01501 }
01502 }
01503 }
01504
01505
return NtBits;
01506 }
01507
01508
VOID
01509 KiGetCacheInformation(
01510 VOID
01511 )
01512 {
01513
#define CPUID_REG_COUNT 4
01514
ULONG CpuidData[
CPUID_REG_COUNT];
01515
01516 ULONG CpuVendor;
01517 PKPCR Pcr;
01518
01519
01520
01521
01522
01523 Pcr =
KeGetPcr();
01524
01525 Pcr->SecondLevelCacheSize = 0;
01526
01527
01528
01529
01530
01531 CpuVendor =
KiGetCpuVendor();
01532
01533
if (CpuVendor ==
CPU_NONE) {
01534
return;
01535 }
01536
01537
01538
01539
01540
01541
01542
switch (CpuVendor) {
01543
case CPU_INTEL:
01544
01545
CPUID(0, CpuidData, CpuidData+1, CpuidData+2, CpuidData+3);
01546
01547
01548
01549
01550
01551
01552
if (CpuidData[0] >= 2) {
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
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
01601
01602
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
01619
01620
01621
01622
continue;
01623 }
01624
01625
while (CpuidReg) {
01626
01627
01628
01629
01630
01631
01632 UCHAR Descriptor = (UCHAR)(CpuidReg & 0xff);
01633 CpuidReg >>= 8;
01634
01635
if (Descriptor == 0) {
01636
01637
01638
01639
01640
01641
continue;
01642 }
01643
01644
if (((Descriptor > 0x40) && (Descriptor <= 0x49)) ||
01645 ((Descriptor > 0x80) && (Descriptor <= 0x89))) {
01646
01647
01648
01649
01650
01651 Descriptor &= 0x0f;
01652
01653
01654
01655
01656
01657
01658
01659
01660
ASSERT(Descriptor <= 0x6);
01661
01662 Pcr->SecondLevelCacheSize = 0x10000 << Descriptor;
01663 }
01664
01665
01666
01667
01668
01669 }
01670
01671 }
01672
01673
01674
01675
01676
01677
01678
01679 }
while (--CpuidIterations);
01680 }
01681
break;
01682
case CPU_AMD:
01683
break;
01684 }
01685
#undef CPUID_REG_COUNT
01686
}
01687
01688 #define MAX_ATTEMPTS 10
01689
01690 BOOLEAN
01691 KiInitMachineDependent (
01692 VOID
01693 )
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
01715
01716
01717
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
01733
01734
01735
Ki386ClearIdentityMap(&IdentityMap);
01736 }
01737
01738
01739
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
01754
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
01769
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
01790
01791
01792
KeFeatureBits &= ~(
KF_PAT |
KF_MTRR);
01793 }
01794 }
01795
01796
01797
01798
01799
01800
01801
if (
KeFeatureBits &
KF_PAT) {
01802
KiInitializePAT();
01803 }
01804
01805
01806
01807
01808
01809
01810
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
01824
01825
01826
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
01844
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
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
01870
01871
01872
01873 ActiveProcessors &= ~CurrentAffinity;
01874
KeSetSystemAffinityThread(CurrentAffinity);
01875
01876
01877
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
01891
01892
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
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 + 500000
L) /
01914 (pSamp->PerfDelta * 1000000
L));
01915
01916
01917
01918
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
01931
01932
01933 pSamp += 1;
01934
Index += 1;
01935
01936
01937
01938
01939
01940
if (
Index >=
MAX_ATTEMPTS) {
01941
01942
#if DBG
01943
01944
01945
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
01966
01967
01968
01969
if (!(
KeFeatureBits &
KF_PAT) && (
KeFeatureBits &
KF_MTRR)) {
01970
KiInitializeMTRR ( (BOOLEAN) (ActiveProcessors ?
FALSE :
TRUE));
01971 }
01972
01973
01974
01975
01976
01977
01978
if (
KeFeatureBits &
KF_AMDK6MTRR) {
01979
KiAmdK6InitializeMTRR();
01980 }
01981
01982
01983
01984
01985
01986
if (
KiI386PentiumLockErrataPresent) {
01987
KiI386PentiumLockErrataFixup ();
01988 }
01989 }
01990 }
01991
01992
KeRevertToUserAffinityThread();
01993
return TRUE;
01994 }
01995
01996
01997
VOID
01998 KeOptimizeProcessorControlState (
01999 VOID
02000 )
02001 {
02002
Ke386ConfigureCyrixProcessor ();
02003 }
02004
02005
02006
02007
VOID
02008 KeSetup80387OrEmulate (
02009 IN PVOID *R3EmulatorTable
02010 )
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
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
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
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
02105
02106
02107
switch (
KeI386ForceNpxEmulation) {
02108
case 0:
02109
02110
02111
02112
02113
break;
02114
02115
case 1:
02116
02117
02118
02119
02120
02121
if (PrecisionErrata) {
02122
KeI386NpxPresent =
FALSE;
02123 }
02124
break;
02125
02126
default:
02127
02128
02129
02130
02131
02132
KeI386NpxPresent =
FALSE;
02133
break;
02134 }
02135 }
02136
02137
02138
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
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
02157
02158
02159 SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] =
FALSE;
02160
02161
02162
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
02176
02177
02178
KeSetSystemAffinityThread(CurrentAffinity);
02179
02180
02181
02182
02183
02184
KiLockDispatcherDatabase(&OldIrql);
02185
02186
02187
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
02197
02198
02199
KiUnlockDispatcherDatabase(OldIrql);
02200 }
02201 }
02202
02203
02204
02205
02206
02207
02208
02209
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
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
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
02276
02277
02278
KiMoveRegTree (SourceHandle, DestHandle);
02279 ZwClose (DestHandle);
02280 }
02281 ZwClose (SourceHandle);
02282 }
02283 ZwClose (SystemHandle);
02284 }
02285 }
02286
02287
02288
02289
02290
02291
KeRevertToUserAffinityThread();
02292 }
02293
02294
02295
02296
NTSTATUS
02297 KiMoveRegTree(
02298 HANDLE Source,
02299 HANDLE Dest
02300 )
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];
02310 UNICODE_STRING
ValueName;
02311 UNICODE_STRING
KeyName;
02312
02313
02314 KeyValue = (PKEY_VALUE_FULL_INFORMATION)buffer;
02315
02316
02317
02318
02319
02320
for (; ;) {
02321
02322
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
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
02353
02354
02355
Status = ZwDeleteValueKey (Source, &
ValueName);
02356
if (!
NT_SUCCESS(
Status)) {
02357
break;
02358 }
02359 }
02360
02361
02362
02363
02364
02365
02366 KeyInformation = (PKEY_BASIC_INFORMATION)buffer;
02367
for (; ;) {
02368
02369
02370
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
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
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
02448
02449
02450 }
02451
02452
02453
02454
02455
02456
return NtDeleteKey (Source);
02457 }
02458
02459
VOID
02460 KiI386PentiumLockErrataFixup (
02461 VOID
02462 )
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
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
02499
02500
02501 BasePage =
MmAllocateIndependentPages (2*
PAGE_SIZE);
02502
02503
02504
02505
02506
02507
02508
02509 NewBase = BasePage +
PAGE_SIZE -
IDT_SKIP;
02510
02511
02512
02513
02514
02515 Enable =
KiDisableInterrupts();
02516
02517
02518
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
02534
02535
02536 _asm {
02537 lidt IdtDescriptor.Limit
02538 }
02539
02540
02541
02542
02543
02544
KeGetPcr()->IDT = (PKIDTENTRY) NewBase;
02545
02546
02547
02548
02549
02550
KiRestoreInterrupts(Enable);
02551
02552
02553
02554
02555
02556
Status =
MmSetPageProtection (BasePage,
PAGE_SIZE, PAGE_READONLY);
02557
ASSERT (
Status);
02558 }