abstract_mem.cc revision 4052
12968SN/A/*
22968SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan
310409Sandreas.hansson@arm.com * All rights reserved.
411754Sandreas.hansson@arm.com *
511754Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
68721SN/A * modification, are permitted provided that the following conditions are
711754Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
811754Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
911754Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
1011754Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
1111754Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
1211336Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
1311336Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
1410036SAli.Saidi@ARM.com * this software without specific prior written permission.
1510036SAli.Saidi@ARM.com *
1611754Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1711201Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1811606Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1911336Sandreas.hansson@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2011606Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2110352Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2211606Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2311201Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2411336Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2511336Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2611606Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2711606Sandreas.sandberg@arm.com *
2811201Sandreas.hansson@arm.com * Authors: Ron Dreslinski
2911606Sandreas.sandberg@arm.com *          Ali Saidi
3011336Sandreas.hansson@arm.com */
3111606Sandreas.sandberg@arm.com
3210352Sandreas.hansson@arm.com#include <sys/types.h>
3311606Sandreas.sandberg@arm.com#include <sys/mman.h>
3411606Sandreas.sandberg@arm.com#include <errno.h>
3511606Sandreas.sandberg@arm.com#include <fcntl.h>
3611201Sandreas.hansson@arm.com#include <unistd.h>
3711754Sandreas.hansson@arm.com#include <zlib.h>
3811336Sandreas.hansson@arm.com
3911606Sandreas.sandberg@arm.com#include <iostream>
4010409Sandreas.hansson@arm.com#include <string>
4111754Sandreas.hansson@arm.com
4211201Sandreas.hansson@arm.com#include "arch/isa_traits.hh"
4311336Sandreas.hansson@arm.com#include "base/misc.hh"
4411336Sandreas.hansson@arm.com#include "config/full_system.hh"
4511606Sandreas.sandberg@arm.com#include "mem/packet_access.hh"
4611606Sandreas.sandberg@arm.com#include "mem/physical.hh"
4711606Sandreas.sandberg@arm.com#include "sim/builder.hh"
4811201Sandreas.hansson@arm.com#include "sim/eventq.hh"
4911754Sandreas.hansson@arm.com#include "sim/host.hh"
5011336Sandreas.hansson@arm.com
5111606Sandreas.sandberg@arm.comusing namespace std;
5210585Sandreas.hansson@arm.comusing namespace TheISA;
5311754Sandreas.hansson@arm.com
5411754Sandreas.hansson@arm.comPhysicalMemory::PhysicalMemory(Params *p)
5511754Sandreas.hansson@arm.com    : MemObject(p->name), pmemAddr(NULL), port(NULL), lat(p->latency), _params(p)
5610036SAli.Saidi@ARM.com{
578721SN/A    if (params()->addrRange.size() % TheISA::PageBytes != 0)
588721SN/A        panic("Memory Size not divisible by page size\n");
598721SN/A
608721SN/A    int map_flags = MAP_ANON | MAP_PRIVATE;
6111336Sandreas.hansson@arm.com    pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE,
6210409Sandreas.hansson@arm.com            map_flags, -1, 0);
638721SN/A
6410409Sandreas.hansson@arm.com    if (pmemAddr == (void *)MAP_FAILED) {
6511336Sandreas.hansson@arm.com        perror("mmap");
6610409Sandreas.hansson@arm.com        fatal("Could not mmap!\n");
6710409Sandreas.hansson@arm.com    }
6810409Sandreas.hansson@arm.com
6911336Sandreas.hansson@arm.com    //If requested, initialize all the memory to 0
7010409Sandreas.hansson@arm.com    if(params()->zero)
7110409Sandreas.hansson@arm.com        memset(pmemAddr, 0, params()->addrRange.size());
7210409Sandreas.hansson@arm.com
7311336Sandreas.hansson@arm.com    pagePtr = 0;
7410409Sandreas.hansson@arm.com}
758721SN/A
7611336Sandreas.hansson@arm.comvoid
778721SN/APhysicalMemory::init()
788721SN/A{
798721SN/A    if (!port)
808721SN/A        panic("PhysicalMemory not connected to anything!");
818721SN/A    port->sendStatusChange(Port::RangeChange);
828721SN/A}
838721SN/A
848721SN/APhysicalMemory::~PhysicalMemory()
856024SN/A{
866024SN/A    if (pmemAddr)
878721SN/A        munmap((char*)pmemAddr, params()->addrRange.size());
888721SN/A    //Remove memPorts?
8911530Sandreas.sandberg@arm.com}
9011530Sandreas.sandberg@arm.com
9111754Sandreas.hansson@arm.comAddr
9211754Sandreas.hansson@arm.comPhysicalMemory::new_page()
9311530Sandreas.sandberg@arm.com{
9411530Sandreas.sandberg@arm.com    Addr return_addr = pagePtr << LogVMPageSize;
9511530Sandreas.sandberg@arm.com    return_addr += start();
9611530Sandreas.sandberg@arm.com
9711530Sandreas.sandberg@arm.com    ++pagePtr;
9811754Sandreas.hansson@arm.com    return return_addr;
9911754Sandreas.hansson@arm.com}
1008721SN/A
1018721SN/Aint
1022968SN/APhysicalMemory::deviceBlockSize()
10310409Sandreas.hansson@arm.com{
10411336Sandreas.hansson@arm.com    //Can accept anysize request
10510409Sandreas.hansson@arm.com    return 0;
10611336Sandreas.hansson@arm.com}
10710409Sandreas.hansson@arm.com
10810409Sandreas.hansson@arm.comTick
10911336Sandreas.hansson@arm.comPhysicalMemory::calculateLatency(PacketPtr pkt)
11011336Sandreas.hansson@arm.com{
11110409Sandreas.hansson@arm.com    return lat;
11210409Sandreas.hansson@arm.com}
11310409Sandreas.hansson@arm.com
11410409Sandreas.hansson@arm.com
11510409Sandreas.hansson@arm.com
11610409Sandreas.hansson@arm.com// Add load-locked to tracking list.  Should only be called if the
11711754Sandreas.hansson@arm.com// operation is a load and the LOCKED flag is set.
11810409Sandreas.hansson@arm.comvoid
11910409Sandreas.hansson@arm.comPhysicalMemory::trackLoadLocked(Request *req)
12010409Sandreas.hansson@arm.com{
12111336Sandreas.hansson@arm.com    Addr paddr = LockedAddr::mask(req->getPaddr());
12211754Sandreas.hansson@arm.com
12310409Sandreas.hansson@arm.com    // first we check if we already have a locked addr for this
1246127SN/A    // xc.  Since each xc only gets one, we just update the
1256127SN/A    // existing record with the new address.
1266127SN/A    list<LockedAddr>::iterator i;
12711336Sandreas.hansson@arm.com
12811336Sandreas.hansson@arm.com    for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) {
1298721SN/A        if (i->matchesContext(req)) {
13010409Sandreas.hansson@arm.com            DPRINTF(LLSC, "Modifying lock record: cpu %d thread %d addr %#x\n",
13110409Sandreas.hansson@arm.com                    req->getCpuNum(), req->getThreadNum(), paddr);
13210409Sandreas.hansson@arm.com            i->addr = paddr;
13310409Sandreas.hansson@arm.com            return;
13410409Sandreas.hansson@arm.com        }
13510409Sandreas.hansson@arm.com    }
13610409Sandreas.hansson@arm.com
13711336Sandreas.hansson@arm.com    // no record for this xc: need to allocate a new one
13810409Sandreas.hansson@arm.com    DPRINTF(LLSC, "Adding lock record: cpu %d thread %d addr %#x\n",
13910409Sandreas.hansson@arm.com            req->getCpuNum(), req->getThreadNum(), paddr);
14010409Sandreas.hansson@arm.com    lockedAddrList.push_front(LockedAddr(req));
14110409Sandreas.hansson@arm.com}
14210409Sandreas.hansson@arm.com
14310409Sandreas.hansson@arm.com
14410409Sandreas.hansson@arm.com// Called on *writes* only... both regular stores and
14510409Sandreas.hansson@arm.com// store-conditional operations.  Check for conventional stores which
14611336Sandreas.hansson@arm.com// conflict with locked addresses, and for success/failure of store
14710409Sandreas.hansson@arm.com// conditionals.
14811336Sandreas.hansson@arm.combool
1498721SN/APhysicalMemory::checkLockedAddrList(Request *req)
15011336Sandreas.hansson@arm.com{
15111336Sandreas.hansson@arm.com    Addr paddr = LockedAddr::mask(req->getPaddr());
1528721SN/A    bool isLocked = req->isLocked();
15311336Sandreas.hansson@arm.com
1548721SN/A    // Initialize return value.  Non-conditional stores always
1558983Snate@binkert.org    // succeed.  Assume conditional stores will fail until proven
15611336Sandreas.hansson@arm.com    // otherwise.
15711754Sandreas.hansson@arm.com    bool success = !isLocked;
15811336Sandreas.hansson@arm.com
1598721SN/A    // Iterate over list.  Note that there could be multiple matching
16010409Sandreas.hansson@arm.com    // records, as more than one context could have done a load locked
16111336Sandreas.hansson@arm.com    // to this location.
16211336Sandreas.hansson@arm.com    list<LockedAddr>::iterator i = lockedAddrList.begin();
16311336Sandreas.hansson@arm.com
16411201Sandreas.hansson@arm.com    while (i != lockedAddrList.end()) {
16511336Sandreas.hansson@arm.com
16611336Sandreas.hansson@arm.com        if (i->addr == paddr) {
16711336Sandreas.hansson@arm.com            // we have a matching address
16811201Sandreas.hansson@arm.com
16911336Sandreas.hansson@arm.com            if (isLocked && i->matchesContext(req)) {
17011336Sandreas.hansson@arm.com                // it's a store conditional, and as far as the memory
17111201Sandreas.hansson@arm.com                // system can tell, the requesting context's lock is
17211201Sandreas.hansson@arm.com                // still valid.
17311336Sandreas.hansson@arm.com                DPRINTF(LLSC, "StCond success: cpu %d thread %d addr %#x\n",
17411336Sandreas.hansson@arm.com                        req->getCpuNum(), req->getThreadNum(), paddr);
17511336Sandreas.hansson@arm.com                success = true;
17611754Sandreas.hansson@arm.com            }
17711754Sandreas.hansson@arm.com
17811201Sandreas.hansson@arm.com            // Get rid of our record of this lock and advance to next
17911201Sandreas.hansson@arm.com            DPRINTF(LLSC, "Erasing lock record: cpu %d thread %d addr %#x\n",
18011336Sandreas.hansson@arm.com                    i->cpuNum, i->threadNum, paddr);
18111336Sandreas.hansson@arm.com            i = lockedAddrList.erase(i);
18211336Sandreas.hansson@arm.com        }
18311336Sandreas.hansson@arm.com        else {
18411201Sandreas.hansson@arm.com            // no match: advance to next record
18511201Sandreas.hansson@arm.com            ++i;
18611201Sandreas.hansson@arm.com        }
18711201Sandreas.hansson@arm.com    }
18811201Sandreas.hansson@arm.com
18911687Sandreas.hansson@arm.com    if (isLocked) {
19011201Sandreas.hansson@arm.com        req->setExtraData(success ? 1 : 0);
19111687Sandreas.hansson@arm.com    }
19211201Sandreas.hansson@arm.com
19311201Sandreas.hansson@arm.com    return success;
19411201Sandreas.hansson@arm.com}
19511201Sandreas.hansson@arm.com
19611201Sandreas.hansson@arm.comvoid
19711201Sandreas.hansson@arm.comPhysicalMemory::doFunctionalAccess(PacketPtr pkt)
19811201Sandreas.hansson@arm.com{
19911201Sandreas.hansson@arm.com    assert(pkt->getAddr() >= start() &&
20011201Sandreas.hansson@arm.com           pkt->getAddr() + pkt->getSize() <= start() + size());
20111201Sandreas.hansson@arm.com
20211201Sandreas.hansson@arm.com    if (pkt->isRead()) {
20311201Sandreas.hansson@arm.com        if (pkt->req->isLocked()) {
20411201Sandreas.hansson@arm.com            trackLoadLocked(pkt->req);
20511201Sandreas.hansson@arm.com        }
20611201Sandreas.hansson@arm.com        memcpy(pkt->getPtr<uint8_t>(), pmemAddr + pkt->getAddr() - start(),
20711201Sandreas.hansson@arm.com               pkt->getSize());
20811201Sandreas.hansson@arm.com#if TRACING_ON
20911201Sandreas.hansson@arm.com        switch (pkt->getSize()) {
21011201Sandreas.hansson@arm.com          case sizeof(uint64_t):
21111201Sandreas.hansson@arm.com            DPRINTF(MemoryAccess, "Read of size %i on address 0x%x data 0x%x\n",
21211201Sandreas.hansson@arm.com                    pkt->getSize(), pkt->getAddr(),pkt->get<uint64_t>());
21311687Sandreas.hansson@arm.com            break;
21411687Sandreas.hansson@arm.com          case sizeof(uint32_t):
21511687Sandreas.hansson@arm.com            DPRINTF(MemoryAccess, "Read of size %i on address 0x%x data 0x%x\n",
21611687Sandreas.hansson@arm.com                    pkt->getSize(), pkt->getAddr(),pkt->get<uint32_t>());
21711336Sandreas.hansson@arm.com            break;
21811201Sandreas.hansson@arm.com          case sizeof(uint16_t):
21911336Sandreas.hansson@arm.com            DPRINTF(MemoryAccess, "Read of size %i on address 0x%x data 0x%x\n",
22011754Sandreas.hansson@arm.com                    pkt->getSize(), pkt->getAddr(),pkt->get<uint16_t>());
22111502SCurtis.Dunham@arm.com            break;
22211754Sandreas.hansson@arm.com          case sizeof(uint8_t):
22311502SCurtis.Dunham@arm.com            DPRINTF(MemoryAccess, "Read of size %i on address 0x%x data 0x%x\n",
22411502SCurtis.Dunham@arm.com                    pkt->getSize(), pkt->getAddr(),pkt->get<uint8_t>());
22511502SCurtis.Dunham@arm.com            break;
22610585Sandreas.hansson@arm.com          default:
22711754Sandreas.hansson@arm.com            DPRINTF(MemoryAccess, "Read of size %i on address 0x%x\n",
22810585Sandreas.hansson@arm.com                    pkt->getSize(), pkt->getAddr());
22910585Sandreas.hansson@arm.com        }
23010585Sandreas.hansson@arm.com#endif
23110585Sandreas.hansson@arm.com    }
23210585Sandreas.hansson@arm.com    else if (pkt->isWrite()) {
23310585Sandreas.hansson@arm.com        if (writeOK(pkt->req)) {
23410585Sandreas.hansson@arm.com                memcpy(pmemAddr + pkt->getAddr() - start(), pkt->getPtr<uint8_t>(),
23511502SCurtis.Dunham@arm.com                        pkt->getSize());
23611502SCurtis.Dunham@arm.com#if TRACING_ON
23711754Sandreas.hansson@arm.com            switch (pkt->getSize()) {
23811502SCurtis.Dunham@arm.com              case sizeof(uint64_t):
23911502SCurtis.Dunham@arm.com                DPRINTF(MemoryAccess, "Write of size %i on address 0x%x data 0x%x\n",
24011606Sandreas.sandberg@arm.com                        pkt->getSize(), pkt->getAddr(),pkt->get<uint64_t>());
24111606Sandreas.sandberg@arm.com                break;
24211336Sandreas.hansson@arm.com              case sizeof(uint32_t):
24311336Sandreas.hansson@arm.com                DPRINTF(MemoryAccess, "Write of size %i on address 0x%x data 0x%x\n",
24411606Sandreas.sandberg@arm.com                        pkt->getSize(), pkt->getAddr(),pkt->get<uint32_t>());
24511606Sandreas.sandberg@arm.com                break;
24611606Sandreas.sandberg@arm.com              case sizeof(uint16_t):
24711606Sandreas.sandberg@arm.com                DPRINTF(MemoryAccess, "Write of size %i on address 0x%x data 0x%x\n",
24811606Sandreas.sandberg@arm.com                        pkt->getSize(), pkt->getAddr(),pkt->get<uint16_t>());
24911606Sandreas.sandberg@arm.com                break;
25011502SCurtis.Dunham@arm.com              case sizeof(uint8_t):
25111502SCurtis.Dunham@arm.com                DPRINTF(MemoryAccess, "Write of size %i on address 0x%x data 0x%x\n",
25211606Sandreas.sandberg@arm.com                        pkt->getSize(), pkt->getAddr(),pkt->get<uint8_t>());
25311606Sandreas.sandberg@arm.com                break;
25411336Sandreas.hansson@arm.com              default:
25511336Sandreas.hansson@arm.com                DPRINTF(MemoryAccess, "Write of size %i on address 0x%x\n",
25611606Sandreas.sandberg@arm.com                        pkt->getSize(), pkt->getAddr());
25711606Sandreas.sandberg@arm.com            }
25811606Sandreas.sandberg@arm.com#endif
25911606Sandreas.sandberg@arm.com        }
26011606Sandreas.sandberg@arm.com    } else if (pkt->isInvalidate()) {
26111606Sandreas.sandberg@arm.com        //upgrade or invalidate
26211336Sandreas.hansson@arm.com        pkt->flags |= SATISFIED;
26311336Sandreas.hansson@arm.com    } else if (pkt->isReadWrite()) {
26411336Sandreas.hansson@arm.com        IntReg overwrite_val;
26511336Sandreas.hansson@arm.com        bool overwrite_mem;
26610585Sandreas.hansson@arm.com        uint64_t condition_val64;
26710585Sandreas.hansson@arm.com        uint32_t condition_val32;
26810585Sandreas.hansson@arm.com
26910585Sandreas.hansson@arm.com        assert(sizeof(IntReg) >= pkt->getSize());
27011336Sandreas.hansson@arm.com
27111336Sandreas.hansson@arm.com        overwrite_mem = true;
27211336Sandreas.hansson@arm.com        // keep a copy of our possible write value, and copy what is at the
27311336Sandreas.hansson@arm.com        // memory address into the packet
27411336Sandreas.hansson@arm.com        std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize());
27511336Sandreas.hansson@arm.com        std::memcpy(pkt->getPtr<uint8_t>(), pmemAddr + pkt->getAddr() - start(),
27611606Sandreas.sandberg@arm.com               pkt->getSize());
27711606Sandreas.sandberg@arm.com
27811336Sandreas.hansson@arm.com        if (pkt->req->isCondSwap()) {
27911336Sandreas.hansson@arm.com            if (pkt->getSize() == sizeof(uint64_t)) {
28011606Sandreas.sandberg@arm.com                condition_val64 = pkt->req->getExtraData();
28111606Sandreas.sandberg@arm.com                overwrite_mem = !std::memcmp(&condition_val64, pmemAddr +
28211606Sandreas.sandberg@arm.com                        pkt->getAddr() - start(), sizeof(uint64_t));
28311606Sandreas.sandberg@arm.com            } else if (pkt->getSize() == sizeof(uint32_t)) {
28411606Sandreas.sandberg@arm.com                condition_val32 = (uint32_t)pkt->req->getExtraData();
28511606Sandreas.sandberg@arm.com                overwrite_mem = !std::memcmp(&condition_val32, pmemAddr +
28610585Sandreas.hansson@arm.com                        pkt->getAddr() - start(), sizeof(uint32_t));
28710585Sandreas.hansson@arm.com            } else
28810585Sandreas.hansson@arm.com                panic("Invalid size for conditional read/write\n");
28910585Sandreas.hansson@arm.com        }
29010585Sandreas.hansson@arm.com
29110585Sandreas.hansson@arm.com        if (overwrite_mem)
29211606Sandreas.sandberg@arm.com            std::memcpy(pmemAddr + pkt->getAddr() - start(),
29311606Sandreas.sandberg@arm.com               &overwrite_val, pkt->getSize());
29411754Sandreas.hansson@arm.com
29511336Sandreas.hansson@arm.com#if TRACING_ON
29611336Sandreas.hansson@arm.com        switch (pkt->getSize()) {
29711336Sandreas.hansson@arm.com          case sizeof(uint64_t):
29811336Sandreas.hansson@arm.com            DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n",
29911336Sandreas.hansson@arm.com                    pkt->getSize(), pkt->getAddr(),pkt->get<uint64_t>());
30010409Sandreas.hansson@arm.com            DPRINTF(MemoryAccess, "New Data 0x%x %s conditional (0x%x) and %s \n",
30111336Sandreas.hansson@arm.com                    overwrite_mem, pkt->req->isCondSwap() ? "was" : "wasn't",
30210409Sandreas.hansson@arm.com                    condition_val64, overwrite_mem ? "happened" : "didn't happen");
30310409Sandreas.hansson@arm.com            break;
30410036SAli.Saidi@ARM.com          case sizeof(uint32_t):
30510409Sandreas.hansson@arm.com            DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n",
30610409Sandreas.hansson@arm.com                    pkt->getSize(), pkt->getAddr(),pkt->get<uint32_t>());
30710409Sandreas.hansson@arm.com            DPRINTF(MemoryAccess, "New Data 0x%x %s conditional (0x%x) and %s \n",
30810036SAli.Saidi@ARM.com                    overwrite_mem, pkt->req->isCondSwap() ? "was" : "wasn't",
30911336Sandreas.hansson@arm.com                    condition_val32, overwrite_mem ? "happened" : "didn't happen");
31011336Sandreas.hansson@arm.com            break;
31111754Sandreas.hansson@arm.com          case sizeof(uint16_t):
31211336Sandreas.hansson@arm.com            DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n",
31311336Sandreas.hansson@arm.com                    pkt->getSize(), pkt->getAddr(),pkt->get<uint16_t>());
31411336Sandreas.hansson@arm.com            DPRINTF(MemoryAccess, "New Data 0x%x wasn't conditional and happned\n",
31511336Sandreas.hansson@arm.com                    overwrite_mem);
31611336Sandreas.hansson@arm.com            break;
31711336Sandreas.hansson@arm.com          case sizeof(uint8_t):
31811336Sandreas.hansson@arm.com            DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n",
31911336Sandreas.hansson@arm.com                    pkt->getSize(), pkt->getAddr(),pkt->get<uint8_t>());
32011336Sandreas.hansson@arm.com            DPRINTF(MemoryAccess, "New Data 0x%x wasn't conditional and happned\n",
32111336Sandreas.hansson@arm.com                    overwrite_mem);
32211336Sandreas.hansson@arm.com            break;
32311336Sandreas.hansson@arm.com          default:
32411336Sandreas.hansson@arm.com            DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x\n",
32511336Sandreas.hansson@arm.com                    pkt->getSize(), pkt->getAddr());
32611336Sandreas.hansson@arm.com        }
32711336Sandreas.hansson@arm.com#endif
32811336Sandreas.hansson@arm.com    } else {
32911336Sandreas.hansson@arm.com        panic("unimplemented");
33010409Sandreas.hansson@arm.com    }
33110409Sandreas.hansson@arm.com
33210409Sandreas.hansson@arm.com    pkt->result = Packet::Success;
33310409Sandreas.hansson@arm.com}
33410409Sandreas.hansson@arm.com
33510409Sandreas.hansson@arm.comPort *
3368721SN/APhysicalMemory::getPort(const std::string &if_name, int idx)
3378721SN/A{
3388721SN/A    if (if_name == "port" && idx == -1) {
3398721SN/A        if (port != NULL)
3408983Snate@binkert.org           panic("PhysicalMemory::getPort: additional port requested to memory!");
3418983Snate@binkert.org        port = new MemoryPort(name() + "-port", this);
34211336Sandreas.hansson@arm.com        return port;
34311336Sandreas.hansson@arm.com    } else if (if_name == "functional") {
3448721SN/A        /* special port for functional writes at startup. And for memtester */
3458721SN/A        return new MemoryPort(name() + "-funcport", this);
3468721SN/A    } else {
3478721SN/A        panic("PhysicalMemory::getPort: unknown port %s requested", if_name);
34811336Sandreas.hansson@arm.com    }
34910409Sandreas.hansson@arm.com}
3508721SN/A
35110409Sandreas.hansson@arm.comvoid
35210409Sandreas.hansson@arm.comPhysicalMemory::recvStatusChange(Port::Status status)
35310409Sandreas.hansson@arm.com{
35410409Sandreas.hansson@arm.com}
35510409Sandreas.hansson@arm.com
35611336Sandreas.hansson@arm.comPhysicalMemory::MemoryPort::MemoryPort(const std::string &_name,
35710409Sandreas.hansson@arm.com                                       PhysicalMemory *_memory)
35810409Sandreas.hansson@arm.com    : SimpleTimingPort(_name), memory(_memory)
35910409Sandreas.hansson@arm.com{ }
36010409Sandreas.hansson@arm.com
36110409Sandreas.hansson@arm.comvoid
3628721SN/APhysicalMemory::MemoryPort::recvStatusChange(Port::Status status)
36310409Sandreas.hansson@arm.com{
3648721SN/A    memory->recvStatusChange(status);
3658721SN/A}
3668721SN/A
3678721SN/Avoid
3688721SN/APhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp,
3698721SN/A                                            AddrRangeList &snoop)
3708721SN/A{
3718721SN/A    memory->getAddressRanges(resp, snoop);
3726024SN/A}
3736024SN/A
3748721SN/Avoid
3758721SN/APhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
37611530Sandreas.sandberg@arm.com{
37711530Sandreas.sandberg@arm.com    snoop.clear();
37811754Sandreas.hansson@arm.com    resp.clear();
37911754Sandreas.hansson@arm.com    resp.push_back(RangeSize(start(),
38011530Sandreas.sandberg@arm.com                             params()->addrRange.size()));
38111530Sandreas.sandberg@arm.com}
38211530Sandreas.sandberg@arm.com
38311530Sandreas.sandberg@arm.comint
38411530Sandreas.sandberg@arm.comPhysicalMemory::MemoryPort::deviceBlockSize()
38511754Sandreas.hansson@arm.com{
38611754Sandreas.hansson@arm.com    return memory->deviceBlockSize();
3878721SN/A}
3888721SN/A
3892968SN/ATick
39010409Sandreas.hansson@arm.comPhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt)
39110409Sandreas.hansson@arm.com{
39210409Sandreas.hansson@arm.com    memory->doFunctionalAccess(pkt);
39310409Sandreas.hansson@arm.com    return memory->calculateLatency(pkt);
39410409Sandreas.hansson@arm.com}
39510409Sandreas.hansson@arm.com
39610409Sandreas.hansson@arm.comvoid
39710409Sandreas.hansson@arm.comPhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt)
39810409Sandreas.hansson@arm.com{
39910409Sandreas.hansson@arm.com    //Since we are overriding the function, make sure to have the impl of the
40010409Sandreas.hansson@arm.com    //check or functional accesses here.
40110409Sandreas.hansson@arm.com    std::list<std::pair<Tick,PacketPtr> >::iterator i = transmitList.begin();
40211754Sandreas.hansson@arm.com    std::list<std::pair<Tick,PacketPtr> >::iterator end = transmitList.end();
40310409Sandreas.hansson@arm.com    bool notDone = true;
40410409Sandreas.hansson@arm.com
40511336Sandreas.hansson@arm.com    while (i != end && notDone) {
40611754Sandreas.hansson@arm.com        PacketPtr target = i->second;
40710409Sandreas.hansson@arm.com        // If the target contains data, and it overlaps the
4086127SN/A        // probed request, need to update data
4096127SN/A        if (target->intersect(pkt))
41010409Sandreas.hansson@arm.com            notDone = fixPacket(pkt, target);
41110409Sandreas.hansson@arm.com        i++;
4128721SN/A    }
41310409Sandreas.hansson@arm.com
41410409Sandreas.hansson@arm.com    // Default implementation of SimpleTimingPort::recvFunctional()
41510409Sandreas.hansson@arm.com    // calls recvAtomic() and throws away the latency; we can save a
41610409Sandreas.hansson@arm.com    // little here by just not calculating the latency.
41710409Sandreas.hansson@arm.com    memory->doFunctionalAccess(pkt);
41810409Sandreas.hansson@arm.com}
41910409Sandreas.hansson@arm.com
42010409Sandreas.hansson@arm.comunsigned int
42110409Sandreas.hansson@arm.comPhysicalMemory::drain(Event *de)
42210409Sandreas.hansson@arm.com{
42310409Sandreas.hansson@arm.com    int count = port->drain(de);
42410409Sandreas.hansson@arm.com    if (count)
42510409Sandreas.hansson@arm.com        changeState(Draining);
42610409Sandreas.hansson@arm.com    else
42710409Sandreas.hansson@arm.com        changeState(Drained);
4288721SN/A    return count;
42910409Sandreas.hansson@arm.com}
43010409Sandreas.hansson@arm.com
43110409Sandreas.hansson@arm.comvoid
43210409Sandreas.hansson@arm.comPhysicalMemory::serialize(ostream &os)
43310409Sandreas.hansson@arm.com{
43410409Sandreas.hansson@arm.com    gzFile compressedMem;
43510409Sandreas.hansson@arm.com    string filename = name() + ".physmem";
43610409Sandreas.hansson@arm.com
4378721SN/A    SERIALIZE_SCALAR(filename);
43810409Sandreas.hansson@arm.com
43910409Sandreas.hansson@arm.com    // write memory file
44011336Sandreas.hansson@arm.com    string thefile = Checkpoint::dir() + "/" + filename.c_str();
44110409Sandreas.hansson@arm.com    int fd = creat(thefile.c_str(), 0664);
44211754Sandreas.hansson@arm.com    if (fd < 0) {
44310409Sandreas.hansson@arm.com        perror("creat");
44411336Sandreas.hansson@arm.com        fatal("Can't open physical memory checkpoint file '%s'\n", filename);
44511336Sandreas.hansson@arm.com    }
44611336Sandreas.hansson@arm.com
44711201Sandreas.hansson@arm.com    compressedMem = gzdopen(fd, "wb");
44811201Sandreas.hansson@arm.com    if (compressedMem == NULL)
44911336Sandreas.hansson@arm.com        fatal("Insufficient memory to allocate compression state for %s\n",
45011336Sandreas.hansson@arm.com                filename);
45111201Sandreas.hansson@arm.com
45211336Sandreas.hansson@arm.com    if (gzwrite(compressedMem, pmemAddr, params()->addrRange.size()) != params()->addrRange.size()) {
45311336Sandreas.hansson@arm.com        fatal("Write failed on physical memory checkpoint file '%s'\n",
45411201Sandreas.hansson@arm.com              filename);
45511201Sandreas.hansson@arm.com    }
45611336Sandreas.hansson@arm.com
45711336Sandreas.hansson@arm.com    if (gzclose(compressedMem))
45811201Sandreas.hansson@arm.com        fatal("Close failed on physical memory checkpoint file '%s'\n",
45911754Sandreas.hansson@arm.com              filename);
46011754Sandreas.hansson@arm.com}
46111201Sandreas.hansson@arm.com
46211201Sandreas.hansson@arm.comvoid
46311336Sandreas.hansson@arm.comPhysicalMemory::unserialize(Checkpoint *cp, const string &section)
46411201Sandreas.hansson@arm.com{
46511336Sandreas.hansson@arm.com    gzFile compressedMem;
46611201Sandreas.hansson@arm.com    long *tempPage;
46711201Sandreas.hansson@arm.com    long *pmem_current;
46811201Sandreas.hansson@arm.com    uint64_t curSize;
46911201Sandreas.hansson@arm.com    uint32_t bytesRead;
47011201Sandreas.hansson@arm.com    const int chunkSize = 16384;
47111201Sandreas.hansson@arm.com
47211687Sandreas.hansson@arm.com
47311201Sandreas.hansson@arm.com    string filename;
47411687Sandreas.hansson@arm.com
47511201Sandreas.hansson@arm.com    UNSERIALIZE_SCALAR(filename);
47611201Sandreas.hansson@arm.com
47711201Sandreas.hansson@arm.com    filename = cp->cptDir + "/" + filename;
47811201Sandreas.hansson@arm.com
47911201Sandreas.hansson@arm.com    // mmap memoryfile
48011201Sandreas.hansson@arm.com    int fd = open(filename.c_str(), O_RDONLY);
48111201Sandreas.hansson@arm.com    if (fd < 0) {
48211201Sandreas.hansson@arm.com        perror("open");
48311201Sandreas.hansson@arm.com        fatal("Can't open physical memory checkpoint file '%s'", filename);
48411201Sandreas.hansson@arm.com    }
48511201Sandreas.hansson@arm.com
48611201Sandreas.hansson@arm.com    compressedMem = gzdopen(fd, "rb");
48711201Sandreas.hansson@arm.com    if (compressedMem == NULL)
48811201Sandreas.hansson@arm.com        fatal("Insufficient memory to allocate compression state for %s\n",
48911201Sandreas.hansson@arm.com                filename);
49011201Sandreas.hansson@arm.com
49111201Sandreas.hansson@arm.com    // unmap file that was mmaped in the constructor
49211201Sandreas.hansson@arm.com    // This is done here to make sure that gzip and open don't muck with our
49311201Sandreas.hansson@arm.com    // nice large space of memory before we reallocate it
49411201Sandreas.hansson@arm.com    munmap((char*)pmemAddr, params()->addrRange.size());
49511201Sandreas.hansson@arm.com
49611687Sandreas.hansson@arm.com    pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE,
49711687Sandreas.hansson@arm.com                                MAP_ANON | MAP_PRIVATE, -1, 0);
49811687Sandreas.hansson@arm.com
49911687Sandreas.hansson@arm.com    if (pmemAddr == (void *)MAP_FAILED) {
50011201Sandreas.hansson@arm.com        perror("mmap");
50111201Sandreas.hansson@arm.com        fatal("Could not mmap physical memory!\n");
50211336Sandreas.hansson@arm.com    }
50311754Sandreas.hansson@arm.com
50411336Sandreas.hansson@arm.com    curSize = 0;
50511754Sandreas.hansson@arm.com    tempPage = (long*)malloc(chunkSize);
50611336Sandreas.hansson@arm.com    if (tempPage == NULL)
50711336Sandreas.hansson@arm.com        fatal("Unable to malloc memory to read file %s\n", filename);
50811336Sandreas.hansson@arm.com
50910409Sandreas.hansson@arm.com    /* Only copy bytes that are non-zero, so we don't give the VM system hell */
51011754Sandreas.hansson@arm.com    while (curSize < params()->addrRange.size()) {
51111336Sandreas.hansson@arm.com        bytesRead = gzread(compressedMem, tempPage, chunkSize);
51211336Sandreas.hansson@arm.com        if (bytesRead != chunkSize && bytesRead != params()->addrRange.size() - curSize)
51310409Sandreas.hansson@arm.com            fatal("Read failed on physical memory checkpoint file '%s'"
51410409Sandreas.hansson@arm.com                  " got %d bytes, expected %d or %d bytes\n",
51510409Sandreas.hansson@arm.com                  filename, bytesRead, chunkSize, params()->addrRange.size()-curSize);
51610409Sandreas.hansson@arm.com
51711336Sandreas.hansson@arm.com        assert(bytesRead % sizeof(long) == 0);
51811336Sandreas.hansson@arm.com
51911754Sandreas.hansson@arm.com        for (int x = 0; x < bytesRead/sizeof(long); x++)
52011336Sandreas.hansson@arm.com        {
52111336Sandreas.hansson@arm.com             if (*(tempPage+x) != 0) {
52211606Sandreas.sandberg@arm.com                 pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long));
52311606Sandreas.sandberg@arm.com                 *pmem_current = *(tempPage+x);
52411336Sandreas.hansson@arm.com             }
52511336Sandreas.hansson@arm.com        }
52611606Sandreas.sandberg@arm.com        curSize += bytesRead;
52711606Sandreas.sandberg@arm.com    }
52811606Sandreas.sandberg@arm.com
52911606Sandreas.sandberg@arm.com    free(tempPage);
53011606Sandreas.sandberg@arm.com
53111606Sandreas.sandberg@arm.com    if (gzclose(compressedMem))
53211336Sandreas.hansson@arm.com        fatal("Close failed on physical memory checkpoint file '%s'\n",
53311336Sandreas.hansson@arm.com              filename);
53411606Sandreas.sandberg@arm.com
53511606Sandreas.sandberg@arm.com}
53611336Sandreas.hansson@arm.com
53711336Sandreas.hansson@arm.com
53811606Sandreas.sandberg@arm.comBEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
53911606Sandreas.sandberg@arm.com
54011606Sandreas.sandberg@arm.com    Param<string> file;
54111606Sandreas.sandberg@arm.com    Param<Range<Addr> > range;
54211606Sandreas.sandberg@arm.com    Param<Tick> latency;
54311606Sandreas.sandberg@arm.com    Param<bool> zero;
54411336Sandreas.hansson@arm.com
54511336Sandreas.hansson@arm.comEND_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
54610409Sandreas.hansson@arm.com
54710409Sandreas.hansson@arm.comBEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
54810409Sandreas.hansson@arm.com
54910409Sandreas.hansson@arm.com    INIT_PARAM_DFLT(file, "memory mapped file", ""),
55010409Sandreas.hansson@arm.com    INIT_PARAM(range, "Device Address Range"),
55110409Sandreas.hansson@arm.com    INIT_PARAM(latency, "Memory access latency"),
55211336Sandreas.hansson@arm.com    INIT_PARAM(zero, "Zero initialize memory")
55311336Sandreas.hansson@arm.com
55411336Sandreas.hansson@arm.comEND_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
55511336Sandreas.hansson@arm.com
55610409Sandreas.hansson@arm.comCREATE_SIM_OBJECT(PhysicalMemory)
55710409Sandreas.hansson@arm.com{
55811606Sandreas.sandberg@arm.com    PhysicalMemory::Params *p = new PhysicalMemory::Params;
55911606Sandreas.sandberg@arm.com    p->name = getInstanceName();
56011336Sandreas.hansson@arm.com    p->addrRange = range;
56111336Sandreas.hansson@arm.com    p->latency = latency;
56211606Sandreas.sandberg@arm.com    p->zero = zero;
56311606Sandreas.sandberg@arm.com    return new PhysicalMemory(p);
56411606Sandreas.sandberg@arm.com}
56511606Sandreas.sandberg@arm.com
56611606Sandreas.sandberg@arm.comREGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory)
56711606Sandreas.sandberg@arm.com