From 1d5233958ad208e3b229e394ba5ab689b82d8cac Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 2 Jun 2010 12:58:10 -0500 Subject: ARM: Implement the V7 version of alignment checking. --- src/arch/arm/insts/macromem.hh | 3 ++- src/arch/arm/isa/insts/branch.isa | 15 ++++++++++++--- src/arch/arm/isa/insts/ldr.isa | 28 ++++++++++++++++++++-------- src/arch/arm/isa/insts/mem.isa | 5 +---- src/arch/arm/isa/insts/str.isa | 16 ++++++++++++---- src/arch/arm/isa/insts/swap.isa | 8 ++++++-- src/arch/arm/tlb.cc | 13 ++++++++++++- src/arch/arm/tlb.hh | 15 +++++++++++++++ 8 files changed, 80 insertions(+), 23 deletions(-) (limited to 'src/arch') diff --git a/src/arch/arm/insts/macromem.hh b/src/arch/arm/insts/macromem.hh index 21a37a29e..436a5b4a3 100644 --- a/src/arch/arm/insts/macromem.hh +++ b/src/arch/arm/insts/macromem.hh @@ -43,6 +43,7 @@ #define __ARCH_ARM_MACROMEM_HH__ #include "arch/arm/insts/pred_inst.hh" +#include "arch/arm/tlb.hh" namespace ArmISA { @@ -88,7 +89,7 @@ class MicroMemOp : public MicroIntOp MicroMemOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, RegIndex _ura, RegIndex _urb, bool _up, uint8_t _imm) : MicroIntOp(mnem, machInst, __opClass, _ura, _urb, _imm), - up(_up), memAccessFlags(0) + up(_up), memAccessFlags(TLB::MustBeOne | TLB::AlignWord) { } }; diff --git a/src/arch/arm/isa/insts/branch.isa b/src/arch/arm/isa/insts/branch.isa index b79f610b6..1aa37f483 100644 --- a/src/arch/arm/isa/insts/branch.isa +++ b/src/arch/arm/isa/insts/branch.isa @@ -153,14 +153,23 @@ let {{ #TBB, TBH for isTbh in (0, 1): if isTbh: - eaCode = "EA = Op1 + Op2 * 2" + eaCode = ''' + unsigned memAccessFlags = ArmISA::TLB::AllowUnaligned | + ArmISA::TLB::AlignHalfWord | + ArmISA::TLB::MustBeOne; + EA = Op1 + Op2 * 2 + ''' accCode = "NPC = readPC(xc) + 2 * (Mem.uh);" mnem = "tbh" else: - eaCode = "EA = Op1 + Op2" + eaCode = ''' + unsigned memAccessFlags = ArmISA::TLB::AllowUnaligned | + ArmISA::TLB::AlignByte | + ArmISA::TLB::MustBeOne; + EA = Op1 + Op2 + ''' accCode = "NPC = readPC(xc) + 2 * (Mem.ub);" mnem = "tbb" - eaCode = "unsigned memAccessFlags = 0;\n" + eaCode iop = InstObjParams(mnem, mnem.capitalize(), "BranchRegReg", {'ea_code': eaCode, 'memacc_code': accCode, diff --git a/src/arch/arm/isa/insts/ldr.isa b/src/arch/arm/isa/insts/ldr.isa index cb4c5c869..b216daa6d 100644 --- a/src/arch/arm/isa/insts/ldr.isa +++ b/src/arch/arm/isa/insts/ldr.isa @@ -92,20 +92,23 @@ let {{ eaCode += offset eaCode += ";" + memFlags = ["ArmISA::TLB::MustBeOne", "%d" % (size - 1)] if prefetch: Name = "%s_%s" % (mnem.upper(), Name) - memFlags = ["Request::PREFETCH"] + memFlags.append("Request::PREFETCH") accCode = ''' uint64_t temp = Mem%s;\n temp = temp; ''' % buildMemSuffix(sign, size) else: if ldrex: - memFlags = ["Request::LLSC"] + memFlags.append("Request::LLSC") Name = "%s_%s" % (mnem.upper(), Name) - else: - memFlags = [] accCode = "IWDest = Mem%s;\n" % buildMemSuffix(sign, size) + + if not prefetch and not ldrex: + memFlags.append("ArmISA::TLB::AllowUnaligned") + if writeback: accCode += "Base = Base %s;\n" % offset base = buildMemBase("MemoryImm", post, writeback) @@ -142,7 +145,8 @@ let {{ (newHeader, newDecoder, - newExec) = RfeBase(name, Name, eaCode, accCode, [], []) + newExec) = RfeBase(name, Name, eaCode, accCode, + ["ArmISA::TLB::AlignWord", "ArmISA::TLB::MustBeOne"], []) header_output += newHeader decoder_output += newDecoder @@ -166,18 +170,22 @@ let {{ eaCode += offset eaCode += ";" + memFlags = ["%d" % (size - 1), "ArmISA::TLB::MustBeOne"] if prefetch: Name = "%s_%s" % (mnem.upper(), Name) - memFlags = ["Request::PREFETCH"] + memFlags.append("Request::PREFETCH") accCode = ''' uint64_t temp = Mem%s;\n temp = temp; ''' % buildMemSuffix(sign, size) else: - memFlags = [] accCode = "IWDest = Mem%s;\n" % buildMemSuffix(sign, size) if writeback: accCode += "Base = Base %s;\n" % offset + + if not prefetch: + memFlags.append("ArmISA::TLB::AllowUnaligned") + base = buildMemBase("MemoryReg", post, writeback) emitLoad(name, Name, False, eaCode, accCode, \ @@ -211,6 +219,9 @@ let {{ accCode += "Base = Base %s;\n" % offset base = buildMemBase("MemoryDImm", post, writeback) + memFlags.extend(["ArmISA::TLB::MustBeOne", + "ArmISA::TLB::AlignWord"]) + emitLoad(name, Name, True, eaCode, accCode, \ memFlags, [], base, double=True) @@ -239,7 +250,8 @@ let {{ base = buildMemBase("MemoryDReg", post, writeback) emitLoad(name, Name, False, eaCode, accCode, - [], [], base, double=True) + ["ArmISA::TLB::MustBeOne", "ArmISA::TLB::AlignWord"], + [], base, double=True) def buildLoads(mnem, size=4, sign=False, user=False): buildImmLoad(mnem, True, True, True, size, sign, user) diff --git a/src/arch/arm/isa/insts/mem.isa b/src/arch/arm/isa/insts/mem.isa index 7f893bbed..db3665a54 100644 --- a/src/arch/arm/isa/insts/mem.isa +++ b/src/arch/arm/isa/insts/mem.isa @@ -50,10 +50,7 @@ let {{ # This shouldn't be part of the eaCode, but until the exec templates # are converted over it's the easiest place to put it. eaCode += '\n unsigned memAccessFlags = ' - if memFlags: - eaCode += (string.join(memFlags, '|') + ';') - else: - eaCode += '0;' + eaCode += (string.join(memFlags, '|') + ';') codeBlobs["ea_code"] = eaCode diff --git a/src/arch/arm/isa/insts/str.isa b/src/arch/arm/isa/insts/str.isa index cf9eed74e..c22245947 100644 --- a/src/arch/arm/isa/insts/str.isa +++ b/src/arch/arm/isa/insts/str.isa @@ -98,7 +98,10 @@ let {{ accCode += "Base = Base %s;\n" % offset base = buildMemBase("MemoryImm", post, writeback) - emitStore(name, Name, True, eaCode, accCode, [], [], base) + emitStore(name, Name, True, eaCode, accCode, \ + ["ArmISA::TLB::MustBeOne", \ + "ArmISA::TLB::AllowUnaligned", \ + "%d" % (size - 1)], [], base) def buildRegStore(mnem, post, add, writeback, \ size=4, sign=False, user=False): @@ -123,7 +126,10 @@ let {{ accCode += "Base = Base %s;\n" % offset base = buildMemBase("MemoryReg", post, writeback) - emitStore(name, Name, False, eaCode, accCode, [], [], base) + emitStore(name, Name, False, eaCode, accCode, \ + ["ArmISA::TLB::MustBeOne", \ + "ArmISA::TLB::AllowUnaligned", \ + "%d" % (size - 1)], [], base) def buildDoubleImmStore(mnem, post, add, writeback): name = mnem @@ -146,7 +152,8 @@ let {{ base = buildMemBase("MemoryDImm", post, writeback) emitStore(name, Name, True, eaCode, accCode, \ - [], [], base, double=True) + ["ArmISA::TLB::MustBeOne", + "ArmISA::TLB::AlignWord"], [], base, double=True) def buildDoubleRegStore(mnem, post, add, writeback): name = mnem @@ -170,7 +177,8 @@ let {{ base = buildMemBase("MemoryDReg", post, writeback) emitStore(name, Name, False, eaCode, accCode, \ - [], [], base, double=True) + ["ArmISA::TLB::MustBeOne", \ + "ArmISA::TLB::AlignWord"], [], base, double=True) def buildStores(mnem, size=4, sign=False, user=False): buildImmStore(mnem, True, True, True, size, sign, user) diff --git a/src/arch/arm/isa/insts/swap.isa b/src/arch/arm/isa/insts/swap.isa index 6cbca6d6c..9456c1314 100644 --- a/src/arch/arm/isa/insts/swap.isa +++ b/src/arch/arm/isa/insts/swap.isa @@ -45,7 +45,9 @@ let {{ newDecoder, newExec) = SwapBase("swp", "Swp", "EA = Base;", "Mem = Op1;", "Dest = memData;", - ["Request::MEM_SWAP"], []) + ["Request::MEM_SWAP", + "ArmISA::TLB::AlignWord", + "ArmISA::TLB::MustBeOne"], []) header_output += newHeader decoder_output += newDecoder exec_output += newExec @@ -54,7 +56,9 @@ let {{ newDecoder, newExec) = SwapBase("swpb", "Swpb", "EA = Base;", "Mem.ub = Op1.ub;", "Dest.ub = (uint8_t)memData;", - ["Request::MEM_SWAP"], []) + ["Request::MEM_SWAP", + "ArmISA::TLB::AlignByte", + "ArmISA::TLB::MustBeOne"], []) header_output += newHeader decoder_output += newDecoder exec_output += newExec diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc index 5ed77aea1..94f4019d6 100644 --- a/src/arch/arm/tlb.cc +++ b/src/arch/arm/tlb.cc @@ -291,6 +291,18 @@ Fault TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode) { Addr vaddr = req->getVaddr() & ~PcModeMask; + SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); + uint32_t flags = req->getFlags(); + + if (mode != Execute) { + assert(flags & MustBeOne); + + if (sctlr.a || (flags & AllowUnaligned) == 0) { + if ((vaddr & flags & AlignmentMask) != 0) { + return new DataAbort; + } + } + } #if !FULL_SYSTEM Process * p = tc->getProcessPtr(); @@ -301,7 +313,6 @@ TLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode) return NoFault; #else - SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR); if (!sctlr.m) { req->setPaddr(vaddr); return NoFault; diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh index d2c035b31..d6fe981b9 100644 --- a/src/arch/arm/tlb.hh +++ b/src/arch/arm/tlb.hh @@ -86,6 +86,21 @@ struct TlbEntry class TLB : public BaseTLB { + public: + enum ArmFlags { + AlignmentMask = 0x7, + + AlignByte = 0x0, + AlignHalfWord = 0x1, + AlignWord = 0x3, + AlignDoubleWord = 0x7, + + AllowUnaligned = 0x8, + // Because zero otherwise looks like a valid setting and may be used + // accidentally, this bit must be non-zero to show it was used on + // purpose. + MustBeOne = 0x10 + }; protected: typedef std::multimap PageTable; PageTable lookupTable; // Quick lookup into page table -- cgit v1.2.3