arch-arm: Annotate original address in CMOs
authorGiacomo Travaglini <giacomo.travaglini@arm.com>
Wed, 9 Oct 2019 13:53:38 +0000 (14:53 +0100)
committerGiacomo Travaglini <giacomo.travaglini@arm.com>
Tue, 5 Nov 2019 16:31:57 +0000 (16:31 +0000)
This is needed when a CMO triggers an exception (e.g. DataAbort) In that
case the faulting address should be the one encoded in the instruction
rather than the cacheline address:

According to armarm:
If a memory fault that sets FAR_EL1 is generated from a data cache
maintenance or other DC instruction, FAR_EL1[63:0] holds the address
specified in the register argument of the instruction.

Change-Id: I6d0dadbef6e70db57438b01a76c5def3bdd2d974
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/22443
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
src/arch/arm/faults.cc
src/arch/arm/faults.hh
src/arch/arm/insts/mem64.hh
src/arch/arm/isa/insts/data64.isa

index b006d12ca62e301e9391b3ad1089ab196b9e4848..dbad5bf667d11ef2d619d7ec3acd62e9304956ec 100644 (file)
@@ -1418,6 +1418,9 @@ DataAbort::annotate(AnnotationIDs id, uint64_t val)
       case CM:
         cm  = val;
         break;
+      case OFA:
+        faultAddr  = val;
+        break;
       // Just ignore unknown ID's
       default:
         break;
index 645a461fe59ab0db0edb8a25c9e09da8087b22c8..3f61bc7221af72360b3923666fbb0b7e55796a28 100644 (file)
@@ -137,6 +137,10 @@ class ArmFault : public FaultBase
         SSE,   // DataAbort: Syndrome Sign Extend
         SRT,   // DataAbort: Syndrome Register Transfer
         CM,    // DataAbort: Cache Maintenance/Address Translation Op
+        OFA,   // DataAbort: Override fault Address. This is needed when
+               // the abort is triggered by a CMO. The faulting address is
+               // then the address specified in the register argument of the
+               // instruction and not the cacheline address (See FAR doc)
 
         // AArch64 only
         SF,    // DataAbort: width of the accessed register is SixtyFour
index 886c54f35b809773c7afc2bb78397367601e7bc4..25ef1484108e9897064b8d4e52e3bc30f9cf780a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2013,2017 ARM Limited
+ * Copyright (c) 2011-2013,2017-2019 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -52,10 +52,13 @@ class SysDC64 : public MiscRegOp64
     MiscRegIndex dest;
     uint64_t imm;
 
+    // This is used for fault handling only
+    mutable Addr faultAddr;
+
     SysDC64(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
             IntRegIndex _base, MiscRegIndex _dest, uint64_t _imm)
         : MiscRegOp64(mnem, _machInst, __opClass, false),
-          base(_base), dest(_dest), imm(_imm)
+          base(_base), dest(_dest), imm(_imm), faultAddr(0)
     {}
 
     std::string generateDisassembly(
index fcce0112a44f17d545bfbf7ed9e95f0cd537da2f..75d47925f801ba30c23aadec99b1f325518a2f8b 100644 (file)
@@ -412,9 +412,10 @@ let {{
 
     # Cache maintenance fault annotation
     # The DC ZVA instruction is not classified as a cache maintenance
-    # instruction, and therefore we shouldn't annotate it
+    # instruction, and therefore we shouldn't annotate it.
     cachem_fa = '''
         fault->annotate(ArmFault::CM, 1);
+        fault->annotate(ArmFault::OFA, faultAddr);
     '''
 
     msrdccvau_ea_code = msr_check_code
@@ -422,6 +423,7 @@ let {{
            Request::Flags memAccessFlags = Request::CLEAN | Request::DST_POU |
               ArmISA::TLB::MustBeOne;
            EA = XBase;
+           faultAddr = EA;
            System *sys = xc->tcBase()->getSystemPtr();
            Addr op_size = sys->cacheLineSize();
            EA &= ~(op_size - 1);
@@ -446,6 +448,7 @@ let {{
            Request::Flags memAccessFlags = Request::CLEAN | Request::DST_POC |
               ArmISA::TLB::MustBeOne;
            EA = XBase;
+           faultAddr = EA;
            System *sys = xc->tcBase()->getSystemPtr();
            Addr op_size = sys->cacheLineSize();
            EA &= ~(op_size - 1);
@@ -470,6 +473,7 @@ let {{
            Request::Flags memAccessFlags = Request::CLEAN |
               Request::INVALIDATE | Request::DST_POC | ArmISA::TLB::MustBeOne;
            EA = XBase;
+           faultAddr = EA;
            System *sys = xc->tcBase()->getSystemPtr();
            Addr op_size = sys->cacheLineSize();
            EA &= ~(op_size - 1);
@@ -494,6 +498,7 @@ let {{
            Request::Flags memAccessFlags = Request::INVALIDATE |
               Request::DST_POC | ArmISA::TLB::MustBeOne;
            EA = XBase;
+           faultAddr = EA;
            HCR hcr = Hcr64;
            SCR scr = Scr64;
            if (el == EL1 && ArmSystem::haveVirtualization(xc->tcBase()) &&