1use crate::PciInterruptModel;
7use crate::VirtioPciDevice;
8use crate::resolve::VirtioResolveInput;
9use async_trait::async_trait;
10use pci_resources::ResolvePciDeviceHandleParams;
11use pci_resources::ResolvedPciDevice;
12use thiserror::Error;
13use virtio_resources::VirtioPciDeviceHandle;
14use vm_resource::AsyncResolveResource;
15use vm_resource::ResolveError;
16use vm_resource::ResourceResolver;
17use vm_resource::declare_static_async_resolver;
18use vm_resource::kind::PciDeviceHandleKind;
19
20declare_static_async_resolver! {
21 VirtioPciResolver,
22 (PciDeviceHandleKind, VirtioPciDeviceHandle),
23}
24
25pub struct VirtioPciResolver;
27
28#[derive(Debug, Error)]
29pub enum ResolveVirtioPciError {
30 #[error("failed to resolve virtio device")]
31 Virtio(#[source] ResolveError),
32 #[error("failed to create PCI device")]
33 Pci(#[source] std::io::Error),
34}
35
36#[async_trait]
37impl AsyncResolveResource<PciDeviceHandleKind, VirtioPciDeviceHandle> for VirtioPciResolver {
38 type Output = ResolvedPciDevice;
39 type Error = ResolveVirtioPciError;
40
41 async fn resolve(
42 &self,
43 resolver: &ResourceResolver,
44 resource: VirtioPciDeviceHandle,
45 input: ResolvePciDeviceHandleParams<'_>,
46 ) -> Result<Self::Output, Self::Error> {
47 let inner = resolver
48 .resolve(
49 resource.0,
50 VirtioResolveInput {
51 driver_source: input.driver_source,
52 guest_memory: input.guest_memory,
53 },
54 )
55 .await
56 .map_err(ResolveVirtioPciError::Virtio)?;
57
58 let device = VirtioPciDevice::new(
59 inner.0,
60 PciInterruptModel::Msix(input.register_msi),
61 input.doorbell_registration,
62 input.register_mmio,
63 input.shared_mem_mapper,
64 )
65 .map_err(ResolveVirtioPciError::Pci)?;
66
67 Ok(device.into())
68 }
69}