mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm: make PCI BDF configurable for balloon
Add shared PCI config to virtio-balloon. On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This commit is contained in:
committed by
Rob Bradford
parent
08bd7727ff
commit
5aa0587f2a
@@ -6092,6 +6092,7 @@ mod common_parallel {
|
|||||||
.args(["--kernel", kernel_path.to_str().unwrap()])
|
.args(["--kernel", kernel_path.to_str().unwrap()])
|
||||||
.args(["--cmdline", DIRECT_KERNEL_BOOT_CMDLINE])
|
.args(["--cmdline", DIRECT_KERNEL_BOOT_CMDLINE])
|
||||||
.args(["--console", "tty,pci_device_id=7"])
|
.args(["--console", "tty,pci_device_id=7"])
|
||||||
|
.args(["--balloon", "size=0,pci_device_id=8"])
|
||||||
.default_net()
|
.default_net()
|
||||||
.default_disks()
|
.default_disks()
|
||||||
.capture_output();
|
.capture_output();
|
||||||
@@ -6113,6 +6114,17 @@ mod common_parallel {
|
|||||||
.is_ok()
|
.is_ok()
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Make sure an explicit BDF for virtio-balloon is set.
|
||||||
|
assert!(wait_until(Duration::from_secs(10), || {
|
||||||
|
ssh_command_ip_with_auth(
|
||||||
|
"lspci -n | grep \"00:08.0\"",
|
||||||
|
&default_guest_auth(),
|
||||||
|
&guest.network.guest_ip0,
|
||||||
|
Some(Duration::from_secs(1)),
|
||||||
|
)
|
||||||
|
.is_ok()
|
||||||
|
}));
|
||||||
|
|
||||||
let (cmd_success, cmd_stdout, _) = remote_command_w_output(
|
let (cmd_success, cmd_stdout, _) = remote_command_w_output(
|
||||||
&api_socket,
|
&api_socket,
|
||||||
"add-net",
|
"add-net",
|
||||||
|
|||||||
@@ -1127,6 +1127,17 @@ components:
|
|||||||
- size
|
- size
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
pci_segment:
|
||||||
|
type: integer
|
||||||
|
format: int16
|
||||||
|
pci_device_id:
|
||||||
|
type: integer
|
||||||
|
format: uint8
|
||||||
|
iommu:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
size:
|
size:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
|
|||||||
+89
-1
@@ -1896,13 +1896,15 @@ impl RtcConfig {
|
|||||||
|
|
||||||
impl BalloonConfig {
|
impl BalloonConfig {
|
||||||
pub const SYNTAX: &'static str = "Balloon parameters \"size=<balloon_size>,deflate_on_oom=on|off,\
|
pub const SYNTAX: &'static str = "Balloon parameters \"size=<balloon_size>,deflate_on_oom=on|off,\
|
||||||
free_page_reporting=on|off\"";
|
free_page_reporting=on|off,iommu=on|off,id=<device_id>,pci_segment=<segment_id>,\
|
||||||
|
pci_device_id=<pci_slot>\"";
|
||||||
|
|
||||||
pub fn parse(balloon: &str) -> Result<Self> {
|
pub fn parse(balloon: &str) -> Result<Self> {
|
||||||
let mut parser = OptionParser::new();
|
let mut parser = OptionParser::new();
|
||||||
parser.add("size");
|
parser.add("size");
|
||||||
parser.add("deflate_on_oom");
|
parser.add("deflate_on_oom");
|
||||||
parser.add("free_page_reporting");
|
parser.add("free_page_reporting");
|
||||||
|
parser.add_all(PciDeviceCommonConfig::OPTIONS_IOMMU);
|
||||||
parser.parse(balloon).map_err(Error::ParseBalloon)?;
|
parser.parse(balloon).map_err(Error::ParseBalloon)?;
|
||||||
|
|
||||||
let size = parser
|
let size = parser
|
||||||
@@ -1922,12 +1924,19 @@ impl BalloonConfig {
|
|||||||
.unwrap_or(Toggle(false))
|
.unwrap_or(Toggle(false))
|
||||||
.0;
|
.0;
|
||||||
|
|
||||||
|
let pci_common = PciDeviceCommonConfig::parse(balloon)?;
|
||||||
|
|
||||||
Ok(BalloonConfig {
|
Ok(BalloonConfig {
|
||||||
|
pci_common,
|
||||||
size,
|
size,
|
||||||
deflate_on_oom,
|
deflate_on_oom,
|
||||||
free_page_reporting,
|
free_page_reporting,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn validate(&self, vm_config: &VmConfig) -> ValidationResult<()> {
|
||||||
|
self.pci_common.validate(vm_config)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GenericVhostUserConfig {
|
impl GenericVhostUserConfig {
|
||||||
@@ -3258,6 +3267,10 @@ impl VmConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(balloon) = &self.balloon {
|
if let Some(balloon) = &self.balloon {
|
||||||
|
balloon.validate(self)?;
|
||||||
|
Self::validate_identifier(&mut id_list, &balloon.pci_common.id)?;
|
||||||
|
self.iommu |= balloon.pci_common.iommu;
|
||||||
|
|
||||||
let ram_size = self.memory.total_size();
|
let ram_size = self.memory.total_size();
|
||||||
if balloon.size >= ram_size {
|
if balloon.size >= ram_size {
|
||||||
return Err(ValidationError::BalloonLargerThanRam(
|
return Err(ValidationError::BalloonLargerThanRam(
|
||||||
@@ -4373,6 +4386,40 @@ mod unit_tests {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_balloon() -> Result<()> {
|
||||||
|
assert_eq!(
|
||||||
|
BalloonConfig::parse(
|
||||||
|
"size=128M,deflate_on_oom=on,free_page_reporting=on,pci_segment=1,pci_device_id=7"
|
||||||
|
)?,
|
||||||
|
BalloonConfig {
|
||||||
|
pci_common: PciDeviceCommonConfig {
|
||||||
|
pci_segment: 1,
|
||||||
|
pci_device_id: Some(7),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
size: 128 << 20,
|
||||||
|
deflate_on_oom: true,
|
||||||
|
free_page_reporting: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
BalloonConfig::parse("size=0,iommu=on")?,
|
||||||
|
BalloonConfig {
|
||||||
|
pci_common: PciDeviceCommonConfig {
|
||||||
|
iommu: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
size: 0,
|
||||||
|
deflate_on_oom: false,
|
||||||
|
free_page_reporting: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn fs_fixture() -> FsConfig {
|
fn fs_fixture() -> FsConfig {
|
||||||
FsConfig {
|
FsConfig {
|
||||||
pci_common: PciDeviceCommonConfig::default(),
|
pci_common: PciDeviceCommonConfig::default(),
|
||||||
@@ -6124,6 +6171,47 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
|
|||||||
Err(ValidationError::InvalidPciDeviceId(pci::NUM_DEVICE_IDS + 1))
|
Err(ValidationError::InvalidPciDeviceId(pci::NUM_DEVICE_IDS + 1))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Invalid balloon BDF - Same ID as Root device
|
||||||
|
let mut invalid_config = valid_config.clone();
|
||||||
|
invalid_config.balloon = Some(BalloonConfig {
|
||||||
|
pci_common: PciDeviceCommonConfig {
|
||||||
|
pci_device_id: Some(pci::PCI_ROOT_DEVICE_ID),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
size: 0,
|
||||||
|
deflate_on_oom: false,
|
||||||
|
free_page_reporting: false,
|
||||||
|
});
|
||||||
|
assert_eq!(
|
||||||
|
invalid_config.validate(),
|
||||||
|
Err(ValidationError::ReservedPciDeviceId(
|
||||||
|
pci::PCI_ROOT_DEVICE_ID
|
||||||
|
))
|
||||||
|
);
|
||||||
|
|
||||||
|
// Invalid balloon ID - Duplicate identifier
|
||||||
|
let mut invalid_config = valid_config.clone();
|
||||||
|
invalid_config.balloon = Some(BalloonConfig {
|
||||||
|
pci_common: PciDeviceCommonConfig {
|
||||||
|
id: Some("test0".to_string()),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
size: 0,
|
||||||
|
deflate_on_oom: false,
|
||||||
|
free_page_reporting: false,
|
||||||
|
});
|
||||||
|
invalid_config.disks = Some(vec![DiskConfig {
|
||||||
|
pci_common: PciDeviceCommonConfig {
|
||||||
|
id: Some("test0".to_string()),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
..disk_fixture()
|
||||||
|
}]);
|
||||||
|
assert_eq!(
|
||||||
|
invalid_config.validate(),
|
||||||
|
Err(ValidationError::IdentifierNotUnique("test0".to_string()))
|
||||||
|
);
|
||||||
|
|
||||||
// Invalid console BDF - Same ID as Root device
|
// Invalid console BDF - Same ID as Root device
|
||||||
let mut invalid_config = valid_config.clone();
|
let mut invalid_config = valid_config.clone();
|
||||||
invalid_config.console.pci_common.pci_device_id = Some(pci::PCI_ROOT_DEVICE_ID);
|
invalid_config.console.pci_common.pci_device_id = Some(pci::PCI_ROOT_DEVICE_ID);
|
||||||
|
|||||||
@@ -3664,8 +3664,16 @@ impl DeviceManager {
|
|||||||
&mut self,
|
&mut self,
|
||||||
snapshot: Option<&Snapshot>,
|
snapshot: Option<&Snapshot>,
|
||||||
) -> DeviceManagerResult<()> {
|
) -> DeviceManagerResult<()> {
|
||||||
if let Some(balloon_config) = &self.config.lock().unwrap().balloon {
|
let mut balloon_config = self.config.lock().unwrap().balloon.clone();
|
||||||
let id = String::from(BALLOON_DEVICE_NAME);
|
if let Some(balloon_config) = &mut balloon_config {
|
||||||
|
let id = match balloon_config.pci_common.id.as_ref() {
|
||||||
|
Some(id) => id.clone(),
|
||||||
|
None => balloon_config
|
||||||
|
.pci_common
|
||||||
|
.id
|
||||||
|
.insert(BALLOON_DEVICE_NAME.to_string())
|
||||||
|
.clone(),
|
||||||
|
};
|
||||||
info!("Creating virtio-balloon device: id = {id}");
|
info!("Creating virtio-balloon device: id = {id}");
|
||||||
|
|
||||||
let virtio_balloon_device = Arc::new(Mutex::new(
|
let virtio_balloon_device = Arc::new(Mutex::new(
|
||||||
@@ -3674,7 +3682,7 @@ impl DeviceManager {
|
|||||||
balloon_config.size,
|
balloon_config.size,
|
||||||
balloon_config.deflate_on_oom,
|
balloon_config.deflate_on_oom,
|
||||||
balloon_config.free_page_reporting,
|
balloon_config.free_page_reporting,
|
||||||
self.force_access_platform,
|
self.force_access_platform | balloon_config.pci_common.iommu,
|
||||||
self.seccomp_action.clone(),
|
self.seccomp_action.clone(),
|
||||||
self.exit_evt
|
self.exit_evt
|
||||||
.try_clone()
|
.try_clone()
|
||||||
@@ -3690,10 +3698,7 @@ impl DeviceManager {
|
|||||||
self.virtio_devices.push(MetaVirtioDevice {
|
self.virtio_devices.push(MetaVirtioDevice {
|
||||||
virtio_device: Arc::clone(&virtio_balloon_device)
|
virtio_device: Arc::clone(&virtio_balloon_device)
|
||||||
as Arc<Mutex<dyn virtio_devices::VirtioDevice>>,
|
as Arc<Mutex<dyn virtio_devices::VirtioDevice>>,
|
||||||
pci_common: PciDeviceCommonConfig {
|
pci_common: balloon_config.pci_common.clone(),
|
||||||
id: Some(id.clone()),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
dma_handler: None,
|
dma_handler: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -535,6 +535,8 @@ impl ApplyLandlock for RngConfig {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub struct BalloonConfig {
|
pub struct BalloonConfig {
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub pci_common: PciDeviceCommonConfig,
|
||||||
pub size: u64,
|
pub size: u64,
|
||||||
/// Option to deflate the balloon in case the guest is out of memory.
|
/// Option to deflate the balloon in case the guest is out of memory.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
|||||||
Reference in New Issue
Block a user