arm: Add support for memory-mapped m5ops
authorAndreas Sandberg <andreas.sandberg@arm.com>
Tue, 16 Feb 2016 19:21:04 +0000 (13:21 -0600)
committerAndreas Sandberg <andreas.sandberg@arm.com>
Tue, 9 May 2017 10:09:58 +0000 (10:09 +0000)
Add support for a memory mapped m5op interface. When enabled, the TLB
intercepts accesses in the 64KiB region designated by the
ArmTLB.m5ops_base parameter. An access to this range maps to a
specific m5op call. The upper 8 bits of the offset into the range
denote the m5op function to call and the lower 8 bits denote the
subfunction.

Change-Id: I55fd8ac1afef4c3cc423b973870c9fe600a843a2
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2964

src/arch/arm/ArmSystem.py
src/arch/arm/ArmTLB.py
src/arch/arm/system.cc
src/arch/arm/system.hh
src/arch/arm/tlb.cc
src/arch/arm/tlb.hh

index 41f6b9d79b127f066ec3312a68128305071a7b58..c21b9c6ecdddb43ff9579c32ac2d079a8e408b8f 100644 (file)
@@ -76,6 +76,10 @@ class ArmSystem(System):
     have_large_asid_64 = Param.Bool(False,
         "True if ASID is 16 bits in AArch64 (ARMv8)")
 
+    m5ops_base = Param.Addr(0,
+        "Base of the 64KiB PA range used for memory-mapped m5ops. Set to 0 "
+        "to disable.")
+
 class GenericArmSystem(ArmSystem):
     type = 'GenericArmSystem'
     cxx_header = "arch/arm/system.hh"
index 4e6c69f72a73561ef7351090bdd6810f530b0ebb..b3f711d831c9ff76e549194360d55675424d86f7 100644 (file)
@@ -63,6 +63,7 @@ class ArmTLB(SimObject):
     type = 'ArmTLB'
     cxx_class = 'ArmISA::TLB'
     cxx_header = "arch/arm/tlb.hh"
+    sys = Param.System(Parent.any, "system object parameter")
     size = Param.Int(64, "TLB size")
     walker = Param.ArmTableWalker(ArmTableWalker(), "HW Table walker")
     is_stage2 = Param.Bool(False, "Is this a stage 2 TLB?")
index 322f686dc55f0053ab0af844adc9a076b46ae9d4..50d0af9095662e3c64e2d3ae82eabb3d152d3dce 100644 (file)
@@ -65,6 +65,9 @@ ArmSystem::ArmSystem(Params *p)
       _resetAddr64(p->reset_addr_64),
       _physAddrRange64(p->phys_addr_range_64),
       _haveLargeAsid64(p->have_large_asid_64),
+      _m5opRange(p->m5ops_base ?
+                 RangeSize(p->m5ops_base, 0x10000) :
+                 AddrRange(1, 0)), // Create an empty range if disabled
       multiProc(p->multi_proc)
 {
     // Check if the physical address range is valid
index ee286d23a574eb76b0a0a688425c887d5d10e725..97769337a5ed572e52806d0f31363e716e3079e7 100644 (file)
@@ -116,6 +116,12 @@ class ArmSystem : public System
      */
     const bool _haveLargeAsid64;
 
+    /**
+     * Range for memory-mapped m5 pseudo ops. The range will be
+     * invalid/empty if disabled.
+     */
+    const AddrRange _m5opRange;
+
   protected:
     /**
      * Get a boot loader that matches the kernel.
@@ -216,6 +222,12 @@ class ArmSystem : public System
         return mask(physAddrRange());
     }
 
+    /**
+     * Range used by memory-mapped m5 pseudo-ops if enabled. Returns
+     * an invalid/empty range if disabled.
+     */
+    const AddrRange &m5opRange() const { return _m5opRange; }
+
     /** Returns true if the system of a specific thread context implements the
      * Security Extensions
      */
index eeccca0c08867388ef03a57da58e83b754001951..6f7998db2ececae1b2d1cde92058f08f7a1f96fe 100644 (file)
@@ -55,6 +55,7 @@
 #include "arch/arm/system.hh"
 #include "arch/arm/table_walker.hh"
 #include "arch/arm/utility.hh"
+#include "arch/generic/mmapped_ipr.hh"
 #include "base/inifile.hh"
 #include "base/str.hh"
 #include "base/trace.hh"
@@ -81,12 +82,17 @@ TLB::TLB(const ArmTLBParams *p)
       isHyp(false), asid(0), vmid(0), dacr(0),
       miscRegValid(false), miscRegContext(0), curTranType(NormalTran)
 {
+    const ArmSystem *sys = dynamic_cast<const ArmSystem *>(p->sys);
+
     tableWalker->setTlb(this);
 
     // Cache system-level properties
     haveLPAE = tableWalker->haveLPAE();
     haveVirtualization = tableWalker->haveVirtualization();
     haveLargeAsid64 = tableWalker->haveLargeAsid64();
+
+    if (sys)
+        m5opRange = sys->m5opRange();
 }
 
 TLB::~TLB()
@@ -129,6 +135,15 @@ TLB::translateFunctional(ThreadContext *tc, Addr va, Addr &pa)
 Fault
 TLB::finalizePhysical(RequestPtr req, ThreadContext *tc, Mode mode) const
 {
+    const Addr paddr = req->getPaddr();
+
+    if (m5opRange.contains(paddr)) {
+        req->setFlags(Request::MMAPPED_IPR | Request::GENERIC_IPR);
+        req->setPaddr(GenericISA::iprAddressPseudoInst(
+                          (paddr >> 8) & 0xFF,
+                          paddr & 0xFF));
+    }
+
     return NoFault;
 }
 
@@ -582,7 +597,7 @@ TLB::translateSe(RequestPtr req, ThreadContext *tc, Mode mode,
         return std::make_shared<GenericPageTableFault>(vaddr_tainted);
     req->setPaddr(paddr);
 
-    return NoFault;
+    return finalizePhysical(req, tc, mode);
 }
 
 Fault
@@ -1108,14 +1123,18 @@ TLB::translateFs(RequestPtr req, ThreadContext *tc, Mode mode,
             fault = testTranslation(req, mode, te->domain);
     }
 
-    // Generate Illegal Inst Set State fault if IL bit is set in CPSR
     if (fault == NoFault) {
+        // Generate Illegal Inst Set State fault if IL bit is set in CPSR
         if (aarch64 && is_fetch && cpsr.il == 1) {
             return std::make_shared<IllegalInstSetStateFault>();
         }
-    }
 
-    return fault;
+        // Don't try to finalize a physical address unless the
+        // translation has completed (i.e., there is a table entry).
+        return te ? finalizePhysical(req, tc, mode) : NoFault;
+    } else {
+        return fault;
+    }
 }
 
 Fault
index f4530a219dc91a42bcdb597b7bd725c5cf66cdec..f5849f3e39dc6ced3fc3a1d49e54f20830954f79 100644 (file)
@@ -393,6 +393,8 @@ protected:
     bool haveVirtualization;
     bool haveLargeAsid64;
 
+    AddrRange m5opRange;
+
     void updateMiscReg(ThreadContext *tc,
                        ArmTranslationType tranType = NormalTran);