diff --git a/src/runtime-rs/crates/hypervisor/src/device/device_manager.rs b/src/runtime-rs/crates/hypervisor/src/device/device_manager.rs index e5ec6276f5..83bed0ce3f 100644 --- a/src/runtime-rs/crates/hypervisor/src/device/device_manager.rs +++ b/src/runtime-rs/crates/hypervisor/src/device/device_manager.rs @@ -14,8 +14,8 @@ use tokio::sync::{Mutex, RwLock}; use crate::{ vhost_user_blk::VhostUserBlkDevice, BlockConfig, BlockDevice, HybridVsockDevice, Hypervisor, NetworkDevice, ShareFsDevice, VfioDevice, VhostUserConfig, VhostUserNetDevice, VsockDevice, - KATA_BLK_DEV_TYPE, KATA_MMIO_BLK_DEV_TYPE, KATA_NVDIMM_DEV_TYPE, VIRTIO_BLOCK_MMIO, - VIRTIO_BLOCK_PCI, VIRTIO_PMEM, + KATA_BLK_DEV_TYPE, KATA_CCW_DEV_TYPE, KATA_MMIO_BLK_DEV_TYPE, KATA_NVDIMM_DEV_TYPE, + VIRTIO_BLOCK_CCW, VIRTIO_BLOCK_MMIO, VIRTIO_BLOCK_PCI, VIRTIO_PMEM, }; use super::{ @@ -447,6 +447,9 @@ impl DeviceManager { VIRTIO_BLOCK_PCI => { block_config.driver_option = KATA_BLK_DEV_TYPE.to_string(); } + VIRTIO_BLOCK_CCW => { + block_config.driver_option = KATA_CCW_DEV_TYPE.to_string(); + } VIRTIO_PMEM => { block_config.driver_option = KATA_NVDIMM_DEV_TYPE.to_string(); is_pmem = true; diff --git a/src/runtime-rs/crates/hypervisor/src/device/driver/mod.rs b/src/runtime-rs/crates/hypervisor/src/device/driver/mod.rs index f30070b355..6b6d23c839 100644 --- a/src/runtime-rs/crates/hypervisor/src/device/driver/mod.rs +++ b/src/runtime-rs/crates/hypervisor/src/device/driver/mod.rs @@ -20,8 +20,8 @@ pub use vfio::{ pub use vhost_user::{VhostUserConfig, VhostUserDevice, VhostUserType}; pub use vhost_user_net::VhostUserNetDevice; pub use virtio_blk::{ - BlockConfig, BlockDevice, KATA_BLK_DEV_TYPE, KATA_MMIO_BLK_DEV_TYPE, KATA_NVDIMM_DEV_TYPE, - VIRTIO_BLOCK_MMIO, VIRTIO_BLOCK_PCI, VIRTIO_PMEM, + BlockConfig, BlockDevice, KATA_BLK_DEV_TYPE, KATA_CCW_DEV_TYPE, KATA_MMIO_BLK_DEV_TYPE, + KATA_NVDIMM_DEV_TYPE, VIRTIO_BLOCK_CCW, VIRTIO_BLOCK_MMIO, VIRTIO_BLOCK_PCI, VIRTIO_PMEM, }; pub use virtio_fs::{ ShareFsConfig, ShareFsDevice, ShareFsMountConfig, ShareFsMountOperation, ShareFsMountType, diff --git a/src/runtime-rs/crates/hypervisor/src/device/driver/virtio_blk.rs b/src/runtime-rs/crates/hypervisor/src/device/driver/virtio_blk.rs index 50d8179200..fdf0f7ea2d 100644 --- a/src/runtime-rs/crates/hypervisor/src/device/driver/virtio_blk.rs +++ b/src/runtime-rs/crates/hypervisor/src/device/driver/virtio_blk.rs @@ -15,9 +15,11 @@ use async_trait::async_trait; /// VIRTIO_BLOCK_PCI indicates block driver is virtio-pci based pub const VIRTIO_BLOCK_PCI: &str = "virtio-blk-pci"; pub const VIRTIO_BLOCK_MMIO: &str = "virtio-blk-mmio"; +pub const VIRTIO_BLOCK_CCW: &str = "virtio-blk-ccw"; pub const VIRTIO_PMEM: &str = "virtio-pmem"; pub const KATA_MMIO_BLK_DEV_TYPE: &str = "mmioblk"; pub const KATA_BLK_DEV_TYPE: &str = "blk"; +pub const KATA_CCW_DEV_TYPE: &str = "ccw"; pub const KATA_NVDIMM_DEV_TYPE: &str = "nvdimm"; #[derive(Debug, Clone, Default)] 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 123bff82c9..447049f351 100644 --- a/src/runtime-rs/crates/hypervisor/src/qemu/cmdline_generator.rs +++ b/src/runtime-rs/crates/hypervisor/src/qemu/cmdline_generator.rs @@ -651,6 +651,154 @@ impl ToQemuParams for DeviceNvdimm { } } +#[derive(Debug)] +struct BlockBackend { + driver: String, + id: String, + path: String, + aio: String, + cache_direct: bool, + cache_no_flush: bool, + read_only: bool, +} + +impl BlockBackend { + fn new(id: &str, path: &str) -> BlockBackend { + BlockBackend { + driver: "file".to_owned(), + id: id.to_owned(), + path: path.to_owned(), + aio: "threads".to_owned(), + cache_direct: true, + cache_no_flush: false, + read_only: true, + } + } + + #[allow(dead_code)] + fn set_driver(&mut self, driver: &str) -> &mut Self { + self.driver = driver.to_owned(); + self + } + + #[allow(dead_code)] + fn set_aio(&mut self, aio: &str) -> &mut Self { + self.aio = aio.to_owned(); + self + } + + #[allow(dead_code)] + fn set_cache_direct(&mut self, cache_direct: bool) -> &mut Self { + self.cache_direct = cache_direct; + self + } + + #[allow(dead_code)] + fn set_cache_no_flush(&mut self, cache_no_flush: bool) -> &mut Self { + self.cache_no_flush = cache_no_flush; + self + } + + #[allow(dead_code)] + fn set_read_only(&mut self, read_only: bool) -> &mut Self { + self.read_only = read_only; + self + } +} + +#[async_trait] +impl ToQemuParams for BlockBackend { + async fn qemu_params(&self) -> Result> { + let mut params = Vec::new(); + params.push(format!("driver={}", self.driver)); + params.push(format!("node-name=image-{}", self.id)); + params.push(format!("filename={}", self.path)); + params.push(format!("aio={}", self.aio)); + if self.cache_direct { + params.push("cache.direct=on".to_owned()); + } else { + params.push("cache.direct=off".to_owned()); + } + if self.cache_no_flush { + params.push("cache.no-flush=on".to_owned()); + } else { + params.push("cache.no-flush=off".to_owned()); + } + if self.read_only { + params.push("auto-read-only=on".to_owned()); + } else { + params.push("auto-read-only=off".to_owned()); + } + Ok(vec!["-blockdev".to_owned(), params.join(",")]) + } +} + +#[derive(Debug)] +struct DeviceVirtioBlk { + bus_type: VirtioBusType, + id: String, + scsi: bool, + config_wce: bool, + share_rw: bool, +} + +impl DeviceVirtioBlk { + fn new(id: &str, bus_type: VirtioBusType) -> DeviceVirtioBlk { + DeviceVirtioBlk { + bus_type, + id: id.to_owned(), + scsi: false, + config_wce: false, + share_rw: true, + } + } + + #[allow(dead_code)] + fn set_scsi(&mut self, scsi: bool) -> &mut Self { + self.scsi = scsi; + self + } + + #[allow(dead_code)] + fn set_config_wce(&mut self, config_wce: bool) -> &mut Self { + self.config_wce = config_wce; + self + } + + #[allow(dead_code)] + fn set_share_rw(&mut self, share_rw: bool) -> &mut Self { + self.share_rw = share_rw; + self + } +} + +#[async_trait] +impl ToQemuParams for DeviceVirtioBlk { + async fn qemu_params(&self) -> Result> { + let mut params = Vec::new(); + params.push(format!("virtio-blk-{}", self.bus_type)); + params.push(format!("drive=image-{}", self.id)); + if self.scsi { + params.push("scsi=on".to_owned()); + } else { + params.push("scsi=off".to_owned()); + } + if self.config_wce { + params.push("config-wce=on".to_owned()); + } else { + params.push("config-wce=off".to_owned()); + } + if self.share_rw { + params.push("share-rw=on".to_owned()); + } else { + params.push("share-rw=off".to_owned()); + } + params.push(format!("serial=image-{}", self.id)); + + Ok(vec!["-device".to_owned(), params.join(",")]) + } +} + struct VhostVsock { bus_type: VirtioBusType, vhostfd: RawFd, @@ -894,6 +1042,14 @@ impl<'a> QemuCmdLine<'a> { Ok(()) } + pub fn add_block_device(&mut self, device_id: &str, path: &str) -> Result<()> { + self.devices + .push(Box::new(BlockBackend::new(device_id, path))); + self.devices + .push(Box::new(DeviceVirtioBlk::new(device_id, self.bus_type()))); + Ok(()) + } + #[allow(dead_code)] pub fn add_serial_console(&mut self, character_device_file_path: &str) { let serial = Serial::new(character_device_file_path); diff --git a/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs b/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs index 3d6d47526b..23c9bc7ab8 100644 --- a/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs +++ b/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs @@ -103,6 +103,10 @@ impl QemuInner { &block_dev.config.path_on_host, block_dev.config.is_readonly, )?, + "ccw" => cmdline.add_block_device( + block_dev.device_id.as_str(), + &block_dev.config.path_on_host, + )?, unsupported => { info!(sl!(), "unsupported block device driver: {}", unsupported) }