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

flushtb.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Module Name: 00004 00005 flushtb.c 00006 00007 Abstract: 00008 00009 This module implement machine dependent functions to flush the 00010 translation buffer and synchronize PIDs in an MP system. 00011 00012 Author: 00013 00014 Koichi Yamada 2-Jan-95 00015 00016 Environment: 00017 00018 Kernel mode only. 00019 00020 Revision History: 00021 00022 --*/ 00023 00024 #include "ki.h" 00025 #include "mm.h" 00026 #include "..\..\mm\mi.h" 00027 00028 extern KSPIN_LOCK KiTbBroadcastLock; 00029 extern KSPIN_LOCK KiMasterRidLock; 00030 00031 #define _x256mb (1024*1024*256) 00032 00033 //extern VOID MiCheckPointBreak(VOID); 00034 00035 #define KiFlushSingleTbGlobal(Invalid, Va) __ptcga((__int64)Va, PAGE_SHIFT << 2) 00036 00037 #define KiFlushSingleTbLocal(Invalid, va) __ptcl((__int64)va, PAGE_SHIFT << 2) 00038 00039 #define KiTbSynchronizeGlobal() { __mf(); __isrlz(); } 00040 00041 #define KiTbSynchronizeLocal() { __isrlz(); } 00042 00043 #define KiFlush2gbTbGlobal(Invalid) \ 00044 { \ 00045 __ptcga((__int64)0, 28 << 2); \ 00046 __ptcg((__int64)_x256mb, 28 << 2); \ 00047 __ptcg((__int64)_x256mb*2,28 << 2); \ 00048 __ptcg((__int64)_x256mb*3, 28 << 2); \ 00049 __ptcg((__int64)_x256mb*4, 28 << 2); \ 00050 __ptcg((__int64)_x256mb*5, 28 << 2); \ 00051 __ptcg((__int64)_x256mb*6, 28 << 2); \ 00052 __ptcg((__int64)_x256mb*7, 28 << 2); \ 00053 } 00054 00055 #define KiFlush2gbTbLocal(Invalid) \ 00056 { \ 00057 __ptcl((__int64)0, 28 << 2); \ 00058 __ptcl((__int64)_x256mb, 28 << 2); \ 00059 __ptcl((__int64)_x256mb*2,28 << 2); \ 00060 __ptcl((__int64)_x256mb*3, 28 << 2); \ 00061 __ptcl((__int64)_x256mb*4, 28 << 2); \ 00062 __ptcl((__int64)_x256mb*5, 28 << 2); \ 00063 __ptcl((__int64)_x256mb*6, 28 << 2); \ 00064 __ptcl((__int64)_x256mb*7, 28 << 2); \ 00065 } 00066 00067 00068 VOID 00069 KiSetProcessRid ( 00070 ULONG NewProcessRid 00071 ); 00072 00073 VOID 00074 KiSetRegionRegister ( 00075 PVOID VirtualAddress, 00076 ULONGLONG Contents 00077 ); 00078 00079 00080 // 00081 // Define forward referenced prototypes. 00082 // 00083 00084 VOID 00085 KiFlushEntireTbTarget ( 00086 IN PULONG SignalDone, 00087 IN PVOID Parameter1, 00088 IN PVOID Parameter2, 00089 IN PVOID Parameter3 00090 ); 00091 00092 VOID 00093 KiInvalidateForwardProgressTbBuffer( 00094 KAFFINITY TargetProcessors 00095 ); 00096 00097 VOID 00098 KiFlushForwardProgressTbBuffer( 00099 KAFFINITY TargetProcessors 00100 ); 00101 00102 VOID 00103 KiFlushForwardProgressTbBufferLocal( 00104 VOID 00105 ); 00106 00107 00108 VOID 00109 KeFlushEntireTb ( 00110 IN BOOLEAN Invalid, 00111 IN BOOLEAN AllProcessors 00112 ) 00113 00114 /*++ 00115 00116 Routine Description: 00117 00118 This function flushes the entire translation buffer (TB) on all 00119 processors that are currently running threads which are children 00120 of the current process or flushes the entire translation buffer 00121 on all processors in the host configuration. 00122 00123 Arguments: 00124 00125 Invalid - Supplies a boolean value that specifies the reason for 00126 flushing the translation buffer. 00127 00128 AllProcessors - Supplies a boolean value that determines which 00129 translation buffers are to be flushed. 00130 00131 Return Value: 00132 00133 None. 00134 00135 00136 --*/ 00137 00138 { 00139 00140 KIRQL OldIrql; 00141 KAFFINITY TargetProcessors; 00142 PKTHREAD Thread; 00143 BOOLEAN NeedTbFlush = FALSE; 00144 00145 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); 00146 00147 OldIrql = KeRaiseIrqlToSynchLevel(); 00148 00149 #if !defined(NT_UP) 00150 TargetProcessors = KeActiveProcessors; 00151 TargetProcessors &= PCR->NotMember; 00152 if (TargetProcessors != 0) { 00153 KiIpiSendPacket(TargetProcessors, 00154 KiFlushEntireTbTarget, 00155 (PVOID)NeedTbFlush, 00156 NULL, 00157 NULL); 00158 } 00159 00160 if (PsGetCurrentProcess()->Wow64Process != 0) { 00161 KiInvalidateForwardProgressTbBuffer(TargetProcessors); 00162 } 00163 #endif 00164 00165 KeFlushCurrentTb(); 00166 00167 // 00168 // Wait until all target processors have finished. 00169 // 00170 00171 #if !defined(NT_UP) 00172 00173 if (TargetProcessors != 0) { 00174 KiIpiStallOnPacketTargets(TargetProcessors); 00175 } 00176 00177 #endif 00178 00179 // 00180 // Wait until all target processors have finished. 00181 // 00182 00183 #if defined(NT_UP) 00184 00185 KeLowerIrql(OldIrql); 00186 00187 #else 00188 00189 if (TargetProcessors != 0) { 00190 KiIpiStallOnPacketTargets(TargetProcessors); 00191 } 00192 00193 KeLowerIrql(OldIrql); 00194 00195 #endif 00196 00197 return; 00198 } 00199 00200 00201 00202 VOID 00203 KiFlushEntireTbTarget ( 00204 IN PULONG SignalDone, 00205 IN PVOID Parameter1, 00206 IN PVOID Parameter2, 00207 IN PVOID Parameter3 00208 ) 00209 00210 /*++ 00211 00212 Routine Description: 00213 00214 This is the target function for flushing the entire TB. 00215 00216 Arguments: 00217 00218 SignalDone Supplies a pointer to a variable that is cleared when the 00219 requested operation has been performed. 00220 00221 Parameter1 - Parameter3 - Not used. 00222 00223 Return Value: 00224 00225 None. 00226 00227 --*/ 00228 00229 { 00230 00231 #if !defined(NT_UP) 00232 00233 // 00234 // Flush the entire TB on the current processor. 00235 // 00236 00237 KiIpiSignalPacketDone(SignalDone); 00238 00239 KeFlushCurrentTb(); 00240 00241 #endif 00242 00243 return; 00244 } 00245 00246 VOID 00247 KeFlushMultipleTb ( 00248 IN ULONG Number, 00249 IN PVOID *Virtual, 00250 IN BOOLEAN Invalid, 00251 IN BOOLEAN AllProcessors, 00252 IN PHARDWARE_PTE *PtePointer OPTIONAL, 00253 IN HARDWARE_PTE PteValue 00254 ) 00255 00256 /*++ 00257 00258 Routine Description: 00259 00260 This function flushes multiple entries from the translation buffer 00261 on all processors that are currently running threads which are 00262 children of the current process or flushes multiple entries from 00263 the translation buffer on all processors in the host configuration. 00264 00265 N.B. The specified translation entries on all processors in the host 00266 configuration are always flushed since PowerPC TB is tagged by 00267 VSID and translations are held across context switch boundaries. 00268 00269 Arguments: 00270 00271 Number - Supplies the number of TB entries to flush. 00272 00273 Virtual - Supplies a pointer to an array of virtual addresses that 00274 are within the pages whose translation buffer entries are to be 00275 flushed. 00276 00277 Invalid - Supplies a boolean value that specifies the reason for 00278 flushing the translation buffer. 00279 00280 AllProcessors - Supplies a boolean value that determines which 00281 translation buffers are to be flushed. 00282 00283 PtePointer - Supplies an optional pointer to an array of pointers to 00284 page table entries that receive the specified page table entry 00285 value. 00286 00287 PteValue - Supplies the the new page table entry value. 00288 00289 Return Value: 00290 00291 None. 00292 00293 --*/ 00294 00295 { 00296 00297 ULONG Index; 00298 PKPRCB Prcb; 00299 KAFFINITY TargetProcessors; 00300 PWOW64_PROCESS Wow64Process; 00301 KIRQL OldIrql; 00302 BOOLEAN Flush2gb = FALSE; 00303 00304 #if 0 00305 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); 00306 #endif 00307 00308 OldIrql = KeRaiseIrqlToSynchLevel(); 00309 00310 Wow64Process = PsGetCurrentProcess()->Wow64Process; 00311 00312 #ifdef MI_ALTFLG_FLUSH2G 00313 if ((Wow64Process != NULL) && 00314 ((Wow64Process->AltFlags & MI_ALTFLG_FLUSH2G) != 0)) { 00315 Flush2gb = TRUE; 00316 } 00317 #endif 00318 00319 // 00320 // If a page table entry address array is specified, then set the 00321 // specified page table entries to the specific value. 00322 // 00323 00324 #if !defined(NT_UP) 00325 00326 TargetProcessors = KeActiveProcessors; 00327 TargetProcessors &= PCR->NotMember; 00328 00329 if (TargetProcessors != 0) { 00330 00331 // 00332 // Acquire a global lock. Only one processor at a time can issue 00333 // a PTC.G operation. 00334 // 00335 00336 KiAcquireSpinLock(&KiTbBroadcastLock); 00337 00338 for (Index = 0; Index < Number; Index += 1) { 00339 if (ARGUMENT_PRESENT(PtePointer)) { 00340 *PtePointer[Index] = PteValue; 00341 } 00342 00343 // 00344 // Flush the specified TB on each processor. Hardware automatically 00345 // perform broadcasts if MP. 00346 // 00347 00348 KiFlushSingleTbGlobal(Invalid, Virtual[Index]); 00349 } 00350 00351 if (Wow64Process != NULL) { 00352 KiFlushForwardProgressTbBuffer(TargetProcessors); 00353 } 00354 00355 if (Flush2gb == TRUE) { 00356 KiFlush2gbTbGlobal(Invalid); 00357 } 00358 00359 // 00360 // Wait for the broadcast to be complete. 00361 // 00362 00363 KiTbSynchronizeGlobal(); 00364 00365 KiReleaseSpinLock(&KiTbBroadcastLock); 00366 00367 } 00368 else { 00369 00370 for (Index = 0; Index < Number; Index += 1) { 00371 if (ARGUMENT_PRESENT(PtePointer)) { 00372 *PtePointer[Index] = PteValue; 00373 } 00374 00375 // 00376 // Flush the specified TB on the local processor. No broadcast is 00377 // performed. 00378 // 00379 00380 KiFlushSingleTbLocal(Invalid, Virtual[Index]); 00381 } 00382 00383 if (Wow64Process != NULL) { 00384 KiFlushForwardProgressTbBufferLocal(); 00385 } 00386 00387 if (Flush2gb == TRUE) { 00388 KiFlush2gbTbLocal(Invalid); 00389 } 00390 00391 KiTbSynchronizeLocal(); 00392 } 00393 00394 #else 00395 for (Index = 0; Index < Number; Index += 1) { 00396 if (ARGUMENT_PRESENT(PtePointer)) { 00397 *PtePointer[Index] = PteValue; 00398 } 00399 00400 // 00401 // Flush the specified TB on the local processor. No broadcast is 00402 // performed. 00403 // 00404 00405 KiFlushSingleTbLocal(Invalid, Virtual[Index]); 00406 } 00407 00408 if (Wow64Process != NULL) { 00409 KiFlushForwardProgressTbBufferLocal(); 00410 } 00411 00412 if (Flush2gb == TRUE) { 00413 KiFlush2gbTbLocal(Invalid); 00414 } 00415 00416 KiTbSynchronizeLocal(); 00417 00418 #endif 00419 00420 KeLowerIrql(OldIrql); 00421 00422 return; 00423 } 00424 00425 00426 HARDWARE_PTE 00427 KeFlushSingleTb ( 00428 IN PVOID Virtual, 00429 IN BOOLEAN Invalid, 00430 IN BOOLEAN AllProcessors, 00431 IN PHARDWARE_PTE PtePointer, 00432 IN HARDWARE_PTE PteValue 00433 ) 00434 00435 /*++ 00436 00437 Routine Description: 00438 00439 This function flushes a single entry from the translation buffer 00440 on all processors that are currently running threads which are 00441 children of the current process or flushes a single entry from 00442 the translation buffer on all processors in the host configuration. 00443 00444 N.B. The specified translation entry on all processors in the host 00445 configuration is always flushed since PowerPC TB is tagged by 00446 VSID and translations are held across context switch boundaries. 00447 00448 Arguments: 00449 00450 Virtual - Supplies a virtual address that is within the page whose 00451 translation buffer entry is to be flushed. 00452 00453 Invalid - Supplies a boolean value that specifies the reason for 00454 flushing the translation buffer. 00455 00456 AllProcessors - Supplies a boolean value that determines which 00457 translation buffers are to be flushed. 00458 00459 PtePointer - Supplies a pointer to the page table entry which 00460 receives the specified value. 00461 00462 PteValue - Supplies the the new page table entry value. 00463 00464 Return Value: 00465 00466 The previous contents of the specified page table entry is returned 00467 as the function value. 00468 00469 --*/ 00470 00471 { 00472 00473 HARDWARE_PTE OldPte; 00474 PKPRCB Prcb; 00475 KAFFINITY TargetProcessors; 00476 PWOW64_PROCESS Wow64Process; 00477 KIRQL OldIrql; 00478 BOOLEAN Flush2gb = FALSE; 00479 00480 #if 0 00481 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); 00482 #endif 00483 00484 // 00485 // Compute the target set of processors. 00486 // 00487 00488 OldIrql = KeRaiseIrqlToSynchLevel(); 00489 00490 // 00491 // Check to see if it is the Wow64 process 00492 // 00493 00494 Wow64Process = PsGetCurrentProcess()->Wow64Process; 00495 00496 #ifdef MI_ALTFLG_FLUSH2G 00497 if ((Wow64Process != NULL) && 00498 ((Wow64Process->AltFlags & MI_ALTFLG_FLUSH2G) != 0)) { 00499 Flush2gb = TRUE; 00500 } 00501 #endif 00502 00503 // 00504 // Capture the previous contents of the page table entry and set the 00505 // page table entry to the new value. 00506 // 00507 00508 OldPte = *PtePointer; 00509 *PtePointer = PteValue; 00510 00511 #if !defined(NT_UP) 00512 00513 TargetProcessors = KeActiveProcessors; 00514 TargetProcessors &= PCR->NotMember; 00515 00516 if (TargetProcessors != 0) { 00517 00518 // 00519 // Flush the specified TB on each processor. Hardware automatically 00520 // perform broadcasts if MP. 00521 // 00522 00523 KiAcquireSpinLock(&KiTbBroadcastLock); 00524 00525 KiFlushSingleTbGlobal(Invalid, Virtual); 00526 00527 if (Wow64Process != NULL) { 00528 KiFlushForwardProgressTbBuffer(TargetProcessors); 00529 } 00530 00531 if (Flush2gb) { 00532 KiFlush2gbTbGlobal(Invalid); 00533 } 00534 00535 KiTbSynchronizeGlobal(); 00536 00537 KiReleaseSpinLock(&KiTbBroadcastLock); 00538 00539 } 00540 else { 00541 00542 // 00543 // Flush the specified TB on the local processor. No broadcast is 00544 // performed. 00545 // 00546 00547 KiFlushSingleTbLocal(Invalid, Virtual); 00548 00549 if (Wow64Process != NULL) { 00550 KiFlushForwardProgressTbBufferLocal(); 00551 } 00552 00553 if (Flush2gb == TRUE) { 00554 KiFlush2gbTbLocal(Invalid); 00555 } 00556 00557 KiTbSynchronizeLocal(); 00558 00559 } 00560 00561 #else 00562 00563 // 00564 // Flush the specified entry from the TB on the local processor. 00565 // 00566 00567 KiFlushSingleTbLocal(Invalid, Virtual); 00568 00569 if (Wow64Process != NULL) { 00570 KiFlushForwardProgressTbBufferLocal(); 00571 } 00572 00573 if (Flush2gb == TRUE) { 00574 KiFlush2gbTbLocal(Invalid); 00575 } 00576 00577 KiTbSynchronizeLocal(); 00578 00579 #endif 00580 00581 // 00582 // Wait until all target processors have finished. 00583 // 00584 00585 KeLowerIrql(OldIrql); 00586 00587 // 00588 // Return the previous page table entry value. 00589 // 00590 00591 return OldPte; 00592 } 00593 00594 VOID 00595 KiInvalidateForwardProgressTbBuffer( 00596 KAFFINITY TargetProcessors 00597 ) 00598 { 00599 PKPRCB Prcb; 00600 ULONG BitNumber; 00601 PKPROCESS CurrentProcess; 00602 PKPROCESS TargetProcess; 00603 PKPCR Pcr; 00604 ULONG i; 00605 00606 CurrentProcess = KeGetCurrentThread()->ApcState.Process; 00607 00608 // 00609 // Invalidate the ForwardProgressTb buffer on the current processor 00610 // 00611 00612 for (i = 0; i < MAXIMUM_FWP_BUFFER_ENTRY; i += 1) { 00613 00614 PCR->ForwardProgressBuffer[(i*2)+1] = 0; 00615 00616 } 00617 00618 // 00619 // Invalidate the ForwardProgressTb buffer on all the other processors 00620 // 00621 00622 while (TargetProcessors != 0) { 00623 00624 BitNumber = KeFindFirstSetRightMember(TargetProcessors); 00625 ClearMember(BitNumber, TargetProcessors); 00626 Prcb = KiProcessorBlock[BitNumber]; 00627 00628 Pcr = KSEG_ADDRESS(Prcb->PcrPage); 00629 00630 TargetProcess = Pcr->CurrentThread->ApcState.Process; 00631 00632 if (TargetProcess == CurrentProcess) { 00633 00634 for (i = 0; i < MAXIMUM_FWP_BUFFER_ENTRY; i += 1) { 00635 00636 Pcr->ForwardProgressBuffer[(i*2)+1] = 0; 00637 00638 } 00639 } 00640 } 00641 } 00642 00643 VOID 00644 KiFlushForwardProgressTbBuffer( 00645 KAFFINITY TargetProcessors 00646 ) 00647 { 00648 PKPRCB Prcb; 00649 ULONG BitNumber; 00650 PKPROCESS CurrentProcess; 00651 PKPROCESS TargetProcess; 00652 PKPCR Pcr; 00653 ULONG i; 00654 PVOID Va; 00655 volatile ULONGLONG *PointerPte; 00656 00657 CurrentProcess = KeGetCurrentThread()->ApcState.Process; 00658 00659 // 00660 // Flush the ForwardProgressTb buffer on the current processor 00661 // 00662 00663 for (i = 0; i < MAXIMUM_FWP_BUFFER_ENTRY; i += 1) { 00664 00665 Va = (PVOID)PCR->ForwardProgressBuffer[i*2]; 00666 PointerPte = &PCR->ForwardProgressBuffer[(i*2)+1]; 00667 00668 if (*PointerPte != 0) { 00669 *PointerPte = 0; 00670 KiFlushSingleTbGlobal(Invalid, Va); 00671 } 00672 00673 } 00674 00675 // 00676 // Flush the ForwardProgressTb buffer on all the processors 00677 // 00678 00679 while (TargetProcessors != 0) { 00680 00681 BitNumber = KeFindFirstSetRightMember(TargetProcessors); 00682 ClearMember(BitNumber, TargetProcessors); 00683 Prcb = KiProcessorBlock[BitNumber]; 00684 00685 Pcr = KSEG_ADDRESS(Prcb->PcrPage); 00686 00687 TargetProcess = Pcr->CurrentThread->ApcState.Process; 00688 00689 if (TargetProcess == CurrentProcess) { 00690 00691 for (i = 0; i < MAXIMUM_FWP_BUFFER_ENTRY; i += 1) { 00692 00693 Va = (PVOID)Pcr->ForwardProgressBuffer[i*2]; 00694 PointerPte = &Pcr->ForwardProgressBuffer[(i*2)+1]; 00695 00696 if (*PointerPte != 0) { 00697 *PointerPte = 0; 00698 KiFlushSingleTbGlobal(Invalid, Va); 00699 } 00700 } 00701 } 00702 } 00703 } 00704 00705 VOID 00706 KiFlushForwardProgressTbBufferLocal( 00707 VOID 00708 ) 00709 { 00710 ULONG i; 00711 PVOID Va; 00712 volatile ULONGLONG *PointerPte; 00713 00714 // 00715 // Flush the ForwardProgressTb buffer on the current processor 00716 // 00717 00718 for (i = 0; i < MAXIMUM_FWP_BUFFER_ENTRY; i += 1) { 00719 00720 Va = (PVOID)PCR->ForwardProgressBuffer[i*2]; 00721 PointerPte = &PCR->ForwardProgressBuffer[(i*2)+1]; 00722 00723 if (*PointerPte != 0) { 00724 *PointerPte = 0; 00725 KiFlushSingleTbLocal(Invalid, Va); 00726 } 00727 00728 } 00729 } 00730 00731 00732 ULONG 00733 KiGetNewRid ( 00734 IN PULONG ProcessNewRid, 00735 IN PULONGLONG ProcessNewSequence 00736 ) 00737 00738 /*++ 00739 00740 Routine Description: 00741 00742 Generate a new region id. If the region id wraps then the TBs of 00743 all the processors need to be flushed. 00744 00745 Arguments: 00746 00747 ProcessNewRid (a0) - Supplies a pointer to rid of new process (64-bit). 00748 00749 ProcessNewSeqNum (a1) - Pointer to new process sequence number (64-bit). 00750 00751 Return Value: 00752 00753 New rid value 00754 00755 Notes: 00756 00757 This routine called by KiSwapProcess only. 00758 00759 Environment: 00760 00761 Kernel mode. 00762 KiLockDispaterLock or LockQueuedDispatcherLock is held 00763 00764 --*/ 00765 00766 { 00767 00768 ULONG NewRid; 00769 KAFFINITY TargetProcessors; 00770 00771 KiMasterRid += 1; 00772 00773 if (KiMasterRid <= MAXIMUM_RID) { 00774 00775 // 00776 // Update Process->ProcessRid and Process->ProcessSequence. 00777 // 00778 00779 *ProcessNewRid = KiMasterRid; 00780 *ProcessNewSequence = KiMasterSequence; 00781 00782 return (*ProcessNewRid); 00783 } 00784 00785 // 00786 // Region ID must be recycled. 00787 // 00788 00789 00790 KiMasterRid = START_PROCESS_RID; 00791 00792 KiMasterSequence += 1; 00793 00794 if (KiMasterSequence > MAXIMUM_SEQUENCE) { 00795 00796 KiMasterSequence = START_SEQUENCE; 00797 00798 } 00799 00800 // 00801 // Update new process's ProcessRid and ProcessSequence. 00802 // 00803 00804 *ProcessNewRid = KiMasterRid; 00805 *ProcessNewSequence = KiMasterSequence; 00806 00807 #if !defined(NT_UP) 00808 00809 // 00810 // Broadcast TB flush. 00811 // 00812 00813 TargetProcessors = KeActiveProcessors; 00814 TargetProcessors &= PCR->NotMember; 00815 if (TargetProcessors != 0) { 00816 KiIpiSendPacket(TargetProcessors, 00817 KiFlushEntireTbTarget, 00818 (PVOID)TRUE, 00819 NULL, 00820 NULL); 00821 } 00822 00823 #endif 00824 00825 KeFlushCurrentTb(); 00826 00827 00828 #if !defined(NT_UP) 00829 00830 // 00831 // Wait until all target processors have finished. 00832 // 00833 00834 if (TargetProcessors != 0) { 00835 KiIpiStallOnPacketTargets(TargetProcessors); 00836 } 00837 00838 #endif 00839 00840 return *ProcessNewRid; 00841 }

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