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

flush.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1990 Microsoft Corporation 00004 00005 Module Name: 00006 00007 flush.c 00008 00009 Abstract: 00010 00011 This module implements MIPS machine dependent kernel functions to flush 00012 the data and instruction caches and to flush I/O buffers. 00013 00014 Author: 00015 00016 David N. Cutler (davec) 26-Apr-1990 00017 00018 Environment: 00019 00020 Kernel mode only. 00021 00022 Revision History: 00023 00024 --*/ 00025 00026 #include "ki.h" 00027 ULONG ChangeColor; 00028 00029 // 00030 // Define forward referenced prototyes. 00031 // 00032 00033 VOID 00034 KiChangeColorPageTarget ( 00035 IN PULONG SignalDone, 00036 IN PVOID NewColor, 00037 IN PVOID OldColor, 00038 IN PVOID PageFrame 00039 ); 00040 00041 VOID 00042 KiSweepDcacheTarget ( 00043 IN PULONG SignalDone, 00044 IN PVOID Parameter1, 00045 IN PVOID Parameter2, 00046 IN PVOID Parameter3 00047 ); 00048 00049 VOID 00050 KiSweepIcacheTarget ( 00051 IN PULONG SignalDone, 00052 IN PVOID Parameter1, 00053 IN PVOID Parameter2, 00054 IN PVOID Parameter3 00055 ); 00056 00057 VOID 00058 KiSweepIcacheRangeTarget ( 00059 IN PULONG SignalDone, 00060 IN PVOID BaseAddress, 00061 IN PVOID Length, 00062 IN PVOID Parameter3 00063 ); 00064 00065 VOID 00066 KiFlushIoBuffersTarget ( 00067 IN PULONG SignalDone, 00068 IN PVOID Mdl, 00069 IN PVOID ReadOperation, 00070 IN PVOID DmaOperation 00071 ); 00072 00073 VOID 00074 KeChangeColorPage ( 00075 IN PVOID NewColor, 00076 IN PVOID OldColor, 00077 IN ULONG PageFrame 00078 ) 00079 00080 /*++ 00081 00082 Routine Description: 00083 00084 This routine changes the color of a page. 00085 00086 Arguments: 00087 00088 NewColor - Supplies the page aligned virtual address of the new color 00089 the page to change. 00090 00091 OldColor - Supplies the page aligned virtual address of the old color 00092 of the page to change. 00093 00094 PageFrame - Supplies the page frame number of the page that is changed. 00095 00096 Return Value: 00097 00098 None. 00099 00100 --*/ 00101 00102 { 00103 00104 KIRQL OldIrql; 00105 KAFFINITY TargetProcessors; 00106 00107 ASSERT(KeGetCurrentIrql() <= KiSynchIrql); 00108 00109 ChangeColor += 1; 00110 00111 // 00112 // Raise IRQL to synchronization level to prevent a context switch. 00113 // 00114 00115 #if !defined(NT_UP) 00116 00117 OldIrql = KeRaiseIrqlToSynchLevel(); 00118 00119 // 00120 // Compute the set of target processors and send the change color 00121 // parameters to the target processors, if any, for execution. 00122 // 00123 00124 TargetProcessors = KeActiveProcessors & PCR->NotMember; 00125 if (TargetProcessors != 0) { 00126 KiIpiSendPacket(TargetProcessors, 00127 KiChangeColorPageTarget, 00128 (PVOID)NewColor, 00129 (PVOID)OldColor, 00130 (PVOID)PageFrame); 00131 } 00132 00133 #endif 00134 00135 // 00136 // Change the color of the page on the current processor. 00137 // 00138 00139 HalChangeColorPage(NewColor, OldColor, PageFrame); 00140 00141 // 00142 // Wait until all target processors have finished changing the color 00143 // of the page. 00144 // 00145 00146 #if !defined(NT_UP) 00147 00148 if (TargetProcessors != 0) { 00149 KiIpiStallOnPacketTargets(); 00150 } 00151 00152 // 00153 // Lower IRQL to its previous level and return. 00154 // 00155 00156 KeLowerIrql(OldIrql); 00157 00158 #endif 00159 00160 return; 00161 } 00162 00163 VOID 00164 KiChangeColorPageTarget ( 00165 IN PULONG SignalDone, 00166 IN PVOID NewColor, 00167 IN PVOID OldColor, 00168 IN PVOID PageFrame 00169 ) 00170 00171 /*++ 00172 00173 Routine Description: 00174 00175 This is the target function for changing the color of a page. 00176 00177 Arguments: 00178 00179 SignalDone Supplies a pointer to a variable that is cleared when the 00180 requested operation has been performed. 00181 00182 NewColor - Supplies the page aligned virtual address of the new color 00183 the page to change. 00184 00185 OldColor - Supplies the page aligned virtual address of the old color 00186 of the page to change. 00187 00188 PageFrame - Supplies the page frame number of the page that is changed. 00189 00190 Return Value: 00191 00192 None. 00193 00194 --*/ 00195 00196 { 00197 00198 00199 // 00200 // Change the color of the page on the current processor and clear 00201 // change color packet address to signal the source to continue. 00202 // 00203 00204 #if !defined(NT_UP) 00205 00206 HalChangeColorPage(NewColor, OldColor, (ULONG)PageFrame); 00207 KiIpiSignalPacketDone(SignalDone); 00208 00209 #endif 00210 00211 return; 00212 } 00213 00214 VOID 00215 KeSweepDcache ( 00216 IN BOOLEAN AllProcessors 00217 ) 00218 00219 /*++ 00220 00221 Routine Description: 00222 00223 This function flushes the data cache on all processors that are currently 00224 running threads which are children of the current process or flushes the 00225 data cache on all processors in the host configuration. 00226 00227 Arguments: 00228 00229 AllProcessors - Supplies a boolean value that determines which data 00230 caches are flushed. 00231 00232 Return Value: 00233 00234 None. 00235 00236 --*/ 00237 00238 { 00239 00240 KIRQL OldIrql; 00241 KAFFINITY TargetProcessors; 00242 00243 ASSERT(KeGetCurrentIrql() <= KiSynchIrql); 00244 00245 // 00246 // Raise IRQL to synchronization level to prevent a context switch. 00247 // 00248 00249 #if !defined(NT_UP) 00250 00251 OldIrql = KeRaiseIrqlToSynchLevel(); 00252 00253 // 00254 // Compute the set of target processors and send the sweep parameters 00255 // to the target processors, if any, for execution. 00256 // 00257 00258 TargetProcessors = KeActiveProcessors & PCR->NotMember; 00259 if (TargetProcessors != 0) { 00260 KiIpiSendPacket(TargetProcessors, 00261 KiSweepDcacheTarget, 00262 NULL, 00263 NULL, 00264 NULL); 00265 } 00266 00267 #endif 00268 00269 // 00270 // Sweep the data cache on the current processor. 00271 // 00272 00273 HalSweepDcache(); 00274 00275 // 00276 // Wait until all target processors have finished sweeping the their 00277 // data cache. 00278 // 00279 00280 #if !defined(NT_UP) 00281 00282 if (TargetProcessors != 0) { 00283 KiIpiStallOnPacketTargets(); 00284 } 00285 00286 // 00287 // Lower IRQL to its previous level and return. 00288 // 00289 00290 KeLowerIrql(OldIrql); 00291 00292 #endif 00293 00294 return; 00295 } 00296 00297 VOID 00298 KiSweepDcacheTarget ( 00299 IN PULONG SignalDone, 00300 IN PVOID Parameter1, 00301 IN PVOID Parameter2, 00302 IN PVOID Parameter3 00303 ) 00304 00305 /*++ 00306 00307 Routine Description: 00308 00309 This is the target function for sweeping the data cache on target 00310 processors. 00311 00312 Arguments: 00313 00314 SignalDone Supplies a pointer to a variable that is cleared when the 00315 requested operation has been performed. 00316 00317 Parameter1 - Parameter3 - Not used. 00318 00319 Return Value: 00320 00321 None. 00322 00323 --*/ 00324 00325 { 00326 00327 // 00328 // Sweep the data cache on the current processor and clear the sweep 00329 // data cache packet address to signal the source to continue. 00330 // 00331 00332 #if !defined(NT_UP) 00333 00334 HalSweepDcache(); 00335 KiIpiSignalPacketDone(SignalDone); 00336 00337 #endif 00338 00339 return; 00340 } 00341 00342 VOID 00343 KeSweepIcache ( 00344 IN BOOLEAN AllProcessors 00345 ) 00346 00347 /*++ 00348 00349 Routine Description: 00350 00351 This function flushes the instruction cache on all processors that are 00352 currently running threads which are children of the current process or 00353 flushes the instruction cache on all processors in the host configuration. 00354 00355 Arguments: 00356 00357 AllProcessors - Supplies a boolean value that determines which instruction 00358 caches are flushed. 00359 00360 Return Value: 00361 00362 None. 00363 00364 --*/ 00365 00366 { 00367 00368 KIRQL OldIrql; 00369 KAFFINITY TargetProcessors; 00370 00371 ASSERT(KeGetCurrentIrql() <= KiSynchIrql); 00372 00373 // 00374 // Raise IRQL to synchrnization level to prevent a context switch. 00375 // 00376 00377 #if !defined(NT_UP) 00378 00379 OldIrql = KeRaiseIrqlToSynchLevel(); 00380 00381 // 00382 // Compute the set of target processors and send the sweep parameters 00383 // to the target processors, if any, for execution. 00384 // 00385 00386 TargetProcessors = KeActiveProcessors & PCR->NotMember; 00387 if (TargetProcessors != 0) { 00388 KiIpiSendPacket(TargetProcessors, 00389 KiSweepIcacheTarget, 00390 NULL, 00391 NULL, 00392 NULL); 00393 } 00394 00395 #endif 00396 00397 // 00398 // Sweep the instruction cache on the current processor. 00399 // 00400 00401 HalSweepIcache(); 00402 HalSweepDcache(); 00403 00404 // 00405 // Wait until all target processors have finished sweeping the their 00406 // instruction cache. 00407 // 00408 00409 #if !defined(NT_UP) 00410 00411 if (TargetProcessors != 0) { 00412 KiIpiStallOnPacketTargets(); 00413 } 00414 00415 // 00416 // Lower IRQL to its previous level and return. 00417 // 00418 00419 KeLowerIrql(OldIrql); 00420 00421 #endif 00422 00423 return; 00424 } 00425 00426 VOID 00427 KiSweepIcacheTarget ( 00428 IN PULONG SignalDone, 00429 IN PVOID Parameter1, 00430 IN PVOID Parameter2, 00431 IN PVOID Parameter3 00432 ) 00433 00434 /*++ 00435 00436 Routine Description: 00437 00438 This is the target function for sweeping the instruction cache on 00439 target processors. 00440 00441 Arguments: 00442 00443 SignalDone Supplies a pointer to a variable that is cleared when the 00444 requested operation has been performed. 00445 00446 Parameter1 - Parameter3 - Not used. 00447 00448 Return Value: 00449 00450 None. 00451 00452 --*/ 00453 00454 { 00455 00456 // 00457 // Sweep the instruction cache on the current processor and clear 00458 // the sweep instruction cache packet address to signal the source 00459 // to continue. 00460 // 00461 00462 #if !defined(NT_UP) 00463 00464 HalSweepIcache(); 00465 HalSweepDcache(); 00466 KiIpiSignalPacketDone(SignalDone); 00467 00468 #endif 00469 00470 return; 00471 } 00472 00473 VOID 00474 KeSweepIcacheRange ( 00475 IN BOOLEAN AllProcessors, 00476 IN PVOID BaseAddress, 00477 IN ULONG Length 00478 ) 00479 00480 /*++ 00481 00482 Routine Description: 00483 00484 This function flushes the an range of virtual addresses from the primary 00485 instruction cache on all processors that are currently running threads 00486 which are children of the current process or flushes the range of virtual 00487 addresses from the primary instruction cache on all processors in the host 00488 configuration. 00489 00490 Arguments: 00491 00492 AllProcessors - Supplies a boolean value that determines which instruction 00493 caches are flushed. 00494 00495 BaseAddress - Supplies a pointer to the base of the range that is flushed. 00496 00497 Length - Supplies the length of the range that is flushed if the base 00498 address is specified. 00499 00500 Return Value: 00501 00502 None. 00503 00504 --*/ 00505 00506 { 00507 00508 ULONG Offset; 00509 KIRQL OldIrql; 00510 KAFFINITY TargetProcessors; 00511 00512 ASSERT(KeGetCurrentIrql() <= KiSynchIrql); 00513 00514 // 00515 // If the length of the range is greater than the size of the primary 00516 // instruction cache, then set the length of the flush to the size of 00517 // the primary instruction cache and set the base address of zero. 00518 // 00519 // N.B. It is assumed that the size of the primary instruction and 00520 // data caches are the same. 00521 // 00522 00523 if (Length > PCR->FirstLevelIcacheSize) { 00524 BaseAddress = (PVOID)0; 00525 Length = PCR->FirstLevelIcacheSize; 00526 } 00527 00528 // 00529 // Raise IRQL to synchronization level to prevent a context switch. 00530 // 00531 00532 #if !defined(NT_UP) 00533 00534 OldIrql = KeRaiseIrqlToSynchLevel(); 00535 00536 // 00537 // Compute the set of target processors, and send the sweep range 00538 // parameters to the target processors, if any, for execution. 00539 // 00540 00541 TargetProcessors = KeActiveProcessors & PCR->NotMember; 00542 if (TargetProcessors != 0) { 00543 KiIpiSendPacket(TargetProcessors, 00544 KiSweepIcacheRangeTarget, 00545 (PVOID)BaseAddress, 00546 (PVOID)Length, 00547 NULL); 00548 } 00549 00550 #endif 00551 00552 // 00553 // Flush the specified range of virtual addresses from the primary 00554 // instruction cache. 00555 // 00556 00557 Offset = (ULONG)BaseAddress & PCR->IcacheAlignment; 00558 HalSweepIcacheRange((PVOID)((ULONG)BaseAddress & ~PCR->IcacheAlignment), 00559 (Offset + Length + PCR->IcacheAlignment) & ~PCR->IcacheAlignment); 00560 00561 Offset = (ULONG)BaseAddress & PCR->DcacheAlignment; 00562 HalSweepDcacheRange((PVOID)((ULONG)BaseAddress & ~PCR->DcacheAlignment), 00563 (Offset + Length + PCR->DcacheAlignment) & ~PCR->DcacheAlignment); 00564 00565 // 00566 // Wait until all target processors have finished sweeping the specified 00567 // range of addresses from the instruction cache. 00568 // 00569 00570 #if !defined(NT_UP) 00571 00572 if (TargetProcessors != 0) { 00573 KiIpiStallOnPacketTargets(); 00574 } 00575 00576 // 00577 // Lower IRQL to its previous level and return. 00578 // 00579 00580 KeLowerIrql(OldIrql); 00581 00582 #endif 00583 00584 return; 00585 } 00586 00587 VOID 00588 KiSweepIcacheRangeTarget ( 00589 IN PULONG SignalDone, 00590 IN PVOID BaseAddress, 00591 IN PVOID Length, 00592 IN PVOID Parameter3 00593 ) 00594 00595 /*++ 00596 00597 Routine Description: 00598 00599 This is the target function for sweeping a range of addresses from the 00600 instruction cache. 00601 processors. 00602 00603 Arguments: 00604 00605 SignalDone Supplies a pointer to a variable that is cleared when the 00606 requested operation has been performed. 00607 00608 BaseAddress - Supplies a pointer to the base of the range that is flushed. 00609 00610 Length - Supplies the length of the range that is flushed if the base 00611 address is specified. 00612 00613 Parameter3 - Not used. 00614 00615 Return Value: 00616 00617 None. 00618 00619 --*/ 00620 00621 { 00622 00623 ULONG Offset; 00624 00625 // 00626 // Sweep the specified instruction cache range on the current processor. 00627 // 00628 00629 #if !defined(NT_UP) 00630 00631 Offset = (ULONG)(BaseAddress) & PCR->IcacheAlignment; 00632 HalSweepIcacheRange((PVOID)((ULONG)(BaseAddress) & ~PCR->IcacheAlignment), 00633 (Offset + (ULONG)Length + PCR->IcacheAlignment) & ~PCR->IcacheAlignment); 00634 00635 Offset = (ULONG)(BaseAddress) & PCR->DcacheAlignment; 00636 HalSweepDcacheRange((PVOID)((ULONG)(BaseAddress) & ~PCR->DcacheAlignment), 00637 (Offset + (ULONG)Length + PCR->DcacheAlignment) & ~PCR->DcacheAlignment); 00638 00639 KiIpiSignalPacketDone(SignalDone); 00640 00641 #endif 00642 00643 return; 00644 } 00645 00646 VOID 00647 KeFlushIoBuffers ( 00648 IN PMDL Mdl, 00649 IN BOOLEAN ReadOperation, 00650 IN BOOLEAN DmaOperation 00651 ) 00652 00653 /*++ 00654 00655 Routine Description: 00656 00657 This function flushes the I/O buffer specified by the memory descriptor 00658 list from the data cache on all processors. 00659 00660 Arguments: 00661 00662 Mdl - Supplies a pointer to a memory descriptor list that describes the 00663 I/O buffer location. 00664 00665 ReadOperation - Supplies a boolean value that determines whether the I/O 00666 operation is a read into memory. 00667 00668 DmaOperation - Supplies a boolean value that determines whether the I/O 00669 operation is a DMA operation. 00670 00671 Return Value: 00672 00673 None. 00674 00675 --*/ 00676 00677 { 00678 00679 KIRQL OldIrql; 00680 KAFFINITY TargetProcessors; 00681 00682 ASSERT(KeGetCurrentIrql() <= KiSynchIrql); 00683 00684 // 00685 // If the operation is a DMA operation, then check if the flush 00686 // can be avoided because the host system supports the right set 00687 // of cache coherency attributes. Otherwise, the flush can also 00688 // be avoided if the operation is a programmed I/O and not a page 00689 // read. 00690 // 00691 00692 if (DmaOperation != FALSE) { 00693 if (ReadOperation != FALSE) { 00694 if ((KiDmaIoCoherency & DMA_READ_ICACHE_INVALIDATE) != 0) { 00695 00696 ASSERT((KiDmaIoCoherency & DMA_READ_DCACHE_INVALIDATE) != 0); 00697 00698 return; 00699 00700 } else if (((Mdl->MdlFlags & MDL_IO_PAGE_READ) == 0) && 00701 ((KiDmaIoCoherency & DMA_READ_DCACHE_INVALIDATE) != 0)) { 00702 return; 00703 } 00704 00705 } else if ((KiDmaIoCoherency & DMA_WRITE_DCACHE_SNOOP) != 0) { 00706 return; 00707 } 00708 00709 } else if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) == 0) { 00710 return; 00711 } 00712 00713 // 00714 // Either the operation is a DMA operation and the right coherency 00715 // atributes are not supported by the host system, or the operation 00716 // is programmed I/O and a page read. 00717 // 00718 // Raise IRQL to synchronization level to prevent a context switch. 00719 // 00720 00721 OldIrql = KeRaiseIrqlToSynchLevel(); 00722 00723 // 00724 // Compute the set of target processors, and send the flush I/O 00725 // parameters to the target processors, if any, for execution. 00726 // 00727 00728 #if !defined(NT_UP) 00729 00730 TargetProcessors = KeActiveProcessors & PCR->NotMember; 00731 if (TargetProcessors != 0) { 00732 KiIpiSendPacket(TargetProcessors, 00733 KiFlushIoBuffersTarget, 00734 (PVOID)Mdl, 00735 (PVOID)((ULONG)ReadOperation), 00736 (PVOID)((ULONG)DmaOperation)); 00737 } 00738 00739 #endif 00740 00741 // 00742 // Flush I/O buffer on current processor. 00743 // 00744 00745 HalFlushIoBuffers(Mdl, ReadOperation, DmaOperation); 00746 00747 // 00748 // Wait until all target processors have finished flushing the 00749 // specified I/O buffer. 00750 // 00751 00752 #if !defined(NT_UP) 00753 00754 if (TargetProcessors != 0) { 00755 KiIpiStallOnPacketTargets(); 00756 } 00757 00758 #endif 00759 00760 // 00761 // Lower IRQL to its previous level and return. 00762 // 00763 00764 KeLowerIrql(OldIrql); 00765 return; 00766 } 00767 00768 VOID 00769 KiFlushIoBuffersTarget ( 00770 IN PULONG SignalDone, 00771 IN PVOID Mdl, 00772 IN PVOID ReadOperation, 00773 IN PVOID DmaOperation 00774 ) 00775 00776 /*++ 00777 00778 Routine Description: 00779 00780 This is the target function for flushing an I/O buffer on target 00781 processors. 00782 00783 Arguments: 00784 00785 SignalDone Supplies a pointer to a variable that is cleared when the 00786 requested operation has been performed. 00787 00788 Mdl - Supplies a pointer to a memory descriptor list that describes the 00789 I/O buffer location. 00790 00791 ReadOperation - Supplies a boolean value that determines whether the I/O 00792 operation is a read into memory. 00793 00794 DmaOperation - Supplies a boolean value that determines whether the I/O 00795 operation is a DMA operation. 00796 00797 Return Value: 00798 00799 None. 00800 00801 --*/ 00802 00803 { 00804 00805 // 00806 // Flush the specified I/O buffer on the current processor. 00807 // 00808 00809 #if !defined(NT_UP) 00810 00811 HalFlushIoBuffers((PMDL)Mdl, 00812 (BOOLEAN)((ULONG)ReadOperation), 00813 (BOOLEAN)((ULONG)DmaOperation)); 00814 00815 KiIpiSignalPacketDone(SignalDone); 00816 00817 #endif 00818 00819 return; 00820 }

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