Move TLB faults into the normal fault classes. Now they are executed when the fault is invoked.

--HG--
extra : convert_revision : b5f00fff277e863b3fe43422bc39d0487c482e60
This commit is contained in:
Kevin Lim 2006-04-22 18:09:08 -04:00
parent 6f590b4ddc
commit bd38b56774
4 changed files with 167 additions and 86 deletions

View file

@ -30,6 +30,9 @@
#include "cpu/exec_context.hh"
#include "cpu/base.hh"
#include "base/trace.hh"
#if FULL_SYSTEM
#include "arch/alpha/ev5.hh"
#endif
namespace AlphaISA
{
@ -70,6 +73,10 @@ FaultName DtbAcvFault::_name = "dfault";
FaultVect DtbAcvFault::_vect = 0x0381;
FaultStat DtbAcvFault::_count;
FaultName DtbAlignmentFault::_name = "unalign";
FaultVect DtbAlignmentFault::_vect = 0x0301;
FaultStat DtbAlignmentFault::_count;
FaultName ItbMissFault::_name = "itbmiss";
FaultVect ItbMissFault::_vect = 0x0181;
FaultStat ItbMissFault::_count;
@ -125,6 +132,44 @@ void ArithmeticFault::invoke(ExecContext * xc)
panic("Arithmetic traps are unimplemented!");
}
void DtbFault::invoke(ExecContext * xc)
{
// Set fault address and flags. Even though we're modeling an
// EV5, we use the EV6 technique of not latching fault registers
// on VPTE loads (instead of locking the registers until IPR_VA is
// read, like the EV5). The EV6 approach is cleaner and seems to
// work with EV5 PAL code, but not the other way around.
if (!xc->misspeculating()
&& !(reqFlags & VPTE) && !(reqFlags & NO_FAULT)) {
// set VA register with faulting address
xc->setMiscReg(AlphaISA::IPR_VA, vaddr);
// set MM_STAT register flags
xc->setMiscReg(AlphaISA::IPR_MM_STAT,
(((EV5::Opcode(xc->getInst()) & 0x3f) << 11)
| ((EV5::Ra(xc->getInst()) & 0x1f) << 6)
| (flags & 0x3f)));
// set VA_FORM register with faulting formatted address
xc->setMiscReg(AlphaISA::IPR_VA_FORM,
xc->readMiscReg(AlphaISA::IPR_MVPTBR) | (vaddr.vpn() << 3));
}
AlphaFault::invoke(xc);
}
void ItbFault::invoke(ExecContext * xc)
{
if (!xc->misspeculating()) {
xc->setMiscReg(AlphaISA::IPR_ITB_TAG, pc);
xc->setMiscReg(AlphaISA::IPR_IFAULT_VA_FORM,
xc->readMiscReg(AlphaISA::IPR_IVPTBR) |
(AlphaISA::VAddr(pc).vpn() << 3));
}
AlphaFault::invoke(xc);
}
#endif
} // namespace AlphaISA

View file

