Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dragonball: add pci vfio passthrough, hot(un)plug support #8740

Merged
merged 4 commits into from Dec 28, 2023

Conversation

studychao
Copy link
Member

@studychao studychao commented Dec 27, 2023

dragonball: add InsertHostDevice vmm action

Introduce a new vmm action InsertHostDevice to passthrough
host pci devices like NIC or GPU devices into guest so that
users could have high performance usage of those devices.
dragonball: add pci hotplug / hot-unplug support
    
    Introduce two new vmm action to implement pci hotplug
    and pci hot-unplug: PrepareRemoveHostDevice and RemoveHostDevice.
    
    PrepareRemoveHostDevice is to call upcall to unregister the pci device
    in the guest kernel.
    RemoveHostDevice should be called after PrepareRemoveHostDevice, it is used
    to clean the PCI resource in the Dragonball side.
dragonball: add InsertHostDevice vmm action
    
    Introduce a new vmm action InsertHostDevice to passthrough
    host pci devices like NIC or GPU devices into guest so that
    users could have high performance usage of those devices.

@katacontainersbot katacontainersbot added the size/huge Largest and most complex task (probably needs breaking into small pieces) label Dec 27, 2023
Comment on lines 52 to 53
vfio-bindings = { version = "0.3.0", optional = true}
vfio-ioctls = { version = "0.1.0", optional = true}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing a space after true.

Suggested change
vfio-bindings = { version = "0.3.0", optional = true}
vfio-ioctls = { version = "0.1.0", optional = true}
vfio-bindings = { version = "0.3.0", optional = true }
vfio-ioctls = { version = "0.1.0", optional = true }

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@studychao studychao force-pushed the upstream/pci-6-final branch 2 times, most recently from 7d731ca to 4511761 Compare December 27, 2023 08:56
@studychao studychao changed the title [wip]pci final Dragonball: add pci vfio passthrough, hot(un)plug support Dec 27, 2023
@studychao studychao force-pushed the upstream/pci-6-final branch 3 times, most recently from ae6a7d0 to 82c02fa Compare December 27, 2023 09:19
Copy link
Member

@justxuewei justxuewei left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @studychao, a few comments here.

#[cfg(feature = "host-device")]
fn add_vfio_device(&self, vmm: &mut Vmm, config: HostDeviceConfig) -> VmmRequestResult {
let vm = vmm.get_vm_mut().ok_or(VmmActionError::HostDeviceConfig(
VfioDeviceError::InvalidVMID,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: InvalidVMID -> InvalidVmId

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll raise a separate PR to fix this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#8747 is raised for this problem.


let mut ctx = vm.create_device_op_context(None).map_err(|e| {
info!("create device op context error: {:?}", e);
if let StartMicroVmError::MicroVMAlreadyRunning = e {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: MicroVMAlreadyRunning -> MicroVmAlreadyRunning

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto


let (sender, receiver) = unbounded();

let vfio_manager = vm.device_manager.vfio_manager.lock().unwrap();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Give some comments to describe why it is safe?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}
})?;

let mut vfio_manager = vm.device_manager.vfio_manager.lock().unwrap();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


self.bus
.upgrade()
.unwrap()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.
will return error here.

use crate::device_manager::DeviceManagerContext;
use crate::resource_manager::ResourceManager;

///we only support one pci bus
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
///we only support one pci bus
/// we only support one pci bus

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines +61 to +65
base: 0xcf8,
size: 0x8,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Give some comments?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment added

@@ -205,6 +207,14 @@ pub enum StartMicroVmError {
VhostUserNetDeviceError(
#[source] device_manager::vhost_user_net_dev_mgr::VhostUserNetDeviceError,
),
#[cfg(feature = "host-device")]
/// Failed to create VFIO device
#[error("cannot create VFIO device")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Print error stack?

Suggested change
#[error("cannot create VFIO device")]
#[error("cannot create VFIO device: {0:?}")]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

CreateVfioDevice(#[source] VfioDeviceError),
#[cfg(feature = "host-device")]
/// Failed to register DMA memory address range.
#[error("failure while registering DMA address range: {0}")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#[error("failure while registering DMA address range: {0}")]
#[error("failure while registering DMA address range: {0:?}")]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

#[cfg(feature = "host-device")]
/// Failed to register DMA memory address range.
#[error("failure while registering DMA address range: {0}")]
RegisterDMAAddress(#[source] VfioDeviceError),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: RegisterDMAAddress -> RegisterDmaAddress


#[cfg(feature = "host-device")]
/// The action `InsertHostDevice` failed either because of bad user input or an internal error.
#[error("failed to add VFIO passthrough device: {0}")]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0:?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same below

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -17,6 +17,8 @@ use std::cmp::{Ord, PartialOrd};
use std::convert::TryFrom;
use std::sync::Mutex;

use downcast_rs::{impl_downcast, Downcast};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use std::any instead of downcast_rs

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -73,11 +73,7 @@ impl PciDevice for PciHostBridge {
}
}

impl DeviceIo for PciHostBridge {
fn as_any(&self) -> &dyn std::any::Any {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can use as_any, not downcast

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -884,7 +884,7 @@ impl Region {
}
}

struct VfioPciDeviceState<C: PciSystemContext> {
pub struct VfioPciDeviceState<C: PciSystemContext> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why make state a pub struct?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cause we need to get the state of VfioPciDevice, if we make this pub, Rust will complain that we leak a private struct. Error is attached.
image

Copy link
Member

@justxuewei justxuewei left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few addtional comments.

}

impl VfioPciDeviceConfig {
///default pci domain is 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
///default pci domain is 0
/// default pci domain is 0

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

pub fn host_pci_domain(&self) -> u32 {
0
}
pub fn valid_vendor_device(&self) -> bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a blank here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

error!("send upcall result failed, due to {:?}!", e);
}
}
_ => {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do something? Like print some logs or return an error?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add the match arm for test case here.

.iter()
.position(|info| info.config.id().eq(id))
}
/// Register guest memory to the VFIO container.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a blank.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

}
Ok(())
}
pub(crate) fn register_memory_region(&mut self, region: &GuestRegionMmap) -> Result<()> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a blank.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

let readonly = region.prot() & libc::PROT_WRITE == 0;
self.register_region(gpa, size, user_addr, readonly)
}
pub(crate) fn register_region(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a blank.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

Ok(cfg.sysfs_path.clone())
}
}
/// Get all PCI devices' legacy irqs
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a blank.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

}
Ok(self.pci_vfio_manager.as_mut().unwrap())
}
/// Get the PCI manager to support PCI device passthrough
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a blank here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added.

