physical.cc revision 9413
110066Sandreas.hansson@arm.com/* 210066Sandreas.hansson@arm.com * Copyright (c) 2012 ARM Limited 310066Sandreas.hansson@arm.com * All rights reserved 410066Sandreas.hansson@arm.com * 510066Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 610066Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 710066Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 810066Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 910066Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 1010066Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 1110066Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 1210066Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 1310066Sandreas.hansson@arm.com * 1410066Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 1510066Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 1610066Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 1710066Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 1810066Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 1910066Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 2010066Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 2110066Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 2210066Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 2310066Sandreas.hansson@arm.com * this software without specific prior written permission. 2410066Sandreas.hansson@arm.com * 2510066Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2610066Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2710066Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2810066Sandreas.hansson@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2910066Sandreas.hansson@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3010066Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3110066Sandreas.hansson@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3210066Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3310066Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3410066Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3510066Sandreas.hansson@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3610066Sandreas.hansson@arm.com * 3710066Sandreas.hansson@arm.com * Authors: Andreas Hansson 3810066Sandreas.hansson@arm.com */ 3910066Sandreas.hansson@arm.com 4010066Sandreas.hansson@arm.com#include <sys/mman.h> 4110066Sandreas.hansson@arm.com#include <sys/types.h> 4210066Sandreas.hansson@arm.com#include <sys/user.h> 4310066Sandreas.hansson@arm.com#include <fcntl.h> 4410066Sandreas.hansson@arm.com#include <unistd.h> 4510066Sandreas.hansson@arm.com#include <zlib.h> 4610066Sandreas.hansson@arm.com 4710066Sandreas.hansson@arm.com#include <cerrno> 4810066Sandreas.hansson@arm.com#include <climits> 4910066Sandreas.hansson@arm.com#include <cstdio> 5010066Sandreas.hansson@arm.com#include <iostream> 5110066Sandreas.hansson@arm.com#include <string> 5210066Sandreas.hansson@arm.com 5310296Sandreas.hansson@arm.com#include "base/trace.hh" 5410066Sandreas.hansson@arm.com#include "debug/BusAddrRanges.hh" 5510066Sandreas.hansson@arm.com#include "debug/Checkpoint.hh" 5610066Sandreas.hansson@arm.com#include "mem/abstract_mem.hh" 5710066Sandreas.hansson@arm.com#include "mem/physical.hh" 5810066Sandreas.hansson@arm.com 5910066Sandreas.hansson@arm.comusing namespace std; 6010066Sandreas.hansson@arm.com 6110066Sandreas.hansson@arm.comPhysicalMemory::PhysicalMemory(const string& _name, 6210066Sandreas.hansson@arm.com const vector<AbstractMemory*>& _memories) : 6310066Sandreas.hansson@arm.com _name(_name), size(0) 6410066Sandreas.hansson@arm.com{ 6510066Sandreas.hansson@arm.com // add the memories from the system to the address map as 6610066Sandreas.hansson@arm.com // appropriate 6710066Sandreas.hansson@arm.com for (vector<AbstractMemory*>::const_iterator m = _memories.begin(); 6810066Sandreas.hansson@arm.com m != _memories.end(); ++m) { 6910066Sandreas.hansson@arm.com // only add the memory if it is part of the global address map 7010066Sandreas.hansson@arm.com if ((*m)->isInAddrMap()) { 7110066Sandreas.hansson@arm.com memories.push_back(*m); 7210066Sandreas.hansson@arm.com 7310066Sandreas.hansson@arm.com // calculate the total size once and for all 7410066Sandreas.hansson@arm.com size += (*m)->size(); 7510066Sandreas.hansson@arm.com 7610066Sandreas.hansson@arm.com // add the range to our interval tree and make sure it does not 7710066Sandreas.hansson@arm.com // intersect an existing range 7810066Sandreas.hansson@arm.com if (addrMap.insert((*m)->getAddrRange(), *m) == addrMap.end()) 7910466Sandreas.hansson@arm.com fatal("Memory address range for %s is overlapping\n", 8010466Sandreas.hansson@arm.com (*m)->name()); 8110066Sandreas.hansson@arm.com } else { 8210066Sandreas.hansson@arm.com DPRINTF(BusAddrRanges, 8310066Sandreas.hansson@arm.com "Skipping memory %s that is not in global address map\n", 8410066Sandreas.hansson@arm.com (*m)->name()); 8510066Sandreas.hansson@arm.com // this type of memory is used e.g. as reference memory by 8610066Sandreas.hansson@arm.com // Ruby, and they also needs a backing store, but should 8710066Sandreas.hansson@arm.com // not be part of the global address map 8810066Sandreas.hansson@arm.com 8910066Sandreas.hansson@arm.com // simply do it independently, also note that this kind of 9010066Sandreas.hansson@arm.com // memories are allowed to overlap in the logic address 9110066Sandreas.hansson@arm.com // map 9210066Sandreas.hansson@arm.com vector<AbstractMemory*> unmapped_mems; 9310066Sandreas.hansson@arm.com unmapped_mems.push_back(*m); 9410066Sandreas.hansson@arm.com createBackingStore((*m)->getAddrRange(), unmapped_mems); 9510296Sandreas.hansson@arm.com } 9610296Sandreas.hansson@arm.com } 9710066Sandreas.hansson@arm.com 9810066Sandreas.hansson@arm.com // iterate over the increasing addresses and chunks of contigous 9910066Sandreas.hansson@arm.com // space to be mapped to backing store, also remember what 10010066Sandreas.hansson@arm.com // memories constitute the range so we can go and find out if we 10110066Sandreas.hansson@arm.com // have to init their parts to zero 10210066Sandreas.hansson@arm.com vector<AbstractMemory*> curr_memories; 10310066Sandreas.hansson@arm.com for (AddrRangeMap<AbstractMemory*>::const_iterator r = addrMap.begin(); 10410066Sandreas.hansson@arm.com r != addrMap.end(); ++r) { 10510066Sandreas.hansson@arm.com // simply skip past all memories that are null and hence do 10610066Sandreas.hansson@arm.com // not need any backing store 10710066Sandreas.hansson@arm.com if (!r->second->isNull()) { 10810066Sandreas.hansson@arm.com // this will eventually be extended to support merging of 10910066Sandreas.hansson@arm.com // interleaved address ranges, and although it might seem 11010066Sandreas.hansson@arm.com // overly complicated at this point it will all be used 11110066Sandreas.hansson@arm.com curr_memories.push_back(r->second); 11210066Sandreas.hansson@arm.com createBackingStore(r->first, curr_memories); 11310066Sandreas.hansson@arm.com curr_memories.clear(); 11410066Sandreas.hansson@arm.com } 11510066Sandreas.hansson@arm.com } 11610066Sandreas.hansson@arm.com} 11710066Sandreas.hansson@arm.com 11810066Sandreas.hansson@arm.comvoid 11910066Sandreas.hansson@arm.comPhysicalMemory::createBackingStore(AddrRange range, 12010913Sandreas.sandberg@arm.com const vector<AbstractMemory*>& _memories) 12110913Sandreas.sandberg@arm.com{ 12210066Sandreas.hansson@arm.com if (range.interleaved()) 12310066Sandreas.hansson@arm.com panic("Cannot create backing store for interleaved range %s\n", 12410066Sandreas.hansson@arm.com range.to_string()); 12510066Sandreas.hansson@arm.com 12610066Sandreas.hansson@arm.com // perform the actual mmap 12710066Sandreas.hansson@arm.com DPRINTF(BusAddrRanges, "Creating backing store for range %s with size %d\n", 12810066Sandreas.hansson@arm.com range.to_string(), range.size()); 12910066Sandreas.hansson@arm.com int map_flags = MAP_ANON | MAP_PRIVATE; 13010066Sandreas.hansson@arm.com uint8_t* pmem = (uint8_t*) mmap(NULL, range.size(), 13110066Sandreas.hansson@arm.com PROT_READ | PROT_WRITE, 13210066Sandreas.hansson@arm.com map_flags, -1, 0); 13310066Sandreas.hansson@arm.com 13410066Sandreas.hansson@arm.com if (pmem == (uint8_t*) MAP_FAILED) { 13510066Sandreas.hansson@arm.com perror("mmap"); 13610066Sandreas.hansson@arm.com fatal("Could not mmap %d bytes for range %s!\n", range.size(), 13710066Sandreas.hansson@arm.com range.to_string()); 13810066Sandreas.hansson@arm.com } 13910066Sandreas.hansson@arm.com 14010066Sandreas.hansson@arm.com // remember this backing store so we can checkpoint it and unmap 14110066Sandreas.hansson@arm.com // it appropriately 14210066Sandreas.hansson@arm.com backingStore.push_back(make_pair(range, pmem)); 14310066Sandreas.hansson@arm.com 14410066Sandreas.hansson@arm.com // count how many of the memories are to be zero initialized so we 14510066Sandreas.hansson@arm.com // can see if some but not all have this parameter set 14610713Sandreas.hansson@arm.com uint32_t init_to_zero = 0; 14710066Sandreas.hansson@arm.com 14810066Sandreas.hansson@arm.com // point the memories to their backing store, and if requested, 14910066Sandreas.hansson@arm.com // initialize the memory range to 0 15010066Sandreas.hansson@arm.com for (vector<AbstractMemory*>::const_iterator m = _memories.begin(); 15110066Sandreas.hansson@arm.com m != _memories.end(); ++m) { 15210066Sandreas.hansson@arm.com DPRINTF(BusAddrRanges, "Mapping memory %s to backing store\n", 15310066Sandreas.hansson@arm.com (*m)->name()); 15410066Sandreas.hansson@arm.com (*m)->setBackingStore(pmem); 15510066Sandreas.hansson@arm.com 15610066Sandreas.hansson@arm.com // if it should be zero, then go and make it so 15710066Sandreas.hansson@arm.com if ((*m)->initToZero()) { 15810066Sandreas.hansson@arm.com ++init_to_zero; 15910066Sandreas.hansson@arm.com } 16010066Sandreas.hansson@arm.com } 16110066Sandreas.hansson@arm.com 16210066Sandreas.hansson@arm.com if (init_to_zero != 0) { 16310066Sandreas.hansson@arm.com if (init_to_zero != _memories.size()) 16410066Sandreas.hansson@arm.com fatal("Some, but not all memories in range %s are set zero\n", 16510066Sandreas.hansson@arm.com range.to_string()); 16610066Sandreas.hansson@arm.com 16710066Sandreas.hansson@arm.com memset(pmem, 0, range.size()); 16810066Sandreas.hansson@arm.com } 16910066Sandreas.hansson@arm.com} 17010066Sandreas.hansson@arm.com 17110066Sandreas.hansson@arm.comPhysicalMemory::~PhysicalMemory() 17210066Sandreas.hansson@arm.com{ 17310066Sandreas.hansson@arm.com // unmap the backing store 17410066Sandreas.hansson@arm.com for (vector<pair<AddrRange, uint8_t*> >::iterator s = backingStore.begin(); 17510066Sandreas.hansson@arm.com s != backingStore.end(); ++s) 17610066Sandreas.hansson@arm.com munmap((char*)s->second, s->first.size()); 17710066Sandreas.hansson@arm.com} 17811192Sandreas.hansson@arm.com 17910066Sandreas.hansson@arm.combool 18011190Sandreas.hansson@arm.comPhysicalMemory::isMemAddr(Addr addr) const 18110066Sandreas.hansson@arm.com{ 18210066Sandreas.hansson@arm.com // see if the address is within the last matched range 18310066Sandreas.hansson@arm.com if (!rangeCache.contains(addr)) { 18411192Sandreas.hansson@arm.com // lookup in the interval tree 18511192Sandreas.hansson@arm.com AddrRangeMap<AbstractMemory*>::const_iterator r = addrMap.find(addr); 18611192Sandreas.hansson@arm.com if (r == addrMap.end()) { 18711192Sandreas.hansson@arm.com // not in the cache, and not in the tree 18811192Sandreas.hansson@arm.com return false; 18911192Sandreas.hansson@arm.com } 19010066Sandreas.hansson@arm.com // the range is in the tree, update the cache 19110066Sandreas.hansson@arm.com rangeCache = r->first; 19210066Sandreas.hansson@arm.com } 19310066Sandreas.hansson@arm.com 19410066Sandreas.hansson@arm.com assert(addrMap.find(addr) != addrMap.end()); 19510066Sandreas.hansson@arm.com 19610066Sandreas.hansson@arm.com // either matched the cache or found in the tree 19710066Sandreas.hansson@arm.com return true; 19810066Sandreas.hansson@arm.com} 19910066Sandreas.hansson@arm.com 20010066Sandreas.hansson@arm.comAddrRangeList 20110066Sandreas.hansson@arm.comPhysicalMemory::getConfAddrRanges() const 20210066Sandreas.hansson@arm.com{ 20310066Sandreas.hansson@arm.com // this could be done once in the constructor, but since it is unlikely to 20410066Sandreas.hansson@arm.com // be called more than once the iteration should not be a problem 20510066Sandreas.hansson@arm.com AddrRangeList ranges; 20610066Sandreas.hansson@arm.com vector<AddrRange> intlv_ranges; 20710066Sandreas.hansson@arm.com for (AddrRangeMap<AbstractMemory*>::const_iterator r = addrMap.begin(); 20810066Sandreas.hansson@arm.com r != addrMap.end(); ++r) { 20910066Sandreas.hansson@arm.com if (r->second->isConfReported()) { 21010066Sandreas.hansson@arm.com // if the range is interleaved then save it for now 21110066Sandreas.hansson@arm.com if (r->first.interleaved()) { 21210066Sandreas.hansson@arm.com // if we already got interleaved ranges that are not 21310066Sandreas.hansson@arm.com // part of the same range, then first do a merge 21410066Sandreas.hansson@arm.com // before we add the new one 21510066Sandreas.hansson@arm.com if (!intlv_ranges.empty() && 21610066Sandreas.hansson@arm.com !intlv_ranges.back().mergesWith(r->first)) { 21710066Sandreas.hansson@arm.com ranges.push_back(AddrRange(intlv_ranges)); 21810066Sandreas.hansson@arm.com intlv_ranges.clear(); 21910066Sandreas.hansson@arm.com } 22010066Sandreas.hansson@arm.com intlv_ranges.push_back(r->first); 22110066Sandreas.hansson@arm.com } else { 22210066Sandreas.hansson@arm.com // keep the current range 22310066Sandreas.hansson@arm.com ranges.push_back(r->first); 22410066Sandreas.hansson@arm.com } 22510066Sandreas.hansson@arm.com } 22610066Sandreas.hansson@arm.com } 22710066Sandreas.hansson@arm.com 22810066Sandreas.hansson@arm.com // if there is still interleaved ranges waiting to be merged, 22910066Sandreas.hansson@arm.com // go ahead and do it 23010066Sandreas.hansson@arm.com if (!intlv_ranges.empty()) { 23110066Sandreas.hansson@arm.com ranges.push_back(AddrRange(intlv_ranges)); 23210066Sandreas.hansson@arm.com } 23310066Sandreas.hansson@arm.com 23410066Sandreas.hansson@arm.com return ranges; 23510066Sandreas.hansson@arm.com} 23610066Sandreas.hansson@arm.com 23710066Sandreas.hansson@arm.comvoid 23810066Sandreas.hansson@arm.comPhysicalMemory::access(PacketPtr pkt) 23910713Sandreas.hansson@arm.com{ 24010066Sandreas.hansson@arm.com assert(pkt->isRequest()); 24110066Sandreas.hansson@arm.com Addr addr = pkt->getAddr(); 24210066Sandreas.hansson@arm.com AddrRangeMap<AbstractMemory*>::const_iterator m = addrMap.find(addr); 24310066Sandreas.hansson@arm.com assert(m != addrMap.end()); 24410066Sandreas.hansson@arm.com m->second->access(pkt); 24510066Sandreas.hansson@arm.com} 24610066Sandreas.hansson@arm.com 24710066Sandreas.hansson@arm.comvoid 24810066Sandreas.hansson@arm.comPhysicalMemory::functionalAccess(PacketPtr pkt) 24910066Sandreas.hansson@arm.com{ 25010066Sandreas.hansson@arm.com assert(pkt->isRequest()); 25110066Sandreas.hansson@arm.com Addr addr = pkt->getAddr(); 25210066Sandreas.hansson@arm.com AddrRangeMap<AbstractMemory*>::const_iterator m = addrMap.find(addr); 25310066Sandreas.hansson@arm.com assert(m != addrMap.end()); 25410066Sandreas.hansson@arm.com m->second->functionalAccess(pkt); 25510066Sandreas.hansson@arm.com} 25610066Sandreas.hansson@arm.com 25710066Sandreas.hansson@arm.comvoid 25810066Sandreas.hansson@arm.comPhysicalMemory::serialize(ostream& os) 25910066Sandreas.hansson@arm.com{ 26010066Sandreas.hansson@arm.com // serialize all the locked addresses and their context ids 26110066Sandreas.hansson@arm.com vector<Addr> lal_addr; 26210066Sandreas.hansson@arm.com vector<int> lal_cid; 26310721SMarco.Balboni@ARM.com 26410721SMarco.Balboni@ARM.com for (vector<AbstractMemory*>::iterator m = memories.begin(); 26510721SMarco.Balboni@ARM.com m != memories.end(); ++m) { 26610721SMarco.Balboni@ARM.com const list<LockedAddr>& locked_addrs = (*m)->getLockedAddrList(); 26710694SMarco.Balboni@ARM.com for (list<LockedAddr>::const_iterator l = locked_addrs.begin(); 26810066Sandreas.hansson@arm.com l != locked_addrs.end(); ++l) { 26910066Sandreas.hansson@arm.com lal_addr.push_back(l->addr); 27010066Sandreas.hansson@arm.com lal_cid.push_back(l->contextId); 27110066Sandreas.hansson@arm.com } 27210066Sandreas.hansson@arm.com } 27310066Sandreas.hansson@arm.com 27410066Sandreas.hansson@arm.com arrayParamOut(os, "lal_addr", lal_addr); 27510066Sandreas.hansson@arm.com arrayParamOut(os, "lal_cid", lal_cid); 27610066Sandreas.hansson@arm.com 27710066Sandreas.hansson@arm.com // serialize the backing stores 27810721SMarco.Balboni@ARM.com unsigned int nbr_of_stores = backingStore.size(); 27910066Sandreas.hansson@arm.com SERIALIZE_SCALAR(nbr_of_stores); 28011190Sandreas.hansson@arm.com 28111190Sandreas.hansson@arm.com unsigned int store_id = 0; 28210066Sandreas.hansson@arm.com // store each backing store memory segment in a file 28310066Sandreas.hansson@arm.com for (vector<pair<AddrRange, uint8_t*> >::iterator s = backingStore.begin(); 28410066Sandreas.hansson@arm.com s != backingStore.end(); ++s) { 28510066Sandreas.hansson@arm.com nameOut(os, csprintf("%s.store%d", name(), store_id)); 28610066Sandreas.hansson@arm.com serializeStore(os, store_id++, s->first, s->second); 28710296Sandreas.hansson@arm.com } 28810066Sandreas.hansson@arm.com} 28910066Sandreas.hansson@arm.com 29010066Sandreas.hansson@arm.comvoid 29110066Sandreas.hansson@arm.comPhysicalMemory::serializeStore(ostream& os, unsigned int store_id, 29210066Sandreas.hansson@arm.com AddrRange range, uint8_t* pmem) 29310066Sandreas.hansson@arm.com{ 29410066Sandreas.hansson@arm.com // we cannot use the address range for the name as the 29510066Sandreas.hansson@arm.com // memories that are not part of the address map can overlap 29610066Sandreas.hansson@arm.com string filename = name() + ".store" + to_string(store_id) + ".pmem"; 29710066Sandreas.hansson@arm.com long range_size = range.size(); 29810066Sandreas.hansson@arm.com 29910066Sandreas.hansson@arm.com DPRINTF(Checkpoint, "Serializing physical memory %s with size %d\n", 30010066Sandreas.hansson@arm.com filename, range_size); 30110066Sandreas.hansson@arm.com 30210066Sandreas.hansson@arm.com SERIALIZE_SCALAR(store_id); 30310066Sandreas.hansson@arm.com SERIALIZE_SCALAR(filename); 30410066Sandreas.hansson@arm.com SERIALIZE_SCALAR(range_size); 30510066Sandreas.hansson@arm.com 30610066Sandreas.hansson@arm.com // write memory file 30710066Sandreas.hansson@arm.com string filepath = Checkpoint::dir() + "/" + filename.c_str(); 30810066Sandreas.hansson@arm.com int fd = creat(filepath.c_str(), 0664); 30910066Sandreas.hansson@arm.com if (fd < 0) { 31010066Sandreas.hansson@arm.com perror("creat"); 31110066Sandreas.hansson@arm.com fatal("Can't open physical memory checkpoint file '%s'\n", 31210066Sandreas.hansson@arm.com filename); 31310066Sandreas.hansson@arm.com } 31410066Sandreas.hansson@arm.com 31510296Sandreas.hansson@arm.com gzFile compressed_mem = gzdopen(fd, "wb"); 31610066Sandreas.hansson@arm.com if (compressed_mem == NULL) 31710066Sandreas.hansson@arm.com fatal("Insufficient memory to allocate compression state for %s\n", 31810066Sandreas.hansson@arm.com filename); 31910066Sandreas.hansson@arm.com 32010066Sandreas.hansson@arm.com uint64_t pass_size = 0; 32110066Sandreas.hansson@arm.com 32210066Sandreas.hansson@arm.com // gzwrite fails if (int)len < 0 (gzwrite returns int) 32310066Sandreas.hansson@arm.com for (uint64_t written = 0; written < range.size(); 32410066Sandreas.hansson@arm.com written += pass_size) { 32510066Sandreas.hansson@arm.com pass_size = (uint64_t)INT_MAX < (range.size() - written) ? 32610066Sandreas.hansson@arm.com (uint64_t)INT_MAX : (range.size() - written); 32710066Sandreas.hansson@arm.com 32810066Sandreas.hansson@arm.com if (gzwrite(compressed_mem, pmem + written, 32910066Sandreas.hansson@arm.com (unsigned int) pass_size) != (int) pass_size) { 33010066Sandreas.hansson@arm.com fatal("Write failed on physical memory checkpoint file '%s'\n", 33110066Sandreas.hansson@arm.com filename); 33210066Sandreas.hansson@arm.com } 33310913Sandreas.sandberg@arm.com } 33410913Sandreas.sandberg@arm.com 33510066Sandreas.hansson@arm.com // close the compressed stream and check that the exit status 33610066Sandreas.hansson@arm.com // is zero 33710066Sandreas.hansson@arm.com if (gzclose(compressed_mem)) 33810066Sandreas.hansson@arm.com fatal("Close failed on physical memory checkpoint file '%s'\n", 33910066Sandreas.hansson@arm.com filename); 34010066Sandreas.hansson@arm.com 34110066Sandreas.hansson@arm.com} 34210066Sandreas.hansson@arm.com 34310066Sandreas.hansson@arm.comvoid 34410066Sandreas.hansson@arm.comPhysicalMemory::unserialize(Checkpoint* cp, const string& section) 34510066Sandreas.hansson@arm.com{ 34610066Sandreas.hansson@arm.com // unserialize the locked addresses and map them to the 34710921Sandreas.hansson@arm.com // appropriate memory controller 34810913Sandreas.sandberg@arm.com vector<Addr> lal_addr; 34910066Sandreas.hansson@arm.com vector<int> lal_cid; 35010066Sandreas.hansson@arm.com arrayParamIn(cp, section, "lal_addr", lal_addr); 35110066Sandreas.hansson@arm.com arrayParamIn(cp, section, "lal_cid", lal_cid); 35210913Sandreas.sandberg@arm.com for(size_t i = 0; i < lal_addr.size(); ++i) { 35310066Sandreas.hansson@arm.com AddrRangeMap<AbstractMemory*>::const_iterator m = 35410066Sandreas.hansson@arm.com addrMap.find(lal_addr[i]); 35510066Sandreas.hansson@arm.com m->second->addLockedAddr(LockedAddr(lal_addr[i], lal_cid[i])); 35610066Sandreas.hansson@arm.com } 35710066Sandreas.hansson@arm.com 35810066Sandreas.hansson@arm.com // unserialize the backing stores 35910066Sandreas.hansson@arm.com unsigned int nbr_of_stores; 36010066Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(nbr_of_stores); 36110066Sandreas.hansson@arm.com 36210066Sandreas.hansson@arm.com for (unsigned int i = 0; i < nbr_of_stores; ++i) { 36310066Sandreas.hansson@arm.com unserializeStore(cp, csprintf("%s.store%d", section, i)); 36410066Sandreas.hansson@arm.com } 36510066Sandreas.hansson@arm.com 36610066Sandreas.hansson@arm.com} 36710066Sandreas.hansson@arm.com 36810066Sandreas.hansson@arm.comvoid 36910066Sandreas.hansson@arm.comPhysicalMemory::unserializeStore(Checkpoint* cp, const string& section) 37010066Sandreas.hansson@arm.com{ 37110066Sandreas.hansson@arm.com const uint32_t chunk_size = 16384; 37210066Sandreas.hansson@arm.com 37310066Sandreas.hansson@arm.com unsigned int store_id; 37410066Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(store_id); 37510066Sandreas.hansson@arm.com 37610066Sandreas.hansson@arm.com string filename; 37710066Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(filename); 37810066Sandreas.hansson@arm.com string filepath = cp->cptDir + "/" + filename; 37910066Sandreas.hansson@arm.com 38010066Sandreas.hansson@arm.com // mmap memoryfile 38110066Sandreas.hansson@arm.com int fd = open(filepath.c_str(), O_RDONLY); 38210066Sandreas.hansson@arm.com if (fd < 0) { 38310066Sandreas.hansson@arm.com perror("open"); 38410066Sandreas.hansson@arm.com fatal("Can't open physical memory checkpoint file '%s'", filename); 38510066Sandreas.hansson@arm.com } 38610066Sandreas.hansson@arm.com 38710066Sandreas.hansson@arm.com gzFile compressed_mem = gzdopen(fd, "rb"); 38810713Sandreas.hansson@arm.com if (compressed_mem == NULL) 38910066Sandreas.hansson@arm.com fatal("Insufficient memory to allocate compression state for %s\n", 39010713Sandreas.hansson@arm.com filename); 39110066Sandreas.hansson@arm.com 39210066Sandreas.hansson@arm.com uint8_t* pmem = backingStore[store_id].second; 39310066Sandreas.hansson@arm.com AddrRange range = backingStore[store_id].first; 39410066Sandreas.hansson@arm.com 39510066Sandreas.hansson@arm.com // unmap file that was mmapped in the constructor, this is 39610066Sandreas.hansson@arm.com // done here to make sure that gzip and open don't muck with 39710066Sandreas.hansson@arm.com // our nice large space of memory before we reallocate it 398 munmap((char*) pmem, range.size()); 399 400 long range_size; 401 UNSERIALIZE_SCALAR(range_size); 402 403 DPRINTF(Checkpoint, "Unserializing physical memory %s with size %d\n", 404 filename, range_size); 405 406 if (range_size != range.size()) 407 fatal("Memory range size has changed! Saw %lld, expected %lld\n", 408 range_size, range.size()); 409 410 pmem = (uint8_t*) mmap(NULL, range.size(), PROT_READ | PROT_WRITE, 411 MAP_ANON | MAP_PRIVATE, -1, 0); 412 413 if (pmem == (void*) MAP_FAILED) { 414 perror("mmap"); 415 fatal("Could not mmap physical memory!\n"); 416 } 417 418 uint64_t curr_size = 0; 419 long* temp_page = new long[chunk_size]; 420 long* pmem_current; 421 uint32_t bytes_read; 422 while (curr_size < range.size()) { 423 bytes_read = gzread(compressed_mem, temp_page, chunk_size); 424 if (bytes_read == 0) 425 break; 426 427 assert(bytes_read % sizeof(long) == 0); 428 429 for (uint32_t x = 0; x < bytes_read / sizeof(long); x++) { 430 // Only copy bytes that are non-zero, so we don't give 431 // the VM system hell 432 if (*(temp_page + x) != 0) { 433 pmem_current = (long*)(pmem + curr_size + x * sizeof(long)); 434 *pmem_current = *(temp_page + x); 435 } 436 } 437 curr_size += bytes_read; 438 } 439 440 delete[] temp_page; 441 442 if (gzclose(compressed_mem)) 443 fatal("Close failed on physical memory checkpoint file '%s'\n", 444 filename); 445} 446