1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
mod mem_device;
mod wire;
use {
crate::mem_device::{MemDevice, VmoMemoryBackend},
anyhow::{anyhow, Context},
fidl::endpoints::RequestStream,
fidl_fuchsia_virtualization_hardware::VirtioMemRequestStream,
fuchsia_component::server,
fuchsia_inspect as inspect,
futures::{future, StreamExt, TryFutureExt, TryStreamExt},
tracing,
virtio_device::chain::ReadableChain,
};
async fn run_virtio_mem(mut virtio_mem_fidl: VirtioMemRequestStream) -> Result<(), anyhow::Error> {
let (start_info, region_addr, plugged_block_size, plugged_region_size, responder) =
virtio_mem_fidl
.try_next()
.await?
.ok_or(anyhow!("Failed to read fidl message from the channel."))?
.into_start()
.ok_or(anyhow!("Start should be the first message sent."))?;
let (mut device_builder, guest_mem) = machina_virtio_device::from_start_info(start_info)?;
responder.send()?;
let vmo = device_builder.take_vmo().expect("VMO must be provided to virtio_mem device");
let control_handle = virtio_mem_fidl.control_handle();
let mut virtio_device_fidl = virtio_mem_fidl.cast_stream();
let (device, ready_responder) = machina_virtio_device::config_builder_from_stream(
device_builder,
&mut virtio_device_fidl,
&[wire::GUESTREQUESTQ][..],
&guest_mem,
)
.await
.context("Failed to initialize device.")?;
let guest_request_stream = device.take_stream(wire::GUESTREQUESTQ)?;
ready_responder.send()?;
let mut mem_device = MemDevice::new(
VmoMemoryBackend::new(vmo),
control_handle,
&inspect::component::inspector().root(),
region_addr,
plugged_block_size,
plugged_region_size,
);
futures::future::try_join(
device.run_device_notify(virtio_device_fidl).err_into(),
guest_request_stream.map(|chain| Ok(chain)).try_for_each(|chain| {
future::ready({
if let Err(e) =
mem_device.process_guest_request_chain(ReadableChain::new(chain, &guest_mem))
{
tracing::warn!("Failed to process guest request chain {}", e);
}
Ok(())
})
}),
)
.await
.map(|((), ())| ())
}
#[fuchsia::main(logging = true, threads = 1)]
async fn main() -> Result<(), anyhow::Error> {
let mut fs = server::ServiceFs::new();
inspect_runtime::serve(inspect::component::inspector(), &mut fs)?;
fs.dir("svc").add_fidl_service(|stream: VirtioMemRequestStream| stream);
fs.take_and_serve_directory_handle().context("Error starting server")?;
fs.for_each_concurrent(None, |stream| async {
if let Err(e) = run_virtio_mem(stream).await {
tracing::error!("Error running virtio_mem service: {}", e);
}
})
.await;
Ok(())
}