abstract_mem.cc revision 3170
17404SAli.Saidi@ARM.com/*
212709Sgiacomo.travaglini@arm.com * Copyright (c) 2001-2005 The Regents of The University of Michigan
37404SAli.Saidi@ARM.com * All rights reserved.
47404SAli.Saidi@ARM.com *
57404SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
67404SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
77404SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright
87404SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer;
97404SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright
107404SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the
117404SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution;
127404SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its
137404SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from
147404SAli.Saidi@ARM.com * this software without specific prior written permission.
157404SAli.Saidi@ARM.com *
167404SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177404SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187404SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197404SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207404SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
217404SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227404SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237404SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247404SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
257404SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
267404SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
277404SAli.Saidi@ARM.com *
287404SAli.Saidi@ARM.com * Authors: Ron Dreslinski
297404SAli.Saidi@ARM.com *          Ali Saidi
307404SAli.Saidi@ARM.com */
317404SAli.Saidi@ARM.com
327404SAli.Saidi@ARM.com#include <sys/types.h>
337404SAli.Saidi@ARM.com#include <sys/mman.h>
347404SAli.Saidi@ARM.com#include <errno.h>
357404SAli.Saidi@ARM.com#include <fcntl.h>
367404SAli.Saidi@ARM.com#include <unistd.h>
377404SAli.Saidi@ARM.com#include <zlib.h>
3810037SARM gem5 Developers
397404SAli.Saidi@ARM.com#include <iostream>
4010873Sandreas.sandberg@arm.com#include <string>
417404SAli.Saidi@ARM.com
4210474Sandreas.hansson@arm.com
4310474Sandreas.hansson@arm.com#include "base/misc.hh"
447404SAli.Saidi@ARM.com#include "config/full_system.hh"
4510037SARM gem5 Developers#include "mem/packet_impl.hh"
4610037SARM gem5 Developers#include "mem/physical.hh"
477404SAli.Saidi@ARM.com#include "sim/host.hh"
487728SAli.Saidi@ARM.com#include "sim/builder.hh"
497404SAli.Saidi@ARM.com#include "sim/eventq.hh"
508245Snate@binkert.org#include "arch/isa_traits.hh"
519152Satgutier@umich.edu
528245Snate@binkert.org
538245Snate@binkert.orgusing namespace std;
5410873Sandreas.sandberg@arm.comusing namespace TheISA;
557748SAli.Saidi@ARM.com
567404SAli.Saidi@ARM.com
577404SAli.Saidi@ARM.comPhysicalMemory::PhysicalMemory(Params *p)
587404SAli.Saidi@ARM.com    : MemObject(p->name), pmemAddr(NULL), port(NULL), lat(p->latency), _params(p)
597404SAli.Saidi@ARM.com{
6013892Sgabeblack@google.com    if (params()->addrRange.size() % TheISA::PageBytes != 0)
6110717Sandreas.hansson@arm.com        panic("Memory Size not divisible by page size\n");
6210717Sandreas.hansson@arm.com
6310717Sandreas.hansson@arm.com    int map_flags = MAP_ANON | MAP_PRIVATE;
649258SAli.Saidi@ARM.com    pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE,
6510621SCurtis.Dunham@arm.com                                map_flags, -1, 0);
6610621SCurtis.Dunham@arm.com
6712086Sspwilson2@wisc.edu    if (pmemAddr == (void *)MAP_FAILED) {
6812086Sspwilson2@wisc.edu        perror("mmap");
6912086Sspwilson2@wisc.edu        fatal("Could not mmap!\n");
7012086Sspwilson2@wisc.edu    }
7112086Sspwilson2@wisc.edu
7212086Sspwilson2@wisc.edu    pagePtr = 0;
7311588SCurtis.Dunham@arm.com}
7411588SCurtis.Dunham@arm.com
7512086Sspwilson2@wisc.eduvoid
767439Sdam.sunwoo@arm.comPhysicalMemory::init()
777576SAli.Saidi@ARM.com{
7810037SARM gem5 Developers    if (!port)
7910037SARM gem5 Developers        panic("PhysicalMemory not connected to anything!");
8010037SARM gem5 Developers    port->sendStatusChange(Port::RangeChange);
8110717Sandreas.hansson@arm.com}
8210037SARM gem5 Developers
8310037SARM gem5 DevelopersPhysicalMemory::~PhysicalMemory()
8410037SARM gem5 Developers{
8510037SARM gem5 Developers    if (pmemAddr)
8610037SARM gem5 Developers        munmap(pmemAddr, params()->addrRange.size());
8710037SARM gem5 Developers    //Remove memPorts?
8810037SARM gem5 Developers}
8910037SARM gem5 Developers
9010037SARM gem5 DevelopersAddr
9110037SARM gem5 DevelopersPhysicalMemory::new_page()
9210037SARM gem5 Developers{
9310037SARM gem5 Developers    Addr return_addr = pagePtr << LogVMPageSize;
947439Sdam.sunwoo@arm.com    return_addr += params()->addrRange.start;
957404SAli.Saidi@ARM.com
967404SAli.Saidi@ARM.com    ++pagePtr;
977404SAli.Saidi@ARM.com    return return_addr;
987404SAli.Saidi@ARM.com}
997404SAli.Saidi@ARM.com
1007404SAli.Saidi@ARM.comint
10110717Sandreas.hansson@arm.comPhysicalMemory::deviceBlockSize()
10210717Sandreas.hansson@arm.com{
10310717Sandreas.hansson@arm.com    //Can accept anysize request
10410717Sandreas.hansson@arm.com    return 0;
10513795SAndrea.Mondelli@ucf.edu}
10610717Sandreas.hansson@arm.com
10710717Sandreas.hansson@arm.comTick
10810717Sandreas.hansson@arm.comPhysicalMemory::calculateLatency(Packet *pkt)
10910717Sandreas.hansson@arm.com{
11010717Sandreas.hansson@arm.com    return lat;
11110717Sandreas.hansson@arm.com}
11210717Sandreas.hansson@arm.com
11310717Sandreas.hansson@arm.com
11410717Sandreas.hansson@arm.com
11510717Sandreas.hansson@arm.com// Add load-locked to tracking list.  Should only be called if the
11610717Sandreas.hansson@arm.com// operation is a load and the LOCKED flag is set.
11713784Sgabeblack@google.comvoid
11813784Sgabeblack@google.comPhysicalMemory::trackLoadLocked(Request *req)
11910717Sandreas.hansson@arm.com{
12010717Sandreas.hansson@arm.com    Addr paddr = LockedAddr::mask(req->getPaddr());
12110717Sandreas.hansson@arm.com
12210717Sandreas.hansson@arm.com    // first we check if we already have a locked addr for this
12310717Sandreas.hansson@arm.com    // xc.  Since each xc only gets one, we just update the
12410717Sandreas.hansson@arm.com    // existing record with the new address.
12510717Sandreas.hansson@arm.com    list<LockedAddr>::iterator i;
12610717Sandreas.hansson@arm.com
12713892Sgabeblack@google.com    for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) {
12810717Sandreas.hansson@arm.com        if (i->matchesContext(req)) {
12910717Sandreas.hansson@arm.com            DPRINTF(LLSC, "Modifying lock record: cpu %d thread %d addr %#x\n",
13010537Sandreas.hansson@arm.com                    req->getCpuNum(), req->getThreadNum(), paddr);
13110537Sandreas.hansson@arm.com            i->addr = paddr;
13210537Sandreas.hansson@arm.com            return;
13314040Sgiacomo.travaglini@arm.com        }
13414040Sgiacomo.travaglini@arm.com    }
13514040Sgiacomo.travaglini@arm.com
13614040Sgiacomo.travaglini@arm.com    // no record for this xc: need to allocate a new one
13710537Sandreas.hansson@arm.com    DPRINTF(LLSC, "Adding lock record: cpu %d thread %d addr %#x\n",
13812738Sandreas.sandberg@arm.com            req->getCpuNum(), req->getThreadNum(), paddr);
13910537Sandreas.hansson@arm.com    lockedAddrList.push_front(LockedAddr(req));
14010537Sandreas.hansson@arm.com}
14110537Sandreas.hansson@arm.com
14210037SARM gem5 Developers
14310037SARM gem5 Developers// Called on *writes* only... both regular stores and
14410037SARM gem5 Developers// store-conditional operations.  Check for conventional stores which
1459152Satgutier@umich.edu// conflict with locked addresses, and for success/failure of store
1469152Satgutier@umich.edu// conditionals.
1479152Satgutier@umich.edubool
14810913Sandreas.sandberg@arm.comPhysicalMemory::checkLockedAddrList(Request *req)
14911588SCurtis.Dunham@arm.com{
15011588SCurtis.Dunham@arm.com    Addr paddr = LockedAddr::mask(req->getPaddr());
1519152Satgutier@umich.edu    bool isLocked = req->isLocked();
15210913Sandreas.sandberg@arm.com
1539152Satgutier@umich.edu    // Initialize return value.  Non-conditional stores always
15410913Sandreas.sandberg@arm.com    // succeed.  Assume conditional stores will fail until proven
1559152Satgutier@umich.edu    // otherwise.
1569152Satgutier@umich.edu    bool success = !isLocked;
1579152Satgutier@umich.edu
15810913Sandreas.sandberg@arm.com    // Iterate over list.  Note that there could be multiple matching
15910913Sandreas.sandberg@arm.com    // records, as more than one context could have done a load locked
1607404SAli.Saidi@ARM.com    // to this location.
16110037SARM gem5 Developers    list<LockedAddr>::iterator i = lockedAddrList.begin();
1629152Satgutier@umich.edu
16310037SARM gem5 Developers    while (i != lockedAddrList.end()) {
16410037SARM gem5 Developers
16510037SARM gem5 Developers        if (i->addr == paddr) {
16610037SARM gem5 Developers            // we have a matching address
16710037SARM gem5 Developers
16810037SARM gem5 Developers            if (isLocked && i->matchesContext(req)) {
16910037SARM gem5 Developers                // it's a store conditional, and as far as the memory
17010037SARM gem5 Developers                // system can tell, the requesting context's lock is
1719152Satgutier@umich.edu                // still valid.
17210913Sandreas.sandberg@arm.com                DPRINTF(LLSC, "StCond success: cpu %d thread %d addr %#x\n",
17310037SARM gem5 Developers                        req->getCpuNum(), req->getThreadNum(), paddr);
17410037SARM gem5 Developers                success = true;
17510913Sandreas.sandberg@arm.com            }
1767733SAli.Saidi@ARM.com
1777404SAli.Saidi@ARM.com            // Get rid of our record of this lock and advance to next
1787404SAli.Saidi@ARM.com            DPRINTF(LLSC, "Erasing lock record: cpu %d thread %d addr %#x\n",
1797748SAli.Saidi@ARM.com                    i->cpuNum, i->threadNum, paddr);
1809342SAndreas.Sandberg@arm.com            i = lockedAddrList.erase(i);
1817748SAli.Saidi@ARM.com        }
1829524SAndreas.Sandberg@ARM.com        else {
1839152Satgutier@umich.edu            // no match: advance to next record
1849152Satgutier@umich.edu            ++i;
18510621SCurtis.Dunham@arm.com        }
1867748SAli.Saidi@ARM.com    }
1877748SAli.Saidi@ARM.com
1887748SAli.Saidi@ARM.com    if (isLocked) {
1897404SAli.Saidi@ARM.com        req->setScResult(success ? 1 : 0);
19012749Sgiacomo.travaglini@arm.com    }
19110037SARM gem5 Developers
19210037SARM gem5 Developers    return success;
19311580SDylan.Johnson@ARM.com}
19411580SDylan.Johnson@ARM.com
1957404SAli.Saidi@ARM.comvoid
1968733Sgeoffrey.blake@arm.comPhysicalMemory::doFunctionalAccess(Packet *pkt)
19710621SCurtis.Dunham@arm.com{
19810621SCurtis.Dunham@arm.com    assert(pkt->getAddr() + pkt->getSize() < params()->addrRange.size());
19910109SGeoffrey.Blake@arm.com
20010037SARM gem5 Developers    switch (pkt->cmd) {
20110109SGeoffrey.Blake@arm.com      case Packet::ReadReq:
2027439Sdam.sunwoo@arm.com        if (pkt->req->isLocked()) {
2037439Sdam.sunwoo@arm.com            trackLoadLocked(pkt->req);
2047439Sdam.sunwoo@arm.com        }
2057439Sdam.sunwoo@arm.com        memcpy(pkt->getPtr<uint8_t>(),
2067404SAli.Saidi@ARM.com               pmemAddr + pkt->getAddr() - params()->addrRange.start,
2077439Sdam.sunwoo@arm.com               pkt->getSize());
2087439Sdam.sunwoo@arm.com        break;
20910109SGeoffrey.Blake@arm.com      case Packet::WriteReq:
21010109SGeoffrey.Blake@arm.com        if (writeOK(pkt->req)) {
21110109SGeoffrey.Blake@arm.com            memcpy(pmemAddr + pkt->getAddr() - params()->addrRange.start,
21210109SGeoffrey.Blake@arm.com                   pkt->getPtr<uint8_t>(), pkt->getSize());
21310109SGeoffrey.Blake@arm.com        }
21410109SGeoffrey.Blake@arm.com        break;
21510109SGeoffrey.Blake@arm.com      default:
21610109SGeoffrey.Blake@arm.com        panic("unimplemented");
2178202SAli.Saidi@ARM.com    }
2188202SAli.Saidi@ARM.com
2198202SAli.Saidi@ARM.com    pkt->result = Packet::Success;
2208202SAli.Saidi@ARM.com}
2218202SAli.Saidi@ARM.com
2228202SAli.Saidi@ARM.comPort *
2238202SAli.Saidi@ARM.comPhysicalMemory::getPort(const std::string &if_name, int idx)
22410037SARM gem5 Developers{
22510621SCurtis.Dunham@arm.com    if (if_name == "port" && idx == -1) {
22610474Sandreas.hansson@arm.com        if (port != NULL)
2278202SAli.Saidi@ARM.com           panic("PhysicalMemory::getPort: additional port requested to memory!");
2287439Sdam.sunwoo@arm.com        port = new MemoryPort(name() + "-port", this);
22910621SCurtis.Dunham@arm.com        return port;
2307439Sdam.sunwoo@arm.com    } else if (if_name == "functional") {
23110621SCurtis.Dunham@arm.com        /* special port for functional writes at startup. */
2327439Sdam.sunwoo@arm.com        return new MemoryPort(name() + "-funcport", this);
23311517SCurtis.Dunham@arm.com    } else {
23411517SCurtis.Dunham@arm.com        panic("PhysicalMemory::getPort: unknown port %s requested", if_name);
23511517SCurtis.Dunham@arm.com    }
23612735Sandreas.sandberg@arm.com}
23712735Sandreas.sandberg@arm.com
23812735Sandreas.sandberg@arm.comvoid
23912735Sandreas.sandberg@arm.comPhysicalMemory::recvStatusChange(Port::Status status)
24012735Sandreas.sandberg@arm.com{
24112735Sandreas.sandberg@arm.com}
24212735Sandreas.sandberg@arm.com
24312735Sandreas.sandberg@arm.comPhysicalMemory::MemoryPort::MemoryPort(const std::string &_name,
24412735Sandreas.sandberg@arm.com                                       PhysicalMemory *_memory)
2457439Sdam.sunwoo@arm.com    : SimpleTimingPort(_name), memory(_memory)
2467439Sdam.sunwoo@arm.com{ }
2477439Sdam.sunwoo@arm.com
24810037SARM gem5 Developersvoid
24910037SARM gem5 DevelopersPhysicalMemory::MemoryPort::recvStatusChange(Port::Status status)
25010037SARM gem5 Developers{
2517439Sdam.sunwoo@arm.com    memory->recvStatusChange(status);
2528733Sgeoffrey.blake@arm.com}
2537439Sdam.sunwoo@arm.com
25410037SARM gem5 Developersvoid
25510037SARM gem5 DevelopersPhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp,
25610037SARM gem5 Developers                                            AddrRangeList &snoop)
2577404SAli.Saidi@ARM.com{
2587436Sdam.sunwoo@arm.com    memory->getAddressRanges(resp, snoop);
2597436Sdam.sunwoo@arm.com}
26010037SARM gem5 Developers
26110037SARM gem5 Developersvoid
26210037SARM gem5 DevelopersPhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
26310037SARM gem5 Developers{
26410037SARM gem5 Developers    snoop.clear();
26510037SARM gem5 Developers    resp.clear();
26610037SARM gem5 Developers    resp.push_back(RangeSize(params()->addrRange.start,
26710037SARM gem5 Developers                             params()->addrRange.size()));
26811575SDylan.Johnson@ARM.com}
26911575SDylan.Johnson@ARM.com
27011575SDylan.Johnson@ARM.comint
27111575SDylan.Johnson@ARM.comPhysicalMemory::MemoryPort::deviceBlockSize()
27210037SARM gem5 Developers{
27310037SARM gem5 Developers    return memory->deviceBlockSize();
27410037SARM gem5 Developers}
27510324SCurtis.Dunham@arm.com
27610037SARM gem5 DevelopersTick
27711574SCurtis.Dunham@arm.comPhysicalMemory::MemoryPort::recvAtomic(Packet *pkt)
27811574SCurtis.Dunham@arm.com{
27911574SCurtis.Dunham@arm.com    memory->doFunctionalAccess(pkt);
28011574SCurtis.Dunham@arm.com    return memory->calculateLatency(pkt);
28111574SCurtis.Dunham@arm.com}
28210037SARM gem5 Developers
28310037SARM gem5 Developersvoid
28410037SARM gem5 DevelopersPhysicalMemory::MemoryPort::recvFunctional(Packet *pkt)
28510324SCurtis.Dunham@arm.com{
28610037SARM gem5 Developers    // Default implementation of SimpleTimingPort::recvFunctional()
28710037SARM gem5 Developers    // calls recvAtomic() and throws away the latency; we can save a
28810037SARM gem5 Developers    // little here by just not calculating the latency.
28910037SARM gem5 Developers    memory->doFunctionalAccess(pkt);
29010037SARM gem5 Developers}
29111575SDylan.Johnson@ARM.com
29210037SARM gem5 Developersunsigned int
29312499Sgiacomo.travaglini@arm.comPhysicalMemory::drain(Event *de)
29410037SARM gem5 Developers{
29512499Sgiacomo.travaglini@arm.com    int count = port->drain(de);
29610037SARM gem5 Developers    if (count)
29710037SARM gem5 Developers        changeState(Draining);
29810037SARM gem5 Developers    else
29910037SARM gem5 Developers        changeState(Drained);
30010037SARM gem5 Developers    return count;
3017439Sdam.sunwoo@arm.com}
3027439Sdam.sunwoo@arm.com
3037439Sdam.sunwoo@arm.comvoid
3047439Sdam.sunwoo@arm.comPhysicalMemory::serialize(ostream &os)
3057439Sdam.sunwoo@arm.com{
30610621SCurtis.Dunham@arm.com    gzFile compressedMem;
30710621SCurtis.Dunham@arm.com    string filename = name() + ".physmem";
30811580SDylan.Johnson@ARM.com
3097728SAli.Saidi@ARM.com    SERIALIZE_SCALAR(filename);
31011517SCurtis.Dunham@arm.com
31111517SCurtis.Dunham@arm.com    // write memory file
31210037SARM gem5 Developers    string thefile = Checkpoint::dir() + "/" + filename.c_str();
31310037SARM gem5 Developers    int fd = creat(thefile.c_str(), 0664);
31410037SARM gem5 Developers    if (fd < 0) {
31510037SARM gem5 Developers        perror("creat");
31610037SARM gem5 Developers        fatal("Can't open physical memory checkpoint file '%s'\n", filename);
31710037SARM gem5 Developers    }
31810037SARM gem5 Developers
31910037SARM gem5 Developers    compressedMem = gzdopen(fd, "wb");
32010621SCurtis.Dunham@arm.com    if (compressedMem == NULL)
32110621SCurtis.Dunham@arm.com        fatal("Insufficient memory to allocate compression state for %s\n",
32210621SCurtis.Dunham@arm.com                filename);
32310621SCurtis.Dunham@arm.com
32410037SARM gem5 Developers    if (gzwrite(compressedMem, pmemAddr, params()->addrRange.size()) != params()->addrRange.size()) {
32510037SARM gem5 Developers        fatal("Write failed on physical memory checkpoint file '%s'\n",
32610037SARM gem5 Developers              filename);
32710109SGeoffrey.Blake@arm.com    }
32810037SARM gem5 Developers
32910109SGeoffrey.Blake@arm.com    if (gzclose(compressedMem))
33010037SARM gem5 Developers        fatal("Close failed on physical memory checkpoint file '%s'\n",
33110109SGeoffrey.Blake@arm.com              filename);
33210037SARM gem5 Developers}
33310109SGeoffrey.Blake@arm.com
33410109SGeoffrey.Blake@arm.comvoid
33510109SGeoffrey.Blake@arm.comPhysicalMemory::unserialize(Checkpoint *cp, const string &section)
33610109SGeoffrey.Blake@arm.com{
33710109SGeoffrey.Blake@arm.com    gzFile compressedMem;
33810109SGeoffrey.Blake@arm.com    long *tempPage;
33910109SGeoffrey.Blake@arm.com    long *pmem_current;
34010109SGeoffrey.Blake@arm.com    uint64_t curSize;
34110109SGeoffrey.Blake@arm.com    uint32_t bytesRead;
34210037SARM gem5 Developers    const int chunkSize = 16384;
3437728SAli.Saidi@ARM.com
3448067SAli.Saidi@ARM.com
3457728SAli.Saidi@ARM.com    string filename;
3467728SAli.Saidi@ARM.com
34710621SCurtis.Dunham@arm.com    UNSERIALIZE_SCALAR(filename);
3487728SAli.Saidi@ARM.com
3497728SAli.Saidi@ARM.com    filename = cp->cptDir + "/" + filename;
35010621SCurtis.Dunham@arm.com
35110037SARM gem5 Developers    // mmap memoryfile
35210037SARM gem5 Developers    int fd = open(filename.c_str(), O_RDONLY);
35310037SARM gem5 Developers    if (fd < 0) {
35410037SARM gem5 Developers        perror("open");
35510037SARM gem5 Developers        fatal("Can't open physical memory checkpoint file '%s'", filename);
35610037SARM gem5 Developers    }
3577728SAli.Saidi@ARM.com
3587728SAli.Saidi@ARM.com    compressedMem = gzdopen(fd, "rb");
3597728SAli.Saidi@ARM.com    if (compressedMem == NULL)
3607728SAli.Saidi@ARM.com        fatal("Insufficient memory to allocate compression state for %s\n",
3617728SAli.Saidi@ARM.com                filename);
3627728SAli.Saidi@ARM.com
3637728SAli.Saidi@ARM.com    // unmap file that was mmaped in the constructor
3647728SAli.Saidi@ARM.com    // This is done here to make sure that gzip and open don't muck with our
3657728SAli.Saidi@ARM.com    // nice large space of memory before we reallocate it
3667728SAli.Saidi@ARM.com    munmap(pmemAddr, params()->addrRange.size());
36710621SCurtis.Dunham@arm.com
3687728SAli.Saidi@ARM.com    pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE,
3699258SAli.Saidi@ARM.com                                MAP_ANON | MAP_PRIVATE, -1, 0);
3709535Smrinmoy.ghosh@arm.com
37110037SARM gem5 Developers    if (pmemAddr == (void *)MAP_FAILED) {
37210037SARM gem5 Developers        perror("mmap");
37310037SARM gem5 Developers        fatal("Could not mmap physical memory!\n");
37412735Sandreas.sandberg@arm.com    }
3759258SAli.Saidi@ARM.com
3769535Smrinmoy.ghosh@arm.com    curSize = 0;
3779535Smrinmoy.ghosh@arm.com    tempPage = (long*)malloc(chunkSize);
3789535Smrinmoy.ghosh@arm.com    if (tempPage == NULL)
3799535Smrinmoy.ghosh@arm.com        fatal("Unable to malloc memory to read file %s\n", filename);
3809535Smrinmoy.ghosh@arm.com
3819535Smrinmoy.ghosh@arm.com    /* Only copy bytes that are non-zero, so we don't give the VM system hell */
3829258SAli.Saidi@ARM.com    while (curSize < params()->addrRange.size()) {
3839258SAli.Saidi@ARM.com        bytesRead = gzread(compressedMem, tempPage, chunkSize);
3849258SAli.Saidi@ARM.com        if (bytesRead != chunkSize && bytesRead != params()->addrRange.size() - curSize)
38510579SAndrew.Bardsley@arm.com            fatal("Read failed on physical memory checkpoint file '%s'"
38610579SAndrew.Bardsley@arm.com                  " got %d bytes, expected %d or %d bytes\n",
38710579SAndrew.Bardsley@arm.com                  filename, bytesRead, chunkSize, params()->addrRange.size()-curSize);
38810037SARM gem5 Developers
38910579SAndrew.Bardsley@arm.com        assert(bytesRead % sizeof(long) == 0);
39011517SCurtis.Dunham@arm.com
39111517SCurtis.Dunham@arm.com        for (int x = 0; x < bytesRead/sizeof(long); x++)
39210579SAndrew.Bardsley@arm.com        {
39310037SARM gem5 Developers             if (*(tempPage+x) != 0) {
39410579SAndrew.Bardsley@arm.com                 pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long));
39510579SAndrew.Bardsley@arm.com                 *pmem_current = *(tempPage+x);
39610579SAndrew.Bardsley@arm.com             }
39710579SAndrew.Bardsley@arm.com        }
39810579SAndrew.Bardsley@arm.com        curSize += bytesRead;
39910579SAndrew.Bardsley@arm.com    }
40010579SAndrew.Bardsley@arm.com
40110579SAndrew.Bardsley@arm.com    free(tempPage);
4029258SAli.Saidi@ARM.com
4039258SAli.Saidi@ARM.com    if (gzclose(compressedMem))
4049258SAli.Saidi@ARM.com        fatal("Close failed on physical memory checkpoint file '%s'\n",
4059258SAli.Saidi@ARM.com              filename);
4069258SAli.Saidi@ARM.com
4079258SAli.Saidi@ARM.com}
4089258SAli.Saidi@ARM.com
4099258SAli.Saidi@ARM.com
4109258SAli.Saidi@ARM.comBEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
4119535Smrinmoy.ghosh@arm.com
4129258SAli.Saidi@ARM.com    Param<string> file;
4139258SAli.Saidi@ARM.com    Param<Range<Addr> > range;
41410621SCurtis.Dunham@arm.com    Param<Tick> latency;
4159258SAli.Saidi@ARM.com
41610037SARM gem5 DevelopersEND_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
41710037SARM gem5 Developers
4189258SAli.Saidi@ARM.comBEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
4199535Smrinmoy.ghosh@arm.com
4209535Smrinmoy.ghosh@arm.com    INIT_PARAM_DFLT(file, "memory mapped file", ""),
42110474Sandreas.hansson@arm.com    INIT_PARAM(range, "Device Address Range"),
42210474Sandreas.hansson@arm.com    INIT_PARAM(latency, "Memory access latency")
42310474Sandreas.hansson@arm.com
4249535Smrinmoy.ghosh@arm.comEND_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
4259535Smrinmoy.ghosh@arm.com
42610621SCurtis.Dunham@arm.comCREATE_SIM_OBJECT(PhysicalMemory)
42710037SARM gem5 Developers{
42810037SARM gem5 Developers    PhysicalMemory::Params *p = new PhysicalMemory::Params;
42910037SARM gem5 Developers    p->name = getInstanceName();
4309535Smrinmoy.ghosh@arm.com    p->addrRange = range;
4319258SAli.Saidi@ARM.com    p->latency = latency;
4329258SAli.Saidi@ARM.com    return new PhysicalMemory(p);
4339258SAli.Saidi@ARM.com}
4349258SAli.Saidi@ARM.com
4359258SAli.Saidi@ARM.comREGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory)
4369535Smrinmoy.ghosh@arm.com