machina_virtio_device/
notify.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use fidl_fuchsia_virtualization_hardware::{
6    EVENT_SET_CONFIG, EVENT_SET_INTERRUPT, EVENT_SET_QUEUE,
7};
8use virtio_device::queue::DriverNotify;
9use zx::{self as zx, AsHandleRef};
10
11const USER_SIGNALS: [zx::Signals; 8] = [
12    zx::Signals::USER_0,
13    zx::Signals::USER_1,
14    zx::Signals::USER_2,
15    zx::Signals::USER_3,
16    zx::Signals::USER_4,
17    zx::Signals::USER_5,
18    zx::Signals::USER_6,
19    zx::Signals::USER_7,
20];
21
22/// Wraps a [`zx::Event`] and implements [`DriverNotify`]
23///
24/// Implements [`DriverNotify`] by setting the appropriate signals on a [`zx::Event`] to notify the
25/// machina VMM that the guest needs an interrupt.
26///
27/// The appropriate [`zx::Event`] to use for this can be found in the `StartInfo` provided as the
28/// first message to a device.
29#[derive(Clone)]
30pub struct NotifyEvent(std::sync::Arc<zx::Event>);
31
32impl NotifyEvent {
33    /// Construct a new [`NotifyEvent`]
34    pub fn new(event: zx::Event) -> NotifyEvent {
35        NotifyEvent(std::sync::Arc::new(event))
36    }
37}
38
39impl NotifyEvent {
40    fn signal(&self, event: usize) -> Result<(), zx::Status> {
41        self.0.as_handle_ref().signal(
42            zx::Signals::empty(),
43            USER_SIGNALS[event] | USER_SIGNALS[EVENT_SET_INTERRUPT as usize],
44        )
45    }
46
47    pub fn signal_queue(&self) -> Result<(), zx::Status> {
48        self.signal(EVENT_SET_QUEUE as usize)
49    }
50
51    pub fn signal_config(&self) -> Result<(), zx::Status> {
52        self.signal(EVENT_SET_CONFIG as usize)
53    }
54}
55
56impl DriverNotify for NotifyEvent {
57    fn notify(&self) {
58        // Signaling the event will only fail if the VMM has shutdown unexpectedly, without
59        // first explicitly shutting us down, which is not expected to happen. As we have no way
60        // to forward any error here anyway, just unwrap and panic.
61        self.signal_queue().unwrap();
62    }
63}