Description
This is the result of an excruciatingly long debugging session for #711.
Say that we want to replace arch::RAM_START
in the line 98 of vm.rs:
Line 94 in efc3563
... to let mem = MmapMemory::new(0, memory_size, GuestPhysAddr::new(0x20000), params.thp, params.ksm);
.
So, guest_address
will be equal to 0x20000
. There are many parts of the code which effectively already consider this case, by subtracting self.mem.guest_address
. This is very often the case in vm.rs
.
Debugging this was much more difficult because of the fact that the process "froze". With cargo test gdb
(I could've used gdb) and LLDB running on the side. A previous indicator that something in phys_to_virt
is broken was running the following test with a similar change:
Line 372 in efc3563
This would always return a WrongMemoryError
.
virt_to_phys
invokes a function called mem.host_address(pagetable_l0)
:
Line 208 in efc3563
That function has two conditions (function slightly modified for clarity and because it was easier for me to debug that way):
pub fn host_address(&self, addr: GuestPhysAddr) -> Result<*const u8, MemoryError> {
let addr_lt_guest: bool = addr < self.guest_address;
let addr_ht_guest_plus_memsize: bool = addr.as_u64() as usize > self.guest_address.as_u64() as usize + self.memory_size;
let expression: bool = addr_lt_guest || addr_ht_guest_plus_memsize;
if expression
{
return Err(MemoryError::WrongMemoryError);
}
Ok(
Let's take a look at read_addrs
in uhyve/src/linux/gdb.rs
:
Line 129 in efc3563
This uses a constant: pub const BOOT_PML4: GuestPhysAddr = GuestPhysAddr::new(0x10000);
Line 12 in efc3563
which is passed onto:
Line 134 in efc3563
... as the pagetable_l0
variable, which is in turn passed as the addr
variable. If we choose a guest_address equal to 0x20000
, the first condition will fail.
This error basically pops up everywhere, one way or another, when the guest_address is modified. This was the best and most reproducible case that I could find after spending hours of trying to crack it for #711.