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

flushtb.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 Copyright (c) 1990 Microsoft Corporation 00005 00006 Module Name: 00007 00008 tbflush.c 00009 00010 Abstract: 00011 00012 This module implements machine dependent functions to flush 00013 the translation buffers in an Intel x86 system. 00014 00015 N.B. This module contains only MP versions of the TB flush routines. 00016 The UP versions are macros in ke.h 00017 KeFlushEntireTb remains a routine for the UP system since it is 00018 exported from the kernel for backwards compatibility. 00019 00020 Author: 00021 00022 David N. Cutler (davec) 13-May-1989 00023 00024 Environment: 00025 00026 Kernel mode only. 00027 00028 Revision History: 00029 00030 Shie-Lin Tzong (shielint) 30-Aug-1990 00031 Implement MP version of KeFlushSingleTb and KeFlushEntireTb. 00032 00033 --*/ 00034 00035 #include "ki.h" 00036 00037 VOID 00038 KiFlushTargetEntireTb ( 00039 IN PKIPI_CONTEXT SignalDone, 00040 IN PVOID Invalid, 00041 IN PVOID Parameter2, 00042 IN PVOID Parameter3 00043 ); 00044 00045 VOID 00046 KiFlushTargetMultipleTb ( 00047 IN PKIPI_CONTEXT SignalDone, 00048 IN PVOID Parameter1, 00049 IN PVOID Parameter2, 00050 IN PVOID Parameter3 00051 ); 00052 00053 00054 VOID 00055 KiFlushTargetSingleTb ( 00056 IN PKIPI_CONTEXT SignalDone, 00057 IN PVOID Parameter1, 00058 IN PVOID Parameter2, 00059 IN PVOID Parameter3 00060 ); 00061 00062 HARDWARE_PTE 00063 KiFlushSingleTbSynchronous ( 00064 IN PVOID Virtual, 00065 IN BOOLEAN Invalid, 00066 IN BOOLEAN AllProcessors, 00067 IN PHARDWARE_PTE PtePointer, 00068 IN HARDWARE_PTE PteValue 00069 ); 00070 00071 VOID 00072 KiFlushTargetSingleTbSynchronous ( 00073 IN PKIPI_CONTEXT SignalDone, 00074 IN PVOID Parameter1, 00075 IN PVOID Parameter2, 00076 IN PVOID Parameter3 00077 ); 00078 00079 VOID 00080 Ki386UseSynchronousTbFlush ( 00081 IN volatile PLONG Number 00082 ); 00083 00084 #if defined(NT_UP) 00085 #undef KeFlushEntireTb 00086 #endif 00087 00088 #ifdef ALLOC_PRAGMA 00089 #pragma alloc_text(INIT,Ki386UseSynchronousTbFlush) 00090 #endif 00091 00092 00093 VOID 00094 KeFlushEntireTb ( 00095 IN BOOLEAN Invalid, 00096 IN BOOLEAN AllProcessors 00097 ) 00098 00099 /*++ 00100 00101 Routine Description: 00102 00103 This function flushes the entire translation buffer (TB) on all processors 00104 that are currently running threads which are child of the current process 00105 or flushes the entire translation buffer on all processors in the host 00106 configuration. 00107 00108 Arguments: 00109 00110 Invalid - Supplies a boolean value that specifies the reason for flushing 00111 the translation buffer. 00112 00113 AllProcessors - Supplies a boolean value that determines which translation 00114 buffers are to be flushed. 00115 00116 Return Value: 00117 00118 None. 00119 00120 --*/ 00121 00122 { 00123 00124 KIRQL OldIrql; 00125 PKPRCB Prcb; 00126 PKPROCESS Process; 00127 KAFFINITY TargetProcessors; 00128 00129 // 00130 // Compute the target set of processors, disable context switching, 00131 // and send the flush entire parameters to the target processors, 00132 // if any, for execution. 00133 // 00134 00135 #if defined(NT_UP) 00136 00137 OldIrql = KeRaiseIrqlToSynchLevel(); 00138 00139 #else 00140 00141 if (AllProcessors != FALSE) { 00142 OldIrql = KeRaiseIrqlToSynchLevel(); 00143 Prcb = KeGetCurrentPrcb(); 00144 TargetProcessors = KeActiveProcessors; 00145 00146 } else { 00147 KiLockContextSwap(&OldIrql); 00148 Prcb = KeGetCurrentPrcb(); 00149 Process = Prcb->CurrentThread->ApcState.Process; 00150 TargetProcessors = Process->ActiveProcessors; 00151 } 00152 00153 TargetProcessors &= ~Prcb->SetMember; 00154 if (TargetProcessors != 0) { 00155 KiIpiSendPacket(TargetProcessors, 00156 KiFlushTargetEntireTb, 00157 NULL, 00158 NULL, 00159 NULL); 00160 00161 IPI_INSTRUMENT_COUNT (Prcb->Number, FlushEntireTb); 00162 } 00163 00164 #endif 00165 00166 // 00167 // Flush TB on current processor. 00168 // 00169 00170 KeFlushCurrentTb(); 00171 00172 // 00173 // Wait until all target processors have finished and complete packet. 00174 // 00175 00176 #if defined(NT_UP) 00177 00178 KeLowerIrql(OldIrql); 00179 00180 #else 00181 00182 if (TargetProcessors != 0) { 00183 KiIpiStallOnPacketTargets(TargetProcessors); 00184 } 00185 00186 if (AllProcessors != FALSE) { 00187 KeLowerIrql(OldIrql); 00188 00189 } else { 00190 KiUnlockContextSwap(OldIrql); 00191 } 00192 00193 #endif 00194 00195 return; 00196 } 00197 00198 #if !defined(NT_UP) 00199 00200 00201 VOID 00202 KiFlushTargetEntireTb ( 00203 IN PKIPI_CONTEXT SignalDone, 00204 IN PVOID Parameter1, 00205 IN PVOID Parameter2, 00206 IN PVOID Parameter3 00207 ) 00208 00209 /*++ 00210 00211 Routine Description: 00212 00213 This is the target function for flushing the entire TB. 00214 00215 Arguments: 00216 00217 SignalDone - Supplies a pointer to a variable that is cleared when the 00218 requested operation has been performed. 00219 00220 Parameter1 - Parameter3 - Not used. 00221 00222 Return Value: 00223 00224 None. 00225 00226 --*/ 00227 00228 { 00229 00230 // 00231 // Flush the entire TB on the current processor. 00232 // 00233 00234 KiIpiSignalPacketDone(SignalDone); 00235 KeFlushCurrentTb(); 00236 return; 00237 } 00238 00239 VOID 00240 KeFlushMultipleTb ( 00241 IN ULONG Number, 00242 IN PVOID *Virtual, 00243 IN BOOLEAN Invalid, 00244 IN BOOLEAN AllProcessors, 00245 IN PHARDWARE_PTE *PtePointer OPTIONAL, 00246 IN HARDWARE_PTE PteValue 00247 ) 00248 00249 /*++ 00250 00251 Routine Description: 00252 00253 This function flushes multiple entries from the translation buffer 00254 on all processors that are currently running threads which are 00255 children of the current process or flushes a multiple entries from 00256 the translation buffer on all processors in the host configuration. 00257 00258 Arguments: 00259 00260 Number - Supplies the number of TB entries to flush. 00261 00262 Virtual - Supplies a pointer to an array of virtual addresses that 00263 are within the pages whose translation buffer entries are to be 00264 flushed. 00265 00266 Invalid - Supplies a boolean value that specifies the reason for 00267 flushing the translation buffer. 00268 00269 AllProcessors - Supplies a boolean value that determines which 00270 translation buffers are to be flushed. 00271 00272 PtePointer - Supplies an optional pointer to an array of pointers to 00273 page table entries that receive the specified page table entry 00274 value. 00275 00276 PteValue - Supplies the the new page table entry value. 00277 00278 Return Value: 00279 00280 The previous contents of the specified page table entry is returned 00281 as the function value. 00282 00283 --*/ 00284 00285 { 00286 00287 ULONG Index; 00288 KIRQL OldIrql; 00289 PKPRCB Prcb; 00290 PKPROCESS Process; 00291 KAFFINITY TargetProcessors; 00292 00293 // 00294 // Compute target set of processors. 00295 // 00296 00297 if (AllProcessors != FALSE) { 00298 OldIrql = KeRaiseIrqlToSynchLevel(); 00299 Prcb = KeGetCurrentPrcb(); 00300 TargetProcessors = KeActiveProcessors; 00301 00302 } else { 00303 KiLockContextSwap(&OldIrql); 00304 Prcb = KeGetCurrentPrcb(); 00305 Process = Prcb->CurrentThread->ApcState.Process; 00306 TargetProcessors = Process->ActiveProcessors; 00307 } 00308 00309 TargetProcessors &= ~Prcb->SetMember; 00310 00311 // 00312 // If a page table entry address array is specified, then set the 00313 // specified page table entries to the specific value. 00314 // 00315 00316 if (ARGUMENT_PRESENT(PtePointer)) { 00317 for (Index = 0; Index < Number; Index += 1) { 00318 KI_FILL_PTE(PtePointer[Index], PteValue); 00319 } 00320 } 00321 00322 // 00323 // If any target processors are specified, then send a flush multiple 00324 // packet to the target set of processors. 00325 // 00326 00327 if (TargetProcessors != 0) { 00328 KiIpiSendPacket(TargetProcessors, 00329 KiFlushTargetMultipleTb, 00330 (PVOID)Invalid, 00331 (PVOID)Number, 00332 (PVOID)Virtual); 00333 00334 IPI_INSTRUMENT_COUNT (Prcb->Number, FlushMultipleTb); 00335 } 00336 00337 // 00338 // Flush the specified entries from the TB on the current processor. 00339 // 00340 00341 for (Index = 0; Index < Number; Index += 1) { 00342 KiFlushSingleTb(Invalid, Virtual[Index]); 00343 } 00344 00345 // 00346 // Wait until all target processors have finished and complete packet. 00347 // 00348 00349 if (TargetProcessors != 0) { 00350 KiIpiStallOnPacketTargets(TargetProcessors); 00351 } 00352 00353 // 00354 // Release the context swap lock. 00355 // 00356 00357 if (AllProcessors != FALSE) { 00358 KeLowerIrql(OldIrql); 00359 00360 } else { 00361 KiUnlockContextSwap(OldIrql); 00362 } 00363 00364 return; 00365 } 00366 00367 VOID 00368 KiFlushTargetMultipleTb ( 00369 IN PKIPI_CONTEXT SignalDone, 00370 IN PVOID Invalid, 00371 IN PVOID Number, 00372 IN PVOID Virtual 00373 ) 00374 00375 /*++ 00376 00377 Routine Description: 00378 00379 This is the target function for flushing multiple TB entries. 00380 00381 Arguments: 00382 00383 SignalDone - Supplies a pointer to a variable that is cleared when the 00384 requested operation has been performed. 00385 00386 Invalid - Supplies a bollean value that determines whether the virtual 00387 address is invalid. 00388 00389 Number - Supplies the number of TB entries to flush. 00390 00391 Virtual - Supplies a pointer to an array of virtual addresses that 00392 are within the pages whose translation buffer entries are to be 00393 flushed. 00394 00395 Return Value: 00396 00397 None. 00398 00399 --*/ 00400 00401 { 00402 00403 ULONG Index; 00404 PVOID VirtualAddress[FLUSH_MULTIPLE_MAXIMUM]; 00405 00406 // 00407 // Capture the virtual addresses that are to be flushed from the TB 00408 // on the current processor and signal pack done. 00409 // 00410 00411 for (Index = 0; Index < (ULONG) Number; Index += 1) { 00412 VirtualAddress[Index] = ((PVOID *)(Virtual))[Index]; 00413 } 00414 00415 KiIpiSignalPacketDone(SignalDone); 00416 00417 // 00418 // Flush the specified virtual address for the TB on the current 00419 // processor. 00420 // 00421 00422 for (Index = 0; Index < (ULONG) Number; Index += 1) { 00423 KiFlushSingleTb((BOOLEAN)Invalid, VirtualAddress [Index]); 00424 } 00425 } 00426 00427 HARDWARE_PTE 00428 KeFlushSingleTb ( 00429 IN PVOID Virtual, 00430 IN BOOLEAN Invalid, 00431 IN BOOLEAN AllProcessors, 00432 IN PHARDWARE_PTE PtePointer, 00433 IN HARDWARE_PTE PteValue 00434 ) 00435 00436 /*++ 00437 00438 Routine Description: 00439 00440 This function flushes a single entry from translation buffer (TB) on all 00441 processors that are currently running threads which are child of the current 00442 process or flushes the entire translation buffer on all processors in the 00443 host configuration. 00444 00445 Arguments: 00446 00447 Virtual - Supplies a virtual address that is within the page whose 00448 translation buffer entry is to be flushed. 00449 00450 Invalid - Supplies a boolean value that specifies the reason for flushing 00451 the translation buffer. 00452 00453 AllProcessors - Supplies a boolean value that determines which translation 00454 buffers are to be flushed. 00455 00456 PtePointer - Address of Pte to update with new value. 00457 00458 PteValue - New value to put in the Pte. Will simply be assigned to 00459 *PtePointer, in a fashion correct for the hardware. 00460 00461 Return Value: 00462 00463 Returns the contents of the PtePointer before the new value 00464 is stored. 00465 00466 --*/ 00467 00468 { 00469 00470 KIRQL OldIrql; 00471 PKPRCB Prcb; 00472 PKPROCESS Process; 00473 HARDWARE_PTE OldPteValue; 00474 KAFFINITY TargetProcessors; 00475 00476 // 00477 // Compute target set of processors. 00478 // 00479 00480 if (AllProcessors != FALSE) { 00481 OldIrql = KeRaiseIrqlToSynchLevel(); 00482 Prcb = KeGetCurrentPrcb(); 00483 TargetProcessors = KeActiveProcessors; 00484 00485 } else { 00486 KiLockContextSwap(&OldIrql); 00487 Prcb = KeGetCurrentPrcb(); 00488 Process = Prcb->CurrentThread->ApcState.Process; 00489 TargetProcessors = Process->ActiveProcessors; 00490 } 00491 00492 TargetProcessors &= ~Prcb->SetMember; 00493 00494 // 00495 // Capture the previous contents of the page table entry and set the 00496 // page table entry to the new value. 00497 // 00498 00499 KI_SWAP_PTE(PtePointer, PteValue, OldPteValue); 00500 00501 // 00502 // If any target processors are specified, then send a flush single 00503 // packet to the target set of processors. 00504 // 00505 00506 if (TargetProcessors != 0) { 00507 KiIpiSendPacket(TargetProcessors, 00508 KiFlushTargetSingleTb, 00509 (PVOID)Invalid, 00510 (PVOID)Virtual, 00511 NULL); 00512 00513 IPI_INSTRUMENT_COUNT(Prcb->Number, FlushSingleTb); 00514 } 00515 00516 00517 // 00518 // Flush the specified entry from the TB on the current processor. 00519 // 00520 00521 KiFlushSingleTb(Invalid, Virtual); 00522 00523 // 00524 // Wait until all target processors have finished and complete packet. 00525 // 00526 00527 if (TargetProcessors != 0) { 00528 KiIpiStallOnPacketTargets(TargetProcessors); 00529 } 00530 00531 // 00532 // Release the context swap lock. 00533 // 00534 00535 if (AllProcessors != FALSE) { 00536 KeLowerIrql(OldIrql); 00537 00538 } else { 00539 KiUnlockContextSwap(OldIrql); 00540 } 00541 00542 return(OldPteValue); 00543 } 00544 00545 VOID 00546 KiFlushTargetSingleTb ( 00547 IN PKIPI_CONTEXT SignalDone, 00548 IN PVOID Invalid, 00549 IN PVOID VirtualAddress, 00550 IN PVOID Parameter3 00551 ) 00552 00553 /*++ 00554 00555 Routine Description: 00556 00557 This is the target function for flushing a single TB entry. 00558 00559 Arguments: 00560 00561 SignalDone Supplies a pointer to a variable that is cleared when the 00562 requested operation has been performed. 00563 00564 Invalid - Supplies a bollean value that determines whether the virtual 00565 address is invalid. 00566 00567 Virtual - Supplies a virtual address that is within the page whose 00568 translation buffer entry is to be flushed. 00569 00570 Parameter3 - Not used. 00571 00572 Return Value: 00573 00574 None. 00575 00576 --*/ 00577 00578 { 00579 00580 // 00581 // Flush a single entry from the TB on the current processor. 00582 // 00583 00584 KiIpiSignalPacketDone(SignalDone); 00585 KiFlushSingleTb((BOOLEAN)Invalid, (PVOID)VirtualAddress); 00586 } 00587 00588 HARDWARE_PTE 00589 KiFlushSingleTbSynchronous ( 00590 IN PVOID Virtual, 00591 IN BOOLEAN Invalid, 00592 IN BOOLEAN AllProcessors, 00593 IN PHARDWARE_PTE PtePointer, 00594 IN HARDWARE_PTE PteValue 00595 ) 00596 00597 /*++ 00598 00599 Routine Description: 00600 00601 This function is a slow synchronous version of KeFlushSingleTb. We need 00602 this function as many P6's don't actually know how to deal with PTEs in 00603 an MP safe manner. 00604 00605 Arguments: 00606 00607 See KeFlushSingleTb 00608 00609 Return Value: 00610 00611 See KeFlushSingleTb 00612 00613 --*/ 00614 { 00615 00616 KIRQL OldIrql; 00617 PKPRCB Prcb; 00618 PKPROCESS Process; 00619 HARDWARE_PTE OldPteValue; 00620 KAFFINITY TargetProcessors; 00621 00622 // 00623 // Synchronize will all other single flush calls (and other 00624 // IPIs which use reverse stalls) 00625 // 00626 00627 KiLockContextSwap(&OldIrql); 00628 00629 // 00630 // Compute target set of processors. 00631 // 00632 00633 Prcb = KeGetCurrentPrcb(); 00634 if (AllProcessors != FALSE) { 00635 TargetProcessors = KeActiveProcessors; 00636 } else { 00637 Process = Prcb->CurrentThread->ApcState.Process; 00638 TargetProcessors = Process->ActiveProcessors; 00639 } 00640 00641 TargetProcessors &= ~Prcb->SetMember; 00642 00643 // 00644 // If any target processors are specified, then send a flush single 00645 // packet to the target set of processors. 00646 // 00647 00648 if (TargetProcessors != 0) { 00649 KiIpiSendSynchronousPacket(Prcb, 00650 TargetProcessors, 00651 KiFlushTargetSingleTbSynchronous, 00652 (PVOID)Invalid, 00653 (PVOID)Virtual, 00654 (PVOID)&Prcb->ReverseStall 00655 ); 00656 00657 IPI_INSTRUMENT_COUNT(Prcb->Number, FlushSingleTb); 00658 00659 // 00660 // Wait for the target processors to stall 00661 // 00662 00663 KiIpiStallOnPacketTargets(TargetProcessors); 00664 00665 // 00666 // Capture the previous contents of the page table entry and set the 00667 // page table entry to the new value. 00668 // 00669 00670 KI_SWAP_PTE(PtePointer, PteValue, OldPteValue); 00671 00672 // 00673 // Notify all prcessors it's time to go 00674 // 00675 00676 Prcb->ReverseStall += 1; 00677 00678 } else { 00679 00680 // 00681 // Capture the previous contents of the page table entry and set the 00682 // page table entry to the new value. 00683 // 00684 00685 KI_SWAP_PTE(PtePointer, PteValue, OldPteValue); 00686 } 00687 00688 // 00689 // Flush the specified entry from the TB on the current processor. 00690 // 00691 00692 KiFlushSingleTb(Invalid, Virtual); 00693 00694 // 00695 // Done 00696 // 00697 00698 KiUnlockContextSwap(OldIrql); 00699 return(OldPteValue); 00700 } 00701 00702 VOID 00703 KiFlushTargetSingleTbSynchronous ( 00704 IN PKIPI_CONTEXT SignalDone, 00705 IN PVOID Invalid, 00706 IN PVOID VirtualAddress, 00707 IN PVOID Proceed 00708 ) 00709 00710 /*++ 00711 00712 Routine Description: 00713 00714 This is the target function for flushing a single TB entry synchronously. 00715 00716 Arguments: 00717 00718 SignalDone Supplies a pointer to a variable that is cleared when the 00719 requested operation has been performed. 00720 00721 Invalid - Supplies a bollean value that determines whether the virtual 00722 address is invalid. 00723 00724 Virtual - Supplies a virtual address that is within the page whose 00725 translation buffer entry is to be flushed. 00726 00727 Parameter3 - Not used. 00728 00729 Return Value: 00730 00731 None. 00732 00733 --*/ 00734 00735 { 00736 00737 // 00738 // Flush a single entry from the TB on the current processor. 00739 // 00740 00741 KiIpiSignalPacketDoneAndStall(SignalDone, Proceed); 00742 KiFlushSingleTb((BOOLEAN)Invalid, (PVOID)VirtualAddress); 00743 } 00744 00745 00746 VOID 00747 Ki386UseSynchronousTbFlush ( 00748 IN volatile PLONG Number 00749 ) 00750 { 00751 PKPRCB Prcb; 00752 volatile PUCHAR Patch; 00753 00754 Prcb = KeGetCurrentPrcb(); 00755 Patch = (PUCHAR) KeFlushSingleTb; 00756 00757 // 00758 // Signal we're here and wait for others 00759 // 00760 00761 InterlockedDecrement (Number); 00762 while (*Number) ; 00763 00764 // 00765 // If this is processor 0 apply the patch 00766 // 00767 00768 if (Prcb->Number == 0) { 00769 *((PULONG) &Patch[1]) = ((ULONG) &KiFlushSingleTbSynchronous) - ((ULONG) Patch) - 5; 00770 Patch[0] = 0xe9; 00771 } 00772 00773 // 00774 // Wait for processor 0 to complete installation of handler 00775 // 00776 00777 while (Patch[0] != 0xe9) ; 00778 } 00779 00780 #endif

Generated on Sat May 15 19:40:02 2004 for test by doxygen 1.3.7