Skip to main content

virtio/
resolver.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Resolver for virtio device infrastructure.
5
6use 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
25/// Resolver for [`VirtioPciDeviceHandle`].
26pub 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                },
53            )
54            .await
55            .map_err(ResolveVirtioPciError::Virtio)?;
56
57        let device = VirtioPciDevice::new(
58            inner.0,
59            &input.driver_source.simple(),
60            input.dma_target.guest_memory().clone(),
61            PciInterruptModel::Msix(input.dma_target.msi_target()),
62            input.doorbell_registration,
63            input.register_mmio,
64            input.shared_mem_mapper,
65        )
66        .map_err(ResolveVirtioPciError::Pci)?;
67
68        Ok(device.into())
69    }
70}