diff --git a/src/libs/kata-types/src/config/hypervisor/qemu.rs b/src/libs/kata-types/src/config/hypervisor/qemu.rs index 8d6984b283..36a7cbf82f 100644 --- a/src/libs/kata-types/src/config/hypervisor/qemu.rs +++ b/src/libs/kata-types/src/config/hypervisor/qemu.rs @@ -118,9 +118,12 @@ impl ConfigPlugin for QemuConfig { return Err(eother!("Guest kernel image for qemu is empty")); } if qemu.boot_info.image.is_empty() && qemu.boot_info.initrd.is_empty() { - return Err(eother!( - "Both guest boot image and initrd for qemu are empty" - )); + // IBM SE (CCW + confidential guest) does not require neither image nor initrd. + if !(qemu.boot_info.vm_rootfs_driver.ends_with("ccw") && qemu.security_info.confidential_guest) { + return Err(eother!( + "Both guest boot image and initrd for qemu are empty" + )); + } } if (qemu.cpu_info.default_vcpus > 0 diff --git a/src/runtime-rs/crates/hypervisor/src/device/driver/protection_device.rs b/src/runtime-rs/crates/hypervisor/src/device/driver/protection_device.rs index 17e51a5724..d183cf477c 100644 --- a/src/runtime-rs/crates/hypervisor/src/device/driver/protection_device.rs +++ b/src/runtime-rs/crates/hypervisor/src/device/driver/protection_device.rs @@ -13,6 +13,7 @@ use async_trait::async_trait; #[derive(Debug, Clone)] pub enum ProtectionDeviceConfig { SevSnp(SevSnpConfig), + Se, } #[derive(Debug, Clone)] diff --git a/src/runtime-rs/crates/hypervisor/src/qemu/cmdline_generator.rs b/src/runtime-rs/crates/hypervisor/src/qemu/cmdline_generator.rs index cfab9de84c..4695da4a0b 100644 --- a/src/runtime-rs/crates/hypervisor/src/qemu/cmdline_generator.rs +++ b/src/runtime-rs/crates/hypervisor/src/qemu/cmdline_generator.rs @@ -1740,6 +1740,28 @@ impl ToQemuParams for ObjectIoThread { } } +#[derive(Debug)] +struct ObjectSeGuest { + id: String, +} + +impl ObjectSeGuest { + fn new(id: &str) -> Self { + ObjectSeGuest { id: id.to_owned() } + } +} + +#[async_trait] +impl ToQemuParams for ObjectSeGuest { + async fn qemu_params(&self) -> Result> { + let mut params = Vec::new(); + params.push("s390-pv-guest".to_owned()); + params.push(format!("id={}", self.id)); + + Ok(vec!["-object".to_owned(), params.join(",")]) + } +} + #[derive(Debug)] struct ObjectSevSnpGuest { id: String, @@ -2113,6 +2135,15 @@ impl<'a> QemuCmdLine<'a> { self.devices.push(Box::new(balloon_device)); } + pub fn add_se_protection_device(&mut self) { + let se_object = ObjectSeGuest::new("pv0"); + self.devices.push(Box::new(se_object)); + + self.machine + .set_confidential_guest_support("pv0") + .set_nvdimm(false); + } + pub fn add_sev_protection_device(&mut self, cbitpos: u32, firmware: &str) { let sev_object = ObjectSevSnpGuest::new(false, cbitpos); self.devices.push(Box::new(sev_object)); diff --git a/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs b/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs index b881352763..99e89e838e 100644 --- a/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs +++ b/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs @@ -141,6 +141,7 @@ impl QemuInner { ) } } + ProtectionDeviceConfig::Se => cmdline.add_se_protection_device(), }, _ => info!(sl!(), "qemu cmdline: unsupported device: {:?}", device), } diff --git a/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs b/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs index c95c87daa5..08d6ed2a86 100644 --- a/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs +++ b/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs @@ -273,13 +273,18 @@ impl VirtSandbox { async fn prepare_rootfs_config(&self) -> Result> { let boot_info = self.hypervisor.hypervisor_config().await.boot_info; + let security_info = self.hypervisor.hypervisor_config().await.security_info; if !boot_info.initrd.is_empty() { return Ok(None); } if boot_info.image.is_empty() { - return Err(anyhow!("both of image and initrd isn't set")); + if boot_info.vm_rootfs_driver.ends_with("ccw") && security_info.confidential_guest { + return Ok(None); + } else { + return Err(anyhow!("both of image and initrd isn't set")); + } } Ok(Some(BlockConfig { @@ -367,6 +372,9 @@ impl VirtSandbox { certs_path, }))) } + GuestProtection::Se => { + Ok(Some(ProtectionDeviceConfig::Se)) + } _ => Err(anyhow!("confidential_guest requested by configuration but no supported protection available")) } }