Skip to main content

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