mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
332 lines
6.4 KiB
332 lines
6.4 KiB
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
flush.c
|
|
|
|
Abstract:
|
|
|
|
This module implements i386 machine dependent kernel functions to flush
|
|
the data and instruction caches and to stall processor execution.
|
|
|
|
Author:
|
|
|
|
David N. Cutler (davec) 26-Apr-1990
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "ki.h"
|
|
|
|
|
|
//
|
|
// Prototypes
|
|
//
|
|
|
|
VOID
|
|
KeInvalidateAllCachesTarget (
|
|
IN PKIPI_CONTEXT SignalDone,
|
|
IN PVOID Parameter1,
|
|
IN PVOID Parameter2,
|
|
IN PVOID Parameter3
|
|
);
|
|
|
|
extern ULONG KeI386CpuType;
|
|
|
|
// i386 and i486 have transparent caches, so these routines are nooped
|
|
// out in macros in i386.h.
|
|
|
|
#if 0
|
|
|
|
VOID
|
|
KeSweepDcache (
|
|
IN BOOLEAN AllProcessors
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function flushes the data cache on all processors that are currently
|
|
running threads which are children of the current process or flushes the
|
|
data cache on all processors in the host configuration.
|
|
|
|
Arguments:
|
|
|
|
AllProcessors - Supplies a boolean value that determines which data
|
|
caches are flushed.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
HalSweepDcache();
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
KeSweepIcache (
|
|
IN BOOLEAN AllProcessors
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function flushes the instruction cache on all processors that are
|
|
currently running threads which are children of the current process or
|
|
flushes the instruction cache on all processors in the host configuration.
|
|
|
|
Arguments:
|
|
|
|
AllProcessors - Supplies a boolean value that determines which instruction
|
|
caches are flushed.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
HalSweepIcache();
|
|
|
|
#if defined(R4000)
|
|
|
|
HalSweepDcache();
|
|
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
KeSweepIcacheRange (
|
|
IN BOOLEAN AllProcessors,
|
|
IN PVOID BaseAddress,
|
|
IN ULONG Length
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function flushes the an range of virtual addresses from the primary
|
|
instruction cache on all processors that are currently running threads
|
|
which are children of the current process or flushes the range of virtual
|
|
addresses from the primary instruction cache on all processors in the host
|
|
configuration.
|
|
|
|
Arguments:
|
|
|
|
AllProcessors - Supplies a boolean value that determines which instruction
|
|
caches are flushed.
|
|
|
|
BaseAddress - Supplies a pointer to the base of the range that is flushed.
|
|
|
|
Length - Supplies the length of the range that is flushed if the base
|
|
address is specified.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG Offset;
|
|
|
|
//
|
|
// If the length of the range is greater than the size of the primary
|
|
// instruction cache, then set the length of the flush to the size of
|
|
// the primary instruction cache and set the ase address of zero.
|
|
//
|
|
// N.B. It is assumed that the size of the primary instruction and
|
|
// data caches are the same.
|
|
//
|
|
|
|
if (Length > PCR->FirstLevelIcacheSize) {
|
|
BaseAddress = (PVOID)0;
|
|
Length = PCR->FirstLevelIcacheSize;
|
|
}
|
|
|
|
//
|
|
// Flush the specified range of virtual addresses from the primary
|
|
// instruction cache.
|
|
//
|
|
|
|
Offset = (ULONG)BaseAddress & PCR->DcacheAlignment;
|
|
Length = (Offset + Length + PCR->DcacheAlignment) & ~PCR->DcacheAlignment;
|
|
BaseAddress = (PVOID)((ULONG)BaseAddress & ~PCR->DcacheAlignment);
|
|
HalSweepIcacheRange(BaseAddress, Length);
|
|
|
|
#if defined(R4000)
|
|
|
|
HalSweepDcacheRange(BaseAddress, Length);
|
|
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
BOOLEAN
|
|
KeInvalidateAllCaches (
|
|
IN BOOLEAN AllProcessors
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function writes back and invalidates the cache on all processors
|
|
that are currently running threads which are children of the current
|
|
process or on all processors in the host configuration.
|
|
|
|
Arguments:
|
|
|
|
AllProcessors - Supplies a boolean value that determines which data
|
|
caches are flushed.
|
|
|
|
Return Value:
|
|
|
|
TRUE if the invalidation was done, FALSE otherwise.
|
|
|
|
--*/
|
|
{
|
|
PKPRCB Prcb;
|
|
PKPROCESS Process;
|
|
KIRQL OldIrql;
|
|
KAFFINITY TargetProcessors;
|
|
|
|
//
|
|
// Support for wbinvd on Pentium based platforms is vendor dependent.
|
|
// Check for family first and support on Pentium Pro based platforms
|
|
// onward.
|
|
//
|
|
|
|
if (KeI386CpuType < 6 ) {
|
|
return FALSE;
|
|
}
|
|
|
|
#ifndef NT_UP
|
|
//
|
|
// Compute target set of processors.
|
|
//
|
|
|
|
KiLockContextSwap(&OldIrql);
|
|
Prcb = KeGetCurrentPrcb();
|
|
if (AllProcessors) {
|
|
TargetProcessors = KeActiveProcessors;
|
|
} else {
|
|
Process = Prcb->CurrentThread->ApcState.Process;
|
|
TargetProcessors = Process->ActiveProcessors;
|
|
}
|
|
|
|
TargetProcessors &= ~Prcb->SetMember;
|
|
|
|
//
|
|
// If any target processors are specified, then send writeback
|
|
// invalidate packet to the target set of processors.
|
|
//
|
|
|
|
if (TargetProcessors != 0) {
|
|
KiIpiSendSynchronousPacket(Prcb,
|
|
TargetProcessors,
|
|
KeInvalidateAllCachesTarget,
|
|
(PVOID)&Prcb->ReverseStall,
|
|
NULL,
|
|
NULL);
|
|
|
|
KiIpiStallOnPacketTargets(TargetProcessors);
|
|
}
|
|
|
|
//
|
|
// All target processors have written back and invalidated caches and
|
|
// are waiting to proceed. Write back invalidate current cache and
|
|
// then continue the execution of target processors.
|
|
//
|
|
#endif
|
|
_asm {
|
|
;
|
|
; wbinvd
|
|
;
|
|
|
|
_emit 0Fh
|
|
_emit 09h
|
|
}
|
|
|
|
#ifndef NT_UP
|
|
//
|
|
// Wait until all target processors have finished and completed packet.
|
|
//
|
|
|
|
if (TargetProcessors != 0) {
|
|
Prcb->ReverseStall += 1;
|
|
}
|
|
|
|
//
|
|
// Release the context swap lock.
|
|
//
|
|
|
|
KiUnlockContextSwap(OldIrql);
|
|
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
VOID
|
|
KeInvalidateAllCachesTarget (
|
|
IN PKIPI_CONTEXT SignalDone,
|
|
IN PVOID Proceed,
|
|
IN PVOID Parameter2,
|
|
IN PVOID Parameter3
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the target function for writing back and invalidating the cache.
|
|
|
|
Arguments:
|
|
|
|
SignalDone - Supplies a pointer to a variable that is cleared when the
|
|
requested operation has been performed.
|
|
|
|
Proceed - pointer to flag to syncronize with
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Write back invalidate current cache
|
|
//
|
|
|
|
_asm {
|
|
;
|
|
; wbinvd
|
|
;
|
|
|
|
_emit 0Fh
|
|
_emit 09h
|
|
|
|
}
|
|
|
|
KiIpiSignalPacketDoneAndStall (SignalDone, Proceed);
|
|
}
|