|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
flushtb.c
Abstract:
This module implements machine dependent functions to flush the TB for an AMD64 system.
N.B. This module contains only MP versions of the TB flush routines.
Author:
David N. Cutler (davec) 22-April-2000
Environment:
Kernel mode only.
--*/
#include "ki.h"
//
// Define prototypes for forward referenced functions.
//
VOID KiFlushTargetEntireTb ( IN PKIPI_CONTEXT SignalDone, IN PVOID Parameter1, IN PVOID Parameter2, IN PVOID Parameter3 );
VOID KiFlushTargetProcessTb ( IN PKIPI_CONTEXT SignalDone, IN PVOID Parameter1, IN PVOID Parameter2, IN PVOID Parameter3 );
VOID KiFlushTargetMultipleTb ( IN PKIPI_CONTEXT SignalDone, IN PVOID Parameter1, IN PVOID Parameter2, IN PVOID Parameter3 );
VOID KiFlushTargetSingleTb ( IN PKIPI_CONTEXT SignalDone, IN PVOID Parameter1, IN PVOID Parameter2, IN PVOID Parameter3 );
VOID KeFlushEntireTb ( IN BOOLEAN Invalid, IN BOOLEAN AllProcessors )
/*++
Routine Description:
This function flushes the entire translation buffer (TB) on all processors in the host configuration.
Arguments:
Invalid - Not used.
AllProcessors - Not used.
Return Value:
None.
--*/
{
KIRQL OldIrql;
#if !defined(NT_UP)
PKPRCB Prcb; KAFFINITY TargetProcessors;
#endif
UNREFERENCED_PARAMETER(Invalid); UNREFERENCED_PARAMETER(AllProcessors);
//
// Compute the target set of processors and send the flush entire
// parameters to the target processors, if any, for execution.
//
OldIrql = KeRaiseIrqlToSynchLevel(); KiSetTbFlushTimeStampBusy();
#if !defined(NT_UP)
Prcb = KeGetCurrentPrcb(); TargetProcessors = KeActiveProcessors & Prcb->NotSetMember;
//
// Send packet to target processors.
//
if (TargetProcessors != 0) { KiIpiSendPacket(TargetProcessors, KiFlushTargetEntireTb, NULL, NULL, NULL); }
IPI_INSTRUMENT_COUNT(Prcb->Number, FlushEntireTb);
#endif
//
// Flush TB on current processor.
//
KeFlushCurrentTb();
//
// Wait until all target processors have finished and complete packet.
//
#if !defined(NT_UP)
if (TargetProcessors != 0) { KiIpiStallOnPacketTargets(TargetProcessors); }
#endif
//
// Clear the TB flush time stamp busy.
//
KiClearTbFlushTimeStampBusy();
//
// Lower IRQL to its previous value.
//
KeLowerIrql(OldIrql); return; }
#if !defined(NT_UP)
VOID KiFlushTargetEntireTb ( IN PKIPI_CONTEXT SignalDone, IN PVOID Parameter1, IN PVOID Parameter2, IN PVOID Parameter3 )
/*++
Routine Description:
This is the target function for flushing the entire TB.
Arguments:
SignalDone - Supplies a pointer to a variable that is cleared when the requested operation has been performed.
Parameter1 - Parameter3 - Not used.
Return Value:
None.
--*/
{
UNREFERENCED_PARAMETER(Parameter1); UNREFERENCED_PARAMETER(Parameter2); UNREFERENCED_PARAMETER(Parameter3);
//
// Flush the entire TB on the current processor.
//
KiIpiSignalPacketDone(SignalDone); KeFlushCurrentTb(); return; }
VOID KeFlushProcessTb ( IN BOOLEAN AllProcessors )
/*++
Routine Description:
This function flushes the non-global translation buffer on all processors that are currently running threads which are child of the current process or flushes the non-global translation buffer on all processors in the host configuration.
Arguments:
AllProcessors - Supplies a boolean value that determines which translation buffers are to be flushed.
Return Value:
None.
--*/
{
KIRQL OldIrql; PKPRCB Prcb; PKPROCESS Process; KAFFINITY TargetProcessors;
//
// Compute the target set of processors, disable context switching,
// and send the flush entire parameters to the target processors,
// if any, for execution.
//
OldIrql = KeRaiseIrqlToSynchLevel(); Prcb = KeGetCurrentPrcb(); if (AllProcessors != FALSE) { TargetProcessors = KeActiveProcessors;
} else { Process = Prcb->CurrentThread->ApcState.Process; TargetProcessors = Process->ActiveProcessors; }
TargetProcessors &= ~Prcb->SetMember;
//
// Send packet to target processors.
//
if (TargetProcessors != 0) { KiIpiSendPacket(TargetProcessors, KiFlushTargetProcessTb, NULL, NULL, NULL);
IPI_INSTRUMENT_COUNT (Prcb->Number, FlushEntireTb); }
//
// Flush TB on current processor.
//
KiFlushProcessTb();
//
// Wait until all target processors have finished and complete packet.
//
if (TargetProcessors != 0) { KiIpiStallOnPacketTargets(TargetProcessors); }
//
// Lower IRQL to its previous value.
//
KeLowerIrql(OldIrql); return; }
VOID KiFlushTargetProcessTb ( IN PKIPI_CONTEXT SignalDone, IN PVOID Parameter1, IN PVOID Parameter2, IN PVOID Parameter3 )
/*++
Routine Description:
This is the target function for flushing the non-global TB.
Arguments:
SignalDone - Supplies a pointer to a variable that is cleared when the requested operation has been performed.
Parameter1 - Parameter3 - Not used.
Return Value:
None.
--*/
{
UNREFERENCED_PARAMETER(Parameter1); UNREFERENCED_PARAMETER(Parameter2); UNREFERENCED_PARAMETER(Parameter3);
//
// Flush the non-global TB on the current processor.
//
KiIpiSignalPacketDone(SignalDone); KiFlushProcessTb(); return; }
VOID KeFlushMultipleTb ( IN ULONG Number, IN PVOID *Virtual, IN BOOLEAN AllProcessors )
/*++
Routine Description:
This function flushes multiple entries from the translation buffer on all processors that are currently running threads which are children of the current process or flushes a multiple entries from the translation buffer on all processors in the host configuration.
Arguments:
Number - Supplies the number of TB entries to flush.
Virtual - Supplies a pointer to an array of virtual addresses that are within the pages whose translation buffer entries are to be flushed.
AllProcessors - Supplies a boolean value that determines which translation buffers are to be flushed.
Return Value:
The previous contents of the specified page table entry is returned as the function value.
--*/
{
PVOID *End; KIRQL OldIrql; PKPRCB Prcb; PKPROCESS Process; KAFFINITY TargetProcessors;
ASSERT(Number != 0);
//
// Compute target set of processors.
//
OldIrql = KeRaiseIrqlToSynchLevel(); Prcb = KeGetCurrentPrcb(); if (AllProcessors != FALSE) { TargetProcessors = KeActiveProcessors;
} else { Process = Prcb->CurrentThread->ApcState.Process; TargetProcessors = Process->ActiveProcessors; }
//
// If any target processors are specified, then send a flush multiple
// packet to the target set of processors.
//
End = Virtual + Number; TargetProcessors &= Prcb->NotSetMember; if (TargetProcessors != 0) { KiIpiSendPacket(TargetProcessors, KiFlushTargetMultipleTb, NULL, (PVOID)End, (PVOID)Virtual);
}
IPI_INSTRUMENT_COUNT (Prcb->Number, FlushMultipleTb);
//
// Flush the specified entries from the TB on the current processor.
//
do { KiFlushSingleTb(*Virtual); Virtual += 1; } while (Virtual < End);
//
// Wait until all target processors have finished and complete packet.
//
if (TargetProcessors != 0) { KiIpiStallOnPacketTargets(TargetProcessors); }
//
// Lower IRQL to its previous value.
//
KeLowerIrql(OldIrql); return; }
VOID KiFlushTargetMultipleTb ( IN PKIPI_CONTEXT SignalDone, IN PVOID Parameter1, IN PVOID End, IN PVOID Virtual )
/*++
Routine Description:
This is the target function for flushing multiple TB entries.
Arguments:
SignalDone - Supplies a pointer to a variable that is cleared when the requested operation has been performed.
Parameter1 - Not used.
End - Supplies the a pointer to the ending address of the virtual address array.
Virtual - Supplies a pointer to an array of virtual addresses that are within the pages whose translation buffer entries are to be flushed.
Return Value:
None.
--*/
{
PVOID *xEnd; PVOID *xVirtual;
UNREFERENCED_PARAMETER(Parameter1);
//
// Flush the specified entries from the TB on the current processor and
// signal pack done.
//
xEnd = (PVOID *)End; xVirtual = (PVOID *)Virtual; do { KiFlushSingleTb(*xVirtual); xVirtual += 1; } while (xVirtual < xEnd);
KiIpiSignalPacketDone(SignalDone); return; }
VOID FASTCALL KeFlushSingleTb ( IN PVOID Virtual, IN BOOLEAN AllProcessors )
/*++
Routine Description:
This function flushes a single entry from translation buffer (TB) on all processors that are currently running threads which are children of the current process.
Arguments:
Virtual - Supplies a virtual address that is within the page whose translation buffer entry is to be flushed.
AllProcessors - Supplies a boolean value that determines which translation buffers are to be flushed.
Return Value:
The previous contents of the specified page table entry is returned as the function value.
--*/
{
KIRQL OldIrql; PKPRCB Prcb; PKPROCESS Process; KAFFINITY TargetProcessors;
//
// Compute the target set of processors and send the flush single
// parameters to the target processors, if any, for execution.
//
OldIrql = KeRaiseIrqlToSynchLevel(); Prcb = KeGetCurrentPrcb(); if (AllProcessors != FALSE) { TargetProcessors = KeActiveProcessors;
} else { Process = Prcb->CurrentThread->ApcState.Process; TargetProcessors = Process->ActiveProcessors; }
//
// If any target processors are specified, then send a flush single
// packet to the target set of processors.
//
TargetProcessors &= Prcb->NotSetMember; if (TargetProcessors != 0) { KiIpiSendPacket(TargetProcessors, KiFlushTargetSingleTb, NULL, (PVOID)Virtual, NULL); }
IPI_INSTRUMENT_COUNT(Prcb->Number, FlushSingleTb);
//
// Flush the specified entry from the TB on the current processor.
//
KiFlushSingleTb(Virtual);
//
// Wait until all target processors have finished and complete packet.
//
if (TargetProcessors != 0) { KiIpiStallOnPacketTargets(TargetProcessors); }
//
// Lower IRQL to its previous value.
//
KeLowerIrql(OldIrql); return; }
VOID KiFlushTargetSingleTb ( IN PKIPI_CONTEXT SignalDone, IN PVOID Parameter1, IN PVOID VirtualAddress, IN PVOID Parameter3 )
/*++
Routine Description:
This is the target function for flushing a single TB entry.
Arguments:
SignalDone Supplies a pointer to a variable that is cleared when the requested operation has been performed.
Parameter1 - Not used.
Virtual - Supplies a virtual address that is within the page whose translation buffer entry is to be flushed.
Parameter3 - Not used.
Return Value:
None.
--*/
{ UNREFERENCED_PARAMETER(Parameter1); UNREFERENCED_PARAMETER(Parameter3);
//
// Flush a single entry from the TB on the current processor.
//
KiIpiSignalPacketDone(SignalDone); KiFlushSingleTb(VirtualAddress); }
#endif
|