55#include "debug/AddrRanges.hh"
56#include "debug/Checkpoint.hh"
67#if defined(__APPLE__) || defined(__FreeBSD__)
69#define MAP_NORESERVE 0
81 bool mmap_using_noreserve,
82 const std::string& shared_backstore,
83 bool auto_unlink_shared_backstore) :
90 registerExitCallback([=]() { shm_unlink(shared_backstore.c_str()); });
93 if (mmap_using_noreserve)
94 warn(
"Not reserving swap space. May cause SIGSEGV on actual usage\n");
98 for (
const auto&
m : _memories) {
100 if (
m->isInAddrMap()) {
101 memories.push_back(
m);
108 fatal_if(addrMap.insert(
m->getAddrRange(),
m) == addrMap.end(),
109 "Memory address range for %s is overlapping\n",
116 "Skipping memory %s that is not in global address map\n",
120 fatal_if(
m->getAddrRange().interleaved(),
121 "Memory %s that is not in the global address map cannot "
122 "be interleaved\n",
m->name());
128 createBackingStore(
m->getAddrRange(), unmapped_mems,
129 m->isConfReported(),
m->isInAddrMap(),
137 std::vector<AddrRange> intlv_ranges;
138 std::vector<AbstractMemory*> curr_memories;
139 for (
const auto&
r : addrMap) {
142 if (!
r.second->isNull()) {
144 if (
r.first.interleaved()) {
148 if (!intlv_ranges.empty() &&
149 !intlv_ranges.back().mergesWith(
r.first)) {
150 AddrRange merged_range(intlv_ranges);
153 for (
const auto&
c : curr_memories)
154 if (
f->isConfReported() !=
c->isConfReported() ||
155 f->isInAddrMap() !=
c->isInAddrMap() ||
156 f->isKvmMap() !=
c->isKvmMap())
157 fatal(
"Inconsistent flags in an interleaved "
160 createBackingStore(merged_range, curr_memories,
161 f->isConfReported(),
f->isInAddrMap(),
164 intlv_ranges.clear();
165 curr_memories.clear();
167 intlv_ranges.push_back(
r.first);
168 curr_memories.push_back(
r.second);
170 std::vector<AbstractMemory*> single_memory{
r.second};
171 createBackingStore(
r.first, single_memory,
172 r.second->isConfReported(),
173 r.second->isInAddrMap(),
174 r.second->isKvmMap());
181 if (!intlv_ranges.empty()) {
182 AddrRange merged_range(intlv_ranges);
184 AbstractMemory *f = curr_memories.front();
185 for (const auto& c : curr_memories)
186 if (f->isConfReported() != c->isConfReported() ||
187 f->isInAddrMap() != c->isInAddrMap() ||
188 f->isKvmMap() != c->isKvmMap())
189 fatal(
"Inconsistent flags in an interleaved "
192 createBackingStore(merged_range, curr_memories,
193 f->isConfReported(), f->isInAddrMap(),
201 bool conf_table_reported,
bool in_addr_map,
bool kvm_map)
204 "Cannot create backing store for interleaved range %s\n",
208 DPRINTF(AddrRanges,
"Creating backing store for range %s with size %d\n",
217 map_flags = MAP_ANON | MAP_PRIVATE;
225 DPRINTF(AddrRanges,
"Sharing backing store as %s at offset %llu\n",
229 panic(
"Shared memory failed");
231 panic(
"Setting size of shared memory failed");
232 map_flags = MAP_SHARED;
238 map_flags |= MAP_NORESERVE;
241 uint8_t* pmem = (uint8_t*) mmap(NULL, range.
size(),
242 PROT_READ | PROT_WRITE,
243 map_flags, shm_fd, map_offset);
245 if (pmem == (uint8_t*) MAP_FAILED) {
247 fatal(
"Could not mmap %d bytes for range %s!\n", range.
size(),
254 conf_table_reported, in_addr_map, kvm_map,
258 for (
const auto&
m : _memories) {
259 DPRINTF(AddrRanges,
"Mapping memory %s to backing store\n",
261 m->setBackingStore(pmem);
269 munmap((
char*)
s.pmem,
s.range.size());
286 if (
r.second->isConfReported()) {
288 if (
r.first.interleaved()) {
292 if (!intlv_ranges.empty() &&
293 !intlv_ranges.back().mergesWith(
r.first)) {
294 ranges.push_back(
AddrRange(intlv_ranges));
295 intlv_ranges.clear();
297 intlv_ranges.push_back(
r.first);
300 ranges.push_back(
r.first);
307 if (!intlv_ranges.empty()) {
308 ranges.push_back(
AddrRange(intlv_ranges));
320 m->second->access(pkt);
329 m->second->functionalAccess(pkt);
341 for (
const auto&
l : locked_addrs) {
342 lal_addr.push_back(
l.addr);
343 lal_cid.push_back(
l.contextId);
354 unsigned int store_id = 0;
368 std::string filename =
369 name() +
".store" + std::to_string(store_id) +
".pmem";
372 DPRINTF(Checkpoint,
"Serializing physical memory %s with size %d\n",
373 filename, range_size);
381 gzFile compressed_mem = gzopen(filepath.c_str(),
"wb");
382 if (compressed_mem == NULL)
383 fatal(
"Can't open physical memory checkpoint file '%s'\n",
386 uint64_t pass_size = 0;
389 for (uint64_t written = 0; written < range.
size();
390 written += pass_size) {
391 pass_size = (uint64_t)INT_MAX < (range.
size() - written) ?
392 (uint64_t)INT_MAX : (range.
size() - written);
394 if (gzwrite(compressed_mem, pmem + written,
395 (
unsigned int) pass_size) != (
int) pass_size) {
396 fatal(
"Write failed on physical memory checkpoint file '%s'\n",
403 if (gzclose(compressed_mem))
404 fatal(
"Close failed on physical memory checkpoint file '%s'\n",
418 for (
size_t i = 0;
i < lal_addr.size(); ++
i) {
419 const auto&
m =
addrMap.contains(lal_addr[
i]);
420 m->second->addLockedAddr(
LockedAddr(lal_addr[
i], lal_cid[
i]));
424 unsigned int nbr_of_stores;
427 for (
unsigned int i = 0;
i < nbr_of_stores; ++
i) {
437 const uint32_t chunk_size = 16384;
439 unsigned int store_id;
442 std::string filename;
444 std::string filepath =
cp.getCptDir() +
"/" + filename;
447 gzFile compressed_mem = gzopen(filepath.c_str(),
"rb");
448 if (compressed_mem == NULL)
449 fatal(
"Can't open physical memory checkpoint file '%s'", filename);
458 DPRINTF(Checkpoint,
"Unserializing physical memory %s with size %d\n",
459 filename, range_size);
461 if (range_size != range.
size())
462 fatal(
"Memory range size has changed! Saw %lld, expected %lld\n",
463 range_size, range.
size());
465 uint64_t curr_size = 0;
467 while (curr_size < range.
size()) {
468 bytes_read = gzread(compressed_mem, pmem, chunk_size);
471 curr_size += bytes_read;
475 if (gzclose(compressed_mem))
476 fatal(
"Close failed on physical memory checkpoint file '%s'\n",
AbstractMemory declaration.
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
AddrRange getAddrRange() const
Get address range to which this packet belongs.
An abstract memory represents a contiguous block of physical memory, with an associated address range...
Locked address class that represents a physical address and a context id.
std::vector< BackingStoreEntry > backingStore
AddrRangeList getConfAddrRanges() const
Get the memory ranges for all memories that are to be reported to the configuration table.
bool isMemAddr(Addr addr) const
Check if a physical address is within a range of a memory that is part of the global address map.
~PhysicalMemory()
Unmap all the backing store we have used.
void unserializeStore(CheckpointIn &cp)
Unserialize a specific backing store, identified by a section.
std::vector< AbstractMemory * > memories
AddrRangeMap< AbstractMemory *, 1 > addrMap
void createBackingStore(AddrRange range, const std::vector< AbstractMemory * > &_memories, bool conf_table_reported, bool in_addr_map, bool kvm_map)
Create the memory region providing the backing store for a given address range that corresponds to a ...
PhysicalMemory(const PhysicalMemory &)
void unserialize(CheckpointIn &cp) override
Unserialize the memories in the system.
const bool mmapUsingNoReserve
const std::string sharedBackstore
void serializeStore(CheckpointOut &cp, unsigned int store_id, AddrRange range, uint8_t *pmem) const
Serialize a specific store.
void functionalAccess(PacketPtr pkt)
Perform an untimed memory read or write without changing anything but the memory itself.
uint64_t sharedBackstoreSize
void access(PacketPtr pkt)
Perform an untimed memory access and update all the state (e.g.
void serialize(CheckpointOut &cp) const override
Serialize all the memories in the system.
bool interleaved() const
Determine if the range is interleaved or not.
std::list< AddrRange > AddrRangeList
Convenience typedef for a collection of address ranges.
Addr size() const
Get the size of the address range.
std::string to_string() const
Get a string representation of the range.
static constexpr T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
#define panic(...)
This implements a cprintf based panic() function.
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
#define fatal(...)
This implements a cprintf based fatal() function.
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
#define UNSERIALIZE_CONTAINER(member)
#define SERIALIZE_CONTAINER(member)
static std::string dir()
Get the current checkout directory name.
Copyright (c) 2024 Arm Limited All rights reserved.
std::ostream CheckpointOut
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
std::string csprintf(const char *format, const Args &...args)
#define UNSERIALIZE_SCALAR(scalar)
#define SERIALIZE_SCALAR(scalar)
const std::string & name()