Interviewer: “How did you implement address translation between the guest virtual address and host virtual address?”
Address translation is an important concept in virtualization because the guest and host operate in completely different virtual address spaces.
A pointer inside the guest is a Guest Virtual Address (GVA). If the guest passes a pointer to a buffer or string to the hypervisor, the hypervisor cannot directly dereference that pointer because it belongs to the guest's address space.
When I registered guest memory using KVM_SET_USER_MEMORY_REGION, I mapped guest physical address 0 to the beginning of the userspace memory buffer allocated using mmap.
For the guest configuration used in this buffer-sharing path, the relevant guest virtual addresses map directly to guest physical addresses. Therefore, the hypervisor can obtain the host virtual address by adding the guest address to the base of its allocated memory:
$$\text{HVA} = \text{vm}\to\text{mem} + \text{GVA}$$
For example, when the guest wants the hypervisor to read a string or array:
outl(0xE2, (uint32_t)str_ptr)).KVM_EXIT_IO.kvm_run->io.data_offset.vm->mem to obtain the corresponding host pointer: char *host_str = (char *)vm->mem + guest_addr;
So, for this setup, the translation path is:
$$\mathbf{GVA} \longrightarrow \mathbf{GPA} \longrightarrow \mathbf{HVA}$$
with the GVA-to-GPA step being a direct mapping in our real-mode guest configuration, followed by the GPA-to-HVA mapping provided by my userspace memory layout.
vm->mem).In hardware-assisted virtualization with EPT/NPT, the CPU's memory management unit translates GPA to HPA in hardware across two-dimensional page table walks.
HVA = vm->mem + GVA)?Because:
KVM_SET_USER_MEMORY_REGION maps GPA 0x00000000 directly to userspace_addr = (uint64_t)vm->mem.vm->mem buffer:$$\text{HVA} = \text{vm}\to\text{mem} + \text{GPA} = \text{vm}\to\text{mem} + \text{GVA}$$