Windows2000/private/ntos/ke/mips/tb.s
2020-09-30 17:12:32 +02:00

855 lines
28 KiB
ArmAsm
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// TITLE("TB Management")
//++
//
// Copyright (c) 1996 Microsoft Corporation
//
// Module Name:
//
// tb.s
//
// Abstract:
//
// This module implements the code necessary to fill and flush TB entries.
//
// Author:
//
// David N. Cutler (davec) 4-Apr-1991
//
// Environment:
//
// Kernel mode only.
//
// Revision History:
//
//--
#include "ksmips.h"
//
// Define external variables that can be addressed using GP.
//
.extern KeNumberTbEntries 4
SBTTL("Fill Translation Buffer Entry")
//++
//
// VOID
// KeFillEntryTb (
// IN HARDWARE_PTE Pte[],
// IN PVOID Virtual,
// IN BOOLEAN Invalid
// )
//
// Routine Description:
//
// This function fills a translation buffer entry. If the entry is already
// in the translation buffer, then the entry is overwritten. Otherwise, a
// random entry is overwritten.
//
// Arguments:
//
// Pte (a0) - Supplies a pointer to the page table entries that are to be
// written into the TB.
//
// Virtual (a1) - Supplies the virtual address of the entry that is to
// be filled in the translation buffer.
//
// Invalid (a2) - Supplies a boolean value that determines whether the
// TB entry should be invalidated.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KeFillEntryTb)
and a0,a0,~0x7 // clear low bits of PTE address
lw t0,0(a0) // get first PTE value
lw t1,4(a0) // get second PTE value
#if DBG
xor t2,t1,t0 // compare G-bits
and t2,t2,1 << ENTRYLO_G // isolate comparison
beq zero,t2,5f // if eq, G-bits match
break KERNEL_BREAKPOINT // break into kernel debugger
5: //
#endif
DISABLE_INTERRUPTS(t2) // disable interrupts
.set noreorder
.set noat
mfc0 t3,entryhi // get current PID and VPN2
srl a1,a1,ENTRYHI_VPN2 // isolate VPN2 of virtual address
sll a1,a1,ENTRYHI_VPN2 //
and t3,t3,PID_MASK << ENTRYHI_PID // isolate current PID
or a1,t3,a1 // merge PID with VPN2 of virtual address
mtc0 a1,entryhi // set VPN2 and PID for probe
nop // 3 cycle hazzard
nop //
nop //
tlbp // probe for entry in TB
nop // 2 cycle hazzard
nop //
mfc0 t3,index // read result of probe
mtc0 t0,entrylo0 // set first PTE value
mtc0 t1,entrylo1 // set second PTE value
bltz t3,20f // if ltz, entry is not in TB
nop // fill
#if DBG
sltu t4,t3,FIXED_ENTRIES // check if fixed entry within range
beq zero,t4,10f // if eq, index not in fixed region
nop //
break KERNEL_BREAKPOINT // break into debugger
#endif
10: tlbwi // overwrite indexed entry
nop // 3 cycle hazzard
nop //
b 30f //
nop //
20: tlbwr // overwrite random TB entry
nop // 3 cycle hazzard
nop //
nop //
.set at
.set reorder
30: ENABLE_INTERRUPTS(t2) // enable interrupts
j ra // return
.end KeFillEntryTb
SBTTL("Fill Large Translation Buffer Entry")
//++
//
// VOID
// KeFillLargeEntryTb (
// IN HARDWARE_PTE Pte[],
// IN PVOID Virtual,
// IN ULONG PageSize
// )
//
// Routine Description:
//
// This function fills a large translation buffer entry.
//
// N.B. It is assumed that the large entry is not in the TB and therefore
// the TB is not probed.
//
// Arguments:
//
// Pte (a0) - Supplies a pointer to the page table entries that are to be
// written into the TB.
//
// Virtual (a1) - Supplies the virtual address of the entry that is to
// be filled in the translation buffer.
//
// PageSize (a2) - Supplies the size of the large page table entry.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KeFillLargeEntryTb)
and a0,a0,~0x7 // clear low bits of PTE address
lw t0,0(a0) // get first PTE value
lw t1,4(a0) // get second PTE value
subu a2,a2,1 // compute the page mask value
srl a2,a2,PAGE_SHIFT //
sll a2,a2,PAGE_SHIFT + 1 //
nor a3,a2,zero // compute virtual address mask
DISABLE_INTERRUPTS(t2) // disable interrupts
.set noreorder
.set noat
mfc0 t3,entryhi // get current PID and VPN2
srl a1,a1,ENTRYHI_VPN2 // isolate VPN2 of virtual address
sll a1,a1,ENTRYHI_VPN2 //
and a1,a3,a1 // isolate large entry virtual address
and t3,t3,PID_MASK << ENTRYHI_PID // isolate current PID
or a1,t3,a1 // merge PID with VPN2 of virtual address
li a3,LARGE_ENTRY // set large entry index
mtc0 a1,entryhi // set entry high value for large entry
mtc0 a2,pagemask // set page mask value
mtc0 a3,index //
mtc0 t0,entrylo0 // set first PTE value
mtc0 t1,entrylo1 // set second PTE value
nop // 1 cycle hazzard
tlbwi // overwrite large TB entry
nop // 3 cycle hazzard
nop //
nop //
mtc0 zero,pagemask // clear page mask value
.set at
.set reorder
ENABLE_INTERRUPTS(t2) // enable interrupts
j ra // return
.end KeFillLargeEntryTb
SBTTL("Fill Fixed Translation Buffer Entry")
//++
//
// VOID
// KeFillFixedEntryTb (
// IN HARDWARE_PTE Pte[],
// IN PVOID Virtual,
// IN ULONG Index
// )
//
// Routine Description:
//
// This function fills a fixed translation buffer entry.
//
// Arguments:
//
// Pte (a0) - Supplies a pointer to the page table entries that are to be
// written into the TB.
//
// Virtual (a1) - Supplies the virtual address of the entry that is to
// be filled in the translation buffer.
//
// Index (a2) - Supplies the index where the TB entry is to be written.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KeFillFixedEntryTb)
lw t0,0(a0) // get first PTE value
lw t1,4(a0) // get second PTE value
DISABLE_INTERRUPTS(t2) // disable interrupts
.set noreorder
.set noat
mfc0 t3,entryhi // get current PID and VPN2
srl a1,a1,ENTRYHI_VPN2 // isolate VPN2 of virtual address
sll a1,a1,ENTRYHI_VPN2 //
and t3,t3,PID_MASK << ENTRYHI_PID // isolate current PID
or a1,t3,a1 // merge PID with VPN2 of virtual address
mtc0 a1,entryhi // set VPN2 and PID for probe
mtc0 t0,entrylo0 // set first PTE value
mtc0 t1,entrylo1 // set second PTE value
mtc0 a2,index // set TB entry index
nop // 1 cycle hazzard
tlbwi // overwrite indexed TB entry
nop // 3 cycle hazzard
nop //
nop //
.set at
.set reorder
ENABLE_INTERRUPTS(t2) // enable interrupts
j ra // return
.end KeFillFixedEntryTb
SBTTL("Flush Entire Translation Buffer")
//++
//
// VOID
// KeFlushCurrentTb (
// VOID
// )
//
// Routine Description:
//
// This function flushes the random part of the translation buffer.
//
// Arguments:
//
// None.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KeFlushCurrentTb)
j KiFlushRandomTb // execute common code
.end KeFlushCurrentTb
SBTTL("Flush Fixed Translation Buffer Entries")
//++
//
// VOID
// KiFlushFixedTb (
// VOID
// )
//
// Routine Description:
//
// This function is called to flush all the fixed entries from the
// translation buffer.
//
// Arguments:
//
// None.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiFlushFixedTb)
.set noreorder
.set noat
move t0,zero // set base index of fixed TB entries
j KiFlushTb //
mfc0 t3,wired // set highest index number + 1
.set at
.set reorder
.end KiFlushFixedTb
SBTTL("Flush Random Translation Buffer Entries")
//++
//
// VOID
// KiFlushRandomTb (
// VOID
// )
//
// Routine Description:
//
// This function is called to flush all the random entries from the TB.
//
// Arguments:
//
// None.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiFlushRandomTb)
.set noreorder
.set noat
mfc0 t0,wired // set base index of random TB entries
lw t3,KeNumberTbEntries // set number of entries
.set at
.set reorder
ALTERNATE_ENTRY(KiFlushTb)
li t4,KSEG0_BASE // set high part of TB entry
DISABLE_INTERRUPTS(t2) // disable interrupts
.set noreorder
.set noat
mfc0 t1,entryhi // get current PID and VPN2
sll t0,t0,INDEX_INDEX // shift starting index into position
sll t3,t3,INDEX_INDEX // shift ending index into position
and t1,t1,PID_MASK << ENTRYHI_PID // isolate current PID
li t4,KSEG0_BASE // set invalidate address
or t4,t4,t1 // merge PID with VPN2 of virtual address
mtc0 zero,entrylo0 // set low part of TB entry
mtc0 zero,entrylo1 //
mtc0 t4,entryhi //
mtc0 t0,index // set TB entry index
10: addu t0,t0,1 << INDEX_INDEX //
tlbwi // write TB entry
bne t0,t3,10b // if ne, more entries to flush
mtc0 t0,index // set TB entry index
.set at
.set reorder
ENABLE_INTERRUPTS(t2) // enable interrupts
j ra // return
.end KiFlushRandomTb
SBTTL("Flush Multiple TB Entry")
//++
//
// VOID
// KiFlushMultipleTb (
// IN BOOLEAN Invalid,
// IN PVOID *Virtual,
// IN ULONG Count
// )
//
// Routine Description:
//
// This function flushes multiple entries from the translation buffer.
//
// Arguments:
//
// Invalid (a0) - Supplies a boolean variable that determines the reason
// that the TB entry is being flushed.
//
// Virtual (a1) - Supplies a pointer to an array of virtual addresses of
// the entries that are flushed from the translation buffer.
//
// Count (a2) - Supplies the number of TB entries to flush.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiFlushMultipleTb)
DISABLE_INTERRUPTS(t0) // disable interrupts
.set noreorder
.set noat
mfc0 t1,entryhi // get current PID and VPN2
nop //
and a3,t1,PID_MASK << ENTRYHI_PID // isolate current PID
10: lw v0,0(a1) // get virtual address
addu a1,a1,4 // advance to next entry
subu a2,a2,1 // reduce number of entries
srl t2,v0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
sll t2,t2,ENTRYHI_VPN2 //
or t2,t2,a3 // merge PID with VPN2 of virtual address
mtc0 t2,entryhi // set VPN2 and PID for probe
nop // 3 cycle hazzard
nop //
nop //
tlbp // probe TB for entry
nop // 2 cycle hazzard
nop //
mfc0 t3,index // read result of probe
nop //
bltz t3,30f // if ltz, entry is not in TB
lui t2,KSEG0_BASE >> 16 // set invalidate address
#if DBG
sltu t4,t3,FIXED_ENTRIES // check if fixed entry region
beq zero,t4,20f // if eq, index not in fixed region
nop //
break KERNEL_BREAKPOINT // break into debugger
#endif
20: mtc0 zero,entrylo0 // set low part of TB entry
mtc0 zero,entrylo1 //
or t2,t2,a3 // merge PID with VPN2 of invalid address
mtc0 t2,entryhi // set VPN2 and PID for TB write
nop // 1 cycle hazzard
tlbwi // overwrite index TB entry
nop // 3 cycle hazzard
nop //
nop //
30: bgtz a2,10b // if gtz, more entires to flush
mtc0 zero,pagemask // restore page mask register
.set at
.set reorder
ENABLE_INTERRUPTS(t0) // enable interrupts
j ra // return
.end KiFlushMultipleTb
SBTTL("Flush Multiple TB Entry 64-bits")
//++
//
// VOID
// KiFlushMultipleTb64 (
// IN BOOLEAN Invalid,
// IN PULONG *Virtual,
// IN ULONG Count
// )
//
// Routine Description:
//
// This function flushes multiple entries from the translation buffer.
//
// Arguments:
//
// Invalid (a0) - Supplies a boolean variable that determines the reason
// that the TB entry is being flushed.
//
// Virtual (a1) - Supplies a pointer to an array of virtual page numbers
// of the entries that are flushed from the translation buffer.
//
// Count (a2) - Supplies the number of TB entries to flush.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiFlushMultipleTb64)
DISABLE_INTERRUPTS(t0) // disable interrupts
.set noreorder
.set noat
mfc0 t1,entryhi // get current PID and VPN2
nop //
and a3,t1,PID_MASK << ENTRYHI_PID // isolate current PID
10: lw v0,0(a1) // get virtual address
addu a1,a1,4 // advance to next entry
subu a2,a2,1 // reduce number of entries
srl t2,v0,1 // convert from virtual page to VPN2
sll t2,t2,ENTRYHI_VPN2 // shift VPN2 into place
or t2,t2,a3 // merge PID with VPN2 of virtual address
mtc0 t2,entryhi // set VPN2 and PID for probe
nop // 3 cycle hazzard
nop //
nop //
tlbp // probe TB for entry
nop // 2 cycle hazzard
nop //
mfc0 t3,index // read result of probe
nop //
bltz t3,30f // if ltz, entry is not in TB
lui t2,KSEG0_BASE >> 16 // set invalidate address
#if DBG
sltu t4,t3,FIXED_ENTRIES // check if fixed entry region
beq zero,t4,20f // if eq, index not in fixed region
nop //
break KERNEL_BREAKPOINT // break into debugger
#endif
20: mtc0 zero,entrylo0 // set low part of TB entry
mtc0 zero,entrylo1 //
or t2,t2,a3 // merge PID with VPN2 of invalid address
mtc0 t2,entryhi // set VPN2 and PID for TB write
nop // 1 cycle hazzard
tlbwi // overwrite index TB entry
nop // 3 cycle hazzard
nop //
nop //
30: bgtz a2,10b // if gtz, more entires to flush
mtc0 zero,pagemask // restore page mask register
.set at
.set reorder
ENABLE_INTERRUPTS(t0) // enable interrupts
j ra // return
.end KiFlushMultipleTb64
SBTTL("Flush Single TB Entry")
//++
//
// VOID
// KiFlushSingleTb (
// IN BOOLEAN Invalid,
// IN PVOID Virtual
// )
//
// Routine Description:
//
// This function flushes a single entry from the translation buffer.
//
// Arguments:
//
// Invalid (a0) - Supplies a boolean variable that determines the reason
// that the TB entry is being flushed.
//
// Virtual (a1) - Supplies the virtual address of the entry that is to
// be flushed from the translation buffer.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiFlushSingleTb)
DISABLE_INTERRUPTS(t0) // disable interrupts
.set noreorder
.set noat
mfc0 t1,entryhi // get current PID and VPN2
srl t2,a1,ENTRYHI_VPN2 // isolate VPN2 of virtual address
sll t2,t2,ENTRYHI_VPN2 //
and a2,t1,PID_MASK << ENTRYHI_PID // isolate current PID
or t2,t2,a2 // merge PID with VPN2 of virtual address
mtc0 t2,entryhi // set VPN2 and PID for probe
nop // 3 cycle hazzard
nop //
nop //
tlbp // probe TB for entry
nop // 2 cycle hazzard
nop //
mfc0 t3,index // read result of probe
nop //
bltz t3,20f // if ltz, entry is not in TB
lui t2,KSEG0_BASE >> 16 // set invalid address
#if DBG
sltu t4,t3,FIXED_ENTRIES // check if fixed entry region
beq zero,t4,10f // if eq, index not in fixed region
nop //
break KERNEL_BREAKPOINT // break into debugger
#endif
10: mtc0 zero,entrylo0 // set low part of TB entry
mtc0 zero,entrylo1 //
or t2,t2,a2 // merge PID with VPN2 of invalid address
mtc0 t2,entryhi // set VPN2 and PID for TB write
nop // 1 cycle hazzard
tlbwi // overwrite index TB entry
nop // 3 cycle hazzard
nop //
nop //
mtc0 zero,pagemask // restore page mask register
.set at
.set reorder
20: ENABLE_INTERRUPTS(t0) // enable interrupts
j ra // return
.end KiFlushSingleTb
SBTTL("Flush Single TB Entry 64-bits")
//++
//
// VOID
// KiFlushSingleTb64 (
// IN BOOLEAN Invalid,
// IN ULONG Virtual
// )
//
// Routine Description:
//
// This function flushes a single entry from the translation buffer.
//
// Arguments:
//
// Invalid (a0) - Supplies a boolean variable that determines the reason
// that the TB entry is being flushed.
//
// Virtual (a1) - Supplies the virtual page number of the entry that is
// flushed from the translation buffer.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiFlushSingleTb64)
DISABLE_INTERRUPTS(t0) // disable interrupts
.set noreorder
.set noat
mfc0 t1,entryhi // get current PID and VPN2
srl t2,a1,1 // convert from virtual page to VPN2
sll t2,t2,ENTRYHI_VPN2 // shift VPN2 into place
and a2,t1,PID_MASK << ENTRYHI_PID // isolate current PID
or t2,t2,a2 // merge PID with VPN2 of virtual address
mtc0 t2,entryhi // set VPN2 and PID for probe
nop // 3 cycle hazzard
nop //
nop //
tlbp // probe TB for entry
nop // 2 cycle hazzard
nop //
mfc0 t3,index // read result of probe
nop //
bltz t3,20f // if ltz, entry is not in TB
lui t2,KSEG0_BASE >> 16 // set invalid address
#if DBG
sltu t4,t3,FIXED_ENTRIES // check if fixed entry region
beq zero,t4,10f // if eq, index not in fixed region
nop //
break KERNEL_BREAKPOINT // break into debugger
#endif
10: mtc0 zero,entrylo0 // set low part of TB entry
mtc0 zero,entrylo1 //
or t2,t2,a2 // merge PID with VPN2 of invalid address
mtc0 t2,entryhi // set VPN2 and PID for TB write
nop // 1 cycle hazzard
tlbwi // overwrite index TB entry
nop // 3 cycle hazzard
nop //
nop //
mtc0 zero,pagemask // restore page mask register
.set at
.set reorder
20: ENABLE_INTERRUPTS(t0) // enable interrupts
j ra // return
.end KiFlushSingleTb64
SBTTL("Probe Tb Entry")
//++
//
// ULONG
// KiProbeEntryTb (
// IN PVOID VirtualAddress
// )
//
// Routine Description:
//
// This function is called to determine if a specified entry is valid
/// and within the fixed portion of the TB.
//
// Arguments:
//
// VirtualAddress - Supplies the virtual address to probe.
//
// Return Value:
//
// A value of TRUE is returned if the specified entry is valid and within
// the fixed part of the TB. Otherwise, a value of FALSE is returned.
//
//--
LEAF_ENTRY(KiProbeEntryTb)
DISABLE_INTERRUPTS(t0) // disable interrupts
.set noreorder
.set noat
mfc0 t1,entryhi // get current PID and VPN2
srl t2,a0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
sll t2,t2,ENTRYHI_VPN2 //
and t1,t1,PID_MASK << ENTRYHI_PID // isolate current PID
or t2,t2,t1 // merge PID with VPN2 of virtual address
mtc0 t2,entryhi // set VPN2 and PID for probe
nop // 3 cycle hazzard
nop //
nop //
tlbp // probe for entry in TB
nop // 2 cycle hazzard
nop //
mfc0 t3,index // read result of probe
li v0,FALSE // set to return failure
bltz t3,20f // if ltz, entry is not in TB
sll a0,a0,0x1f - (ENTRYHI_VPN2 - 1) // shift VPN<12> into sign
tlbr // read entry from TB
nop // 3 cycle hazzard
nop //
nop //
bltz a0,10f // if ltz, check second PTE
mfc0 t2,entrylo1 // get second PTE for probe
mfc0 t2,entrylo0 // get first PTE for probe
10: mtc0 t1,entryhi // restore current PID
mtc0 zero,pagemask // restore page mask register
sll t2,t2,0x1f - ENTRYLO_V // shift valid bit into sign position
bgez t2,20f // if geq, entry is not valid
srl t3,INDEX_INDEX // isolate TB index
and t3,t3,0x3f //
mfc0 t4,wired // get number of wired entries
nop // fill
sltu v0,t3,t4 // check if entry in fixed part of TB
.set at
.set reorder
20: ENABLE_INTERRUPTS(t0) // enable interrupts
j ra // return
.end KiProbeEntryTb
SBTTL("Read Tb Entry")
//++
//
// VOID
// KiReadEntryTb (
// IN ULONG Index,
// OUT PTB_ENTRY TbEntry
// )
//
// Routine Description:
//
// This function is called to read an entry from the TB.
//
// Arguments:
//
// Index - Supplies the index of the entry to read.
//
// TbEntry - Supplies a pointer to a TB entry structure that receives the
// contents of the specified TB entry.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiReadEntryTb)
DISABLE_INTERRUPTS(t0) // disable interrupts
.set noreorder
.set noat
sll a0,INDEX_INDEX // shift index into position
dmfc0 t1,entryhi // save entry high register
mtc0 a0,index // set TB entry index
nop //
tlbr // read entry from TB
nop // 3 cycle hazzard
nop //
nop //
mfc0 t2,entrylo0 // save first PTE value
mfc0 t3,entrylo1 // save second PTE value
dmfc0 t4,entryhi // save entry high value
mfc0 t5,pagemask // save page mask value
dmtc0 t1,entryhi // restore entry high register
mtc0 zero,pagemask // restore page mask register
nop // 1 cycle hazzard
.set at
.set reorder
ENABLE_INTERRUPTS(t0) // enable interrupts
sw t2,TbEntrylo0(a1) // set first PTE value
sw t3,TbEntrylo1(a1) // set second PTE value
sw t4,TbEntryhi(a1) // set low part of entry high value
dsrl t4,t4,32 // isolate high bits of vpn2
and t4,t4,0xff //
or t5,t5,t4 // merge with page mask value
sw t5,TbPagemask(a1) // set page mask value
j ra // return
.end KiReadEntryTb