{"record":{"id":"8506a4cc004f6007","repo":"firecracker-microvm/firecracker","slug":"gdb-requires-kvm","errorCode":null,"errorMessage":"GDB requires KVM","messagePattern":"GDB requires KVM","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/vmm/src/gdb/arch/aarch64.rs","lineNumber":68,"sourceCode":"    get_sys_reg(PC_REG_ID, vcpu_fd)\n}\n\n/// Helper to extract a specific number of bits at an offset from a u64\nmacro_rules! extract_bits_64 {\n    ($value: tt, $offset: tt, $length: tt) => {\n        ($value >> $offset) & (!0u64 >> (64 - $length))\n    };\n}\n\n/// Mask to clear the last 3 bits from the page table entry\nconst PTE_ADDRESS_MASK: u64 = !0b111u64;\n\n/// Read a u64 value from a guest memory address\nfn read_address(vmm: &Vmm, address: u64) -> Result<u64, GdbTargetError> {\n    let mut buf = [0; 8];\n    vmm.vm\n        .as_kvm()\n        .expect(\"GDB requires KVM\")\n        .guest_memory()\n        .read(&mut buf, GuestAddress(address))?;\n\n    Ok(u64::from_le_bytes(buf))\n}\n\n/// The grainsize used with 4KB paging\nconst GRAIN_SIZE: usize = 9;\n\n/// Translates a virtual address according to the Vcpu's current address translation mode.\n/// Returns the GPA (guest physical address)\n///\n/// To simplify the implementation we've made some assumptions about the paging setup.\n/// Here we just assert firstly paging is setup and these assumptions are correct.\npub fn translate_gva(vcpu_fd: &VcpuFd, gva: u64, vmm: &Vmm) -> Result<u64, GdbTargetError> {\n    // Check this virtual address is in kernel space\n    if extract_bits_64!(gva, 55, 1) == 0 {\n        return Err(GdbTargetError::GvaTranslateError);","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/firecracker-microvm/firecracker/blob/0a745def42ddf4cc2a744d79a08a27ff50b5d27a/src/vmm/src/gdb/arch/aarch64.rs#L50-L86","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","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)?`"],"exampleFix":"// before\nvmm.vm\n    .as_kvm()\n    .expect(\"GDB requires KVM\")\n    .guest_memory()\n    .read(&mut buf, GuestAddress(address))?;\n\n// after\nlet kvm = vmm.vm.as_kvm().ok_or(GdbTargetError::RequiresKvm)?;\nkvm.guest_memory().read(&mut buf, GuestAddress(address))?;","handlingStrategy":"validation","validationCode":"// Enable the gdb feature only on KVM-backed microvms\nif cfg!(feature = \"gdb\") && vmm.vm.as_kvm().is_none() {\n    return Err(GdbTargetError::RequiresKvm);\n}","typeGuard":"fn is_kvm_backed(vmm: &Vmm) -> bool {\n    vmm.vm.as_kvm().is_some()\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["rust","panic","gdb","kvm","aarch64","firecracker"],"backgroundTag":"kvm-backend-unavailable","analyzedSha":"0a745def42ddf4cc2a744d79a08a27ff50b5d27a","analyzedAt":"2026-08-19T05:27:02.517Z","contentChangedAt":"2026-08-19T05:27:02.517Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}