12391SN/A/* 212776Snikos.nikoleris@arm.com * Copyright (c) 2012, 2014, 2018 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 4011793Sbrandon.potter@amd.com#include "mem/physical.hh" 4111793Sbrandon.potter@amd.com 4211793Sbrandon.potter@amd.com#include <fcntl.h> 439293Sandreas.hansson@arm.com#include <sys/mman.h> 449293Sandreas.hansson@arm.com#include <sys/types.h> 459293Sandreas.hansson@arm.com#include <sys/user.h> 469293Sandreas.hansson@arm.com#include <unistd.h> 479293Sandreas.hansson@arm.com#include <zlib.h> 489293Sandreas.hansson@arm.com 499293Sandreas.hansson@arm.com#include <cerrno> 509293Sandreas.hansson@arm.com#include <climits> 519293Sandreas.hansson@arm.com#include <cstdio> 529293Sandreas.hansson@arm.com#include <iostream> 539293Sandreas.hansson@arm.com#include <string> 549293Sandreas.hansson@arm.com 559356Snilay@cs.wisc.edu#include "base/trace.hh" 5610405Sandreas.hansson@arm.com#include "debug/AddrRanges.hh" 579293Sandreas.hansson@arm.com#include "debug/Checkpoint.hh" 589293Sandreas.hansson@arm.com#include "mem/abstract_mem.hh" 592394SN/A 6010700Sandreas.hansson@arm.com/** 6110700Sandreas.hansson@arm.com * On Linux, MAP_NORESERVE allow us to simulate a very large memory 6210700Sandreas.hansson@arm.com * without committing to actually providing the swap space on the 6311446Sbaz21@cam.ac.uk * host. On FreeBSD or OSX the MAP_NORESERVE flag does not exist, 6411446Sbaz21@cam.ac.uk * so simply make it 0. 6510700Sandreas.hansson@arm.com */ 6611446Sbaz21@cam.ac.uk#if defined(__APPLE__) || defined(__FreeBSD__) 6710700Sandreas.hansson@arm.com#ifndef MAP_NORESERVE 6810700Sandreas.hansson@arm.com#define MAP_NORESERVE 0 6910700Sandreas.hansson@arm.com#endif 7010700Sandreas.hansson@arm.com#endif 7110700Sandreas.hansson@arm.com 722391SN/Ausing namespace std; 732391SN/A 749293Sandreas.hansson@arm.comPhysicalMemory::PhysicalMemory(const string& _name, 7510700Sandreas.hansson@arm.com const vector<AbstractMemory*>& _memories, 7610700Sandreas.hansson@arm.com bool mmap_using_noreserve) : 7712779Sgabeblack@google.com _name(_name), size(0), mmapUsingNoReserve(mmap_using_noreserve) 782391SN/A{ 7910700Sandreas.hansson@arm.com if (mmap_using_noreserve) 8010700Sandreas.hansson@arm.com warn("Not reserving swap space. May cause SIGSEGV on actual usage\n"); 8110700Sandreas.hansson@arm.com 829293Sandreas.hansson@arm.com // add the memories from the system to the address map as 839293Sandreas.hansson@arm.com // appropriate 8410482Sandreas.hansson@arm.com for (const auto& m : _memories) { 858931Sandreas.hansson@arm.com // only add the memory if it is part of the global address map 8610482Sandreas.hansson@arm.com if (m->isInAddrMap()) { 8710482Sandreas.hansson@arm.com memories.push_back(m); 882391SN/A 898931Sandreas.hansson@arm.com // calculate the total size once and for all 9010482Sandreas.hansson@arm.com size += m->size(); 918931Sandreas.hansson@arm.com 928931Sandreas.hansson@arm.com // add the range to our interval tree and make sure it does not 938931Sandreas.hansson@arm.com // intersect an existing range 9410482Sandreas.hansson@arm.com fatal_if(addrMap.insert(m->getAddrRange(), m) == addrMap.end(), 9510482Sandreas.hansson@arm.com "Memory address range for %s is overlapping\n", 9610482Sandreas.hansson@arm.com m->name()); 979293Sandreas.hansson@arm.com } else { 989293Sandreas.hansson@arm.com // this type of memory is used e.g. as reference memory by 999293Sandreas.hansson@arm.com // Ruby, and they also needs a backing store, but should 1009293Sandreas.hansson@arm.com // not be part of the global address map 10110482Sandreas.hansson@arm.com DPRINTF(AddrRanges, 10210482Sandreas.hansson@arm.com "Skipping memory %s that is not in global address map\n", 10310482Sandreas.hansson@arm.com m->name()); 10410482Sandreas.hansson@arm.com 10510482Sandreas.hansson@arm.com // sanity check 10610482Sandreas.hansson@arm.com fatal_if(m->getAddrRange().interleaved(), 10710482Sandreas.hansson@arm.com "Memory %s that is not in the global address map cannot " 10810482Sandreas.hansson@arm.com "be interleaved\n", m->name()); 1099293Sandreas.hansson@arm.com 1109293Sandreas.hansson@arm.com // simply do it independently, also note that this kind of 1119293Sandreas.hansson@arm.com // memories are allowed to overlap in the logic address 1129293Sandreas.hansson@arm.com // map 11310482Sandreas.hansson@arm.com vector<AbstractMemory*> unmapped_mems{m}; 11411614Sdavid.j.hashe@gmail.com createBackingStore(m->getAddrRange(), unmapped_mems, 11511614Sdavid.j.hashe@gmail.com m->isConfReported(), m->isInAddrMap(), 11611614Sdavid.j.hashe@gmail.com m->isKvmMap()); 1178931Sandreas.hansson@arm.com } 1189293Sandreas.hansson@arm.com } 1199293Sandreas.hansson@arm.com 12010070Sandreas.hansson@arm.com // iterate over the increasing addresses and chunks of contiguous 12110070Sandreas.hansson@arm.com // space to be mapped to backing store, create it and inform the 12210070Sandreas.hansson@arm.com // memories 1239565Sandreas.hansson@arm.com vector<AddrRange> intlv_ranges; 1249293Sandreas.hansson@arm.com vector<AbstractMemory*> curr_memories; 12510482Sandreas.hansson@arm.com for (const auto& r : addrMap) { 1269293Sandreas.hansson@arm.com // simply skip past all memories that are null and hence do 1279293Sandreas.hansson@arm.com // not need any backing store 12810482Sandreas.hansson@arm.com if (!r.second->isNull()) { 1299565Sandreas.hansson@arm.com // if the range is interleaved then save it for now 13010482Sandreas.hansson@arm.com if (r.first.interleaved()) { 1319565Sandreas.hansson@arm.com // if we already got interleaved ranges that are not 1329565Sandreas.hansson@arm.com // part of the same range, then first do a merge 1339565Sandreas.hansson@arm.com // before we add the new one 1349565Sandreas.hansson@arm.com if (!intlv_ranges.empty() && 13510482Sandreas.hansson@arm.com !intlv_ranges.back().mergesWith(r.first)) { 1369565Sandreas.hansson@arm.com AddrRange merged_range(intlv_ranges); 13711614Sdavid.j.hashe@gmail.com 13811614Sdavid.j.hashe@gmail.com AbstractMemory *f = curr_memories.front(); 13911614Sdavid.j.hashe@gmail.com for (const auto& c : curr_memories) 14011614Sdavid.j.hashe@gmail.com if (f->isConfReported() != c->isConfReported() || 14111614Sdavid.j.hashe@gmail.com f->isInAddrMap() != c->isInAddrMap() || 14211614Sdavid.j.hashe@gmail.com f->isKvmMap() != c->isKvmMap()) 14311614Sdavid.j.hashe@gmail.com fatal("Inconsistent flags in an interleaved " 14411614Sdavid.j.hashe@gmail.com "range\n"); 14511614Sdavid.j.hashe@gmail.com 14611614Sdavid.j.hashe@gmail.com createBackingStore(merged_range, curr_memories, 14711614Sdavid.j.hashe@gmail.com f->isConfReported(), f->isInAddrMap(), 14811614Sdavid.j.hashe@gmail.com f->isKvmMap()); 14911614Sdavid.j.hashe@gmail.com 1509565Sandreas.hansson@arm.com intlv_ranges.clear(); 1519565Sandreas.hansson@arm.com curr_memories.clear(); 1529565Sandreas.hansson@arm.com } 15310482Sandreas.hansson@arm.com intlv_ranges.push_back(r.first); 15410482Sandreas.hansson@arm.com curr_memories.push_back(r.second); 1559565Sandreas.hansson@arm.com } else { 15610482Sandreas.hansson@arm.com vector<AbstractMemory*> single_memory{r.second}; 15711614Sdavid.j.hashe@gmail.com createBackingStore(r.first, single_memory, 15811614Sdavid.j.hashe@gmail.com r.second->isConfReported(), 15911614Sdavid.j.hashe@gmail.com r.second->isInAddrMap(), 16011614Sdavid.j.hashe@gmail.com r.second->isKvmMap()); 1619565Sandreas.hansson@arm.com } 1629293Sandreas.hansson@arm.com } 1639293Sandreas.hansson@arm.com } 1649565Sandreas.hansson@arm.com 1659565Sandreas.hansson@arm.com // if there is still interleaved ranges waiting to be merged, go 1669565Sandreas.hansson@arm.com // ahead and do it 1679565Sandreas.hansson@arm.com if (!intlv_ranges.empty()) { 1689565Sandreas.hansson@arm.com AddrRange merged_range(intlv_ranges); 16911614Sdavid.j.hashe@gmail.com 17011614Sdavid.j.hashe@gmail.com AbstractMemory *f = curr_memories.front(); 17111614Sdavid.j.hashe@gmail.com for (const auto& c : curr_memories) 17211614Sdavid.j.hashe@gmail.com if (f->isConfReported() != c->isConfReported() || 17311614Sdavid.j.hashe@gmail.com f->isInAddrMap() != c->isInAddrMap() || 17411614Sdavid.j.hashe@gmail.com f->isKvmMap() != c->isKvmMap()) 17511614Sdavid.j.hashe@gmail.com fatal("Inconsistent flags in an interleaved " 17611614Sdavid.j.hashe@gmail.com "range\n"); 17711614Sdavid.j.hashe@gmail.com 17811614Sdavid.j.hashe@gmail.com createBackingStore(merged_range, curr_memories, 17911614Sdavid.j.hashe@gmail.com f->isConfReported(), f->isInAddrMap(), 18011614Sdavid.j.hashe@gmail.com f->isKvmMap()); 1819565Sandreas.hansson@arm.com } 1829293Sandreas.hansson@arm.com} 1839293Sandreas.hansson@arm.com 1849293Sandreas.hansson@arm.comvoid 1859293Sandreas.hansson@arm.comPhysicalMemory::createBackingStore(AddrRange range, 18611614Sdavid.j.hashe@gmail.com const vector<AbstractMemory*>& _memories, 18711614Sdavid.j.hashe@gmail.com bool conf_table_reported, 18811614Sdavid.j.hashe@gmail.com bool in_addr_map, bool kvm_map) 1899293Sandreas.hansson@arm.com{ 19010482Sandreas.hansson@arm.com panic_if(range.interleaved(), 19110482Sandreas.hansson@arm.com "Cannot create backing store for interleaved range %s\n", 1929411Sandreas.hansson@arm.com range.to_string()); 1939411Sandreas.hansson@arm.com 1949293Sandreas.hansson@arm.com // perform the actual mmap 19510405Sandreas.hansson@arm.com DPRINTF(AddrRanges, "Creating backing store for range %s with size %d\n", 1969411Sandreas.hansson@arm.com range.to_string(), range.size()); 1979293Sandreas.hansson@arm.com int map_flags = MAP_ANON | MAP_PRIVATE; 19810700Sandreas.hansson@arm.com 19910700Sandreas.hansson@arm.com // to be able to simulate very large memories, the user can opt to 20010700Sandreas.hansson@arm.com // pass noreserve to mmap 20110700Sandreas.hansson@arm.com if (mmapUsingNoReserve) { 20210700Sandreas.hansson@arm.com map_flags |= MAP_NORESERVE; 20310700Sandreas.hansson@arm.com } 20410700Sandreas.hansson@arm.com 2059293Sandreas.hansson@arm.com uint8_t* pmem = (uint8_t*) mmap(NULL, range.size(), 2069293Sandreas.hansson@arm.com PROT_READ | PROT_WRITE, 2079293Sandreas.hansson@arm.com map_flags, -1, 0); 2089293Sandreas.hansson@arm.com 2099293Sandreas.hansson@arm.com if (pmem == (uint8_t*) MAP_FAILED) { 2109293Sandreas.hansson@arm.com perror("mmap"); 2119405Sandreas.hansson@arm.com fatal("Could not mmap %d bytes for range %s!\n", range.size(), 2129405Sandreas.hansson@arm.com range.to_string()); 2139293Sandreas.hansson@arm.com } 2149293Sandreas.hansson@arm.com 2159293Sandreas.hansson@arm.com // remember this backing store so we can checkpoint it and unmap 2169293Sandreas.hansson@arm.com // it appropriately 21711614Sdavid.j.hashe@gmail.com backingStore.emplace_back(range, pmem, 21811614Sdavid.j.hashe@gmail.com conf_table_reported, in_addr_map, kvm_map); 2199293Sandreas.hansson@arm.com 22010070Sandreas.hansson@arm.com // point the memories to their backing store 22110482Sandreas.hansson@arm.com for (const auto& m : _memories) { 22210405Sandreas.hansson@arm.com DPRINTF(AddrRanges, "Mapping memory %s to backing store\n", 22310482Sandreas.hansson@arm.com m->name()); 22410482Sandreas.hansson@arm.com m->setBackingStore(pmem); 2258931Sandreas.hansson@arm.com } 2268931Sandreas.hansson@arm.com} 2278931Sandreas.hansson@arm.com 2289293Sandreas.hansson@arm.comPhysicalMemory::~PhysicalMemory() 2299293Sandreas.hansson@arm.com{ 2309293Sandreas.hansson@arm.com // unmap the backing store 23110482Sandreas.hansson@arm.com for (auto& s : backingStore) 23211614Sdavid.j.hashe@gmail.com munmap((char*)s.pmem, s.range.size()); 2339293Sandreas.hansson@arm.com} 2349293Sandreas.hansson@arm.com 2358931Sandreas.hansson@arm.combool 2368931Sandreas.hansson@arm.comPhysicalMemory::isMemAddr(Addr addr) const 2378931Sandreas.hansson@arm.com{ 23812779Sgabeblack@google.com return addrMap.contains(addr) != addrMap.end(); 2398931Sandreas.hansson@arm.com} 2407730SAli.Saidi@ARM.com 2418931Sandreas.hansson@arm.comAddrRangeList 2428931Sandreas.hansson@arm.comPhysicalMemory::getConfAddrRanges() const 2438931Sandreas.hansson@arm.com{ 2448931Sandreas.hansson@arm.com // this could be done once in the constructor, but since it is unlikely to 2458931Sandreas.hansson@arm.com // be called more than once the iteration should not be a problem 2468931Sandreas.hansson@arm.com AddrRangeList ranges; 2479413Sandreas.hansson@arm.com vector<AddrRange> intlv_ranges; 24810482Sandreas.hansson@arm.com for (const auto& r : addrMap) { 24910482Sandreas.hansson@arm.com if (r.second->isConfReported()) { 2509413Sandreas.hansson@arm.com // if the range is interleaved then save it for now 25110482Sandreas.hansson@arm.com if (r.first.interleaved()) { 2529413Sandreas.hansson@arm.com // if we already got interleaved ranges that are not 2539413Sandreas.hansson@arm.com // part of the same range, then first do a merge 2549413Sandreas.hansson@arm.com // before we add the new one 2559413Sandreas.hansson@arm.com if (!intlv_ranges.empty() && 25610482Sandreas.hansson@arm.com !intlv_ranges.back().mergesWith(r.first)) { 2579413Sandreas.hansson@arm.com ranges.push_back(AddrRange(intlv_ranges)); 2589413Sandreas.hansson@arm.com intlv_ranges.clear(); 2599413Sandreas.hansson@arm.com } 26010482Sandreas.hansson@arm.com intlv_ranges.push_back(r.first); 2619413Sandreas.hansson@arm.com } else { 2629413Sandreas.hansson@arm.com // keep the current range 26310482Sandreas.hansson@arm.com ranges.push_back(r.first); 2649413Sandreas.hansson@arm.com } 2658931Sandreas.hansson@arm.com } 2667730SAli.Saidi@ARM.com } 2672391SN/A 2689413Sandreas.hansson@arm.com // if there is still interleaved ranges waiting to be merged, 2699413Sandreas.hansson@arm.com // go ahead and do it 2709413Sandreas.hansson@arm.com if (!intlv_ranges.empty()) { 2719413Sandreas.hansson@arm.com ranges.push_back(AddrRange(intlv_ranges)); 2729413Sandreas.hansson@arm.com } 2739413Sandreas.hansson@arm.com 2748931Sandreas.hansson@arm.com return ranges; 2752391SN/A} 2762391SN/A 2772541SN/Avoid 2788931Sandreas.hansson@arm.comPhysicalMemory::access(PacketPtr pkt) 2792541SN/A{ 2808931Sandreas.hansson@arm.com assert(pkt->isRequest()); 28113856Sodanrc@yahoo.com.br const auto& m = addrMap.contains(pkt->getAddrRange()); 28212779Sgabeblack@google.com assert(m != addrMap.end()); 28312779Sgabeblack@google.com m->second->access(pkt); 2842391SN/A} 2852391SN/A 2868719SAli.Saidi@ARM.comvoid 2878931Sandreas.hansson@arm.comPhysicalMemory::functionalAccess(PacketPtr pkt) 2888719SAli.Saidi@ARM.com{ 2898931Sandreas.hansson@arm.com assert(pkt->isRequest()); 29013856Sodanrc@yahoo.com.br const auto& m = addrMap.contains(pkt->getAddrRange()); 29112779Sgabeblack@google.com assert(m != addrMap.end()); 29212779Sgabeblack@google.com m->second->functionalAccess(pkt); 2938719SAli.Saidi@ARM.com} 2949293Sandreas.hansson@arm.com 2959293Sandreas.hansson@arm.comvoid 29610905Sandreas.sandberg@arm.comPhysicalMemory::serialize(CheckpointOut &cp) const 2979293Sandreas.hansson@arm.com{ 2989293Sandreas.hansson@arm.com // serialize all the locked addresses and their context ids 2999293Sandreas.hansson@arm.com vector<Addr> lal_addr; 30011005Sandreas.sandberg@arm.com vector<ContextID> lal_cid; 3019293Sandreas.hansson@arm.com 30210482Sandreas.hansson@arm.com for (auto& m : memories) { 30310482Sandreas.hansson@arm.com const list<LockedAddr>& locked_addrs = m->getLockedAddrList(); 30410482Sandreas.hansson@arm.com for (const auto& l : locked_addrs) { 30510482Sandreas.hansson@arm.com lal_addr.push_back(l.addr); 30610482Sandreas.hansson@arm.com lal_cid.push_back(l.contextId); 3079293Sandreas.hansson@arm.com } 3089293Sandreas.hansson@arm.com } 3099293Sandreas.hansson@arm.com 31010905Sandreas.sandberg@arm.com SERIALIZE_CONTAINER(lal_addr); 31110905Sandreas.sandberg@arm.com SERIALIZE_CONTAINER(lal_cid); 3129293Sandreas.hansson@arm.com 3139293Sandreas.hansson@arm.com // serialize the backing stores 3149293Sandreas.hansson@arm.com unsigned int nbr_of_stores = backingStore.size(); 3159293Sandreas.hansson@arm.com SERIALIZE_SCALAR(nbr_of_stores); 3169293Sandreas.hansson@arm.com 3179293Sandreas.hansson@arm.com unsigned int store_id = 0; 3189293Sandreas.hansson@arm.com // store each backing store memory segment in a file 31910482Sandreas.hansson@arm.com for (auto& s : backingStore) { 32010905Sandreas.sandberg@arm.com ScopedCheckpointSection sec(cp, csprintf("store%d", store_id)); 32111614Sdavid.j.hashe@gmail.com serializeStore(cp, store_id++, s.range, s.pmem); 3229293Sandreas.hansson@arm.com } 3239293Sandreas.hansson@arm.com} 3249293Sandreas.hansson@arm.com 3259293Sandreas.hansson@arm.comvoid 32610905Sandreas.sandberg@arm.comPhysicalMemory::serializeStore(CheckpointOut &cp, unsigned int store_id, 32710905Sandreas.sandberg@arm.com AddrRange range, uint8_t* pmem) const 3289293Sandreas.hansson@arm.com{ 3299293Sandreas.hansson@arm.com // we cannot use the address range for the name as the 3309293Sandreas.hansson@arm.com // memories that are not part of the address map can overlap 3319386Sandreas.hansson@arm.com string filename = name() + ".store" + to_string(store_id) + ".pmem"; 3329293Sandreas.hansson@arm.com long range_size = range.size(); 3339293Sandreas.hansson@arm.com 3349293Sandreas.hansson@arm.com DPRINTF(Checkpoint, "Serializing physical memory %s with size %d\n", 3359293Sandreas.hansson@arm.com filename, range_size); 3369293Sandreas.hansson@arm.com 3379293Sandreas.hansson@arm.com SERIALIZE_SCALAR(store_id); 3389293Sandreas.hansson@arm.com SERIALIZE_SCALAR(filename); 3399293Sandreas.hansson@arm.com SERIALIZE_SCALAR(range_size); 3409293Sandreas.hansson@arm.com 3419293Sandreas.hansson@arm.com // write memory file 34210905Sandreas.sandberg@arm.com string filepath = CheckpointIn::dir() + "/" + filename.c_str(); 34310412Sandreas.hansson@arm.com gzFile compressed_mem = gzopen(filepath.c_str(), "wb"); 34410412Sandreas.hansson@arm.com if (compressed_mem == NULL) 3459293Sandreas.hansson@arm.com fatal("Can't open physical memory checkpoint file '%s'\n", 3469293Sandreas.hansson@arm.com filename); 3479293Sandreas.hansson@arm.com 3489293Sandreas.hansson@arm.com uint64_t pass_size = 0; 3499293Sandreas.hansson@arm.com 3509293Sandreas.hansson@arm.com // gzwrite fails if (int)len < 0 (gzwrite returns int) 3519293Sandreas.hansson@arm.com for (uint64_t written = 0; written < range.size(); 3529293Sandreas.hansson@arm.com written += pass_size) { 3539293Sandreas.hansson@arm.com pass_size = (uint64_t)INT_MAX < (range.size() - written) ? 3549293Sandreas.hansson@arm.com (uint64_t)INT_MAX : (range.size() - written); 3559293Sandreas.hansson@arm.com 3569293Sandreas.hansson@arm.com if (gzwrite(compressed_mem, pmem + written, 3579293Sandreas.hansson@arm.com (unsigned int) pass_size) != (int) pass_size) { 3589293Sandreas.hansson@arm.com fatal("Write failed on physical memory checkpoint file '%s'\n", 3599293Sandreas.hansson@arm.com filename); 3609293Sandreas.hansson@arm.com } 3619293Sandreas.hansson@arm.com } 3629293Sandreas.hansson@arm.com 3639293Sandreas.hansson@arm.com // close the compressed stream and check that the exit status 3649293Sandreas.hansson@arm.com // is zero 3659293Sandreas.hansson@arm.com if (gzclose(compressed_mem)) 3669293Sandreas.hansson@arm.com fatal("Close failed on physical memory checkpoint file '%s'\n", 3679293Sandreas.hansson@arm.com filename); 3689293Sandreas.hansson@arm.com 3699293Sandreas.hansson@arm.com} 3709293Sandreas.hansson@arm.com 3719293Sandreas.hansson@arm.comvoid 37210905Sandreas.sandberg@arm.comPhysicalMemory::unserialize(CheckpointIn &cp) 3739293Sandreas.hansson@arm.com{ 3749293Sandreas.hansson@arm.com // unserialize the locked addresses and map them to the 3759293Sandreas.hansson@arm.com // appropriate memory controller 3769293Sandreas.hansson@arm.com vector<Addr> lal_addr; 37711005Sandreas.sandberg@arm.com vector<ContextID> lal_cid; 37810905Sandreas.sandberg@arm.com UNSERIALIZE_CONTAINER(lal_addr); 37910905Sandreas.sandberg@arm.com UNSERIALIZE_CONTAINER(lal_cid); 38011321Ssteve.reinhardt@amd.com for (size_t i = 0; i < lal_addr.size(); ++i) { 38112776Snikos.nikoleris@arm.com const auto& m = addrMap.contains(lal_addr[i]); 3829293Sandreas.hansson@arm.com m->second->addLockedAddr(LockedAddr(lal_addr[i], lal_cid[i])); 3839293Sandreas.hansson@arm.com } 3849293Sandreas.hansson@arm.com 3859293Sandreas.hansson@arm.com // unserialize the backing stores 3869293Sandreas.hansson@arm.com unsigned int nbr_of_stores; 3879293Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(nbr_of_stores); 3889293Sandreas.hansson@arm.com 3899293Sandreas.hansson@arm.com for (unsigned int i = 0; i < nbr_of_stores; ++i) { 39010905Sandreas.sandberg@arm.com ScopedCheckpointSection sec(cp, csprintf("store%d", i)); 39110905Sandreas.sandberg@arm.com unserializeStore(cp); 3929293Sandreas.hansson@arm.com } 3939293Sandreas.hansson@arm.com 3949293Sandreas.hansson@arm.com} 3959293Sandreas.hansson@arm.com 3969293Sandreas.hansson@arm.comvoid 39710905Sandreas.sandberg@arm.comPhysicalMemory::unserializeStore(CheckpointIn &cp) 3989293Sandreas.hansson@arm.com{ 3999293Sandreas.hansson@arm.com const uint32_t chunk_size = 16384; 4009293Sandreas.hansson@arm.com 4019293Sandreas.hansson@arm.com unsigned int store_id; 4029293Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(store_id); 4039293Sandreas.hansson@arm.com 4049293Sandreas.hansson@arm.com string filename; 4059293Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(filename); 40610905Sandreas.sandberg@arm.com string filepath = cp.cptDir + "/" + filename; 4079293Sandreas.hansson@arm.com 4089293Sandreas.hansson@arm.com // mmap memoryfile 40910412Sandreas.hansson@arm.com gzFile compressed_mem = gzopen(filepath.c_str(), "rb"); 41010412Sandreas.hansson@arm.com if (compressed_mem == NULL) 4119293Sandreas.hansson@arm.com fatal("Can't open physical memory checkpoint file '%s'", filename); 4129293Sandreas.hansson@arm.com 41310070Sandreas.hansson@arm.com // we've already got the actual backing store mapped 41411614Sdavid.j.hashe@gmail.com uint8_t* pmem = backingStore[store_id].pmem; 41511614Sdavid.j.hashe@gmail.com AddrRange range = backingStore[store_id].range; 4169293Sandreas.hansson@arm.com 4179293Sandreas.hansson@arm.com long range_size; 4189293Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(range_size); 4199293Sandreas.hansson@arm.com 4209293Sandreas.hansson@arm.com DPRINTF(Checkpoint, "Unserializing physical memory %s with size %d\n", 4219293Sandreas.hansson@arm.com filename, range_size); 4229293Sandreas.hansson@arm.com 4239293Sandreas.hansson@arm.com if (range_size != range.size()) 4249293Sandreas.hansson@arm.com fatal("Memory range size has changed! Saw %lld, expected %lld\n", 4259293Sandreas.hansson@arm.com range_size, range.size()); 4269293Sandreas.hansson@arm.com 4279293Sandreas.hansson@arm.com uint64_t curr_size = 0; 4289293Sandreas.hansson@arm.com long* temp_page = new long[chunk_size]; 4299293Sandreas.hansson@arm.com long* pmem_current; 4309293Sandreas.hansson@arm.com uint32_t bytes_read; 4319293Sandreas.hansson@arm.com while (curr_size < range.size()) { 4329293Sandreas.hansson@arm.com bytes_read = gzread(compressed_mem, temp_page, chunk_size); 4339293Sandreas.hansson@arm.com if (bytes_read == 0) 4349293Sandreas.hansson@arm.com break; 4359293Sandreas.hansson@arm.com 4369293Sandreas.hansson@arm.com assert(bytes_read % sizeof(long) == 0); 4379293Sandreas.hansson@arm.com 4389293Sandreas.hansson@arm.com for (uint32_t x = 0; x < bytes_read / sizeof(long); x++) { 4399293Sandreas.hansson@arm.com // Only copy bytes that are non-zero, so we don't give 4409293Sandreas.hansson@arm.com // the VM system hell 4419293Sandreas.hansson@arm.com if (*(temp_page + x) != 0) { 4429293Sandreas.hansson@arm.com pmem_current = (long*)(pmem + curr_size + x * sizeof(long)); 4439293Sandreas.hansson@arm.com *pmem_current = *(temp_page + x); 4449293Sandreas.hansson@arm.com } 4459293Sandreas.hansson@arm.com } 4469293Sandreas.hansson@arm.com curr_size += bytes_read; 4479293Sandreas.hansson@arm.com } 4489293Sandreas.hansson@arm.com 4499293Sandreas.hansson@arm.com delete[] temp_page; 4509293Sandreas.hansson@arm.com 4519293Sandreas.hansson@arm.com if (gzclose(compressed_mem)) 4529293Sandreas.hansson@arm.com fatal("Close failed on physical memory checkpoint file '%s'\n", 4539293Sandreas.hansson@arm.com filename); 4549293Sandreas.hansson@arm.com} 455