Skip to content

Commit 9fdf2be

Browse files
authored
Merge pull request #58 from lrowe/fix-accessed-pages
Open existing snapshot file readonly and include size of accessed pages
2 parents 6c7e073 + 59c0a12 commit 9fdf2be

File tree

5 files changed

+21
-15
lines changed

5 files changed

+21
-15
lines changed

lib/tinykvm/amd64/paging.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -531,13 +531,13 @@ void foreach_page_makecow(vMemory& mem, uint64_t kernel_end, uint64_t shared_mem
531531
entry &= ~PDE64_ACCESSED;
532532
});
533533
}
534-
std::vector<uint64_t> get_accessed_pages(const vMemory& memory)
534+
std::vector<std::pair<uint64_t, uint64_t>> get_accessed_pages(const vMemory& memory)
535535
{
536-
std::vector<uint64_t> accessed_pages;
536+
std::vector<std::pair<uint64_t, uint64_t>> accessed_pages;
537537
foreach_page(memory,
538-
[&accessed_pages] (uint64_t addr, uint64_t& entry, size_t /*size*/) {
539-
if ((entry & (PDE64_ACCESSED | PDE64_PRESENT)) == (PDE64_ACCESSED | PDE64_PRESENT)) {
540-
accessed_pages.push_back(addr & PDE64_ADDR_MASK);
538+
[&accessed_pages] (uint64_t addr, uint64_t& entry, size_t size) {
539+
if ((entry & (PDE64_PS | PDE64_ACCESSED | PDE64_PRESENT)) == (PDE64_PS | PDE64_ACCESSED | PDE64_PRESENT)) {
540+
accessed_pages.push_back({addr & PDE64_ADDR_MASK, size});
541541
}
542542
}, false);
543543
return accessed_pages;

lib/tinykvm/amd64/paging.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ using foreach_page_t = std::function<void(uint64_t, uint64_t&, size_t)>;
1414
extern void foreach_page(vMemory&, foreach_page_t callback, bool skip_oob_addresses = true);
1515
extern void foreach_page(const vMemory&, foreach_page_t callback, bool skip_oob_addresses = true);
1616
extern void foreach_page_makecow(vMemory&, uint64_t kernel_end, uint64_t shared_memory_boundary);
17-
extern std::vector<uint64_t> get_accessed_pages(const vMemory& memory);
17+
extern std::vector<std::pair<uint64_t, uint64_t>> get_accessed_pages(const vMemory& memory);
1818

1919
extern void page_at(vMemory&, uint64_t addr, foreach_page_t, bool ignore_missing = false);
2020
struct WritablePage {

lib/tinykvm/machine.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ struct Machine
245245
void set_main_memory_writable(bool v) { memory.main_memory_writes = v; }
246246
bool is_forked() const noexcept { return m_forked; }
247247
bool uses_cow_memory() const noexcept { return m_forked || m_prepped; }
248-
std::vector<uint64_t> get_accessed_pages() const;
248+
std::vector<std::pair<uint64_t, uint64_t>> get_accessed_pages() const;
249249

250250
/* Remote VM through address space merging */
251251
void remote_connect(Machine& other, bool connect_now = false);
@@ -299,7 +299,7 @@ struct Machine
299299
/* Store non-memory VM state to the already existing cold
300300
start state area in memory. Any failure will throw an
301301
exception. The memory must have been pre-allocated. */
302-
void save_snapshot_state_now(const std::vector<uint64_t>& populate_pages = {}) const;
302+
void save_snapshot_state_now(const std::vector<std::pair<uint64_t, uint64_t>>& populate_pages = {}) const;
303303
/* Check if the VM was loaded from a snapshot state. */
304304
bool has_snapshot_state() const noexcept { return m_loaded_from_snapshot; }
305305
/* Get pointer to user area in snapshot state memory, or nullptr

lib/tinykvm/machine_state.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ bool Machine::load_snapshot_state()
208208
}
209209
return true;
210210
}
211-
void Machine::save_snapshot_state_now(const std::vector<uint64_t>& populate_pages) const
211+
void Machine::save_snapshot_state_now(const std::vector<std::pair<uint64_t, uint64_t>>& populate_pages) const
212212
{
213213
if (this->is_forked()) {
214214
throw std::runtime_error("Cannot save snapshot state of a forked VM");
@@ -242,12 +242,12 @@ void Machine::save_snapshot_state_now(const std::vector<uint64_t>& populate_page
242242
if (!populate_pages.empty()) {
243243
uint64_t current_begin = 0;
244244
uint64_t current_end = 0;
245-
for (uint64_t page_addr : populate_pages) {
245+
for (const auto& [page_addr, size] : populate_pages) {
246246
if (page_addr >= MemoryBanks::ARENA_BASE_ADDRESS || page_addr < kernel_end_address())
247247
continue;
248248
// Merge contiguous ranges
249249
if (current_end == page_addr) {
250-
current_end += vMemory::PageSize();
250+
current_end += size;
251251
continue;
252252
}
253253
// Store previous range
@@ -259,7 +259,7 @@ void Machine::save_snapshot_state_now(const std::vector<uint64_t>& populate_page
259259
}
260260
// Start new range
261261
current_begin = page_addr;
262-
current_end = page_addr;
262+
current_end = page_addr + size;
263263
}
264264
// Store last range
265265
if (current_end != current_begin) {

lib/tinykvm/memory.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -397,9 +397,15 @@ vMemory::AllocationResult
397397
if (filename.empty()) {
398398
throw std::runtime_error("No VM snapshot file specified");
399399
}
400-
const int fd = open(filename.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600);
400+
int fd = open(filename.c_str(), O_RDONLY | O_CLOEXEC);
401401
if (fd < 0) {
402-
throw std::runtime_error("Failed to open VM snapshot file: " + filename);
402+
if (errno != ENOENT) {
403+
throw std::runtime_error("Failed to open VM snapshot file: " + filename);
404+
}
405+
fd = open(filename.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600);
406+
if (fd < 0) {
407+
throw std::runtime_error("Failed to create VM snapshot file: " + filename);
408+
}
403409
}
404410
struct stat st;
405411
if (fstat(fd, &st) != 0) {
@@ -512,7 +518,7 @@ char* vMemory::get_userpage_at(uint64_t addr) const
512518
#endif
513519
}
514520

515-
std::vector<uint64_t> Machine::get_accessed_pages() const
521+
std::vector<std::pair<uint64_t, uint64_t>> Machine::get_accessed_pages() const
516522
{
517523
return tinykvm::get_accessed_pages(this->main_memory());
518524
}

0 commit comments

Comments
 (0)