diff --git a/src/main.rs b/src/main.rs index fc9f6038b..6ef75654f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -204,7 +204,7 @@ fn create_app(default_vcpus: String, default_memory: String, default_rng: String .arg( Arg::new("platform") .long("platform") - .help("num_pci_segments=,iommu_segments=,serial_number=,uuid=,oem_strings=") + .help("num_pci_segments=,iommu_segments=,iommu_address_width=,serial_number=,uuid=,oem_strings=") .num_args(1) .group("vm-config"), ) diff --git a/vmm/src/api/openapi/cloud-hypervisor.yaml b/vmm/src/api/openapi/cloud-hypervisor.yaml index b7074fdb5..021f61aa6 100644 --- a/vmm/src/api/openapi/cloud-hypervisor.yaml +++ b/vmm/src/api/openapi/cloud-hypervisor.yaml @@ -718,6 +718,9 @@ components: items: type: integer format: int16 + iommu_address_width: + type: integer + format: uint8 serial_number: type: string uuid: diff --git a/vmm/src/config.rs b/vmm/src/config.rs index b2b9873e6..0cf297925 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -21,6 +21,7 @@ use crate::landlock::LandlockAccess; use crate::vm_config::*; const MAX_NUM_PCI_SEGMENTS: u16 = 96; +const MAX_IOMMU_ADDRESS_WIDTH_BITS: u8 = 64; /// Errors associated with VM configuration parameters. #[derive(Debug, Error)] @@ -183,6 +184,8 @@ pub enum ValidationError { InvalidPciSegment(u16), /// Invalid PCI segment aperture weight InvalidPciSegmentApertureWeight(u32), + /// Invalid IOMMU address width in bits + InvalidIommuAddressWidthBits(u8), /// Balloon too big BalloonLargerThanRam(u64, u64), /// On a IOMMU segment but not behind IOMMU @@ -309,6 +312,9 @@ impl fmt::Display for ValidationError { 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, @@ -817,6 +823,7 @@ impl PlatformConfig { parser .add("num_pci_segments") .add("iommu_segments") + .add("iommu_address_width") .add("serial_number") .add("uuid") .add("oem_strings"); @@ -834,6 +841,10 @@ impl PlatformConfig { .convert::("iommu_segments") .map_err(Error::ParsePlatform)? .map(|v| v.0.iter().map(|e| *e as u16).collect()); + let iommu_address_width_bits: u8 = parser + .convert("iommu_address_width") + .map_err(Error::ParsePlatform)? + .unwrap_or(MAX_IOMMU_ADDRESS_WIDTH_BITS); let serial_number = parser .convert("serial_number") .map_err(Error::ParsePlatform)?; @@ -857,6 +868,7 @@ impl PlatformConfig { Ok(PlatformConfig { num_pci_segments, iommu_segments, + iommu_address_width_bits, serial_number, uuid, oem_strings, @@ -882,6 +894,12 @@ impl PlatformConfig { } } + if self.iommu_address_width_bits > MAX_IOMMU_ADDRESS_WIDTH_BITS { + return Err(ValidationError::InvalidIommuAddressWidthBits( + self.iommu_address_width_bits, + )); + } + Ok(()) } } @@ -3998,6 +4016,7 @@ mod tests { PlatformConfig { num_pci_segments: MAX_NUM_PCI_SEGMENTS, iommu_segments: None, + iommu_address_width_bits: MAX_IOMMU_ADDRESS_WIDTH_BITS, serial_number: None, uuid: None, oem_strings: None, @@ -4296,6 +4315,18 @@ mod tests { Err(ValidationError::InvalidPciSegment(MAX_NUM_PCI_SEGMENTS + 1)) ); + let mut invalid_config = valid_config.clone(); + invalid_config.platform = Some(PlatformConfig { + iommu_address_width_bits: MAX_IOMMU_ADDRESS_WIDTH_BITS + 1, + ..platform_fixture() + }); + assert_eq!( + invalid_config.validate(), + Err(ValidationError::InvalidIommuAddressWidthBits( + MAX_IOMMU_ADDRESS_WIDTH_BITS + 1 + )) + ); + let mut still_valid_config = valid_config.clone(); still_valid_config.platform = Some(PlatformConfig { iommu_segments: Some(vec![1, 2, 3]), diff --git a/vmm/src/vm_config.rs b/vmm/src/vm_config.rs index e74fbc1d6..93304e47d 100644 --- a/vmm/src/vm_config.rs +++ b/vmm/src/vm_config.rs @@ -88,12 +88,19 @@ pub fn default_platformconfig_num_pci_segments() -> u16 { DEFAULT_NUM_PCI_SEGMENTS } +pub const DEFAULT_IOMMU_ADDRESS_WIDTH_BITS: u8 = 64; +pub fn default_platformconfig_iommu_address_width_bits() -> u8 { + DEFAULT_IOMMU_ADDRESS_WIDTH_BITS +} + #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] pub struct PlatformConfig { #[serde(default = "default_platformconfig_num_pci_segments")] pub num_pci_segments: u16, #[serde(default)] pub iommu_segments: Option>, + #[serde(default = "default_platformconfig_iommu_address_width_bits")] + pub iommu_address_width_bits: u8, #[serde(default)] pub serial_number: Option, #[serde(default)]