riscv: fix error on memory op address overflow
authorAlec Roelke <ar4jc@virginia.edu>
Tue, 21 Mar 2017 16:53:29 +0000 (12:53 -0400)
committerAlec Roelke <ar4jc@virginia.edu>
Wed, 5 Apr 2017 20:21:30 +0000 (20:21 +0000)
Previously, if a memory operation referenced an address that caused the
data to wrap around to the beginning of the memory (such as -1 or
0xFFFFFFFFFFFFFFFF), an assert would fail during address translation and
gem5 would crash.  This patch fixes that by checking for such a case in
RISC-V's TLB code and returning a fault from translateData if that would
happen.  Because RISC-V does support unaligned memory accesses, no
checking is performed to make sure that an access doesn't cross a cache
line.

[Update creation of page table fault to use make_shared.]
[Add comment explaining the change and assertion that the memory request
isn't zero size.]

Change-Id: I7b8ef9a5838f30184dbdbd0c7c1655e1c04a9410
Reviewed-on: https://gem5-review.googlesource.com/2345
Maintainer: Alec Roelke <ar4jc@virginia.edu>
Reviewed-by: Brandon Potter <Brandon.Potter@amd.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
src/arch/riscv/tlb.cc

index 841be2488ab55f9e4af00df2088f2c40984d671f..c47260e761f7fdd8065def9c9412da7c25ea1f32 100644 (file)
@@ -303,6 +303,17 @@ TLB::translateData(RequestPtr req, ThreadContext *tc, bool write)
     if (FullSystem)
         panic("translateData not implemented in RISC-V.\n");
 
+    // In the O3 CPU model, sometimes a memory access will be speculatively
+    // executed along a branch that will end up not being taken where the
+    // address is invalid.  In that case, return a fault rather than trying
+    // to translate it (which will cause a panic).  Since RISC-V allows
+    // unaligned memory accesses, this should only happen if the request's
+    // length is long enough to wrap around from the end of the memory to the
+    // start.
+    assert(req->getSize() > 0);
+    if (req->getVaddr() + req->getSize() - 1 < req->getVaddr())
+        return make_shared<GenericPageTableFault>(req->getVaddr());
+
     Process * p = tc->getProcessPtr();
 
     Fault fault = p->pTable->translate(req);