physical.cc revision 8712:7f762428a9f5
11689SN/A/*
22326SN/A * Copyright (c) 2010 ARM Limited
31689SN/A * All rights reserved
41689SN/A *
51689SN/A * The license below extends only to copyright in the software and shall
61689SN/A * not be construed as granting a license to any other intellectual
71689SN/A * property including but not limited to intellectual property relating
81689SN/A * to a hardware implementation of the functionality of the software
91689SN/A * licensed hereunder.  You may use the software subject to the license
101689SN/A * terms below provided that you ensure that this notice is replicated
111689SN/A * unmodified and in its entirety in all distributions of the software,
121689SN/A * modified or unmodified, in source code or in binary form.
131689SN/A *
141689SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan
151689SN/A * All rights reserved.
161689SN/A *
171689SN/A * Redistribution and use in source and binary forms, with or without
181689SN/A * modification, are permitted provided that the following conditions are
191689SN/A * met: redistributions of source code must retain the above copyright
201689SN/A * notice, this list of conditions and the following disclaimer;
211689SN/A * redistributions in binary form must reproduce the above copyright
221689SN/A * notice, this list of conditions and the following disclaimer in the
231689SN/A * documentation and/or other materials provided with the distribution;
241689SN/A * neither the name of the copyright holders nor the names of its
251689SN/A * contributors may be used to endorse or promote products derived from
261689SN/A * this software without specific prior written permission.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
291689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
301689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
311060SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
321060SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
331689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
341060SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
351060SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
361060SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
371060SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
386658Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392292SN/A *
401717SN/A * Authors: Ron Dreslinski
415529Snate@binkert.org *          Ali Saidi
421060SN/A */
436221Snate@binkert.org
446221Snate@binkert.org#include <sys/mman.h>
451681SN/A#include <sys/types.h>
465529Snate@binkert.org#include <sys/user.h>
472873Sktlim@umich.edu#include <fcntl.h>
484329Sktlim@umich.edu#include <unistd.h>
494329Sktlim@umich.edu#include <zlib.h>
504329Sktlim@umich.edu
512292SN/A#include <cerrno>
522292SN/A#include <cstdio>
532292SN/A#include <iostream>
542292SN/A#include <string>
552820Sktlim@umich.edu
562292SN/A#include "arch/isa_traits.hh"
572820Sktlim@umich.edu#include "arch/registers.hh"
582820Sktlim@umich.edu#include "base/intmath.hh"
595529Snate@binkert.org#include "base/misc.hh"
602307SN/A#include "base/random.hh"
611060SN/A#include "base/types.hh"
622292SN/A#include "config/full_system.hh"
632292SN/A#include "config/the_isa.hh"
642292SN/A#include "debug/LLSC.hh"
651060SN/A#include "debug/MemoryAccess.hh"
661060SN/A#include "mem/packet_access.hh"
671060SN/A#include "mem/physical.hh"
681060SN/A#include "sim/eventq.hh"
691060SN/A
701060SN/Ausing namespace std;
711681SN/Ausing namespace TheISA;
726221Snate@binkert.org
736221Snate@binkert.orgPhysicalMemory::PhysicalMemory(const Params *p)
746221Snate@binkert.org    : MemObject(p), pmemAddr(NULL), lat(p->latency), lat_var(p->latency_var),
756221Snate@binkert.org      _size(params()->range.size()), _start(params()->range.start)
762292SN/A{
772292SN/A    if (size() % TheISA::PageBytes != 0)
782820Sktlim@umich.edu        panic("Memory Size not divisible by page size\n");
792820Sktlim@umich.edu
802292SN/A    if (params()->null)
812292SN/A        return;
822820Sktlim@umich.edu
832820Sktlim@umich.edu
842292SN/A    if (params()->file == "") {
852292SN/A        int map_flags = MAP_ANON | MAP_PRIVATE;
862292SN/A        pmemAddr = (uint8_t *)mmap(NULL, size(),
872292SN/A                                   PROT_READ | PROT_WRITE, map_flags, -1, 0);
882292SN/A    } else {
892292SN/A        int map_flags = MAP_PRIVATE;
902292SN/A        int fd = open(params()->file.c_str(), O_RDONLY);
912292SN/A        _size = lseek(fd, 0, SEEK_END);
921060SN/A        lseek(fd, 0, SEEK_SET);
931060SN/A        pmemAddr = (uint8_t *)mmap(NULL, roundUp(size(), sysconf(_SC_PAGESIZE)),
941681SN/A                                   PROT_READ | PROT_WRITE, map_flags, fd, 0);
951062SN/A    }
962292SN/A
971062SN/A    if (pmemAddr == (void *)MAP_FAILED) {
982301SN/A        perror("mmap");
992301SN/A        if (params()->file == "")
1001062SN/A            fatal("Could not mmap!\n");
1012727Sktlim@umich.edu        else
1021062SN/A            fatal("Could not find file: %s\n", params()->file);
1031062SN/A    }
1041062SN/A
1051062SN/A    //If requested, initialize all the memory to 0
1061062SN/A    if (p->zero)
1071062SN/A        memset(pmemAddr, 0, size());
1081062SN/A}
1091062SN/A
1101062SN/Avoid
1111062SN/APhysicalMemory::init()
1121062SN/A{
1131062SN/A    if (ports.size() == 0) {
1141062SN/A        fatal("PhysicalMemory object %s is unconnected!", name());
1151062SN/A    }
1161062SN/A
1171062SN/A    for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) {
1181062SN/A        if (*pi)
1191062SN/A            (*pi)->sendRangeChange();
1201062SN/A    }
1211062SN/A}
1221062SN/A
1231062SN/APhysicalMemory::~PhysicalMemory()
1241062SN/A{
1251062SN/A    if (pmemAddr)
1261062SN/A        munmap((char*)pmemAddr, size());
1271062SN/A}
1281062SN/A
1291062SN/Aunsigned
1301062SN/APhysicalMemory::deviceBlockSize() const
1311062SN/A{
1321062SN/A    //Can accept anysize request
1331062SN/A    return 0;
1341062SN/A}
1351062SN/A
1361062SN/ATick
1371062SN/APhysicalMemory::calculateLatency(PacketPtr pkt)
1381062SN/A{
1391062SN/A    Tick latency = lat;
1401062SN/A    if (lat_var != 0)
1411062SN/A        latency += random_mt.random<Tick>(0, lat_var);
1421062SN/A    return latency;
1432292SN/A}
1442292SN/A
1452292SN/A
1462292SN/A
1471062SN/A// Add load-locked to tracking list.  Should only be called if the
1481062SN/A// operation is a load and the LLSC flag is set.
1491062SN/Avoid
1501062SN/APhysicalMemory::trackLoadLocked(PacketPtr pkt)
1511062SN/A{
1521062SN/A    Request *req = pkt->req;
1531062SN/A    Addr paddr = LockedAddr::mask(req->getPaddr());
1542292SN/A
1552292SN/A    // first we check if we already have a locked addr for this
1562292SN/A    // xc.  Since each xc only gets one, we just update the
1572292SN/A    // existing record with the new address.
1582292SN/A    list<LockedAddr>::iterator i;
1592292SN/A
1602292SN/A    for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) {
1612292SN/A        if (i->matchesContext(req)) {
1622292SN/A            DPRINTF(LLSC, "Modifying lock record: context %d addr %#x\n",
1632292SN/A                    req->contextId(), paddr);
1642301SN/A            i->addr = paddr;
1652727Sktlim@umich.edu            return;
1662353SN/A        }
1672727Sktlim@umich.edu    }
1682727Sktlim@umich.edu
1692727Sktlim@umich.edu    // no record for this xc: need to allocate a new one
1706221Snate@binkert.org    DPRINTF(LLSC, "Adding lock record: context %d addr %#x\n",
1712353SN/A            req->contextId(), paddr);
1722727Sktlim@umich.edu    lockedAddrList.push_front(LockedAddr(req));
1732727Sktlim@umich.edu}
1742727Sktlim@umich.edu
1752727Sktlim@umich.edu
1762353SN/A// Called on *writes* only... both regular stores and
1772727Sktlim@umich.edu// store-conditional operations.  Check for conventional stores which
1782727Sktlim@umich.edu// conflict with locked addresses, and for success/failure of store
1792727Sktlim@umich.edu// conditionals.
1806221Snate@binkert.orgbool
1812301SN/APhysicalMemory::checkLockedAddrList(PacketPtr pkt)
1822301SN/A{
1832727Sktlim@umich.edu    Request *req = pkt->req;
1842301SN/A    Addr paddr = LockedAddr::mask(req->getPaddr());
1852727Sktlim@umich.edu    bool isLLSC = pkt->isLLSC();
1866221Snate@binkert.org
1872301SN/A    // Initialize return value.  Non-conditional stores always
1882301SN/A    // succeed.  Assume conditional stores will fail until proven
1892727Sktlim@umich.edu    // otherwise.
1902301SN/A    bool success = !isLLSC;
1912727Sktlim@umich.edu
1926221Snate@binkert.org    // Iterate over list.  Note that there could be multiple matching
1932301SN/A    // records, as more than one context could have done a load locked
1942301SN/A    // to this location.
1952727Sktlim@umich.edu    list<LockedAddr>::iterator i = lockedAddrList.begin();
1962301SN/A
1972727Sktlim@umich.edu    while (i != lockedAddrList.end()) {
1986221Snate@binkert.org
1992301SN/A        if (i->addr == paddr) {
2002301SN/A            // we have a matching address
2012727Sktlim@umich.edu
2022301SN/A            if (isLLSC && i->matchesContext(req)) {
2032301SN/A                // it's a store conditional, and as far as the memory
2042301SN/A                // system can tell, the requesting context's lock is
2052301SN/A                // still valid.
2062727Sktlim@umich.edu                DPRINTF(LLSC, "StCond success: context %d addr %#x\n",
2072727Sktlim@umich.edu                        req->contextId(), paddr);
2082727Sktlim@umich.edu                success = true;
2092727Sktlim@umich.edu            }
2102727Sktlim@umich.edu
2112727Sktlim@umich.edu            // Get rid of our record of this lock and advance to next
2122727Sktlim@umich.edu            DPRINTF(LLSC, "Erasing lock record: context %d addr %#x\n",
2132727Sktlim@umich.edu                    i->contextId, paddr);
2142727Sktlim@umich.edu            i = lockedAddrList.erase(i);
2152301SN/A        }
2162301SN/A        else {
2176221Snate@binkert.org            // no match: advance to next record
2182301SN/A            ++i;
2192301SN/A        }
2202727Sktlim@umich.edu    }
2212301SN/A
2222326SN/A    if (isLLSC) {
2236221Snate@binkert.org        req->setExtraData(success ? 1 : 0);
2242301SN/A    }
2252301SN/A
2262727Sktlim@umich.edu    return success;
2272301SN/A}
2282326SN/A
2296221Snate@binkert.org
2302301SN/A#if TRACING_ON
2312301SN/A
2322727Sktlim@umich.edu#define CASE(A, T)                                                      \
2332301SN/A  case sizeof(T):                                                       \
2342326SN/A    DPRINTF(MemoryAccess,"%s of size %i on address 0x%x data 0x%x\n",   \
2356221Snate@binkert.org            A, pkt->getSize(), pkt->getAddr(), pkt->get<T>());          \
2362301SN/A  break
2372301SN/A
2382727Sktlim@umich.edu
2392301SN/A#define TRACE_PACKET(A)                                                 \
2402326SN/A    do {                                                                \
2416221Snate@binkert.org        switch (pkt->getSize()) {                                       \
2422301SN/A          CASE(A, uint64_t);                                            \
2432301SN/A          CASE(A, uint32_t);                                            \
2442727Sktlim@umich.edu          CASE(A, uint16_t);                                            \
2452301SN/A          CASE(A, uint8_t);                                             \
2462326SN/A          default:                                                      \
2472301SN/A            DPRINTF(MemoryAccess, "%s of size %i on address 0x%x\n",    \
2482301SN/A                    A, pkt->getSize(), pkt->getAddr());                 \
2492727Sktlim@umich.edu            DDUMP(MemoryAccess, pkt->getPtr<uint8_t>(), pkt->getSize());\
2502301SN/A        }                                                               \
2512326SN/A    } while (0)
2522301SN/A
2532326SN/A#else
2542301SN/A
2552301SN/A#define TRACE_PACKET(A)
2562727Sktlim@umich.edu
2572301SN/A#endif
2582326SN/A
2592301SN/ATick
2602326SN/APhysicalMemory::doAtomicAccess(PacketPtr pkt)
2612301SN/A{
2622301SN/A    assert(pkt->getAddr() >= start() &&
2632727Sktlim@umich.edu           pkt->getAddr() + pkt->getSize() <= start() + size());
2642326SN/A
2651062SN/A    if (pkt->memInhibitAsserted()) {
2661062SN/A        DPRINTF(MemoryAccess, "mem inhibited on 0x%x: not responding\n",
2671681SN/A                pkt->getAddr());
2681060SN/A        return 0;
2692292SN/A    }
2701060SN/A
2716221Snate@binkert.org    uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start();
2722292SN/A
2732292SN/A    if (pkt->cmd == MemCmd::SwapReq) {
2742292SN/A        IntReg overwrite_val;
2752292SN/A        bool overwrite_mem;
2762292SN/A        uint64_t condition_val64;
2772292SN/A        uint32_t condition_val32;
2782292SN/A
2792292SN/A        if (!pmemAddr)
2802292SN/A            panic("Swap only works if there is real memory (i.e. null=False)");
2812733Sktlim@umich.edu        assert(sizeof(IntReg) >= pkt->getSize());
2821060SN/A
2831060SN/A        overwrite_mem = true;
2841681SN/A        // keep a copy of our possible write value, and copy what is at the
2851060SN/A        // memory address into the packet
2862292SN/A        std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize());
2871060SN/A        std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
2881060SN/A
2891060SN/A        if (pkt->req->isCondSwap()) {
2901060SN/A            if (pkt->getSize() == sizeof(uint64_t)) {
2911060SN/A                condition_val64 = pkt->req->getExtraData();
2921060SN/A                overwrite_mem = !std::memcmp(&condition_val64, hostAddr,
2931060SN/A                                             sizeof(uint64_t));
2941060SN/A            } else if (pkt->getSize() == sizeof(uint32_t)) {
2951060SN/A                condition_val32 = (uint32_t)pkt->req->getExtraData();
2962292SN/A                overwrite_mem = !std::memcmp(&condition_val32, hostAddr,
2972292SN/A                                             sizeof(uint32_t));
2981060SN/A            } else
2991060SN/A                panic("Invalid size for conditional read/write\n");
3001060SN/A        }
3011060SN/A
3021681SN/A        if (overwrite_mem)
3031060SN/A            std::memcpy(hostAddr, &overwrite_val, pkt->getSize());
3042292SN/A
3051060SN/A        assert(!pkt->req->isInstFetch());
3061060SN/A        TRACE_PACKET("Read/Write");
3071060SN/A    } else if (pkt->isRead()) {
3081060SN/A        assert(!pkt->isWrite());
3091060SN/A        if (pkt->isLLSC()) {
3101060SN/A            trackLoadLocked(pkt);
3111060SN/A        }
3121681SN/A        if (pmemAddr)
3131060SN/A            memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
3142292SN/A        TRACE_PACKET(pkt->req->isInstFetch() ? "IFetch" : "Read");
3151060SN/A    } else if (pkt->isWrite()) {
3161060SN/A        if (writeOK(pkt)) {
3171060SN/A            if (pmemAddr)
3181060SN/A                memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
3191060SN/A            assert(!pkt->req->isInstFetch());
3201060SN/A            TRACE_PACKET("Write");
3211060SN/A        }
3221681SN/A    } else if (pkt->isInvalidate()) {
3231060SN/A        //upgrade or invalidate
3246221Snate@binkert.org        if (pkt->needsResponse()) {
3251060SN/A            pkt->makeAtomicResponse();
3262292SN/A        }
3272292SN/A    } else {
3282292SN/A        panic("unimplemented");
3292292SN/A    }
3301060SN/A
3311060SN/A    if (pkt->needsResponse()) {
3321681SN/A        pkt->makeAtomicResponse();
3331060SN/A    }
3342292SN/A    return calculateLatency(pkt);
3351060SN/A}
3362292SN/A
3371060SN/A
3381060SN/Avoid
3392307SN/APhysicalMemory::doFunctionalAccess(PacketPtr pkt)
3402863Sktlim@umich.edu{
3412843Sktlim@umich.edu    assert(pkt->getAddr() >= start() &&
3422307SN/A           pkt->getAddr() + pkt->getSize() <= start() + size());
3432843Sktlim@umich.edu
3442843Sktlim@umich.edu
3452863Sktlim@umich.edu    uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start();
3461681SN/A
3471681SN/A    if (pkt->isRead()) {
3482316SN/A        if (pmemAddr)
3491681SN/A            memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
3502843Sktlim@umich.edu        TRACE_PACKET("Read");
3512843Sktlim@umich.edu        pkt->makeAtomicResponse();
3522843Sktlim@umich.edu    } else if (pkt->isWrite()) {
3532843Sktlim@umich.edu        if (pmemAddr)
3542843Sktlim@umich.edu            memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
3552843Sktlim@umich.edu        TRACE_PACKET("Write");
3562843Sktlim@umich.edu        pkt->makeAtomicResponse();
3571681SN/A    } else if (pkt->isPrint()) {
3582348SN/A        Packet::PrintReqState *prs =
3592307SN/A            dynamic_cast<Packet::PrintReqState*>(pkt->senderState);
3602367SN/A        // Need to call printLabels() explicitly since we're not going
3612367SN/A        // through printObj().
3621681SN/A        prs->printLabels();
3632307SN/A        // Right now we just print the single byte at the specified address.
3642307SN/A        ccprintf(prs->os, "%s%#x\n", prs->curPrefix(), *hostAddr);
3652307SN/A    } else {
3662307SN/A        panic("PhysicalMemory: unimplemented functional command %s",
3676221Snate@binkert.org              pkt->cmdString());
3686221Snate@binkert.org    }
3696221Snate@binkert.org}
3706221Snate@binkert.org
3716221Snate@binkert.org
3722307SN/APort *
3731681SN/APhysicalMemory::getPort(const std::string &if_name, int idx)
3741681SN/A{
3752307SN/A    if (if_name != "port") {
3761681SN/A        panic("PhysicalMemory::getPort: unknown port %s requested", if_name);
3772307SN/A    }
3781060SN/A
3792348SN/A    if (idx >= (int)ports.size()) {
3802307SN/A        ports.resize(idx + 1);
3812307SN/A    }
3822307SN/A
3832307SN/A    if (ports[idx] != NULL) {
3841060SN/A        panic("PhysicalMemory::getPort: port %d already assigned", idx);
3852307SN/A    }
3862307SN/A
3872307SN/A    MemoryPort *port =
3881060SN/A        new MemoryPort(csprintf("%s-port%d", name(), idx), this);
3892307SN/A
3902307SN/A    ports[idx] = port;
3911060SN/A    return port;
3926221Snate@binkert.org}
3936221Snate@binkert.org
3946221Snate@binkert.orgPhysicalMemory::MemoryPort::MemoryPort(const std::string &_name,
3956221Snate@binkert.org                                       PhysicalMemory *_memory)
3962307SN/A    : SimpleTimingPort(_name, _memory), memory(_memory)
3971060SN/A{ }
3982307SN/A
3992307SN/Avoid
4002873Sktlim@umich.eduPhysicalMemory::MemoryPort::recvRangeChange()
4012307SN/A{
4021060SN/A    // memory is a slave and thus should never have to worry about its
4031060SN/A    // neighbours address ranges
4041060SN/A}
4051681SN/A
4061060SN/AAddrRangeList
4076221Snate@binkert.orgPhysicalMemory::MemoryPort::getAddrRanges()
4082107SN/A{
4096221Snate@binkert.org    return memory->getAddrRanges();
4102107SN/A}
4112292SN/A
4122292SN/AAddrRangeList
4132107SN/APhysicalMemory::getAddrRanges()
4142292SN/A{
4152326SN/A    AddrRangeList ranges;
4162292SN/A    ranges.push_back(RangeSize(start(), size()));
4172107SN/A    return ranges;
4182292SN/A}
4192935Sksewell@umich.edu
4204632Sgblack@eecs.umich.eduunsigned
4212935Sksewell@umich.eduPhysicalMemory::MemoryPort::deviceBlockSize() const
4222292SN/A{
4232292SN/A    return memory->deviceBlockSize();
4242292SN/A}
4252292SN/A
4262292SN/ATick
4272107SN/APhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt)
4282292SN/A{
4292107SN/A    return memory->doAtomicAccess(pkt);
4302292SN/A}
4312292SN/A
4322107SN/Avoid
4332702Sktlim@umich.eduPhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt)
4342107SN/A{
4352107SN/A    pkt->pushLabel(memory->name());
4362107SN/A
4372107SN/A    if (!checkFunctional(pkt)) {
4386221Snate@binkert.org        // Default implementation of SimpleTimingPort::recvFunctional()
4392292SN/A        // calls recvAtomic() and throws away the latency; we can save a
4402292SN/A        // little here by just not calculating the latency.
4412292SN/A        memory->doFunctionalAccess(pkt);
4422292SN/A    }
4432292SN/A
4442292SN/A    pkt->popLabel();
4452292SN/A}
4462292SN/A
4472935Sksewell@umich.eduunsigned int
4484632Sgblack@eecs.umich.eduPhysicalMemory::drain(Event *de)
4493969Sgblack@eecs.umich.edu{
4504632Sgblack@eecs.umich.edu    int count = 0;
4513795Sgblack@eecs.umich.edu    for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) {
4523795Sgblack@eecs.umich.edu        count += (*pi)->drain(de);
4533795Sgblack@eecs.umich.edu    }
4543093Sksewell@umich.edu
4553093Sksewell@umich.edu    if (count)
4563093Sksewell@umich.edu        changeState(Draining);
4574632Sgblack@eecs.umich.edu    else
4583093Sksewell@umich.edu        changeState(Drained);
4594632Sgblack@eecs.umich.edu    return count;
4604636Sgblack@eecs.umich.edu}
4612292SN/A
4622292SN/Avoid
4632292SN/APhysicalMemory::serialize(ostream &os)
4642292SN/A{
4652292SN/A    if (!pmemAddr)
4662292SN/A        return;
4672292SN/A
4682292SN/A    gzFile compressedMem;
4696221Snate@binkert.org    string filename = name() + ".physmem";
4702292SN/A
4712292SN/A    SERIALIZE_SCALAR(filename);
4722292SN/A    SERIALIZE_SCALAR(_size);
4732292SN/A
4742292SN/A    // write memory file
4752292SN/A    string thefile = Checkpoint::dir() + "/" + filename.c_str();
4762292SN/A    int fd = creat(thefile.c_str(), 0664);
4773795Sgblack@eecs.umich.edu    if (fd < 0) {
4783732Sktlim@umich.edu        perror("creat");
4792292SN/A        fatal("Can't open physical memory checkpoint file '%s'\n", filename);
4802292SN/A    }
4812292SN/A
4822292SN/A    compressedMem = gzdopen(fd, "wb");
4832292SN/A    if (compressedMem == NULL)
4842292SN/A        fatal("Insufficient memory to allocate compression state for %s\n",
4852292SN/A                filename);
4862292SN/A
4876221Snate@binkert.org    if (gzwrite(compressedMem, pmemAddr, size()) != (int)size()) {
4882292SN/A        fatal("Write failed on physical memory checkpoint file '%s'\n",
4892292SN/A              filename);
4902292SN/A    }
4912292SN/A
4922292SN/A    if (gzclose(compressedMem))
4932292SN/A        fatal("Close failed on physical memory checkpoint file '%s'\n",
4942292SN/A              filename);
4953958Sgblack@eecs.umich.edu
4963732Sktlim@umich.edu    list<LockedAddr>::iterator i = lockedAddrList.begin();
4972292SN/A
4982348SN/A    vector<Addr> lal_addr;
4992292SN/A    vector<int> lal_cid;
5002292SN/A    while (i != lockedAddrList.end()) {
5012292SN/A        lal_addr.push_back(i->addr);
5022292SN/A        lal_cid.push_back(i->contextId);
5032292SN/A        i++;
5042292SN/A    }
5052292SN/A    arrayParamOut(os, "lal_addr", lal_addr);
5062292SN/A    arrayParamOut(os, "lal_cid", lal_cid);
5072292SN/A}
5086221Snate@binkert.org
5092292SN/Avoid
5102292SN/APhysicalMemory::unserialize(Checkpoint *cp, const string &section)
5112292SN/A{
5122292SN/A    if (!pmemAddr)
5132292SN/A        return;
5142292SN/A
5152292SN/A    gzFile compressedMem;
5162292SN/A    long *tempPage;
5172292SN/A    long *pmem_current;
5182292SN/A    uint64_t curSize;
5192292SN/A    uint32_t bytesRead;
5202292SN/A    const uint32_t chunkSize = 16384;
5212292SN/A
5222292SN/A    string filename;
5232292SN/A
5242292SN/A    UNSERIALIZE_SCALAR(filename);
5252292SN/A
5262292SN/A    filename = cp->cptDir + "/" + filename;
5276221Snate@binkert.org
5282292SN/A    // mmap memoryfile
5292292SN/A    int fd = open(filename.c_str(), O_RDONLY);
5302292SN/A    if (fd < 0) {
5312292SN/A        perror("open");
5322292SN/A        fatal("Can't open physical memory checkpoint file '%s'", filename);
5332292SN/A    }
5342292SN/A
5352292SN/A    compressedMem = gzdopen(fd, "rb");
5362292SN/A    if (compressedMem == NULL)
5372292SN/A        fatal("Insufficient memory to allocate compression state for %s\n",
5382292SN/A                filename);
5392292SN/A
5402292SN/A    // unmap file that was mmapped in the constructor
5412292SN/A    // This is done here to make sure that gzip and open don't muck with our
5422292SN/A    // nice large space of memory before we reallocate it
5432292SN/A    munmap((char*)pmemAddr, size());
5442292SN/A
5451060SN/A    UNSERIALIZE_SCALAR(_size);
5461681SN/A    if (size() > params()->range.size())
5471060SN/A        fatal("Memory size has changed! size %lld, param size %lld\n",
5481060SN/A              size(), params()->range.size());
5492292SN/A
5502292SN/A    pmemAddr = (uint8_t *)mmap(NULL, size(),
5512292SN/A        PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
5522292SN/A
5532292SN/A    if (pmemAddr == (void *)MAP_FAILED) {
5542292SN/A        perror("mmap");
5551681SN/A        fatal("Could not mmap physical memory!\n");
5561681SN/A    }
5571060SN/A
5582292SN/A    curSize = 0;
5591060SN/A    tempPage = (long*)malloc(chunkSize);
5602292SN/A    if (tempPage == NULL)
5612292SN/A        fatal("Unable to malloc memory to read file %s\n", filename);
5621060SN/A
5632292SN/A    /* Only copy bytes that are non-zero, so we don't give the VM system hell */
5642292SN/A    while (curSize < size()) {
5652292SN/A        bytesRead = gzread(compressedMem, tempPage, chunkSize);
5662292SN/A        if (bytesRead == 0)
5673221Sktlim@umich.edu            break;
5683221Sktlim@umich.edu
5693221Sktlim@umich.edu        assert(bytesRead % sizeof(long) == 0);
5703221Sktlim@umich.edu
5713221Sktlim@umich.edu        for (uint32_t x = 0; x < bytesRead / sizeof(long); x++)
5722292SN/A        {
5732292SN/A             if (*(tempPage+x) != 0) {
5742292SN/A                 pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long));
5752292SN/A                 *pmem_current = *(tempPage+x);
5762326SN/A             }
5772292SN/A        }
5782292SN/A        curSize += bytesRead;
5792820Sktlim@umich.edu    }
5802292SN/A
5812292SN/A    free(tempPage);
5822292SN/A
5832292SN/A    if (gzclose(compressedMem))
5842353SN/A        fatal("Close failed on physical memory checkpoint file '%s'\n",
5852292SN/A              filename);
5862292SN/A
5872353SN/A    vector<Addr> lal_addr;
5882353SN/A    vector<int> lal_cid;
5892292SN/A    arrayParamIn(cp, section, "lal_addr", lal_addr);
5902292SN/A    arrayParamIn(cp, section, "lal_cid", lal_cid);
5912292SN/A    for(int i = 0; i < lal_addr.size(); i++)
5922292SN/A        lockedAddrList.push_front(LockedAddr(lal_addr[i], lal_cid[i]));
5932292SN/A}
5942292SN/A
5952292SN/APhysicalMemory *
5962292SN/APhysicalMemoryParams::create()
5972292SN/A{
5982292SN/A    return new PhysicalMemory(this);
5992292SN/A}
6002292SN/A