This project implements a minimal userspace hypervisor using the Linux KVM interface. It demonstrates how a userspace process can create a virtual machine, map guest memory, run a vCPU, and handle VM exits using /dev/kvm.
The guest communicates with the host via a simple MMIO-based console interface, allowing text output and basic animation without relying on complex device models. The design is intentionally minimal to make KVM internals, VM execution flow, and guest–host interaction easy to understand.
This project is intended for learning, experimentation, and low-level systems or security research.
The guest uses a simple MMIO-based console interface, where fixed guest physical addresses are reserved for host-emulated devices. Writes to these addresses (e.g., console command, data, and refresh ports) trigger KVM_EXIT_MMIO, allowing the userspace hypervisor to intercept and emulate console behavior without PCI, interrupts, or complex device models.
The guest runs in 64-bit long mode with a manually constructed 4-level x86-64 paging hierarchy (PML4 → PDPT → PD → PT). Page tables are built in guest memory starting at a fixed physical address (0x6000), and virtual memory is mapped to guest physical memory using 4 KB pages with present, read/write, and user-accessible flags. This flat, explicit paging setup keeps memory translation simple while enabling full long-mode execution.
bits 64
org 0x0000
%define PORT_REFRESH 0x16020
%define PORT_SERIAL_DATA 0x16021
%define PORT_SERIAL_CMD 0x16022
%define CONSOLE_H 25
%define CENTER_Y (CONSOLE_H / 2)
%define MAX_X 80 -10
_start:
xor rcx, rcx ; horizontal offset
loop:
; Reset cursor
mov rdx, PORT_SERIAL_CMD
mov byte [rdx], 0
; Clear screen
mov byte [rdx], 1
mov rdx, PORT_SERIAL_DATA
mov rbx, CENTER_Y
.y_loop:
test rbx, rbx
jz .x_loop
mov byte [rdx], 10
dec rbx
jmp .y_loop
.x_loop:
mov rbx, rcx
.x_space:
test rbx, rbx
jz .print
mov byte [rdx], ' '
dec rbx
jmp .x_space
.print:
mov byte [rdx], 'H'
mov byte [rdx], 'E'
mov byte [rdx], 'L'
mov byte [rdx], 'L'
mov byte [rdx], 'O'
mov byte [rdx], ' '
mov byte [rdx], 'K'
mov byte [rdx], 'V'
mov byte [rdx], 'M'
mov byte [rdx], '!'
; Refresh
mov rdx, PORT_REFRESH
mov byte [rdx], 1
; Delay
mov rax, 0x200000
.delay:
dec rax
jnz .delay
; Linear wrap
inc rcx
cmp rcx, MAX_X
jl loop
xor rcx, rcx
jmp loop