mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm: streamline Display impl of Error types
Streamlines the code base by using thiserror's #[error] attribute consistently for implementing `Display`. Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de> On-behalf-of: SAP philipp.schuster@sap.com
This commit is contained in:
committed by
Rob Bradford
parent
47c9ddfa7e
commit
a991de9955
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
use std::collections::{BTreeSet, HashMap};
|
use std::collections::{BTreeSet, HashMap};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::result;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::{fmt, result};
|
|
||||||
|
|
||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use option_parser::{
|
use option_parser::{
|
||||||
@@ -16,6 +16,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use virtio_bindings::virtio_blk::VIRTIO_BLK_ID_BYTES;
|
use virtio_bindings::virtio_blk::VIRTIO_BLK_ID_BYTES;
|
||||||
use virtio_devices::block::MINIMUM_BLOCK_QUEUE_SIZE;
|
use virtio_devices::block::MINIMUM_BLOCK_QUEUE_SIZE;
|
||||||
|
use virtio_devices::vhost_user::VIRTIO_FS_TAG_LEN;
|
||||||
use virtio_devices::{RateLimiterConfig, TokenBucketConfig};
|
use virtio_devices::{RateLimiterConfig, TokenBucketConfig};
|
||||||
|
|
||||||
use crate::landlock::LandlockAccess;
|
use crate::landlock::LandlockAccess;
|
||||||
@@ -28,452 +29,299 @@ const MAX_IOMMU_ADDRESS_WIDTH_BITS: u8 = 64;
|
|||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// Filesystem tag is missing
|
/// Filesystem tag is missing
|
||||||
|
#[error("Error parsing --fs: tag missing")]
|
||||||
ParseFsTagMissing,
|
ParseFsTagMissing,
|
||||||
/// Filesystem tag is too long
|
/// Filesystem tag is too long
|
||||||
|
#[error("Error parsing --fs: max tag length is {VIRTIO_FS_TAG_LEN}")]
|
||||||
ParseFsTagTooLong,
|
ParseFsTagTooLong,
|
||||||
/// Filesystem socket is missing
|
/// Filesystem socket is missing
|
||||||
|
#[error("Error parsing --fs: socket missing")]
|
||||||
ParseFsSockMissing,
|
ParseFsSockMissing,
|
||||||
/// Missing persistent memory file parameter.
|
/// Missing persistent memory file parameter.
|
||||||
|
#[error("Error parsing --pmem: file missing")]
|
||||||
ParsePmemFileMissing,
|
ParsePmemFileMissing,
|
||||||
/// Missing vsock socket path parameter.
|
/// Missing vsock socket path parameter.
|
||||||
|
#[error("Error parsing --vsock: socket missing")]
|
||||||
ParseVsockSockMissing,
|
ParseVsockSockMissing,
|
||||||
/// Missing vsock cid parameter.
|
/// Missing vsock cid parameter.
|
||||||
|
#[error("Error parsing --vsock: cid missing")]
|
||||||
ParseVsockCidMissing,
|
ParseVsockCidMissing,
|
||||||
/// Missing restore source_url parameter.
|
/// Missing restore source_url parameter.
|
||||||
|
#[error("Error parsing --restore: source_url missing")]
|
||||||
ParseRestoreSourceUrlMissing,
|
ParseRestoreSourceUrlMissing,
|
||||||
/// Error parsing CPU options
|
/// Error parsing CPU options
|
||||||
|
#[error("Error parsing --cpus")]
|
||||||
ParseCpus(#[source] OptionParserError),
|
ParseCpus(#[source] OptionParserError),
|
||||||
/// Invalid CPU features
|
/// Invalid CPU features
|
||||||
|
#[error("Invalid feature in --cpus features list: {0}")]
|
||||||
InvalidCpuFeatures(String),
|
InvalidCpuFeatures(String),
|
||||||
/// Error parsing memory options
|
/// Error parsing memory options
|
||||||
|
#[error("Error parsing --memory")]
|
||||||
ParseMemory(#[source] OptionParserError),
|
ParseMemory(#[source] OptionParserError),
|
||||||
/// Error parsing memory zone options
|
/// Error parsing memory zone options
|
||||||
|
#[error("Error parsing --memory-zone")]
|
||||||
ParseMemoryZone(#[source] OptionParserError),
|
ParseMemoryZone(#[source] OptionParserError),
|
||||||
/// Missing 'id' from memory zone
|
/// Missing 'id' from memory zone
|
||||||
|
#[error("Error parsing --memory-zone: id missing")]
|
||||||
ParseMemoryZoneIdMissing,
|
ParseMemoryZoneIdMissing,
|
||||||
/// Error parsing rate-limiter group options
|
/// Error parsing rate-limiter group options
|
||||||
|
#[error("Error parsing --rate-limit-group")]
|
||||||
ParseRateLimiterGroup(#[source] OptionParserError),
|
ParseRateLimiterGroup(#[source] OptionParserError),
|
||||||
/// Error parsing disk options
|
/// Error parsing disk options
|
||||||
|
#[error("Error parsing --disk")]
|
||||||
ParseDisk(#[source] OptionParserError),
|
ParseDisk(#[source] OptionParserError),
|
||||||
/// Error parsing network options
|
/// Error parsing network options
|
||||||
|
#[error("Error parsing --net")]
|
||||||
ParseNetwork(#[source] OptionParserError),
|
ParseNetwork(#[source] OptionParserError),
|
||||||
/// Error parsing RNG options
|
/// Error parsing RNG options
|
||||||
|
#[error("Error parsing --rng")]
|
||||||
ParseRng(#[source] OptionParserError),
|
ParseRng(#[source] OptionParserError),
|
||||||
/// Error parsing balloon options
|
/// Error parsing balloon options
|
||||||
|
#[error("Error parsing --balloon")]
|
||||||
ParseBalloon(#[source] OptionParserError),
|
ParseBalloon(#[source] OptionParserError),
|
||||||
/// Error parsing filesystem parameters
|
/// Error parsing filesystem parameters
|
||||||
|
#[error("Error parsing --fs")]
|
||||||
ParseFileSystem(#[source] OptionParserError),
|
ParseFileSystem(#[source] OptionParserError),
|
||||||
/// Error parsing persistent memory parameters
|
/// Error parsing persistent memory parameters
|
||||||
|
#[error("Error parsing --pmem")]
|
||||||
ParsePersistentMemory(#[source] OptionParserError),
|
ParsePersistentMemory(#[source] OptionParserError),
|
||||||
/// Failed parsing console
|
/// Failed parsing console
|
||||||
|
#[error("Error parsing --console")]
|
||||||
ParseConsole(#[source] OptionParserError),
|
ParseConsole(#[source] OptionParserError),
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
/// Failed parsing debug-console
|
/// Failed parsing debug-console
|
||||||
|
#[error("Error parsing --debug-console")]
|
||||||
ParseDebugConsole(#[source] OptionParserError),
|
ParseDebugConsole(#[source] OptionParserError),
|
||||||
/// No mode given for console
|
/// No mode given for console
|
||||||
|
#[error("Error parsing --console: invalid console mode given")]
|
||||||
ParseConsoleInvalidModeGiven,
|
ParseConsoleInvalidModeGiven,
|
||||||
/// Failed parsing device parameters
|
/// Failed parsing device parameters
|
||||||
|
#[error("Error parsing --device")]
|
||||||
ParseDevice(#[source] OptionParserError),
|
ParseDevice(#[source] OptionParserError),
|
||||||
/// Missing path from device,
|
/// Missing path from device,
|
||||||
|
#[error("Error parsing --device: path missing")]
|
||||||
ParseDevicePathMissing,
|
ParseDevicePathMissing,
|
||||||
/// Failed parsing vsock parameters
|
/// Failed parsing vsock parameters
|
||||||
|
#[error("Error parsing --vsock")]
|
||||||
ParseVsock(#[source] OptionParserError),
|
ParseVsock(#[source] OptionParserError),
|
||||||
/// Failed parsing restore parameters
|
/// Failed parsing restore parameters
|
||||||
|
#[error("Error parsing --restore")]
|
||||||
ParseRestore(#[source] OptionParserError),
|
ParseRestore(#[source] OptionParserError),
|
||||||
/// Failed parsing SGX EPC parameters
|
/// Failed parsing SGX EPC parameters
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
#[error("Error parsing --sgx-epc")]
|
||||||
ParseSgxEpc(#[source] OptionParserError),
|
ParseSgxEpc(#[source] OptionParserError),
|
||||||
/// Missing 'id' from SGX EPC section
|
/// Missing 'id' from SGX EPC section
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
#[error("Error parsing --sgx-epc: id missing")]
|
||||||
ParseSgxEpcIdMissing,
|
ParseSgxEpcIdMissing,
|
||||||
/// Failed parsing NUMA parameters
|
/// Failed parsing NUMA parameters
|
||||||
|
#[error("Error parsing --numa")]
|
||||||
ParseNuma(#[source] OptionParserError),
|
ParseNuma(#[source] OptionParserError),
|
||||||
/// Failed validating configuration
|
/// Failed validating configuration
|
||||||
|
#[error("Error validating configuration")]
|
||||||
Validation(#[source] ValidationError),
|
Validation(#[source] ValidationError),
|
||||||
#[cfg(feature = "sev_snp")]
|
#[cfg(feature = "sev_snp")]
|
||||||
|
#[error("Error parsing --sev_snp")]
|
||||||
/// Failed parsing SEV-SNP config
|
/// Failed parsing SEV-SNP config
|
||||||
ParseSevSnp(#[source] OptionParserError),
|
ParseSevSnp(#[source] OptionParserError),
|
||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
|
#[error("Error parsing --tdx")]
|
||||||
/// Failed parsing TDX config
|
/// Failed parsing TDX config
|
||||||
ParseTdx(#[source] OptionParserError),
|
ParseTdx(#[source] OptionParserError),
|
||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
|
#[error("TDX firmware missing")]
|
||||||
/// No TDX firmware
|
/// No TDX firmware
|
||||||
FirmwarePathMissing,
|
FirmwarePathMissing,
|
||||||
/// Failed parsing userspace device
|
/// Failed parsing userspace device
|
||||||
|
#[error("Error parsing --user-device")]
|
||||||
ParseUserDevice(#[source] OptionParserError),
|
ParseUserDevice(#[source] OptionParserError),
|
||||||
/// Missing socket for userspace device
|
/// Missing socket for userspace device
|
||||||
|
#[error("Error parsing --user-device: socket missing")]
|
||||||
ParseUserDeviceSocketMissing,
|
ParseUserDeviceSocketMissing,
|
||||||
/// Error parsing pci segment options
|
/// Error parsing pci segment options
|
||||||
|
#[error("Error parsing --pci-segment")]
|
||||||
ParsePciSegment(#[source] OptionParserError),
|
ParsePciSegment(#[source] OptionParserError),
|
||||||
/// Failed parsing platform parameters
|
/// Failed parsing platform parameters
|
||||||
|
#[error("Error parsing --platform")]
|
||||||
ParsePlatform(#[source] OptionParserError),
|
ParsePlatform(#[source] OptionParserError),
|
||||||
/// Failed parsing vDPA device
|
/// Failed parsing vDPA device
|
||||||
|
#[error("Error parsing --vdpa")]
|
||||||
ParseVdpa(#[source] OptionParserError),
|
ParseVdpa(#[source] OptionParserError),
|
||||||
/// Missing path for vDPA device
|
/// Missing path for vDPA device
|
||||||
|
#[error("Error parsing --vdpa: path missing")]
|
||||||
ParseVdpaPathMissing,
|
ParseVdpaPathMissing,
|
||||||
/// Failed parsing TPM device
|
/// Failed parsing TPM device
|
||||||
|
#[error("Error parsing --tpm")]
|
||||||
ParseTpm(#[source] OptionParserError),
|
ParseTpm(#[source] OptionParserError),
|
||||||
/// Missing path for TPM device
|
/// Missing path for TPM device
|
||||||
|
#[error("Error parsing --tpm: path missing")]
|
||||||
ParseTpmPathMissing,
|
ParseTpmPathMissing,
|
||||||
/// Error parsing Landlock rules
|
/// Error parsing Landlock rules
|
||||||
|
#[error("Error parsing --landlock-rules")]
|
||||||
ParseLandlockRules(#[source] OptionParserError),
|
ParseLandlockRules(#[source] OptionParserError),
|
||||||
/// Missing fields in Landlock rules
|
/// Missing fields in Landlock rules
|
||||||
|
#[error("Error parsing --landlock-rules: path/access field missing")]
|
||||||
ParseLandlockMissingFields,
|
ParseLandlockMissingFields,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Error)]
|
#[derive(Debug, PartialEq, Eq, Error)]
|
||||||
pub enum ValidationError {
|
pub enum ValidationError {
|
||||||
/// No kernel specified
|
/// No kernel specified
|
||||||
|
#[error("No kernel specified")]
|
||||||
KernelMissing,
|
KernelMissing,
|
||||||
/// Missing file value for console
|
/// Missing file value for console
|
||||||
|
#[error("Path missing when using file console mode")]
|
||||||
ConsoleFileMissing,
|
ConsoleFileMissing,
|
||||||
/// Missing socket path for console
|
/// Missing socket path for console
|
||||||
|
#[error("Path missing when using socket console mode")]
|
||||||
ConsoleSocketPathMissing,
|
ConsoleSocketPathMissing,
|
||||||
/// Max is less than boot
|
/// Max is less than boot
|
||||||
|
#[error("Max CPUs lower than boot CPUs")]
|
||||||
CpusMaxLowerThanBoot,
|
CpusMaxLowerThanBoot,
|
||||||
/// Missing file value for debug-console
|
/// Missing file value for debug-console
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
#[error("Path missing when using file mode for debug console")]
|
||||||
DebugconFileMissing,
|
DebugconFileMissing,
|
||||||
/// Both socket and path specified
|
/// Both socket and path specified
|
||||||
|
#[error("Disk path and vhost socket both provided")]
|
||||||
DiskSocketAndPath,
|
DiskSocketAndPath,
|
||||||
/// Using vhost user requires shared memory
|
/// Using vhost user requires shared memory
|
||||||
|
#[error("Using vhost-user requires using shared memory or huge pages")]
|
||||||
VhostUserRequiresSharedMemory,
|
VhostUserRequiresSharedMemory,
|
||||||
/// No socket provided for vhost_use
|
/// No socket provided for vhost_use
|
||||||
|
#[error("No socket provided when using vhost-user")]
|
||||||
VhostUserMissingSocket,
|
VhostUserMissingSocket,
|
||||||
/// Trying to use IOMMU without PCI
|
/// Trying to use IOMMU without PCI
|
||||||
|
#[error("Using an IOMMU without PCI support is unsupported")]
|
||||||
IommuUnsupported,
|
IommuUnsupported,
|
||||||
/// Trying to use VFIO without PCI
|
/// Trying to use VFIO without PCI
|
||||||
|
#[error("Using VFIO without PCI support is unsupported")]
|
||||||
VfioUnsupported,
|
VfioUnsupported,
|
||||||
/// CPU topology count doesn't match max
|
/// CPU topology count doesn't match max
|
||||||
|
#[error("Product of CPU topology parts does not match maximum vCPU")]
|
||||||
CpuTopologyCount,
|
CpuTopologyCount,
|
||||||
/// One part of the CPU topology was zero
|
/// One part of the CPU topology was zero
|
||||||
|
#[error("No part of the CPU topology can be zero")]
|
||||||
CpuTopologyZeroPart,
|
CpuTopologyZeroPart,
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
/// Dies per package must be 1
|
/// Dies per package must be 1
|
||||||
|
#[error("Dies per package must be 1")]
|
||||||
CpuTopologyDiesPerPackage,
|
CpuTopologyDiesPerPackage,
|
||||||
/// Virtio needs a min of 2 queues
|
/// Virtio needs a min of 2 queues
|
||||||
|
#[error("Number of queues to virtio_net less than 2")]
|
||||||
VnetQueueLowerThan2,
|
VnetQueueLowerThan2,
|
||||||
/// The input queue number for virtio_net must match the number of input fds
|
/// The input queue number for virtio_net must match the number of input fds
|
||||||
|
#[error("Number of queues to virtio_net does not match the number of input FDs")]
|
||||||
VnetQueueFdMismatch,
|
VnetQueueFdMismatch,
|
||||||
/// Using reserved fd
|
/// Using reserved fd
|
||||||
|
#[error("Reserved fd number (<= 2)")]
|
||||||
VnetReservedFd,
|
VnetReservedFd,
|
||||||
/// Hardware checksum offload is disabled.
|
/// Hardware checksum offload is disabled.
|
||||||
|
#[error("\"offload_tso\" and \"offload_ufo\" depend on \"offload_csum\"")]
|
||||||
NoHardwareChecksumOffload,
|
NoHardwareChecksumOffload,
|
||||||
/// Hugepages not turned on
|
/// Hugepages not turned on
|
||||||
|
#[error("Huge page size specified but huge pages not enabled")]
|
||||||
HugePageSizeWithoutHugePages,
|
HugePageSizeWithoutHugePages,
|
||||||
/// Huge page size is not power of 2
|
/// Huge page size is not power of 2
|
||||||
|
#[error("Huge page size is not power of 2: {0}")]
|
||||||
InvalidHugePageSize(u64),
|
InvalidHugePageSize(u64),
|
||||||
/// CPU Hotplug is not permitted with TDX
|
/// CPU Hotplug is not permitted with TDX
|
||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
|
#[error("CPU hotplug is not permitted with TDX")]
|
||||||
TdxNoCpuHotplug,
|
TdxNoCpuHotplug,
|
||||||
/// Missing firmware for TDX
|
/// Missing firmware for TDX
|
||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
|
#[error("No TDX firmware specified")]
|
||||||
TdxFirmwareMissing,
|
TdxFirmwareMissing,
|
||||||
/// Insufficient vCPUs for queues
|
/// Insufficient vCPUs for queues
|
||||||
|
#[error("Number of vCPUs is insufficient for number of queues")]
|
||||||
TooManyQueues,
|
TooManyQueues,
|
||||||
/// Invalid queue size
|
/// Invalid queue size
|
||||||
|
#[error("Queue size is smaller than {MINIMUM_BLOCK_QUEUE_SIZE}: {0}")]
|
||||||
InvalidQueueSize(u16),
|
InvalidQueueSize(u16),
|
||||||
/// Need shared memory for vfio-user
|
/// Need shared memory for vfio-user
|
||||||
|
#[error("Using user devices requires using shared memory or huge pages")]
|
||||||
UserDevicesRequireSharedMemory,
|
UserDevicesRequireSharedMemory,
|
||||||
/// VSOCK Context Identifier has a special meaning, unsuitable for a VM.
|
/// VSOCK Context Identifier has a special meaning, unsuitable for a VM.
|
||||||
|
#[error("{0} is a special VSOCK CID")]
|
||||||
VsockSpecialCid(u32),
|
VsockSpecialCid(u32),
|
||||||
/// Memory zone is reused across NUMA nodes
|
/// Memory zone is reused across NUMA nodes
|
||||||
|
#[error("Memory zone: {0} belongs to multiple NUMA nodes: {1} and {2}")]
|
||||||
MemoryZoneReused(String, u32, u32),
|
MemoryZoneReused(String, u32, u32),
|
||||||
/// Invalid number of PCI segments
|
/// Invalid number of PCI segments
|
||||||
|
#[error("Number of PCI segments ({0}) not in range of 1 to {MAX_NUM_PCI_SEGMENTS}")]
|
||||||
InvalidNumPciSegments(u16),
|
InvalidNumPciSegments(u16),
|
||||||
/// Invalid PCI segment id
|
/// Invalid PCI segment id
|
||||||
|
#[error("Invalid PCI segment id: {0}")]
|
||||||
InvalidPciSegment(u16),
|
InvalidPciSegment(u16),
|
||||||
/// Invalid PCI segment aperture weight
|
/// Invalid PCI segment aperture weight
|
||||||
|
#[error("Invalid PCI segment aperture weight: {0}")]
|
||||||
InvalidPciSegmentApertureWeight(u32),
|
InvalidPciSegmentApertureWeight(u32),
|
||||||
/// Invalid IOMMU address width in bits
|
/// Invalid IOMMU address width in bits
|
||||||
|
#[error("IOMMU address width in bits ({0}) should be less than or equal to {MAX_IOMMU_ADDRESS_WIDTH_BITS}")]
|
||||||
InvalidIommuAddressWidthBits(u8),
|
InvalidIommuAddressWidthBits(u8),
|
||||||
/// Balloon too big
|
/// Balloon too big
|
||||||
|
#[error("Ballon size ({0}) greater than RAM ({1})")]
|
||||||
BalloonLargerThanRam(u64, u64),
|
BalloonLargerThanRam(u64, u64),
|
||||||
/// On a IOMMU segment but not behind IOMMU
|
/// On a IOMMU segment but not behind IOMMU
|
||||||
|
#[error("Device is on an IOMMU PCI segment ({0}) but not placed behind IOMMU")]
|
||||||
OnIommuSegment(u16),
|
OnIommuSegment(u16),
|
||||||
// On a IOMMU segment but IOMMU not supported
|
// On a IOMMU segment but IOMMU not supported
|
||||||
|
#[error(
|
||||||
|
"Device is on an IOMMU PCI segment ({0}) but does not support being placed behind IOMMU"
|
||||||
|
)]
|
||||||
IommuNotSupportedOnSegment(u16),
|
IommuNotSupportedOnSegment(u16),
|
||||||
// Identifier is not unique
|
// Identifier is not unique
|
||||||
|
#[error("Identifier {0} is not unique")]
|
||||||
IdentifierNotUnique(String),
|
IdentifierNotUnique(String),
|
||||||
/// Invalid identifier
|
/// Invalid identifier
|
||||||
|
#[error("Identifier {0} is not invalid")]
|
||||||
InvalidIdentifier(String),
|
InvalidIdentifier(String),
|
||||||
/// Placing the device behind a virtual IOMMU is not supported
|
/// Placing the device behind a virtual IOMMU is not supported
|
||||||
|
#[error("Device does not support being placed behind IOMMU")]
|
||||||
IommuNotSupported,
|
IommuNotSupported,
|
||||||
/// Duplicated device path (device added twice)
|
/// Duplicated device path (device added twice)
|
||||||
|
#[error("Duplicated device path: {0}")]
|
||||||
DuplicateDevicePath(String),
|
DuplicateDevicePath(String),
|
||||||
/// Provided MTU is lower than what the VIRTIO specification expects
|
/// Provided MTU is lower than what the VIRTIO specification expects
|
||||||
|
#[error("Provided MTU {0} is lower than 1280 (expected by VIRTIO specification)")]
|
||||||
InvalidMtu(u16),
|
InvalidMtu(u16),
|
||||||
/// PCI segment is reused across NUMA nodes
|
/// PCI segment is reused across NUMA nodes
|
||||||
|
#[error("PCI segment: {0} belongs to multiple NUMA nodes {1} and {2}")]
|
||||||
PciSegmentReused(u16, u32, u32),
|
PciSegmentReused(u16, u32, u32),
|
||||||
/// Default PCI segment is assigned to NUMA node other than 0.
|
/// Default PCI segment is assigned to NUMA node other than 0.
|
||||||
|
#[error("Default PCI segment assigned to non-zero NUMA node {0}")]
|
||||||
DefaultPciSegmentInvalidNode(u32),
|
DefaultPciSegmentInvalidNode(u32),
|
||||||
/// Invalid rate-limiter group
|
/// Invalid rate-limiter group
|
||||||
|
#[error("Invalid rate-limiter group")]
|
||||||
InvalidRateLimiterGroup,
|
InvalidRateLimiterGroup,
|
||||||
/// The specified I/O port was invalid. It should be provided in hex, such as `0xe9`.
|
/// The specified I/O port was invalid. It should be provided in hex, such as `0xe9`.
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
#[error("The IO port was not properly provided in hex or a `0x` prefix is missing: {0}")]
|
||||||
InvalidIoPortHex(String),
|
InvalidIoPortHex(String),
|
||||||
#[cfg(feature = "sev_snp")]
|
#[cfg(feature = "sev_snp")]
|
||||||
|
#[error("Invalid host data format")]
|
||||||
InvalidHostData,
|
InvalidHostData,
|
||||||
/// Restore expects all net ids that have fds
|
/// Restore expects all net ids that have fds
|
||||||
|
#[error("Net id {0} is associated with FDs and is required")]
|
||||||
RestoreMissingRequiredNetId(String),
|
RestoreMissingRequiredNetId(String),
|
||||||
/// Number of FDs passed during Restore are incorrect to the NetConfig
|
/// Number of FDs passed during Restore are incorrect to the NetConfig
|
||||||
|
#[error("Number of Net FDs passed for '{0}' during Restore: {1}. Expected: {2}")]
|
||||||
RestoreNetFdCountMismatch(String, usize, usize),
|
RestoreNetFdCountMismatch(String, usize, usize),
|
||||||
/// Path provided in landlock-rules doesn't exist
|
/// Path provided in landlock-rules doesn't exist
|
||||||
|
#[error("Path {0:?} provided in landlock-rules does not exist")]
|
||||||
LandlockPathDoesNotExist(PathBuf),
|
LandlockPathDoesNotExist(PathBuf),
|
||||||
/// Access provided in landlock-rules in invalid
|
/// Access provided in landlock-rules in invalid
|
||||||
|
#[error("access provided in landlock-rules in invalid")]
|
||||||
InvalidLandlockAccess(String),
|
InvalidLandlockAccess(String),
|
||||||
/// Invalid block device serial length
|
/// Invalid block device serial length
|
||||||
|
#[error("Block device serial length ({0}) exceeds maximum allowed length ({1})")]
|
||||||
InvalidSerialLength(usize, usize),
|
InvalidSerialLength(usize, usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
type ValidationResult<T> = std::result::Result<T, ValidationError>;
|
type ValidationResult<T> = std::result::Result<T, ValidationError>;
|
||||||
|
|
||||||
impl fmt::Display for ValidationError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
use self::ValidationError::*;
|
|
||||||
match self {
|
|
||||||
KernelMissing => write!(f, "No kernel specified"),
|
|
||||||
ConsoleFileMissing => write!(f, "Path missing when using file console mode"),
|
|
||||||
ConsoleSocketPathMissing => write!(f, "Path missing when using socket console mode"),
|
|
||||||
CpusMaxLowerThanBoot => write!(f, "Max CPUs lower than boot CPUs"),
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
DebugconFileMissing => write!(f, "Path missing when using file mode for debug console"),
|
|
||||||
DiskSocketAndPath => write!(f, "Disk path and vhost socket both provided"),
|
|
||||||
VhostUserRequiresSharedMemory => {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"Using vhost-user requires using shared memory or huge pages"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
VhostUserMissingSocket => write!(f, "No socket provided when using vhost-user"),
|
|
||||||
IommuUnsupported => write!(f, "Using an IOMMU without PCI support is unsupported"),
|
|
||||||
VfioUnsupported => write!(f, "Using VFIO without PCI support is unsupported"),
|
|
||||||
CpuTopologyZeroPart => write!(f, "No part of the CPU topology can be zero"),
|
|
||||||
CpuTopologyCount => write!(
|
|
||||||
f,
|
|
||||||
"Product of CPU topology parts does not match maximum vCPUs"
|
|
||||||
),
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
|
||||||
CpuTopologyDiesPerPackage => write!(f, "Dies per package must be 1"),
|
|
||||||
VnetQueueLowerThan2 => write!(f, "Number of queues to virtio_net less than 2"),
|
|
||||||
VnetQueueFdMismatch => write!(
|
|
||||||
f,
|
|
||||||
"Number of queues to virtio_net does not match the number of input FDs"
|
|
||||||
),
|
|
||||||
VnetReservedFd => write!(f, "Reserved fd number (<= 2)"),
|
|
||||||
NoHardwareChecksumOffload => write!(
|
|
||||||
f,
|
|
||||||
"\"offload_tso\" and \"offload_ufo\" depend on \"offload_tso\""
|
|
||||||
),
|
|
||||||
HugePageSizeWithoutHugePages => {
|
|
||||||
write!(f, "Huge page size specified but huge pages not enabled")
|
|
||||||
}
|
|
||||||
InvalidHugePageSize(s) => {
|
|
||||||
write!(f, "Huge page size is not power of 2: {s}")
|
|
||||||
}
|
|
||||||
#[cfg(feature = "tdx")]
|
|
||||||
TdxNoCpuHotplug => {
|
|
||||||
write!(f, "CPU hotplug is not permitted with TDX")
|
|
||||||
}
|
|
||||||
#[cfg(feature = "tdx")]
|
|
||||||
TdxFirmwareMissing => {
|
|
||||||
write!(f, "No TDX firmware specified")
|
|
||||||
}
|
|
||||||
TooManyQueues => {
|
|
||||||
write!(f, "Number of vCPUs is insufficient for number of queues")
|
|
||||||
}
|
|
||||||
InvalidQueueSize(s) => {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"Queue size is smaller than {MINIMUM_BLOCK_QUEUE_SIZE}: {s}"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
UserDevicesRequireSharedMemory => {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"Using user devices requires using shared memory or huge pages"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
VsockSpecialCid(cid) => {
|
|
||||||
write!(f, "{cid} is a special VSOCK CID")
|
|
||||||
}
|
|
||||||
MemoryZoneReused(s, u1, u2) => {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"Memory zone: {s} belongs to multiple NUMA nodes {u1} and {u2}"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
InvalidNumPciSegments(n) => {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"Number of PCI segments ({n}) not in range of 1 to {MAX_NUM_PCI_SEGMENTS}"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
InvalidPciSegment(pci_segment) => {
|
|
||||||
write!(f, "Invalid PCI segment id: {pci_segment}")
|
|
||||||
}
|
|
||||||
InvalidPciSegmentApertureWeight(aperture_weight) => {
|
|
||||||
write!(f, "Invalid PCI segment aperture weight: {aperture_weight}")
|
|
||||||
}
|
|
||||||
InvalidIommuAddressWidthBits(iommu_address_width_bits) => {
|
|
||||||
write!(f, "IOMMU address width in bits ({iommu_address_width_bits}) should be less than or equal to {MAX_IOMMU_ADDRESS_WIDTH_BITS}")
|
|
||||||
}
|
|
||||||
BalloonLargerThanRam(balloon_size, ram_size) => {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"Ballon size ({balloon_size}) greater than RAM ({ram_size})"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
OnIommuSegment(pci_segment) => {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"Device is on an IOMMU PCI segment ({pci_segment}) but not placed behind IOMMU"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
IommuNotSupportedOnSegment(pci_segment) => {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"Device is on an IOMMU PCI segment ({pci_segment}) but does not support being placed behind IOMMU"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
IdentifierNotUnique(s) => {
|
|
||||||
write!(f, "Identifier {s} is not unique")
|
|
||||||
}
|
|
||||||
InvalidIdentifier(s) => {
|
|
||||||
write!(f, "Identifier {s} is invalid")
|
|
||||||
}
|
|
||||||
IommuNotSupported => {
|
|
||||||
write!(f, "Device does not support being placed behind IOMMU")
|
|
||||||
}
|
|
||||||
DuplicateDevicePath(p) => write!(f, "Duplicated device path: {p}"),
|
|
||||||
&InvalidMtu(mtu) => {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"Provided MTU {mtu} is lower than 1280 (expected by VIRTIO specification)"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
PciSegmentReused(pci_segment, u1, u2) => {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"PCI segment: {pci_segment} belongs to multiple NUMA nodes {u1} and {u2}"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
DefaultPciSegmentInvalidNode(u1) => {
|
|
||||||
write!(f, "Default PCI segment assigned to non-zero NUMA node {u1}")
|
|
||||||
}
|
|
||||||
InvalidRateLimiterGroup => {
|
|
||||||
write!(f, "Invalid rate-limiter group")
|
|
||||||
}
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
InvalidIoPortHex(s) => {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"The IO port was not properly provided in hex or a `0x` prefix is missing: {s}"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
#[cfg(feature = "sev_snp")]
|
|
||||||
InvalidHostData => {
|
|
||||||
write!(f, "Invalid host data format")
|
|
||||||
}
|
|
||||||
RestoreMissingRequiredNetId(s) => {
|
|
||||||
write!(f, "Net id {s} is associated with FDs and is required")
|
|
||||||
}
|
|
||||||
RestoreNetFdCountMismatch(s, u1, u2) => {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"Number of Net FDs passed for '{s}' during Restore: {u1}. Expected: {u2}"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
LandlockPathDoesNotExist(s) => {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"Path {:?} provided in landlock-rules does not exist",
|
|
||||||
s.as_path()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
InvalidLandlockAccess(s) => {
|
|
||||||
write!(f, "{s}")
|
|
||||||
}
|
|
||||||
InvalidSerialLength(actual, max) => {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"Block device serial length ({actual}) exceeds maximum allowed length ({max})"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
use self::Error::*;
|
|
||||||
match self {
|
|
||||||
ParseConsole(o) => write!(f, "Error parsing --console: {o}"),
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
ParseDebugConsole(o) => write!(f, "Error parsing --debug-console: {o}"),
|
|
||||||
ParseConsoleInvalidModeGiven => {
|
|
||||||
write!(f, "Error parsing --console: invalid console mode given")
|
|
||||||
}
|
|
||||||
ParseCpus(o) => write!(f, "Error parsing --cpus: {o}"),
|
|
||||||
InvalidCpuFeatures(o) => write!(f, "Invalid feature in --cpus features list: {o}"),
|
|
||||||
ParseDevice(o) => write!(f, "Error parsing --device: {o}"),
|
|
||||||
ParseDevicePathMissing => write!(f, "Error parsing --device: path missing"),
|
|
||||||
ParseFileSystem(o) => write!(f, "Error parsing --fs: {o}"),
|
|
||||||
ParseFsSockMissing => write!(f, "Error parsing --fs: socket missing"),
|
|
||||||
ParseFsTagMissing => write!(f, "Error parsing --fs: tag missing"),
|
|
||||||
ParseFsTagTooLong => write!(
|
|
||||||
f,
|
|
||||||
"Error parsing --fs: max tag length is {}",
|
|
||||||
virtio_devices::vhost_user::VIRTIO_FS_TAG_LEN
|
|
||||||
),
|
|
||||||
ParsePersistentMemory(o) => write!(f, "Error parsing --pmem: {o}"),
|
|
||||||
ParsePmemFileMissing => write!(f, "Error parsing --pmem: file missing"),
|
|
||||||
ParseVsock(o) => write!(f, "Error parsing --vsock: {o}"),
|
|
||||||
ParseVsockCidMissing => write!(f, "Error parsing --vsock: cid missing"),
|
|
||||||
ParseVsockSockMissing => write!(f, "Error parsing --vsock: socket missing"),
|
|
||||||
ParseMemory(o) => write!(f, "Error parsing --memory: {o}"),
|
|
||||||
ParseMemoryZone(o) => write!(f, "Error parsing --memory-zone: {o}"),
|
|
||||||
ParseMemoryZoneIdMissing => write!(f, "Error parsing --memory-zone: id missing"),
|
|
||||||
ParseNetwork(o) => write!(f, "Error parsing --net: {o}"),
|
|
||||||
ParseRateLimiterGroup(o) => write!(f, "Error parsing --rate-limit-group: {o}"),
|
|
||||||
ParseDisk(o) => write!(f, "Error parsing --disk: {o}"),
|
|
||||||
ParseRng(o) => write!(f, "Error parsing --rng: {o}"),
|
|
||||||
ParseBalloon(o) => write!(f, "Error parsing --balloon: {o}"),
|
|
||||||
ParseRestore(o) => write!(f, "Error parsing --restore: {o}"),
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
ParseSgxEpc(o) => write!(f, "Error parsing --sgx-epc: {o}"),
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
ParseSgxEpcIdMissing => write!(f, "Error parsing --sgx-epc: id missing"),
|
|
||||||
ParseNuma(o) => write!(f, "Error parsing --numa: {o}"),
|
|
||||||
ParseRestoreSourceUrlMissing => {
|
|
||||||
write!(f, "Error parsing --restore: source_url missing")
|
|
||||||
}
|
|
||||||
ParseUserDeviceSocketMissing => {
|
|
||||||
write!(f, "Error parsing --user-device: socket missing")
|
|
||||||
}
|
|
||||||
ParseUserDevice(o) => write!(f, "Error parsing --user-device: {o}"),
|
|
||||||
Validation(v) => write!(f, "Error validating configuration: {v}"),
|
|
||||||
#[cfg(feature = "sev_snp")]
|
|
||||||
ParseSevSnp(o) => write!(f, "Error parsing --sev_snp: {o}"),
|
|
||||||
#[cfg(feature = "tdx")]
|
|
||||||
ParseTdx(o) => write!(f, "Error parsing --tdx: {o}"),
|
|
||||||
#[cfg(feature = "tdx")]
|
|
||||||
FirmwarePathMissing => write!(f, "TDX firmware missing"),
|
|
||||||
ParsePciSegment(o) => write!(f, "Error parsing --pci-segment: {o}"),
|
|
||||||
ParsePlatform(o) => write!(f, "Error parsing --platform: {o}"),
|
|
||||||
ParseVdpa(o) => write!(f, "Error parsing --vdpa: {o}"),
|
|
||||||
ParseVdpaPathMissing => write!(f, "Error parsing --vdpa: path missing"),
|
|
||||||
ParseTpm(o) => write!(f, "Error parsing --tpm: {o}"),
|
|
||||||
ParseTpmPathMissing => write!(f, "Error parsing --tpm: path missing"),
|
|
||||||
ParseLandlockRules(o) => write!(f, "Error parsing --landlock-rules: {o}"),
|
|
||||||
ParseLandlockMissingFields => write!(
|
|
||||||
f,
|
|
||||||
"Error parsing --landlock-rules: path/access field missing"
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_to_config<T>(items: &mut Option<Vec<T>>, item: T) {
|
pub fn add_to_config<T>(items: &mut Option<Vec<T>>, item: T) {
|
||||||
if let Some(items) = items {
|
if let Some(items) = items {
|
||||||
items.push(item);
|
items.push(item);
|
||||||
|
|||||||
Reference in New Issue
Block a user