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