mem: Fix guest corruption when caches handle uncacheable accesses
[gem5.git] / src / mem / physical.cc
index b6f4c7a95298926fea1e59b0cf192e08a1f1cb54..df106d8cce7308cb07544db7f20c5e97861c0d3c 100644 (file)
@@ -119,9 +119,13 @@ void
 PhysicalMemory::createBackingStore(AddrRange range,
                                    const vector<AbstractMemory*>& _memories)
 {
+    if (range.interleaved())
+        panic("Cannot create backing store for interleaved range %s\n",
+              range.to_string());
+
     // perform the actual mmap
-    DPRINTF(BusAddrRanges, "Creating backing store for range %x:%x\n",
-            range.start, range.end);
+    DPRINTF(BusAddrRanges, "Creating backing store for range %s with size %d\n",
+            range.to_string(), range.size());
     int map_flags = MAP_ANON | MAP_PRIVATE;
     uint8_t* pmem = (uint8_t*) mmap(NULL, range.size(),
                                     PROT_READ | PROT_WRITE,
@@ -129,8 +133,8 @@ PhysicalMemory::createBackingStore(AddrRange range,
 
     if (pmem == (uint8_t*) MAP_FAILED) {
         perror("mmap");
-        fatal("Could not mmap %d bytes for range %x:%x!\n", range.size(),
-              range.start, range.end);
+        fatal("Could not mmap %d bytes for range %s!\n", range.size(),
+              range.to_string());
     }
 
     // remember this backing store so we can checkpoint it and unmap
@@ -157,8 +161,8 @@ PhysicalMemory::createBackingStore(AddrRange range,
 
     if (init_to_zero != 0) {
         if (init_to_zero != _memories.size())
-            fatal("Some, but not all memories in range %x:%x are set zero\n",
-                  range.start, range.end);
+            fatal("Some, but not all memories in range %s are set zero\n",
+                  range.to_string());
 
         memset(pmem, 0, range.size());
     }
@@ -176,7 +180,7 @@ bool
 PhysicalMemory::isMemAddr(Addr addr) const
 {
     // see if the address is within the last matched range
-    if (addr != rangeCache) {
+    if (!rangeCache.contains(addr)) {
         // lookup in the interval tree
         AddrRangeMap<AbstractMemory*>::const_iterator r = addrMap.find(addr);
         if (r == addrMap.end()) {
@@ -199,13 +203,34 @@ PhysicalMemory::getConfAddrRanges() const
     // this could be done once in the constructor, but since it is unlikely to
     // be called more than once the iteration should not be a problem
     AddrRangeList ranges;
-    for (vector<AbstractMemory*>::const_iterator m = memories.begin();
-         m != memories.end(); ++m) {
-        if ((*m)->isConfReported()) {
-            ranges.push_back((*m)->getAddrRange());
+    vector<AddrRange> intlv_ranges;
+    for (AddrRangeMap<AbstractMemory*>::const_iterator r = addrMap.begin();
+         r != addrMap.end(); ++r) {
+        if (r->second->isConfReported()) {
+            // if the range is interleaved then save it for now
+            if (r->first.interleaved()) {
+                // if we already got interleaved ranges that are not
+                // part of the same range, then first do a merge
+                // before we add the new one
+                if (!intlv_ranges.empty() &&
+                    !intlv_ranges.back().mergesWith(r->first)) {
+                    ranges.push_back(AddrRange(intlv_ranges));
+                    intlv_ranges.clear();
+                }
+                intlv_ranges.push_back(r->first);
+            } else {
+                // keep the current range
+                ranges.push_back(r->first);
+            }
         }
     }
 
+    // if there is still interleaved ranges waiting to be merged,
+    // go ahead and do it
+    if (!intlv_ranges.empty()) {
+        ranges.push_back(AddrRange(intlv_ranges));
+    }
+
     return ranges;
 }
 
@@ -325,7 +350,8 @@ PhysicalMemory::unserialize(Checkpoint* cp, const string& section)
     arrayParamIn(cp, section, "lal_addr", lal_addr);
     arrayParamIn(cp, section, "lal_cid", lal_cid);
     for(size_t i = 0; i < lal_addr.size(); ++i) {
-        AddrRangeMap<AbstractMemory*>::iterator m = addrMap.find(lal_addr[i]);
+        AddrRangeMap<AbstractMemory*>::const_iterator m =
+            addrMap.find(lal_addr[i]);
         m->second->addLockedAddr(LockedAddr(lal_addr[i], lal_cid[i]));
     }