abstract_mem.cc revision 4762
15703SN/A/* 25703SN/A * Copyright (c) 2001-2005 The Regents of The University of Michigan 35703SN/A * All rights reserved. 48825Snilay@cs.wisc.edu * 57935SN/A * Redistribution and use in source and binary forms, with or without 67935SN/A * modification, are permitted provided that the following conditions are 77935SN/A * met: redistributions of source code must retain the above copyright 85703SN/A * notice, this list of conditions and the following disclaimer; 95703SN/A * redistributions in binary form must reproduce the above copyright 105703SN/A * notice, this list of conditions and the following disclaimer in the 119348SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 125703SN/A * neither the name of the copyright holders nor the names of its 135703SN/A * contributors may be used to endorse or promote products derived from 149348SAli.Saidi@ARM.com * this software without specific prior written permission. 159481Snilay@cs.wisc.edu * 165703SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 179481Snilay@cs.wisc.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187670SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 195703SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 209449SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 218464SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 228721SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 239481Snilay@cs.wisc.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245703SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255703SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 265703SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275703SN/A * 287935SN/A * Authors: Ron Dreslinski 297935SN/A * Ali Saidi 307935SN/A */ 317935SN/A 327935SN/A#include <sys/types.h> 337935SN/A#include <sys/mman.h> 347935SN/A#include <errno.h> 358983Snate@binkert.org#include <fcntl.h> 365703SN/A#include <unistd.h> 375703SN/A#include <zlib.h> 385703SN/A 399348SAli.Saidi@ARM.com#include <iostream> 405703SN/A#include <string> 418721SN/A 428721SN/A#include "arch/isa_traits.hh" 438721SN/A#include "base/misc.hh" 448983Snate@binkert.org#include "config/full_system.hh" 458983Snate@binkert.org#include "mem/packet_access.hh" 465703SN/A#include "mem/physical.hh" 475703SN/A#include "sim/eventq.hh" 485703SN/A#include "sim/host.hh" 499481Snilay@cs.wisc.edu 505703SN/Ausing namespace std; 515703SN/Ausing namespace TheISA; 528241SN/A 538241SN/APhysicalMemory::PhysicalMemory(const Params *p) 545703SN/A : MemObject(p), pmemAddr(NULL), lat(p->latency) 555703SN/A{ 565703SN/A if (params()->range.size() % TheISA::PageBytes != 0) 575703SN/A panic("Memory Size not divisible by page size\n"); 589481Snilay@cs.wisc.edu 595703SN/A int map_flags = MAP_ANON | MAP_PRIVATE; 605876SN/A pmemAddr = (uint8_t *)mmap(NULL, params()->range.size(), PROT_READ | PROT_WRITE, 615703SN/A map_flags, -1, 0); 625703SN/A 635703SN/A if (pmemAddr == (void *)MAP_FAILED) { 645703SN/A perror("mmap"); 655703SN/A fatal("Could not mmap!\n"); 665703SN/A } 675703SN/A 685703SN/A //If requested, initialize all the memory to 0 695703SN/A if (p->zero) 705703SN/A memset(pmemAddr, 0, p->range.size()); 715703SN/A 725703SN/A pagePtr = 0; 735703SN/A} 745703SN/A 755703SN/Avoid 765703SN/APhysicalMemory::init() 775703SN/A{ 785703SN/A if (ports.size() == 0) { 795703SN/A fatal("PhysicalMemory object %s is unconnected!", name()); 805703SN/A } 815703SN/A 825703SN/A for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) { 835703SN/A if (*pi) 845703SN/A (*pi)->sendStatusChange(Port::RangeChange); 855703SN/A } 865703SN/A} 875703SN/A 889348SAli.Saidi@ARM.comPhysicalMemory::~PhysicalMemory() 895703SN/A{ 905703SN/A if (pmemAddr) 915703SN/A munmap((char*)pmemAddr, params()->range.size()); 925703SN/A //Remove memPorts? 935703SN/A} 945703SN/A 955703SN/AAddr 968825Snilay@cs.wisc.eduPhysicalMemory::new_page() 975703SN/A{ 985703SN/A Addr return_addr = pagePtr << LogVMPageSize; 995703SN/A return_addr += start(); 1005703SN/A 1015703SN/A ++pagePtr; 1025703SN/A return return_addr; 1035703SN/A} 1045703SN/A 1055703SN/Aint 1065703SN/APhysicalMemory::deviceBlockSize() 1075703SN/A{ 1085703SN/A //Can accept anysize request 1095703SN/A return 0; 1105703SN/A} 1115703SN/A 1125703SN/ATick 1135703SN/APhysicalMemory::calculateLatency(PacketPtr pkt) 1145703SN/A{ 1155703SN/A return lat; 1165703SN/A} 1175703SN/A 1185703SN/A 1195703SN/A 1208521SN/A// Add load-locked to tracking list. Should only be called if the 1219449SAli.Saidi@ARM.com// operation is a load and the LOCKED flag is set. 1225703SN/Avoid 1235703SN/APhysicalMemory::trackLoadLocked(Request *req) 1245703SN/A{ 1255703SN/A Addr paddr = LockedAddr::mask(req->getPaddr()); 1265703SN/A 1278825Snilay@cs.wisc.edu // first we check if we already have a locked addr for this 1285703SN/A // xc. Since each xc only gets one, we just update the 1295703SN/A // existing record with the new address. 1305703SN/A list<LockedAddr>::iterator i; 1319481Snilay@cs.wisc.edu 1329481Snilay@cs.wisc.edu for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) { 1339481Snilay@cs.wisc.edu if (i->matchesContext(req)) { 1349481Snilay@cs.wisc.edu DPRINTF(LLSC, "Modifying lock record: cpu %d thread %d addr %#x\n", 1359481Snilay@cs.wisc.edu req->getCpuNum(), req->getThreadNum(), paddr); 1369481Snilay@cs.wisc.edu i->addr = paddr; 1379481Snilay@cs.wisc.edu return; 1389481Snilay@cs.wisc.edu } 1399481Snilay@cs.wisc.edu } 1409481Snilay@cs.wisc.edu 1419481Snilay@cs.wisc.edu // no record for this xc: need to allocate a new one 1429481Snilay@cs.wisc.edu DPRINTF(LLSC, "Adding lock record: cpu %d thread %d addr %#x\n", 1439481Snilay@cs.wisc.edu req->getCpuNum(), req->getThreadNum(), paddr); 1449481Snilay@cs.wisc.edu lockedAddrList.push_front(LockedAddr(req)); 1459481Snilay@cs.wisc.edu} 1469481Snilay@cs.wisc.edu 1479481Snilay@cs.wisc.edu 1489481Snilay@cs.wisc.edu// Called on *writes* only... both regular stores and 1495703SN/A// store-conditional operations. Check for conventional stores which 1505703SN/A// conflict with locked addresses, and for success/failure of store 1518983Snate@binkert.org// conditionals. 1525703SN/Abool 1535703SN/APhysicalMemory::checkLockedAddrList(Request *req) 1549348SAli.Saidi@ARM.com{ 1556123SN/A Addr paddr = LockedAddr::mask(req->getPaddr()); 1569348SAli.Saidi@ARM.com bool isLocked = req->isLocked(); 1578135SN/A 1585703SN/A // Initialize return value. Non-conditional stores always 1595703SN/A // succeed. Assume conditional stores will fail until proven 1605876SN/A // otherwise. 1618835SAli.Saidi@ARM.com bool success = !isLocked; 1629348SAli.Saidi@ARM.com 1635703SN/A // Iterate over list. Note that there could be multiple matching 1648835SAli.Saidi@ARM.com // records, as more than one context could have done a load locked 1655703SN/A // to this location. 1665703SN/A list<LockedAddr>::iterator i = lockedAddrList.begin(); 1675703SN/A 1685703SN/A while (i != lockedAddrList.end()) { 1699348SAli.Saidi@ARM.com 1705703SN/A if (i->addr == paddr) { 1715703SN/A // we have a matching address 1726024SN/A 1735703SN/A if (isLocked && i->matchesContext(req)) { 1745703SN/A // it's a store conditional, and as far as the memory 1755703SN/A // system can tell, the requesting context's lock is 1765703SN/A // still valid. 1777761SN/A DPRINTF(LLSC, "StCond success: cpu %d thread %d addr %#x\n", 1787761SN/A req->getCpuNum(), req->getThreadNum(), paddr); 1795703SN/A success = true; 1805703SN/A } 1815703SN/A 1825703SN/A // Get rid of our record of this lock and advance to next 1835703SN/A DPRINTF(LLSC, "Erasing lock record: cpu %d thread %d addr %#x\n", 1845703SN/A i->cpuNum, i->threadNum, paddr); 1855703SN/A i = lockedAddrList.erase(i); 1865703SN/A } 1875703SN/A else { 1885703SN/A // no match: advance to next record 1895703SN/A ++i; 1905703SN/A } 1915703SN/A } 1925703SN/A 1935703SN/A if (isLocked) { 1945703SN/A req->setExtraData(success ? 1 : 0); 1955703SN/A } 1965703SN/A 1975703SN/A return success; 1985703SN/A} 1995703SN/A 2005703SN/Avoid 2015703SN/APhysicalMemory::doFunctionalAccess(PacketPtr pkt) 2025703SN/A{ 2035703SN/A assert(pkt->getAddr() >= start() && 2045703SN/A pkt->getAddr() + pkt->getSize() <= start() + size()); 2055703SN/A 2065703SN/A if (pkt->isRead()) { 2075703SN/A if (pkt->req->isLocked()) { 2085703SN/A trackLoadLocked(pkt->req); 2095703SN/A } 2105703SN/A memcpy(pkt->getPtr<uint8_t>(), pmemAddr + pkt->getAddr() - start(), 2115703SN/A pkt->getSize()); 2125703SN/A#if TRACING_ON 2135703SN/A switch (pkt->getSize()) { 2145703SN/A case sizeof(uint64_t): 2155703SN/A DPRINTF(MemoryAccess, "Read of size %i on address 0x%x data 0x%x\n", 2165703SN/A pkt->getSize(), pkt->getAddr(),pkt->get<uint64_t>()); 2175703SN/A break; 2185703SN/A case sizeof(uint32_t): 2195703SN/A DPRINTF(MemoryAccess, "Read of size %i on address 0x%x data 0x%x\n", 2205703SN/A pkt->getSize(), pkt->getAddr(),pkt->get<uint32_t>()); 2215703SN/A break; 2225703SN/A case sizeof(uint16_t): 2235703SN/A DPRINTF(MemoryAccess, "Read of size %i on address 0x%x data 0x%x\n", 2245703SN/A pkt->getSize(), pkt->getAddr(),pkt->get<uint16_t>()); 2255703SN/A break; 2265703SN/A case sizeof(uint8_t): 2275703SN/A DPRINTF(MemoryAccess, "Read of size %i on address 0x%x data 0x%x\n", 2285703SN/A pkt->getSize(), pkt->getAddr(),pkt->get<uint8_t>()); 2295703SN/A break; 2305703SN/A default: 2315703SN/A DPRINTF(MemoryAccess, "Read of size %i on address 0x%x\n", 2325703SN/A pkt->getSize(), pkt->getAddr()); 2335703SN/A } 2345703SN/A#endif 2355703SN/A } 2365703SN/A else if (pkt->isWrite()) { 2375703SN/A if (writeOK(pkt->req)) { 2385703SN/A memcpy(pmemAddr + pkt->getAddr() - start(), pkt->getPtr<uint8_t>(), 2395703SN/A pkt->getSize()); 2405703SN/A#if TRACING_ON 2415703SN/A switch (pkt->getSize()) { 2425703SN/A case sizeof(uint64_t): 2435703SN/A DPRINTF(MemoryAccess, "Write of size %i on address 0x%x data 0x%x\n", 2445703SN/A pkt->getSize(), pkt->getAddr(),pkt->get<uint64_t>()); 2455703SN/A break; 2465703SN/A case sizeof(uint32_t): 2475703SN/A DPRINTF(MemoryAccess, "Write of size %i on address 0x%x data 0x%x\n", 2485703SN/A pkt->getSize(), pkt->getAddr(),pkt->get<uint32_t>()); 2495703SN/A break; 2505703SN/A case sizeof(uint16_t): 2515703SN/A DPRINTF(MemoryAccess, "Write of size %i on address 0x%x data 0x%x\n", 2525703SN/A pkt->getSize(), pkt->getAddr(),pkt->get<uint16_t>()); 2535703SN/A break; 2545703SN/A case sizeof(uint8_t): 2555703SN/A DPRINTF(MemoryAccess, "Write of size %i on address 0x%x data 0x%x\n", 2565703SN/A pkt->getSize(), pkt->getAddr(),pkt->get<uint8_t>()); 2575703SN/A break; 2585703SN/A default: 2595703SN/A DPRINTF(MemoryAccess, "Write of size %i on address 0x%x\n", 2605703SN/A pkt->getSize(), pkt->getAddr()); 2615703SN/A } 2625703SN/A#endif 2635703SN/A } 2645703SN/A } else if (pkt->isInvalidate()) { 2655703SN/A //upgrade or invalidate 2665703SN/A pkt->flags |= SATISFIED; 2675703SN/A } else if (pkt->isReadWrite()) { 2685703SN/A IntReg overwrite_val; 2695703SN/A bool overwrite_mem; 2705703SN/A uint64_t condition_val64; 2715703SN/A uint32_t condition_val32; 2727761SN/A 2737761SN/A assert(sizeof(IntReg) >= pkt->getSize()); 2747761SN/A 2755703SN/A overwrite_mem = true; 2767761SN/A // keep a copy of our possible write value, and copy what is at the 2775703SN/A // memory address into the packet 2785703SN/A std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize()); 2797761SN/A std::memcpy(pkt->getPtr<uint8_t>(), pmemAddr + pkt->getAddr() - start(), 2807761SN/A pkt->getSize()); 2817761SN/A 2827761SN/A if (pkt->req->isCondSwap()) { 2837761SN/A if (pkt->getSize() == sizeof(uint64_t)) { 2847761SN/A condition_val64 = pkt->req->getExtraData(); 2857761SN/A overwrite_mem = !std::memcmp(&condition_val64, pmemAddr + 2867761SN/A pkt->getAddr() - start(), sizeof(uint64_t)); 2877761SN/A } else if (pkt->getSize() == sizeof(uint32_t)) { 2887761SN/A condition_val32 = (uint32_t)pkt->req->getExtraData(); 2897761SN/A overwrite_mem = !std::memcmp(&condition_val32, pmemAddr + 2907761SN/A pkt->getAddr() - start(), sizeof(uint32_t)); 2917761SN/A } else 2927761SN/A panic("Invalid size for conditional read/write\n"); 2937761SN/A } 2947761SN/A 2957761SN/A if (overwrite_mem) 2967761SN/A std::memcpy(pmemAddr + pkt->getAddr() - start(), 2977761SN/A &overwrite_val, pkt->getSize()); 2987761SN/A 2997761SN/A#if TRACING_ON 3007761SN/A switch (pkt->getSize()) { 3017761SN/A case sizeof(uint64_t): 3027761SN/A DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n", 3037761SN/A pkt->getSize(), pkt->getAddr(),pkt->get<uint64_t>()); 3047761SN/A DPRINTF(MemoryAccess, "New Data 0x%x %s conditional (0x%x) and %s \n", 3057761SN/A overwrite_mem, pkt->req->isCondSwap() ? "was" : "wasn't", 3067761SN/A condition_val64, overwrite_mem ? "happened" : "didn't happen"); 3077761SN/A break; 3087761SN/A case sizeof(uint32_t): 3097761SN/A DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n", 3107761SN/A pkt->getSize(), pkt->getAddr(),pkt->get<uint32_t>()); 3117761SN/A DPRINTF(MemoryAccess, "New Data 0x%x %s conditional (0x%x) and %s \n", 3127761SN/A overwrite_mem, pkt->req->isCondSwap() ? "was" : "wasn't", 3137761SN/A condition_val32, overwrite_mem ? "happened" : "didn't happen"); 3147761SN/A break; 3157761SN/A case sizeof(uint16_t): 3167761SN/A DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n", 3177761SN/A pkt->getSize(), pkt->getAddr(),pkt->get<uint16_t>()); 3187761SN/A DPRINTF(MemoryAccess, "New Data 0x%x wasn't conditional and happned\n", 3197761SN/A overwrite_mem); 3207761SN/A break; 3217761SN/A case sizeof(uint8_t): 3227761SN/A DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n", 3237761SN/A pkt->getSize(), pkt->getAddr(),pkt->get<uint8_t>()); 3247761SN/A DPRINTF(MemoryAccess, "New Data 0x%x wasn't conditional and happned\n", 3257761SN/A overwrite_mem); 3267761SN/A break; 3277761SN/A default: 3287761SN/A DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x\n", 3297761SN/A pkt->getSize(), pkt->getAddr()); 3307761SN/A } 3317761SN/A#endif 3327761SN/A } else { 3337761SN/A panic("unimplemented"); 3347761SN/A } 3357761SN/A 3367761SN/A pkt->result = Packet::Success; 3377761SN/A} 3387761SN/A 3397761SN/APort * 3407761SN/APhysicalMemory::getPort(const std::string &if_name, int idx) 3417761SN/A{ 3427761SN/A // Accept request for "functional" port for backwards compatibility 3437761SN/A // with places where this function is called from C++. I'd prefer 3447761SN/A // to move all these into Python someday. 3457761SN/A if (if_name == "functional") { 3467761SN/A return new MemoryPort(csprintf("%s-functional", name()), this); 3477761SN/A } 3487761SN/A 3497761SN/A if (if_name != "port") { 3507761SN/A panic("PhysicalMemory::getPort: unknown port %s requested", if_name); 3517761SN/A } 3527761SN/A 3537761SN/A if (idx >= ports.size()) { 3547761SN/A ports.resize(idx+1); 3557761SN/A } 3567761SN/A 3577761SN/A if (ports[idx] != NULL) { 3587761SN/A panic("PhysicalMemory::getPort: port %d already assigned", idx); 3597761SN/A } 3607761SN/A 3617761SN/A MemoryPort *port = 3627761SN/A new MemoryPort(csprintf("%s-port%d", name(), idx), this); 3637761SN/A 3647761SN/A ports[idx] = port; 3657761SN/A return port; 3667761SN/A} 3677761SN/A 3687761SN/A 3697761SN/Avoid 3707761SN/APhysicalMemory::recvStatusChange(Port::Status status) 3717761SN/A{ 3727761SN/A} 3737761SN/A 3747761SN/APhysicalMemory::MemoryPort::MemoryPort(const std::string &_name, 3757761SN/A PhysicalMemory *_memory) 3767761SN/A : SimpleTimingPort(_name), memory(_memory) 3777761SN/A{ } 3787761SN/A 3797761SN/Avoid 3807761SN/APhysicalMemory::MemoryPort::recvStatusChange(Port::Status status) 3817761SN/A{ 3827761SN/A memory->recvStatusChange(status); 3837761SN/A} 3847761SN/A 3857761SN/Avoid 3867761SN/APhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp, 3877761SN/A bool &snoop) 3887761SN/A{ 3897761SN/A memory->getAddressRanges(resp, snoop); 3907761SN/A} 3917761SN/A 3927761SN/Avoid 3937761SN/APhysicalMemory::getAddressRanges(AddrRangeList &resp, bool &snoop) 3945703SN/A{ 3955703SN/A snoop = false; 3965703SN/A resp.clear(); 3975703SN/A resp.push_back(RangeSize(start(), params()->range.size())); 3987761SN/A} 3997761SN/A 4007761SN/Aint 4015703SN/APhysicalMemory::MemoryPort::deviceBlockSize() 4027761SN/A{ 4035703SN/A return memory->deviceBlockSize(); 4045703SN/A} 4055703SN/A 4065703SN/ATick 4075703SN/APhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt) 4085703SN/A{ 4095703SN/A memory->doFunctionalAccess(pkt); 4107761SN/A return memory->calculateLatency(pkt); 4117761SN/A} 4127761SN/A 4137761SN/Avoid 4147761SN/APhysicalMemory::MemoryPort::recvFunctional(PacketPtr pkt) 4157761SN/A{ 4167761SN/A checkFunctional(pkt); 4177761SN/A 4187761SN/A // Default implementation of SimpleTimingPort::recvFunctional() 4197761SN/A // calls recvAtomic() and throws away the latency; we can save a 4207761SN/A // little here by just not calculating the latency. 4217761SN/A memory->doFunctionalAccess(pkt); 4227761SN/A} 4237761SN/A 4247761SN/Aunsigned int 4257761SN/APhysicalMemory::drain(Event *de) 4267761SN/A{ 4277761SN/A int count = 0; 4285703SN/A for (PortIterator pi = ports.begin(); pi != ports.end(); ++pi) { 4295703SN/A count += (*pi)->drain(de); 4307761SN/A } 4315703SN/A 4327761SN/A if (count) 4335703SN/A changeState(Draining); 4345703SN/A else 4355703SN/A changeState(Drained); 4365703SN/A return count; 4375703SN/A} 4385703SN/A 4395703SN/Avoid 4408983Snate@binkert.orgPhysicalMemory::serialize(ostream &os) 4415703SN/A{ 4425703SN/A gzFile compressedMem; 4439348SAli.Saidi@ARM.com string filename = name() + ".physmem"; 4446123SN/A 4459348SAli.Saidi@ARM.com SERIALIZE_SCALAR(filename); 4468135SN/A 4475703SN/A // write memory file 4485703SN/A string thefile = Checkpoint::dir() + "/" + filename.c_str(); 4495876SN/A int fd = creat(thefile.c_str(), 0664); 4508835SAli.Saidi@ARM.com if (fd < 0) { 4519348SAli.Saidi@ARM.com perror("creat"); 4525703SN/A fatal("Can't open physical memory checkpoint file '%s'\n", filename); 4538835SAli.Saidi@ARM.com } 4545703SN/A 4555703SN/A compressedMem = gzdopen(fd, "wb"); 4565703SN/A if (compressedMem == NULL) 4575703SN/A fatal("Insufficient memory to allocate compression state for %s\n", 4589348SAli.Saidi@ARM.com filename); 4595703SN/A 4605703SN/A if (gzwrite(compressedMem, pmemAddr, params()->range.size()) != 4615703SN/A params()->range.size()) { 4625703SN/A fatal("Write failed on physical memory checkpoint file '%s'\n", 4639348SAli.Saidi@ARM.com filename); 4649348SAli.Saidi@ARM.com } 4659348SAli.Saidi@ARM.com 4665703SN/A if (gzclose(compressedMem)) 4676024SN/A fatal("Close failed on physical memory checkpoint file '%s'\n", 4685703SN/A filename); 4695703SN/A} 4709348SAli.Saidi@ARM.com 4719348SAli.Saidi@ARM.comvoid 4729348SAli.Saidi@ARM.comPhysicalMemory::unserialize(Checkpoint *cp, const string §ion) 4739348SAli.Saidi@ARM.com{ 4749348SAli.Saidi@ARM.com gzFile compressedMem; 4759348SAli.Saidi@ARM.com long *tempPage; 4769348SAli.Saidi@ARM.com long *pmem_current; 4779348SAli.Saidi@ARM.com uint64_t curSize; 4789348SAli.Saidi@ARM.com uint32_t bytesRead; 4799348SAli.Saidi@ARM.com const int chunkSize = 16384; 4809348SAli.Saidi@ARM.com 4819348SAli.Saidi@ARM.com 4829348SAli.Saidi@ARM.com string filename; 4839348SAli.Saidi@ARM.com 4849348SAli.Saidi@ARM.com UNSERIALIZE_SCALAR(filename); 4859348SAli.Saidi@ARM.com 4869348SAli.Saidi@ARM.com filename = cp->cptDir + "/" + filename; 4879348SAli.Saidi@ARM.com 4889348SAli.Saidi@ARM.com // mmap memoryfile 4899348SAli.Saidi@ARM.com int fd = open(filename.c_str(), O_RDONLY); 4909449SAli.Saidi@ARM.com if (fd < 0) { 4919348SAli.Saidi@ARM.com perror("open"); 4929348SAli.Saidi@ARM.com fatal("Can't open physical memory checkpoint file '%s'", filename); 4939348SAli.Saidi@ARM.com } 4949348SAli.Saidi@ARM.com 4959348SAli.Saidi@ARM.com compressedMem = gzdopen(fd, "rb"); 4969348SAli.Saidi@ARM.com if (compressedMem == NULL) 4979348SAli.Saidi@ARM.com fatal("Insufficient memory to allocate compression state for %s\n", 4989348SAli.Saidi@ARM.com filename); 4999348SAli.Saidi@ARM.com 5009348SAli.Saidi@ARM.com // unmap file that was mmaped in the constructor 5019348SAli.Saidi@ARM.com // This is done here to make sure that gzip and open don't muck with our 5025703SN/A // nice large space of memory before we reallocate it 5035703SN/A munmap((char*)pmemAddr, params()->range.size()); 5045703SN/A 5055703SN/A pmemAddr = (uint8_t *)mmap(NULL, params()->range.size(), 5065703SN/A PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); 5075703SN/A 5085703SN/A if (pmemAddr == (void *)MAP_FAILED) { 5095703SN/A perror("mmap"); 5105703SN/A fatal("Could not mmap physical memory!\n"); 5115703SN/A } 5125703SN/A 5135703SN/A curSize = 0; 5145703SN/A tempPage = (long*)malloc(chunkSize); 5155703SN/A if (tempPage == NULL) 5165876SN/A fatal("Unable to malloc memory to read file %s\n", filename); 5175703SN/A 5185703SN/A /* Only copy bytes that are non-zero, so we don't give the VM system hell */ 5195703SN/A while (curSize < params()->range.size()) { 5205703SN/A bytesRead = gzread(compressedMem, tempPage, chunkSize); 5215703SN/A if (bytesRead != chunkSize && 5229481Snilay@cs.wisc.edu bytesRead != params()->range.size() - curSize) 5235703SN/A fatal("Read failed on physical memory checkpoint file '%s'" 5245703SN/A " got %d bytes, expected %d or %d bytes\n", 5255703SN/A filename, bytesRead, chunkSize, 5265703SN/A params()->range.size() - curSize); 5275703SN/A 5285703SN/A assert(bytesRead % sizeof(long) == 0); 5295703SN/A 5305703SN/A for (int x = 0; x < bytesRead/sizeof(long); x++) 5315703SN/A { 5325703SN/A if (*(tempPage+x) != 0) { 5335703SN/A pmem_current = (long*)(pmemAddr + curSize + x * sizeof(long)); 5345703SN/A *pmem_current = *(tempPage+x); 5355703SN/A } 5365876SN/A } 5375703SN/A curSize += bytesRead; 5385703SN/A } 5395703SN/A 5405703SN/A free(tempPage); 5415703SN/A 5429481Snilay@cs.wisc.edu if (gzclose(compressedMem)) 5435703SN/A fatal("Close failed on physical memory checkpoint file '%s'\n", 5445703SN/A filename); 5455703SN/A 5465703SN/A} 5475703SN/A 5485703SN/APhysicalMemory * 5495703SN/APhysicalMemoryParams::create() 5509055Ssaidi@eecs.umich.edu{ 5515703SN/A return new PhysicalMemory(this); 5525703SN/A} 5535703SN/A