Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Print MicrovmState from vmstate file of snapshot #4205

Merged
merged 5 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
each individual block device will emit metrics under the label `"block_{drive_id}"`.
E.g. the associated metrics for the endpoint `"/drives/{drive_id}"` will
be available under `"block_drive_id"` in the metrics json object.
- [#4205](https://github.com/firecracker-microvm/firecracker/pull/4205):
Added a new `vm-state` subcommand to `info-vmstate` command in the
`snapshot-editor` tool to print MicrovmState of vmstate snapshot file in
a readable format. Also made the `vcpu-states` subcommand available on
x86_64.

### Changed

Expand Down
203 changes: 112 additions & 91 deletions docs/snapshotting/snapshot-editor.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,104 +16,125 @@ Firecracker snapshot consists of 2 files:

#### `rebase` subcommand

This command is used to merge a `diff` snapshot memory file on
top of a base memory file.

**Note**
You can also use `rebase-snap` (deprecated) tool for this.

Arguments:

- `MEMORY_PATH` - path to the `memory` file
- `DIFF_PATH` - path to the `diff` file

Usage:

```bash
snapshot-editor edit-memory rebase \
--memory-path <MEMORY_PATH> \
--diff-path <DIFF_PATH>
```

Example:

```bash
snapshot-editor edit-memory rebase \
--memory-path ./memory_file \
--diff-path ./diff_file
```
> This command is used to merge a `diff` snapshot memory file on
> top of a base memory file.
>
> **Note**
> You can also use `rebase-snap` (deprecated) tool for this.
>
> Arguments:
>
> - `MEMORY_PATH` - path to the `memory` file
> - `DIFF_PATH` - path to the `diff` file
>
> Usage:
>
> ```bash
> snapshot-editor edit-memory rebase \
> --memory-path <MEMORY_PATH> \
> --diff-path <DIFF_PATH>
> ```
>
> Example:
>
> ```bash
> snapshot-editor edit-memory rebase \
> --memory-path ./memory_file \
> --diff-path ./diff_file
> ```

### `edit-vmstate` command

#### `remove-regs` subcommand (aarch64 only)

This command is used to remove specified registers from vcpu states inside
vmstate snapshot file.

Arguments:

- `VMSTATE_PATH` - path to the `vmstate` file
- `OUTPUT_PATH` - path to the file where the output will be placed
- `[REGS]` - set of u32 values representing registers ids as they are defined
in KVM. Can be both in decimal and in hex formats.

Usage:

```bash
snapshot-editor edit-vmstate remove-regs \
--vmstate-path <VMSTATE_PATH> \
--output-path <OUTPUT_PATH> \
[REGS]...
```

Example:

```bash
./snapshot-editor edit-vmstate remove-regs \
--vmstate-path ./vmstate_file \
--output-path ./new_vmstate_file \
0x1 0x2
```
> This command is used to remove specified registers from vcpu states inside
> vmstate snapshot file.
>
> Arguments:
>
> - `VMSTATE_PATH` - path to the `vmstate` file
> - `OUTPUT_PATH` - path to the file where the output will be placed
> - `[REGS]` - set of u32 values representing registers ids as they are defined
> in KVM. Can be both in decimal and in hex formats.
>
> Usage:
>
> ```bash
> snapshot-editor edit-vmstate remove-regs \
> --vmstate-path <VMSTATE_PATH> \
> --output-path <OUTPUT_PATH> \
> [REGS]...
> ```
>
> Example:
>
> ```bash
> ./snapshot-editor edit-vmstate remove-regs \
> --vmstate-path ./vmstate_file \
> --output-path ./new_vmstate_file \
> 0x1 0x2
> ```

### `info-vmstate` command

#### `version` subcommand

This command is used to print version of the provided
vmstate file.

Arguments:

- `VMSTATE_PATH` - path to the `vmstate` file

Usage:

```bash
snapshot-editor info-vmstate version --vmstate-path <VMSTATE_PATH>
```

Example:

```bash
./snapshot-editor info-vmstate version --vmstate-path ./vmstate_file
```

#### `vcpu-states` subcommand (aarch64 only)

This command is used to print the vCPU states inside vmstate snapshot file.

Arguments:

- `VMSTATE_PATH` - path to the `vmstate` file

Usage:

```bash
snapshot-editor info-vmstate vcpu-states --vmstate-path <VMSTATE_PATH>
```

Example:

```bash
./snapshot-editor info-vmstate vcpu-states --vmstate-path ./vmstate_file
```
> This command is used to print version of the provided
> vmstate file.
>
> Arguments:
>
> - `VMSTATE_PATH` - path to the `vmstate` file
>
> Usage:
>
> ```bash
> snapshot-editor info-vmstate version --vmstate-path <VMSTATE_PATH>
> ```
>
> Example:
>
> ```bash
> ./snapshot-editor info-vmstate version --vmstate-path ./vmstate_file
> ```

#### `vcpu-states` subcommand

> This command is used to print the vCPU states inside vmstate snapshot file.
>
> Arguments:
>
> - `VMSTATE_PATH` - path to the `vmstate` file
>
> Usage:
>
> ```bash
> snapshot-editor info-vmstate vcpu-states --vmstate-path <VMSTATE_PATH>
> ```
>
> Example:
>
> ```bash
> ./snapshot-editor info-vmstate vcpu-states --vmstate-path ./vmstate_file
> ```

#### `vm-state` subcommand

> This command is used to print the vmstate of snapshot file in
> readable format thus, making it easier to compare vmstate of 2 snapshots.
>
> Arguments:
>
> - `VMSTATE_PATH` - path to the `vmstate` file
>
> Usage:
>
> ```bash
> snapshot-editor info-vmstate vm-state --vmstate-path <VMSTATE_PATH>
> ```
>
> Example:
>
> ```bash
> ./snapshot-editor info-vmstate vm-state --vmstate-path ./vmstate_file
> ```
29 changes: 13 additions & 16 deletions src/snapshot-editor/src/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,26 @@
vmstate_path: PathBuf,
},
/// Print info about vcpu states.
#[cfg(target_arch = "aarch64")]
VcpuStates {
/// Path to the vmstate file.
#[arg(short, long)]
vmstate_path: PathBuf,
},
/// Print readable MicroVM state.
wearyzen marked this conversation as resolved.
Show resolved Hide resolved
VmState {
/// Path to the vmstate file.
#[arg(short, long)]
vmstate_path: PathBuf,

Check warning on line 38 in src/snapshot-editor/src/info.rs

View check run for this annotation

Codecov / codecov/patch

src/snapshot-editor/src/info.rs#L38

Added line #L38 was not covered by tests
},
}

