mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
devices: Add fw_cfg cli options
This allows us to enable/disable the fw_cfg device via the cli We can also now upload files into the guest vm using fw_cfg_items via the cli Signed-off-by: Alex Orozco <alexorozco@google.com>
This commit is contained in:
+132
-74
@@ -34,6 +34,8 @@ use arch::PciSpaceInfo;
|
||||
use arch::{get_host_cpu_phys_bits, EntryPoint, NumaNode, NumaNodes};
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use devices::interrupt_controller;
|
||||
#[cfg(feature = "fw_cfg")]
|
||||
use devices::legacy::fw_cfg::FwCfgItem;
|
||||
use devices::AcpiNotificationFlags;
|
||||
#[cfg(all(target_arch = "aarch64", feature = "guest_debug"))]
|
||||
use gdbstub_arch::aarch64::reg::AArch64CoreRegs as CoreRegs;
|
||||
@@ -91,6 +93,8 @@ use crate::migration::get_vm_snapshot;
|
||||
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
|
||||
use crate::migration::url_to_file;
|
||||
use crate::migration::{url_to_path, SNAPSHOT_CONFIG_FILE, SNAPSHOT_STATE_FILE};
|
||||
#[cfg(feature = "fw_cfg")]
|
||||
use crate::vm_config::FwCfgConfig;
|
||||
use crate::vm_config::{
|
||||
DeviceConfig, DiskConfig, FsConfig, HotplugMethod, NetConfig, NumaConfig, PayloadConfig,
|
||||
PmemConfig, UserDeviceConfig, VdpaConfig, VmConfig, VsockConfig,
|
||||
@@ -359,6 +363,18 @@ pub enum Error {
|
||||
#[cfg(feature = "fw_cfg")]
|
||||
#[error("Error creating acpi tables")]
|
||||
CreatingAcpiTables(#[source] io::Error),
|
||||
|
||||
#[cfg(feature = "fw_cfg")]
|
||||
#[error("Error adding fw_cfg item")]
|
||||
AddingFwCfgItem(#[source] io::Error),
|
||||
|
||||
#[cfg(feature = "fw_cfg")]
|
||||
#[error("Error populating fw_cfg")]
|
||||
ErrorPopulatingFwCfg(#[source] io::Error),
|
||||
|
||||
#[cfg(feature = "fw_cfg")]
|
||||
#[error("Error using fw_cfg while disabled")]
|
||||
FwCfgDisabled,
|
||||
}
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
@@ -741,11 +757,22 @@ impl Vm {
|
||||
}
|
||||
|
||||
#[cfg(feature = "fw_cfg")]
|
||||
device_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
.create_fw_cfg_device()
|
||||
.map_err(Error::DeviceManager)?;
|
||||
{
|
||||
let fw_cfg_config = config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.payload
|
||||
.as_ref()
|
||||
.map(|p| p.fw_cfg_config.is_some())
|
||||
.unwrap_or(false);
|
||||
if fw_cfg_config {
|
||||
device_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
.create_fw_cfg_device()
|
||||
.map_err(Error::DeviceManager)?;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "tdx")]
|
||||
let kernel = config
|
||||
@@ -806,76 +833,85 @@ impl Vm {
|
||||
|
||||
#[cfg(feature = "fw_cfg")]
|
||||
fn populate_fw_cfg(
|
||||
fw_cfg_config: &FwCfgConfig,
|
||||
device_manager: &Arc<Mutex<DeviceManager>>,
|
||||
config: &Arc<Mutex<VmConfig>>,
|
||||
) -> Result<()> {
|
||||
device_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
.fw_cfg()
|
||||
.expect("fw_cfg device must be present")
|
||||
.lock()
|
||||
.unwrap()
|
||||
.add_e820(config.lock().unwrap().memory.size as usize)
|
||||
.map_err(Error::CreatingE820Map)?;
|
||||
let kernel = config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.payload
|
||||
.as_ref()
|
||||
.map(|p| p.kernel.as_ref().map(File::open))
|
||||
.unwrap_or_default()
|
||||
.transpose()
|
||||
.map_err(Error::MissingFwCfgKernelFile)?;
|
||||
if let Some(kernel_file) = kernel {
|
||||
device_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
.fw_cfg()
|
||||
.expect("fw_cfg device must be present")
|
||||
.lock()
|
||||
.unwrap()
|
||||
.add_kernel_data(&kernel_file)
|
||||
.map_err(Error::MissingFwCfgKernelFile)?
|
||||
let mut e820_option: Option<usize> = None;
|
||||
if fw_cfg_config.e820 {
|
||||
e820_option = Some(config.lock().unwrap().memory.size as usize);
|
||||
}
|
||||
let cmdline = Vm::generate_cmdline(
|
||||
config.lock().unwrap().payload.as_ref().unwrap(),
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
device_manager,
|
||||
)
|
||||
.map_err(|_| Error::MissingFwCfgCmdline)?
|
||||
.as_cstring()
|
||||
.map_err(|_| Error::MissingFwCfgCmdline)?;
|
||||
device_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
.fw_cfg()
|
||||
.expect("fw_cfg device must be present")
|
||||
.lock()
|
||||
.unwrap()
|
||||
.add_kernel_cmdline(cmdline);
|
||||
let initramfs = config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.payload
|
||||
.as_ref()
|
||||
.map(|p| p.initramfs.as_ref().map(File::open))
|
||||
.unwrap_or_default()
|
||||
.transpose()
|
||||
.map_err(Error::MissingFwCfgInitramfs)?;
|
||||
// We measure the initramfs when running Oak Containers in SNP mode (initramfs = Stage1)
|
||||
// o/w use Stage0 to launch cloud disk images
|
||||
if let Some(initramfs_file) = initramfs {
|
||||
device_manager
|
||||
let mut kernel_option: Option<File> = None;
|
||||
if fw_cfg_config.kernel {
|
||||
let kernel = config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.fw_cfg()
|
||||
.expect("fw_cfg device must be present")
|
||||
.payload
|
||||
.as_ref()
|
||||
.map(|p| p.kernel.as_ref().map(File::open))
|
||||
.unwrap_or_default()
|
||||
.transpose()
|
||||
.map_err(Error::MissingFwCfgKernelFile)?;
|
||||
kernel_option = kernel;
|
||||
}
|
||||
let mut cmdline_option: Option<std::ffi::CString> = None;
|
||||
if fw_cfg_config.cmdline {
|
||||
let cmdline = Vm::generate_cmdline(
|
||||
config.lock().unwrap().payload.as_ref().unwrap(),
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
device_manager,
|
||||
)
|
||||
.map_err(|_| Error::MissingFwCfgCmdline)?
|
||||
.as_cstring()
|
||||
.map_err(|_| Error::MissingFwCfgCmdline)?;
|
||||
cmdline_option = Some(cmdline);
|
||||
}
|
||||
let mut initramfs_option: Option<File> = None;
|
||||
if fw_cfg_config.initramfs {
|
||||
let initramfs = config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.add_initramfs_data(&initramfs_file)
|
||||
.payload
|
||||
.as_ref()
|
||||
.map(|p| p.initramfs.as_ref().map(File::open))
|
||||
.unwrap_or_default()
|
||||
.transpose()
|
||||
.map_err(Error::MissingFwCfgInitramfs)?;
|
||||
// We measure the initramfs when running Oak Containers in SNP mode (initramfs = Stage1)
|
||||
// o/w use Stage0 to launch cloud disk images
|
||||
initramfs_option = initramfs;
|
||||
}
|
||||
let mut fw_cfg_item_list_option: Option<Vec<FwCfgItem>> = None;
|
||||
if let Some(fw_cfg_files) = &fw_cfg_config.items {
|
||||
let mut fw_cfg_item_list = vec![];
|
||||
for fw_cfg_file in fw_cfg_files.item_list.clone() {
|
||||
fw_cfg_item_list.push(FwCfgItem {
|
||||
name: fw_cfg_file.name,
|
||||
content: devices::legacy::fw_cfg::FwCfgContent::File(
|
||||
0,
|
||||
File::open(fw_cfg_file.file).map_err(Error::AddingFwCfgItem)?,
|
||||
),
|
||||
});
|
||||
}
|
||||
fw_cfg_item_list_option = Some(fw_cfg_item_list);
|
||||
}
|
||||
|
||||
let device_manager_binding = device_manager.lock().unwrap();
|
||||
let Some(fw_cfg) = device_manager_binding.fw_cfg() else {
|
||||
return Err(Error::FwCfgDisabled);
|
||||
};
|
||||
|
||||
fw_cfg
|
||||
.lock()
|
||||
.unwrap()
|
||||
.populate_fw_cfg(
|
||||
e820_option,
|
||||
kernel_option,
|
||||
initramfs_option,
|
||||
cmdline_option,
|
||||
fw_cfg_item_list_option,
|
||||
)
|
||||
.map_err(Error::ErrorPopulatingFwCfg)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -2370,15 +2406,37 @@ impl Vm {
|
||||
|
||||
#[cfg(feature = "fw_cfg")]
|
||||
{
|
||||
Self::populate_fw_cfg(&self.device_manager, &self.config)?;
|
||||
let tpm_enabled = self.config.lock().unwrap().tpm.is_some();
|
||||
crate::acpi::create_acpi_tables_for_fw_cfg(
|
||||
&self.device_manager,
|
||||
&self.cpu_manager,
|
||||
&self.memory_manager,
|
||||
&self.numa_nodes,
|
||||
tpm_enabled,
|
||||
)?
|
||||
let fw_cfg_enabled = self
|
||||
.config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.payload
|
||||
.as_ref()
|
||||
.map(|p| p.fw_cfg_config.is_some())
|
||||
.unwrap_or(false);
|
||||
if fw_cfg_enabled {
|
||||
let fw_cfg_config = self
|
||||
.config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.payload
|
||||
.as_ref()
|
||||
.map(|p| p.fw_cfg_config.clone())
|
||||
.unwrap_or_default()
|
||||
.ok_or(Error::VmMissingConfig)?;
|
||||
Self::populate_fw_cfg(&fw_cfg_config, &self.device_manager, &self.config)?;
|
||||
|
||||
if fw_cfg_config.acpi_tables {
|
||||
let tpm_enabled = self.config.lock().unwrap().tpm.is_some();
|
||||
crate::acpi::create_acpi_tables_for_fw_cfg(
|
||||
&self.device_manager,
|
||||
&self.cpu_manager,
|
||||
&self.memory_manager,
|
||||
&self.numa_nodes,
|
||||
tpm_enabled,
|
||||
)?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do earlier to parallelise with loading kernel
|
||||
|
||||
Reference in New Issue
Block a user