Introduce a new vmm action InsertHostDevice to passthrough
host pci devices like NIC or GPU devices into guest so that
users could have high performance usage of those devices.

fixes: kata-containers#8741

Signed-off-by: Gerry Liu <gerry@linux.alibaba.com>
Signed-off-by: Zizheng Bian <zizheng.bian@linux.alibaba.com>
Signed-off-by: Zha Bin <zhabin@linux.alibaba.com>
Signed-off-by: Helin Guo <helinguo@linux.alibaba.com>
Signed-off-by: Chao Wu <chaowu@linux.alibaba.com>
Introduce two new vmm action to implement pci hotplug
and pci hot-unplug: PrepareRemoveHostDevice and RemoveHostDevice.

PrepareRemoveHostDevice is to call upcall to unregister the pci device
in the guest kernel.
RemoveHostDevice should be called after PrepareRemoveHostDevice, it is used
to clean the PCI resource in the Dragonball side.

fixes: kata-containers#8741

Signed-off-by: Gerry Liu <gerry@linux.alibaba.com>
Signed-off-by: Zizheng Bian <zizheng.bian@linux.alibaba.com>
Signed-off-by: Zha Bin <zhabin@linux.alibaba.com>
Signed-off-by: Helin Guo <helinguo@linux.alibaba.com>
Signed-off-by: Chao Wu <chaowu@linux.alibaba.com>
add pci add and del guest kernel patch as the extension
in the upcall device manager server side.

also, dump config version to 120 since we need to add config
for dragonball pci in upcall

fixes: kata-containers#8741

Signed-off-by: Gerry Liu <gerry@linux.alibaba.com>
Signed-off-by: Helin Guo <helinguo@linux.alibaba.com>
Signed-off-by: Chao Wu <chaowu@linux.alibaba.com>
Copy link
Member

@justxuewei justxuewei left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm, thanks!

Copy link
Contributor

@ZizhengBian ZizhengBian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@justxuewei
Copy link
Member

Looks like unit tests were failing. Please fix this first.

@studychao
Copy link
Member Author

Looks like unit tests were failing. Please fix this first.

yep, I'm trying to fix all CI complains

@studychao
Copy link
Member Author

/test

@studychao
Copy link
Member Author

/test

vfio commits introduce quite a lot change in runtime-rs, this commit is
for all the changes related to ci, including compilation errors and so on.

Signed-off-by: Chao Wu <chaowu@linux.alibaba.com>
@studychao
Copy link
Member Author

/test

@studychao studychao merged commit 67b91c1 into kata-containers:main Dec 28, 2023
169 of 176 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ok-to-test runtime-rs size/huge Largest and most complex task (probably needs breaking into small pieces)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants