Skip to main content

nvme_test/
resolver.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Resource resolver for the nvme controller.
5
6use crate::AddNamespaceError;
7use crate::NvmeFaultController;
8use crate::NvmeFaultControllerCaps;
9use async_trait::async_trait;
10use disk_backend::resolve::ResolveDiskParameters;
11use nvme_resources::NamespaceDefinition;
12use nvme_resources::NvmeFaultControllerHandle;
13use pci_resources::ResolvePciDeviceHandleParams;
14use pci_resources::ResolvedPciDevice;
15use thiserror::Error;
16use vm_resource::AsyncResolveResource;
17use vm_resource::ResolveError;
18use vm_resource::ResourceResolver;
19use vm_resource::declare_static_async_resolver;
20use vm_resource::kind::PciDeviceHandleKind;
21
22/// Resource resolver for [`NvmeFaultControllerHandle`].
23pub struct NvmeFaultControllerResolver;
24
25declare_static_async_resolver! {
26    NvmeFaultControllerResolver,
27    (PciDeviceHandleKind, NvmeFaultControllerHandle),
28}
29
30/// Error returned by [`NvmeFaultControllerResolver`].
31#[derive(Debug, Error)]
32#[expect(missing_docs)]
33pub enum Error {
34    #[error("failed to resolve namespace {nsid}")]
35    NamespaceResolve {
36        nsid: u32,
37        #[source]
38        source: ResolveError,
39    },
40    #[error(transparent)]
41    AddNamespace(AddNamespaceError),
42}
43
44#[async_trait]
45impl AsyncResolveResource<PciDeviceHandleKind, NvmeFaultControllerHandle>
46    for NvmeFaultControllerResolver
47{
48    type Output = ResolvedPciDevice;
49    type Error = Error;
50
51    async fn resolve(
52        &self,
53        resolver: &ResourceResolver,
54        resource: NvmeFaultControllerHandle,
55        input: ResolvePciDeviceHandleParams<'_>,
56    ) -> Result<Self::Output, Self::Error> {
57        let controller = NvmeFaultController::new(
58            input.driver_source,
59            input.dma_target.guest_memory().clone(),
60            input.dma_target.msi_target(),
61            input.register_mmio,
62            NvmeFaultControllerCaps {
63                msix_count: resource.msix_count,
64                max_io_queues: resource.max_io_queues,
65                subsystem_id: resource.subsystem_id,
66            },
67            resource.fault_config,
68            resource.enable_tdisp_tests,
69        );
70        for NamespaceDefinition {
71            nsid,
72            read_only,
73            disk,
74        } in resource.namespaces
75        {
76            let disk = resolver
77                .resolve(
78                    disk,
79                    ResolveDiskParameters {
80                        read_only,
81                        driver_source: input.driver_source,
82                    },
83                )
84                .await
85                .map_err(|source| Error::NamespaceResolve { nsid, source })?;
86            controller
87                .client()
88                .add_namespace(nsid, disk.0)
89                .await
90                .map_err(Error::AddNamespace)?;
91        }
92        Ok(controller.into())
93    }
94}