mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-02-01 09:25:21 +00:00
vmm: introduce platform option to limit maximum IOMMU address width
Signed-off-by: Nikolay Edigaryev <edigaryev@gmail.com>
This commit is contained in:
parent
fa686fdfc7
commit
74ca38f7a9
@ -204,7 +204,7 @@ fn create_app(default_vcpus: String, default_memory: String, default_rng: String
|
|||||||
.arg(
|
.arg(
|
||||||
Arg::new("platform")
|
Arg::new("platform")
|
||||||
.long("platform")
|
.long("platform")
|
||||||
.help("num_pci_segments=<num_pci_segments>,iommu_segments=<list_of_segments>,serial_number=<dmi_device_serial_number>,uuid=<dmi_device_uuid>,oem_strings=<list_of_strings>")
|
.help("num_pci_segments=<num_pci_segments>,iommu_segments=<list_of_segments>,iommu_address_width=<bits>,serial_number=<dmi_device_serial_number>,uuid=<dmi_device_uuid>,oem_strings=<list_of_strings>")
|
||||||
.num_args(1)
|
.num_args(1)
|
||||||
.group("vm-config"),
|
.group("vm-config"),
|
||||||
)
|
)
|
||||||
|
@ -718,6 +718,9 @@ components:
|
|||||||
items:
|
items:
|
||||||
type: integer
|
type: integer
|
||||||
format: int16
|
format: int16
|
||||||
|
iommu_address_width:
|
||||||
|
type: integer
|
||||||
|
format: uint8
|
||||||
serial_number:
|
serial_number:
|
||||||
type: string
|
type: string
|
||||||
uuid:
|
uuid:
|
||||||
|
@ -21,6 +21,7 @@ use crate::landlock::LandlockAccess;
|
|||||||
use crate::vm_config::*;
|
use crate::vm_config::*;
|
||||||
|
|
||||||
const MAX_NUM_PCI_SEGMENTS: u16 = 96;
|
const MAX_NUM_PCI_SEGMENTS: u16 = 96;
|
||||||
|
const MAX_IOMMU_ADDRESS_WIDTH_BITS: u8 = 64;
|
||||||
|
|
||||||
/// Errors associated with VM configuration parameters.
|
/// Errors associated with VM configuration parameters.
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
@ -183,6 +184,8 @@ pub enum ValidationError {
|
|||||||
InvalidPciSegment(u16),
|
InvalidPciSegment(u16),
|
||||||
/// Invalid PCI segment aperture weight
|
/// Invalid PCI segment aperture weight
|
||||||
InvalidPciSegmentApertureWeight(u32),
|
InvalidPciSegmentApertureWeight(u32),
|
||||||
|
/// Invalid IOMMU address width in bits
|
||||||
|
InvalidIommuAddressWidthBits(u8),
|
||||||
/// Balloon too big
|
/// Balloon too big
|
||||||
BalloonLargerThanRam(u64, u64),
|
BalloonLargerThanRam(u64, u64),
|
||||||
/// On a IOMMU segment but not behind IOMMU
|
/// On a IOMMU segment but not behind IOMMU
|
||||||
@ -309,6 +312,9 @@ impl fmt::Display for ValidationError {
|
|||||||
InvalidPciSegmentApertureWeight(aperture_weight) => {
|
InvalidPciSegmentApertureWeight(aperture_weight) => {
|
||||||
write!(f, "Invalid PCI segment aperture weight: {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) => {
|
BalloonLargerThanRam(balloon_size, ram_size) => {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
@ -817,6 +823,7 @@ impl PlatformConfig {
|
|||||||
parser
|
parser
|
||||||
.add("num_pci_segments")
|
.add("num_pci_segments")
|
||||||
.add("iommu_segments")
|
.add("iommu_segments")
|
||||||
|
.add("iommu_address_width")
|
||||||
.add("serial_number")
|
.add("serial_number")
|
||||||
.add("uuid")
|
.add("uuid")
|
||||||
.add("oem_strings");
|
.add("oem_strings");
|
||||||
@ -834,6 +841,10 @@ impl PlatformConfig {
|
|||||||
.convert::<IntegerList>("iommu_segments")
|
.convert::<IntegerList>("iommu_segments")
|
||||||
.map_err(Error::ParsePlatform)?
|
.map_err(Error::ParsePlatform)?
|
||||||
.map(|v| v.0.iter().map(|e| *e as u16).collect());
|
.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
|
let serial_number = parser
|
||||||
.convert("serial_number")
|
.convert("serial_number")
|
||||||
.map_err(Error::ParsePlatform)?;
|
.map_err(Error::ParsePlatform)?;
|
||||||
@ -857,6 +868,7 @@ impl PlatformConfig {
|
|||||||
Ok(PlatformConfig {
|
Ok(PlatformConfig {
|
||||||
num_pci_segments,
|
num_pci_segments,
|
||||||
iommu_segments,
|
iommu_segments,
|
||||||
|
iommu_address_width_bits,
|
||||||
serial_number,
|
serial_number,
|
||||||
uuid,
|
uuid,
|
||||||
oem_strings,
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3998,6 +4016,7 @@ mod tests {
|
|||||||
PlatformConfig {
|
PlatformConfig {
|
||||||
num_pci_segments: MAX_NUM_PCI_SEGMENTS,
|
num_pci_segments: MAX_NUM_PCI_SEGMENTS,
|
||||||
iommu_segments: None,
|
iommu_segments: None,
|
||||||
|
iommu_address_width_bits: MAX_IOMMU_ADDRESS_WIDTH_BITS,
|
||||||
serial_number: None,
|
serial_number: None,
|
||||||
uuid: None,
|
uuid: None,
|
||||||
oem_strings: None,
|
oem_strings: None,
|
||||||
@ -4296,6 +4315,18 @@ mod tests {
|
|||||||
Err(ValidationError::InvalidPciSegment(MAX_NUM_PCI_SEGMENTS + 1))
|
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();
|
let mut still_valid_config = valid_config.clone();
|
||||||
still_valid_config.platform = Some(PlatformConfig {
|
still_valid_config.platform = Some(PlatformConfig {
|
||||||
iommu_segments: Some(vec![1, 2, 3]),
|
iommu_segments: Some(vec![1, 2, 3]),
|
||||||
|
@ -88,12 +88,19 @@ pub fn default_platformconfig_num_pci_segments() -> u16 {
|
|||||||
DEFAULT_NUM_PCI_SEGMENTS
|
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)]
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub struct PlatformConfig {
|
pub struct PlatformConfig {
|
||||||
#[serde(default = "default_platformconfig_num_pci_segments")]
|
#[serde(default = "default_platformconfig_num_pci_segments")]
|
||||||
pub num_pci_segments: u16,
|
pub num_pci_segments: u16,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub iommu_segments: Option<Vec<u16>>,
|
pub iommu_segments: Option<Vec<u16>>,
|
||||||
|
#[serde(default = "default_platformconfig_iommu_address_width_bits")]
|
||||||
|
pub iommu_address_width_bits: u8,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub serial_number: Option<String>,
|
pub serial_number: Option<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user