mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-05-02 13:44:33 +00:00
runtime-rs: ch: Enable initrd usage
Allow an initrd/initramfs image to be used with Cloud Hypervisor, which is handled differently to the default rootfs image type. Fixes: #6335. Signed-off-by: James O. D. Hunt <james.o.hunt@intel.com>
This commit is contained in:
parent
fbee6c820e
commit
3483272bbd
@ -7,7 +7,7 @@ use crate::NamedHypervisorConfig;
|
||||
use crate::VmConfig;
|
||||
use crate::{
|
||||
ConsoleConfig, ConsoleOutputMode, CpuFeatures, CpuTopology, CpusConfig, MacAddr, MemoryConfig,
|
||||
PayloadConfig, RngConfig, VsockConfig,
|
||||
PayloadConfig, PmemConfig, RngConfig, VsockConfig,
|
||||
};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use kata_types::config::default::DEFAULT_CH_ENTROPY_SOURCE;
|
||||
@ -20,6 +20,8 @@ use std::path::PathBuf;
|
||||
// 1 MiB
|
||||
const MIB: u64 = 1024 * 1024;
|
||||
|
||||
const PMEM_ALIGN_BYTES: u64 = 2 * MIB;
|
||||
|
||||
const DEFAULT_CH_MAX_PHYS_BITS: u8 = 46;
|
||||
|
||||
impl TryFrom<NamedHypervisorConfig> for VmConfig {
|
||||
@ -31,14 +33,42 @@ impl TryFrom<NamedHypervisorConfig> for VmConfig {
|
||||
let vsock_socket_path = n.vsock_socket_path;
|
||||
let sandbox_path = n.sandbox_path;
|
||||
let fs = n.shared_fs_devices;
|
||||
let pmem = n.pmem_devices;
|
||||
|
||||
let cpus = CpusConfig::try_from(cfg.cpu_info)?;
|
||||
|
||||
let rng = RngConfig::try_from(cfg.machine_info)?;
|
||||
|
||||
// Note that PmemConfig replaces the PayloadConfig.initrd.
|
||||
let payload = PayloadConfig::try_from((cfg.boot_info, kernel_params))?;
|
||||
// Note how CH handles the different image types:
|
||||
//
|
||||
// - An image is specified in PmemConfig.
|
||||
// - An initrd/initramfs is specified in PayloadConfig.
|
||||
let boot_info = cfg.boot_info;
|
||||
|
||||
let use_initrd = !boot_info.initrd.is_empty();
|
||||
let use_image = !boot_info.image.is_empty();
|
||||
|
||||
if use_initrd && use_image {
|
||||
return Err(anyhow!("cannot specify image and initrd"));
|
||||
}
|
||||
|
||||
if !use_initrd && !use_image {
|
||||
return Err(anyhow!("missing boot file (no image or initrd)"));
|
||||
}
|
||||
|
||||
let initrd = if use_initrd {
|
||||
Some(PathBuf::from(boot_info.initrd.clone()))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let pmem = if use_initrd {
|
||||
None
|
||||
} else {
|
||||
let pmem = PmemConfig::try_from(&boot_info)?;
|
||||
Some(vec![pmem])
|
||||
};
|
||||
|
||||
let payload = PayloadConfig::try_from((boot_info, kernel_params, initrd))?;
|
||||
|
||||
let serial = get_serial_cfg()?;
|
||||
let console = get_console_cfg()?;
|
||||
@ -90,13 +120,18 @@ impl TryFrom<MemoryInfo> for MemoryConfig {
|
||||
.ok_or("failed to calculate max hotplug size for CH")
|
||||
.map_err(|e| anyhow!(e))?;
|
||||
|
||||
let aligned_hotplug_size_bytes =
|
||||
checked_next_multiple_of(hotplug_size_bytes, PMEM_ALIGN_BYTES)
|
||||
.ok_or("cannot handle pmem alignment for CH")
|
||||
.map_err(|e| anyhow!(e))?;
|
||||
|
||||
let cfg = MemoryConfig {
|
||||
size: mem_bytes,
|
||||
|
||||
// Required
|
||||
shared: true,
|
||||
|
||||
hotplug_size: Some(hotplug_size_bytes),
|
||||
hotplug_size: Some(aligned_hotplug_size_bytes),
|
||||
|
||||
..Default::default()
|
||||
};
|
||||
@ -105,6 +140,20 @@ impl TryFrom<MemoryInfo> for MemoryConfig {
|
||||
}
|
||||
}
|
||||
|
||||
// Return the next multiple of 'multiple' starting from the specified value
|
||||
// (aka align value to multiple).
|
||||
//
|
||||
// This is a temporary solution until checked_next_multiple_of() integer
|
||||
// method is available in the rust language.
|
||||
//
|
||||
// See: https://github.com/rust-lang/rust/issues/88581
|
||||
fn checked_next_multiple_of(value: u64, multiple: u64) -> Option<u64> {
|
||||
match value.checked_rem(multiple) {
|
||||
None => Some(value),
|
||||
Some(r) => value.checked_add(multiple - r),
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<CpuInfo> for CpusConfig {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
@ -153,20 +202,23 @@ impl TryFrom<String> for CpuFeatures {
|
||||
}
|
||||
|
||||
// The 2nd tuple element is the space separated kernel parameters list.
|
||||
// The 3rd tuple element is an optional initramfs image to use.
|
||||
// This cannot be created only from BootInfo since that contains the
|
||||
// user-specified kernel parameters only.
|
||||
impl TryFrom<(BootInfo, String)> for PayloadConfig {
|
||||
impl TryFrom<(BootInfo, String, Option<PathBuf>)> for PayloadConfig {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(args: (BootInfo, String)) -> Result<Self, Self::Error> {
|
||||
fn try_from(args: (BootInfo, String, Option<PathBuf>)) -> Result<Self, Self::Error> {
|
||||
let b = args.0;
|
||||
let cmdline = args.1;
|
||||
let initramfs = args.2;
|
||||
|
||||
let kernel = PathBuf::from(b.kernel);
|
||||
|
||||
let payload = PayloadConfig {
|
||||
kernel: Some(kernel),
|
||||
cmdline: Some(cmdline),
|
||||
initramfs,
|
||||
|
||||
..Default::default()
|
||||
};
|
||||
@ -195,6 +247,27 @@ impl TryFrom<MachineInfo> for RngConfig {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&BootInfo> for PmemConfig {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(b: &BootInfo) -> Result<Self, Self::Error> {
|
||||
let file = if b.image.is_empty() {
|
||||
return Err(anyhow!("CH PmemConfig only used for images"));
|
||||
} else {
|
||||
b.image.clone()
|
||||
};
|
||||
|
||||
let cfg = PmemConfig {
|
||||
file: PathBuf::from(file),
|
||||
discard_writes: true,
|
||||
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
Ok(cfg)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_serial_cfg() -> Result<ConsoleConfig> {
|
||||
let cfg = ConsoleConfig {
|
||||
file: None,
|
||||
|
@ -492,5 +492,4 @@ pub struct NamedHypervisorConfig {
|
||||
pub cfg: HypervisorConfig,
|
||||
|
||||
pub shared_fs_devices: Option<Vec<FsConfig>>,
|
||||
pub pmem_devices: Option<Vec<PmemConfig>>,
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ use crate::HybridVsockConfig;
|
||||
use crate::VmmState;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use ch_config::ch_api::cloud_hypervisor_vm_fs_add;
|
||||
use ch_config::{FsConfig, PmemConfig};
|
||||
use ch_config::FsConfig;
|
||||
use safe_path::scoped_join;
|
||||
use std::convert::TryFrom;
|
||||
use std::path::PathBuf;
|
||||
@ -148,41 +148,6 @@ impl CloudHypervisorInner {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn get_boot_file(&mut self) -> Result<PathBuf> {
|
||||
if let Some(ref config) = self.config {
|
||||
let boot_info = &config.boot_info;
|
||||
|
||||
let file = if !boot_info.initrd.is_empty() {
|
||||
boot_info.initrd.clone()
|
||||
} else if !boot_info.image.is_empty() {
|
||||
boot_info.image.clone()
|
||||
} else {
|
||||
return Err(anyhow!("missing boot file (no image or initrd)"));
|
||||
};
|
||||
|
||||
Ok(PathBuf::from(file))
|
||||
} else {
|
||||
Err(anyhow!("no hypervisor config"))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn get_pmem_devices(&mut self) -> Result<Option<Vec<PmemConfig>>> {
|
||||
let file = self.get_boot_file().await?;
|
||||
|
||||
let pmem_cfg = PmemConfig {
|
||||
file,
|
||||
size: None,
|
||||
iommu: false,
|
||||
discard_writes: true,
|
||||
id: None,
|
||||
pci_segment: 0,
|
||||
};
|
||||
|
||||
let pmem_devices = vec![pmem_cfg];
|
||||
|
||||
Ok(Some(pmem_devices))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -96,8 +96,6 @@ impl CloudHypervisorInner {
|
||||
async fn boot_vm(&mut self) -> Result<()> {
|
||||
let shared_fs_devices = self.get_shared_fs_devices().await?;
|
||||
|
||||
let pmem_devices = self.get_pmem_devices().await?;
|
||||
|
||||
let socket = self
|
||||
.api_socket
|
||||
.as_ref()
|
||||
@ -129,7 +127,6 @@ impl CloudHypervisorInner {
|
||||
vsock_socket_path,
|
||||
cfg: hypervisor_config.clone(),
|
||||
shared_fs_devices,
|
||||
pmem_devices,
|
||||
};
|
||||
|
||||
let cfg = VmConfig::try_from(named_cfg)?;
|
||||
|
Loading…
Reference in New Issue
Block a user