From e9ff3de7c5ead21419e1bbae2bfcc5b7b1b27f9e Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Tue, 22 Oct 2024 10:22:11 +0000 Subject: [PATCH 1/2] feat(gdb): Support config over api Allow a GDB debugging session to be started over API Signed-off-by: Jack Thomson --- docs/gdb-debugging.md | 25 +++++++++++++++++------- src/firecracker/swagger/firecracker.yaml | 3 +++ src/vmm/src/builder.rs | 4 ++-- src/vmm/src/persist.rs | 2 ++ src/vmm/src/resources.rs | 12 ------------ src/vmm/src/vmm_config/machine_config.rs | 19 ++++++++++++++++++ 6 files changed, 44 insertions(+), 21 deletions(-) diff --git a/docs/gdb-debugging.md b/docs/gdb-debugging.md index 74832665c9d..f230dbb0cc6 100644 --- a/docs/gdb-debugging.md +++ b/docs/gdb-debugging.md @@ -6,8 +6,6 @@ Firecracker supports debugging the guest kernel via GDB remote serial protocol. This allows us to connect GDB to the firecracker process and step through debug the guest kernel. -The GDB feature requires Firecracker to be booted with a config file. - ## Prerequisites Firstly, to enable GDB debugging we need to compile Firecracker with the `gdb` @@ -25,22 +23,35 @@ debugging to work. The key config options to enable are: ``` CONFIG_FRAME_POINTER=y -CONFIG_KGDB=y -CONFIG_KGDB_SERIAL_CONSOLE=y CONFIG_DEBUG_INFO=y ``` -For GDB debugging the `gdb-socket` option should be set in your config file. In -this example we set it to `/tmp/gdb.socket` +For GDB debugging the `gdb_socket_path` option under `machine-config` should be +set. When using the API the socket address must be set before instance start. + +In this example we set the address to `/tmp/gdb.socket` in the config file: ``` { ... - "gdb-socket": "/tmp/gdb.socket" + "machine-config": { + ... + "gdb_socket_path": "/tmp/gdb.socket" + ... + } ... } ``` +Using the API the socket address can be configured before boot like so: + +``` +sudo curl -X PATCH --unix-socket "${API_SOCKET}" \ + --data "{ + \"gdb_socket_path\": \"/tmp/gdb.socket\" + }" "http://localhost/machine-config" +``` + ## Starting Firecracker with GDB With all the prerequisites in place you can now start firecracker ready to diff --git a/src/firecracker/swagger/firecracker.yaml b/src/firecracker/swagger/firecracker.yaml index 6da2b8777f4..dadabf5039f 100644 --- a/src/firecracker/swagger/firecracker.yaml +++ b/src/firecracker/swagger/firecracker.yaml @@ -1028,6 +1028,9 @@ definitions: properties: cpu_template: $ref: "#/definitions/CpuTemplate" + gdb_socket_path: + type: string + description: Path to the GDB socket. Requires the gdb feature to be enabled. smt: type: boolean description: Flag for enabling/disabling simultaneous multithreading. Can be enabled only on x86. diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs index fee6be35b4f..1f52fdad063 100644 --- a/src/vmm/src/builder.rs +++ b/src/vmm/src/builder.rs @@ -346,8 +346,8 @@ pub fn build_microvm_for_boot( let vmm = Arc::new(Mutex::new(vmm)); #[cfg(feature = "gdb")] - if let Some(gdb_socket_addr) = &vm_resources.gdb_socket_addr { - gdb::gdb_thread(vmm.clone(), vcpu_fds, gdb_rx, entry_addr, gdb_socket_addr) + if let Some(gdb_socket_path) = &vm_resources.vm_config.gdb_socket_path { + gdb::gdb_thread(vmm.clone(), vcpu_fds, gdb_rx, entry_addr, gdb_socket_path) .map_err(GdbServer)?; } else { debug!("No GDB socket provided not starting gdb server."); diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs index 6410e4d6c9b..560d9d7c6b7 100644 --- a/src/vmm/src/persist.rs +++ b/src/vmm/src/persist.rs @@ -433,6 +433,8 @@ pub fn restore_from_snapshot( cpu_template: Some(microvm_state.vm_info.cpu_template), track_dirty_pages: Some(track_dirty_pages), huge_pages: Some(microvm_state.vm_info.huge_pages), + #[cfg(feature = "gdb")] + gdb_socket_path: None, }) .map_err(BuildMicrovmFromSnapshotError::VmUpdateConfig)?; diff --git a/src/vmm/src/resources.rs b/src/vmm/src/resources.rs index 923225c6a8a..a4d15641975 100644 --- a/src/vmm/src/resources.rs +++ b/src/vmm/src/resources.rs @@ -86,9 +86,6 @@ pub struct VmmConfig { vsock_device: Option, #[serde(rename = "entropy")] entropy_device: Option, - #[cfg(feature = "gdb")] - #[serde(rename = "gdb-socket")] - gdb_socket_addr: Option, } /// A data structure that encapsulates the device configurations @@ -117,9 +114,6 @@ pub struct VmResources { pub mmds_size_limit: usize, /// Whether or not to load boot timer device. pub boot_timer: bool, - #[cfg(feature = "gdb")] - /// Configures the location of the GDB socket - pub gdb_socket_addr: Option, } impl VmResources { @@ -142,8 +136,6 @@ impl VmResources { let mut resources: Self = Self { mmds_size_limit, - #[cfg(feature = "gdb")] - gdb_socket_addr: vmm_config.gdb_socket_addr, ..Default::default() }; if let Some(machine_config) = vmm_config.machine_config { @@ -529,8 +521,6 @@ impl From<&VmResources> for VmmConfig { net_devices: resources.net_builder.configs(), vsock_device: resources.vsock.config(), entropy_device: resources.entropy.config(), - #[cfg(feature = "gdb")] - gdb_socket_addr: resources.gdb_socket_addr.clone(), } } } @@ -640,8 +630,6 @@ mod tests { boot_timer: false, mmds_size_limit: HTTP_MAX_PAYLOAD_SIZE, entropy: Default::default(), - #[cfg(feature = "gdb")] - gdb_socket_addr: None, } } diff --git a/src/vmm/src/vmm_config/machine_config.rs b/src/vmm/src/vmm_config/machine_config.rs index 3c657b9133c..8eee91c88be 100644 --- a/src/vmm/src/vmm_config/machine_config.rs +++ b/src/vmm/src/vmm_config/machine_config.rs @@ -111,6 +111,10 @@ pub struct MachineConfig { /// Configures what page size Firecracker should use to back guest memory. #[serde(default)] pub huge_pages: HugePageConfig, + /// GDB socket address. + #[cfg(feature = "gdb")] + #[serde(default, skip_serializing_if = "Option::is_none")] + pub gdb_socket_path: Option, } impl Default for MachineConfig { @@ -146,6 +150,10 @@ pub struct MachineConfigUpdate { /// Configures what page size Firecracker should use to back guest memory. #[serde(default, skip_serializing_if = "Option::is_none")] pub huge_pages: Option, + /// GDB socket address. + #[cfg(feature = "gdb")] + #[serde(default, skip_serializing_if = "Option::is_none")] + pub gdb_socket_path: Option, } impl MachineConfigUpdate { @@ -166,6 +174,8 @@ impl From for MachineConfigUpdate { cpu_template: cfg.cpu_template, track_dirty_pages: Some(cfg.track_dirty_pages), huge_pages: Some(cfg.huge_pages), + #[cfg(feature = "gdb")] + gdb_socket_path: cfg.gdb_socket_path, } } } @@ -185,6 +195,9 @@ pub struct VmConfig { pub track_dirty_pages: bool, /// Configures what page size Firecracker should use to back guest memory. pub huge_pages: HugePageConfig, + /// GDB socket address. + #[cfg(feature = "gdb")] + pub gdb_socket_path: Option, } impl VmConfig { @@ -238,6 +251,8 @@ impl VmConfig { cpu_template, track_dirty_pages: update.track_dirty_pages.unwrap_or(self.track_dirty_pages), huge_pages: page_config, + #[cfg(feature = "gdb")] + gdb_socket_path: update.gdb_socket_path.clone(), }) } } @@ -251,6 +266,8 @@ impl Default for VmConfig { cpu_template: None, track_dirty_pages: false, huge_pages: HugePageConfig::None, + #[cfg(feature = "gdb")] + gdb_socket_path: None, } } } @@ -264,6 +281,8 @@ impl From<&VmConfig> for MachineConfig { cpu_template: value.cpu_template.as_ref().map(|template| template.into()), track_dirty_pages: value.track_dirty_pages, huge_pages: value.huge_pages, + #[cfg(feature = "gdb")] + gdb_socket_path: value.gdb_socket_path.clone(), } } } From 08ff34e8c2ecebf2b0c37222c6505a908ec819f8 Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Tue, 22 Oct 2024 11:11:45 +0000 Subject: [PATCH 2/2] Add changelog entry for GDB debugging Add an entry for the new microVM guest kernel debugging feature Signed-off-by: Jack Thomson --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7f50678de4..a77d45eb21e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ and this project adheres to `VIRTIO_NET_F_RX_MRGBUF` support to the `virtio-net` device. When this feature is negotiated, guest `virtio-net` driver can perform more efficient memory management which in turn improves RX and TX performance. +- [#4797](https://github.com/firecracker-microvm/firecracker/pull/4797), + [#4854](https://github.com/firecracker-microvm/firecracker/pull/4854): Added + GDB debugging support for a microVM guest kernel. Please see our + [GDB debugging documentation](docs/gdb-debugging.md) for more information. ### Changed