summaryrefslogtreecommitdiffstats
path: root/private/ntos/ke/i386/flushtb.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/ke/i386/flushtb.c')
-rw-r--r--private/ntos/ke/i386/flushtb.c565
1 files changed, 565 insertions, 0 deletions
diff --git a/private/ntos/ke/i386/flushtb.c b/private/ntos/ke/i386/flushtb.c
new file mode 100644
index 000000000..77e8a5511
--- /dev/null
+++ b/private/ntos/ke/i386/flushtb.c
@@ -0,0 +1,565 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ tbflush.c
+
+Abstract:
+
+ This module implements machine dependent functions to flush
+ the translation buffers in an Intel x86 system.
+
+ N.B. This module contains only MP versions of the TB flush routines.
+ The UP versions are macros in ke.h
+ KeFlushEntireTb remains a routine for the UP system since it is
+ exported from the kernel for backwards compatibility.
+
+Author:
+
+ David N. Cutler (davec) 13-May-1989
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Shie-Lin Tzong (shielint) 30-Aug-1990
+ Implement MP version of KeFlushSingleTb and KeFlushEntireTb.
+
+--*/
+
+#include "ki.h"
+
+VOID
+KiFlushTargetEntireTb (
+ IN PKIPI_CONTEXT SignalDone,
+ IN PVOID Invalid,
+ 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
+ );
+
+#if defined(NT_UP)
+#undef KeFlushEntireTb
+#endif
+
+
+VOID
+KeFlushEntireTb (
+ IN BOOLEAN Invalid,
+ IN BOOLEAN AllProcessors
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the entire translation buffer (TB) on all processors
+ that are currently running threads which are child of the current process
+ or flushes the entire translation buffer on all processors in the host
+ configuration.
+
+Arguments:
+
+ Invalid - Supplies a boolean value that specifies the reason for flushing
+ the translation buffer.
+
+ 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.
+ //
+
+#if defined(NT_UP)
+
+ OldIrql = KeRaiseIrqlToSynchLevel();
+
+#else
+
+ if (AllProcessors != FALSE) {
+ OldIrql = KeRaiseIrqlToSynchLevel();
+ Prcb = KeGetCurrentPrcb();
+ TargetProcessors = KeActiveProcessors;
+
+ } else {
+ KiLockContextSwap(&OldIrql);
+ Prcb = KeGetCurrentPrcb();
+ Process = Prcb->CurrentThread->ApcState.Process;
+ TargetProcessors = Process->ActiveProcessors;
+ }
+
+ TargetProcessors &= ~Prcb->SetMember;
+ 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)
+
+ KeLowerIrql(OldIrql);
+
+#else
+
+ if (TargetProcessors != 0) {
+ KiIpiStallOnPacketTargets();
+ }
+
+ if (AllProcessors != FALSE) {
+ KeLowerIrql(OldIrql);
+
+ } else {
+ KiUnlockContextSwap(OldIrql);
+ }
+
+#endif
+
+ 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.
+
+--*/
+
+{
+
+ //
+ // Flush the entire TB on the current processor.
+ //
+
+ KiIpiSignalPacketDone(SignalDone);
+ KeFlushCurrentTb();
+ return;
+}
+
+VOID
+KeFlushMultipleTb (
+ IN ULONG Number,
+ IN PVOID *Virtual,
+ IN BOOLEAN Invalid,
+ IN BOOLEAN AllProcessors,
+ IN PHARDWARE_PTE *PtePointer OPTIONAL,
+ IN HARDWARE_PTE PteValue
+ )
+
+/*++
+
+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.
+
+ Invalid - Supplies a boolean value that specifies the reason for
+ flushing the translation buffer.
+
+ AllProcessors - Supplies a boolean value that determines which
+ translation buffers are to be flushed.
+
+ PtePointer - Supplies an optional pointer to an array of pointers to
+ page table entries that receive the specified page table entry
+ value.
+
+ PteValue - Supplies the the new page table entry value.
+
+Return Value:
+
+ The previous contents of the specified page table entry is returned
+ as the function value.
+
+--*/
+
+{
+
+ ULONG Index;
+ KIRQL OldIrql;
+ PKPRCB Prcb;
+ PKPROCESS Process;
+ KAFFINITY TargetProcessors;
+
+ ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
+
+ //
+ // Compute target set of processors.
+ //
+
+ Prcb = KeGetCurrentPrcb();
+ if (AllProcessors != FALSE) {
+ OldIrql = KeRaiseIrqlToSynchLevel();
+ TargetProcessors = KeActiveProcessors;
+
+ } else {
+ KiLockContextSwap(&OldIrql);
+ Process = Prcb->CurrentThread->ApcState.Process;
+ TargetProcessors = Process->ActiveProcessors;
+ }
+
+ TargetProcessors &= ~Prcb->SetMember;
+
+ //
+ // If a page table entry address array is specified, then set the
+ // specified page table entries to the specific value.
+ //
+
+ if (ARGUMENT_PRESENT(PtePointer)) {
+ for (Index = 0; Index < Number; Index += 1) {
+ *PtePointer[Index] = PteValue;
+ }
+ }
+
+ //
+ // If any target processors are specified, then send a flush multiple
+ // packet to the target set of processors.
+ //
+
+ if (TargetProcessors != 0) {
+ KiIpiSendPacket(TargetProcessors,
+ KiFlushTargetMultipleTb,
+ (PVOID)Invalid,
+ (PVOID)Number,
+ (PVOID)Virtual);
+
+ IPI_INSTRUMENT_COUNT (Prcb->Number, FlushMultipleTb);
+ }
+
+ //
+ // Flush the specified entries from the TB on the current processor.
+ //
+
+ for (Index = 0; Index < Number; Index += 1) {
+ KiFlushSingleTb(Invalid, Virtual[Index]);
+ }
+
+ //
+ // Wait until all target processors have finished and complete packet.
+ //
+
+ if (TargetProcessors != 0) {
+ KiIpiStallOnPacketTargets();
+ }
+
+ //
+ // Release the context swap lock.
+ //
+
+ if (AllProcessors != FALSE) {
+ KeLowerIrql(OldIrql);
+
+ } else {
+ KiUnlockContextSwap(OldIrql);
+ }
+
+ return;
+}
+
+VOID
+KiFlushTargetMultipleTb (
+ IN PKIPI_CONTEXT SignalDone,
+ IN PVOID Invalid,
+ IN PVOID Number,
+ 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.
+
+ Invalid - Supplies a bollean value that determines whether the virtual
+ address is invalid.
+
+ 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.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Index;
+ PVOID VirtualAddress[FLUSH_MULTIPLE_MAXIMUM];
+
+ //
+ // Capture the virtual addresses that are to be flushed from the TB
+ // on the current processor and signal pack done.
+ //
+
+ for (Index = 0; Index < (ULONG) Number; Index += 1) {
+ VirtualAddress[Index] = ((PVOID *)(Virtual))[Index];
+ }
+
+ KiIpiSignalPacketDone(SignalDone);
+
+ //
+ // Flush the specified virtual address for the TB on the current
+ // processor.
+ //
+
+ for (Index = 0; Index < (ULONG) Number; Index += 1) {
+ KiFlushSingleTb((BOOLEAN)Invalid, VirtualAddress [Index]);
+ }
+}
+
+HARDWARE_PTE
+KeFlushSingleTb (
+ IN PVOID Virtual,
+ IN BOOLEAN Invalid,
+ IN BOOLEAN AllProcessors,
+ IN PHARDWARE_PTE PtePointer,
+ IN HARDWARE_PTE PteValue
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes a single entry from translation buffer (TB) on all
+ processors that are currently running threads which are child of the current
+ process or flushes the entire translation buffer on all processors in the
+ host configuration.
+
+Arguments:
+
+ Virtual - Supplies a virtual address that is within the page whose
+ translation buffer entry is to be flushed.
+
+ Invalid - Supplies a boolean value that specifies the reason for flushing
+ the translation buffer.
+
+ AllProcessors - Supplies a boolean value that determines which translation
+ buffers are to be flushed.
+
+ PtePointer - Address of Pte to update with new value.
+
+ PteValue - New value to put in the Pte. Will simply be assigned to
+ *PtePointer, in a fashion correct for the hardware.
+
+Return Value:
+
+ Returns the contents of the PtePointer before the new value
+ is stored.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ PKPRCB Prcb;
+ PKPROCESS Process;
+ HARDWARE_PTE OldPteValue;
+ KAFFINITY TargetProcessors;
+
+ ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
+
+ //
+ // Compute target set of processors.
+ //
+
+ Prcb = KeGetCurrentPrcb();
+ if (AllProcessors != FALSE) {
+ OldIrql = KeRaiseIrqlToSynchLevel();
+ TargetProcessors = KeActiveProcessors;
+
+ } else {
+ KiLockContextSwap(&OldIrql);
+ Process = Prcb->CurrentThread->ApcState.Process;
+ TargetProcessors = Process->ActiveProcessors;
+ }
+
+ TargetProcessors &= ~Prcb->SetMember;
+
+ //
+ // Capture the previous contents of the page table entry and set the
+ // page table entry to the new value.
+ //
+
+ OldPteValue = *PtePointer;
+ *PtePointer = PteValue;
+
+ //
+ // If any target processors are specified, then send a flush single
+ // packet to the target set of processors.
+ //
+
+ if (TargetProcessors != 0) {
+ KiIpiSendPacket(TargetProcessors,
+ KiFlushTargetSingleTb,
+ (PVOID)Invalid,
+ (PVOID)Virtual,
+ NULL);
+
+ IPI_INSTRUMENT_COUNT(Prcb->Number, FlushSingleTb);
+ }
+
+
+ //
+ // Flush the specified entry from the TB on the current processor.
+ //
+
+ KiFlushSingleTb(Invalid, Virtual);
+
+ //
+ // Wait until all target processors have finished and complete packet.
+ //
+
+ if (TargetProcessors != 0) {
+ KiIpiStallOnPacketTargets();
+ }
+
+ //
+ // Release the context swap lock.
+ //
+
+ if (AllProcessors != FALSE) {
+ KeLowerIrql(OldIrql);
+
+ } else {
+ KiUnlockContextSwap(OldIrql);
+ }
+
+ return(OldPteValue);
+}
+
+VOID
+KiFlushTargetSingleTb (
+ IN PKIPI_CONTEXT SignalDone,
+ IN PVOID Invalid,
+ 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.
+
+ Invalid - Supplies a bollean value that determines whether the virtual
+ address is invalid.
+
+ Virtual - Supplies a virtual address that is within the page whose
+ translation buffer entry is to be flushed.
+
+ Parameter3 - Not used.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Flush a single entry from the TB on the current processor.
+ //
+
+ KiIpiSignalPacketDone(SignalDone);
+ KiFlushSingleTb((BOOLEAN)Invalid, (PVOID)VirtualAddress);
+}
+
+#endif