Target Duration: ~3.5 to 5 minutes (~650–850 spoken words)
Goal: Deliver an end-to-end architectural narrative covering initialization, execution loops, trap-based communication, address translation, and multi-VM coordination.
To explain the complete architecture of the hypervisor, I divide the project into four main stages: VM and memory initialization, vCPU configuration and execution, VM exits and guest-host communication, and dual-VM scheduling and synchronization.
Everything begins in userspace by opening /dev/kvm and using the Linux KVM API to create and manage virtual machines.
/dev/kvm to obtain the system-level file descriptor and verify the API version using KVM_GET_API_VERSION.ioctl(dev_fd, KVM_CREATE_VM, 0), which yields vm_fd.mmap() with MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE.ioctl(vm_fd, KVM_SET_USER_MEMORY_REGION, ®ion), establishing that Guest Physical Address (GPA) 0x0 corresponds to (uint64_t)vm->mem.ioctl(vm_fd, KVM_CREATE_VCPU, 0) and map the shared struct kvm_run structure using mmap() with MAP_SHARED.(Hook: Deep dive into Topic 01: Core KVM API & Memory Layout)
Before running guest code, the hypervisor configures the initial CPU register state:
KVM_GET_SREGS and KVM_SET_SREGS (setting code segment base to 0, data segment base to 0).KVM_SET_REGS: setting the instruction pointer rip = 0x0000 and flags rflags = 0x0002 (x86 reserved bit).vm->mem.ioctl(vcpu_fd, KVM_RUN, 0).VMLAUNCH/VMRESUME instruction, transitioning the CPU into non-root guest execution mode. The guest executes natively at silicon speed until a privileged instruction forces a VM exit.(Hook: Deep dive into Topic 02: VM Exits & Hypercall Traps)
When a VM exit occurs, control returns from the CPU to KVM, and KVM_RUN returns to userspace. The hypervisor checks vcpu->kvm_run->exit_reason:
KVM_EXIT_HLT: Indicates the guest has completed its workload (hlt instruction). The hypervisor breaks out of the loop and verifies the terminal CPU state via KVM_GET_REGS.KVM_EXIT_IO: Acts as our hypercall communication channel. The guest executes in or out instructions on designated ports:0xE0: Single character console output.0xE1: Integer display output.0xE2: String buffer printing.0xE3: Guest requests configuration data from host.For buffer operations (like string printing), the guest passes a Guest Virtual Address (GVA). Because real mode maps addresses 1:1 (GVA == GPA), and guest physical RAM starts at vm->mem, the hypervisor computes:
$$\text{HVA} = \text{vm}\to\text{mem} + \text{GVA}$$
The hypervisor safely dereferences the host virtual address to access the guest's data buffer.
(Hook: Deep dive into Topic 03: GVA→HVA Address Translation)
In the second phase, I expanded the architecture to run two concurrent VMs: VM1 as a Producer and VM2 as a Consumer.
produce_ptr, then signals via an out instruction on port 0xF0.KVM_EXIT_IO, identifies newly produced items, copies them into VM2's buffer, and updates VM2's produce_ptr.0xF1, and the hypervisor synchronizes the consume_ptr back to VM1.KVM_RUN on the designated vCPU, processes the exit, and moves to the next scheduled VM.(Hook: Deep dive into Topic 04: Dual-VM Circular Buffer and Topic 05: Userspace vCPU Scheduling)
| Dimension | Implementation in Hypervisor |
|---|---|
| Virtualization Model | Type-2 Hypervisor leveraging Linux /dev/kvm hardware-assisted virtualization |
| Execution Mode | x86 Real Mode with identity paging (GVA == GPA) |
| Memory Allocation | 2 MB per VM via anonymous mmap with MAP_NORESERVE |
| Guest-Host Hypercalls | Synchronous x86 in/out port traps handled via KVM_EXIT_IO |
| Address Translation | Direct offset translation: HVA = vm->mem + GVA |
| Concurrency & Sync | Shadow circular ring buffer mediated entirely by userspace hypervisor |