/*1* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 20092* The President and Fellows of Harvard College.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12* 3. Neither the name of the University nor the names of its contributors13* may be used to endorse or promote products derived from this software14* without specific prior written permission.15*16* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND17* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE18* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE19* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE20* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL21* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS22* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)23* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT24* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY25* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF26* SUCH DAMAGE.27*/2829#include <kern/mips/regdefs.h>30#include <mips/specialreg.h>3132/*33* TLB handling for mips-1 (r2000/r3000)34*/3536.text37.set noreorder3839/*40* tlb_random: use the "tlbwr" instruction to write a TLB entry41* into a (very pseudo-) random slot in the TLB.42*43* Pipeline hazard: must wait between setting entryhi/lo and44* doing the tlbwr. Use two cycles; some processors may vary.45*/46.globl tlb_random47.type tlb_random,@function48.ent tlb_random49tlb_random:50mtc0 a0, c0_entryhi /* store the passed entry into the */51mtc0 a1, c0_entrylo /* tlb entry registers */52nop /* wait for pipeline hazard */53nop54tlbwr /* do it */55j ra56nop57.end tlb_random5859/*60* tlb_write: use the "tlbwi" instruction to write a TLB entry61* into a selected slot in the TLB.62*63* Pipeline hazard: must wait between setting entryhi/lo and64* doing the tlbwi. Use two cycles; some processors may vary.65*/66.text67.globl tlb_write68.type tlb_write,@function69.ent tlb_write70tlb_write:71mtc0 a0, c0_entryhi /* store the passed entry into the */72mtc0 a1, c0_entrylo /* tlb entry registers */73sll t0, a2, CIN_INDEXSHIFT /* shift the passed index into place */74mtc0 t0, c0_index /* store the shifted index into the index register */75nop /* wait for pipeline hazard */76nop77tlbwi /* do it */78j ra79nop80.end tlb_write8182/*83* tlb_read: use the "tlbr" instruction to read a TLB entry84* from a selected slot in the TLB.85*86* Pipeline hazard: must wait between setting c0_index and87* doing the tlbr. Use two cycles; some processors may vary.88* Similarly, three more cycles before reading c0_entryhi/lo.89*/90.text91.globl tlb_read92.type tlb_read,@function93.ent tlb_read94tlb_read:95sll t0, a2, CIN_INDEXSHIFT /* shift the passed index into place */96mtc0 t0, c0_index /* store the shifted index into the index register */97nop /* wait for pipeline hazard */98nop99tlbr /* do it */100nop /* wait for pipeline hazard */101nop102nop103mfc0 t0, c0_entryhi /* get the tlb entry out of the */104mfc0 t1, c0_entrylo /* tlb entry registers */105sw t0, 0(a0) /* store through the passed pointer */106j ra107sw t1, 0(a1) /* store (in delay slot) */108.end tlb_read109110/*111* tlb_probe: use the "tlbp" instruction to find the index in the112* TLB of a TLB entry matching the relevant parts of the one supplied.113*114* Pipeline hazard: must wait between setting c0_entryhi/lo and115* doing the tlbp. Use two cycles; some processors may vary.116* Similarly, two more cycles before reading c0_index.117*/118.text119.globl tlb_probe120.type tlb_probe,@function121.ent tlb_probe122tlb_probe:123mtc0 a0, c0_entryhi /* store the passed entry into the */124mtc0 a1, c0_entrylo /* tlb entry registers */125nop /* wait for pipeline hazard */126nop127tlbp /* do it */128nop /* wait for pipeline hazard */129nop130mfc0 t0, c0_index /* fetch the index back in t0 */131132/*133* If the high bit (CIN_P) of c0_index is set, the probe failed.134* The high bit is not set <--> c0_index (now in t0) >= 0.135*/136137bgez t0, 1f /* did probe succeed? if so, skip forward */138nop /* delay slot */139addi v0, z0, -1 /* set return value to -1 to indicate failure */140j ra /* done */141nop /* delay slot */1421431:144/* succeeded - get the index field from the index register value */145andi t1, t0, CIN_INDEX /* mask off the field */146j ra /* done */147sra v0, t1, CIN_INDEXSHIFT /* shift it (in delay slot) */148.end tlb_probe149150151/*152* tlb_reset153*154* Initialize the TLB. At processor startup, the TLB state is completely155* undefined. So be sure to avoid creating any duplicates. Also make sure156* that the initialization entries don't duplicate the INVALID entries157* defined in tlb.h. (This way you can write the invalid entries in158* without having to use tlbp to find out if they're going to cause dups.)159*160* This function is not defined in tlb.h because it's only called from161* start.S.162*163* Pipeline hazards are as above.164*/165.text166.globl tlb_reset167.type tlb_reset,@function168.ent tlb_reset169tlb_reset:170li t0, 0 /* t0 <- tlb index number (shifted) */171li t1, 0x81000000 /* t1 <- tlb reset vaddr */1721:173mtc0 $0, c0_entrylo /* set up proposed tlb entry for reset */174mtc0 t1, c0_entryhi175nop /* wait for pipeline hazard */176nop177tlbp /* check if it already exists */178nop /* wait for pipeline hazard */179nop180mfc0 t2, c0_index181bgez t2, 1b /* if it does, loop back */182addiu t1, t1, 0x1000 /* next vaddr (in delay slot) */183mtc0 t0, c0_index /* doesn't exist, set index to write to */184/* nop */ /* don't wait for pipeline hazard */185/* nop */ /* (have enough other instructions) */186addiu t0, t0, 0x100 /* next tlb index (shifted) */187bne t0, 0x4000, 1b /* if it's not the last tlb index, loop */188tlbwi /* write tlb entry (in delay slot) */189j ra /* done */190nop /* delay slot */191.end tlb_reset192193194