pub fn info_vmstate_command(command: InfoVmStateSubCommand) -> Result<(), InfoVmStateError> {
match command {
InfoVmStateSubCommand::Version { vmstate_path } => info(&vmstate_path, info_version)?,
#[cfg(target_arch = "aarch64")]
InfoVmStateSubCommand::VcpuStates { vmstate_path } => {
info(&vmstate_path, info_vcpu_states)?
}
InfoVmStateSubCommand::VmState { vmstate_path } => info(&vmstate_path, info_vmstate)?,

Check warning on line 48 in src/snapshot-editor/src/info.rs

View check run for this annotation

Codecov / codecov/patch

src/snapshot-editor/src/info.rs#L48

Added line #L48 was not covered by tests
}
Ok(())
}
Expand All @@ -67,23 +72,15 @@
}
}

#[cfg(target_arch = "aarch64")]
fn info_vcpu_states(state: &MicrovmState, _: u16) -> Result<(), InfoVmStateError> {
for (i, state) in state.vcpu_states.iter().enumerate() {
println!("vcpu {i}:");
println!("kvm_mp_state: {:#x}", state.mp_state.mp_state);
println!("mpidr: {:#x}", state.mpidr);
for reg in state.regs.iter() {
println!(
"{:#x} 0x{}",
reg.id,
reg.as_slice()
.iter()
.rev()
.map(|b| format!("{b:x}"))
.collect::<String>()
);
}
println!("{state:#?}");

Check warning on line 78 in src/snapshot-editor/src/info.rs

View check run for this annotation

Codecov / codecov/patch

src/snapshot-editor/src/info.rs#L78

Added line #L78 was not covered by tests
}
wearyzen marked this conversation as resolved.
Show resolved Hide resolved
Ok(())
}

fn info_vmstate(vmstate: &MicrovmState, _version: u16) -> Result<(), InfoVmStateError> {
println!("{vmstate:#?}");
Ok(())
}

