Skip to content

Commit cd1fbf9

Browse files
committed
Update gigapage mappings during remote page faults
1 parent bc5f072 commit cd1fbf9

File tree

3 files changed

+51
-20
lines changed

3 files changed

+51
-20
lines changed

lib/tinykvm/machine.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ struct Machine
320320
void smp_vcpu_broadcast(std::function<void(vCPU&)>);
321321
address_t remote_activate_now();
322322
void remote_pfault_permanent_ipre(uint64_t return_stack, uint64_t return_address);
323+
void remote_update_gigapage_mappings(Machine& other);
323324
/* Prepare for resume with a pagetable reload */
324325
void prepare_vmresume(address_t fsbase = 0, bool reload_pagetables = true);
325326

lib/tinykvm/remote.cpp

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,33 @@ void Machine::permanent_remote_connect(Machine& other)
3030
other.remote_connect(*this, true);
3131
}
3232

33+
void Machine::remote_update_gigapage_mappings(Machine& remote)
34+
{
35+
auto& caller = *this;
36+
const auto remote_vmem = remote.main_memory().vmem();
37+
static constexpr uint64_t PDE64_ADDR_MASK = ~0x8000000000000FFF;
38+
auto* main_pml4 = caller.main_memory().page_at(caller.main_memory().page_tables);
39+
auto* main_pdpt = caller.main_memory().page_at(main_pml4[0] & PDE64_ADDR_MASK);
40+
41+
auto* remote_pml4 = remote.main_memory().page_at(remote.main_memory().page_tables);
42+
auto* remote_pdpt = remote.main_memory().page_at(remote_pml4[0] & PDE64_ADDR_MASK);
43+
44+
// Gigabyte starting index and end index (rounded up)
45+
const auto begin = remote_vmem.physbase >> 30;
46+
const auto end = (remote_vmem.remote_end + 0x3FFFFFFF) >> 30;
47+
48+
for (size_t i = begin; i < end; i++)
49+
{
50+
if (main_pdpt[i] != remote_pdpt[i]) {
51+
if constexpr (VERBOSE_REMOTE) {
52+
fprintf(stderr, "Updating remote PDPT entry %zu from 0x%lX to 0x%lX\n",
53+
i, main_pdpt[i], remote_pdpt[i]);
54+
}
55+
main_pdpt[i] = remote_pdpt[i];
56+
}
57+
}
58+
59+
}
3360
void Machine::remote_connect(Machine& remote, bool connect_now)
3461
{
3562
const auto remote_vmem = remote.main_memory().vmem();
@@ -50,25 +77,7 @@ void Machine::remote_connect(Machine& remote, bool connect_now)
5077
if (connect_now)
5178
{
5279
// Copy gigabyte entries covered by remote memory into these page tables
53-
static constexpr uint64_t PDE64_ADDR_MASK = ~0x8000000000000FFF;
54-
auto* main_pml4 = this->main_memory().page_at(this->main_memory().page_tables);
55-
auto* main_pdpt = this->main_memory().page_at(main_pml4[0] & PDE64_ADDR_MASK);
56-
57-
auto* remote_pml4 = remote.main_memory().page_at(remote.main_memory().page_tables);
58-
auto* remote_pdpt = remote.main_memory().page_at(remote_pml4[0] & PDE64_ADDR_MASK);
59-
60-
// Gigabyte starting index and end index (rounded up)
61-
const auto begin = remote_vmem.physbase >> 30;
62-
const auto end = (remote_vmem.remote_end + 0x3FFFFFFF) >> 30;
63-
if (UNLIKELY(begin >= 512 || end > 512 || begin >= end))
64-
throw MachineException("Remote memory produced invalid indexes (>512GB?)");
65-
66-
// Install gigabyte entries from remote VM into this VM
67-
// The VM and page tables technically support 2MB region alignments.
68-
for (size_t i = begin; i < end; i++)
69-
{
70-
main_pdpt[i] = remote_pdpt[i]; // GB-page
71-
}
80+
this->remote_update_gigapage_mappings(remote);
7281
}
7382

7483
// Finalize
@@ -118,7 +127,7 @@ void Machine::ipre_remote_resume_now(bool save_all, std::function<void(Machine&)
118127

119128
const auto remote_cow_counter = remote().memory.cow_written_pages.size();
120129
bool do_prepare = false;
121-
if (this->m_remote_cow_counter != remote_cow_counter) {
130+
if (true || this->m_remote_cow_counter != remote_cow_counter) {
122131
this->m_remote_cow_counter = remote_cow_counter;
123132
// New working memory pages have been created in the remote,
124133
// so we need to make sure we see the latest changes.

lib/tinykvm/vcpu_run.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,11 @@ long vCPU::run_once()
332332
WritablePageOptions zero_opts;
333333
zero_opts.zeroes = false;
334334
auto result = writable_page_at(memory, addr, PDE64_USER | PDE64_RW, zero_opts);
335+
if (machine().has_remote() && machine().remote().is_foreign_address(addr) && machine().remote().is_remote_connected()) {
336+
// If a new gigapage was created, we need to update the
337+
// PML4[0] 512GB page table entry in the caller VM too
338+
machine().remote().remote_update_gigapage_mappings(machine());
339+
}
335340
if constexpr (false) {
336341
char buffer[256];
337342
PRINTER(machine().m_printer, buffer,
@@ -341,6 +346,22 @@ long vCPU::run_once()
341346
PRINTER(machine().m_printer, buffer,
342347
" Our bank arena: begin=0x%lX\n",
343348
memory.banks.arena_begin());
349+
static uint64_t last_reported = 0;
350+
static int count = 0;
351+
if (last_reported == addr) {
352+
count++;
353+
PRINTER(machine().m_printer, buffer,
354+
" Page fault repeats %d times, address=0x%lX\n",
355+
count, last_reported);
356+
if (count > 2) {
357+
//this->handle_exception(intr);
358+
print_pagetables(memory);
359+
Machine::machine_exception("Too many page faults", intr);
360+
}
361+
} else {
362+
last_reported = addr;
363+
count = 0;
364+
}
344365
}
345366
return KVM_EXIT_IO;
346367
}

0 commit comments

Comments
 (0)