Merge with the main repository again.
[gem5.git] / src / mem / physical.cc
index a49c12a5c7c9f138a445b89be14d6a8ee4587577..d5c4e892fb2467d78d573654bfd05486dcc28618 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2010 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2001-2005 The Regents of The University of Michigan
  * All rights reserved.
  *
  *          Ali Saidi
  */
 
-#include <sys/types.h>
 #include <sys/mman.h>
-#include <errno.h>
+#include <sys/types.h>
+#include <sys/user.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <zlib.h>
 
+#include <cerrno>
+#include <cstdio>
 #include <iostream>
 #include <string>
 
 #include "arch/isa_traits.hh"
+#include "arch/registers.hh"
+#include "base/intmath.hh"
 #include "base/misc.hh"
 #include "base/random.hh"
 #include "base/types.hh"
-#include "config/full_system.hh"
+#include "config/the_isa.hh"
+#include "debug/LLSC.hh"
+#include "debug/MemoryAccess.hh"
 #include "mem/packet_access.hh"
 #include "mem/physical.hh"
 #include "sim/eventq.hh"
@@ -52,28 +70,40 @@ using namespace std;
 using namespace TheISA;
 
 PhysicalMemory::PhysicalMemory(const Params *p)
-    : MemObject(p), pmemAddr(NULL), pagePtr(0),
-      lat(p->latency), lat_var(p->latency_var),
-      cachedSize(params()->range.size()), cachedStart(params()->range.start)
+    : MemObject(p), pmemAddr(NULL), lat(p->latency), lat_var(p->latency_var),
+      _size(params()->range.size()), _start(params()->range.start)
 {
-    if (params()->range.size() % TheISA::PageBytes != 0)
+    if (size() % TheISA::PageBytes != 0)
         panic("Memory Size not divisible by page size\n");
 
     if (params()->null)
         return;
 
-    int map_flags = MAP_ANON | MAP_PRIVATE;
-    pmemAddr = (uint8_t *)mmap(NULL, params()->range.size(),
-                               PROT_READ | PROT_WRITE, map_flags, -1, 0);
+
+    if (params()->file == "") {
+        int map_flags = MAP_ANON | MAP_PRIVATE;
+        pmemAddr = (uint8_t *)mmap(NULL, size(),
+                                   PROT_READ | PROT_WRITE, map_flags, -1, 0);
+    } else {
+        int map_flags = MAP_PRIVATE;
+        int fd = open(params()->file.c_str(), O_RDONLY);
+        _size = lseek(fd, 0, SEEK_END);
+        lseek(fd, 0, SEEK_SET);
+        pmemAddr = (uint8_t *)mmap(NULL, roundUp(size(), sysconf(_SC_PAGESIZE)),
+                                   PROT_READ | PROT_WRITE, map_flags, fd, 0);
+    }
 
     if (pmemAddr == (void *)MAP_FAILED) {
         perror("mmap");
-        fatal("Could not mmap!\n");
+        if (params()->file == "")
+            fatal("Could not mmap!\n");
+        else
+            fatal("Could not find file: %s\n", params()->file);
     }
 
     //If requested, initialize all the memory to 0
     if (p->zero)
-        memset(pmemAddr, 0, p->range.size());
+        memset(pmemAddr, 0, size());
 }
 
 void
@@ -92,22 +122,11 @@ PhysicalMemory::init()
 PhysicalMemory::~PhysicalMemory()
 {
     if (pmemAddr)
-        munmap((char*)pmemAddr, params()->range.size());
-    //Remove memPorts?
-}
-
-Addr
-PhysicalMemory::new_page()
-{
-    Addr return_addr = pagePtr << LogVMPageSize;
-    return_addr += start();
-
-    ++pagePtr;
-    return return_addr;
+        munmap((char*)pmemAddr, size());
 }
 
-int
-PhysicalMemory::deviceBlockSize()
+unsigned
+PhysicalMemory::deviceBlockSize() const
 {
     //Can accept anysize request
     return 0;
@@ -211,8 +230,8 @@ PhysicalMemory::checkLockedAddrList(PacketPtr pkt)
 
 #define CASE(A, T)                                                      \
   case sizeof(T):                                                       \
-    DPRINTF(MemoryAccess, A " of size %i on address 0x%x data 0x%x\n",  \
-            pkt->getSize(), pkt->getAddr(), pkt->get<T>());             \
+    DPRINTF(MemoryAccess,"%s of size %i on address 0x%x data 0x%x\n",   \
+            A, pkt->getSize(), pkt->getAddr(), pkt->get<T>());          \
   break
 
 
@@ -224,8 +243,9 @@ PhysicalMemory::checkLockedAddrList(PacketPtr pkt)
           CASE(A, uint16_t);                                            \
           CASE(A, uint8_t);                                             \
           default:                                                      \
-            DPRINTF(MemoryAccess, A " of size %i on address 0x%x\n",    \
-                    pkt->getSize(), pkt->getAddr());                    \
+            DPRINTF(MemoryAccess, "%s of size %i on address 0x%x\n",    \
+                    A, pkt->getSize(), pkt->getAddr());                 \
+            DDUMP(MemoryAccess, pkt->getPtr<uint8_t>(), pkt->getSize());\
         }                                                               \
     } while (0)
 
@@ -281,6 +301,7 @@ PhysicalMemory::doAtomicAccess(PacketPtr pkt)
         if (overwrite_mem)
             std::memcpy(hostAddr, &overwrite_val, pkt->getSize());
 
+        assert(!pkt->req->isInstFetch());
         TRACE_PACKET("Read/Write");
     } else if (pkt->isRead()) {
         assert(!pkt->isWrite());
@@ -289,11 +310,12 @@ PhysicalMemory::doAtomicAccess(PacketPtr pkt)
         }
         if (pmemAddr)
             memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
