Initial Spring 2016 commit.
This commit is contained in:
204
kern/arch/mips/vm/tlb-mips161.S
Normal file
204
kern/arch/mips/vm/tlb-mips161.S
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
|
||||
* The President and Fellows of Harvard College.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <kern/mips/regdefs.h>
|
||||
#include <mips/specialreg.h>
|
||||
|
||||
/*
|
||||
* TLB handling for the MIPS-161.
|
||||
*
|
||||
* The MIPS-161 uses the simpler MIPS-1 (r2000/r3000) TLB rather
|
||||
* than the paired-page TLB of later MIPS models.
|
||||
*
|
||||
* However, we handle MIPS32 pipeline hazards. If you want to run on
|
||||
* a real MIPS-1, change the ssnops to plain nops and check where and
|
||||
* how many you need in the matching processor docs.
|
||||
*
|
||||
* (ssnop means "superscalar nop"; it exists because the pipeline
|
||||
* hazards require a fixed number of cycles, and a superscalar CPU can
|
||||
* potentially issue arbitrarily many nops in one cycle.)
|
||||
*/
|
||||
|
||||
.text
|
||||
.set noreorder
|
||||
.set mips32 /* so we can use ssnop */
|
||||
|
||||
/*
|
||||
* tlb_random: use the "tlbwr" instruction to write a TLB entry
|
||||
* into a (very pseudo-) random slot in the TLB.
|
||||
*
|
||||
* Pipeline hazard: must wait between setting entryhi/lo and
|
||||
* doing the tlbwr. Use two cycles; some processors may vary.
|
||||
*/
|
||||
.globl tlb_random
|
||||
.type tlb_random,@function
|
||||
.ent tlb_random
|
||||
tlb_random:
|
||||
mtc0 a0, c0_entryhi /* store the passed entry into the */
|
||||
mtc0 a1, c0_entrylo /* tlb entry registers */
|
||||
ssnop /* wait for pipeline hazard */
|
||||
ssnop
|
||||
tlbwr /* do it */
|
||||
j ra
|
||||
nop
|
||||
.end tlb_random
|
||||
|
||||
/*
|
||||
* tlb_write: use the "tlbwi" instruction to write a TLB entry
|
||||
* into a selected slot in the TLB.
|
||||
*
|
||||
* Pipeline hazard: must wait between setting entryhi/lo and
|
||||
* doing the tlbwi. Use two cycles; some processors may vary.
|
||||
*/
|
||||
.text
|
||||
.globl tlb_write
|
||||
.type tlb_write,@function
|
||||
.ent tlb_write
|
||||
tlb_write:
|
||||
mtc0 a0, c0_entryhi /* store the passed entry into the */
|
||||
mtc0 a1, c0_entrylo /* tlb entry registers */
|
||||
sll t0, a2, CIN_INDEXSHIFT /* shift the passed index into place */
|
||||
mtc0 t0, c0_index /* store the shifted index into the index register */
|
||||
ssnop /* wait for pipeline hazard */
|
||||
ssnop
|
||||
tlbwi /* do it */
|
||||
j ra
|
||||
nop
|
||||
.end tlb_write
|
||||
|
||||
/*
|
||||
* tlb_read: use the "tlbr" instruction to read a TLB entry
|
||||
* from a selected slot in the TLB.
|
||||
*
|
||||
* Pipeline hazard: must wait between setting c0_index and
|
||||
* doing the tlbr. Use two cycles; some processors may vary.
|
||||
* Similarly, three more cycles before reading c0_entryhi/lo.
|
||||
*/
|
||||
.text
|
||||
.globl tlb_read
|
||||
.type tlb_read,@function
|
||||
.ent tlb_read
|
||||
tlb_read:
|
||||
sll t0, a2, CIN_INDEXSHIFT /* shift the passed index into place */
|
||||
mtc0 t0, c0_index /* store the shifted index into the index register */
|
||||
ssnop /* wait for pipeline hazard */
|
||||
ssnop
|
||||
tlbr /* do it */
|
||||
ssnop /* wait for pipeline hazard */
|
||||
ssnop
|
||||
ssnop
|
||||
mfc0 t0, c0_entryhi /* get the tlb entry out of the */
|
||||
mfc0 t1, c0_entrylo /* tlb entry registers */
|
||||
sw t0, 0(a0) /* store through the passed pointer */
|
||||
j ra
|
||||
sw t1, 0(a1) /* store (in delay slot) */
|
||||
.end tlb_read
|
||||
|
||||
/*
|
||||
* tlb_probe: use the "tlbp" instruction to find the index in the
|
||||
* TLB of a TLB entry matching the relevant parts of the one supplied.
|
||||
*
|
||||
* Pipeline hazard: must wait between setting c0_entryhi/lo and
|
||||
* doing the tlbp. Use two cycles; some processors may vary.
|
||||
* Similarly, two more cycles before reading c0_index.
|
||||
*/
|
||||
.text
|
||||
.globl tlb_probe
|
||||
.type tlb_probe,@function
|
||||
.ent tlb_probe
|
||||
tlb_probe:
|
||||
mtc0 a0, c0_entryhi /* store the passed entry into the */
|
||||
mtc0 a1, c0_entrylo /* tlb entry registers */
|
||||
ssnop /* wait for pipeline hazard */
|
||||
ssnop
|
||||
tlbp /* do it */
|
||||
ssnop /* wait for pipeline hazard */
|
||||
ssnop
|
||||
mfc0 t0, c0_index /* fetch the index back in t0 */
|
||||
|
||||
/*
|
||||
* If the high bit (CIN_P) of c0_index is set, the probe failed.
|
||||
* The high bit is not set <--> c0_index (now in t0) >= 0.
|
||||
*/
|
||||
|
||||
bgez t0, 1f /* did probe succeed? if so, skip forward */
|
||||
nop /* delay slot */
|
||||
addi v0, z0, -1 /* set return value to -1 to indicate failure */
|
||||
j ra /* done */
|
||||
nop /* delay slot */
|
||||
|
||||
1:
|
||||
/* succeeded - get the index field from the index register value */
|
||||
andi t1, t0, CIN_INDEX /* mask off the field */
|
||||
j ra /* done */
|
||||
sra v0, t1, CIN_INDEXSHIFT /* shift it (in delay slot) */
|
||||
.end tlb_probe
|
||||
|
||||
|
||||
/*
|
||||
* tlb_reset
|
||||
*
|
||||
* Initialize the TLB. At processor startup, the TLB state is completely
|
||||
* undefined. So be sure to avoid creating any duplicates. Also make sure
|
||||
* that the initialization entries don't duplicate the INVALID entries
|
||||
* defined in tlb.h. (This way you can write the invalid entries in
|
||||
* without having to use tlbp to find out if they're going to cause dups.)
|
||||
*
|
||||
* This function is not defined in tlb.h because it's only called from
|
||||
* start.S.
|
||||
*
|
||||
* Pipeline hazards are as above.
|
||||
*/
|
||||
.text
|
||||
.globl tlb_reset
|
||||
.type tlb_reset,@function
|
||||
.ent tlb_reset
|
||||
tlb_reset:
|
||||
li t0, 0 /* t0 <- tlb index number (shifted) */
|
||||
li t1, 0x81000000 /* t1 <- tlb reset vaddr */
|
||||
1:
|
||||
mtc0 $0, c0_entrylo /* set up proposed tlb entry for reset */
|
||||
mtc0 t1, c0_entryhi
|
||||
ssnop /* wait for pipeline hazard */
|
||||
ssnop
|
||||
tlbp /* check if it already exists */
|
||||
ssnop /* wait for pipeline hazard */
|
||||
ssnop
|
||||
mfc0 t2, c0_index
|
||||
bgez t2, 1b /* if it does, loop back */
|
||||
addiu t1, t1, 0x1000 /* next vaddr (in delay slot) */
|
||||
mtc0 t0, c0_index /* doesn't exist, set index to write to */
|
||||
ssnop /* wait for pipeline hazard */
|
||||
ssnop
|
||||
addiu t0, t0, 0x100 /* next tlb index (shifted) */
|
||||
bne t0, 0x4000, 1b /* if it's not the last tlb index, loop */
|
||||
tlbwi /* write tlb entry (in delay slot) */
|
||||
j ra /* done */
|
||||
nop /* delay slot */
|
||||
.end tlb_reset
|
Reference in New Issue
Block a user