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 @@ pub enum InfoVmStateSubCommand {
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.
VmState {
/// Path to the vmstate file.
#[arg(short, long)]
vmstate_path: PathBuf,
},
}

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)?,
}
Ok(())
}
Expand All @@ -67,23 +72,15 @@ fn info_version(_: &MicrovmState, version: u16) -> Result<(), InfoVmStateError>
}
}

#[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:#?}");
}
Ok(())
}

fn info_vmstate(vmstate: &MicrovmState, _version: u16) -> Result<(), InfoVmStateError> {
println!("{vmstate:#?}");
Ok(())
}
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 @@ impl KvmVcpu {
}

/// 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 struct VcpuState {
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>()
)?;
}
Ok(())
}
}

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 @@ impl KvmVcpu {
}
}

#[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 struct VcpuState {
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()
}
}

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