* Steve Reinhardt
*/
+#include "arch/arm/tlb.hh"
+
#include <memory>
#include <string>
#include <vector>
#include "arch/arm/table_walker.hh"
#include "arch/arm/stage2_lookup.hh"
#include "arch/arm/stage2_mmu.hh"
-#include "arch/arm/tlb.hh"
#include "arch/arm/utility.hh"
#include "base/inifile.hh"
#include "base/str.hh"
: BaseTLB(p), table(new TlbEntry[p->size]), size(p->size),
isStage2(p->is_stage2), stage2Req(false), _attr(0),
directToStage2(false), tableWalker(p->walker), stage2Tlb(NULL),
- stage2Mmu(NULL), rangeMRU(1), bootUncacheability(false),
+ stage2Mmu(NULL), rangeMRU(1),
aarch64(false), aarch64EL(EL0), isPriv(false), isSecure(false),
isHyp(false), asid(0), vmid(0), dacr(0),
- miscRegValid(false), curTranType(NormalTran)
+ miscRegValid(false), miscRegContext(0), curTranType(NormalTran)
{
tableWalker->setTlb(this);
// than rangeMRU
if (x > rangeMRU && !functional) {
TlbEntry tmp_entry = table[x];
- for(int i = x; i > 0; i--)
+ for (int i = x; i > 0; i--)
table[i] = table[i - 1];
table[0] = tmp_entry;
retval = &table[0];
haveLPAE = otlb->haveLPAE;
directToStage2 = otlb->directToStage2;
stage2Req = otlb->stage2Req;
- bootUncacheability = otlb->bootUncacheability;
/* Sync the stage2 MMU if they exist in both
* the old CPU and the new
}
void
-TLB::serialize(ostream &os)
+TLB::serialize(CheckpointOut &cp) const
{
DPRINTF(Checkpoint, "Serializing Arm TLB\n");
SERIALIZE_SCALAR(haveLPAE);
SERIALIZE_SCALAR(directToStage2);
SERIALIZE_SCALAR(stage2Req);
- SERIALIZE_SCALAR(bootUncacheability);
int num_entries = size;
SERIALIZE_SCALAR(num_entries);
- for(int i = 0; i < size; i++){
- nameOut(os, csprintf("%s.TlbEntry%d", name(), i));
- table[i].serialize(os);
- }
+ for (int i = 0; i < size; i++)
+ table[i].serializeSection(cp, csprintf("TlbEntry%d", i));
}
void
-TLB::unserialize(Checkpoint *cp, const string §ion)
+TLB::unserialize(CheckpointIn &cp)
{
DPRINTF(Checkpoint, "Unserializing Arm TLB\n");
UNSERIALIZE_SCALAR(haveLPAE);
UNSERIALIZE_SCALAR(directToStage2);
UNSERIALIZE_SCALAR(stage2Req);
- UNSERIALIZE_SCALAR(bootUncacheability);
int num_entries;
UNSERIALIZE_SCALAR(num_entries);
- for(int i = 0; i < min(size, num_entries); i++){
- table[i].unserialize(cp, csprintf("%s.TlbEntry%d", section, i));
- }
+ for (int i = 0; i < min(size, num_entries); i++)
+ table[i].unserializeSection(cp, csprintf("TlbEntry%d", i));
}
void
Addr vaddr_tainted = req->getVaddr();
Addr vaddr = 0;
if (aarch64)
- vaddr = purifyTaggedAddr(vaddr_tainted, tc, aarch64EL);
+ vaddr = purifyTaggedAddr(vaddr_tainted, tc, aarch64EL, ttbcr);
else
vaddr = vaddr_tainted;
uint32_t flags = req->getFlags();
assert(aarch64);
Addr vaddr_tainted = req->getVaddr();
- Addr vaddr = purifyTaggedAddr(vaddr_tainted, tc, aarch64EL);
+ Addr vaddr = purifyTaggedAddr(vaddr_tainted, tc, aarch64EL, ttbcr);
uint32_t flags = req->getFlags();
bool is_fetch = (mode == Execute);
Addr vaddr_tainted = req->getVaddr();
Addr vaddr = 0;
if (aarch64)
- vaddr = purifyTaggedAddr(vaddr_tainted, tc, aarch64EL);
+ vaddr = purifyTaggedAddr(vaddr_tainted, tc, aarch64EL, ttbcr);
else
vaddr = vaddr_tainted;
uint32_t flags = req->getFlags();
"flags %#x tranType 0x%x\n", vaddr_tainted, mode, isStage2,
scr, sctlr, flags, tranType);
- // If this is a clrex instruction, provide a PA of 0 with no fault
- // This will force the monitor to set the tracked address to 0
- // a bit of a hack but this effectively clrears this processors monitor
- if (flags & Request::CLEAR_LL){
- // @todo: check implications of security extensions
- req->setPaddr(0);
- req->setFlags(Request::UNCACHEABLE);
- req->setFlags(Request::CLEAR_LL);
- return NoFault;
- }
if ((req->isInstFetch() && (!sctlr.i)) ||
((!req->isInstFetch()) && (!sctlr.c))){
- req->setFlags(Request::UNCACHEABLE);
+ req->setFlags(Request::UNCACHEABLE | Request::STRICT_ORDER);
}
if (!is_fetch) {
assert(flags & MustBeOne);
// @todo: double check this (ARM ARM issue C B3.2.1)
if (long_desc_format || sctlr.tre == 0) {
- req->setFlags(Request::UNCACHEABLE);
+ req->setFlags(Request::UNCACHEABLE | Request::STRICT_ORDER);
} else {
if (nmrr.ir0 == 0 || nmrr.or0 == 0 || prrr.tr0 != 0x2)
- req->setFlags(Request::UNCACHEABLE);
+ req->setFlags(Request::UNCACHEABLE | Request::STRICT_ORDER);
}
// Set memory attributes
te->shareable, te->innerAttrs, te->outerAttrs,
static_cast<uint8_t>(te->mtype), isStage2);
setAttr(te->attributes);
- if (te->nonCacheable) {
- req->setFlags(Request::UNCACHEABLE);
- }
- if (!bootUncacheability &&
- ((ArmSystem*)tc->getSystemPtr())->adderBootUncacheable(vaddr)) {
+ if (te->nonCacheable)
req->setFlags(Request::UNCACHEABLE);
- }
+
+ // Require requests to be ordered if the request goes to
+ // strongly ordered or device memory (i.e., anything other
+ // than normal memory requires strict order).
+ if (te->mtype != TlbEntry::MemoryType::Normal)
+ req->setFlags(Request::STRICT_ORDER);
Addr pa = te->pAddr(vaddr);
req->setPaddr(pa);
- if (!bootUncacheability &&
- ((ArmSystem*)tc->getSystemPtr())->adderBootUncacheable(pa)) {
- req->setFlags(Request::UNCACHEABLE);
- }
-
if (isSecure && !te->ns) {
req->setFlags(Request::SECURE);
}
// Generate Illegal Inst Set State fault if IL bit is set in CPSR
if (fault == NoFault) {
- CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
if (aarch64 && is_fetch && cpsr.il == 1) {
return std::make_shared<IllegalInstSetStateFault>();
}
// check if the regs have changed, or the translation mode is different.
// NOTE: the tran type doesn't affect stage 2 TLB's as they only handle
// one type of translation anyway
- if (miscRegValid && ((tranType == curTranType) || isStage2)) {
+ if (miscRegValid && miscRegContext == tc->contextId() &&
+ ((tranType == curTranType) || isStage2)) {
return;
}
DPRINTF(TLBVerbose, "TLB variables changed!\n");
- CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
+ cpsr = tc->readMiscReg(MISCREG_CPSR);
// Dependencies: SCR/SCR_EL3, CPSR
isSecure = inSecureState(tc);
isSecure &= (tranType & HypMode) == 0;
}
}
miscRegValid = true;
+ miscRegContext = tc->contextId();
curTranType = tranType;
}
Addr vaddr = 0;
ExceptionLevel target_el = aarch64 ? aarch64EL : EL1;
if (aarch64) {
- vaddr = purifyTaggedAddr(vaddr_tainted, tc, target_el);
+ vaddr = purifyTaggedAddr(vaddr_tainted, tc, target_el, ttbcr);
} else {
vaddr = vaddr_tainted;
}