abstract_mem.cc revision 5314
12623SN/A/*
210596Sgabeblack@google.com * Copyright (c) 2001-2005 The Regents of The University of Michigan
313012Sandreas.sandberg@arm.com * All rights reserved.
48926Sandreas.hansson@arm.com *
58926Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
68926Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
78926Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
88926Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
98926Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
108926Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
118926Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
128926Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
138926Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
148926Sandreas.hansson@arm.com * this software without specific prior written permission.
152623SN/A *
162623SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182623SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192623SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202623SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212623SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242623SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252623SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262623SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272623SN/A *
282623SN/A * Authors: Ron Dreslinski
292623SN/A *          Ali Saidi
302623SN/A */
312623SN/A
322623SN/A#include <sys/types.h>
332623SN/A#include <sys/mman.h>
342623SN/A#include <errno.h>
352623SN/A#include <fcntl.h>
362623SN/A#include <unistd.h>
372623SN/A#include <zlib.h>
382623SN/A
392623SN/A#include <iostream>
402665Ssaidi@eecs.umich.edu#include <string>
412665Ssaidi@eecs.umich.edu
422623SN/A#include "arch/isa_traits.hh"
432623SN/A#include "base/misc.hh"
4411793Sbrandon.potter@amd.com#include "config/full_system.hh"
4511793Sbrandon.potter@amd.com#include "mem/packet_access.hh"
463170Sstever@eecs.umich.edu#include "mem/physical.hh"
478105Sgblack@eecs.umich.edu#include "sim/eventq.hh"
482623SN/A#include "sim/host.hh"
499647Sdam.sunwoo@arm.com
506658Snate@binkert.orgusing namespace std;
512623SN/Ausing namespace TheISA;
5213954Sgiacomo.gabrielli@arm.com
539443SAndreas.Sandberg@ARM.comPhysicalMemory::PhysicalMemory(const Params *p)
548232Snate@binkert.org    : MemObject(p), pmemAddr(NULL), lat(p->latency)
558232Snate@binkert.org{
563348Sbinkertn@umich.edu    if (params()->range.size() % TheISA::PageBytes != 0)
573348Sbinkertn@umich.edu        panic("Memory Size not divisible by page size\n");
588926Sandreas.hansson@arm.com
594762Snate@binkert.org    int map_flags = MAP_ANON | MAP_PRIVATE;
607678Sgblack@eecs.umich.edu    pmemAddr = (uint8_t *)mmap(NULL, params()->range.size(),
6111793Sbrandon.potter@amd.com                               PROT_READ | PROT_WRITE, map_flags, -1, 0);
622901Ssaidi@eecs.umich.edu
632623SN/A    if (pmemAddr == (void *)MAP_FAILED) {
642623SN/A        perror("mmap");
652623SN/A        fatal("Could not mmap!\n");
662623SN/A    }
672623SN/A
682623SN/A    //If requested, initialize all the memory to 0
692623SN/A    if (p->zero)
7011147Smitch.hayenga@arm.com        memset(pmemAddr, 0, p->range.size());
718921Sandreas.hansson@arm.com
7211148Smitch.hayenga@arm.com    pagePtr = 0;
7312749Sgiacomo.travaglini@arm.com
7412749Sgiacomo.travaglini@arm.com    cachedSize = params()->range.size();
7512749Sgiacomo.travaglini@arm.com    cachedStart = params()->range.start;
7613652Sqtt2@cornell.edu
772623SN/A}
782623SN/A
795529Snate@binkert.orgvoid
8012127Sspwilson2@wisc.eduPhysicalMemory::init()
8112127Sspwilson2@wisc.edu{
8212127Sspwilson2@wisc.edu    if (ports.size() == 0) {
8312127Sspwilson2@wisc.edu        fatal("PhysicalMemory object %s is unconnected!", name());
845487Snate@binkert.org    }
855487Snate@binkert.org
869095Sandreas.hansson@arm.com    for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) {
879095Sandreas.hansson@arm.com        if (*pi)
8813012Sandreas.sandberg@arm.com            (*pi)->sendStatusChange(Port::RangeChange);
8910537Sandreas.hansson@arm.com    }
902623SN/A}
912623SN/A
9212749Sgiacomo.travaglini@arm.comPhysicalMemory::~PhysicalMemory()
9312749Sgiacomo.travaglini@arm.com{
9412749Sgiacomo.travaglini@arm.com    if (pmemAddr)
9513652Sqtt2@cornell.edu        munmap((char*)pmemAddr, params()->range.size());
962623SN/A    //Remove memPorts?
972623SN/A}
982623SN/A
992623SN/AAddr
1002623SN/APhysicalMemory::new_page()
1016775SBrad.Beckmann@amd.com{
1026775SBrad.Beckmann@amd.com    Addr return_addr = pagePtr << LogVMPageSize;
1036775SBrad.Beckmann@amd.com    return_addr += start();
1042623SN/A
1052623SN/A    ++pagePtr;
10610913Sandreas.sandberg@arm.com    return return_addr;
10710913Sandreas.sandberg@arm.com}
1082623SN/A
10912276Sanouk.vanlaer@arm.comint
11012276Sanouk.vanlaer@arm.comPhysicalMemory::deviceBlockSize()
11112276Sanouk.vanlaer@arm.com{
1129448SAndreas.Sandberg@ARM.com    //Can accept anysize request
11310913Sandreas.sandberg@arm.com    return 0;
1142623SN/A}
11514085Sgiacomo.travaglini@arm.com
11611147Smitch.hayenga@arm.comTick
11710913Sandreas.sandberg@arm.comPhysicalMemory::calculateLatency(PacketPtr pkt)
1189443SAndreas.Sandberg@ARM.com{
1199443SAndreas.Sandberg@ARM.com    return lat;
1209443SAndreas.Sandberg@ARM.com}
1212915Sktlim@umich.edu
12211147Smitch.hayenga@arm.com
1239443SAndreas.Sandberg@ARM.com
12410913Sandreas.sandberg@arm.com// Add load-locked to tracking list.  Should only be called if the
1259443SAndreas.Sandberg@ARM.com// operation is a load and the LOCKED flag is set.
1269342SAndreas.Sandberg@arm.comvoid
1279342SAndreas.Sandberg@arm.comPhysicalMemory::trackLoadLocked(PacketPtr pkt)
1282915Sktlim@umich.edu{
12911148Smitch.hayenga@arm.com    Request *req = pkt->req;
13011148Smitch.hayenga@arm.com    Addr paddr = LockedAddr::mask(req->getPaddr());
13111148Smitch.hayenga@arm.com
13211148Smitch.hayenga@arm.com    // first we check if we already have a locked addr for this
13311148Smitch.hayenga@arm.com    // xc.  Since each xc only gets one, we just update the
13411148Smitch.hayenga@arm.com    // existing record with the new address.
13511148Smitch.hayenga@arm.com    list<LockedAddr>::iterator i;
13611321Ssteve.reinhardt@amd.com
13711151Smitch.hayenga@arm.com    for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) {
13811148Smitch.hayenga@arm.com        if (i->matchesContext(req)) {
13911148Smitch.hayenga@arm.com            DPRINTF(LLSC, "Modifying lock record: cpu %d thread %d addr %#x\n",
14011148Smitch.hayenga@arm.com                    req->getCpuNum(), req->getThreadNum(), paddr);
14111148Smitch.hayenga@arm.com            i->addr = paddr;
14211148Smitch.hayenga@arm.com            return;
14311148Smitch.hayenga@arm.com        }
14411148Smitch.hayenga@arm.com    }
14511148Smitch.hayenga@arm.com
14611148Smitch.hayenga@arm.com    // no record for this xc: need to allocate a new one
1479342SAndreas.Sandberg@arm.com    DPRINTF(LLSC, "Adding lock record: cpu %d thread %d addr %#x\n",
1482915Sktlim@umich.edu            req->getCpuNum(), req->getThreadNum(), paddr);
1499448SAndreas.Sandberg@ARM.com    lockedAddrList.push_front(LockedAddr(req));
1509448SAndreas.Sandberg@ARM.com}
1515220Ssaidi@eecs.umich.edu
1525220Ssaidi@eecs.umich.edu
1534940Snate@binkert.org// Called on *writes* only... both regular stores and
1549523SAndreas.Sandberg@ARM.com// store-conditional operations.  Check for conventional stores which
1553324Shsul@eecs.umich.edu// conflict with locked addresses, and for success/failure of store
1569448SAndreas.Sandberg@ARM.com// conditionals.
1579448SAndreas.Sandberg@ARM.combool
15811147Smitch.hayenga@arm.comPhysicalMemory::checkLockedAddrList(PacketPtr pkt)
15911147Smitch.hayenga@arm.com{
16011147Smitch.hayenga@arm.com    Request *req = pkt->req;
16111147Smitch.hayenga@arm.com    Addr paddr = LockedAddr::mask(req->getPaddr());
16211147Smitch.hayenga@arm.com    bool isLocked = pkt->isLocked();
16311147Smitch.hayenga@arm.com
16411147Smitch.hayenga@arm.com    // Initialize return value.  Non-conditional stores always
16511147Smitch.hayenga@arm.com    // succeed.  Assume conditional stores will fail until proven
16611147Smitch.hayenga@arm.com    // otherwise.
16711147Smitch.hayenga@arm.com    bool success = !isLocked;
16811147Smitch.hayenga@arm.com
16911147Smitch.hayenga@arm.com    // Iterate over list.  Note that there could be multiple matching
17011147Smitch.hayenga@arm.com    // records, as more than one context could have done a load locked
17111147Smitch.hayenga@arm.com    // to this location.
17211147Smitch.hayenga@arm.com    list<LockedAddr>::iterator i = lockedAddrList.begin();
1739448SAndreas.Sandberg@ARM.com
17412276Sanouk.vanlaer@arm.com    while (i != lockedAddrList.end()) {
17512276Sanouk.vanlaer@arm.com
17612276Sanouk.vanlaer@arm.com        if (i->addr == paddr) {
1772623SN/A            // we have a matching address
1782623SN/A
1799443SAndreas.Sandberg@ARM.com            if (isLocked && i->matchesContext(req)) {
1809443SAndreas.Sandberg@ARM.com                // it's a store conditional, and as far as the memory
1819443SAndreas.Sandberg@ARM.com                // system can tell, the requesting context's lock is
18210913Sandreas.sandberg@arm.com                // still valid.
1839443SAndreas.Sandberg@ARM.com                DPRINTF(LLSC, "StCond success: cpu %d thread %d addr %#x\n",
1849443SAndreas.Sandberg@ARM.com                        req->getCpuNum(), req->getThreadNum(), paddr);
18511147Smitch.hayenga@arm.com                success = true;
18614085Sgiacomo.travaglini@arm.com            }
1879443SAndreas.Sandberg@ARM.com
1889443SAndreas.Sandberg@ARM.com            // Get rid of our record of this lock and advance to next
1899443SAndreas.Sandberg@ARM.com            DPRINTF(LLSC, "Erasing lock record: cpu %d thread %d addr %#x\n",
19010913Sandreas.sandberg@arm.com                    i->cpuNum, i->threadNum, paddr);
1919443SAndreas.Sandberg@ARM.com            i = lockedAddrList.erase(i);
1929443SAndreas.Sandberg@ARM.com        }
1939443SAndreas.Sandberg@ARM.com        else {
1949443SAndreas.Sandberg@ARM.com            // no match: advance to next record
1959443SAndreas.Sandberg@ARM.com            ++i;
1962623SN/A        }
1972798Sktlim@umich.edu    }
1982623SN/A
1999429SAndreas.Sandberg@ARM.com    if (isLocked) {
2009429SAndreas.Sandberg@ARM.com        req->setExtraData(success ? 1 : 0);
2019443SAndreas.Sandberg@ARM.com    }
2029342SAndreas.Sandberg@arm.com
20314085Sgiacomo.travaglini@arm.com    return success;
2042623SN/A}
2052623SN/A
2062623SN/A
2072623SN/A#if TRACING_ON
2082623SN/A
2092623SN/A#define CASE(A, T)                                                      \
2109429SAndreas.Sandberg@ARM.com  case sizeof(T):                                                       \
2112623SN/A    DPRINTF(MemoryAccess, A " of size %i on address 0x%x data 0x%x\n",  \
2129443SAndreas.Sandberg@ARM.com            pkt->getSize(), pkt->getAddr(), pkt->get<T>());             \
2132623SN/A  break
2142623SN/A
2152623SN/A
2169523SAndreas.Sandberg@ARM.com#define TRACE_PACKET(A)                                                 \
2179523SAndreas.Sandberg@ARM.com    do {                                                                \
2189523SAndreas.Sandberg@ARM.com        switch (pkt->getSize()) {                                       \
2199524SAndreas.Sandberg@ARM.com          CASE(A, uint64_t);                                            \
2209523SAndreas.Sandberg@ARM.com          CASE(A, uint32_t);                                            \
2219523SAndreas.Sandberg@ARM.com          CASE(A, uint16_t);                                            \
2229523SAndreas.Sandberg@ARM.com          CASE(A, uint8_t);                                             \
2239523SAndreas.Sandberg@ARM.com          default:                                                      \
2242623SN/A            DPRINTF(MemoryAccess, A " of size %i on address 0x%x\n",    \
2252623SN/A                    pkt->getSize(), pkt->getAddr());                    \
22610407Smitch.hayenga@arm.com        }                                                               \
2272623SN/A    } while (0)
22810407Smitch.hayenga@arm.com
2294940Snate@binkert.org#else
23011147Smitch.hayenga@arm.com
2312623SN/A#define TRACE_PACKET(A)
23211147Smitch.hayenga@arm.com
23311147Smitch.hayenga@arm.com#endif
23411147Smitch.hayenga@arm.com
23510464SAndreas.Sandberg@ARM.comTick
2363686Sktlim@umich.eduPhysicalMemory::doAtomicAccess(PacketPtr pkt)
23711147Smitch.hayenga@arm.com{
23811147Smitch.hayenga@arm.com    assert(pkt->getAddr() >= start() &&
23911147Smitch.hayenga@arm.com           pkt->getAddr() + pkt->getSize() <= start() + size());
24011147Smitch.hayenga@arm.com
2419342SAndreas.Sandberg@arm.com    if (pkt->memInhibitAsserted()) {
24211147Smitch.hayenga@arm.com        DPRINTF(MemoryAccess, "mem inhibited on 0x%x: not responding\n",
24311147Smitch.hayenga@arm.com                pkt->getAddr());
24411147Smitch.hayenga@arm.com        return 0;
24511147Smitch.hayenga@arm.com    }
24611526Sdavid.guillen@arm.com
24711526Sdavid.guillen@arm.com    uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start();
2482623SN/A
2492623SN/A    if (pkt->cmd == MemCmd::SwapReq) {
2502623SN/A        IntReg overwrite_val;
2512623SN/A        bool overwrite_mem;
2528737Skoansin.tan@gmail.com        uint64_t condition_val64;
2532623SN/A        uint32_t condition_val32;
2544940Snate@binkert.org
2554940Snate@binkert.org        assert(sizeof(IntReg) >= pkt->getSize());
25611147Smitch.hayenga@arm.com
25711147Smitch.hayenga@arm.com        overwrite_mem = true;
2582623SN/A        // keep a copy of our possible write value, and copy what is at the
2596043Sgblack@eecs.umich.edu        // memory address into the packet
2606043Sgblack@eecs.umich.edu        std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize());
2616043Sgblack@eecs.umich.edu        std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
2629342SAndreas.Sandberg@arm.com
2632626SN/A        if (pkt->req->isCondSwap()) {
26411147Smitch.hayenga@arm.com            if (pkt->getSize() == sizeof(uint64_t)) {
2652623SN/A                condition_val64 = pkt->req->getExtraData();
26611147Smitch.hayenga@arm.com                overwrite_mem = !std::memcmp(&condition_val64, hostAddr,
26711147Smitch.hayenga@arm.com                                             sizeof(uint64_t));
26811147Smitch.hayenga@arm.com            } else if (pkt->getSize() == sizeof(uint32_t)) {
26911147Smitch.hayenga@arm.com                condition_val32 = (uint32_t)pkt->req->getExtraData();
27011147Smitch.hayenga@arm.com                overwrite_mem = !std::memcmp(&condition_val32, hostAddr,
27111147Smitch.hayenga@arm.com                                             sizeof(uint32_t));
27211147Smitch.hayenga@arm.com            } else
27311147Smitch.hayenga@arm.com                panic("Invalid size for conditional read/write\n");
27411526Sdavid.guillen@arm.com        }
2752623SN/A
2762623SN/A        if (overwrite_mem)
27713012Sandreas.sandberg@arm.com            std::memcpy(hostAddr, &overwrite_val, pkt->getSize());
27813012Sandreas.sandberg@arm.com
27913012Sandreas.sandberg@arm.com        TRACE_PACKET("Read/Write");
28013012Sandreas.sandberg@arm.com    } else if (pkt->isRead()) {
28113012Sandreas.sandberg@arm.com        assert(!pkt->isWrite());
2822623SN/A        if (pkt->isLocked()) {
28310030SAli.Saidi@ARM.com            trackLoadLocked(pkt);
28410030SAli.Saidi@ARM.com        }
28510030SAli.Saidi@ARM.com        memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
28610030SAli.Saidi@ARM.com        TRACE_PACKET("Read");
28710030SAli.Saidi@ARM.com    } else if (pkt->isWrite()) {
28810030SAli.Saidi@ARM.com        if (writeOK(pkt)) {
28910529Smorr@cs.wisc.edu            memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
29010529Smorr@cs.wisc.edu            TRACE_PACKET("Write");
29111148Smitch.hayenga@arm.com        }
29211148Smitch.hayenga@arm.com    } else if (pkt->isInvalidate()) {
29311148Smitch.hayenga@arm.com        //upgrade or invalidate
29411151Smitch.hayenga@arm.com        if (pkt->needsResponse()) {
29511148Smitch.hayenga@arm.com            pkt->makeAtomicResponse();
29610529Smorr@cs.wisc.edu        }
29710529Smorr@cs.wisc.edu    } else {
29810030SAli.Saidi@ARM.com        panic("unimplemented");
29911356Skrinat01@arm.com    }
30011356Skrinat01@arm.com
30111356Skrinat01@arm.com    if (pkt->needsResponse()) {
30211356Skrinat01@arm.com        pkt->makeAtomicResponse();
30310030SAli.Saidi@ARM.com    }
30410030SAli.Saidi@ARM.com    return calculateLatency(pkt);
30511147Smitch.hayenga@arm.com}
30611147Smitch.hayenga@arm.com
30711147Smitch.hayenga@arm.com
30810030SAli.Saidi@ARM.comvoid
30910030SAli.Saidi@ARM.comPhysicalMemory::doFunctionalAccess(PacketPtr pkt)
31010030SAli.Saidi@ARM.com{
31110030SAli.Saidi@ARM.com    assert(pkt->getAddr() >= start() &&
31210030SAli.Saidi@ARM.com           pkt->getAddr() + pkt->getSize() <= start() + size());
31310030SAli.Saidi@ARM.com
31410030SAli.Saidi@ARM.com
31510030SAli.Saidi@ARM.com    uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start();
31610030SAli.Saidi@ARM.com
31710030SAli.Saidi@ARM.com    if (pkt->isRead()) {
31810030SAli.Saidi@ARM.com        memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
31910529Smorr@cs.wisc.edu        TRACE_PACKET("Read");
32010529Smorr@cs.wisc.edu        pkt->makeAtomicResponse();
32111148Smitch.hayenga@arm.com    } else if (pkt->isWrite()) {
32211321Ssteve.reinhardt@amd.com        memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
32311151Smitch.hayenga@arm.com        TRACE_PACKET("Write");
32411148Smitch.hayenga@arm.com        pkt->makeAtomicResponse();
32510529Smorr@cs.wisc.edu    } else if (pkt->isPrint()) {
32610529Smorr@cs.wisc.edu        Packet::PrintReqState *prs = dynamic_cast<Packet::PrintReqState*>(pkt->senderState);
32710030SAli.Saidi@ARM.com        prs->printLabels();
32810030SAli.Saidi@ARM.com        ccprintf(prs->os, "%s%#x\n", prs->curPrefix(), *hostAddr);
32910030SAli.Saidi@ARM.com    } else {
33010030SAli.Saidi@ARM.com        panic("PhysicalMemory: unimplemented functional command %s",
33111147Smitch.hayenga@arm.com              pkt->cmdString());
33211147Smitch.hayenga@arm.com    }
33311147Smitch.hayenga@arm.com}
33410030SAli.Saidi@ARM.com
33510030SAli.Saidi@ARM.com
33610030SAli.Saidi@ARM.comPort *
33713954Sgiacomo.gabrielli@arm.comPhysicalMemory::getPort(const std::string &if_name, int idx)
33813954Sgiacomo.gabrielli@arm.com{
33913954Sgiacomo.gabrielli@arm.com    // Accept request for "functional" port for backwards compatibility
34013954Sgiacomo.gabrielli@arm.com    // with places where this function is called from C++.  I'd prefer
34113954Sgiacomo.gabrielli@arm.com    // to move all these into Python someday.
34213954Sgiacomo.gabrielli@arm.com    if (if_name == "functional") {
34313954Sgiacomo.gabrielli@arm.com        return new MemoryPort(csprintf("%s-functional", name()), this);
34413954Sgiacomo.gabrielli@arm.com    }
34513954Sgiacomo.gabrielli@arm.com
34613954Sgiacomo.gabrielli@arm.com    if (if_name != "port") {
34713954Sgiacomo.gabrielli@arm.com        panic("PhysicalMemory::getPort: unknown port %s requested", if_name);
34813954Sgiacomo.gabrielli@arm.com    }
34913954Sgiacomo.gabrielli@arm.com
35013954Sgiacomo.gabrielli@arm.com    if (idx >= ports.size()) {
35113954Sgiacomo.gabrielli@arm.com        ports.resize(idx+1);
35213954Sgiacomo.gabrielli@arm.com    }
35313954Sgiacomo.gabrielli@arm.com
35413954Sgiacomo.gabrielli@arm.com    if (ports[idx] != NULL) {
35513954Sgiacomo.gabrielli@arm.com        panic("PhysicalMemory::getPort: port %d already assigned", idx);
35613954Sgiacomo.gabrielli@arm.com    }
35713954Sgiacomo.gabrielli@arm.com
35813954Sgiacomo.gabrielli@arm.com    MemoryPort *port =
35913954Sgiacomo.gabrielli@arm.com        new MemoryPort(csprintf("%s-port%d", name(), idx), this);
36013954Sgiacomo.gabrielli@arm.com
36113954Sgiacomo.gabrielli@arm.com    ports[idx] = port;
36213954Sgiacomo.gabrielli@arm.com    return port;
36313954Sgiacomo.gabrielli@arm.com}
36413954Sgiacomo.gabrielli@arm.com
36513954Sgiacomo.gabrielli@arm.com
36613954Sgiacomo.gabrielli@arm.comvoid
36713954Sgiacomo.gabrielli@arm.comPhysicalMemory::recvStatusChange(Port::Status status)
36813954Sgiacomo.gabrielli@arm.com{
36913954Sgiacomo.gabrielli@arm.com}
3702623SN/A
37111608Snikos.nikoleris@arm.comPhysicalMemory::MemoryPort::MemoryPort(const std::string &_name,
37213954Sgiacomo.gabrielli@arm.com                                       PhysicalMemory *_memory)
37313954Sgiacomo.gabrielli@arm.com    : SimpleTimingPort(_name), memory(_memory)
3742623SN/A{ }
37511147Smitch.hayenga@arm.com
37611147Smitch.hayenga@arm.comvoid
37711147Smitch.hayenga@arm.comPhysicalMemory::MemoryPort::recvStatusChange(Port::Status status)
3783169Sstever@eecs.umich.edu{
37912749Sgiacomo.travaglini@arm.com    memory->recvStatusChange(status);
3802623SN/A}
38110665SAli.Saidi@ARM.com
38210665SAli.Saidi@ARM.comvoid
3832623SN/APhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp,
3844999Sgblack@eecs.umich.edu                                                   bool &snoop)
3854999Sgblack@eecs.umich.edu{
38610024Sdam.sunwoo@arm.com    memory->getAddressRanges(resp, snoop);
38713954Sgiacomo.gabrielli@arm.com}
38813954Sgiacomo.gabrielli@arm.com
38913954Sgiacomo.gabrielli@arm.comvoid
39013954Sgiacomo.gabrielli@arm.comPhysicalMemory::getAddressRanges(AddrRangeList &resp, bool &snoop)
39113954Sgiacomo.gabrielli@arm.com{
39213954Sgiacomo.gabrielli@arm.com    snoop = false;
39313954Sgiacomo.gabrielli@arm.com    resp.clear();
3947520Sgblack@eecs.umich.edu    resp.push_back(RangeSize(start(), params()->range.size()));
39513954Sgiacomo.gabrielli@arm.com}
39613954Sgiacomo.gabrielli@arm.com
3974999Sgblack@eecs.umich.eduint
3984999Sgblack@eecs.umich.eduPhysicalMemory::MemoryPort::deviceBlockSize()
39913954Sgiacomo.gabrielli@arm.com{
40013954Sgiacomo.gabrielli@arm.com    return memory->deviceBlockSize();
40113954Sgiacomo.gabrielli@arm.com}
40213954Sgiacomo.gabrielli@arm.com
4034999Sgblack@eecs.umich.eduTick
4044999Sgblack@eecs.umich.eduPhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt)
40513954Sgiacomo.gabrielli@arm.com{
40613954Sgiacomo.gabrielli@arm.com    return memory->doAtomicAccess(pkt);
40710739Ssteve.reinhardt@amd.com}
4087520Sgblack@eecs.umich.edu
4094999Sgblack@eecs.umich.eduvoid
41013012Sandreas.sandberg@arm.comPhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt)
4114999Sgblack@eecs.umich.edu{
41213012Sandreas.sandberg@arm.com    pkt->pushLabel(memory->name());
41313012Sandreas.sandberg@arm.com
4144999Sgblack@eecs.umich.edu    if (!checkFunctional(pkt)) {
4154999Sgblack@eecs.umich.edu        // Default implementation of SimpleTimingPort::recvFunctional()
4165012Sgblack@eecs.umich.edu        // calls recvAtomic() and throws away the latency; we can save a
4174999Sgblack@eecs.umich.edu        // little here by just not calculating the latency.
4184999Sgblack@eecs.umich.edu        memory->doFunctionalAccess(pkt);
4196102Sgblack@eecs.umich.edu    }
4204999Sgblack@eecs.umich.edu
4214999Sgblack@eecs.umich.edu    pkt->popLabel();
4224968Sacolyte@umich.edu}
4234986Ssaidi@eecs.umich.edu
4244999Sgblack@eecs.umich.eduunsigned int
4256739Sgblack@eecs.umich.eduPhysicalMemory::drain(Event *de)
4266739Sgblack@eecs.umich.edu{
4276739Sgblack@eecs.umich.edu    int count = 0;
4286739Sgblack@eecs.umich.edu    for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) {
4296739Sgblack@eecs.umich.edu        count += (*pi)->drain(de);
4306739Sgblack@eecs.umich.edu    }
4316739Sgblack@eecs.umich.edu
4326739Sgblack@eecs.umich.edu    if (count)
43313954Sgiacomo.gabrielli@arm.com        changeState(Draining);
43413954Sgiacomo.gabrielli@arm.com    else
43510760Ssteve.reinhardt@amd.com        changeState(Drained);
4366078Sgblack@eecs.umich.edu    return count;
4376078Sgblack@eecs.umich.edu}
4386078Sgblack@eecs.umich.edu
4394999Sgblack@eecs.umich.eduvoid
4404968Sacolyte@umich.eduPhysicalMemory::serialize(ostream &os)
4413170Sstever@eecs.umich.edu{
4424999Sgblack@eecs.umich.edu    gzFile compressedMem;
44313954Sgiacomo.gabrielli@arm.com    string filename = name() + ".physmem";
4444999Sgblack@eecs.umich.edu
44513954Sgiacomo.gabrielli@arm.com    SERIALIZE_SCALAR(filename);
4464999Sgblack@eecs.umich.edu
4474999Sgblack@eecs.umich.edu    // write memory file
44813954Sgiacomo.gabrielli@arm.com    string thefile = Checkpoint::dir() + "/" + filename.c_str();
4492623SN/A    int fd = creat(thefile.c_str(), 0664);
4502623SN/A    if (fd < 0) {
4512623SN/A        perror("creat");
45211303Ssteve.reinhardt@amd.com        fatal("Can't open physical memory checkpoint file '%s'\n", filename);
45311608Snikos.nikoleris@arm.com    }
45413954Sgiacomo.gabrielli@arm.com
45513954Sgiacomo.gabrielli@arm.com    compressedMem = gzdopen(fd, "wb");
4562623SN/A    if (compressedMem == NULL)
45711147Smitch.hayenga@arm.com        fatal("Insufficient memory to allocate compression state for %s\n",
45811147Smitch.hayenga@arm.com                filename);
45910031SAli.Saidi@ARM.com
46010031SAli.Saidi@ARM.com    if (gzwrite(compressedMem, pmemAddr, params()->range.size()) !=
46110031SAli.Saidi@ARM.com        params()->range.size()) {
46210031SAli.Saidi@ARM.com        fatal("Write failed on physical memory checkpoint file '%s'\n",
46312355Snikos.nikoleris@arm.com              filename);
46410031SAli.Saidi@ARM.com    }
46510031SAli.Saidi@ARM.com
46610031SAli.Saidi@ARM.com    if (gzclose(compressedMem))
46710031SAli.Saidi@ARM.com        fatal("Close failed on physical memory checkpoint file '%s'\n",
4683169Sstever@eecs.umich.edu              filename);
46912749Sgiacomo.travaglini@arm.com}
4702623SN/A
47110665SAli.Saidi@ARM.comvoid
47210665SAli.Saidi@ARM.comPhysicalMemory::unserialize(Checkpoint *cp, const string &section)
4732623SN/A{
4744999Sgblack@eecs.umich.edu    gzFile compressedMem;
4754999Sgblack@eecs.umich.edu    long *tempPage;
47610024Sdam.sunwoo@arm.com    long *pmem_current;
47713954Sgiacomo.gabrielli@arm.com    uint64_t curSize;
47813954Sgiacomo.gabrielli@arm.com    uint32_t bytesRead;
47913954Sgiacomo.gabrielli@arm.com    const int chunkSize = 16384;
48013954Sgiacomo.gabrielli@arm.com
48113954Sgiacomo.gabrielli@arm.com
48213954Sgiacomo.gabrielli@arm.com    string filename;
48313954Sgiacomo.gabrielli@arm.com
48413954Sgiacomo.gabrielli@arm.com    UNSERIALIZE_SCALAR(filename);
48511321Ssteve.reinhardt@amd.com
48613954Sgiacomo.gabrielli@arm.com    filename = cp->cptDir + "/" + filename;
48713954Sgiacomo.gabrielli@arm.com
4884999Sgblack@eecs.umich.edu    // mmap memoryfile
4894999Sgblack@eecs.umich.edu    int fd = open(filename.c_str(), O_RDONLY);
49013954Sgiacomo.gabrielli@arm.com    if (fd < 0) {
49113954Sgiacomo.gabrielli@arm.com        perror("open");
49213954Sgiacomo.gabrielli@arm.com        fatal("Can't open physical memory checkpoint file '%s'", filename);
4934999Sgblack@eecs.umich.edu    }
4944999Sgblack@eecs.umich.edu
49513954Sgiacomo.gabrielli@arm.com    compressedMem = gzdopen(fd, "rb");
4964999Sgblack@eecs.umich.edu    if (compressedMem == NULL)
4974999Sgblack@eecs.umich.edu        fatal("Insufficient memory to allocate compression state for %s\n",
4986102Sgblack@eecs.umich.edu                filename);
49913954Sgiacomo.gabrielli@arm.com
50013954Sgiacomo.gabrielli@arm.com    // unmap file that was mmaped in the constructor
50113954Sgiacomo.gabrielli@arm.com    // This is done here to make sure that gzip and open don't muck with our
50213954Sgiacomo.gabrielli@arm.com    // nice large space of memory before we reallocate it
5034999Sgblack@eecs.umich.edu    munmap((char*)pmemAddr, params()->range.size());
50413954Sgiacomo.gabrielli@arm.com
5054999Sgblack@eecs.umich.edu    pmemAddr = (uint8_t *)mmap(NULL, params()->range.size(),
5064999Sgblack@eecs.umich.edu        PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
5074999Sgblack@eecs.umich.edu
5084999Sgblack@eecs.umich.edu    if (pmemAddr == (void *)MAP_FAILED) {
5094999Sgblack@eecs.umich.edu        perror("mmap");
5104999Sgblack@eecs.umich.edu        fatal("Could not mmap physical memory!\n");
5116623Sgblack@eecs.umich.edu    }
51212355Snikos.nikoleris@arm.com
5137520Sgblack@eecs.umich.edu    curSize = 0;
5144999Sgblack@eecs.umich.edu    tempPage = (long*)malloc(chunkSize);
5158105Sgblack@eecs.umich.edu    if (tempPage == NULL)
5164999Sgblack@eecs.umich.edu        fatal("Unable to malloc memory to read file %s\n", filename);
5174999Sgblack@eecs.umich.edu
5184999Sgblack@eecs.umich.edu    /* Only copy bytes that are non-zero, so we don't give the VM system hell */
51913012Sandreas.sandberg@arm.com    while (curSize < params()->range.size()) {
52011148Smitch.hayenga@arm.com        bytesRead = gzread(compressedMem, tempPage, chunkSize);
52111148Smitch.hayenga@arm.com        if (bytesRead != chunkSize &&
52211148Smitch.hayenga@arm.com            bytesRead != params()->range.size() - curSize)
5234999Sgblack@eecs.umich.edu            fatal("Read failed on physical memory checkpoint file '%s'"
5244999Sgblack@eecs.umich.edu                  " got %d bytes, expected %d or %d bytes\n",
5254999Sgblack@eecs.umich.edu                  filename, bytesRead, chunkSize,
5264999Sgblack@eecs.umich.edu                  params()->range.size() - curSize);
5274999Sgblack@eecs.umich.edu
52813954Sgiacomo.gabrielli@arm.com        assert(bytesRead % sizeof(long) == 0);
52913954Sgiacomo.gabrielli@arm.com
5304999Sgblack@eecs.umich.edu        for (int x = 0; x < bytesRead/sizeof(long); x++)
5314999Sgblack@eecs.umich.edu        {
5324999Sgblack@eecs.umich.edu             if (*(tempPage+x) != 0) {
5334999Sgblack@eecs.umich.edu                 pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long));
5344999Sgblack@eecs.umich.edu                 *pmem_current = *(tempPage+x);
5354878Sstever@eecs.umich.edu             }
5364040Ssaidi@eecs.umich.edu        }
5374040Ssaidi@eecs.umich.edu        curSize += bytesRead;
5384999Sgblack@eecs.umich.edu    }
5394999Sgblack@eecs.umich.edu
54013954Sgiacomo.gabrielli@arm.com    free(tempPage);
5414999Sgblack@eecs.umich.edu
54210760Ssteve.reinhardt@amd.com    if (gzclose(compressedMem))
54313954Sgiacomo.gabrielli@arm.com        fatal("Close failed on physical memory checkpoint file '%s'\n",
5446078Sgblack@eecs.umich.edu              filename);
5456078Sgblack@eecs.umich.edu
54611147Smitch.hayenga@arm.com}
5476739Sgblack@eecs.umich.edu
5486739Sgblack@eecs.umich.eduPhysicalMemory *
5496739Sgblack@eecs.umich.eduPhysicalMemoryParams::create()
5506739Sgblack@eecs.umich.edu{
5516739Sgblack@eecs.umich.edu    return new PhysicalMemory(this);
5523170Sstever@eecs.umich.edu}
5533170Sstever@eecs.umich.edu