break;
case MISCREG_SCTLR:
{
+ DPRINTF(MiscRegs, "Writing SCTLR: %#x\n", newVal);
SCTLR sctlr = miscRegs[MISCREG_SCTLR];
SCTLR new_sctlr = newVal;
new_sctlr.nmfi = (bool)sctlr.nmfi;
sctlr.nmfi = (bool)sctlr_rst.nmfi;
sctlr.v = (bool)sctlr_rst.v;
sctlr.u = 1;
- sctlr.rao1 = 1;
+ sctlr.xp = 1;
sctlr.rao2 = 1;
sctlr.rao3 = 1;
sctlr.rao4 = 1;
}
break;
case 2:
- if (opc2 == 0 && crm == 0) {
+ if (opc1 == 0 && crm == 0) {
switch (opc2) {
case 0:
return MISCREG_TTBR0;
case 13:
if (opc1 == 0) {
if (crm == 0) {
- switch (crm) {
+ switch (opc2) {
case 0:
return MISCREG_FCEIDR;
case 1:
MISCREG_NMRR,
MISCREG_TTBCR,
MISCREG_ID_PFR0,
+ MISCREG_CTR,
+ MISCREG_SCR,
+ MISCREG_SDER,
MISCREG_CP15_UNIMP_START,
- MISCREG_CTR = MISCREG_CP15_UNIMP_START,
- MISCREG_TCMTR,
+ MISCREG_TCMTR = MISCREG_CP15_UNIMP_START,
MISCREG_ID_PFR1,
MISCREG_ID_DFR0,
MISCREG_ID_AFR0,
MISCREG_DCISW,
MISCREG_MCCSW,
MISCREG_DCCMVAU,
- MISCREG_SCR,
- MISCREG_SDER,
MISCREG_NSACR,
MISCREG_V2PCWPR,
MISCREG_V2PCWPW,
"dtlbiall", "dtlbimva", "dtlbiasid",
"tlbiall", "tlbimva", "tlbiasid", "tlbimvaa",
"dfsr", "ifsr", "dfar", "ifar", "mpidr",
- "prrr", "nmrr", "ttbcr", "id_pfr0",
+ "prrr", "nmrr", "ttbcr", "id_pfr0", "ctr"
+ "scr", "sder"
// Unimplemented below
- "ctr", "tcmtr",
+ "tcmtr",
"id_pfr1", "id_dfr0", "id_afr0",
"id_mmfr0", "id_mmfr1", "id_mmfr2", "id_mmfr3",
"id_isar0", "id_isar1", "id_isar2", "id_isar3", "id_isar4", "id_isar5",
"adfsr", "aifsr",
"dcimvac", "dcisw", "mccsw",
"dccmvau",
- "scr", "sder", "nsacr",
+ "nsacr",
"v2pcwpr", "v2pcwpw", "v2pcwur", "v2pcwuw",
"v2powpr", "v2powpw", "v2powur", "v2powuw",
"vbar", "mvbar", "isr", "fceidr",
Bitfield<27> nmfi;// Non-maskable fast interrupts enable
Bitfield<25> ee; // Exception Endianness bit
Bitfield<24> ve; // Interrupt vectors enable
- Bitfield<23> rao1;// Read as one
+ Bitfield<23> xp; // Extended page table enable bit
Bitfield<22> u; // Alignment (now unused)
Bitfield<21> fi; // Fast interrupts configuration enable
Bitfield<19> dz; // Divide by Zero fault enable bit
Bitfield<12> i; // instruction cache enable
Bitfield<11> z; // branch prediction enable bit
Bitfield<10> sw; // Enable swp/swpb
+ Bitfield<9,8> rs; // deprecated protection bits
Bitfield<6,3> rao4;// Read as one
Bitfield<7> b; // Endianness support (unused)
Bitfield<2> c; // Cache enable bit
// If translation isn't enabled, we shouldn't be here
assert(sctlr.m);
- if (N == 0 || mbits(vaddr, 31, 32-N)) {
+ DPRINTF(TLB, "Begining table walk for address %#x, TTBCR: %#x, bits:%#x\n",
+ vaddr, N, mbits(vaddr, 31, 32-N));
+
+ if (N == 0 || !mbits(vaddr, 31, 32-N)) {
+ DPRINTF(TLB, " - Selecting TTBR0\n");
ttbr = tc->readMiscReg(MISCREG_TTBR0);
} else {
- ttbr = tc->readMiscReg(MISCREG_TTBR0);
+ DPRINTF(TLB, " - Selecting TTBR1\n");
+ ttbr = tc->readMiscReg(MISCREG_TTBR1);
N = 0;
}
Addr l1desc_addr = mbits(ttbr, 31, 14-N) | (bits(vaddr,31-N,20) << 2);
- DPRINTF(TLB, "Begining table walk for address %#x at descriptor %#x\n",
- vaddr, l1desc_addr);
+ DPRINTF(TLB, " - Descriptor at address %#x\n", l1desc_addr);
// Trickbox address check
fault = tlb->walkTrickBoxCheck(l1desc_addr, vaddr, sizeof(uint32_t),
- isFetch, 0, true);
+ isFetch, isWrite, 0, true);
if (fault) {
tc = NULL;
req = NULL;
case L1Descriptor::Reserved:
tc = NULL;
req = NULL;
- fault = new DataAbort(vaddr, NULL, isWrite, ArmFault::Translation0);
+ DPRINTF(TLB, "L1 Descriptor Reserved/Ignore, causing fault\n");
+ if (isFetch)
+ fault = new PrefetchAbort(vaddr, ArmFault::Translation0);
+ else
+ fault = new DataAbort(vaddr, NULL, isWrite, ArmFault::Translation0);
return;
case L1Descriptor::Section:
if (sctlr.afe && bits(l1Desc.ap(), 0) == 0)
// Trickbox address check
fault = tlb->walkTrickBoxCheck(l2desc_addr, vaddr, sizeof(uint32_t),
- isFetch, l1Desc.domain(), false);
+ isFetch, isWrite, l1Desc.domain(), false);
if (fault) {
tc = NULL;
req = NULL;
DPRINTF(TLB, "L2 descriptor invalid, causing fault\n");
tc = NULL;
req = NULL;
- fault = new DataAbort(vaddr, l1Desc.domain(), isWrite, ArmFault::Translation1);
+ if (isFetch)
+ fault = new PrefetchAbort(vaddr, ArmFault::Translation1);
+ else
+ fault = new DataAbort(vaddr, l1Desc.domain(), isWrite, ArmFault::Translation1);
return;
}
/** Is the translation global (no asid used)? */
bool global() const
{
- return bits(data, 17);
+ return bits(data, 4);
}
/** Is the translation not allow execution? */
/** Memory region attributes: ARM DDI 0406B: B3-32 */
uint8_t texcb() const
{
- return bits(data, 2) | bits(data,3) << 1 | bits(data, 12, 14) << 2;
+ return bits(data, 2) | bits(data,3) << 1 | bits(data, 14, 12) << 2;
}
};
uint8_t texcb() const
{
return large() ?
- (bits(data, 2) | (bits(data,3) << 1) | (bits(data, 12, 14) << 2)) :
- (bits(data, 2) | (bits(data,3) << 1) | (bits(data, 6, 8) << 2));
+ (bits(data, 2) | (bits(data,3) << 1) | (bits(data, 14, 12) << 2)) :
+ (bits(data, 2) | (bits(data,3) << 1) | (bits(data, 8, 6) << 2));
}
/** Return the physical frame, bits shifted right */
#include "arch/arm/faults.hh"
#include "arch/arm/pagetable.hh"
-#include "arch/arm/table_walker.hh"
#include "arch/arm/tlb.hh"
#include "arch/arm/utility.hh"
#include "base/inifile.hh"
#include "params/ArmTLB.hh"
#include "sim/process.hh"
+#if FULL_SYSTEM
+#include "arch/arm/table_walker.hh"
+#endif
+
using namespace std;
using namespace ArmISA;
table = new TlbEntry[size];
memset(table, 0, sizeof(TlbEntry[size]));
+#if FULL_SYSTEM
tableWalker->setTlb(this);
+#endif
}
TLB::~TLB()
accesses = read_accesses + write_accesses;
}
-Fault
-TLB::trickBoxCheck(RequestPtr req, Mode mode, uint8_t domain, bool sNp)
-{
- return NoFault;
-}
-
-Fault
-TLB::walkTrickBoxCheck(Addr pa, Addr va, Addr sz, bool is_exec,
- uint8_t domain, bool sNp)
-{
- return NoFault;
-}
-
#if !FULL_SYSTEM
Fault
TLB::translateSe(RequestPtr req, ThreadContext *tc, Mode mode,
#else // FULL_SYSTEM
+Fault
+TLB::trickBoxCheck(RequestPtr req, Mode mode, uint8_t domain, bool sNp)
+{
+ return NoFault;
+}
+
+Fault
+TLB::walkTrickBoxCheck(Addr pa, Addr va, Addr sz, bool is_exec,
+ bool is_write, uint8_t domain, bool sNp)
+{
+ return NoFault;
+}
+
Fault
TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
Translation *translation, bool &delay, bool timing)
bool abt;
+ /* if (!sctlr.xp)
+ ap &= 0x3;
+*/
switch (ap) {
case 0:
- abt = true;
+ DPRINTF(TLB, "Access permissions 0, checking rs:%#x\n", (int)sctlr.rs);
+ if (!sctlr.xp) {
+ switch ((int)sctlr.rs) {
+ case 2:
+ abt = is_write;
+ break;
+ case 1:
+ abt = is_write || !is_priv;
+ break;
+ case 0:
+ case 3:
+ default:
+ abt = true;
+ break;
+ }
+ } else {
+ abt = true;
+ }
break;
case 1:
abt = !is_priv;
TlbEntry *table; // the Page Table
int size; // TLB Size
int nlu; // not last used entry (for replacement)
+
+#if FULL_SYSTEM
TableWalker *tableWalker;
+#endif
void nextnlu() { if (++nlu >= size) nlu = 0; }
TlbEntry *lookup(Addr vpn, uint8_t asn);
void flushMva(Addr mva);
Fault trickBoxCheck(RequestPtr req, Mode mode, uint8_t domain, bool sNp);
- Fault walkTrickBoxCheck(Addr pa, Addr va, Addr sz, bool is_exec, uint8_t
- domain, bool sNp);
+ Fault walkTrickBoxCheck(Addr pa, Addr va, Addr sz, bool is_exec,
+ bool is_write, uint8_t domain, bool sNp);
void printTlb();