Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions lib/tinykvm/amd64/paging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -531,13 +531,13 @@ void foreach_page_makecow(vMemory& mem, uint64_t kernel_end, uint64_t shared_mem
entry &= ~PDE64_ACCESSED;
});
}
std::vector<uint64_t> get_accessed_pages(const vMemory& memory)
std::vector<std::pair<uint64_t, uint64_t>> get_accessed_pages(const vMemory& memory)
{
std::vector<uint64_t> accessed_pages;
std::vector<std::pair<uint64_t, uint64_t>> accessed_pages;
foreach_page(memory,
[&accessed_pages] (uint64_t addr, uint64_t& entry, size_t /*size*/) {
if ((entry & (PDE64_ACCESSED | PDE64_PRESENT)) == (PDE64_ACCESSED | PDE64_PRESENT)) {
accessed_pages.push_back(addr & PDE64_ADDR_MASK);
[&accessed_pages] (uint64_t addr, uint64_t& entry, size_t size) {
if ((entry & (PDE64_PS | PDE64_ACCESSED | PDE64_PRESENT)) == (PDE64_PS | PDE64_ACCESSED | PDE64_PRESENT)) {
accessed_pages.push_back({addr & PDE64_ADDR_MASK, size});
}
}, false);
return accessed_pages;
Expand Down
2 changes: 1 addition & 1 deletion lib/tinykvm/amd64/paging.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ using foreach_page_t = std::function<void(uint64_t, uint64_t&, size_t)>;
extern void foreach_page(vMemory&, foreach_page_t callback, bool skip_oob_addresses = true);
extern void foreach_page(const vMemory&, foreach_page_t callback, bool skip_oob_addresses = true);
extern void foreach_page_makecow(vMemory&, uint64_t kernel_end, uint64_t shared_memory_boundary);
extern std::vector<uint64_t> get_accessed_pages(const vMemory& memory);
extern std::vector<std::pair<uint64_t, uint64_t>> get_accessed_pages(const vMemory& memory);

extern void page_at(vMemory&, uint64_t addr, foreach_page_t, bool ignore_missing = false);
struct WritablePage {
Expand Down
4 changes: 2 additions & 2 deletions lib/tinykvm/machine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ struct Machine
void set_main_memory_writable(bool v) { memory.main_memory_writes = v; }
bool is_forked() const noexcept { return m_forked; }
bool uses_cow_memory() const noexcept { return m_forked || m_prepped; }
std::vector<uint64_t> get_accessed_pages() const;
std::vector<std::pair<uint64_t, uint64_t>> get_accessed_pages() const;

/* Remote VM through address space merging */
void remote_connect(Machine& other, bool connect_now = false);
Expand Down Expand Up @@ -299,7 +299,7 @@ struct Machine
/* Store non-memory VM state to the already existing cold
start state area in memory. Any failure will throw an
exception. The memory must have been pre-allocated. */
void save_snapshot_state_now(const std::vector<uint64_t>& populate_pages = {}) const;
void save_snapshot_state_now(const std::vector<std::pair<uint64_t, uint64_t>>& populate_pages = {}) const;
/* Check if the VM was loaded from a snapshot state. */
bool has_snapshot_state() const noexcept { return m_loaded_from_snapshot; }
/* Get pointer to user area in snapshot state memory, or nullptr
Expand Down
8 changes: 4 additions & 4 deletions lib/tinykvm/machine_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ bool Machine::load_snapshot_state()
}
return true;
}
void Machine::save_snapshot_state_now(const std::vector<uint64_t>& populate_pages) const
void Machine::save_snapshot_state_now(const std::vector<std::pair<uint64_t, uint64_t>>& populate_pages) const
{
if (this->is_forked()) {
throw std::runtime_error("Cannot save snapshot state of a forked VM");
Expand Down Expand Up @@ -242,12 +242,12 @@ void Machine::save_snapshot_state_now(const std::vector<uint64_t>& populate_page
if (!populate_pages.empty()) {
uint64_t current_begin = 0;
uint64_t current_end = 0;
for (uint64_t page_addr : populate_pages) {
for (const auto& [page_addr, size] : populate_pages) {
if (page_addr >= MemoryBanks::ARENA_BASE_ADDRESS || page_addr < kernel_end_address())
continue;
// Merge contiguous ranges
if (current_end == page_addr) {
current_end += vMemory::PageSize();
current_end += size;
continue;
}
// Store previous range
Expand All @@ -259,7 +259,7 @@ void Machine::save_snapshot_state_now(const std::vector<uint64_t>& populate_page
}
// Start new range
current_begin = page_addr;
current_end = page_addr;
current_end = page_addr + size;
}
// Store last range
if (current_end != current_begin) {
Expand Down
12 changes: 9 additions & 3 deletions lib/tinykvm/memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,9 +397,15 @@ vMemory::AllocationResult
if (filename.empty()) {
throw std::runtime_error("No VM snapshot file specified");
}
const int fd = open(filename.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600);
int fd = open(filename.c_str(), O_RDONLY | O_CLOEXEC);
if (fd < 0) {
throw std::runtime_error("Failed to open VM snapshot file: " + filename);
if (errno != ENOENT) {
throw std::runtime_error("Failed to open VM snapshot file: " + filename);
}
fd = open(filename.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600);
if (fd < 0) {
throw std::runtime_error("Failed to create VM snapshot file: " + filename);
}
}
struct stat st;
if (fstat(fd, &st) != 0) {
Expand Down Expand Up @@ -512,7 +518,7 @@ char* vMemory::get_userpage_at(uint64_t addr) const
#endif
}

std::vector<uint64_t> Machine::get_accessed_pages() const
std::vector<std::pair<uint64_t, uint64_t>> Machine::get_accessed_pages() const
{
return tinykvm::get_accessed_pages(this->main_memory());
}
Expand Down