test: flush.c Source File

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 }