mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-05-03 05:57:25 +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::VmConfig;
|
||||||
use crate::{
|
use crate::{
|
||||||
ConsoleConfig, ConsoleOutputMode, CpuFeatures, CpuTopology, CpusConfig, MacAddr, MemoryConfig,
|
ConsoleConfig, ConsoleOutputMode, CpuFeatures, CpuTopology, CpusConfig, MacAddr, MemoryConfig,
|
||||||
PayloadConfig, RngConfig, VsockConfig,
|
PayloadConfig, PmemConfig, RngConfig, VsockConfig,
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use kata_types::config::default::DEFAULT_CH_ENTROPY_SOURCE;
|
use kata_types::config::default::DEFAULT_CH_ENTROPY_SOURCE;
|
||||||
@ -20,6 +20,8 @@ use std::path::PathBuf;
|
|||||||
// 1 MiB
|
// 1 MiB
|
||||||
const MIB: u64 = 1024 * 1024;
|
const MIB: u64 = 1024 * 1024;
|
||||||
|
|
||||||
|
const PMEM_ALIGN_BYTES: u64 = 2 * MIB;
|
||||||
|
|
||||||
const DEFAULT_CH_MAX_PHYS_BITS: u8 = 46;
|
const DEFAULT_CH_MAX_PHYS_BITS: u8 = 46;
|
||||||
|
|
||||||
impl TryFrom<NamedHypervisorConfig> for VmConfig {
|
impl TryFrom<NamedHypervisorConfig> for VmConfig {
|
||||||
@ -31,14 +33,42 @@ impl TryFrom<NamedHypervisorConfig> for VmConfig {
|
|||||||
let vsock_socket_path = n.vsock_socket_path;
|
let vsock_socket_path = n.vsock_socket_path;
|
||||||
let sandbox_path = n.sandbox_path;
|
let sandbox_path = n.sandbox_path;
|
||||||
let fs = n.shared_fs_devices;
|
let fs = n.shared_fs_devices;
|
||||||
let pmem = n.pmem_devices;
|
|
||||||
|
|
||||||
let cpus = CpusConfig::try_from(cfg.cpu_info)?;
|
let cpus = CpusConfig::try_from(cfg.cpu_info)?;
|
||||||
|
|
||||||
let rng = RngConfig::try_from(cfg.machine_info)?;
|
let rng = RngConfig::try_from(cfg.machine_info)?;
|
||||||
|
|
||||||
// Note that PmemConfig replaces the PayloadConfig.initrd.
|
// Note how CH handles the different image types:
|
||||||
let payload = PayloadConfig::try_from((cfg.boot_info, kernel_params))?;
|
//
|
||||||
|
// - 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 serial = get_serial_cfg()?;
|
||||||
let console = get_console_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")
|
.ok_or("failed to calculate max hotplug size for CH")
|
||||||
.map_err(|e| anyhow!(e))?;
|
.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 {
|
let cfg = MemoryConfig {
|
||||||
size: mem_bytes,
|
size: mem_bytes,
|
||||||
|
|
||||||
// Required
|
// Required
|
||||||
shared: true,
|
shared: true,
|
||||||
|
|
||||||
hotplug_size: Some(hotplug_size_bytes),
|
hotplug_size: Some(aligned_hotplug_size_bytes),
|
||||||
|
|
||||||
..Default::default()
|
..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 {
|
impl TryFrom<CpuInfo> for CpusConfig {
|
||||||
type Error = anyhow::Error;
|
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 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
|
// This cannot be created only from BootInfo since that contains the
|
||||||
// user-specified kernel parameters only.
|
// user-specified kernel parameters only.
|
||||||
impl TryFrom<(BootInfo, String)> for PayloadConfig {
|
impl TryFrom<(BootInfo, String, Option<PathBuf>)> for PayloadConfig {
|
||||||
type Error = anyhow::Error;
|
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 b = args.0;
|
||||||
let cmdline = args.1;
|
let cmdline = args.1;
|
||||||
|
let initramfs = args.2;
|
||||||
|
|
||||||
let kernel = PathBuf::from(b.kernel);
|
let kernel = PathBuf::from(b.kernel);
|
||||||
|
|
||||||
let payload = PayloadConfig {
|
let payload = PayloadConfig {
|
||||||
kernel: Some(kernel),
|
kernel: Some(kernel),
|
||||||
cmdline: Some(cmdline),
|
cmdline: Some(cmdline),
|
||||||
|
initramfs,
|
||||||
|
|
||||||
..Default::default()
|
..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> {
|
fn get_serial_cfg() -> Result<ConsoleConfig> {
|
||||||
let cfg = ConsoleConfig {
|
let cfg = ConsoleConfig {
|
||||||
file: None,
|
file: None,
|
||||||
|
@ -492,5 +492,4 @@ pub struct NamedHypervisorConfig {
|
|||||||
pub cfg: HypervisorConfig,
|
pub cfg: HypervisorConfig,
|
||||||
|
|
||||||
pub shared_fs_devices: Option<Vec<FsConfig>>,
|
pub shared_fs_devices: Option<Vec<FsConfig>>,
|
||||||
pub pmem_devices: Option<Vec<PmemConfig>>,
|
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ use crate::HybridVsockConfig;
|
|||||||
use crate::VmmState;
|
use crate::VmmState;
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use ch_config::ch_api::cloud_hypervisor_vm_fs_add;
|
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 safe_path::scoped_join;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@ -148,41 +148,6 @@ impl CloudHypervisorInner {
|
|||||||
Ok(None)
|
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)]
|
#[derive(Debug)]
|
||||||
|
@ -96,8 +96,6 @@ impl CloudHypervisorInner {
|
|||||||
async fn boot_vm(&mut self) -> Result<()> {
|
async fn boot_vm(&mut self) -> Result<()> {
|
||||||
let shared_fs_devices = self.get_shared_fs_devices().await?;
|
let shared_fs_devices = self.get_shared_fs_devices().await?;
|
||||||
|
|
||||||
let pmem_devices = self.get_pmem_devices().await?;
|
|
||||||
|
|
||||||
let socket = self
|
let socket = self
|
||||||
.api_socket
|
.api_socket
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@ -129,7 +127,6 @@ impl CloudHypervisorInner {
|
|||||||
vsock_socket_path,
|
vsock_socket_path,
|
||||||
cfg: hypervisor_config.clone(),
|
cfg: hypervisor_config.clone(),
|
||||||
shared_fs_devices,
|
shared_fs_devices,
|
||||||
pmem_devices,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let cfg = VmConfig::try_from(named_cfg)?;
|
let cfg = VmConfig::try_from(named_cfg)?;
|
||||||
|
Loading…
Reference in New Issue
Block a user