/* * Copyright 1993,1994,1995 Emin Gun Sirer * MIPSI - Mips Instruction Set Simulator. */ #include #include "config.h" #include "main.h" #include "mem.h" #include "tlb.h" #include "mt_os.h" #include #define TLB_SIZE 64 #define TLB_MASK (TLB_SIZE-1) typedef struct tlb_elt { unsigned long vpage; unsigned long ppage; unsigned flags; } tlb_elt; tlb_elt TLB[TLB_SIZE]; void tlb_flush() { int i; for (i = 0; i < TLB_SIZE; i++) { TLB[i].vpage = INVALID; } } void tlb_invalidate (unsigned long vpage) { int i; for (i = 0; i < TLB_SIZE; i++) { if (TLB[i].vpage == vpage) { TLB[i].vpage = INVALID; } } } unsigned long tlb_translate(unsigned long vaddr,c_rw rw) { unsigned long offset,paddr,vpage,ppage; unsigned long index; /* figure out the offset and the page */ offset = GET_OFFSET(vaddr); vpage = GET_PAGE(vaddr); /* figure out the table index */ index = vpage & TLB_MASK; if (TLB[index].vpage == vpage) { /* check the tag */ ppage = TLB[index].ppage; } else { return INVALID; } /* if attempt to write to a protected page */ if ( (TLB[index].flags & TLB_WRITE_PROTECT) && (rw == C_WRITE)) { /* fault */ unsigned long V0,A0,A1,A2,A3,RES; unsigned long vpage, flags; /* setup for a trap ---save the registers */ V0 = R[REG_V0]; A0 = R[REG_A0]; A1 = R[REG_A1]; A2 = R[REG_A2]; A3 = R[REG_A3]; RES = R[REG_RES]; /* put in the trap number */ R[REG_V0] = MT_ENTRY; /* to get an MT-OS call */ R[REG_A0] = MT_TLB_WRITE_FAULT; /* to pick the TLB fault */ /* compute vpage */ vpage = GET_PAGE(vaddr); /* put in the virtual page */ R[REG_A1] = vpage; dosyscall(); /* perform the trap */ /* get the resulting flags */ TLB[index].flags = R[REG_RES]; /* restore the registers */ R[REG_V0] = V0; R[REG_A0] = A0; R[REG_A1] = A1; R[REG_A2] = A2; R[REG_A3] = A3; R[REG_RES] = RES; } /* put together the physical page and the offset */ paddr = (ppage << PAGESHIFT) | offset; if (paddr & 3) { index = 5; } return paddr; } void set_tlb_ppage(unsigned long vpage, PTE ptentry) { unsigned long index; index = vpage & TLB_MASK; TLB[index].ppage = TLB_GETPAGE(ptentry); TLB[index].flags = TLB_GETFLAGS(ptentry); TLB[index].vpage = vpage; } void set_tlb_flags(unsigned long vpage, unsigned flags) { unsigned long index; index = vpage & TLB_MASK; assert(vpage == TLB[index].vpage); TLB[index].flags = flags; }