Check warning on line 86 in src/snapshot-editor/src/info.rs

View check run for this annotation

Codecov / codecov/patch

src/snapshot-editor/src/info.rs#L83-L86

Added lines #L83 - L86 were not covered by tests
24 changes: 23 additions & 1 deletion src/vmm/src/vstate/vcpu/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the THIRD-PARTY file.

use std::fmt::Debug;

use kvm_bindings::*;
use kvm_ioctls::*;
use versionize::{VersionMap, Versionize, VersionizeError, VersionizeResult};
Expand Down Expand Up @@ -250,7 +252,7 @@
}

/// Structure holding VCPU kvm state.
#[derive(Debug, Default, Clone, Versionize)]
#[derive(Default, Clone, Versionize)]
pub struct VcpuState {
/// Multiprocessing state.
pub mp_state: kvm_bindings::kvm_mp_state,
Expand All @@ -271,6 +273,26 @@
pub kvi: Option<kvm_bindings::kvm_vcpu_init>,
}

impl Debug for VcpuState {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "kvm_mp_state: {:#x}", self.mp_state.mp_state)?;
writeln!(f, "mpidr: {:#x}", self.mpidr)?;
for reg in self.regs.iter() {
writeln!(
f,
"{:#x} 0x{}",
reg.id,
reg.as_slice()
.iter()
.rev()
.map(|b| format!("{b:x}"))
.collect::<String>()
)?;

Check warning on line 290 in src/vmm/src/vstate/vcpu/aarch64.rs

View check run for this annotation

Codecov / codecov/patch

src/vmm/src/vstate/vcpu/aarch64.rs#L278-L290

Added lines #L278 - L290 were not covered by tests
}
Ok(())
}

Check warning on line 293 in src/vmm/src/vstate/vcpu/aarch64.rs

View check run for this annotation

Codecov / codecov/patch

src/vmm/src/vstate/vcpu/aarch64.rs#L292-L293

Added lines #L292 - L293 were not covered by tests
}

impl VcpuState {
fn default_old_regs(_: u16) -> Vec<Aarch64RegisterOld> {
Vec::default()
Expand Down
27 changes: 26 additions & 1 deletion src/vmm/src/vstate/vcpu/x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// found in the THIRD-PARTY file.

use std::collections::{HashMap, HashSet};
use std::fmt::Debug;

use kvm_bindings::{
kvm_debugregs, kvm_lapic_state, kvm_mp_state, kvm_regs, kvm_sregs, kvm_vcpu_events, kvm_xcrs,
Expand Down Expand Up @@ -540,7 +541,7 @@
}
}

#[derive(Debug, Clone, Versionize)]
#[derive(Clone, Versionize)]
/// Structure holding VCPU kvm state.
// NOTICE: Any changes to this structure require a snapshot version bump.
pub struct VcpuState {
Expand Down Expand Up @@ -573,6 +574,30 @@
pub tsc_khz: Option<u32>,
}

impl Debug for VcpuState {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut debug_kvm_regs: Vec<kvm_bindings::kvm_msrs> = Vec::new();
for kvm_msrs in self.saved_msrs.iter() {
debug_kvm_regs = kvm_msrs.clone().into_raw();
debug_kvm_regs.sort_by_key(|msr| (msr.nmsrs, msr.pad));
}
f.debug_struct("VcpuState")
.field("cpuid", &self.cpuid)
.field("msrs", &self.msrs)
.field("saved_msrs", &debug_kvm_regs)
.field("debug_regs", &self.debug_regs)
.field("lapic", &self.lapic)
.field("mp_state", &self.mp_state)
.field("regs", &self.regs)
.field("sregs", &self.sregs)
.field("vcpu_events", &self.vcpu_events)
.field("xcrs", &self.xcrs)
.field("xsave", &self.xsave)
.field("tsc_khz", &self.tsc_khz)
.finish()
}

Check warning on line 598 in src/vmm/src/vstate/vcpu/x86_64.rs

View check run for this annotation

Codecov / codecov/patch

src/vmm/src/vstate/vcpu/x86_64.rs#L578-L598

Added lines #L578 - L598 were not covered by tests
}

impl VcpuState {
fn default_tsc_khz(_: u16) -> Option<u32> {
warn!("CPU TSC freq not found in snapshot");
Expand Down