physical.cc revision 9404
12391SN/A/* 28931Sandreas.hansson@arm.com * Copyright (c) 2012 ARM Limited 37733SAli.Saidi@ARM.com * All rights reserved 47733SAli.Saidi@ARM.com * 57733SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall 67733SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual 77733SAli.Saidi@ARM.com * property including but not limited to intellectual property relating 87733SAli.Saidi@ARM.com * to a hardware implementation of the functionality of the software 97733SAli.Saidi@ARM.com * licensed hereunder. You may use the software subject to the license 107733SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated 117733SAli.Saidi@ARM.com * unmodified and in its entirety in all distributions of the software, 127733SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form. 137733SAli.Saidi@ARM.com * 142391SN/A * Redistribution and use in source and binary forms, with or without 152391SN/A * modification, are permitted provided that the following conditions are 162391SN/A * met: redistributions of source code must retain the above copyright 172391SN/A * notice, this list of conditions and the following disclaimer; 182391SN/A * redistributions in binary form must reproduce the above copyright 192391SN/A * notice, this list of conditions and the following disclaimer in the 202391SN/A * documentation and/or other materials provided with the distribution; 212391SN/A * neither the name of the copyright holders nor the names of its 222391SN/A * contributors may be used to endorse or promote products derived from 232391SN/A * this software without specific prior written permission. 242391SN/A * 252391SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 262391SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 272391SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 282391SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 292391SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 302391SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 312391SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 322391SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 332391SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 342391SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 352391SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 362665Ssaidi@eecs.umich.edu * 378931Sandreas.hansson@arm.com * Authors: Andreas Hansson 382391SN/A */ 392391SN/A 409293Sandreas.hansson@arm.com#include <sys/mman.h> 419293Sandreas.hansson@arm.com#include <sys/types.h> 429293Sandreas.hansson@arm.com#include <sys/user.h> 439293Sandreas.hansson@arm.com#include <fcntl.h> 449293Sandreas.hansson@arm.com#include <unistd.h> 459293Sandreas.hansson@arm.com#include <zlib.h> 469293Sandreas.hansson@arm.com 479293Sandreas.hansson@arm.com#include <cerrno> 489293Sandreas.hansson@arm.com#include <climits> 499293Sandreas.hansson@arm.com#include <cstdio> 509293Sandreas.hansson@arm.com#include <iostream> 519293Sandreas.hansson@arm.com#include <string> 529293Sandreas.hansson@arm.com 539356Snilay@cs.wisc.edu#include "base/trace.hh" 548931Sandreas.hansson@arm.com#include "debug/BusAddrRanges.hh" 559293Sandreas.hansson@arm.com#include "debug/Checkpoint.hh" 569293Sandreas.hansson@arm.com#include "mem/abstract_mem.hh" 572394SN/A#include "mem/physical.hh" 582394SN/A 592391SN/Ausing namespace std; 602391SN/A 619293Sandreas.hansson@arm.comPhysicalMemory::PhysicalMemory(const string& _name, 629293Sandreas.hansson@arm.com const vector<AbstractMemory*>& _memories) : 639293Sandreas.hansson@arm.com _name(_name), size(0) 642391SN/A{ 659293Sandreas.hansson@arm.com // add the memories from the system to the address map as 669293Sandreas.hansson@arm.com // appropriate 678931Sandreas.hansson@arm.com for (vector<AbstractMemory*>::const_iterator m = _memories.begin(); 688931Sandreas.hansson@arm.com m != _memories.end(); ++m) { 698931Sandreas.hansson@arm.com // only add the memory if it is part of the global address map 708931Sandreas.hansson@arm.com if ((*m)->isInAddrMap()) { 718931Sandreas.hansson@arm.com memories.push_back(*m); 722391SN/A 738931Sandreas.hansson@arm.com // calculate the total size once and for all 748931Sandreas.hansson@arm.com size += (*m)->size(); 758931Sandreas.hansson@arm.com 768931Sandreas.hansson@arm.com // add the range to our interval tree and make sure it does not 778931Sandreas.hansson@arm.com // intersect an existing range 788931Sandreas.hansson@arm.com if (addrMap.insert((*m)->getAddrRange(), *m) == addrMap.end()) 798931Sandreas.hansson@arm.com fatal("Memory address range for %s is overlapping\n", 808931Sandreas.hansson@arm.com (*m)->name()); 819293Sandreas.hansson@arm.com } else { 829293Sandreas.hansson@arm.com DPRINTF(BusAddrRanges, 839293Sandreas.hansson@arm.com "Skipping memory %s that is not in global address map\n", 849293Sandreas.hansson@arm.com (*m)->name()); 859293Sandreas.hansson@arm.com // this type of memory is used e.g. as reference memory by 869293Sandreas.hansson@arm.com // Ruby, and they also needs a backing store, but should 879293Sandreas.hansson@arm.com // not be part of the global address map 889293Sandreas.hansson@arm.com 899293Sandreas.hansson@arm.com // simply do it independently, also note that this kind of 909293Sandreas.hansson@arm.com // memories are allowed to overlap in the logic address 919293Sandreas.hansson@arm.com // map 929293Sandreas.hansson@arm.com vector<AbstractMemory*> unmapped_mems; 939293Sandreas.hansson@arm.com unmapped_mems.push_back(*m); 949293Sandreas.hansson@arm.com createBackingStore((*m)->getAddrRange(), unmapped_mems); 958931Sandreas.hansson@arm.com } 969293Sandreas.hansson@arm.com } 979293Sandreas.hansson@arm.com 989404Sandreas.hansson@arm.com // iterate over the increasing addresses and chunks of contigous 999404Sandreas.hansson@arm.com // space to be mapped to backing store, also remember what 1009404Sandreas.hansson@arm.com // memories constitute the range so we can go and find out if we 1019404Sandreas.hansson@arm.com // have to init their parts to zero 1029293Sandreas.hansson@arm.com vector<AbstractMemory*> curr_memories; 1039293Sandreas.hansson@arm.com for (AddrRangeMap<AbstractMemory*>::const_iterator r = addrMap.begin(); 1049293Sandreas.hansson@arm.com r != addrMap.end(); ++r) { 1059293Sandreas.hansson@arm.com // simply skip past all memories that are null and hence do 1069293Sandreas.hansson@arm.com // not need any backing store 1079293Sandreas.hansson@arm.com if (!r->second->isNull()) { 1089404Sandreas.hansson@arm.com // this will eventually be extended to support merging of 1099404Sandreas.hansson@arm.com // interleaved address ranges, and although it might seem 1109404Sandreas.hansson@arm.com // overly complicated at this point it will all be used 1119404Sandreas.hansson@arm.com curr_memories.push_back(r->second); 1129404Sandreas.hansson@arm.com createBackingStore(r->first, curr_memories); 1139404Sandreas.hansson@arm.com curr_memories.clear(); 1149293Sandreas.hansson@arm.com } 1159293Sandreas.hansson@arm.com } 1169293Sandreas.hansson@arm.com} 1179293Sandreas.hansson@arm.com 1189293Sandreas.hansson@arm.comvoid 1199293Sandreas.hansson@arm.comPhysicalMemory::createBackingStore(AddrRange range, 1209293Sandreas.hansson@arm.com const vector<AbstractMemory*>& _memories) 1219293Sandreas.hansson@arm.com{ 1229293Sandreas.hansson@arm.com // perform the actual mmap 1239293Sandreas.hansson@arm.com DPRINTF(BusAddrRanges, "Creating backing store for range %x:%x\n", 1249293Sandreas.hansson@arm.com range.start, range.end); 1259293Sandreas.hansson@arm.com int map_flags = MAP_ANON | MAP_PRIVATE; 1269293Sandreas.hansson@arm.com uint8_t* pmem = (uint8_t*) mmap(NULL, range.size(), 1279293Sandreas.hansson@arm.com PROT_READ | PROT_WRITE, 1289293Sandreas.hansson@arm.com map_flags, -1, 0); 1299293Sandreas.hansson@arm.com 1309293Sandreas.hansson@arm.com if (pmem == (uint8_t*) MAP_FAILED) { 1319293Sandreas.hansson@arm.com perror("mmap"); 1329293Sandreas.hansson@arm.com fatal("Could not mmap %d bytes for range %x:%x!\n", range.size(), 1339293Sandreas.hansson@arm.com range.start, range.end); 1349293Sandreas.hansson@arm.com } 1359293Sandreas.hansson@arm.com 1369293Sandreas.hansson@arm.com // remember this backing store so we can checkpoint it and unmap 1379293Sandreas.hansson@arm.com // it appropriately 1389293Sandreas.hansson@arm.com backingStore.push_back(make_pair(range, pmem)); 1399293Sandreas.hansson@arm.com 1409404Sandreas.hansson@arm.com // count how many of the memories are to be zero initialized so we 1419404Sandreas.hansson@arm.com // can see if some but not all have this parameter set 1429404Sandreas.hansson@arm.com uint32_t init_to_zero = 0; 1439404Sandreas.hansson@arm.com 1449293Sandreas.hansson@arm.com // point the memories to their backing store, and if requested, 1459293Sandreas.hansson@arm.com // initialize the memory range to 0 1469293Sandreas.hansson@arm.com for (vector<AbstractMemory*>::const_iterator m = _memories.begin(); 1479293Sandreas.hansson@arm.com m != _memories.end(); ++m) { 1489293Sandreas.hansson@arm.com DPRINTF(BusAddrRanges, "Mapping memory %s to backing store\n", 1498931Sandreas.hansson@arm.com (*m)->name()); 1509293Sandreas.hansson@arm.com (*m)->setBackingStore(pmem); 1519293Sandreas.hansson@arm.com 1529293Sandreas.hansson@arm.com // if it should be zero, then go and make it so 1539404Sandreas.hansson@arm.com if ((*m)->initToZero()) { 1549404Sandreas.hansson@arm.com ++init_to_zero; 1559404Sandreas.hansson@arm.com } 1569404Sandreas.hansson@arm.com } 1579293Sandreas.hansson@arm.com 1589404Sandreas.hansson@arm.com if (init_to_zero != 0) { 1599404Sandreas.hansson@arm.com if (init_to_zero != _memories.size()) 1609404Sandreas.hansson@arm.com fatal("Some, but not all memories in range %x:%x are set zero\n", 1619404Sandreas.hansson@arm.com range.start, range.end); 1629404Sandreas.hansson@arm.com 1639404Sandreas.hansson@arm.com memset(pmem, 0, range.size()); 1648931Sandreas.hansson@arm.com } 1658931Sandreas.hansson@arm.com} 1668931Sandreas.hansson@arm.com 1679293Sandreas.hansson@arm.comPhysicalMemory::~PhysicalMemory() 1689293Sandreas.hansson@arm.com{ 1699293Sandreas.hansson@arm.com // unmap the backing store 1709293Sandreas.hansson@arm.com for (vector<pair<AddrRange, uint8_t*> >::iterator s = backingStore.begin(); 1719293Sandreas.hansson@arm.com s != backingStore.end(); ++s) 1729293Sandreas.hansson@arm.com munmap((char*)s->second, s->first.size()); 1739293Sandreas.hansson@arm.com} 1749293Sandreas.hansson@arm.com 1758931Sandreas.hansson@arm.combool 1768931Sandreas.hansson@arm.comPhysicalMemory::isMemAddr(Addr addr) const 1778931Sandreas.hansson@arm.com{ 1788931Sandreas.hansson@arm.com // see if the address is within the last matched range 1798931Sandreas.hansson@arm.com if (addr != rangeCache) { 1808931Sandreas.hansson@arm.com // lookup in the interval tree 1819235Sandreas.hansson@arm.com AddrRangeMap<AbstractMemory*>::const_iterator r = addrMap.find(addr); 1828931Sandreas.hansson@arm.com if (r == addrMap.end()) { 1838931Sandreas.hansson@arm.com // not in the cache, and not in the tree 1848931Sandreas.hansson@arm.com return false; 1858931Sandreas.hansson@arm.com } 1868931Sandreas.hansson@arm.com // the range is in the tree, update the cache 1878931Sandreas.hansson@arm.com rangeCache = r->first; 1888851Sandreas.hansson@arm.com } 1898851Sandreas.hansson@arm.com 1908931Sandreas.hansson@arm.com assert(addrMap.find(addr) != addrMap.end()); 1915477Snate@binkert.org 1928931Sandreas.hansson@arm.com // either matched the cache or found in the tree 1938931Sandreas.hansson@arm.com return true; 1948931Sandreas.hansson@arm.com} 1957730SAli.Saidi@ARM.com 1968931Sandreas.hansson@arm.comAddrRangeList 1978931Sandreas.hansson@arm.comPhysicalMemory::getConfAddrRanges() const 1988931Sandreas.hansson@arm.com{ 1998931Sandreas.hansson@arm.com // this could be done once in the constructor, but since it is unlikely to 2008931Sandreas.hansson@arm.com // be called more than once the iteration should not be a problem 2018931Sandreas.hansson@arm.com AddrRangeList ranges; 2028931Sandreas.hansson@arm.com for (vector<AbstractMemory*>::const_iterator m = memories.begin(); 2038931Sandreas.hansson@arm.com m != memories.end(); ++m) { 2048931Sandreas.hansson@arm.com if ((*m)->isConfReported()) { 2058931Sandreas.hansson@arm.com ranges.push_back((*m)->getAddrRange()); 2068931Sandreas.hansson@arm.com } 2077730SAli.Saidi@ARM.com } 2082391SN/A 2098931Sandreas.hansson@arm.com return ranges; 2102391SN/A} 2112391SN/A 2122541SN/Avoid 2138931Sandreas.hansson@arm.comPhysicalMemory::access(PacketPtr pkt) 2142541SN/A{ 2158931Sandreas.hansson@arm.com assert(pkt->isRequest()); 2168931Sandreas.hansson@arm.com Addr addr = pkt->getAddr(); 2179235Sandreas.hansson@arm.com AddrRangeMap<AbstractMemory*>::const_iterator m = addrMap.find(addr); 2188931Sandreas.hansson@arm.com assert(m != addrMap.end()); 2198931Sandreas.hansson@arm.com m->second->access(pkt); 2202391SN/A} 2212391SN/A 2228719SAli.Saidi@ARM.comvoid 2238931Sandreas.hansson@arm.comPhysicalMemory::functionalAccess(PacketPtr pkt) 2248719SAli.Saidi@ARM.com{ 2258931Sandreas.hansson@arm.com assert(pkt->isRequest()); 2268931Sandreas.hansson@arm.com Addr addr = pkt->getAddr(); 2279235Sandreas.hansson@arm.com AddrRangeMap<AbstractMemory*>::const_iterator m = addrMap.find(addr); 2288931Sandreas.hansson@arm.com assert(m != addrMap.end()); 2298931Sandreas.hansson@arm.com m->second->functionalAccess(pkt); 2308719SAli.Saidi@ARM.com} 2319293Sandreas.hansson@arm.com 2329293Sandreas.hansson@arm.comvoid 2339293Sandreas.hansson@arm.comPhysicalMemory::serialize(ostream& os) 2349293Sandreas.hansson@arm.com{ 2359293Sandreas.hansson@arm.com // serialize all the locked addresses and their context ids 2369293Sandreas.hansson@arm.com vector<Addr> lal_addr; 2379293Sandreas.hansson@arm.com vector<int> lal_cid; 2389293Sandreas.hansson@arm.com 2399293Sandreas.hansson@arm.com for (vector<AbstractMemory*>::iterator m = memories.begin(); 2409293Sandreas.hansson@arm.com m != memories.end(); ++m) { 2419293Sandreas.hansson@arm.com const list<LockedAddr>& locked_addrs = (*m)->getLockedAddrList(); 2429293Sandreas.hansson@arm.com for (list<LockedAddr>::const_iterator l = locked_addrs.begin(); 2439293Sandreas.hansson@arm.com l != locked_addrs.end(); ++l) { 2449293Sandreas.hansson@arm.com lal_addr.push_back(l->addr); 2459293Sandreas.hansson@arm.com lal_cid.push_back(l->contextId); 2469293Sandreas.hansson@arm.com } 2479293Sandreas.hansson@arm.com } 2489293Sandreas.hansson@arm.com 2499293Sandreas.hansson@arm.com arrayParamOut(os, "lal_addr", lal_addr); 2509293Sandreas.hansson@arm.com arrayParamOut(os, "lal_cid", lal_cid); 2519293Sandreas.hansson@arm.com 2529293Sandreas.hansson@arm.com // serialize the backing stores 2539293Sandreas.hansson@arm.com unsigned int nbr_of_stores = backingStore.size(); 2549293Sandreas.hansson@arm.com SERIALIZE_SCALAR(nbr_of_stores); 2559293Sandreas.hansson@arm.com 2569293Sandreas.hansson@arm.com unsigned int store_id = 0; 2579293Sandreas.hansson@arm.com // store each backing store memory segment in a file 2589293Sandreas.hansson@arm.com for (vector<pair<AddrRange, uint8_t*> >::iterator s = backingStore.begin(); 2599293Sandreas.hansson@arm.com s != backingStore.end(); ++s) { 2609293Sandreas.hansson@arm.com nameOut(os, csprintf("%s.store%d", name(), store_id)); 2619293Sandreas.hansson@arm.com serializeStore(os, store_id++, s->first, s->second); 2629293Sandreas.hansson@arm.com } 2639293Sandreas.hansson@arm.com} 2649293Sandreas.hansson@arm.com 2659293Sandreas.hansson@arm.comvoid 2669293Sandreas.hansson@arm.comPhysicalMemory::serializeStore(ostream& os, unsigned int store_id, 2679293Sandreas.hansson@arm.com AddrRange range, uint8_t* pmem) 2689293Sandreas.hansson@arm.com{ 2699293Sandreas.hansson@arm.com // we cannot use the address range for the name as the 2709293Sandreas.hansson@arm.com // memories that are not part of the address map can overlap 2719386Sandreas.hansson@arm.com string filename = name() + ".store" + to_string(store_id) + ".pmem"; 2729293Sandreas.hansson@arm.com long range_size = range.size(); 2739293Sandreas.hansson@arm.com 2749293Sandreas.hansson@arm.com DPRINTF(Checkpoint, "Serializing physical memory %s with size %d\n", 2759293Sandreas.hansson@arm.com filename, range_size); 2769293Sandreas.hansson@arm.com 2779293Sandreas.hansson@arm.com SERIALIZE_SCALAR(store_id); 2789293Sandreas.hansson@arm.com SERIALIZE_SCALAR(filename); 2799293Sandreas.hansson@arm.com SERIALIZE_SCALAR(range_size); 2809293Sandreas.hansson@arm.com 2819293Sandreas.hansson@arm.com // write memory file 2829293Sandreas.hansson@arm.com string filepath = Checkpoint::dir() + "/" + filename.c_str(); 2839293Sandreas.hansson@arm.com int fd = creat(filepath.c_str(), 0664); 2849293Sandreas.hansson@arm.com if (fd < 0) { 2859293Sandreas.hansson@arm.com perror("creat"); 2869293Sandreas.hansson@arm.com fatal("Can't open physical memory checkpoint file '%s'\n", 2879293Sandreas.hansson@arm.com filename); 2889293Sandreas.hansson@arm.com } 2899293Sandreas.hansson@arm.com 2909293Sandreas.hansson@arm.com gzFile compressed_mem = gzdopen(fd, "wb"); 2919293Sandreas.hansson@arm.com if (compressed_mem == NULL) 2929293Sandreas.hansson@arm.com fatal("Insufficient memory to allocate compression state for %s\n", 2939293Sandreas.hansson@arm.com filename); 2949293Sandreas.hansson@arm.com 2959293Sandreas.hansson@arm.com uint64_t pass_size = 0; 2969293Sandreas.hansson@arm.com 2979293Sandreas.hansson@arm.com // gzwrite fails if (int)len < 0 (gzwrite returns int) 2989293Sandreas.hansson@arm.com for (uint64_t written = 0; written < range.size(); 2999293Sandreas.hansson@arm.com written += pass_size) { 3009293Sandreas.hansson@arm.com pass_size = (uint64_t)INT_MAX < (range.size() - written) ? 3019293Sandreas.hansson@arm.com (uint64_t)INT_MAX : (range.size() - written); 3029293Sandreas.hansson@arm.com 3039293Sandreas.hansson@arm.com if (gzwrite(compressed_mem, pmem + written, 3049293Sandreas.hansson@arm.com (unsigned int) pass_size) != (int) pass_size) { 3059293Sandreas.hansson@arm.com fatal("Write failed on physical memory checkpoint file '%s'\n", 3069293Sandreas.hansson@arm.com filename); 3079293Sandreas.hansson@arm.com } 3089293Sandreas.hansson@arm.com } 3099293Sandreas.hansson@arm.com 3109293Sandreas.hansson@arm.com // close the compressed stream and check that the exit status 3119293Sandreas.hansson@arm.com // is zero 3129293Sandreas.hansson@arm.com if (gzclose(compressed_mem)) 3139293Sandreas.hansson@arm.com fatal("Close failed on physical memory checkpoint file '%s'\n", 3149293Sandreas.hansson@arm.com filename); 3159293Sandreas.hansson@arm.com 3169293Sandreas.hansson@arm.com} 3179293Sandreas.hansson@arm.com 3189293Sandreas.hansson@arm.comvoid 3199293Sandreas.hansson@arm.comPhysicalMemory::unserialize(Checkpoint* cp, const string& section) 3209293Sandreas.hansson@arm.com{ 3219293Sandreas.hansson@arm.com // unserialize the locked addresses and map them to the 3229293Sandreas.hansson@arm.com // appropriate memory controller 3239293Sandreas.hansson@arm.com vector<Addr> lal_addr; 3249293Sandreas.hansson@arm.com vector<int> lal_cid; 3259293Sandreas.hansson@arm.com arrayParamIn(cp, section, "lal_addr", lal_addr); 3269293Sandreas.hansson@arm.com arrayParamIn(cp, section, "lal_cid", lal_cid); 3279293Sandreas.hansson@arm.com for(size_t i = 0; i < lal_addr.size(); ++i) { 3289293Sandreas.hansson@arm.com AddrRangeMap<AbstractMemory*>::iterator m = addrMap.find(lal_addr[i]); 3299293Sandreas.hansson@arm.com m->second->addLockedAddr(LockedAddr(lal_addr[i], lal_cid[i])); 3309293Sandreas.hansson@arm.com } 3319293Sandreas.hansson@arm.com 3329293Sandreas.hansson@arm.com // unserialize the backing stores 3339293Sandreas.hansson@arm.com unsigned int nbr_of_stores; 3349293Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(nbr_of_stores); 3359293Sandreas.hansson@arm.com 3369293Sandreas.hansson@arm.com for (unsigned int i = 0; i < nbr_of_stores; ++i) { 3379293Sandreas.hansson@arm.com unserializeStore(cp, csprintf("%s.store%d", section, i)); 3389293Sandreas.hansson@arm.com } 3399293Sandreas.hansson@arm.com 3409293Sandreas.hansson@arm.com} 3419293Sandreas.hansson@arm.com 3429293Sandreas.hansson@arm.comvoid 3439293Sandreas.hansson@arm.comPhysicalMemory::unserializeStore(Checkpoint* cp, const string& section) 3449293Sandreas.hansson@arm.com{ 3459293Sandreas.hansson@arm.com const uint32_t chunk_size = 16384; 3469293Sandreas.hansson@arm.com 3479293Sandreas.hansson@arm.com unsigned int store_id; 3489293Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(store_id); 3499293Sandreas.hansson@arm.com 3509293Sandreas.hansson@arm.com string filename; 3519293Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(filename); 3529293Sandreas.hansson@arm.com string filepath = cp->cptDir + "/" + filename; 3539293Sandreas.hansson@arm.com 3549293Sandreas.hansson@arm.com // mmap memoryfile 3559293Sandreas.hansson@arm.com int fd = open(filepath.c_str(), O_RDONLY); 3569293Sandreas.hansson@arm.com if (fd < 0) { 3579293Sandreas.hansson@arm.com perror("open"); 3589293Sandreas.hansson@arm.com fatal("Can't open physical memory checkpoint file '%s'", filename); 3599293Sandreas.hansson@arm.com } 3609293Sandreas.hansson@arm.com 3619293Sandreas.hansson@arm.com gzFile compressed_mem = gzdopen(fd, "rb"); 3629293Sandreas.hansson@arm.com if (compressed_mem == NULL) 3639293Sandreas.hansson@arm.com fatal("Insufficient memory to allocate compression state for %s\n", 3649293Sandreas.hansson@arm.com filename); 3659293Sandreas.hansson@arm.com 3669293Sandreas.hansson@arm.com uint8_t* pmem = backingStore[store_id].second; 3679293Sandreas.hansson@arm.com AddrRange range = backingStore[store_id].first; 3689293Sandreas.hansson@arm.com 3699293Sandreas.hansson@arm.com // unmap file that was mmapped in the constructor, this is 3709293Sandreas.hansson@arm.com // done here to make sure that gzip and open don't muck with 3719293Sandreas.hansson@arm.com // our nice large space of memory before we reallocate it 3729293Sandreas.hansson@arm.com munmap((char*) pmem, range.size()); 3739293Sandreas.hansson@arm.com 3749293Sandreas.hansson@arm.com long range_size; 3759293Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(range_size); 3769293Sandreas.hansson@arm.com 3779293Sandreas.hansson@arm.com DPRINTF(Checkpoint, "Unserializing physical memory %s with size %d\n", 3789293Sandreas.hansson@arm.com filename, range_size); 3799293Sandreas.hansson@arm.com 3809293Sandreas.hansson@arm.com if (range_size != range.size()) 3819293Sandreas.hansson@arm.com fatal("Memory range size has changed! Saw %lld, expected %lld\n", 3829293Sandreas.hansson@arm.com range_size, range.size()); 3839293Sandreas.hansson@arm.com 3849293Sandreas.hansson@arm.com pmem = (uint8_t*) mmap(NULL, range.size(), PROT_READ | PROT_WRITE, 3859293Sandreas.hansson@arm.com MAP_ANON | MAP_PRIVATE, -1, 0); 3869293Sandreas.hansson@arm.com 3879293Sandreas.hansson@arm.com if (pmem == (void*) MAP_FAILED) { 3889293Sandreas.hansson@arm.com perror("mmap"); 3899293Sandreas.hansson@arm.com fatal("Could not mmap physical memory!\n"); 3909293Sandreas.hansson@arm.com } 3919293Sandreas.hansson@arm.com 3929293Sandreas.hansson@arm.com uint64_t curr_size = 0; 3939293Sandreas.hansson@arm.com long* temp_page = new long[chunk_size]; 3949293Sandreas.hansson@arm.com long* pmem_current; 3959293Sandreas.hansson@arm.com uint32_t bytes_read; 3969293Sandreas.hansson@arm.com while (curr_size < range.size()) { 3979293Sandreas.hansson@arm.com bytes_read = gzread(compressed_mem, temp_page, chunk_size); 3989293Sandreas.hansson@arm.com if (bytes_read == 0) 3999293Sandreas.hansson@arm.com break; 4009293Sandreas.hansson@arm.com 4019293Sandreas.hansson@arm.com assert(bytes_read % sizeof(long) == 0); 4029293Sandreas.hansson@arm.com 4039293Sandreas.hansson@arm.com for (uint32_t x = 0; x < bytes_read / sizeof(long); x++) { 4049293Sandreas.hansson@arm.com // Only copy bytes that are non-zero, so we don't give 4059293Sandreas.hansson@arm.com // the VM system hell 4069293Sandreas.hansson@arm.com if (*(temp_page + x) != 0) { 4079293Sandreas.hansson@arm.com pmem_current = (long*)(pmem + curr_size + x * sizeof(long)); 4089293Sandreas.hansson@arm.com *pmem_current = *(temp_page + x); 4099293Sandreas.hansson@arm.com } 4109293Sandreas.hansson@arm.com } 4119293Sandreas.hansson@arm.com curr_size += bytes_read; 4129293Sandreas.hansson@arm.com } 4139293Sandreas.hansson@arm.com 4149293Sandreas.hansson@arm.com delete[] temp_page; 4159293Sandreas.hansson@arm.com 4169293Sandreas.hansson@arm.com if (gzclose(compressed_mem)) 4179293Sandreas.hansson@arm.com fatal("Close failed on physical memory checkpoint file '%s'\n", 4189293Sandreas.hansson@arm.com filename); 4199293Sandreas.hansson@arm.com} 420