physical.cc revision 8799:dac1e33e07b0
110259SAndrew.Bardsley@arm.com/*
210259SAndrew.Bardsley@arm.com * Copyright (c) 2010-2011 ARM Limited
310259SAndrew.Bardsley@arm.com * All rights reserved
410259SAndrew.Bardsley@arm.com *
510259SAndrew.Bardsley@arm.com * The license below extends only to copyright in the software and shall
610259SAndrew.Bardsley@arm.com * not be construed as granting a license to any other intellectual
710259SAndrew.Bardsley@arm.com * property including but not limited to intellectual property relating
810259SAndrew.Bardsley@arm.com * to a hardware implementation of the functionality of the software
910259SAndrew.Bardsley@arm.com * licensed hereunder.  You may use the software subject to the license
1010259SAndrew.Bardsley@arm.com * terms below provided that you ensure that this notice is replicated
1110259SAndrew.Bardsley@arm.com * unmodified and in its entirety in all distributions of the software,
1210259SAndrew.Bardsley@arm.com * modified or unmodified, in source code or in binary form.
1310259SAndrew.Bardsley@arm.com *
1410259SAndrew.Bardsley@arm.com * Copyright (c) 2001-2005 The Regents of The University of Michigan
1510259SAndrew.Bardsley@arm.com * All rights reserved.
1610259SAndrew.Bardsley@arm.com *
1710259SAndrew.Bardsley@arm.com * Redistribution and use in source and binary forms, with or without
1810259SAndrew.Bardsley@arm.com * modification, are permitted provided that the following conditions are
1910259SAndrew.Bardsley@arm.com * met: redistributions of source code must retain the above copyright
2010259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer;
2110259SAndrew.Bardsley@arm.com * redistributions in binary form must reproduce the above copyright
2210259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer in the
2310259SAndrew.Bardsley@arm.com * documentation and/or other materials provided with the distribution;
2410259SAndrew.Bardsley@arm.com * neither the name of the copyright holders nor the names of its
2510259SAndrew.Bardsley@arm.com * contributors may be used to endorse or promote products derived from
2610259SAndrew.Bardsley@arm.com * this software without specific prior written permission.
2710259SAndrew.Bardsley@arm.com *
2810259SAndrew.Bardsley@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2910259SAndrew.Bardsley@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3010259SAndrew.Bardsley@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3110259SAndrew.Bardsley@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3210259SAndrew.Bardsley@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3310259SAndrew.Bardsley@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3410259SAndrew.Bardsley@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3510259SAndrew.Bardsley@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3610259SAndrew.Bardsley@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3710259SAndrew.Bardsley@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3810259SAndrew.Bardsley@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3910259SAndrew.Bardsley@arm.com *
4010259SAndrew.Bardsley@arm.com * Authors: Ron Dreslinski
4110259SAndrew.Bardsley@arm.com *          Ali Saidi
4210259SAndrew.Bardsley@arm.com */
4310259SAndrew.Bardsley@arm.com
4410259SAndrew.Bardsley@arm.com#include <sys/mman.h>
4510259SAndrew.Bardsley@arm.com#include <sys/types.h>
4610259SAndrew.Bardsley@arm.com#include <sys/user.h>
4710259SAndrew.Bardsley@arm.com#include <fcntl.h>
4810259SAndrew.Bardsley@arm.com#include <unistd.h>
4910259SAndrew.Bardsley@arm.com#include <zlib.h>
5010259SAndrew.Bardsley@arm.com
5110259SAndrew.Bardsley@arm.com#include <cerrno>
5210259SAndrew.Bardsley@arm.com#include <cstdio>
5310259SAndrew.Bardsley@arm.com#include <iostream>
5410259SAndrew.Bardsley@arm.com#include <string>
5510259SAndrew.Bardsley@arm.com
5610259SAndrew.Bardsley@arm.com#include "arch/isa_traits.hh"
5710259SAndrew.Bardsley@arm.com#include "arch/registers.hh"
5810259SAndrew.Bardsley@arm.com#include "base/intmath.hh"
5910259SAndrew.Bardsley@arm.com#include "base/misc.hh"
6010259SAndrew.Bardsley@arm.com#include "base/random.hh"
6110259SAndrew.Bardsley@arm.com#include "base/types.hh"
6210259SAndrew.Bardsley@arm.com#include "config/the_isa.hh"
6310259SAndrew.Bardsley@arm.com#include "debug/LLSC.hh"
6410259SAndrew.Bardsley@arm.com#include "debug/MemoryAccess.hh"
6510259SAndrew.Bardsley@arm.com#include "mem/packet_access.hh"
6610259SAndrew.Bardsley@arm.com#include "mem/physical.hh"
6710259SAndrew.Bardsley@arm.com#include "sim/eventq.hh"
6810259SAndrew.Bardsley@arm.com
6910259SAndrew.Bardsley@arm.comusing namespace std;
7010259SAndrew.Bardsley@arm.comusing namespace TheISA;
7110259SAndrew.Bardsley@arm.com
7210259SAndrew.Bardsley@arm.comPhysicalMemory::PhysicalMemory(const Params *p)
7310259SAndrew.Bardsley@arm.com    : MemObject(p), pmemAddr(NULL), lat(p->latency), lat_var(p->latency_var),
7410259SAndrew.Bardsley@arm.com      _size(params()->range.size()), _start(params()->range.start)
7510259SAndrew.Bardsley@arm.com{
7610259SAndrew.Bardsley@arm.com    if (size() % TheISA::PageBytes != 0)
7710259SAndrew.Bardsley@arm.com        panic("Memory Size not divisible by page size\n");
7810259SAndrew.Bardsley@arm.com
7910259SAndrew.Bardsley@arm.com    if (params()->null)
8010259SAndrew.Bardsley@arm.com        return;
8110259SAndrew.Bardsley@arm.com
8210259SAndrew.Bardsley@arm.com
8310259SAndrew.Bardsley@arm.com    if (params()->file == "") {
8410259SAndrew.Bardsley@arm.com        int map_flags = MAP_ANON | MAP_PRIVATE;
8510259SAndrew.Bardsley@arm.com        pmemAddr = (uint8_t *)mmap(NULL, size(),
8610259SAndrew.Bardsley@arm.com                                   PROT_READ | PROT_WRITE, map_flags, -1, 0);
8710259SAndrew.Bardsley@arm.com    } else {
8810259SAndrew.Bardsley@arm.com        int map_flags = MAP_PRIVATE;
8910259SAndrew.Bardsley@arm.com        int fd = open(params()->file.c_str(), O_RDONLY);
9010259SAndrew.Bardsley@arm.com        _size = lseek(fd, 0, SEEK_END);
9110259SAndrew.Bardsley@arm.com        lseek(fd, 0, SEEK_SET);
9210259SAndrew.Bardsley@arm.com        pmemAddr = (uint8_t *)mmap(NULL, roundUp(size(), sysconf(_SC_PAGESIZE)),
9310259SAndrew.Bardsley@arm.com                                   PROT_READ | PROT_WRITE, map_flags, fd, 0);
9410259SAndrew.Bardsley@arm.com    }
9510259SAndrew.Bardsley@arm.com
9610259SAndrew.Bardsley@arm.com    if (pmemAddr == (void *)MAP_FAILED) {
9710259SAndrew.Bardsley@arm.com        perror("mmap");
9810259SAndrew.Bardsley@arm.com        if (params()->file == "")
9910259SAndrew.Bardsley@arm.com            fatal("Could not mmap!\n");
10010259SAndrew.Bardsley@arm.com        else
10110259SAndrew.Bardsley@arm.com            fatal("Could not find file: %s\n", params()->file);
10210259SAndrew.Bardsley@arm.com    }
10310259SAndrew.Bardsley@arm.com
10410259SAndrew.Bardsley@arm.com    //If requested, initialize all the memory to 0
10510259SAndrew.Bardsley@arm.com    if (p->zero)
10610259SAndrew.Bardsley@arm.com        memset(pmemAddr, 0, size());
10710259SAndrew.Bardsley@arm.com}
10810259SAndrew.Bardsley@arm.com
10910259SAndrew.Bardsley@arm.comvoid
11010259SAndrew.Bardsley@arm.comPhysicalMemory::init()
11110259SAndrew.Bardsley@arm.com{
11210259SAndrew.Bardsley@arm.com    if (ports.size() == 0) {
11310259SAndrew.Bardsley@arm.com        fatal("PhysicalMemory object %s is unconnected!", name());
11410259SAndrew.Bardsley@arm.com    }
11510259SAndrew.Bardsley@arm.com
11610259SAndrew.Bardsley@arm.com    for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) {
11710259SAndrew.Bardsley@arm.com        if (*pi)
11810259SAndrew.Bardsley@arm.com            (*pi)->sendRangeChange();
11910259SAndrew.Bardsley@arm.com    }
12010259SAndrew.Bardsley@arm.com}
12110259SAndrew.Bardsley@arm.com
12210259SAndrew.Bardsley@arm.comPhysicalMemory::~PhysicalMemory()
12310259SAndrew.Bardsley@arm.com{
12410259SAndrew.Bardsley@arm.com    if (pmemAddr)
12510259SAndrew.Bardsley@arm.com        munmap((char*)pmemAddr, size());
12610259SAndrew.Bardsley@arm.com}
12710259SAndrew.Bardsley@arm.com
12810259SAndrew.Bardsley@arm.comvoid
12910259SAndrew.Bardsley@arm.comPhysicalMemory::regStats()
13010259SAndrew.Bardsley@arm.com{
13110259SAndrew.Bardsley@arm.com    using namespace Stats;
13210259SAndrew.Bardsley@arm.com
13310259SAndrew.Bardsley@arm.com    bytesRead
13410259SAndrew.Bardsley@arm.com        .name(name() + ".bytes_read")
13510259SAndrew.Bardsley@arm.com        .desc("Number of bytes read from this memory")
13610259SAndrew.Bardsley@arm.com        ;
13710259SAndrew.Bardsley@arm.com    bytesInstRead
13810259SAndrew.Bardsley@arm.com        .name(name() + ".bytes_inst_read")
13910259SAndrew.Bardsley@arm.com        .desc("Number of instructions bytes read from this memory")
14010259SAndrew.Bardsley@arm.com        ;
14110259SAndrew.Bardsley@arm.com    bytesWritten
14210259SAndrew.Bardsley@arm.com        .name(name() + ".bytes_written")
14310259SAndrew.Bardsley@arm.com        .desc("Number of bytes written to this memory")
14410259SAndrew.Bardsley@arm.com        ;
14510259SAndrew.Bardsley@arm.com    numReads
14610259SAndrew.Bardsley@arm.com        .name(name() + ".num_reads")
14710259SAndrew.Bardsley@arm.com        .desc("Number of read requests responded to by this memory")
14810259SAndrew.Bardsley@arm.com        ;
14910259SAndrew.Bardsley@arm.com    numWrites
15010259SAndrew.Bardsley@arm.com        .name(name() + ".num_writes")
15110259SAndrew.Bardsley@arm.com        .desc("Number of write requests responded to by this memory")
15210259SAndrew.Bardsley@arm.com        ;
15310814Sandreas.hansson@arm.com    numOther
15410259SAndrew.Bardsley@arm.com        .name(name() + ".num_other")
15510259SAndrew.Bardsley@arm.com        .desc("Number of other requests responded to by this memory")
15610259SAndrew.Bardsley@arm.com        ;
15710259SAndrew.Bardsley@arm.com    bwRead
15810259SAndrew.Bardsley@arm.com        .name(name() + ".bw_read")
15910259SAndrew.Bardsley@arm.com        .desc("Total read bandwidth from this memory (bytes/s)")
16010259SAndrew.Bardsley@arm.com        .precision(0)
16110259SAndrew.Bardsley@arm.com        .prereq(bytesRead)
16210259SAndrew.Bardsley@arm.com        ;
16310259SAndrew.Bardsley@arm.com    bwInstRead
16410259SAndrew.Bardsley@arm.com        .name(name() + ".bw_inst_read")
16510259SAndrew.Bardsley@arm.com        .desc("Instruction read bandwidth from this memory (bytes/s)")
16610259SAndrew.Bardsley@arm.com        .precision(0)
16710259SAndrew.Bardsley@arm.com        .prereq(bytesInstRead)
16810259SAndrew.Bardsley@arm.com        ;
16910259SAndrew.Bardsley@arm.com    bwWrite
17010259SAndrew.Bardsley@arm.com        .name(name() + ".bw_write")
17110259SAndrew.Bardsley@arm.com        .desc("Write bandwidth from this memory (bytes/s)")
17210259SAndrew.Bardsley@arm.com        .precision(0)
17310259SAndrew.Bardsley@arm.com        .prereq(bytesWritten)
17410259SAndrew.Bardsley@arm.com        ;
17510259SAndrew.Bardsley@arm.com    bwTotal
17610259SAndrew.Bardsley@arm.com        .name(name() + ".bw_total")
17710259SAndrew.Bardsley@arm.com        .desc("Total bandwidth to/from this memory (bytes/s)")
17810259SAndrew.Bardsley@arm.com        .precision(0)
17910259SAndrew.Bardsley@arm.com        .prereq(bwTotal)
18010259SAndrew.Bardsley@arm.com        ;
18110259SAndrew.Bardsley@arm.com    bwRead = bytesRead / simSeconds;
18210259SAndrew.Bardsley@arm.com    bwInstRead = bytesInstRead / simSeconds;
18310259SAndrew.Bardsley@arm.com    bwWrite = bytesWritten / simSeconds;
18410259SAndrew.Bardsley@arm.com    bwTotal = (bytesRead + bytesWritten) / simSeconds;
18510259SAndrew.Bardsley@arm.com}
18610259SAndrew.Bardsley@arm.com
18710259SAndrew.Bardsley@arm.comunsigned
18810259SAndrew.Bardsley@arm.comPhysicalMemory::deviceBlockSize() const
18910259SAndrew.Bardsley@arm.com{
19010259SAndrew.Bardsley@arm.com    //Can accept anysize request
19110259SAndrew.Bardsley@arm.com    return 0;
19210259SAndrew.Bardsley@arm.com}
19310259SAndrew.Bardsley@arm.com
19410259SAndrew.Bardsley@arm.comTick
19510259SAndrew.Bardsley@arm.comPhysicalMemory::calculateLatency(PacketPtr pkt)
19610259SAndrew.Bardsley@arm.com{
19710259SAndrew.Bardsley@arm.com    Tick latency = lat;
19810259SAndrew.Bardsley@arm.com    if (lat_var != 0)
19910259SAndrew.Bardsley@arm.com        latency += random_mt.random<Tick>(0, lat_var);
20010259SAndrew.Bardsley@arm.com    return latency;
20110259SAndrew.Bardsley@arm.com}
20210259SAndrew.Bardsley@arm.com
20310259SAndrew.Bardsley@arm.com
20410259SAndrew.Bardsley@arm.com
20510259SAndrew.Bardsley@arm.com// Add load-locked to tracking list.  Should only be called if the
20610259SAndrew.Bardsley@arm.com// operation is a load and the LLSC flag is set.
20710259SAndrew.Bardsley@arm.comvoid
20810259SAndrew.Bardsley@arm.comPhysicalMemory::trackLoadLocked(PacketPtr pkt)
20910259SAndrew.Bardsley@arm.com{
21010259SAndrew.Bardsley@arm.com    Request *req = pkt->req;
21110259SAndrew.Bardsley@arm.com    Addr paddr = LockedAddr::mask(req->getPaddr());
21210259SAndrew.Bardsley@arm.com
21310259SAndrew.Bardsley@arm.com    // first we check if we already have a locked addr for this
21410259SAndrew.Bardsley@arm.com    // xc.  Since each xc only gets one, we just update the
21510259SAndrew.Bardsley@arm.com    // existing record with the new address.
21610259SAndrew.Bardsley@arm.com    list<LockedAddr>::iterator i;
21710259SAndrew.Bardsley@arm.com
21810259SAndrew.Bardsley@arm.com    for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) {
21910259SAndrew.Bardsley@arm.com        if (i->matchesContext(req)) {
22010259SAndrew.Bardsley@arm.com            DPRINTF(LLSC, "Modifying lock record: context %d addr %#x\n",
22110259SAndrew.Bardsley@arm.com                    req->contextId(), paddr);
22210259SAndrew.Bardsley@arm.com            i->addr = paddr;
22310259SAndrew.Bardsley@arm.com            return;
22410259SAndrew.Bardsley@arm.com        }
22510259SAndrew.Bardsley@arm.com    }
22610259SAndrew.Bardsley@arm.com
22710259SAndrew.Bardsley@arm.com    // no record for this xc: need to allocate a new one
22810259SAndrew.Bardsley@arm.com    DPRINTF(LLSC, "Adding lock record: context %d addr %#x\n",
22910259SAndrew.Bardsley@arm.com            req->contextId(), paddr);
23010259SAndrew.Bardsley@arm.com    lockedAddrList.push_front(LockedAddr(req));
23110259SAndrew.Bardsley@arm.com}
23210259SAndrew.Bardsley@arm.com
23310259SAndrew.Bardsley@arm.com
23410259SAndrew.Bardsley@arm.com// Called on *writes* only... both regular stores and
23510259SAndrew.Bardsley@arm.com// store-conditional operations.  Check for conventional stores which
23610259SAndrew.Bardsley@arm.com// conflict with locked addresses, and for success/failure of store
23710259SAndrew.Bardsley@arm.com// conditionals.
23810259SAndrew.Bardsley@arm.combool
23910259SAndrew.Bardsley@arm.comPhysicalMemory::checkLockedAddrList(PacketPtr pkt)
24010259SAndrew.Bardsley@arm.com{
24110259SAndrew.Bardsley@arm.com    Request *req = pkt->req;
24210259SAndrew.Bardsley@arm.com    Addr paddr = LockedAddr::mask(req->getPaddr());
24310259SAndrew.Bardsley@arm.com    bool isLLSC = pkt->isLLSC();
24410259SAndrew.Bardsley@arm.com
24510259SAndrew.Bardsley@arm.com    // Initialize return value.  Non-conditional stores always
24610259SAndrew.Bardsley@arm.com    // succeed.  Assume conditional stores will fail until proven
24710259SAndrew.Bardsley@arm.com    // otherwise.
24810259SAndrew.Bardsley@arm.com    bool success = !isLLSC;
24910259SAndrew.Bardsley@arm.com
25010259SAndrew.Bardsley@arm.com    // Iterate over list.  Note that there could be multiple matching
25110259SAndrew.Bardsley@arm.com    // records, as more than one context could have done a load locked
25210259SAndrew.Bardsley@arm.com    // to this location.
25310259SAndrew.Bardsley@arm.com    list<LockedAddr>::iterator i = lockedAddrList.begin();
25410259SAndrew.Bardsley@arm.com
25510259SAndrew.Bardsley@arm.com    while (i != lockedAddrList.end()) {
25610259SAndrew.Bardsley@arm.com
25710259SAndrew.Bardsley@arm.com        if (i->addr == paddr) {
25810259SAndrew.Bardsley@arm.com            // we have a matching address
25910259SAndrew.Bardsley@arm.com
26010259SAndrew.Bardsley@arm.com            if (isLLSC && i->matchesContext(req)) {
26110259SAndrew.Bardsley@arm.com                // it's a store conditional, and as far as the memory
26210366Sandreas.hansson@arm.com                // system can tell, the requesting context's lock is
26310366Sandreas.hansson@arm.com                // still valid.
26410366Sandreas.hansson@arm.com                DPRINTF(LLSC, "StCond success: context %d addr %#x\n",
26510259SAndrew.Bardsley@arm.com                        req->contextId(), paddr);
26610259SAndrew.Bardsley@arm.com                success = true;
26710259SAndrew.Bardsley@arm.com            }
26810259SAndrew.Bardsley@arm.com
26910259SAndrew.Bardsley@arm.com            // Get rid of our record of this lock and advance to next
27010259SAndrew.Bardsley@arm.com            DPRINTF(LLSC, "Erasing lock record: context %d addr %#x\n",
27110259SAndrew.Bardsley@arm.com                    i->contextId, paddr);
27210259SAndrew.Bardsley@arm.com            i = lockedAddrList.erase(i);
27310259SAndrew.Bardsley@arm.com        }
27410259SAndrew.Bardsley@arm.com        else {
27510259SAndrew.Bardsley@arm.com            // no match: advance to next record
27610259SAndrew.Bardsley@arm.com            ++i;
27710259SAndrew.Bardsley@arm.com        }
27810259SAndrew.Bardsley@arm.com    }
27910259SAndrew.Bardsley@arm.com
28010259SAndrew.Bardsley@arm.com    if (isLLSC) {
28110259SAndrew.Bardsley@arm.com        req->setExtraData(success ? 1 : 0);
28210259SAndrew.Bardsley@arm.com    }
28310259SAndrew.Bardsley@arm.com
28410259SAndrew.Bardsley@arm.com    return success;
28510259SAndrew.Bardsley@arm.com}
28610259SAndrew.Bardsley@arm.com
28710259SAndrew.Bardsley@arm.com
28810259SAndrew.Bardsley@arm.com#if TRACING_ON
28910259SAndrew.Bardsley@arm.com
29010259SAndrew.Bardsley@arm.com#define CASE(A, T)                                                      \
29110259SAndrew.Bardsley@arm.com  case sizeof(T):                                                       \
29210259SAndrew.Bardsley@arm.com    DPRINTF(MemoryAccess,"%s of size %i on address 0x%x data 0x%x\n",   \
29310259SAndrew.Bardsley@arm.com            A, pkt->getSize(), pkt->getAddr(), pkt->get<T>());          \
29410259SAndrew.Bardsley@arm.com  break
29510259SAndrew.Bardsley@arm.com
29610259SAndrew.Bardsley@arm.com
29710259SAndrew.Bardsley@arm.com#define TRACE_PACKET(A)                                                 \
29810259SAndrew.Bardsley@arm.com    do {                                                                \
29910259SAndrew.Bardsley@arm.com        switch (pkt->getSize()) {                                       \
30010259SAndrew.Bardsley@arm.com          CASE(A, uint64_t);                                            \
30110259SAndrew.Bardsley@arm.com          CASE(A, uint32_t);                                            \
30210259SAndrew.Bardsley@arm.com          CASE(A, uint16_t);                                            \
30310259SAndrew.Bardsley@arm.com          CASE(A, uint8_t);                                             \
30410259SAndrew.Bardsley@arm.com          default:                                                      \
30510259SAndrew.Bardsley@arm.com            DPRINTF(MemoryAccess, "%s of size %i on address 0x%x\n",    \
30610259SAndrew.Bardsley@arm.com                    A, pkt->getSize(), pkt->getAddr());                 \
30710259SAndrew.Bardsley@arm.com            DDUMP(MemoryAccess, pkt->getPtr<uint8_t>(), pkt->getSize());\
30810259SAndrew.Bardsley@arm.com        }                                                               \
30910259SAndrew.Bardsley@arm.com    } while (0)
31010259SAndrew.Bardsley@arm.com
31110259SAndrew.Bardsley@arm.com#else
31210259SAndrew.Bardsley@arm.com
31310259SAndrew.Bardsley@arm.com#define TRACE_PACKET(A)
31410259SAndrew.Bardsley@arm.com
31510259SAndrew.Bardsley@arm.com#endif
31610259SAndrew.Bardsley@arm.com
31710259SAndrew.Bardsley@arm.comTick
31810259SAndrew.Bardsley@arm.comPhysicalMemory::doAtomicAccess(PacketPtr pkt)
31910259SAndrew.Bardsley@arm.com{
32010259SAndrew.Bardsley@arm.com    assert(pkt->getAddr() >= start() &&
32110259SAndrew.Bardsley@arm.com           pkt->getAddr() + pkt->getSize() <= start() + size());
32210259SAndrew.Bardsley@arm.com
32310259SAndrew.Bardsley@arm.com    if (pkt->memInhibitAsserted()) {
32410259SAndrew.Bardsley@arm.com        DPRINTF(MemoryAccess, "mem inhibited on 0x%x: not responding\n",
32510259SAndrew.Bardsley@arm.com                pkt->getAddr());
32610259SAndrew.Bardsley@arm.com        return 0;
32710259SAndrew.Bardsley@arm.com    }
32810259SAndrew.Bardsley@arm.com
32910259SAndrew.Bardsley@arm.com    uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start();
33010259SAndrew.Bardsley@arm.com
33110259SAndrew.Bardsley@arm.com    if (pkt->cmd == MemCmd::SwapReq) {
33210259SAndrew.Bardsley@arm.com        IntReg overwrite_val;
33310259SAndrew.Bardsley@arm.com        bool overwrite_mem;
33410259SAndrew.Bardsley@arm.com        uint64_t condition_val64;
33510259SAndrew.Bardsley@arm.com        uint32_t condition_val32;
33610259SAndrew.Bardsley@arm.com
33710259SAndrew.Bardsley@arm.com        if (!pmemAddr)
33810259SAndrew.Bardsley@arm.com            panic("Swap only works if there is real memory (i.e. null=False)");
33910259SAndrew.Bardsley@arm.com        assert(sizeof(IntReg) >= pkt->getSize());
34010259SAndrew.Bardsley@arm.com
34110259SAndrew.Bardsley@arm.com        overwrite_mem = true;
34210259SAndrew.Bardsley@arm.com        // keep a copy of our possible write value, and copy what is at the
34310259SAndrew.Bardsley@arm.com        // memory address into the packet
34410259SAndrew.Bardsley@arm.com        std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize());
34510259SAndrew.Bardsley@arm.com        std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
34610259SAndrew.Bardsley@arm.com
34710259SAndrew.Bardsley@arm.com        if (pkt->req->isCondSwap()) {
34810259SAndrew.Bardsley@arm.com            if (pkt->getSize() == sizeof(uint64_t)) {
34910259SAndrew.Bardsley@arm.com                condition_val64 = pkt->req->getExtraData();
35010259SAndrew.Bardsley@arm.com                overwrite_mem = !std::memcmp(&condition_val64, hostAddr,
35110259SAndrew.Bardsley@arm.com                                             sizeof(uint64_t));
35210259SAndrew.Bardsley@arm.com            } else if (pkt->getSize() == sizeof(uint32_t)) {
35310259SAndrew.Bardsley@arm.com                condition_val32 = (uint32_t)pkt->req->getExtraData();
35410259SAndrew.Bardsley@arm.com                overwrite_mem = !std::memcmp(&condition_val32, hostAddr,
35510259SAndrew.Bardsley@arm.com                                             sizeof(uint32_t));
35610259SAndrew.Bardsley@arm.com            } else
35710259SAndrew.Bardsley@arm.com                panic("Invalid size for conditional read/write\n");
35810563Sandreas.hansson@arm.com        }
35910259SAndrew.Bardsley@arm.com
36010259SAndrew.Bardsley@arm.com        if (overwrite_mem)
36110259SAndrew.Bardsley@arm.com            std::memcpy(hostAddr, &overwrite_val, pkt->getSize());
36210259SAndrew.Bardsley@arm.com
36310259SAndrew.Bardsley@arm.com        assert(!pkt->req->isInstFetch());
36410259SAndrew.Bardsley@arm.com        TRACE_PACKET("Read/Write");
36510259SAndrew.Bardsley@arm.com        numOther++;
36610259SAndrew.Bardsley@arm.com    } else if (pkt->isRead()) {
36710259SAndrew.Bardsley@arm.com        assert(!pkt->isWrite());
36810259SAndrew.Bardsley@arm.com        if (pkt->isLLSC()) {
36910259SAndrew.Bardsley@arm.com            trackLoadLocked(pkt);
37010259SAndrew.Bardsley@arm.com        }
37110259SAndrew.Bardsley@arm.com        if (pmemAddr)
37210259SAndrew.Bardsley@arm.com            memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
37310259SAndrew.Bardsley@arm.com        TRACE_PACKET(pkt->req->isInstFetch() ? "IFetch" : "Read");
37410259SAndrew.Bardsley@arm.com        numReads++;
37510259SAndrew.Bardsley@arm.com        bytesRead += pkt->getSize();
37610259SAndrew.Bardsley@arm.com        if (pkt->req->isInstFetch())
37710259SAndrew.Bardsley@arm.com            bytesInstRead += pkt->getSize();
37810259SAndrew.Bardsley@arm.com    } else if (pkt->isWrite()) {
37910259SAndrew.Bardsley@arm.com        if (writeOK(pkt)) {
38010259SAndrew.Bardsley@arm.com            if (pmemAddr)
38110259SAndrew.Bardsley@arm.com                memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
38210259SAndrew.Bardsley@arm.com            assert(!pkt->req->isInstFetch());
38310259SAndrew.Bardsley@arm.com            TRACE_PACKET("Write");
38410259SAndrew.Bardsley@arm.com            numWrites++;
38510259SAndrew.Bardsley@arm.com            bytesWritten += pkt->getSize();
38610259SAndrew.Bardsley@arm.com        }
38710259SAndrew.Bardsley@arm.com    } else if (pkt->isInvalidate()) {
38810259SAndrew.Bardsley@arm.com        //upgrade or invalidate
38910259SAndrew.Bardsley@arm.com        if (pkt->needsResponse()) {
39010259SAndrew.Bardsley@arm.com            pkt->makeAtomicResponse();
39110259SAndrew.Bardsley@arm.com        }
39210259SAndrew.Bardsley@arm.com    } else {
39310259SAndrew.Bardsley@arm.com        panic("unimplemented");
39410259SAndrew.Bardsley@arm.com    }
39510259SAndrew.Bardsley@arm.com
39610259SAndrew.Bardsley@arm.com    if (pkt->needsResponse()) {
39710259SAndrew.Bardsley@arm.com        pkt->makeAtomicResponse();
39810259SAndrew.Bardsley@arm.com    }
39910259SAndrew.Bardsley@arm.com    return calculateLatency(pkt);
40010259SAndrew.Bardsley@arm.com}
40110259SAndrew.Bardsley@arm.com
40210259SAndrew.Bardsley@arm.com
40310259SAndrew.Bardsley@arm.comvoid
40410259SAndrew.Bardsley@arm.comPhysicalMemory::doFunctionalAccess(PacketPtr pkt)
40510259SAndrew.Bardsley@arm.com{
40610259SAndrew.Bardsley@arm.com    assert(pkt->getAddr() >= start() &&
40710259SAndrew.Bardsley@arm.com           pkt->getAddr() + pkt->getSize() <= start() + size());
40810259SAndrew.Bardsley@arm.com
40910259SAndrew.Bardsley@arm.com
41010259SAndrew.Bardsley@arm.com    uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start();
41110259SAndrew.Bardsley@arm.com
41210259SAndrew.Bardsley@arm.com    if (pkt->isRead()) {
41310259SAndrew.Bardsley@arm.com        if (pmemAddr)
41410259SAndrew.Bardsley@arm.com            memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
41510259SAndrew.Bardsley@arm.com        TRACE_PACKET("Read");
41610259SAndrew.Bardsley@arm.com        pkt->makeAtomicResponse();
41710259SAndrew.Bardsley@arm.com    } else if (pkt->isWrite()) {
41810259SAndrew.Bardsley@arm.com        if (pmemAddr)
41910259SAndrew.Bardsley@arm.com            memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
42010259SAndrew.Bardsley@arm.com        TRACE_PACKET("Write");
42110259SAndrew.Bardsley@arm.com        pkt->makeAtomicResponse();
42210259SAndrew.Bardsley@arm.com    } else if (pkt->isPrint()) {
42310259SAndrew.Bardsley@arm.com        Packet::PrintReqState *prs =
42410259SAndrew.Bardsley@arm.com            dynamic_cast<Packet::PrintReqState*>(pkt->senderState);
42510259SAndrew.Bardsley@arm.com        // Need to call printLabels() explicitly since we're not going
42610259SAndrew.Bardsley@arm.com        // through printObj().
42710259SAndrew.Bardsley@arm.com        prs->printLabels();
42810259SAndrew.Bardsley@arm.com        // Right now we just print the single byte at the specified address.
42910259SAndrew.Bardsley@arm.com        ccprintf(prs->os, "%s%#x\n", prs->curPrefix(), *hostAddr);
43010259SAndrew.Bardsley@arm.com    } else {
43110259SAndrew.Bardsley@arm.com        panic("PhysicalMemory: unimplemented functional command %s",
43210259SAndrew.Bardsley@arm.com              pkt->cmdString());
43310259SAndrew.Bardsley@arm.com    }
43410259SAndrew.Bardsley@arm.com}
43510259SAndrew.Bardsley@arm.com
43610259SAndrew.Bardsley@arm.com
43710259SAndrew.Bardsley@arm.comPort *
43810259SAndrew.Bardsley@arm.comPhysicalMemory::getPort(const std::string &if_name, int idx)
43910259SAndrew.Bardsley@arm.com{
44010259SAndrew.Bardsley@arm.com    if (if_name != "port") {
44110259SAndrew.Bardsley@arm.com        panic("PhysicalMemory::getPort: unknown port %s requested", if_name);
44210259SAndrew.Bardsley@arm.com    }
44310259SAndrew.Bardsley@arm.com
44410259SAndrew.Bardsley@arm.com    if (idx >= (int)ports.size()) {
44510259SAndrew.Bardsley@arm.com        ports.resize(idx + 1);
44610259SAndrew.Bardsley@arm.com    }
44710259SAndrew.Bardsley@arm.com
44810259SAndrew.Bardsley@arm.com    if (ports[idx] != NULL) {
44910259SAndrew.Bardsley@arm.com        panic("PhysicalMemory::getPort: port %d already assigned", idx);
45010259SAndrew.Bardsley@arm.com    }
45110259SAndrew.Bardsley@arm.com
45210259SAndrew.Bardsley@arm.com    MemoryPort *port =
45310259SAndrew.Bardsley@arm.com        new MemoryPort(csprintf("%s-port%d", name(), idx), this);
45410259SAndrew.Bardsley@arm.com
45510259SAndrew.Bardsley@arm.com    ports[idx] = port;
45610259SAndrew.Bardsley@arm.com    return port;
45710259SAndrew.Bardsley@arm.com}
45810259SAndrew.Bardsley@arm.com
45910259SAndrew.Bardsley@arm.comPhysicalMemory::MemoryPort::MemoryPort(const std::string &_name,
46010259SAndrew.Bardsley@arm.com                                       PhysicalMemory *_memory)
46110259SAndrew.Bardsley@arm.com    : SimpleTimingPort(_name, _memory), memory(_memory)
46210259SAndrew.Bardsley@arm.com{ }
46310259SAndrew.Bardsley@arm.com
46410259SAndrew.Bardsley@arm.comvoid
46510259SAndrew.Bardsley@arm.comPhysicalMemory::MemoryPort::recvRangeChange()
46610259SAndrew.Bardsley@arm.com{
46710259SAndrew.Bardsley@arm.com    // memory is a slave and thus should never have to worry about its
46810259SAndrew.Bardsley@arm.com    // neighbours address ranges
46910259SAndrew.Bardsley@arm.com}
47010259SAndrew.Bardsley@arm.com
47110259SAndrew.Bardsley@arm.comAddrRangeList
47210259SAndrew.Bardsley@arm.comPhysicalMemory::MemoryPort::getAddrRanges()
47310259SAndrew.Bardsley@arm.com{
47410259SAndrew.Bardsley@arm.com    return memory->getAddrRanges();
47510259SAndrew.Bardsley@arm.com}
47610259SAndrew.Bardsley@arm.com
47710259SAndrew.Bardsley@arm.comAddrRangeList
47810259SAndrew.Bardsley@arm.comPhysicalMemory::getAddrRanges()
47910259SAndrew.Bardsley@arm.com{
48010259SAndrew.Bardsley@arm.com    AddrRangeList ranges;
48110259SAndrew.Bardsley@arm.com    ranges.push_back(RangeSize(start(), size()));
48210259SAndrew.Bardsley@arm.com    return ranges;
48310259SAndrew.Bardsley@arm.com}
48410259SAndrew.Bardsley@arm.com
48510259SAndrew.Bardsley@arm.comunsigned
48610259SAndrew.Bardsley@arm.comPhysicalMemory::MemoryPort::deviceBlockSize() const
48710259SAndrew.Bardsley@arm.com{
48810259SAndrew.Bardsley@arm.com    return memory->deviceBlockSize();
48910259SAndrew.Bardsley@arm.com}
49010259SAndrew.Bardsley@arm.com
49110259SAndrew.Bardsley@arm.comTick
49210259SAndrew.Bardsley@arm.comPhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt)
49310259SAndrew.Bardsley@arm.com{
49410259SAndrew.Bardsley@arm.com    return memory->doAtomicAccess(pkt);
49510259SAndrew.Bardsley@arm.com}
49610259SAndrew.Bardsley@arm.com
49710259SAndrew.Bardsley@arm.comvoid
49810259SAndrew.Bardsley@arm.comPhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt)
49910259SAndrew.Bardsley@arm.com{
50010259SAndrew.Bardsley@arm.com    pkt->pushLabel(memory->name());
50110259SAndrew.Bardsley@arm.com
50210259SAndrew.Bardsley@arm.com    if (!checkFunctional(pkt)) {
50310259SAndrew.Bardsley@arm.com        // Default implementation of SimpleTimingPort::recvFunctional()
50410259SAndrew.Bardsley@arm.com        // calls recvAtomic() and throws away the latency; we can save a
50510259SAndrew.Bardsley@arm.com        // little here by just not calculating the latency.
50610259SAndrew.Bardsley@arm.com        memory->doFunctionalAccess(pkt);
50710259SAndrew.Bardsley@arm.com    }
50810259SAndrew.Bardsley@arm.com
50910259SAndrew.Bardsley@arm.com    pkt->popLabel();
51010259SAndrew.Bardsley@arm.com}
51110259SAndrew.Bardsley@arm.com
51210259SAndrew.Bardsley@arm.comunsigned int
51310259SAndrew.Bardsley@arm.comPhysicalMemory::drain(Event *de)
51410259SAndrew.Bardsley@arm.com{
51510259SAndrew.Bardsley@arm.com    int count = 0;
51610259SAndrew.Bardsley@arm.com    for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) {
51710259SAndrew.Bardsley@arm.com        count += (*pi)->drain(de);
51810259SAndrew.Bardsley@arm.com    }
51910259SAndrew.Bardsley@arm.com
52010259SAndrew.Bardsley@arm.com    if (count)
52110259SAndrew.Bardsley@arm.com        changeState(Draining);
52210259SAndrew.Bardsley@arm.com    else
52310259SAndrew.Bardsley@arm.com        changeState(Drained);
52410259SAndrew.Bardsley@arm.com    return count;
52510259SAndrew.Bardsley@arm.com}
52610259SAndrew.Bardsley@arm.com
52710259SAndrew.Bardsley@arm.comvoid
52810259SAndrew.Bardsley@arm.comPhysicalMemory::serialize(ostream &os)
52910259SAndrew.Bardsley@arm.com{
53010259SAndrew.Bardsley@arm.com    if (!pmemAddr)
53110259SAndrew.Bardsley@arm.com        return;
53210259SAndrew.Bardsley@arm.com
53310259SAndrew.Bardsley@arm.com    gzFile compressedMem;
53410259SAndrew.Bardsley@arm.com    string filename = name() + ".physmem";
53510259SAndrew.Bardsley@arm.com
53610259SAndrew.Bardsley@arm.com    SERIALIZE_SCALAR(filename);
53710259SAndrew.Bardsley@arm.com    SERIALIZE_SCALAR(_size);
53810259SAndrew.Bardsley@arm.com
53910259SAndrew.Bardsley@arm.com    // write memory file
54010259SAndrew.Bardsley@arm.com    string thefile = Checkpoint::dir() + "/" + filename.c_str();
54110259SAndrew.Bardsley@arm.com    int fd = creat(thefile.c_str(), 0664);
54210259SAndrew.Bardsley@arm.com    if (fd < 0) {
54310259SAndrew.Bardsley@arm.com        perror("creat");
54410259SAndrew.Bardsley@arm.com        fatal("Can't open physical memory checkpoint file '%s'\n", filename);
54510259SAndrew.Bardsley@arm.com    }
54610259SAndrew.Bardsley@arm.com
54710259SAndrew.Bardsley@arm.com    compressedMem = gzdopen(fd, "wb");
54810259SAndrew.Bardsley@arm.com    if (compressedMem == NULL)
54910259SAndrew.Bardsley@arm.com        fatal("Insufficient memory to allocate compression state for %s\n",
55010259SAndrew.Bardsley@arm.com                filename);
55110259SAndrew.Bardsley@arm.com
55210259SAndrew.Bardsley@arm.com    if (gzwrite(compressedMem, pmemAddr, size()) != (int)size()) {
55310259SAndrew.Bardsley@arm.com        fatal("Write failed on physical memory checkpoint file '%s'\n",
55410259SAndrew.Bardsley@arm.com              filename);
55510259SAndrew.Bardsley@arm.com    }
55610259SAndrew.Bardsley@arm.com
55710259SAndrew.Bardsley@arm.com    if (gzclose(compressedMem))
55810259SAndrew.Bardsley@arm.com        fatal("Close failed on physical memory checkpoint file '%s'\n",
55910259SAndrew.Bardsley@arm.com              filename);
56010259SAndrew.Bardsley@arm.com
56110259SAndrew.Bardsley@arm.com    list<LockedAddr>::iterator i = lockedAddrList.begin();
56210259SAndrew.Bardsley@arm.com
56310259SAndrew.Bardsley@arm.com    vector<Addr> lal_addr;
56410259SAndrew.Bardsley@arm.com    vector<int> lal_cid;
56510259SAndrew.Bardsley@arm.com    while (i != lockedAddrList.end()) {
56610259SAndrew.Bardsley@arm.com        lal_addr.push_back(i->addr);
56710259SAndrew.Bardsley@arm.com        lal_cid.push_back(i->contextId);
56810259SAndrew.Bardsley@arm.com        i++;
56910259SAndrew.Bardsley@arm.com    }
57010259SAndrew.Bardsley@arm.com    arrayParamOut(os, "lal_addr", lal_addr);
57110259SAndrew.Bardsley@arm.com    arrayParamOut(os, "lal_cid", lal_cid);
57210259SAndrew.Bardsley@arm.com}
57310259SAndrew.Bardsley@arm.com
57410259SAndrew.Bardsley@arm.comvoid
57510259SAndrew.Bardsley@arm.comPhysicalMemory::unserialize(Checkpoint *cp, const string &section)
57610259SAndrew.Bardsley@arm.com{
57710259SAndrew.Bardsley@arm.com    if (!pmemAddr)
57810259SAndrew.Bardsley@arm.com        return;
57910259SAndrew.Bardsley@arm.com
58010259SAndrew.Bardsley@arm.com    gzFile compressedMem;
58110259SAndrew.Bardsley@arm.com    long *tempPage;
58210259SAndrew.Bardsley@arm.com    long *pmem_current;
58310259SAndrew.Bardsley@arm.com    uint64_t curSize;
58410259SAndrew.Bardsley@arm.com    uint32_t bytesRead;
58510259SAndrew.Bardsley@arm.com    const uint32_t chunkSize = 16384;
58610259SAndrew.Bardsley@arm.com
58710259SAndrew.Bardsley@arm.com    string filename;
58810259SAndrew.Bardsley@arm.com
58910259SAndrew.Bardsley@arm.com    UNSERIALIZE_SCALAR(filename);
59010259SAndrew.Bardsley@arm.com
59110259SAndrew.Bardsley@arm.com    filename = cp->cptDir + "/" + filename;
59210259SAndrew.Bardsley@arm.com
59310259SAndrew.Bardsley@arm.com    // mmap memoryfile
59410259SAndrew.Bardsley@arm.com    int fd = open(filename.c_str(), O_RDONLY);
59510259SAndrew.Bardsley@arm.com    if (fd < 0) {
59610259SAndrew.Bardsley@arm.com        perror("open");
59710259SAndrew.Bardsley@arm.com        fatal("Can't open physical memory checkpoint file '%s'", filename);
59810259SAndrew.Bardsley@arm.com    }
59910259SAndrew.Bardsley@arm.com
60010259SAndrew.Bardsley@arm.com    compressedMem = gzdopen(fd, "rb");
60110259SAndrew.Bardsley@arm.com    if (compressedMem == NULL)
60210259SAndrew.Bardsley@arm.com        fatal("Insufficient memory to allocate compression state for %s\n",
60310259SAndrew.Bardsley@arm.com                filename);
60410259SAndrew.Bardsley@arm.com
60510259SAndrew.Bardsley@arm.com    // unmap file that was mmapped in the constructor
60610259SAndrew.Bardsley@arm.com    // This is done here to make sure that gzip and open don't muck with our
60710259SAndrew.Bardsley@arm.com    // nice large space of memory before we reallocate it
60810259SAndrew.Bardsley@arm.com    munmap((char*)pmemAddr, size());
60910259SAndrew.Bardsley@arm.com
61010259SAndrew.Bardsley@arm.com    UNSERIALIZE_SCALAR(_size);
61110259SAndrew.Bardsley@arm.com    if (size() > params()->range.size())
61210259SAndrew.Bardsley@arm.com        fatal("Memory size has changed! size %lld, param size %lld\n",
61310259SAndrew.Bardsley@arm.com              size(), params()->range.size());
61410259SAndrew.Bardsley@arm.com
61510259SAndrew.Bardsley@arm.com    pmemAddr = (uint8_t *)mmap(NULL, size(),
61610259SAndrew.Bardsley@arm.com        PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
61710259SAndrew.Bardsley@arm.com
61810259SAndrew.Bardsley@arm.com    if (pmemAddr == (void *)MAP_FAILED) {
61910259SAndrew.Bardsley@arm.com        perror("mmap");
62010259SAndrew.Bardsley@arm.com        fatal("Could not mmap physical memory!\n");
62110259SAndrew.Bardsley@arm.com    }
62210259SAndrew.Bardsley@arm.com
62310259SAndrew.Bardsley@arm.com    curSize = 0;
62410259SAndrew.Bardsley@arm.com    tempPage = (long*)malloc(chunkSize);
62510259SAndrew.Bardsley@arm.com    if (tempPage == NULL)
62610259SAndrew.Bardsley@arm.com        fatal("Unable to malloc memory to read file %s\n", filename);
62710259SAndrew.Bardsley@arm.com
62810259SAndrew.Bardsley@arm.com    /* Only copy bytes that are non-zero, so we don't give the VM system hell */
62910259SAndrew.Bardsley@arm.com    while (curSize < size()) {
63010259SAndrew.Bardsley@arm.com        bytesRead = gzread(compressedMem, tempPage, chunkSize);
63110259SAndrew.Bardsley@arm.com        if (bytesRead == 0)
63210259SAndrew.Bardsley@arm.com            break;
63310259SAndrew.Bardsley@arm.com
63410259SAndrew.Bardsley@arm.com        assert(bytesRead % sizeof(long) == 0);
63510259SAndrew.Bardsley@arm.com
63610259SAndrew.Bardsley@arm.com        for (uint32_t x = 0; x < bytesRead / sizeof(long); x++)
63710259SAndrew.Bardsley@arm.com        {
63810259SAndrew.Bardsley@arm.com             if (*(tempPage+x) != 0) {
63910259SAndrew.Bardsley@arm.com                 pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long));
64010259SAndrew.Bardsley@arm.com                 *pmem_current = *(tempPage+x);
64110259SAndrew.Bardsley@arm.com             }
64210259SAndrew.Bardsley@arm.com        }
64310259SAndrew.Bardsley@arm.com        curSize += bytesRead;
64410259SAndrew.Bardsley@arm.com    }
64510259SAndrew.Bardsley@arm.com
64610259SAndrew.Bardsley@arm.com    free(tempPage);
64710259SAndrew.Bardsley@arm.com
64810259SAndrew.Bardsley@arm.com    if (gzclose(compressedMem))
64910259SAndrew.Bardsley@arm.com        fatal("Close failed on physical memory checkpoint file '%s'\n",
65010259SAndrew.Bardsley@arm.com              filename);
65110259SAndrew.Bardsley@arm.com
65210259SAndrew.Bardsley@arm.com    vector<Addr> lal_addr;
65310259SAndrew.Bardsley@arm.com    vector<int> lal_cid;
65410259SAndrew.Bardsley@arm.com    arrayParamIn(cp, section, "lal_addr", lal_addr);
65510259SAndrew.Bardsley@arm.com    arrayParamIn(cp, section, "lal_cid", lal_cid);
65610259SAndrew.Bardsley@arm.com    for(int i = 0; i < lal_addr.size(); i++)
65710259SAndrew.Bardsley@arm.com        lockedAddrList.push_front(LockedAddr(lal_addr[i], lal_cid[i]));
65810259SAndrew.Bardsley@arm.com}
65910259SAndrew.Bardsley@arm.com
66010259SAndrew.Bardsley@arm.comPhysicalMemory *
66110259SAndrew.Bardsley@arm.comPhysicalMemoryParams::create()
66210259SAndrew.Bardsley@arm.com{
66310259SAndrew.Bardsley@arm.com    return new PhysicalMemory(this);
66410259SAndrew.Bardsley@arm.com}
66510259SAndrew.Bardsley@arm.com