chipset_device_worker/
resolver.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! The resolver for remote chipset devices.
5
6use crate::RemoteDynamicResolvers;
7use crate::guestmem::GuestMemoryProxy;
8use crate::proxy::ChipsetDeviceProxy;
9use crate::worker::RemoteChipsetDeviceHandleParams;
10use crate::worker::RemoteChipsetDeviceWorkerParameters;
11use crate::worker::remote_chipset_device_worker_id;
12use async_trait::async_trait;
13use chipset_device_resources::ResolveChipsetDeviceHandleParams;
14use chipset_device_resources::ResolvedChipsetDevice;
15use chipset_device_worker_defs::RemoteChipsetDeviceHandle;
16use thiserror::Error;
17use vm_resource::AsyncResolveResource;
18use vm_resource::ResourceResolver;
19use vm_resource::kind::ChipsetDeviceHandleKind;
20
21/// The resolver for remote chipset devices.
22/// T is the type of the dynamic resolvers needed for the remote chipset device.
23// FUTURE: Create a way to store a Vec of all registered dynamic resolvers
24// and transfer them, instead of maintaining a list of just a few.
25pub struct RemoteChipsetDeviceResolver<T: RemoteDynamicResolvers>(pub T);
26
27/// Errors that can occur while resolving a remote chipset device.
28#[derive(Debug, Error)]
29pub enum ResolveRemoteChipsetDeviceError {
30    /// Error launching the worker.
31    #[error("error launching worker")]
32    LaunchWorker(#[source] anyhow::Error),
33    /// Error constructing the proxy.
34    #[error("error constructing proxy device")]
35    ConstructProxy(#[source] anyhow::Error),
36}
37
38#[async_trait]
39impl<T: RemoteDynamicResolvers>
40    AsyncResolveResource<ChipsetDeviceHandleKind, RemoteChipsetDeviceHandle>
41    for RemoteChipsetDeviceResolver<T>
42{
43    type Error = ResolveRemoteChipsetDeviceError;
44    type Output = ResolvedChipsetDevice;
45
46    async fn resolve(
47        &self,
48        _resolver: &ResourceResolver,
49        resource: RemoteChipsetDeviceHandle,
50        input: ResolveChipsetDeviceHandleParams<'_>,
51    ) -> Result<Self::Output, Self::Error> {
52        let RemoteChipsetDeviceHandle {
53            device,
54            worker_host,
55        } = resource;
56
57        let (req_send, req_recv) = mesh::channel();
58        let (resp_send, resp_recv) = mesh::channel();
59        let (cap_send, cap_recv) = mesh::oneshot();
60
61        let (gm_proxy, gm_remote) = GuestMemoryProxy::new(input.guest_memory.clone());
62        let (enc_gm_proxy, enc_gm_remote) =
63            GuestMemoryProxy::new(input.encrypted_guest_memory.clone());
64
65        let worker = worker_host
66            .launch_worker(
67                remote_chipset_device_worker_id(),
68                RemoteChipsetDeviceWorkerParameters {
69                    device,
70                    dyn_resolvers: self.0.clone(),
71                    inputs: RemoteChipsetDeviceHandleParams {
72                        device_name: input.device_name.to_string(),
73                        vmtime: input.vmtime.builder().clone(),
74                        is_restoring: input.is_restoring,
75                        guest_memory: gm_remote,
76                        encrypted_guest_memory: enc_gm_remote,
77                    },
78                    req_recv,
79                    resp_send,
80                    cap_send,
81                },
82            )
83            .await
84            .map_err(ResolveRemoteChipsetDeviceError::LaunchWorker)?;
85
86        let proxy = ChipsetDeviceProxy::new(
87            req_send,
88            resp_recv,
89            cap_recv,
90            worker,
91            gm_proxy,
92            enc_gm_proxy,
93            input,
94        )
95        .await
96        .map_err(ResolveRemoteChipsetDeviceError::ConstructProxy)?;
97
98        Ok(proxy.into())
99    }
100}