dragonball: add upcall support

Upcall is a direct communication tool between VMM and guest developed
upon vsock. It is used to implement device hotplug.

Signed-off-by: Liu Jiang <gerry@linux.alibaba.com>
Signed-off-by: jingshan <jingshan@linux.alibaba.com>
Signed-off-by: Chao Wu <chaowu@linux.alibaba.com>
Signed-off-by: wllenyj <wllenyj@linux.alibaba.com>
Signed-off-by: Zizheng Bian <zizheng.bian@linux.alibaba.com>
This commit is contained in:
wllenyj 2022-05-15 00:42:42 +08:00 committed by Chao Wu
parent 7d1953b52e
commit 78c9718752
2 changed files with 103 additions and 6 deletions

View File

@ -19,6 +19,7 @@ dbs-boot = "0.2.0"
dbs-device = "0.1.0" dbs-device = "0.1.0"
dbs-interrupt = { version = "0.1.0", features = ["kvm-irq"] } dbs-interrupt = { version = "0.1.0", features = ["kvm-irq"] }
dbs-legacy-devices = "0.1.0" dbs-legacy-devices = "0.1.0"
dbs-upcall = { version = "0.1.0", optional = true }
dbs-utils = "0.1.0" dbs-utils = "0.1.0"
dbs-virtio-devices = { version = "0.1.0", optional = true, features = ["virtio-mmio"] } dbs-virtio-devices = { version = "0.1.0", optional = true, features = ["virtio-mmio"] }
kvm-bindings = "0.5.0" kvm-bindings = "0.5.0"
@ -45,12 +46,13 @@ slog-async = "2.7.0"
[features] [features]
atomic-guest-memory = [] atomic-guest-memory = []
hotplug = ["dbs-upcall", "virtio-vsock"]
virtio-vsock = ["dbs-virtio-devices/virtio-vsock", "virtio-queue"] virtio-vsock = ["dbs-virtio-devices/virtio-vsock", "virtio-queue"]
[patch.'crates-io'] [patch.'crates-io']
dbs-device = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "84eee5737cc7d85f9921c94a93e6b9dc4ae24a39" } dbs-device = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "127621db934af5ffba558e44b77afa00cdf62af6" }
dbs-interrupt = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "84eee5737cc7d85f9921c94a93e6b9dc4ae24a39" } dbs-interrupt = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "127621db934af5ffba558e44b77afa00cdf62af6" }
dbs-legacy-devices = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "84eee5737cc7d85f9921c94a93e6b9dc4ae24a39" } dbs-legacy-devices = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "127621db934af5ffba558e44b77afa00cdf62af6" }
dbs-utils = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "84eee5737cc7d85f9921c94a93e6b9dc4ae24a39" } dbs-upcall = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "127621db934af5ffba558e44b77afa00cdf62af6" }
dbs-virtio-devices = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "84eee5737cc7d85f9921c94a93e6b9dc4ae24a39" } dbs-utils = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "127621db934af5ffba558e44b77afa00cdf62af6" }
dbs-upcall = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "84eee5737cc7d85f9921c94a93e6b9dc4ae24a39" } dbs-virtio-devices = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "127621db934af5ffba558e44b77afa00cdf62af6" }

View File

