vmm: Improve error handling for vmm::vm::Error

In particular implement thiserror::Error, cleanup wording and remove
unused errors.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford 2022-04-20 17:20:54 +01:00
parent cb03540ffd
commit 62f17ccf8c
2 changed files with 99 additions and 106 deletions

View File

@ -508,7 +508,7 @@ impl Vmm {
let source_url = restore_cfg.source_url.as_path().to_str(); let source_url = restore_cfg.source_url.as_path().to_str();
if source_url.is_none() { if source_url.is_none() {
return Err(VmError::RestoreSourceUrlPathToStr); return Err(VmError::InvalidRestoreSourceUrl);
} }
// Safe to unwrap as we checked it was Some(&str). // Safe to unwrap as we checked it was Some(&str).
let source_url = source_url.unwrap(); let source_url = source_url.unwrap();

View File

@ -17,7 +17,7 @@ use crate::config::{
UserDeviceConfig, ValidationError, VdpaConfig, VmConfig, VsockConfig, UserDeviceConfig, ValidationError, VdpaConfig, VmConfig, VsockConfig,
}; };
use crate::cpu; use crate::cpu;
use crate::device_manager::{self, Console, DeviceManager, DeviceManagerError, PtyPair}; use crate::device_manager::{Console, DeviceManager, DeviceManagerError, PtyPair};
use crate::device_tree::DeviceTree; use crate::device_tree::DeviceTree;
#[cfg(feature = "gdb")] #[cfg(feature = "gdb")]
use crate::gdb::{Debuggable, DebuggableError, GdbRequestPayload, GdbResponsePayload}; use crate::gdb::{Debuggable, DebuggableError, GdbRequestPayload, GdbResponsePayload};
@ -73,6 +73,7 @@ use std::os::unix::net::UnixStream;
use std::panic::AssertUnwindSafe; use std::panic::AssertUnwindSafe;
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, Mutex, RwLock};
use std::{result, str, thread}; use std::{result, str, thread};
use thiserror::Error;
use vm_device::Bus; use vm_device::Bus;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
use vm_device::BusDevice; use vm_device::BusDevice;
@ -99,200 +100,192 @@ use arch::aarch64::gic::kvm::create_gic;
use devices::interrupt_controller::{self, InterruptController}; use devices::interrupt_controller::{self, InterruptController};
/// Errors associated with VM management /// Errors associated with VM management
#[derive(Debug)] #[derive(Debug, Error)]
pub enum Error { pub enum Error {
/// Cannot open the kernel image #[error("Cannot open kernel file: {0}")]
KernelFile(io::Error), KernelFile(#[source] io::Error),
/// Cannot open the initramfs image #[error("Cannot open initramfs file: {0}")]
InitramfsFile(io::Error), InitramfsFile(#[source] io::Error),
/// Cannot load the kernel in memory #[error("Cannot load the kernel into memory: {0}")]
KernelLoad(linux_loader::loader::Error), KernelLoad(#[source] linux_loader::loader::Error),
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
/// Cannot load the UEFI binary in memory #[error("Cannot load the UEFI binary in memory: {0:?}")]
UefiLoad(arch::aarch64::uefi::Error), UefiLoad(arch::aarch64::uefi::Error),
/// Cannot load the initramfs in memory #[error("Cannot load the initramfs into memory")]
InitramfsLoad, InitramfsLoad,
/// Cannot load the command line in memory #[error("Cannot load the kernel command line in memory: {0}")]
LoadCmdLine(linux_loader::loader::Error), LoadCmdLine(#[source] linux_loader::loader::Error),
/// Cannot modify the command line #[error("Cannot modify the kernel command line: {0}")]
CmdLineInsertStr(linux_loader::cmdline::Error), CmdLineInsertStr(#[source] linux_loader::cmdline::Error),
/// Cannot configure system #[error("Cannot configure system: {0}")]
ConfigureSystem(arch::Error), ConfigureSystem(#[source] arch::Error),
/// Cannot enable interrupt controller
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
#[error("Cannot enable interrupt controller: {0:?}")]
EnableInterruptController(interrupt_controller::Error), EnableInterruptController(interrupt_controller::Error),
#[error("VM state is poisoned")]
PoisonedState, PoisonedState,
/// Cannot create a device manager. #[error("Error from device manager: {0:?}")]
DeviceManager(DeviceManagerError), DeviceManager(DeviceManagerError),
/// Write to the console failed. #[error("Cannot setup terminal in raw mode: {0}")]
Console(vmm_sys_util::errno::Error), SetTerminalRaw(#[source] vmm_sys_util::errno::Error),
/// Write to the pty console failed. #[error("Cannot setup terminal in canonical mode.: {0}")]
PtyConsole(io::Error), SetTerminalCanon(#[source] vmm_sys_util::errno::Error),
/// Cannot setup terminal in raw mode. #[error("Cannot spawn a signal handler thread: {0}")]
SetTerminalRaw(vmm_sys_util::errno::Error), SignalHandlerSpawn(#[source] io::Error),
/// Cannot setup terminal in canonical mode. #[error("Failed to join on threads: {0:?}")]
SetTerminalCanon(vmm_sys_util::errno::Error),
/// Memory is overflow
MemOverflow,
/// Cannot spawn a signal handler thread
SignalHandlerSpawn(io::Error),
/// Failed to join on vCPU threads
ThreadCleanup(std::boxed::Box<dyn std::any::Any + std::marker::Send>), ThreadCleanup(std::boxed::Box<dyn std::any::Any + std::marker::Send>),
/// VM config is missing. #[error("VM config is missing")]
VmMissingConfig, VmMissingConfig,
/// VM is not created #[error("VM is not created")]
VmNotCreated, VmNotCreated,
/// VM is already created #[error("VM is already created")]
VmAlreadyCreated, VmAlreadyCreated,
/// VM is not running #[error("VM is not running")]
VmNotRunning, VmNotRunning,
/// Cannot clone EventFd. #[error("Cannot clone EventFd: {0}")]
EventFdClone(io::Error), EventFdClone(#[source] io::Error),
/// Invalid VM state transition #[error("invalid VM state transition: {0:?} to {1:?}")]
InvalidStateTransition(VmState, VmState), InvalidStateTransition(VmState, VmState),
/// Error from CPU handling #[error("Error from CPU manager: {0}")]
CpuManager(cpu::Error), CpuManager(#[source] cpu::Error),
/// Cannot pause devices #[error("Cannot pause devices: {0}")]
PauseDevices(MigratableError), PauseDevices(#[source] MigratableError),
/// Cannot resume devices #[error("Cannot resume devices: {0}")]
ResumeDevices(MigratableError), ResumeDevices(#[source] MigratableError),
/// Cannot pause CPUs #[error("Cannot pause CPUs: {0}")]
PauseCpus(MigratableError), PauseCpus(#[source] MigratableError),
/// Cannot resume cpus #[error("Cannot resume cpus: {0}")]
ResumeCpus(MigratableError), ResumeCpus(#[source] MigratableError),
/// Cannot pause VM #[error("Cannot pause VM: {0}")]
Pause(MigratableError), Pause(#[source] MigratableError),
/// Cannot resume VM #[error("Cannot resume VM: {0}")]
Resume(MigratableError), Resume(#[source] MigratableError),
/// Memory manager error #[error("Memory manager error: {0:?}")]
MemoryManager(MemoryManagerError), MemoryManager(MemoryManagerError),
/// Eventfd write error #[error("Eventfd write error: {0}")]
EventfdError(std::io::Error), EventfdError(#[source] std::io::Error),
/// Cannot snapshot VM #[error("Cannot snapshot VM: {0}")]
Snapshot(MigratableError), Snapshot(#[source] MigratableError),
/// Cannot restore VM #[error("Cannot restore VM: {0}")]
Restore(MigratableError), Restore(#[source] MigratableError),
/// Cannot send VM snapshot #[error("Cannot send VM snapshot: {0}")]
SnapshotSend(MigratableError), SnapshotSend(#[source] MigratableError),
/// Cannot convert source URL from Path into &str #[error("Invalid restore source URL")]
RestoreSourceUrlPathToStr, InvalidRestoreSourceUrl,
/// Failed to validate config #[error("Failed to validate config: {0}")]
ConfigValidation(ValidationError), ConfigValidation(#[source] ValidationError),
/// No more that one virtio-vsock device #[error("Too many virtio-vsock devices")]
TooManyVsockDevices, TooManyVsockDevices,
/// Failed serializing into JSON #[error("Failed serializing into JSON: {0}")]
SerializeJson(serde_json::Error), SerializeJson(#[source] serde_json::Error),
/// Invalid configuration for NUMA. #[error("Invalid NUMA configuration")]
InvalidNumaConfig, InvalidNumaConfig,
/// Cannot create seccomp filter #[error("Cannot create seccomp filter: {0}")]
CreateSeccompFilter(seccompiler::Error), CreateSeccompFilter(#[source] seccompiler::Error),
/// Cannot apply seccomp filter #[error("Cannot apply seccomp filter: {0}")]
ApplySeccompFilter(seccompiler::Error), ApplySeccompFilter(#[source] seccompiler::Error),
/// Failed resizing a memory zone. #[error("Failed resizing a memory zone")]
ResizeZone, ResizeZone,
/// Cannot activate virtio devices #[error("Cannot activate virtio devices: {0:?}")]
ActivateVirtioDevices(device_manager::DeviceManagerError), ActivateVirtioDevices(DeviceManagerError),
/// Error triggering power button #[error("Error triggering power button: {0:?}")]
PowerButton(device_manager::DeviceManagerError), PowerButton(DeviceManagerError),
/// Kernel lacks PVH header #[error("Kernel lacks PVH header")]
KernelMissingPvhHeader, KernelMissingPvhHeader,
/// Failed to allocate firmware RAM #[error("Failed to allocate firmware RAM: {0:?}")]
AllocateFirmwareMemory(MemoryManagerError), AllocateFirmwareMemory(MemoryManagerError),
/// Error manipulating firmware file #[error("Error manipulating firmware file: {0}")]
FirmwareFile(std::io::Error), FirmwareFile(#[source] std::io::Error),
/// Firmware too big #[error("Firmware too big")]
FirmwareTooLarge, FirmwareTooLarge,
// Failed to copy to memory #[error("Failed to copy firmware to memory: {0}")]
FirmwareLoad(vm_memory::GuestMemoryError), FirmwareLoad(#[source] vm_memory::GuestMemoryError),
/// Error performing I/O on TDX firmware file
#[cfg(feature = "tdx")] #[cfg(feature = "tdx")]
LoadTdvf(std::io::Error), #[error("Error performing I/O on TDX firmware file: {0}")]
LoadTdvf(#[source] std::io::Error),
/// Error performing I/O on the payload file
#[cfg(feature = "tdx")] #[cfg(feature = "tdx")]
LoadPayload(std::io::Error), #[error("Error performing I/O on the TDX payload file: {0}")]
LoadPayload(#[source] std::io::Error),
/// Error parsing TDVF
#[cfg(feature = "tdx")] #[cfg(feature = "tdx")]
ParseTdvf(arch::x86_64::tdx::TdvfError), #[error("Error parsing TDVF: {0}")]
ParseTdvf(#[source] arch::x86_64::tdx::TdvfError),
/// Error populating HOB
#[cfg(feature = "tdx")] #[cfg(feature = "tdx")]
PopulateHob(arch::x86_64::tdx::TdvfError), #[error("Error populating TDX HOB: {0}")]
PopulateHob(#[source] arch::x86_64::tdx::TdvfError),
/// Error allocating TDVF memory
#[cfg(feature = "tdx")] #[cfg(feature = "tdx")]
#[error("Error allocating TDVF memory: {0:?}")]
AllocatingTdvfMemory(crate::memory_manager::Error), AllocatingTdvfMemory(crate::memory_manager::Error),
/// Error enabling TDX VM
#[cfg(feature = "tdx")] #[cfg(feature = "tdx")]
InitializeTdxVm(hypervisor::HypervisorVmError), #[error("Error enabling TDX VM: {0}")]
InitializeTdxVm(#[source] hypervisor::HypervisorVmError),
/// Error enabling TDX memory region
#[cfg(feature = "tdx")] #[cfg(feature = "tdx")]
InitializeTdxMemoryRegion(hypervisor::HypervisorVmError), #[error("Error enabling TDX memory region: {0}")]
InitializeTdxMemoryRegion(#[source] hypervisor::HypervisorVmError),
/// Error finalizing TDX setup
#[cfg(feature = "tdx")] #[cfg(feature = "tdx")]
FinalizeTdx(hypervisor::HypervisorVmError), #[error("Error finalizing TDX VM: {0}")]
FinalizeTdx(#[source] hypervisor::HypervisorVmError),
/// Invalid payload type
#[cfg(feature = "tdx")] #[cfg(feature = "tdx")]
#[error("Invalid TDX payload type")]
InvalidPayloadType, InvalidPayloadType,
/// Error debugging VM
#[cfg(feature = "gdb")] #[cfg(feature = "gdb")]
#[error("Error debugging VM: {0:?}")]
Debug(DebuggableError), Debug(DebuggableError),
} }
pub type Result<T> = result::Result<T, Error>; pub type Result<T> = result::Result<T, Error>;