abstract_mem.cc revision 9053:9cad1c26c3b3
12623SN/A/*
210596Sgabeblack@google.com * Copyright (c) 2010-2012 ARM Limited
311147Smitch.hayenga@arm.com * All rights reserved
48926Sandreas.hansson@arm.com *
58926Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
68926Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
78926Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
88926Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
98926Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
108926Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
118926Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
128926Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
138926Sandreas.hansson@arm.com *
148926Sandreas.hansson@arm.com * Copyright (c) 2001-2005 The Regents of The University of Michigan
152623SN/A * All rights reserved.
162623SN/A *
172623SN/A * Redistribution and use in source and binary forms, with or without
182623SN/A * modification, are permitted provided that the following conditions are
192623SN/A * met: redistributions of source code must retain the above copyright
202623SN/A * notice, this list of conditions and the following disclaimer;
212623SN/A * redistributions in binary form must reproduce the above copyright
222623SN/A * notice, this list of conditions and the following disclaimer in the
232623SN/A * documentation and/or other materials provided with the distribution;
242623SN/A * neither the name of the copyright holders nor the names of its
252623SN/A * contributors may be used to endorse or promote products derived from
262623SN/A * this software without specific prior written permission.
272623SN/A *
282623SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
292623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
302623SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
312623SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
322623SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
332623SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
342623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
352623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
362623SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
372623SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
382623SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392623SN/A *
402665Ssaidi@eecs.umich.edu * Authors: Ron Dreslinski
412665Ssaidi@eecs.umich.edu *          Ali Saidi
422623SN/A *          Andreas Hansson
432623SN/A */
4411793Sbrandon.potter@amd.com
4511793Sbrandon.potter@amd.com#include <sys/mman.h>
463170Sstever@eecs.umich.edu#include <sys/types.h>
478105Sgblack@eecs.umich.edu#include <sys/user.h>
482623SN/A#include <fcntl.h>
494040Ssaidi@eecs.umich.edu#include <unistd.h>
509647Sdam.sunwoo@arm.com#include <zlib.h>
516658Snate@binkert.org
522623SN/A#include <cerrno>
539443SAndreas.Sandberg@ARM.com#include <cstdio>
548232Snate@binkert.org#include <iostream>
558232Snate@binkert.org#include <string>
563348Sbinkertn@umich.edu
573348Sbinkertn@umich.edu#include "arch/registers.hh"
588926Sandreas.hansson@arm.com#include "config/the_isa.hh"
594762Snate@binkert.org#include "debug/LLSC.hh"
607678Sgblack@eecs.umich.edu#include "debug/MemoryAccess.hh"
6111793Sbrandon.potter@amd.com#include "mem/abstract_mem.hh"
622901Ssaidi@eecs.umich.edu#include "mem/packet_access.hh"
632623SN/A#include "sim/system.hh"
642623SN/A
652623SN/Ausing namespace std;
662623SN/A
672623SN/AAbstractMemory::AbstractMemory(const Params *p) :
685606Snate@binkert.org    MemObject(p), range(params()->range), pmemAddr(NULL),
692623SN/A    confTableReported(p->conf_table_reported), inAddrMap(p->in_addr_map),
702623SN/A    _system(NULL)
712623SN/A{
722623SN/A    if (size() % TheISA::PageBytes != 0)
732623SN/A        panic("Memory Size not divisible by page size\n");
742623SN/A
752623SN/A    if (params()->null)
762623SN/A        return;
772623SN/A
782623SN/A    if (params()->file == "") {
792623SN/A        int map_flags = MAP_ANON | MAP_PRIVATE;
805336Shines@cs.fsu.edu        pmemAddr = (uint8_t *)mmap(NULL, size(),
812623SN/A                                   PROT_READ | PROT_WRITE, map_flags, -1, 0);
824873Sstever@eecs.umich.edu    } else {
832623SN/A        int map_flags = MAP_PRIVATE;
842623SN/A        int fd = open(params()->file.c_str(), O_RDONLY);
852623SN/A        long _size = lseek(fd, 0, SEEK_END);
862623SN/A        if (_size != range.size()) {
872623SN/A            warn("Specified size %d does not match file %s %d\n", range.size(),
8811147Smitch.hayenga@arm.com                 params()->file, _size);
898921Sandreas.hansson@arm.com            range = RangeSize(range.start, _size);
9011148Smitch.hayenga@arm.com        }
9111435Smitch.hayenga@arm.com        lseek(fd, 0, SEEK_SET);
9211435Smitch.hayenga@arm.com        pmemAddr = (uint8_t *)mmap(NULL, roundUp(_size, sysconf(_SC_PAGESIZE)),
9311435Smitch.hayenga@arm.com                                   PROT_READ | PROT_WRITE, map_flags, fd, 0);
942623SN/A    }
952623SN/A
965529Snate@binkert.org    if (pmemAddr == (void *)MAP_FAILED) {
976078Sgblack@eecs.umich.edu        perror("mmap");
985487Snate@binkert.org        if (params()->file == "")
995487Snate@binkert.org            fatal("Could not mmap!\n");
1009095Sandreas.hansson@arm.com        else
1019095Sandreas.hansson@arm.com            fatal("Could not find file: %s\n", params()->file);
10210537Sandreas.hansson@arm.com    }
10310537Sandreas.hansson@arm.com
1042623SN/A    //If requested, initialize all the memory to 0
1052623SN/A    if (p->zero)
1062623SN/A        memset(pmemAddr, 0, size());
1072623SN/A}
1082623SN/A
1092623SN/A
1102623SN/AAbstractMemory::~AbstractMemory()
1116775SBrad.Beckmann@amd.com{
1126775SBrad.Beckmann@amd.com    if (pmemAddr)
1136775SBrad.Beckmann@amd.com        munmap((char*)pmemAddr, size());
1142623SN/A}
1152623SN/A
11610913Sandreas.sandberg@arm.comvoid
11710913Sandreas.sandberg@arm.comAbstractMemory::regStats()
1182623SN/A{
1199448SAndreas.Sandberg@ARM.com    using namespace Stats;
12010913Sandreas.sandberg@arm.com
1212623SN/A    assert(system());
1229443SAndreas.Sandberg@ARM.com
12311147Smitch.hayenga@arm.com    bytesRead
12410913Sandreas.sandberg@arm.com        .init(system()->maxMasters())
1259443SAndreas.Sandberg@ARM.com        .name(name() + ".bytes_read")
1269443SAndreas.Sandberg@ARM.com        .desc("Number of bytes read from this memory")
1279443SAndreas.Sandberg@ARM.com        .flags(total | nozero | nonan)
1282915Sktlim@umich.edu        ;
12911147Smitch.hayenga@arm.com    for (int i = 0; i < system()->maxMasters(); i++) {
1309443SAndreas.Sandberg@ARM.com        bytesRead.subname(i, system()->getMasterName(i));
13110913Sandreas.sandberg@arm.com    }
1329443SAndreas.Sandberg@ARM.com    bytesInstRead
1339342SAndreas.Sandberg@arm.com        .init(system()->maxMasters())
1349342SAndreas.Sandberg@arm.com        .name(name() + ".bytes_inst_read")
1352915Sktlim@umich.edu        .desc("Number of instructions bytes read from this memory")
13611148Smitch.hayenga@arm.com        .flags(total | nozero | nonan)
13711148Smitch.hayenga@arm.com        ;
13811148Smitch.hayenga@arm.com    for (int i = 0; i < system()->maxMasters(); i++) {
13911148Smitch.hayenga@arm.com        bytesInstRead.subname(i, system()->getMasterName(i));
14011148Smitch.hayenga@arm.com    }
14111148Smitch.hayenga@arm.com    bytesWritten
14211148Smitch.hayenga@arm.com        .init(system()->maxMasters())
14311321Ssteve.reinhardt@amd.com        .name(name() + ".bytes_written")
14411151Smitch.hayenga@arm.com        .desc("Number of bytes written to this memory")
14511148Smitch.hayenga@arm.com        .flags(total | nozero | nonan)
14611148Smitch.hayenga@arm.com        ;
14711148Smitch.hayenga@arm.com    for (int i = 0; i < system()->maxMasters(); i++) {
14811148Smitch.hayenga@arm.com        bytesWritten.subname(i, system()->getMasterName(i));
14911148Smitch.hayenga@arm.com    }
15011148Smitch.hayenga@arm.com    numReads
15111148Smitch.hayenga@arm.com        .init(system()->maxMasters())
15211148Smitch.hayenga@arm.com        .name(name() + ".num_reads")
15311148Smitch.hayenga@arm.com        .desc("Number of read requests responded to by this memory")
1549342SAndreas.Sandberg@arm.com        .flags(total | nozero | nonan)
1552915Sktlim@umich.edu        ;
1569448SAndreas.Sandberg@ARM.com    for (int i = 0; i < system()->maxMasters(); i++) {
1579448SAndreas.Sandberg@ARM.com        numReads.subname(i, system()->getMasterName(i));
1585220Ssaidi@eecs.umich.edu    }
1595220Ssaidi@eecs.umich.edu    numWrites
1604940Snate@binkert.org        .init(system()->maxMasters())
1619523SAndreas.Sandberg@ARM.com        .name(name() + ".num_writes")
1623324Shsul@eecs.umich.edu        .desc("Number of write requests responded to by this memory")
1639448SAndreas.Sandberg@ARM.com        .flags(total | nozero | nonan)
1649448SAndreas.Sandberg@ARM.com        ;
16511147Smitch.hayenga@arm.com    for (int i = 0; i < system()->maxMasters(); i++) {
16611147Smitch.hayenga@arm.com        numWrites.subname(i, system()->getMasterName(i));
16711147Smitch.hayenga@arm.com    }
16811147Smitch.hayenga@arm.com    numOther
16911147Smitch.hayenga@arm.com        .init(system()->maxMasters())
17011147Smitch.hayenga@arm.com        .name(name() + ".num_other")
17111147Smitch.hayenga@arm.com        .desc("Number of other requests responded to by this memory")
17211147Smitch.hayenga@arm.com        .flags(total | nozero | nonan)
17311147Smitch.hayenga@arm.com        ;
17411147Smitch.hayenga@arm.com    for (int i = 0; i < system()->maxMasters(); i++) {
17511147Smitch.hayenga@arm.com        numOther.subname(i, system()->getMasterName(i));
17611147Smitch.hayenga@arm.com    }
17711147Smitch.hayenga@arm.com    bwRead
17811147Smitch.hayenga@arm.com        .name(name() + ".bw_read")
17911147Smitch.hayenga@arm.com        .desc("Total read bandwidth from this memory (bytes/s)")
1809448SAndreas.Sandberg@ARM.com        .precision(0)
1812623SN/A        .prereq(bytesRead)
1822623SN/A        .flags(total | nozero | nonan)
1839443SAndreas.Sandberg@ARM.com        ;
1849443SAndreas.Sandberg@ARM.com    for (int i = 0; i < system()->maxMasters(); i++) {
1859443SAndreas.Sandberg@ARM.com        bwRead.subname(i, system()->getMasterName(i));
18610913Sandreas.sandberg@arm.com    }
1879443SAndreas.Sandberg@ARM.com
1889443SAndreas.Sandberg@ARM.com    bwInstRead
18911147Smitch.hayenga@arm.com        .name(name() + ".bw_inst_read")
1909443SAndreas.Sandberg@ARM.com        .desc("Instruction read bandwidth from this memory (bytes/s)")
1919443SAndreas.Sandberg@ARM.com        .precision(0)
1929443SAndreas.Sandberg@ARM.com        .prereq(bytesInstRead)
1939443SAndreas.Sandberg@ARM.com        .flags(total | nozero | nonan)
19410913Sandreas.sandberg@arm.com        ;
1959443SAndreas.Sandberg@ARM.com    for (int i = 0; i < system()->maxMasters(); i++) {
1969443SAndreas.Sandberg@ARM.com        bwInstRead.subname(i, system()->getMasterName(i));
1979443SAndreas.Sandberg@ARM.com    }
1989443SAndreas.Sandberg@ARM.com    bwWrite
1999443SAndreas.Sandberg@ARM.com        .name(name() + ".bw_write")
2002623SN/A        .desc("Write bandwidth from this memory (bytes/s)")
2012798Sktlim@umich.edu        .precision(0)
2022623SN/A        .prereq(bytesWritten)
2039429SAndreas.Sandberg@ARM.com        .flags(total | nozero | nonan)
2049429SAndreas.Sandberg@ARM.com        ;
2059443SAndreas.Sandberg@ARM.com    for (int i = 0; i < system()->maxMasters(); i++) {
2069342SAndreas.Sandberg@arm.com        bwWrite.subname(i, system()->getMasterName(i));
2079443SAndreas.Sandberg@ARM.com    }
2082623SN/A    bwTotal
2092623SN/A        .name(name() + ".bw_total")
2102623SN/A        .desc("Total bandwidth to/from this memory (bytes/s)")
2112623SN/A        .precision(0)
2122623SN/A        .prereq(bwTotal)
2132623SN/A        .flags(total | nozero | nonan)
2149429SAndreas.Sandberg@ARM.com        ;
2152623SN/A    for (int i = 0; i < system()->maxMasters(); i++) {
2169443SAndreas.Sandberg@ARM.com        bwTotal.subname(i, system()->getMasterName(i));
2172623SN/A    }
2182623SN/A    bwRead = bytesRead / simSeconds;
2192623SN/A    bwInstRead = bytesInstRead / simSeconds;
2209523SAndreas.Sandberg@ARM.com    bwWrite = bytesWritten / simSeconds;
2219523SAndreas.Sandberg@ARM.com    bwTotal = (bytesRead + bytesWritten) / simSeconds;
2229523SAndreas.Sandberg@ARM.com}
2239524SAndreas.Sandberg@ARM.com
2249523SAndreas.Sandberg@ARM.comRange<Addr>
2259523SAndreas.Sandberg@ARM.comAbstractMemory::getAddrRange()
2269523SAndreas.Sandberg@ARM.com{
2279523SAndreas.Sandberg@ARM.com    return range;
2282623SN/A}
2292623SN/A
23010407Smitch.hayenga@arm.com// Add load-locked to tracking list.  Should only be called if the
2312623SN/A// operation is a load and the LLSC flag is set.
23210407Smitch.hayenga@arm.comvoid
2334940Snate@binkert.orgAbstractMemory::trackLoadLocked(PacketPtr pkt)
23411147Smitch.hayenga@arm.com{
2352623SN/A    Request *req = pkt->req;
23611147Smitch.hayenga@arm.com    Addr paddr = LockedAddr::mask(req->getPaddr());
23711147Smitch.hayenga@arm.com
23811147Smitch.hayenga@arm.com    // first we check if we already have a locked addr for this
23910464SAndreas.Sandberg@ARM.com    // xc.  Since each xc only gets one, we just update the
24010464SAndreas.Sandberg@ARM.com    // existing record with the new address.
2413686Sktlim@umich.edu    list<LockedAddr>::iterator i;
24211147Smitch.hayenga@arm.com
24311147Smitch.hayenga@arm.com    for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) {
24411147Smitch.hayenga@arm.com        if (i->matchesContext(req)) {
24511147Smitch.hayenga@arm.com            DPRINTF(LLSC, "Modifying lock record: context %d addr %#x\n",
2469342SAndreas.Sandberg@arm.com                    req->contextId(), paddr);
24711147Smitch.hayenga@arm.com            i->addr = paddr;
24811147Smitch.hayenga@arm.com            return;
24911147Smitch.hayenga@arm.com        }
25011147Smitch.hayenga@arm.com    }
25111526Sdavid.guillen@arm.com
25211526Sdavid.guillen@arm.com    // no record for this xc: need to allocate a new one
2532623SN/A    DPRINTF(LLSC, "Adding lock record: context %d addr %#x\n",
2542623SN/A            req->contextId(), paddr);
2552623SN/A    lockedAddrList.push_front(LockedAddr(req));
2562623SN/A}
2578737Skoansin.tan@gmail.com
2582623SN/A
2594940Snate@binkert.org// Called on *writes* only... both regular stores and
2604940Snate@binkert.org// store-conditional operations.  Check for conventional stores which
26111147Smitch.hayenga@arm.com// conflict with locked addresses, and for success/failure of store
26211147Smitch.hayenga@arm.com// conditionals.
2632623SN/Abool
2646043Sgblack@eecs.umich.eduAbstractMemory::checkLockedAddrList(PacketPtr pkt)
2656043Sgblack@eecs.umich.edu{
2666043Sgblack@eecs.umich.edu    Request *req = pkt->req;
2679342SAndreas.Sandberg@arm.com    Addr paddr = LockedAddr::mask(req->getPaddr());
2682626SN/A    bool isLLSC = pkt->isLLSC();
26911147Smitch.hayenga@arm.com
2702623SN/A    // Initialize return value.  Non-conditional stores always
27111147Smitch.hayenga@arm.com    // succeed.  Assume conditional stores will fail until proven
27211147Smitch.hayenga@arm.com    // otherwise.
27311147Smitch.hayenga@arm.com    bool success = !isLLSC;
27411147Smitch.hayenga@arm.com
27511147Smitch.hayenga@arm.com    // Iterate over list.  Note that there could be multiple matching
27611147Smitch.hayenga@arm.com    // records, as more than one context could have done a load locked
27711147Smitch.hayenga@arm.com    // to this location.
27811147Smitch.hayenga@arm.com    list<LockedAddr>::iterator i = lockedAddrList.begin();
27911526Sdavid.guillen@arm.com
2802623SN/A    while (i != lockedAddrList.end()) {
2812623SN/A
2822623SN/A        if (i->addr == paddr) {
28310030SAli.Saidi@ARM.com            // we have a matching address
28410030SAli.Saidi@ARM.com
28510030SAli.Saidi@ARM.com            if (isLLSC && i->matchesContext(req)) {
28610030SAli.Saidi@ARM.com                // it's a store conditional, and as far as the memory
28710030SAli.Saidi@ARM.com                // system can tell, the requesting context's lock is
28810030SAli.Saidi@ARM.com                // still valid.
28910529Smorr@cs.wisc.edu                DPRINTF(LLSC, "StCond success: context %d addr %#x\n",
29010529Smorr@cs.wisc.edu                        req->contextId(), paddr);
29111148Smitch.hayenga@arm.com                success = true;
29211148Smitch.hayenga@arm.com            }
29311148Smitch.hayenga@arm.com
29411151Smitch.hayenga@arm.com            // Get rid of our record of this lock and advance to next
29511148Smitch.hayenga@arm.com            DPRINTF(LLSC, "Erasing lock record: context %d addr %#x\n",
29610529Smorr@cs.wisc.edu                    i->contextId, paddr);
29710529Smorr@cs.wisc.edu            i = lockedAddrList.erase(i);
29810030SAli.Saidi@ARM.com        }
29911356Skrinat01@arm.com        else {
30011356Skrinat01@arm.com            // no match: advance to next record
30111356Skrinat01@arm.com            ++i;
30211356Skrinat01@arm.com        }
30310030SAli.Saidi@ARM.com    }
30410030SAli.Saidi@ARM.com
30511147Smitch.hayenga@arm.com    if (isLLSC) {
30611147Smitch.hayenga@arm.com        req->setExtraData(success ? 1 : 0);
30711147Smitch.hayenga@arm.com    }
30810030SAli.Saidi@ARM.com
30910030SAli.Saidi@ARM.com    return success;
31010030SAli.Saidi@ARM.com}
31110030SAli.Saidi@ARM.com
31210030SAli.Saidi@ARM.com
31310030SAli.Saidi@ARM.com#if TRACING_ON
31410030SAli.Saidi@ARM.com
31510030SAli.Saidi@ARM.com#define CASE(A, T)                                                      \
31610030SAli.Saidi@ARM.com  case sizeof(T):                                                       \
31710030SAli.Saidi@ARM.com    DPRINTF(MemoryAccess,"%s of size %i on address 0x%x data 0x%x\n",   \
31810030SAli.Saidi@ARM.com            A, pkt->getSize(), pkt->getAddr(), pkt->get<T>());          \
31910529Smorr@cs.wisc.edu  break
32010529Smorr@cs.wisc.edu
32111148Smitch.hayenga@arm.com
32211321Ssteve.reinhardt@amd.com#define TRACE_PACKET(A)                                                 \
32311151Smitch.hayenga@arm.com    do {                                                                \
32411148Smitch.hayenga@arm.com        switch (pkt->getSize()) {                                       \
32510529Smorr@cs.wisc.edu          CASE(A, uint64_t);                                            \
32610529Smorr@cs.wisc.edu          CASE(A, uint32_t);                                            \
32710030SAli.Saidi@ARM.com          CASE(A, uint16_t);                                            \
32810030SAli.Saidi@ARM.com          CASE(A, uint8_t);                                             \
32910030SAli.Saidi@ARM.com          default:                                                      \
33010030SAli.Saidi@ARM.com            DPRINTF(MemoryAccess, "%s of size %i on address 0x%x\n",    \
33111147Smitch.hayenga@arm.com                    A, pkt->getSize(), pkt->getAddr());                 \
33211147Smitch.hayenga@arm.com            DDUMP(MemoryAccess, pkt->getPtr<uint8_t>(), pkt->getSize());\
33311147Smitch.hayenga@arm.com        }                                                               \
33410030SAli.Saidi@ARM.com    } while (0)
33510030SAli.Saidi@ARM.com
33610030SAli.Saidi@ARM.com#else
3372623SN/A
33811608Snikos.nikoleris@arm.com#define TRACE_PACKET(A)
33911608Snikos.nikoleris@arm.com
3402623SN/A#endif
34111147Smitch.hayenga@arm.com
34211147Smitch.hayenga@arm.comvoid
34311147Smitch.hayenga@arm.comAbstractMemory::access(PacketPtr pkt)
3443169Sstever@eecs.umich.edu{
3454870Sstever@eecs.umich.edu    assert(pkt->getAddr() >= range.start &&
3462623SN/A           (pkt->getAddr() + pkt->getSize() - 1) <= range.end);
34710665SAli.Saidi@ARM.com
34810665SAli.Saidi@ARM.com    if (pkt->memInhibitAsserted()) {
3492623SN/A        DPRINTF(MemoryAccess, "mem inhibited on 0x%x: not responding\n",
3504999Sgblack@eecs.umich.edu                pkt->getAddr());
3517520Sgblack@eecs.umich.edu        return;
3522623SN/A    }
3534999Sgblack@eecs.umich.edu
3544999Sgblack@eecs.umich.edu    uint8_t *hostAddr = pmemAddr + pkt->getAddr() - range.start;
3559814Sandreas.hansson@arm.com
3564999Sgblack@eecs.umich.edu    if (pkt->cmd == MemCmd::SwapReq) {
3577520Sgblack@eecs.umich.edu        TheISA::IntReg overwrite_val;
3587520Sgblack@eecs.umich.edu        bool overwrite_mem;
3594999Sgblack@eecs.umich.edu        uint64_t condition_val64;
3604999Sgblack@eecs.umich.edu        uint32_t condition_val32;
3614999Sgblack@eecs.umich.edu
36210024Sdam.sunwoo@arm.com        if (!pmemAddr)
3637520Sgblack@eecs.umich.edu            panic("Swap only works if there is real memory (i.e. null=False)");
3648832SAli.Saidi@ARM.com        assert(sizeof(TheISA::IntReg) >= pkt->getSize());
3654999Sgblack@eecs.umich.edu
3664999Sgblack@eecs.umich.edu        overwrite_mem = true;
36711147Smitch.hayenga@arm.com        // keep a copy of our possible write value, and copy what is at the
36811147Smitch.hayenga@arm.com        // memory address into the packet
3694999Sgblack@eecs.umich.edu        std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize());
3704999Sgblack@eecs.umich.edu        std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
3716623Sgblack@eecs.umich.edu
37210739Ssteve.reinhardt@amd.com        if (pkt->req->isCondSwap()) {
3737520Sgblack@eecs.umich.edu            if (pkt->getSize() == sizeof(uint64_t)) {
3744999Sgblack@eecs.umich.edu                condition_val64 = pkt->req->getExtraData();
3758105Sgblack@eecs.umich.edu                overwrite_mem = !std::memcmp(&condition_val64, hostAddr,
3764999Sgblack@eecs.umich.edu                                             sizeof(uint64_t));
3774999Sgblack@eecs.umich.edu            } else if (pkt->getSize() == sizeof(uint32_t)) {
3788931Sandreas.hansson@arm.com                condition_val32 = (uint32_t)pkt->req->getExtraData();
3798931Sandreas.hansson@arm.com                overwrite_mem = !std::memcmp(&condition_val32, hostAddr,
3804999Sgblack@eecs.umich.edu                                             sizeof(uint32_t));
3814999Sgblack@eecs.umich.edu            } else
3824999Sgblack@eecs.umich.edu                panic("Invalid size for conditional read/write\n");
3834999Sgblack@eecs.umich.edu        }
3845012Sgblack@eecs.umich.edu
3854999Sgblack@eecs.umich.edu        if (overwrite_mem)
3864999Sgblack@eecs.umich.edu            std::memcpy(hostAddr, &overwrite_val, pkt->getSize());
3876102Sgblack@eecs.umich.edu
3884999Sgblack@eecs.umich.edu        assert(!pkt->req->isInstFetch());
3894999Sgblack@eecs.umich.edu        TRACE_PACKET("Read/Write");
3904968Sacolyte@umich.edu        numOther[pkt->req->masterId()]++;
3914986Ssaidi@eecs.umich.edu    } else if (pkt->isRead()) {
3924999Sgblack@eecs.umich.edu        assert(!pkt->isWrite());
3936739Sgblack@eecs.umich.edu        if (pkt->isLLSC()) {
3946739Sgblack@eecs.umich.edu            trackLoadLocked(pkt);
3956739Sgblack@eecs.umich.edu        }
3966739Sgblack@eecs.umich.edu        if (pmemAddr)
3976739Sgblack@eecs.umich.edu            memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
3986739Sgblack@eecs.umich.edu        TRACE_PACKET(pkt->req->isInstFetch() ? "IFetch" : "Read");
3996739Sgblack@eecs.umich.edu        numReads[pkt->req->masterId()]++;
4006739Sgblack@eecs.umich.edu        bytesRead[pkt->req->masterId()] += pkt->getSize();
4014999Sgblack@eecs.umich.edu        if (pkt->req->isInstFetch())
4024999Sgblack@eecs.umich.edu            bytesInstRead[pkt->req->masterId()] += pkt->getSize();
4034999Sgblack@eecs.umich.edu    } else if (pkt->isWrite()) {
40410760Ssteve.reinhardt@amd.com        if (writeOK(pkt)) {
4056078Sgblack@eecs.umich.edu            if (pmemAddr)
4066078Sgblack@eecs.umich.edu                memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
4076078Sgblack@eecs.umich.edu            assert(!pkt->req->isInstFetch());
40811147Smitch.hayenga@arm.com            TRACE_PACKET("Write");
4094999Sgblack@eecs.umich.edu            numWrites[pkt->req->masterId()]++;
4104968Sacolyte@umich.edu            bytesWritten[pkt->req->masterId()] += pkt->getSize();
4113170Sstever@eecs.umich.edu        }
4124999Sgblack@eecs.umich.edu    } else if (pkt->isInvalidate()) {
4134999Sgblack@eecs.umich.edu        // no need to do anything
4144999Sgblack@eecs.umich.edu    } else {
4154999Sgblack@eecs.umich.edu        panic("unimplemented");
4164999Sgblack@eecs.umich.edu    }
4177520Sgblack@eecs.umich.edu
4184999Sgblack@eecs.umich.edu    if (pkt->needsResponse()) {
4197520Sgblack@eecs.umich.edu        pkt->makeResponse();
4204999Sgblack@eecs.umich.edu    }
4214999Sgblack@eecs.umich.edu}
4222623SN/A
4232623SN/Avoid
4242623SN/AAbstractMemory::functionalAccess(PacketPtr pkt)
42511303Ssteve.reinhardt@amd.com{
42611608Snikos.nikoleris@arm.com    assert(pkt->getAddr() >= range.start &&
42711608Snikos.nikoleris@arm.com           (pkt->getAddr() + pkt->getSize() - 1) <= range.end);
42811303Ssteve.reinhardt@amd.com
42911303Ssteve.reinhardt@amd.com    uint8_t *hostAddr = pmemAddr + pkt->getAddr() - range.start;
43011303Ssteve.reinhardt@amd.com
43111303Ssteve.reinhardt@amd.com    if (pkt->isRead()) {
4327520Sgblack@eecs.umich.edu        if (pmemAddr)
4332623SN/A            memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
43411608Snikos.nikoleris@arm.com        TRACE_PACKET("Read");
43511608Snikos.nikoleris@arm.com        pkt->makeResponse();
4362623SN/A    } else if (pkt->isWrite()) {
43711147Smitch.hayenga@arm.com        if (pmemAddr)
43811147Smitch.hayenga@arm.com            memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
43910031SAli.Saidi@ARM.com        TRACE_PACKET("Write");
44010031SAli.Saidi@ARM.com        pkt->makeResponse();
44110031SAli.Saidi@ARM.com    } else if (pkt->isPrint()) {
44210031SAli.Saidi@ARM.com        Packet::PrintReqState *prs =
44310031SAli.Saidi@ARM.com            dynamic_cast<Packet::PrintReqState*>(pkt->senderState);
44410031SAli.Saidi@ARM.com        assert(prs);
44510031SAli.Saidi@ARM.com        // Need to call printLabels() explicitly since we're not going
44610031SAli.Saidi@ARM.com        // through printObj().
44710031SAli.Saidi@ARM.com        prs->printLabels();
4483169Sstever@eecs.umich.edu        // Right now we just print the single byte at the specified address.
4494870Sstever@eecs.umich.edu        ccprintf(prs->os, "%s%#x\n", prs->curPrefix(), *hostAddr);
4502623SN/A    } else {
45110665SAli.Saidi@ARM.com        panic("AbstractMemory: unimplemented functional command %s",
45210665SAli.Saidi@ARM.com              pkt->cmdString());
4532623SN/A    }
4544999Sgblack@eecs.umich.edu}
4557520Sgblack@eecs.umich.edu
4562623SN/Avoid
4574999Sgblack@eecs.umich.eduAbstractMemory::serialize(ostream &os)
4584999Sgblack@eecs.umich.edu{
4599814Sandreas.hansson@arm.com    if (!pmemAddr)
4604999Sgblack@eecs.umich.edu        return;
46111321Ssteve.reinhardt@amd.com
4627520Sgblack@eecs.umich.edu    gzFile compressedMem;
4634999Sgblack@eecs.umich.edu    string filename = name() + ".physmem";
4644999Sgblack@eecs.umich.edu    long _size = range.size();
4654999Sgblack@eecs.umich.edu
46610024Sdam.sunwoo@arm.com    SERIALIZE_SCALAR(filename);
46711321Ssteve.reinhardt@amd.com    SERIALIZE_SCALAR(_size);
4688832SAli.Saidi@ARM.com
4694999Sgblack@eecs.umich.edu    // write memory file
4704999Sgblack@eecs.umich.edu    string thefile = Checkpoint::dir() + "/" + filename.c_str();
47111147Smitch.hayenga@arm.com    int fd = creat(thefile.c_str(), 0664);
4724999Sgblack@eecs.umich.edu    if (fd < 0) {
4734999Sgblack@eecs.umich.edu        perror("creat");
4744999Sgblack@eecs.umich.edu        fatal("Can't open physical memory checkpoint file '%s'\n", filename);
4754999Sgblack@eecs.umich.edu    }
4764999Sgblack@eecs.umich.edu
4774999Sgblack@eecs.umich.edu    compressedMem = gzdopen(fd, "wb");
4786102Sgblack@eecs.umich.edu    if (compressedMem == NULL)
4794999Sgblack@eecs.umich.edu        fatal("Insufficient memory to allocate compression state for %s\n",
48010030SAli.Saidi@ARM.com                filename);
4814999Sgblack@eecs.umich.edu
4824999Sgblack@eecs.umich.edu    if (gzwrite(compressedMem, pmemAddr, size()) != (int)size()) {
4834999Sgblack@eecs.umich.edu        fatal("Write failed on physical memory checkpoint file '%s'\n",
4844999Sgblack@eecs.umich.edu              filename);
4854999Sgblack@eecs.umich.edu    }
4864999Sgblack@eecs.umich.edu
4874999Sgblack@eecs.umich.edu    if (gzclose(compressedMem))
4884999Sgblack@eecs.umich.edu        fatal("Close failed on physical memory checkpoint file '%s'\n",
4896623Sgblack@eecs.umich.edu              filename);
4908949Sandreas.hansson@arm.com
4917520Sgblack@eecs.umich.edu    list<LockedAddr>::iterator i = lockedAddrList.begin();
4924999Sgblack@eecs.umich.edu
4938105Sgblack@eecs.umich.edu    vector<Addr> lal_addr;
4944999Sgblack@eecs.umich.edu    vector<int> lal_cid;
4954999Sgblack@eecs.umich.edu    while (i != lockedAddrList.end()) {
4964999Sgblack@eecs.umich.edu        lal_addr.push_back(i->addr);
4978931Sandreas.hansson@arm.com        lal_cid.push_back(i->contextId);
4988931Sandreas.hansson@arm.com        i++;
4994999Sgblack@eecs.umich.edu    }
5004999Sgblack@eecs.umich.edu    arrayParamOut(os, "lal_addr", lal_addr);
50111148Smitch.hayenga@arm.com    arrayParamOut(os, "lal_cid", lal_cid);
50211148Smitch.hayenga@arm.com}
50311148Smitch.hayenga@arm.com
5044999Sgblack@eecs.umich.eduvoid
5054999Sgblack@eecs.umich.eduAbstractMemory::unserialize(Checkpoint *cp, const string &section)
5064999Sgblack@eecs.umich.edu{
5074999Sgblack@eecs.umich.edu    if (!pmemAddr)
5084999Sgblack@eecs.umich.edu        return;
5094999Sgblack@eecs.umich.edu
51010563Sandreas.hansson@arm.com    gzFile compressedMem;
5114999Sgblack@eecs.umich.edu    long *tempPage;
5124999Sgblack@eecs.umich.edu    long *pmem_current;
5134999Sgblack@eecs.umich.edu    uint64_t curSize;
5144999Sgblack@eecs.umich.edu    uint32_t bytesRead;
5154999Sgblack@eecs.umich.edu    const uint32_t chunkSize = 16384;
5164878Sstever@eecs.umich.edu
5174040Ssaidi@eecs.umich.edu    string filename;
5184040Ssaidi@eecs.umich.edu
5194999Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(filename);
5204999Sgblack@eecs.umich.edu
5214999Sgblack@eecs.umich.edu    filename = cp->cptDir + "/" + filename;
5224999Sgblack@eecs.umich.edu
52310760Ssteve.reinhardt@amd.com    // mmap memoryfile
5246078Sgblack@eecs.umich.edu    int fd = open(filename.c_str(), O_RDONLY);
5256078Sgblack@eecs.umich.edu    if (fd < 0) {
5266078Sgblack@eecs.umich.edu        perror("open");
52711147Smitch.hayenga@arm.com        fatal("Can't open physical memory checkpoint file '%s'", filename);
52811147Smitch.hayenga@arm.com    }
5296739Sgblack@eecs.umich.edu
5306739Sgblack@eecs.umich.edu    compressedMem = gzdopen(fd, "rb");
5316739Sgblack@eecs.umich.edu    if (compressedMem == NULL)
5326739Sgblack@eecs.umich.edu        fatal("Insufficient memory to allocate compression state for %s\n",
5336739Sgblack@eecs.umich.edu                filename);
5343170Sstever@eecs.umich.edu
5353170Sstever@eecs.umich.edu    // unmap file that was mmapped in the constructor
5364999Sgblack@eecs.umich.edu    // This is done here to make sure that gzip and open don't muck with our
5374999Sgblack@eecs.umich.edu    // nice large space of memory before we reallocate it
5384999Sgblack@eecs.umich.edu    munmap((char*)pmemAddr, size());
5394999Sgblack@eecs.umich.edu
5404999Sgblack@eecs.umich.edu    long _size;
5417520Sgblack@eecs.umich.edu    UNSERIALIZE_SCALAR(_size);
5424999Sgblack@eecs.umich.edu    if (_size > params()->range.size())
5437520Sgblack@eecs.umich.edu        fatal("Memory size has changed! size %lld, param size %lld\n",
5444999Sgblack@eecs.umich.edu              _size, params()->range.size());
5454999Sgblack@eecs.umich.edu
5462623SN/A    pmemAddr = (uint8_t *)mmap(NULL, size(),
5472623SN/A        PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
5482623SN/A
5492623SN/A    if (pmemAddr == (void *)MAP_FAILED) {
5502623SN/A        perror("mmap");
5512623SN/A        fatal("Could not mmap physical memory!\n");
5522623SN/A    }
5534940Snate@binkert.org
5544940Snate@binkert.org    curSize = 0;
55511147Smitch.hayenga@arm.com    tempPage = (long*)malloc(chunkSize);
55611147Smitch.hayenga@arm.com    if (tempPage == NULL)
55711147Smitch.hayenga@arm.com        fatal("Unable to malloc memory to read file %s\n", filename);
55811147Smitch.hayenga@arm.com
55911147Smitch.hayenga@arm.com    /* Only copy bytes that are non-zero, so we don't give the VM system hell */
56011148Smitch.hayenga@arm.com    while (curSize < size()) {
56111148Smitch.hayenga@arm.com        bytesRead = gzread(compressedMem, tempPage, chunkSize);
56211435Smitch.hayenga@arm.com        if (bytesRead == 0)
56311435Smitch.hayenga@arm.com            break;
56411435Smitch.hayenga@arm.com
56511147Smitch.hayenga@arm.com        assert(bytesRead % sizeof(long) == 0);
56611147Smitch.hayenga@arm.com
56711147Smitch.hayenga@arm.com        for (uint32_t x = 0; x < bytesRead / sizeof(long); x++)
56811147Smitch.hayenga@arm.com        {
56911147Smitch.hayenga@arm.com             if (*(tempPage+x) != 0) {
5705487Snate@binkert.org                 pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long));
5712623SN/A                 *pmem_current = *(tempPage+x);
5726078Sgblack@eecs.umich.edu             }
5732623SN/A        }
57410464SAndreas.Sandberg@ARM.com        curSize += bytesRead;
5752623SN/A    }
57610596Sgabeblack@google.com
5773387Sgblack@eecs.umich.edu    free(tempPage);
57810596Sgabeblack@google.com
57910596Sgabeblack@google.com    if (gzclose(compressedMem))
5802626SN/A        fatal("Close failed on physical memory checkpoint file '%s'\n",
5818143SAli.Saidi@ARM.com              filename);
5829443SAndreas.Sandberg@ARM.com
5839443SAndreas.Sandberg@ARM.com    vector<Addr> lal_addr;
5848143SAli.Saidi@ARM.com    vector<int> lal_cid;
5859443SAndreas.Sandberg@ARM.com    arrayParamIn(cp, section, "lal_addr", lal_addr);
5865348Ssaidi@eecs.umich.edu    arrayParamIn(cp, section, "lal_cid", lal_cid);
5875669Sgblack@eecs.umich.edu    for(int i = 0; i < lal_addr.size(); i++)
5885669Sgblack@eecs.umich.edu        lockedAddrList.push_front(LockedAddr(lal_addr[i], lal_cid[i]));
5897720Sgblack@eecs.umich.edu}
5907720Sgblack@eecs.umich.edu