physical.cc revision 8712:7f762428a9f5
11689SN/A/* 22326SN/A * Copyright (c) 2010 ARM Limited 31689SN/A * All rights reserved 41689SN/A * 51689SN/A * The license below extends only to copyright in the software and shall 61689SN/A * not be construed as granting a license to any other intellectual 71689SN/A * property including but not limited to intellectual property relating 81689SN/A * to a hardware implementation of the functionality of the software 91689SN/A * licensed hereunder. You may use the software subject to the license 101689SN/A * terms below provided that you ensure that this notice is replicated 111689SN/A * unmodified and in its entirety in all distributions of the software, 121689SN/A * modified or unmodified, in source code or in binary form. 131689SN/A * 141689SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan 151689SN/A * All rights reserved. 161689SN/A * 171689SN/A * Redistribution and use in source and binary forms, with or without 181689SN/A * modification, are permitted provided that the following conditions are 191689SN/A * met: redistributions of source code must retain the above copyright 201689SN/A * notice, this list of conditions and the following disclaimer; 211689SN/A * redistributions in binary form must reproduce the above copyright 221689SN/A * notice, this list of conditions and the following disclaimer in the 231689SN/A * documentation and/or other materials provided with the distribution; 241689SN/A * neither the name of the copyright holders nor the names of its 251689SN/A * contributors may be used to endorse or promote products derived from 261689SN/A * this software without specific prior written permission. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 291689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 301689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 311060SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 321060SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 331689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 341060SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 351060SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 361060SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 371060SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 386658Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392292SN/A * 401717SN/A * Authors: Ron Dreslinski 415529Snate@binkert.org * Ali Saidi 421060SN/A */ 436221Snate@binkert.org 446221Snate@binkert.org#include <sys/mman.h> 451681SN/A#include <sys/types.h> 465529Snate@binkert.org#include <sys/user.h> 472873Sktlim@umich.edu#include <fcntl.h> 484329Sktlim@umich.edu#include <unistd.h> 494329Sktlim@umich.edu#include <zlib.h> 504329Sktlim@umich.edu 512292SN/A#include <cerrno> 522292SN/A#include <cstdio> 532292SN/A#include <iostream> 542292SN/A#include <string> 552820Sktlim@umich.edu 562292SN/A#include "arch/isa_traits.hh" 572820Sktlim@umich.edu#include "arch/registers.hh" 582820Sktlim@umich.edu#include "base/intmath.hh" 595529Snate@binkert.org#include "base/misc.hh" 602307SN/A#include "base/random.hh" 611060SN/A#include "base/types.hh" 622292SN/A#include "config/full_system.hh" 632292SN/A#include "config/the_isa.hh" 642292SN/A#include "debug/LLSC.hh" 651060SN/A#include "debug/MemoryAccess.hh" 661060SN/A#include "mem/packet_access.hh" 671060SN/A#include "mem/physical.hh" 681060SN/A#include "sim/eventq.hh" 691060SN/A 701060SN/Ausing namespace std; 711681SN/Ausing namespace TheISA; 726221Snate@binkert.org 736221Snate@binkert.orgPhysicalMemory::PhysicalMemory(const Params *p) 746221Snate@binkert.org : MemObject(p), pmemAddr(NULL), lat(p->latency), lat_var(p->latency_var), 756221Snate@binkert.org _size(params()->range.size()), _start(params()->range.start) 762292SN/A{ 772292SN/A if (size() % TheISA::PageBytes != 0) 782820Sktlim@umich.edu panic("Memory Size not divisible by page size\n"); 792820Sktlim@umich.edu 802292SN/A if (params()->null) 812292SN/A return; 822820Sktlim@umich.edu 832820Sktlim@umich.edu 842292SN/A if (params()->file == "") { 852292SN/A int map_flags = MAP_ANON | MAP_PRIVATE; 862292SN/A pmemAddr = (uint8_t *)mmap(NULL, size(), 872292SN/A PROT_READ | PROT_WRITE, map_flags, -1, 0); 882292SN/A } else { 892292SN/A int map_flags = MAP_PRIVATE; 902292SN/A int fd = open(params()->file.c_str(), O_RDONLY); 912292SN/A _size = lseek(fd, 0, SEEK_END); 921060SN/A lseek(fd, 0, SEEK_SET); 931060SN/A pmemAddr = (uint8_t *)mmap(NULL, roundUp(size(), sysconf(_SC_PAGESIZE)), 941681SN/A PROT_READ | PROT_WRITE, map_flags, fd, 0); 951062SN/A } 962292SN/A 971062SN/A if (pmemAddr == (void *)MAP_FAILED) { 982301SN/A perror("mmap"); 992301SN/A if (params()->file == "") 1001062SN/A fatal("Could not mmap!\n"); 1012727Sktlim@umich.edu else 1021062SN/A fatal("Could not find file: %s\n", params()->file); 1031062SN/A } 1041062SN/A 1051062SN/A //If requested, initialize all the memory to 0 1061062SN/A if (p->zero) 1071062SN/A memset(pmemAddr, 0, size()); 1081062SN/A} 1091062SN/A 1101062SN/Avoid 1111062SN/APhysicalMemory::init() 1121062SN/A{ 1131062SN/A if (ports.size() == 0) { 1141062SN/A fatal("PhysicalMemory object %s is unconnected!", name()); 1151062SN/A } 1161062SN/A 1171062SN/A for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) { 1181062SN/A if (*pi) 1191062SN/A (*pi)->sendRangeChange(); 1201062SN/A } 1211062SN/A} 1221062SN/A 1231062SN/APhysicalMemory::~PhysicalMemory() 1241062SN/A{ 1251062SN/A if (pmemAddr) 1261062SN/A munmap((char*)pmemAddr, size()); 1271062SN/A} 1281062SN/A 1291062SN/Aunsigned 1301062SN/APhysicalMemory::deviceBlockSize() const 1311062SN/A{ 1321062SN/A //Can accept anysize request 1331062SN/A return 0; 1341062SN/A} 1351062SN/A 1361062SN/ATick 1371062SN/APhysicalMemory::calculateLatency(PacketPtr pkt) 1381062SN/A{ 1391062SN/A Tick latency = lat; 1401062SN/A if (lat_var != 0) 1411062SN/A latency += random_mt.random<Tick>(0, lat_var); 1421062SN/A return latency; 1432292SN/A} 1442292SN/A 1452292SN/A 1462292SN/A 1471062SN/A// Add load-locked to tracking list. Should only be called if the 1481062SN/A// operation is a load and the LLSC flag is set. 1491062SN/Avoid 1501062SN/APhysicalMemory::trackLoadLocked(PacketPtr pkt) 1511062SN/A{ 1521062SN/A Request *req = pkt->req; 1531062SN/A Addr paddr = LockedAddr::mask(req->getPaddr()); 1542292SN/A 1552292SN/A // first we check if we already have a locked addr for this 1562292SN/A // xc. Since each xc only gets one, we just update the 1572292SN/A // existing record with the new address. 1582292SN/A list<LockedAddr>::iterator i; 1592292SN/A 1602292SN/A for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) { 1612292SN/A if (i->matchesContext(req)) { 1622292SN/A DPRINTF(LLSC, "Modifying lock record: context %d addr %#x\n", 1632292SN/A req->contextId(), paddr); 1642301SN/A i->addr = paddr; 1652727Sktlim@umich.edu return; 1662353SN/A } 1672727Sktlim@umich.edu } 1682727Sktlim@umich.edu 1692727Sktlim@umich.edu // no record for this xc: need to allocate a new one 1706221Snate@binkert.org DPRINTF(LLSC, "Adding lock record: context %d addr %#x\n", 1712353SN/A req->contextId(), paddr); 1722727Sktlim@umich.edu lockedAddrList.push_front(LockedAddr(req)); 1732727Sktlim@umich.edu} 1742727Sktlim@umich.edu 1752727Sktlim@umich.edu 1762353SN/A// Called on *writes* only... both regular stores and 1772727Sktlim@umich.edu// store-conditional operations. Check for conventional stores which 1782727Sktlim@umich.edu// conflict with locked addresses, and for success/failure of store 1792727Sktlim@umich.edu// conditionals. 1806221Snate@binkert.orgbool 1812301SN/APhysicalMemory::checkLockedAddrList(PacketPtr pkt) 1822301SN/A{ 1832727Sktlim@umich.edu Request *req = pkt->req; 1842301SN/A Addr paddr = LockedAddr::mask(req->getPaddr()); 1852727Sktlim@umich.edu bool isLLSC = pkt->isLLSC(); 1866221Snate@binkert.org 1872301SN/A // Initialize return value. Non-conditional stores always 1882301SN/A // succeed. Assume conditional stores will fail until proven 1892727Sktlim@umich.edu // otherwise. 1902301SN/A bool success = !isLLSC; 1912727Sktlim@umich.edu 1926221Snate@binkert.org // Iterate over list. Note that there could be multiple matching 1932301SN/A // records, as more than one context could have done a load locked 1942301SN/A // to this location. 1952727Sktlim@umich.edu list<LockedAddr>::iterator i = lockedAddrList.begin(); 1962301SN/A 1972727Sktlim@umich.edu while (i != lockedAddrList.end()) { 1986221Snate@binkert.org 1992301SN/A if (i->addr == paddr) { 2002301SN/A // we have a matching address 2012727Sktlim@umich.edu 2022301SN/A if (isLLSC && i->matchesContext(req)) { 2032301SN/A // it's a store conditional, and as far as the memory 2042301SN/A // system can tell, the requesting context's lock is 2052301SN/A // still valid. 2062727Sktlim@umich.edu DPRINTF(LLSC, "StCond success: context %d addr %#x\n", 2072727Sktlim@umich.edu req->contextId(), paddr); 2082727Sktlim@umich.edu success = true; 2092727Sktlim@umich.edu } 2102727Sktlim@umich.edu 2112727Sktlim@umich.edu // Get rid of our record of this lock and advance to next 2122727Sktlim@umich.edu DPRINTF(LLSC, "Erasing lock record: context %d addr %#x\n", 2132727Sktlim@umich.edu i->contextId, paddr); 2142727Sktlim@umich.edu i = lockedAddrList.erase(i); 2152301SN/A } 2162301SN/A else { 2176221Snate@binkert.org // no match: advance to next record 2182301SN/A ++i; 2192301SN/A } 2202727Sktlim@umich.edu } 2212301SN/A 2222326SN/A if (isLLSC) { 2236221Snate@binkert.org req->setExtraData(success ? 1 : 0); 2242301SN/A } 2252301SN/A 2262727Sktlim@umich.edu return success; 2272301SN/A} 2282326SN/A 2296221Snate@binkert.org 2302301SN/A#if TRACING_ON 2312301SN/A 2322727Sktlim@umich.edu#define CASE(A, T) \ 2332301SN/A case sizeof(T): \ 2342326SN/A DPRINTF(MemoryAccess,"%s of size %i on address 0x%x data 0x%x\n", \ 2356221Snate@binkert.org A, pkt->getSize(), pkt->getAddr(), pkt->get<T>()); \ 2362301SN/A break 2372301SN/A 2382727Sktlim@umich.edu 2392301SN/A#define TRACE_PACKET(A) \ 2402326SN/A do { \ 2416221Snate@binkert.org switch (pkt->getSize()) { \ 2422301SN/A CASE(A, uint64_t); \ 2432301SN/A CASE(A, uint32_t); \ 2442727Sktlim@umich.edu CASE(A, uint16_t); \ 2452301SN/A CASE(A, uint8_t); \ 2462326SN/A default: \ 2472301SN/A DPRINTF(MemoryAccess, "%s of size %i on address 0x%x\n", \ 2482301SN/A A, pkt->getSize(), pkt->getAddr()); \ 2492727Sktlim@umich.edu DDUMP(MemoryAccess, pkt->getPtr<uint8_t>(), pkt->getSize());\ 2502301SN/A } \ 2512326SN/A } while (0) 2522301SN/A 2532326SN/A#else 2542301SN/A 2552301SN/A#define TRACE_PACKET(A) 2562727Sktlim@umich.edu 2572301SN/A#endif 2582326SN/A 2592301SN/ATick 2602326SN/APhysicalMemory::doAtomicAccess(PacketPtr pkt) 2612301SN/A{ 2622301SN/A assert(pkt->getAddr() >= start() && 2632727Sktlim@umich.edu pkt->getAddr() + pkt->getSize() <= start() + size()); 2642326SN/A 2651062SN/A if (pkt->memInhibitAsserted()) { 2661062SN/A DPRINTF(MemoryAccess, "mem inhibited on 0x%x: not responding\n", 2671681SN/A pkt->getAddr()); 2681060SN/A return 0; 2692292SN/A } 2701060SN/A 2716221Snate@binkert.org uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start(); 2722292SN/A 2732292SN/A if (pkt->cmd == MemCmd::SwapReq) { 2742292SN/A IntReg overwrite_val; 2752292SN/A bool overwrite_mem; 2762292SN/A uint64_t condition_val64; 2772292SN/A uint32_t condition_val32; 2782292SN/A 2792292SN/A if (!pmemAddr) 2802292SN/A panic("Swap only works if there is real memory (i.e. null=False)"); 2812733Sktlim@umich.edu assert(sizeof(IntReg) >= pkt->getSize()); 2821060SN/A 2831060SN/A overwrite_mem = true; 2841681SN/A // keep a copy of our possible write value, and copy what is at the 2851060SN/A // memory address into the packet 2862292SN/A std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize()); 2871060SN/A std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 2881060SN/A 2891060SN/A if (pkt->req->isCondSwap()) { 2901060SN/A if (pkt->getSize() == sizeof(uint64_t)) { 2911060SN/A condition_val64 = pkt->req->getExtraData(); 2921060SN/A overwrite_mem = !std::memcmp(&condition_val64, hostAddr, 2931060SN/A sizeof(uint64_t)); 2941060SN/A } else if (pkt->getSize() == sizeof(uint32_t)) { 2951060SN/A condition_val32 = (uint32_t)pkt->req->getExtraData(); 2962292SN/A overwrite_mem = !std::memcmp(&condition_val32, hostAddr, 2972292SN/A sizeof(uint32_t)); 2981060SN/A } else 2991060SN/A panic("Invalid size for conditional read/write\n"); 3001060SN/A } 3011060SN/A 3021681SN/A if (overwrite_mem) 3031060SN/A std::memcpy(hostAddr, &overwrite_val, pkt->getSize()); 3042292SN/A 3051060SN/A assert(!pkt->req->isInstFetch()); 3061060SN/A TRACE_PACKET("Read/Write"); 3071060SN/A } else if (pkt->isRead()) { 3081060SN/A assert(!pkt->isWrite()); 3091060SN/A if (pkt->isLLSC()) { 3101060SN/A trackLoadLocked(pkt); 3111060SN/A } 3121681SN/A if (pmemAddr) 3131060SN/A memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 3142292SN/A TRACE_PACKET(pkt->req->isInstFetch() ? "IFetch" : "Read"); 3151060SN/A } else if (pkt->isWrite()) { 3161060SN/A if (writeOK(pkt)) { 3171060SN/A if (pmemAddr) 3181060SN/A memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize()); 3191060SN/A assert(!pkt->req->isInstFetch()); 3201060SN/A TRACE_PACKET("Write"); 3211060SN/A } 3221681SN/A } else if (pkt->isInvalidate()) { 3231060SN/A //upgrade or invalidate 3246221Snate@binkert.org if (pkt->needsResponse()) { 3251060SN/A pkt->makeAtomicResponse(); 3262292SN/A } 3272292SN/A } else { 3282292SN/A panic("unimplemented"); 3292292SN/A } 3301060SN/A 3311060SN/A if (pkt->needsResponse()) { 3321681SN/A pkt->makeAtomicResponse(); 3331060SN/A } 3342292SN/A return calculateLatency(pkt); 3351060SN/A} 3362292SN/A 3371060SN/A 3381060SN/Avoid 3392307SN/APhysicalMemory::doFunctionalAccess(PacketPtr pkt) 3402863Sktlim@umich.edu{ 3412843Sktlim@umich.edu assert(pkt->getAddr() >= start() && 3422307SN/A pkt->getAddr() + pkt->getSize() <= start() + size()); 3432843Sktlim@umich.edu 3442843Sktlim@umich.edu 3452863Sktlim@umich.edu uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start(); 3461681SN/A 3471681SN/A if (pkt->isRead()) { 3482316SN/A if (pmemAddr) 3491681SN/A memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize()); 3502843Sktlim@umich.edu TRACE_PACKET("Read"); 3512843Sktlim@umich.edu pkt->makeAtomicResponse(); 3522843Sktlim@umich.edu } else if (pkt->isWrite()) { 3532843Sktlim@umich.edu if (pmemAddr) 3542843Sktlim@umich.edu memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize()); 3552843Sktlim@umich.edu TRACE_PACKET("Write"); 3562843Sktlim@umich.edu pkt->makeAtomicResponse(); 3571681SN/A } else if (pkt->isPrint()) { 3582348SN/A Packet::PrintReqState *prs = 3592307SN/A dynamic_cast<Packet::PrintReqState*>(pkt->senderState); 3602367SN/A // Need to call printLabels() explicitly since we're not going 3612367SN/A // through printObj(). 3621681SN/A prs->printLabels(); 3632307SN/A // Right now we just print the single byte at the specified address. 3642307SN/A ccprintf(prs->os, "%s%#x\n", prs->curPrefix(), *hostAddr); 3652307SN/A } else { 3662307SN/A panic("PhysicalMemory: unimplemented functional command %s", 3676221Snate@binkert.org pkt->cmdString()); 3686221Snate@binkert.org } 3696221Snate@binkert.org} 3706221Snate@binkert.org 3716221Snate@binkert.org 3722307SN/APort * 3731681SN/APhysicalMemory::getPort(const std::string &if_name, int idx) 3741681SN/A{ 3752307SN/A if (if_name != "port") { 3761681SN/A panic("PhysicalMemory::getPort: unknown port %s requested", if_name); 3772307SN/A } 3781060SN/A 3792348SN/A if (idx >= (int)ports.size()) { 3802307SN/A ports.resize(idx + 1); 3812307SN/A } 3822307SN/A 3832307SN/A if (ports[idx] != NULL) { 3841060SN/A panic("PhysicalMemory::getPort: port %d already assigned", idx); 3852307SN/A } 3862307SN/A 3872307SN/A MemoryPort *port = 3881060SN/A new MemoryPort(csprintf("%s-port%d", name(), idx), this); 3892307SN/A 3902307SN/A ports[idx] = port; 3911060SN/A return port; 3926221Snate@binkert.org} 3936221Snate@binkert.org 3946221Snate@binkert.orgPhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, 3956221Snate@binkert.org PhysicalMemory *_memory) 3962307SN/A : SimpleTimingPort(_name, _memory), memory(_memory) 3971060SN/A{ } 3982307SN/A 3992307SN/Avoid 4002873Sktlim@umich.eduPhysicalMemory::MemoryPort::recvRangeChange() 4012307SN/A{ 4021060SN/A // memory is a slave and thus should never have to worry about its 4031060SN/A // neighbours address ranges 4041060SN/A} 4051681SN/A 4061060SN/AAddrRangeList 4076221Snate@binkert.orgPhysicalMemory::MemoryPort::getAddrRanges() 4082107SN/A{ 4096221Snate@binkert.org return memory->getAddrRanges(); 4102107SN/A} 4112292SN/A 4122292SN/AAddrRangeList 4132107SN/APhysicalMemory::getAddrRanges() 4142292SN/A{ 4152326SN/A AddrRangeList ranges; 4162292SN/A ranges.push_back(RangeSize(start(), size())); 4172107SN/A return ranges; 4182292SN/A} 4192935Sksewell@umich.edu 4204632Sgblack@eecs.umich.eduunsigned 4212935Sksewell@umich.eduPhysicalMemory::MemoryPort::deviceBlockSize() const 4222292SN/A{ 4232292SN/A return memory->deviceBlockSize(); 4242292SN/A} 4252292SN/A 4262292SN/ATick 4272107SN/APhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt) 4282292SN/A{ 4292107SN/A return memory->doAtomicAccess(pkt); 4302292SN/A} 4312292SN/A 4322107SN/Avoid 4332702Sktlim@umich.eduPhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt) 4342107SN/A{ 4352107SN/A pkt->pushLabel(memory->name()); 4362107SN/A 4372107SN/A if (!checkFunctional(pkt)) { 4386221Snate@binkert.org // Default implementation of SimpleTimingPort::recvFunctional() 4392292SN/A // calls recvAtomic() and throws away the latency; we can save a 4402292SN/A // little here by just not calculating the latency. 4412292SN/A memory->doFunctionalAccess(pkt); 4422292SN/A } 4432292SN/A 4442292SN/A pkt->popLabel(); 4452292SN/A} 4462292SN/A 4472935Sksewell@umich.eduunsigned int 4484632Sgblack@eecs.umich.eduPhysicalMemory::drain(Event *de) 4493969Sgblack@eecs.umich.edu{ 4504632Sgblack@eecs.umich.edu int count = 0; 4513795Sgblack@eecs.umich.edu for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) { 4523795Sgblack@eecs.umich.edu count += (*pi)->drain(de); 4533795Sgblack@eecs.umich.edu } 4543093Sksewell@umich.edu 4553093Sksewell@umich.edu if (count) 4563093Sksewell@umich.edu changeState(Draining); 4574632Sgblack@eecs.umich.edu else 4583093Sksewell@umich.edu changeState(Drained); 4594632Sgblack@eecs.umich.edu return count; 4604636Sgblack@eecs.umich.edu} 4612292SN/A 4622292SN/Avoid 4632292SN/APhysicalMemory::serialize(ostream &os) 4642292SN/A{ 4652292SN/A if (!pmemAddr) 4662292SN/A return; 4672292SN/A 4682292SN/A gzFile compressedMem; 4696221Snate@binkert.org string filename = name() + ".physmem"; 4702292SN/A 4712292SN/A SERIALIZE_SCALAR(filename); 4722292SN/A SERIALIZE_SCALAR(_size); 4732292SN/A 4742292SN/A // write memory file 4752292SN/A string thefile = Checkpoint::dir() + "/" + filename.c_str(); 4762292SN/A int fd = creat(thefile.c_str(), 0664); 4773795Sgblack@eecs.umich.edu if (fd < 0) { 4783732Sktlim@umich.edu perror("creat"); 4792292SN/A fatal("Can't open physical memory checkpoint file '%s'\n", filename); 4802292SN/A } 4812292SN/A 4822292SN/A compressedMem = gzdopen(fd, "wb"); 4832292SN/A if (compressedMem == NULL) 4842292SN/A fatal("Insufficient memory to allocate compression state for %s\n", 4852292SN/A filename); 4862292SN/A 4876221Snate@binkert.org if (gzwrite(compressedMem, pmemAddr, size()) != (int)size()) { 4882292SN/A fatal("Write failed on physical memory checkpoint file '%s'\n", 4892292SN/A filename); 4902292SN/A } 4912292SN/A 4922292SN/A if (gzclose(compressedMem)) 4932292SN/A fatal("Close failed on physical memory checkpoint file '%s'\n", 4942292SN/A filename); 4953958Sgblack@eecs.umich.edu 4963732Sktlim@umich.edu list<LockedAddr>::iterator i = lockedAddrList.begin(); 4972292SN/A 4982348SN/A vector<Addr> lal_addr; 4992292SN/A vector<int> lal_cid; 5002292SN/A while (i != lockedAddrList.end()) { 5012292SN/A lal_addr.push_back(i->addr); 5022292SN/A lal_cid.push_back(i->contextId); 5032292SN/A i++; 5042292SN/A } 5052292SN/A arrayParamOut(os, "lal_addr", lal_addr); 5062292SN/A arrayParamOut(os, "lal_cid", lal_cid); 5072292SN/A} 5086221Snate@binkert.org 5092292SN/Avoid 5102292SN/APhysicalMemory::unserialize(Checkpoint *cp, const string §ion) 5112292SN/A{ 5122292SN/A if (!pmemAddr) 5132292SN/A return; 5142292SN/A 5152292SN/A gzFile compressedMem; 5162292SN/A long *tempPage; 5172292SN/A long *pmem_current; 5182292SN/A uint64_t curSize; 5192292SN/A uint32_t bytesRead; 5202292SN/A const uint32_t chunkSize = 16384; 5212292SN/A 5222292SN/A string filename; 5232292SN/A 5242292SN/A UNSERIALIZE_SCALAR(filename); 5252292SN/A 5262292SN/A filename = cp->cptDir + "/" + filename; 5276221Snate@binkert.org 5282292SN/A // mmap memoryfile 5292292SN/A int fd = open(filename.c_str(), O_RDONLY); 5302292SN/A if (fd < 0) { 5312292SN/A perror("open"); 5322292SN/A fatal("Can't open physical memory checkpoint file '%s'", filename); 5332292SN/A } 5342292SN/A 5352292SN/A compressedMem = gzdopen(fd, "rb"); 5362292SN/A if (compressedMem == NULL) 5372292SN/A fatal("Insufficient memory to allocate compression state for %s\n", 5382292SN/A filename); 5392292SN/A 5402292SN/A // unmap file that was mmapped in the constructor 5412292SN/A // This is done here to make sure that gzip and open don't muck with our 5422292SN/A // nice large space of memory before we reallocate it 5432292SN/A munmap((char*)pmemAddr, size()); 5442292SN/A 5451060SN/A UNSERIALIZE_SCALAR(_size); 5461681SN/A if (size() > params()->range.size()) 5471060SN/A fatal("Memory size has changed! size %lld, param size %lld\n", 5481060SN/A size(), params()->range.size()); 5492292SN/A 5502292SN/A pmemAddr = (uint8_t *)mmap(NULL, size(), 5512292SN/A PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); 5522292SN/A 5532292SN/A if (pmemAddr == (void *)MAP_FAILED) { 5542292SN/A perror("mmap"); 5551681SN/A fatal("Could not mmap physical memory!\n"); 5561681SN/A } 5571060SN/A 5582292SN/A curSize = 0; 5591060SN/A tempPage = (long*)malloc(chunkSize); 5602292SN/A if (tempPage == NULL) 5612292SN/A fatal("Unable to malloc memory to read file %s\n", filename); 5621060SN/A 5632292SN/A /* Only copy bytes that are non-zero, so we don't give the VM system hell */ 5642292SN/A while (curSize < size()) { 5652292SN/A bytesRead = gzread(compressedMem, tempPage, chunkSize); 5662292SN/A if (bytesRead == 0) 5673221Sktlim@umich.edu break; 5683221Sktlim@umich.edu 5693221Sktlim@umich.edu assert(bytesRead % sizeof(long) == 0); 5703221Sktlim@umich.edu 5713221Sktlim@umich.edu for (uint32_t x = 0; x < bytesRead / sizeof(long); x++) 5722292SN/A { 5732292SN/A if (*(tempPage+x) != 0) { 5742292SN/A pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long)); 5752292SN/A *pmem_current = *(tempPage+x); 5762326SN/A } 5772292SN/A } 5782292SN/A curSize += bytesRead; 5792820Sktlim@umich.edu } 5802292SN/A 5812292SN/A free(tempPage); 5822292SN/A 5832292SN/A if (gzclose(compressedMem)) 5842353SN/A fatal("Close failed on physical memory checkpoint file '%s'\n", 5852292SN/A filename); 5862292SN/A 5872353SN/A vector<Addr> lal_addr; 5882353SN/A vector<int> lal_cid; 5892292SN/A arrayParamIn(cp, section, "lal_addr", lal_addr); 5902292SN/A arrayParamIn(cp, section, "lal_cid", lal_cid); 5912292SN/A for(int i = 0; i < lal_addr.size(); i++) 5922292SN/A lockedAddrList.push_front(LockedAddr(lal_addr[i], lal_cid[i])); 5932292SN/A} 5942292SN/A 5952292SN/APhysicalMemory * 5962292SN/APhysicalMemoryParams::create() 5972292SN/A{ 5982292SN/A return new PhysicalMemory(this); 5992292SN/A} 6002292SN/A