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.
45use 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};
1011const 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];
2122/// 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>);
3132impl NotifyEvent {
33/// Construct a new [`NotifyEvent`]
34pub fn new(event: zx::Event) -> NotifyEvent {
35 NotifyEvent(std::sync::Arc::new(event))
36 }
37}
3839impl NotifyEvent {
40fn signal(&self, event: usize) -> Result<(), zx::Status> {
41self.0.as_handle_ref().signal(
42 zx::Signals::empty(),
43 USER_SIGNALS[event] | USER_SIGNALS[EVENT_SET_INTERRUPT as usize],
44 )
45 }
4647pub fn signal_queue(&self) -> Result<(), zx::Status> {
48self.signal(EVENT_SET_QUEUE as usize)
49 }
5051pub fn signal_config(&self) -> Result<(), zx::Status> {
52self.signal(EVENT_SET_CONFIG as usize)
53 }
54}
5556impl DriverNotify for NotifyEvent {
57fn 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.
61self.signal_queue().unwrap();
62 }
63}