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