* Authors: Nathan Binkert
* Steve Reinhardt
* Jaidev Patwardhan
+ * Zhengxing Li
+ * Deyuan Guo
*/
#include <string>
#include <vector>
-#include "arch/mips/pra_constants.hh"
+#include "arch/mips/faults.hh"
#include "arch/mips/pagetable.hh"
+#include "arch/mips/pra_constants.hh"
#include "arch/mips/tlb.hh"
-#include "arch/mips/faults.hh"
#include "arch/mips/utility.hh"
#include "base/inifile.hh"
#include "base/str.hh"
#include "base/trace.hh"
#include "cpu/thread_context.hh"
-#include "sim/process.hh"
+#include "debug/MipsPRA.hh"
+#include "debug/TLB.hh"
#include "mem/page_table.hh"
#include "params/MipsTLB.hh"
-
+#include "sim/process.hh"
using namespace std;
using namespace MipsISA;
// MIPS TLB
//
-static inline mode_type
-getOperatingMode(MiscReg Stat)
-{
- if ((Stat & 0x10000006) != 0 || (Stat & 0x18) ==0) {
- return mode_kernel;
- } else if ((Stat & 0x18) == 0x8) {
- return mode_supervisor;
- } else if ((Stat & 0x18) == 0x10) {
- return mode_user;
- } else {
- return mode_number;
- }
-}
-
-
TLB::TLB(const Params *p)
: BaseTLB(p), size(p->size), nlu(0)
{
TLB::probeEntry(Addr vpn, uint8_t asn) const
{
// assume not found...
- PTE *retval = NULL;
int Ind = -1;
PageTable::const_iterator i = lookupTable.find(vpn);
if (i != lookupTable.end()) {
if (((vpn & InvMask) == (VPN & InvMask)) &&
(pte->G || (asn == pte->asid))) {
// We have a VPN + ASID Match
- retval = pte;
Ind = index;
break;
}
(pte.D0 << 2) | (pte.V0 <<1) | pte.G),
((pte.PFN1 <<6) | (pte.C1 << 3) |
(pte.D1 << 2) | (pte.V1 <<1) | pte.G));
- if (table[Index].V0 == true || table[Index].V1 == true) {
+ if (table[Index].V0 || table[Index].V1) {
// Previous entry is valid
PageTable::iterator i = lookupTable.find(table[Index].VPN);
lookupTable.erase(i);
.desc("DTB misses")
;
- invalids
- .name(name() + ".invalids")
- .desc("DTB access violations")
- ;
-
accesses
.name(name() + ".accesses")
.desc("DTB accesses")
Fault
TLB::translateInst(RequestPtr req, ThreadContext *tc)
{
-#if !FULL_SYSTEM
+ if (FullSystem)
+ panic("translateInst not implemented in MIPS.\n");
+
Process * p = tc->getProcessPtr();
Fault fault = p->pTable->translate(req);
return fault;
return NoFault;
-#else
- if (IsKSeg0(req->getVaddr())) {
- // Address will not be translated through TLB, set response, and go!
- req->setPaddr(KSeg02Phys(req->getVaddr()));
- if (getOperatingMode(tc->readMiscReg(Status)) != mode_kernel ||
- req->isMisaligned()) {
- AddressErrorFault *Flt = new AddressErrorFault();
- /* BadVAddr must be set */
- Flt->BadVAddr = req->getVaddr();
- return Flt;
- }
- } else if(IsKSeg1(req->getVaddr())) {
- // Address will not be translated through TLB, set response, and go!
- req->setPaddr(KSeg02Phys(req->getVaddr()));
- } else {
- /*
- * This is an optimization - smallPages is updated every time a TLB
- * operation is performed. That way, we don't need to look at
- * Config3 _ SP and PageGrain _ ESP every time we do a TLB lookup
- */
- Addr VPN;
- if (smallPages == 1) {
- VPN = ((req->getVaddr() >> 11));
- } else {
- VPN = ((req->getVaddr() >> 11) & 0xFFFFFFFC);
- }
- uint8_t Asid = req->getAsid();
- if (req->isMisaligned()) {
- // Unaligned address!
- AddressErrorFault *Flt = new AddressErrorFault();
- /* BadVAddr must be set */
- Flt->BadVAddr = req->getVaddr();
- return Flt;
- }
- PTE *pte = lookup(VPN,Asid);
- if (pte != NULL) {
- // Ok, found something
- /* Check for valid bits */
- int EvenOdd;
- bool Valid;
- if ((((req->getVaddr()) >> pte->AddrShiftAmount) & 1) == 0) {
- // Check even bits
- Valid = pte->V0;
- EvenOdd = 0;
- } else {
- // Check odd bits
- Valid = pte->V1;
- EvenOdd = 1;
- }
-
- if (Valid == false) {
- //Invalid entry
- ItbInvalidFault *Flt = new ItbInvalidFault();
- /* EntryHi VPN, ASID fields must be set */
- Flt->EntryHi_Asid = Asid;
- Flt->EntryHi_VPN2 = (VPN >> 2);
- Flt->EntryHi_VPN2X = (VPN & 0x3);
-
- /* BadVAddr must be set */
- Flt->BadVAddr = req->getVaddr();
-
- /* Context must be set */
- Flt->Context_BadVPN2 = (VPN >> 2);
- return Flt;
- } else {
- // Ok, this is really a match, set paddr
- Addr PAddr;
- if (EvenOdd == 0) {
- PAddr = pte->PFN0;
- } else {
- PAddr = pte->PFN1;
- }
- PAddr >>= (pte->AddrShiftAmount - 12);
- PAddr <<= pte->AddrShiftAmount;
- PAddr |= ((req->getVaddr()) & pte->OffsetMask);
- req->setPaddr(PAddr);
- }
- } else {
- // Didn't find any match, return a TLB Refill Exception
- ItbRefillFault *Flt=new ItbRefillFault();
- /* EntryHi VPN, ASID fields must be set */
- Flt->EntryHi_Asid = Asid;
- Flt->EntryHi_VPN2 = (VPN >> 2);
- Flt->EntryHi_VPN2X = (VPN & 0x3);
-
- /* BadVAddr must be set */
- Flt->BadVAddr = req->getVaddr();
-
- /* Context must be set */
- Flt->Context_BadVPN2 = (VPN >> 2);
- return Flt;
- }
- }
- return checkCacheability(req);
-#endif
}
Fault
TLB::translateData(RequestPtr req, ThreadContext *tc, bool write)
{
-#if !FULL_SYSTEM
- //@TODO: This should actually use TLB instead of going directly
- // to the page table in syscall mode.
- /**
- * Check for alignment faults
- */
- if (req->getVaddr() & (req->getSize() - 1)) {
- DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->getVaddr(),
- req->getSize());
- return new AlignmentFault();
- }
-
+ if (FullSystem)
+ panic("translateData not implemented in MIPS.\n");
Process * p = tc->getProcessPtr();
return fault;
return NoFault;
-#else
- if (IsKSeg0(req->getVaddr())) {
- // Address will not be translated through TLB, set response, and go!
- req->setPaddr(KSeg02Phys(req->getVaddr()));
- if (getOperatingMode(tc->readMiscReg(Status)) != mode_kernel ||
- req->isMisaligned()) {
- StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
- /* BadVAddr must be set */
- Flt->BadVAddr = req->getVaddr();
-
- return Flt;
- }
- } else if(IsKSeg1(req->getVaddr())) {
- // Address will not be translated through TLB, set response, and go!
- req->setPaddr(KSeg02Phys(req->getVaddr()));
- } else {
- /*
- * This is an optimization - smallPages is updated every time a TLB
- * operation is performed. That way, we don't need to look at
- * Config3 _ SP and PageGrain _ ESP every time we do a TLB lookup
- */
- Addr VPN = ((req->getVaddr() >> 11) & 0xFFFFFFFC);
- if (smallPages == 1) {
- VPN = ((req->getVaddr() >> 11));
- }
- uint8_t Asid = req->getAsid();
- PTE *pte = lookup(VPN, Asid);
- if (req->isMisaligned()) {
- // Unaligned address!
- StoreAddressErrorFault *Flt = new StoreAddressErrorFault();
- /* BadVAddr must be set */
- Flt->BadVAddr = req->getVaddr();
- return Flt;
- }
- if (pte != NULL) {
- // Ok, found something
- /* Check for valid bits */
- int EvenOdd;
- bool Valid;
- bool Dirty;
- if (((((req->getVaddr()) >> pte->AddrShiftAmount) & 1)) == 0) {
- // Check even bits
- Valid = pte->V0;
- Dirty = pte->D0;
- EvenOdd = 0;
- } else {
- // Check odd bits
- Valid = pte->V1;
- Dirty = pte->D1;
- EvenOdd = 1;
- }
-
- if (Valid == false) {
- //Invalid entry
- DtbInvalidFault *Flt = new DtbInvalidFault();
- /* EntryHi VPN, ASID fields must be set */
- Flt->EntryHi_Asid = Asid;
- Flt->EntryHi_VPN2 = (VPN>>2);
- Flt->EntryHi_VPN2X = (VPN & 0x3);
-
- /* BadVAddr must be set */
- Flt->BadVAddr = req->getVaddr();
-
- /* Context must be set */
- Flt->Context_BadVPN2 = (VPN >> 2);
-
- return Flt;
- } else {
- // Ok, this is really a match, set paddr
- if (!Dirty) {
- TLBModifiedFault *Flt = new TLBModifiedFault();
- /* EntryHi VPN, ASID fields must be set */
- Flt->EntryHi_Asid = Asid;
- Flt->EntryHi_VPN2 = (VPN >> 2);
- Flt->EntryHi_VPN2X = (VPN & 0x3);
-
- /* BadVAddr must be set */
- Flt->BadVAddr = req->getVaddr();
-
- /* Context must be set */
- Flt->Context_BadVPN2 = (VPN >> 2);
- return Flt;
- }
- Addr PAddr;
- if (EvenOdd == 0) {
- PAddr = pte->PFN0;
- } else {
- PAddr = pte->PFN1;
- }
- PAddr >>= (pte->AddrShiftAmount - 12);
- PAddr <<= pte->AddrShiftAmount;
- PAddr |= ((req->getVaddr()) & pte->OffsetMask);
- req->setPaddr(PAddr);
- }
- } else {
- // Didn't find any match, return a TLB Refill Exception
- DtbRefillFault *Flt = new DtbRefillFault();
- /* EntryHi VPN, ASID fields must be set */
- Flt->EntryHi_Asid = Asid;
- Flt->EntryHi_VPN2 = (VPN >> 2);
- Flt->EntryHi_VPN2X = (VPN & 0x3);
-
- /* BadVAddr must be set */
- Flt->BadVAddr = req->getVaddr();
-
- /* Context must be set */
- Flt->Context_BadVPN2 = (VPN >> 2);
- return Flt;
- }
- }
- return checkCacheability(req);
-#endif
}
Fault
translation->finish(translateAtomic(req, tc, mode), req, tc, mode);
}
+Fault
+TLB::translateFunctional(RequestPtr req, ThreadContext *tc, Mode mode)
+{
+ panic("Not implemented\n");
+ return NoFault;
+}
+
+Fault
+TLB::finalizePhysical(RequestPtr req, ThreadContext *tc, Mode mode) const
+{
+ return NoFault;
+}
+
MipsISA::PTE &
TLB::index(bool advance)