855 lines
28 KiB
ArmAsm
855 lines
28 KiB
ArmAsm
|
// 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
|