@ -29,6 +29,12 @@ use dbs_virtio_devices::{
VirtioDevice, VirtioDevice,
}; };
#[cfg(feature = "hotplug")]
use dbs_upcall::{
MmioDevRequest, DevMgrRequest, DevMgrService, UpcallClient, UpcallClientError,
UpcallClientRequest, UpcallClientResponse
};
use crate::address_space_manager::GuestAddressSpaceImpl; use crate::address_space_manager::GuestAddressSpaceImpl;
use crate::error::StartMicrovmError; use crate::error::StartMicrovmError;
use crate::resource_manager::ResourceManager; use crate::resource_manager::ResourceManager;
@ -83,6 +89,11 @@ pub enum DeviceMgrError {
/// Error from Virtio subsystem. /// Error from Virtio subsystem.
#[error(transparent)] #[error(transparent)]
Virtio(virtio::Error), Virtio(virtio::Error),
#[cfg(feature = "hotplug")]
/// Failed to hotplug the device.
#[error("failed to hotplug virtual device")]
HotplugDevice(#[source] UpcallClientError),
} }
/// Specialized version of `std::result::Result` for device manager operations. /// Specialized version of `std::result::Result` for device manager operations.
@ -188,6 +199,8 @@ pub struct DeviceOpContext {
logger: slog::Logger, logger: slog::Logger,
is_hotplug: bool, is_hotplug: bool,
#[cfg(feature = "hotplug")]
upcall_client: Option<Arc<UpcallClient<DevMgrService>>>,
#[cfg(feature = "dbs-virtio-devices")] #[cfg(feature = "dbs-virtio-devices")]
virtio_devices: Vec<Arc<DbsMmioV2Device>>, virtio_devices: Vec<Arc<DbsMmioV2Device>>,
} }
@ -220,6 +233,8 @@ impl DeviceOpContext {
address_space, address_space,
logger, logger,
is_hotplug, is_hotplug,
#[cfg(feature = "hotplug")]
upcall_client: None,
#[cfg(feature = "dbs-virtio-devices")] #[cfg(feature = "dbs-virtio-devices")]
virtio_devices: Vec::new(), virtio_devices: Vec::new(),
} }
@ -265,6 +280,86 @@ impl DeviceOpContext {
} }
} }
#[cfg(not(feature = "hotplug"))]
impl DeviceOpContext {
pub(crate) fn insert_hotplug_mmio_device(
&self,
_dev: &Arc<dyn DeviceIo>,
_callback: Option<()>,
) -> Result<()> {
Err(DeviceMgrError::InvalidOperation)
}
pub(crate) fn remove_hotplug_mmio_device(
&self,
_dev: &Arc<dyn DeviceIo>,
_callback: Option<()>,
) -> Result<()> {
Err(DeviceMgrError::InvalidOperation)
}
}
#[cfg(feature = "hotplug")]
impl DeviceOpContext {
fn call_hotplug_device(
&self,
req: DevMgrRequest,
callback: Option<Box<dyn Fn(UpcallClientResponse) + Send>>,
) -> Result<()> {
if let Some(upcall_client) = self.upcall_client.as_ref() {
if let Some(cb) = callback {
upcall_client
.send_request(UpcallClientRequest::DevMgr(req), cb)
.map_err(DeviceMgrError::HotplugDevice)?;
} else {
upcall_client
.send_request_without_result(UpcallClientRequest::DevMgr(req))
.map_err(DeviceMgrError::HotplugDevice)?;
}
Ok(())
} else {
Err(DeviceMgrError::InvalidOperation)
}
}
pub(crate) fn insert_hotplug_mmio_device(
&self,
dev: &Arc<DbsMmioV2Device>,
callback: Option<Box<dyn Fn(UpcallClientResponse) + Send>>,
) -> Result<()> {
if !self.is_hotplug {
return Err(DeviceMgrError::InvalidOperation);
}
let (mmio_base, mmio_size, mmio_irq) = DeviceManager::get_virtio_device_info(dev)?;
let req = DevMgrRequest::AddMmioDev(MmioDevRequest {
mmio_base,
mmio_size,
mmio_irq,
});
self.call_hotplug_device(req, callback)
}
pub(crate) fn remove_hotplug_mmio_device(
&self,
dev: &Arc<DbsMmioV2Device>,
callback: Option<Box<dyn Fn(UpcallClientResponse) + Send>>,
) -> Result<()> {
if !self.is_hotplug {
return Err(DeviceMgrError::InvalidOperation);
}
let (mmio_base, mmio_size, mmio_irq) = DeviceManager::get_virtio_device_info(dev)?;
let req = DevMgrRequest::DelMmioDev(MmioDevRequest {
mmio_base,
mmio_size,
mmio_irq,
});
self.call_hotplug_device(req, callback)
}
}
/// Device manager for virtual machines, which manages all device for a virtual machine. /// Device manager for virtual machines, which manages all device for a virtual machine.
pub struct DeviceManager { pub struct DeviceManager {
io_manager: Arc<ArcSwap<IoManager>>, io_manager: Arc<ArcSwap<IoManager>>,