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

pat.c

Go to the documentation of this file.
00001 /*++ 00002 Copyright (c) 1997-8 Microsoft Corporation 00003 00004 Module Name: 00005 00006 pat.c 00007 00008 Abstract: 00009 00010 This module implements interfaces that set the Page Attribute 00011 Table. These entry points only exist on i386 machines. 00012 00013 Author: 00014 00015 Shivnandan Kaushik (Intel Corp.) 00016 00017 Environment: 00018 00019 Kernel mode only. 00020 00021 Revision History: 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 // Structure used for PAT initialization 00035 00036 typedef struct _NEW_PAT { 00037 00038 PAT Attributes; 00039 00040 // IPI context to coordinate concurrent PAT update 00041 00042 ULONG Processor; 00043 volatile ULONG TargetCount; 00044 volatile ULONG *TargetPhase; 00045 00046 } NEW_PAT, *PNEW_PAT; 00047 00048 // Prototypes 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 Routine Description: 00099 00100 Reinitialize the Page Attribute Table (PAT) on all processors. 00101 00102 N.B. The caller must have the PAGELK code locked 00103 00104 Arguments: 00105 00106 None. 00107 00108 Return Value: 00109 00110 None. 00111 --*/ 00112 { 00113 if (KeFeatureBits & KF_PAT) { 00114 KiInitializePAT(); 00115 } 00116 } 00117 00118 VOID 00119 KiInitializePAT ( 00120 VOID 00121 ) 00122 /*++ 00123 00124 Routine Description: 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 } 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 Routine Description: 00258 00259 Synchronize with target processors prior to PAT modification. 00260 00261 Arguments: 00262 00263 Context - Context which includes the PAT to load 00264 00265 Return Value: 00266 00267 None 00268 00269 --*/ 00270 { 00271 PNEW_PAT Context; 00272 00273 Context = (PNEW_PAT) NewPAT; 00274 00275 // 00276 // Wait for all processors to be ready 00277 // 00278 00279 KiIpiSignalPacketDoneAndStall (SignalDone, Context->TargetPhase); 00280 00281 // 00282 // Update PAT 00283 // 00284 00285 KiLoadPAT (Context); 00286 } 00287 00288 VOID 00289 KiLoadPAT ( 00290 IN PNEW_PAT Context 00291 ) 00292 /*++ 00293 00294 Routine Description: 00295 00296 This function loads the PAT to all processors. 00297 00298 Arguments: 00299 00300 Context - Context which includes new PAT to load 00301 00302 Return Value: 00303 00304 PAT on all processors programmed to new values 00305 00306 --*/ 00307 { 00308 BOOLEAN Enable; 00309 ULONG HldCr0, HldCr4, Index; 00310 00311 // 00312 // Disable interrupts 00313 // 00314 00315 Enable = KiDisableInterrupts(); 00316 00317 // 00318 // Synchronize all processors 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 // Synchronize all processors 00378 // 00379 00380 KiSynchronizePATLoad (Context); 00381 00382 // 00383 // Load new PAT 00384 // 00385 00386 WRMSR (PAT_MSR, Context->Attributes.QuadPart); 00387 00388 // 00389 // Synchronize all processors 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 // Synchronize all processors 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 // Restore interrupts and return 00441 // 00442 00443 KiRestoreInterrupts (Enable); 00444 } 00445 00446 VOID 00447 KiSynchronizePATLoad ( 00448 IN PNEW_PAT Context 00449 ) 00450 /*++ 00451 00452 Routine Description: 00453 00454 This function synchronizes all processors during the various phases 00455 of modifying the PAT. 00456 00457 Arguments: 00458 00459 Context - Context which includes the barrier synchronization counter. 00460 00461 Return Value: 00462 00463 PAT on all processors programmed to new values 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 // Wait for all processors to signal 00478 // 00479 00480 while (Context->TargetCount != (ULONG) KeNumberProcessors - 1) ; 00481 00482 // 00483 // Reset count for next time 00484 // 00485 00486 Context->TargetCount = 0; 00487 00488 // 00489 // Let waiting processor go to next synchronization point 00490 // 00491 00492 InterlockedIncrement ((PULONG) TargetPhase); 00493 00494 00495 } else { 00496 00497 // 00498 // Get current phase 00499 // 00500 00501 CurrentPhase = *TargetPhase; 00502 00503 // 00504 // Signal that we have completed the current phase 00505 // 00506 00507 InterlockedIncrement ((PULONG) &Context->TargetCount); 00508 00509 // 00510 // Wait for new phase to begin 00511 // 00512 00513 while (*TargetPhase == CurrentPhase) ; 00514 } 00515 }

Generated on Sat May 15 19:41:08 2004 for test by doxygen 1.3.7