{"record":{"id":"1dea175889a7e39b","repo":"firecracker-microvm/firecracker","slug":"gdb-requires-kvm-1dea17","errorCode":null,"errorMessage":"GDB requires KVM","messagePattern":"GDB requires KVM","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/vmm/src/gdb/target.rs","lineNumber":172,"sourceCode":"/// the Tid required by GDB\npub fn vcpuid_to_tid(cpu_id: usize) -> Result<Tid, GdbTargetError> {\n    Tid::new(get_raw_tid(cpu_id)).ok_or(GdbTargetError::TidConversionError)\n}\n\n/// Converts the inernal index of a Vcpu to\n/// the 1 indexed value for GDB\npub fn get_raw_tid(cpu_id: usize) -> usize {\n    cpu_id + 1\n}\n\nimpl FirecrackerTarget {\n    /// Creates a new Target for GDB stub. This is used as the layer between GDB and the VMM it\n    /// will handle requests from GDB and perform the appropriate actions, while also updating GDB\n    /// with the state of the VMM / Vcpu's as we hit debug events\n    pub fn new(vmm: Arc<Mutex<Vmm>>, gdb_event: Receiver<usize>, entry_addr: GuestAddress) -> Self {\n        let vcpus_count = {\n            let vmm = vmm.lock().unwrap();\n            let kvm_vm = vmm.vm.as_kvm().expect(\"GDB requires KVM\");\n            kvm_vm.vcpus_handles().len()\n        };\n        let mut vcpu_state = vec![VcpuState::default(); vcpus_count];\n        // By default vcpu 1 will be paused at the entry point\n        vcpu_state[0].paused = true;\n\n        Self {\n            vmm,\n            entry_addr,\n            gdb_event,\n            // We only support 4 hw breakpoints on x86 this will need to be configurable on arm\n            hw_breakpoints: Default::default(),\n            sw_breakpoints: HashMap::new(),\n            vcpu_state,\n\n            paused_vcpu: Tid::new(1),\n            scheduler_locking: false,\n        }","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/firecracker-microvm/firecracker/blob/0a745def42ddf4cc2a744d79a08a27ff50b5d27a/src/vmm/src/gdb/target.rs#L154-L190","documentation":"`expect(\"GDB requires KVM\")` in `FirecrackerTarget::new` (target.rs:172): building the GDB target locks the Vmm, calls `vmm.vm.as_kvm()` and counts vcpus via `kvm_vm.vcpus_handles().len()` to size `vcpu_state`. A non-KVM VM wrapper yields None and construction panics.","triggerScenarios":"Constructing `FirecrackerTarget` (i.e. any gdb session start) when the Vmm's vm is not a KVM vm — the vcpu-handle enumeration this code depends on exists only on the KVM implementation.","commonSituations":"GDB feature turned on for a microvm launched without the KVM backend; tests instantiating FirecrackerTarget with a stubbed Vmm/Vm; running on hosts without /dev/kvm where the VM fell back to a non-KVM path.","solutions":["Before creating the target, validate the backend: `if vmm.vm.as_kvm().is_none() { return Err(GdbTargetError::RequiresKvm) }`","Run the microvm with KVM (check /dev/kvm permissions, kvm group membership)","Disable the gdb option in deployments that intentionally use a non-KVM backend"],"exampleFix":"// before\nlet kvm_vm = vmm.vm.as_kvm().expect(\"GDB requires KVM\");\nlet vcpus_count = kvm_vm.vcpus_handles().len();\n\n// after\nlet vcpus_count = vmm\n    .vm\n    .as_kvm()\n    .ok_or(GdbTargetError::RequiresKvm)?\n    .vcpus_handles()\n    .len();","handlingStrategy":"validation","validationCode":"if vmm.lock().unwrap().vm.as_kvm().is_none() {\n    return Err(GdbTargetError::RequiresKvm);\n}\nlet target = FirecrackerTarget::new(vmm.clone(), rx, entry_addr);","typeGuard":"fn can_build_gdb_target(vmm: &Arc<Mutex<Vmm>>) -> bool {\n    vmm.lock().map(|v| v.vm.as_kvm().is_some()).unwrap_or(false)\n}","tryCatchPattern":null,"preventionTips":["Construct the target only after the VM is confirmed KVM-backed","Pass vcpus_count explicitly from a validated source instead of re-deriving it inside new()","Unit-test FirecrackerTarget::new against a KVM-enabled test VM in CI"],"tags":["rust","panic","gdb","kvm","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"}