-        TRACE_PACKET("Read");
+        TRACE_PACKET(pkt->req->isInstFetch() ? "IFetch" : "Read");
     } else if (pkt->isWrite()) {
         if (writeOK(pkt)) {
             if (pmemAddr)
                 memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
+            assert(!pkt->req->isInstFetch());
             TRACE_PACKET("Write");
         }
     } else if (pkt->isInvalidate()) {
@@ -360,8 +382,8 @@ PhysicalMemory::getPort(const std::string &if_name, int idx)
         panic("PhysicalMemory::getPort: unknown port %s requested", if_name);
     }
 
-    if (idx >= ports.size()) {
-        ports.resize(idx+1);
+    if (idx >= (int)ports.size()) {
+        ports.resize(idx + 1);
     }
 
     if (ports[idx] != NULL) {
@@ -404,11 +426,11 @@ PhysicalMemory::getAddressRanges(AddrRangeList &resp, bool &snoop)
 {
     snoop = false;
     resp.clear();
-    resp.push_back(RangeSize(start(), params()->range.size()));
+    resp.push_back(RangeSize(start(), size()));
 }
 
-int
-PhysicalMemory::MemoryPort::deviceBlockSize()
+unsigned
+PhysicalMemory::MemoryPort::deviceBlockSize() const
 {
     return memory->deviceBlockSize();
 }
@@ -459,6 +481,7 @@ PhysicalMemory::serialize(ostream &os)
     string filename = name() + ".physmem";
 
     SERIALIZE_SCALAR(filename);
+    SERIALIZE_SCALAR(_size);
 
     // write memory file
     string thefile = Checkpoint::dir() + "/" + filename.c_str();
@@ -473,8 +496,7 @@ PhysicalMemory::serialize(ostream &os)
         fatal("Insufficient memory to allocate compression state for %s\n",
                 filename);
 
-    if (gzwrite(compressedMem, pmemAddr, params()->range.size()) !=
-        params()->range.size()) {
+    if (gzwrite(compressedMem, pmemAddr, size()) != (int)size()) {
         fatal("Write failed on physical memory checkpoint file '%s'\n",
               filename);
     }
@@ -482,6 +504,18 @@ PhysicalMemory::serialize(ostream &os)
     if (gzclose(compressedMem))
         fatal("Close failed on physical memory checkpoint file '%s'\n",
               filename);
+
+    list<LockedAddr>::iterator i = lockedAddrList.begin();
+
+    vector<Addr> lal_addr;
+    vector<int> lal_cid;
+    while (i != lockedAddrList.end()) {
+        lal_addr.push_back(i->addr);
+        lal_cid.push_back(i->contextId);
+        i++;
+    }
+    arrayParamOut(os, "lal_addr", lal_addr);
+    arrayParamOut(os, "lal_cid", lal_cid);
 }
 
 void
@@ -495,7 +529,7 @@ PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
     long *pmem_current;
     uint64_t curSize;
     uint32_t bytesRead;
-    const int chunkSize = 16384;
+    const uint32_t chunkSize = 16384;
 
     string filename;
 
@@ -515,12 +549,17 @@ PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
         fatal("Insufficient memory to allocate compression state for %s\n",
                 filename);
 
-    // unmap file that was mmaped in the constructor
+    // unmap file that was mmapped in the constructor
     // This is done here to make sure that gzip and open don't muck with our
     // nice large space of memory before we reallocate it
-    munmap((char*)pmemAddr, params()->range.size());
+    munmap((char*)pmemAddr, size());
+
+    UNSERIALIZE_SCALAR(_size);
+    if (size() > params()->range.size())
+        fatal("Memory size has changed! size %lld, param size %lld\n",
+              size(), params()->range.size());
 
-    pmemAddr = (uint8_t *)mmap(NULL, params()->range.size(),
+    pmemAddr = (uint8_t *)mmap(NULL, size(),
         PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
 
     if (pmemAddr == (void *)MAP_FAILED) {
@@ -534,18 +573,14 @@ PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
         fatal("Unable to malloc memory to read file %s\n", filename);
 
     /* Only copy bytes that are non-zero, so we don't give the VM system hell */
-    while (curSize < params()->range.size()) {
+    while (curSize < size()) {
         bytesRead = gzread(compressedMem, tempPage, chunkSize);
-        if (bytesRead != chunkSize &&
-            bytesRead != params()->range.size() - curSize)
-            fatal("Read failed on physical memory checkpoint file '%s'"
-                  " got %d bytes, expected %d or %d bytes\n",
-                  filename, bytesRead, chunkSize,
-                  params()->range.size() - curSize);
+        if (bytesRead == 0)
+            break;
 
         assert(bytesRead % sizeof(long) == 0);
 
-        for (int x = 0; x < bytesRead/sizeof(long); x++)
+        for (uint32_t x = 0; x < bytesRead / sizeof(long); x++)
         {
              if (*(tempPage+x) != 0) {
                  pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long));
@@ -561,6 +596,12 @@ PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
         fatal("Close failed on physical memory checkpoint file '%s'\n",
               filename);
 
+    vector<Addr> lal_addr;
+    vector<int> lal_cid;
+    arrayParamIn(cp, section, "lal_addr", lal_addr);
+    arrayParamIn(cp, section, "lal_cid", lal_cid);
+    for(int i = 0; i < lal_addr.size(); i++)
+        lockedAddrList.push_front(LockedAddr(lal_addr[i], lal_cid[i]));
 }
 
 PhysicalMemory *