@ -29,6 +29,7 @@
#ifndef __ALPHA_FAULTS_HH__
#define __ALPHA_FAULTS_HH__
#include "arch/alpha/isa_traits.hh"
#include "sim/faults.hh"
// The design of the "name" and "vect" functions is in sim/faults.hh
@ -130,85 +131,167 @@ class InterruptFault : public AlphaFault
FaultStat & countStat() {return _count;}
};
class NDtbMissFault : public AlphaFault
class DtbFault : public AlphaFault
{
#if FULL_SYSTEM
private:
AlphaISA::VAddr vaddr;
uint32_t reqFlags;
uint64_t flags;
public:
DtbFault(AlphaISA::VAddr _vaddr, uint32_t _reqFlags, uint64_t _flags)
: vaddr(_vaddr), reqFlags(_reqFlags), flags(_flags)
{ }
#endif
FaultName name() = 0;
FaultVect vect() = 0;
FaultStat & countStat() = 0;
#if FULL_SYSTEM
void invoke(ExecContext * xc);
#endif
};
class NDtbMissFault : public DtbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
#if FULL_SYSTEM
NDtbMissFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
: DtbFault(vaddr, reqFlags, flags)
{ }
#endif
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
};
class PDtbMissFault : public AlphaFault
class PDtbMissFault : public DtbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
#if FULL_SYSTEM
PDtbMissFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
: DtbFault(vaddr, reqFlags, flags)
{ }
#endif
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
};
class DtbPageFault : public AlphaFault
class DtbPageFault : public DtbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
#if FULL_SYSTEM
DtbPageFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
: DtbFault(vaddr, reqFlags, flags)
{ }
#endif
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
};
class DtbAcvFault : public AlphaFault
class DtbAcvFault : public DtbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
#if FULL_SYSTEM
DtbAcvFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
: DtbFault(vaddr, reqFlags, flags)
{ }
#endif
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
};
class ItbMissFault : public AlphaFault
class DtbAlignmentFault : public DtbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
#if FULL_SYSTEM
DtbAlignmentFault(AlphaISA::VAddr vaddr, uint32_t reqFlags, uint64_t flags)
: DtbFault(vaddr, reqFlags, flags)
{ }
#endif
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
};
class ItbPageFault : public AlphaFault
class ItbFault : public AlphaFault
{
private:
Addr pc;
public:
ItbFault(Addr _pc)
: pc(_pc)
{ }
FaultName name() = 0;
FaultVect vect() = 0;
FaultStat & countStat() = 0;
#if FULL_SYSTEM
void invoke(ExecContext * xc);
#endif
};
class ItbMissFault : public ItbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
ItbMissFault(Addr pc)
: ItbFault(pc)
{ }
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
};
class ItbAcvFault : public AlphaFault
class ItbPageFault : public ItbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
ItbPageFault(Addr pc)
: ItbFault(pc)
{ }
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}
};
class ItbAcvFault : public ItbFault
{
private:
static FaultName _name;
static FaultVect _vect;
static FaultStat _count;
public:
ItbAcvFault(Addr pc)
: ItbFault(pc)
{ }
FaultName name() {return _name;}
FaultVect vect() {return _vect;}
FaultStat & countStat() {return _count;}

View file

@ -290,17 +290,6 @@ AlphaITB::regStats()
accesses = hits + misses;
}
void
AlphaITB::fault(Addr pc, ExecContext *xc) const
{
if (!xc->misspeculating()) {
xc->setMiscReg(AlphaISA::IPR_ITB_TAG, pc);
xc->setMiscReg(AlphaISA::IPR_IFAULT_VA_FORM,
xc->readMiscReg(AlphaISA::IPR_IVPTBR) |
(AlphaISA::VAddr(pc).vpn() << 3));
}
}
Fault
AlphaITB::translate(MemReqPtr &req) const
@ -319,9 +308,8 @@ AlphaITB::translate(MemReqPtr &req) const
} else {
// verify that this is a good virtual address
if (!validVirtualAddress(req->vaddr)) {
fault(req->vaddr, req->xc);
acv++;
return new ItbAcvFault;
return new ItbAcvFault(req->vaddr);
}
@ -336,9 +324,8 @@ AlphaITB::translate(MemReqPtr &req) const
// only valid in kernel mode
if (ICM_CM(xc->readMiscReg(AlphaISA::IPR_ICM)) !=
AlphaISA::mode_kernel) {
fault(req->vaddr, req->xc);
acv++;
return new ItbAcvFault;
return new ItbAcvFault(req->vaddr);
}
req->paddr = req->vaddr & PAddrImplMask;
@ -358,9 +345,8 @@ AlphaITB::translate(MemReqPtr &req) const
asn);
if (!pte) {
fault(req->vaddr, req->xc);
misses++;
return new ItbPageFault;
return new ItbPageFault(req->vaddr);
}
req->paddr = (pte->ppn << AlphaISA::PageShift) +
@ -370,9 +356,8 @@ AlphaITB::translate(MemReqPtr &req) const
if (!(pte->xre &
(1 << ICM_CM(xc->readMiscReg(AlphaISA::IPR_ICM))))) {
// instruction access fault
fault(req->vaddr, req->xc);
acv++;
return new ItbAcvFault;
return new ItbAcvFault(req->vaddr);
}
hits++;
@ -465,34 +450,6 @@ AlphaDTB::regStats()
accesses = read_accesses + write_accesses;
}
void
AlphaDTB::fault(MemReqPtr &req, uint64_t flags) const
{
ExecContext *xc = req->xc;
AlphaISA::VAddr vaddr = req->vaddr;
// Set fault address and flags. Even though we're modeling an
// EV5, we use the EV6 technique of not latching fault registers
// on VPTE loads (instead of locking the registers until IPR_VA is
// read, like the EV5). The EV6 approach is cleaner and seems to
// work with EV5 PAL code, but not the other way around.
if (!xc->misspeculating()
&& !(req->flags & VPTE) && !(req->flags & NO_FAULT)) {
// set VA register with faulting address
xc->setMiscReg(AlphaISA::IPR_VA, req->vaddr);
// set MM_STAT register flags
xc->setMiscReg(AlphaISA::IPR_MM_STAT,
(((Opcode(xc->getInst()) & 0x3f) << 11)
| ((Ra(xc->getInst()) & 0x1f) << 6)
| (flags & 0x3f)));
// set VA_FORM register with faulting formatted address
xc->setMiscReg(AlphaISA::IPR_VA_FORM,
xc->readMiscReg(AlphaISA::IPR_MVPTBR) | (vaddr.vpn() << 3));
}
}
Fault
AlphaDTB::translate(MemReqPtr &req, bool write) const
{
@ -507,10 +464,10 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
* Check for alignment faults
*/
if (req->vaddr & (req->size - 1)) {
fault(req, write ? MM_STAT_WR_MASK : 0);
DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->vaddr,
req->size);
return genAlignmentFault();
uint64_t flags = write ? MM_STAT_WR_MASK : 0;
return new DtbAlignmentFault(req->vaddr, req->flags, flags);
}
if (pc & 0x1) {
@ -525,12 +482,11 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
} else {
// verify that this is a good virtual address
if (!validVirtualAddress(req->vaddr)) {
fault(req, (write ? MM_STAT_WR_MASK : 0) |
MM_STAT_BAD_VA_MASK |
MM_STAT_ACV_MASK);
if (write) { write_acv++; } else { read_acv++; }
return new DtbPageFault;
uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
MM_STAT_BAD_VA_MASK |
MM_STAT_ACV_MASK;
return new DtbPageFault(req->vaddr, req->flags, flags);
}
// Check for "superpage" mapping
@ -544,10 +500,10 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
// only valid in kernel mode
if (DTB_CM_CM(xc->readMiscReg(AlphaISA::IPR_DTB_CM)) !=
AlphaISA::mode_kernel) {
fault(req, ((write ? MM_STAT_WR_MASK : 0) |
MM_STAT_ACV_MASK));
if (write) { write_acv++; } else { read_acv++; }
return new DtbAcvFault;
uint64_t flags = ((write ? MM_STAT_WR_MASK : 0) |
MM_STAT_ACV_MASK);
return new DtbAcvFault(req->vaddr, req->flags, flags);
}
req->paddr = req->vaddr & PAddrImplMask;
@ -574,12 +530,14 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
if (!pte) {
// page fault
fault(req, (write ? MM_STAT_WR_MASK : 0) |
MM_STAT_DTB_MISS_MASK);
if (write) { write_misses++; } else { read_misses++; }
uint64_t flags = (write ? MM_STAT_WR_MASK : 0) |
MM_STAT_DTB_MISS_MASK;
return (req->flags & VPTE) ?
(Fault)(new PDtbMissFault) :
(Fault)(new NDtbMissFault);
(Fault)(new PDtbMissFault(req->vaddr, req->flags,
flags)) :
(Fault)(new NDtbMissFault(req->vaddr, req->flags,
flags));
}
req->paddr = (pte->ppn << AlphaISA::PageShift) +
@ -588,29 +546,29 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
if (write) {
if (!(pte->xwe & MODE2MASK(mode))) {
// declare the instruction access fault
fault(req, MM_STAT_WR_MASK |
MM_STAT_ACV_MASK |
(pte->fonw ? MM_STAT_FONW_MASK : 0));
write_acv++;
return new DtbPageFault;
uint64_t flags = MM_STAT_WR_MASK |
MM_STAT_ACV_MASK |
(pte->fonw ? MM_STAT_FONW_MASK : 0);
return new DtbPageFault(req->vaddr, req->flags, flags);
}
if (pte->fonw) {
fault(req, MM_STAT_WR_MASK |
MM_STAT_FONW_MASK);
write_acv++;
return new DtbPageFault;
uint64_t flags = MM_STAT_WR_MASK |
MM_STAT_FONW_MASK;
return new DtbPageFault(req->vaddr, req->flags, flags);
}
} else {
if (!(pte->xre & MODE2MASK(mode))) {
fault(req, MM_STAT_ACV_MASK |
(pte->fonr ? MM_STAT_FONR_MASK : 0));
read_acv++;
return new DtbAcvFault;
uint64_t flags = MM_STAT_ACV_MASK |
(pte->fonr ? MM_STAT_FONR_MASK : 0);
return new DtbAcvFault(req->vaddr, req->flags, flags);
}
if (pte->fonr) {
fault(req, MM_STAT_FONR_MASK);
read_acv++;
return new DtbPageFault;
uint64_t flags = MM_STAT_FONR_MASK;
return new DtbPageFault(req->vaddr, req->flags, flags);
}
}
}

View file

@ -31,6 +31,7 @@
#include <map>
#include "arch/alpha/ev5.hh"
#include "arch/alpha/isa_traits.hh"
#include "arch/alpha/faults.hh"
#include "base/statistics.hh"
@ -87,9 +88,6 @@ class AlphaITB : public AlphaTLB
mutable Stats::Scalar<> acv;
mutable Stats::Formula accesses;
protected:
void fault(Addr pc, ExecContext *xc) const;
public:
AlphaITB(const std::string &name, int size);
virtual void regStats();
@ -113,9 +111,6 @@ class AlphaDTB : public AlphaTLB
Stats::Formula acv;
Stats::Formula accesses;
protected:
void fault(MemReqPtr &req, uint64_t flags) const;
public:
AlphaDTB(const std::string &name, int size);
virtual void regStats();