firecracker-microvm/firecracker · error
GDB requires KVM
Error message
GDB requires KVM
What it means
`expect("GDB requires KVM")` in the AArch64 GDB support (arch/aarch64.rs:68): `vmm.vm.as_kvm()` returns None when the Vmm was not built on a KVM-backed VM, and GDB stub memory access (read_address) has no fallback. Firecracker's GDB implementation is written exclusively against the KVM API (vcpu fds, KVM translations), hence the hard requirement.
Source
Thrown at src/vmm/src/gdb/arch/aarch64.rs:68
get_sys_reg(PC_REG_ID, vcpu_fd)
}
/// Helper to extract a specific number of bits at an offset from a u64
macro_rules! extract_bits_64 {
($value: tt, $offset: tt, $length: tt) => {
($value >> $offset) & (!0u64 >> (64 - $length))
};
}
/// Mask to clear the last 3 bits from the page table entry
const PTE_ADDRESS_MASK: u64 = !0b111u64;
/// Read a u64 value from a guest memory address
fn read_address(vmm: &Vmm, address: u64) -> Result<u64, GdbTargetError> {
let mut buf = [0; 8];
vmm.vm
.as_kvm()
.expect("GDB requires KVM")
.guest_memory()
.read(&mut buf, GuestAddress(address))?;
Ok(u64::from_le_bytes(buf))
}
/// The grainsize used with 4KB paging
const GRAIN_SIZE: usize = 9;
/// Translates a virtual address according to the Vcpu's current address translation mode.
/// Returns the GPA (guest physical address)
///
/// To simplify the implementation we've made some assumptions about the paging setup.
/// Here we just assert firstly paging is setup and these assumptions are correct.
pub fn translate_gva(vcpu_fd: &VcpuFd, gva: u64, vmm: &Vmm) -> Result<u64, GdbTargetError> {
// Check this virtual address is in kernel space
if extract_bits_64!(gva, 55, 1) == 0 {
return Err(GdbTargetError::GvaTranslateError);View on GitHub (pinned to 0a745def42)
Solutions
- Run the microvm with the KVM backend and confirm /dev/kvm exists and is accessible (rw for the user/kvm group)
- Gate the GDB feature: refuse to start the gdb thread unless `vmm.vm.as_kvm().is_some()`
- In code, convert the expect into an error: `vmm.vm.as_kvm().ok_or(GdbTargetError::RequiresKvm)?`
Example fix
// before
vmm.vm
.as_kvm()
.expect("GDB requires KVM")
.guest_memory()
.read(&mut buf, GuestAddress(address))?;
// after
let kvm = vmm.vm.as_kvm().ok_or(GdbTargetError::RequiresKvm)?;
kvm.guest_memory().read(&mut buf, GuestAddress(address))?; Defensive patterns
Strategy: validation
Validate before calling
// Enable the gdb feature only on KVM-backed microvms
if cfg!(feature = "gdb") && vmm.vm.as_kvm().is_none() {
return Err(GdbTargetError::RequiresKvm);
} Type guard
fn is_kvm_backed(vmm: &Vmm) -> bool {
vmm.vm.as_kvm().is_some()
} Prevention
- Check /dev/kvm exists and the user is in the kvm group before launching with --gdb
- Refuse to start the gdb thread unless as_kvm() is Some
- In tests, mock as_kvm() to return a KVM-shaped handle or skip gdb tests on non-KVM hosts
When it happens
Trigger: Enabling the GDB socket (`--gdb`/api config) and issuing a memory read (GDB `x`/`m` packet) on a Vmm whose `vm` wrapper is not a KVM Vm — alternate hypervisor backends, or test harnesses constructing Vmm with a mock/non-KVM vm object.
Common situations: Running the VMM under a non-KVM backend or in unit tests with fake Vm types while the gdb feature is compiled in; platforms where /dev/kvm is unavailable so a degraded backend was selected.
Related errors
- GDB requires KVM
- GDB requires KVM
- Error getting initial gdb event
- Error converting cpu id to Tid
- error unlocking vmm
AI-assisted analysis of firecracker-microvm/firecracker@0a745def42 (2026-08-19).
Data as JSON: /api/errors/8506a4cc004f6007.
Report an issue: GitHub.