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
#include "ki.h"
00026
#include "pat.h"
00027
00028
#if DBG
00029
#define DBGMSG(a) DbgPrint(a)
00030
#else
00031 #define DBGMSG(a)
00032
#endif
00033
00034
00035
00036 typedef struct _NEW_PAT {
00037
00038 PAT Attributes;
00039
00040
00041
00042 ULONG
Processor;
00043 volatile ULONG
TargetCount;
00044 volatile ULONG *
TargetPhase;
00045
00046 }
NEW_PAT, *
PNEW_PAT;
00047
00048
00049
00050
VOID
00051
KeRestorePAT (
00052 VOID
00053 );
00054
00055
VOID
00056
KiInitializePAT (
00057 VOID
00058 );
00059
00060
VOID
00061
KiLoadPAT (
00062 IN PNEW_PAT Context
00063 );
00064
00065
VOID
00066
KiLoadPATTarget (
00067 IN PKIPI_CONTEXT SignalDone,
00068 IN PVOID Context,
00069 IN PVOID Parameter2,
00070 IN PVOID Parameter3
00071 );
00072
00073
VOID
00074
KiSynchronizePATLoad (
00075 IN PNEW_PAT Context
00076 );
00077
00078
#if DBG
00079
VOID
00080 KiDumpPAT (
00081 PUCHAR DebugString,
00082
PAT Attributes
00083 );
00084
#endif
00085
00086
#ifdef ALLOC_PRAGMA
00087
#pragma alloc_text(PAGELK,KiInitializePAT)
00088
#pragma alloc_text(PAGELK,KiLoadPAT)
00089
#pragma alloc_text(PAGELK,KiLoadPATTarget)
00090
#pragma alloc_text(PAGELK,KiSynchronizePATLoad)
00091
#endif
00092
00093
VOID
00094 KeRestorePAT (
00095 VOID
00096 )
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 {
00113
if (
KeFeatureBits &
KF_PAT) {
00114
KiInitializePAT();
00115 }
00116 }
00117
00118
VOID
00119 KiInitializePAT (
00120 VOID
00121 )
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
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
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
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
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
00211
00212
00213
KiIpiStallOnPacketTargets(TargetProcessors);
00214
00215
00216
00217
00218
00219
00220
00221
KeRaiseIrql (
HIGH_LEVEL, &NewIrql);
00222
00223
00224
00225
00226
00227
00228 Prcb->ReverseStall += 1;
00229 }
00230
00231
#endif
00232
00233
00234
00235
00236
00237
KiLoadPAT(&NewPAT);
00238
00239
00240
00241
00242
00243
KiUnlockContextSwap(OldIrql);
00244
MmEnablePAT();
00245
return;
00246 }
00247
00248
VOID
00249 KiLoadPATTarget (
00250 IN PKIPI_CONTEXT SignalDone,
00251 IN PVOID NewPAT,
00252 IN PVOID Parameter2,
00253 IN PVOID Parameter3
00254 )
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 {
00271
PNEW_PAT Context;
00272
00273 Context = (
PNEW_PAT) NewPAT;
00274
00275
00276
00277
00278
00279 KiIpiSignalPacketDoneAndStall (SignalDone, Context->
TargetPhase);
00280
00281
00282
00283
00284
00285
KiLoadPAT (Context);
00286 }
00287
00288
VOID
00289 KiLoadPAT (
00290 IN PNEW_PAT Context
00291 )
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 {
00308 BOOLEAN Enable;
00309 ULONG HldCr0, HldCr4,
Index;
00310
00311
00312
00313
00314
00315 Enable =
KiDisableInterrupts();
00316
00317
00318
00319
00320
00321
KiSynchronizePATLoad (Context);
00322
00323 _asm {
00324 ;
00325 ; Get current CR0
00326 ;
00327
00328 mov eax, cr0
00329 mov HldCr0, eax
00330
00331 ;
00332 ; Disable caching & line fill
00333 ;
00334
00335 and eax, not CR0_NW
00336 or eax, CR0_CD
00337 mov cr0, eax
00338
00339 ;
00340 ; Flush caches
00341 ;
00342
00343 ;
00344 ; wbinvd
00345 ;
00346
00347 _emit 0Fh
00348 _emit 09h
00349
00350 ;
00351 ; Get current cr4
00352 ;
00353
00354 _emit 0Fh
00355 _emit 20h
00356 _emit 0E0h ; mov eax, cr4
00357 mov HldCr4, eax
00358
00359 ;
00360 ; Disable global page
00361 ;
00362
00363 and eax, not CR4_PGE
00364 _emit 0Fh
00365 _emit 22h
00366 _emit 0E0h ; mov cr4, eax
00367
00368 ;
00369 ; Flush TLB
00370 ;
00371
00372 mov eax, cr3
00373 mov cr3, eax
00374 }
00375
00376
00377
00378
00379
00380
KiSynchronizePATLoad (Context);
00381
00382
00383
00384
00385
00386
WRMSR (
PAT_MSR, Context->Attributes.QuadPart);
00387
00388
00389
00390
00391
00392
KiSynchronizePATLoad (Context);
00393
00394 _asm {
00395
00396 ;
00397 ; Flush caches.
00398 ;
00399
00400 ;
00401 ; wbinvd
00402 ;
00403
00404 _emit 0Fh
00405 _emit 09h
00406
00407 ;
00408 ; Flush TLBs
00409 ;
00410
00411 mov eax, cr3
00412 mov cr3, eax
00413 }
00414
00415
00416
00417
00418
00419
KiSynchronizePATLoad (Context);
00420
00421 _asm {
00422 ;
00423 ; Restore CR4 (global page enable)
00424 ;
00425
00426 mov eax, HldCr4
00427 _emit 0Fh
00428 _emit 22h
00429 _emit 0E0h ; mov cr4, eax
00430
00431 ;
00432 ; Restore CR0 (cache enable)
00433 ;
00434
00435 mov eax, HldCr0
00436 mov cr0, eax
00437 }
00438
00439
00440
00441
00442
00443
KiRestoreInterrupts (Enable);
00444 }
00445
00446
VOID
00447 KiSynchronizePATLoad (
00448 IN PNEW_PAT Context
00449 )
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 {
00467 ULONG CurrentPhase;
00468
volatile ULONG *TargetPhase;
00469 PKPRCB Prcb;
00470
00471 TargetPhase = Context->TargetPhase;
00472 Prcb =
KeGetCurrentPrcb();
00473
00474
if (Prcb->Number == (CCHAR) Context->Processor) {
00475
00476
00477
00478
00479
00480
while (Context->TargetCount != (ULONG)
KeNumberProcessors - 1) ;
00481
00482
00483
00484
00485
00486 Context->TargetCount = 0;
00487
00488
00489
00490
00491
00492 InterlockedIncrement ((PULONG) TargetPhase);
00493
00494
00495 }
else {
00496
00497
00498
00499
00500
00501 CurrentPhase = *TargetPhase;
00502
00503
00504
00505
00506
00507 InterlockedIncrement ((PULONG) &Context->TargetCount);
00508
00509
00510
00511
00512
00513
while (*TargetPhase == CurrentPhase) ;
00514 }
00515 }