Skip to main content

virtio_driver/common/
device_status.rs

1// Copyright 2026 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 bitfield::bitfield;
6
7bitfield! {
8    /// Modified by both the driver and the device during lifecycle transitions.
9    ///
10    /// The bits are intended to represent stages in the device + driver
11    /// lifecycle. After a device is reset, the value is guaranteed to be
12    /// [`DeviceStatus::RESET`].
13    ///
14    /// With the exception of resetting the device, the driver must not clear
15    /// (write 0 to) a bit that is set (to 1).
16    // @cite(virtio): sec="2.1" title="Device Status Field"
17    // @cite(virtio): sec="2.4" title="Device Reset"
18    // @cite(virtio): sec="3" title="General Initialization And Device Operation"
19    #[derive(Default, Copy, Clone, PartialEq, Eq)]
20    #[repr(transparent)]
21    pub struct DeviceStatus(u8);
22    impl Debug;
23
24    /// True iff the driver recognized the hardware as a virtio device.
25    ///
26    /// Set to true (1) by the driver in step 2 of device initialization.
27    ///
28    /// The specification recommends that the virtualized operating system sets
29    /// this bit. Fuchsia does not special-case virtio devices, so this bit is
30    /// set by Fuchsia drivers.
31    // @cite(virtio): sec="2.1" title="Device Status Field" bits=0
32    // @cite(virtio): sec="3.1.1" title="Driver Requirements: Device Initialization"
33    // @alias(virtio): theirs="ACKNOWLEDGE"
34    pub bool, virtio_device_detected, set_virtio_device_detected: 0;
35
36    /// True iff the guest OS has found a driver for the device.
37    ///
38    /// Set to true (1) by the driver in step 3 of device initialization. Fuchsia
39    /// does not special-case virtio devices, so the driver must perform this
40    /// step.
41    ///
42    /// The driver may only read the feature bits offered by the device after
43    /// setting this bit to true.
44    // @cite(virtio): sec="2.1" title="Device Status Field" bits=1
45    // @cite(virtio): sec="3.1.1" title="Driver Requirements: Device Initialization"
46    // @alias(virtio): theirs="DRIVER"
47    pub bool, driver_found, set_driver_found: 1;
48
49    /// True iff the driver is sufficiently initialized to drive the device.
50    ///
51    /// Set to true (1) by the driver in step 8 of device initialization.
52    ///
53    /// The driver must only set this bit to true after it has completed the
54    /// device-specific initialization process.
55    ///
56    /// The driver may only operate the device's virtqueues while this bit is
57    /// set to true (1).
58    // @cite(virtio): sec="2.1" title="Device Status Field" bits=2
59    // @cite(virtio): sec="3.1.1" title="Driver Requirements: Device Initialization"
60    // @alias(virtio): theirs="DRIVER_OK"
61    pub bool, driver_initialized, set_driver_initialized: 2;
62
63    /// True iff the feature negotiation is complete.
64    ///
65    /// Set to true (1) by the driver in step 5 of device initialization.
66    ///
67    /// The driver must only set this bit to true after it has acknowledged all
68    /// the features it understands.
69    // @cite(virtio): sec="2.1" title="Device Status Field" bits=3
70    // @cite(virtio): sec="3.1.1" title="Driver Requirements: Device Initialization"
71    // @alias(virtio): theirs="FEATURES_OK"
72    pub bool, feature_negotiation_complete, set_feature_negotiation_complete: 3;
73
74    /// True iff the device has been suspended by the driver.
75    ///
76    /// The driver triggers device suspension by setting this bit to true (1).
77    /// The device sets the [`driver_initialized`] bit to false (0) after the
78    /// device completes suspending.
79    ///
80    /// The driver triggers resuming a suspended device by setting the
81    /// [`driver_initialized`] bit to true (1). The device sets this bit to
82    /// false (0) after the device completes resuming.
83    ///
84    /// The driver is only allowed to set this bit if
85    /// [`VirtioFeatureBits::suspend_enabled`] is negotiated.
86    // @cite(virtio): sec="2.1" title="Device Status Field" bits=4
87    // @cite(virtio): sec="3.4" title="Device Suspend"
88    // @alias(virtio): theirs="SUSPEND"
89    pub bool, suspended, set_suspended: 4;
90
91    /// True iff the device has experienced an unrecoverable error.
92    ///
93    /// The device sends a configuration change notification when setting this
94    /// bit to true (1). The driver cannot assume that virtqueue operations will
95    /// complete (or, conversely, that the operations will be dropped) while
96    /// this bit is set.
97    // @cite(virtio): sec="2.1" title="Device Status Field" bits=6
98    // @alias(virtio): theirs="DEVICE_NEEDS_RESET"
99    pub bool, device_needs_reset, set_device_needs_reset: 6;
100
101    /// True iff the driver has experienced an unrecoverable error.
102    ///
103    /// The driver sets this bit when it gives up on driving the device.
104    // @cite(virtio): sec="2.1" title="Device Status Field" bits=7
105    // @alias(virtio): theirs="FAILED"
106    pub bool, driver_terminated, set_driver_terminated: 7;
107}
108
109impl DeviceStatus {
110    /// The status value that indicates the device has been reset.
111    // @cite(virtio): sec="2.4" title="Device Reset"
112    pub const RESET: DeviceStatus = DeviceStatus(0);
113}
114
115#[cfg(test)]
116mod tests {
117    use super::*;
118
119    #[fuchsia::test]
120    fn test_device_status() {
121        let mut status = DeviceStatus(0);
122        assert!(!status.virtio_device_detected());
123        status.set_virtio_device_detected(true);
124        assert!(status.virtio_device_detected());
125        assert_eq!(status.0, 1);
126    }
127
128    #[fuchsia::test]
129    fn test_device_status_debug() {
130        let mut status = DeviceStatus(0);
131        status.set_virtio_device_detected(true);
132        let debug_str = format!("{:?}", status);
133        assert_eq!(
134            debug_str,
135            "DeviceStatus { .0: 1, virtio_device_detected: true, driver_found: false, driver_initialized: false, feature_negotiation_complete: false, suspended: false, device_needs_reset: false, driver_terminated: false }"
136        );
137
138        let mut status3 = DeviceStatus(0);
139        status3.set_virtio_device_detected(true);
140        status3.set_driver_found(true);
141        status3.set_driver_initialized(true);
142        let debug_str3 = format!("{:?}", status3);
143        assert_eq!(
144            debug_str3,
145            "DeviceStatus { .0: 7, virtio_device_detected: true, driver_found: true, driver_initialized: true, feature_negotiation_complete: false, suspended: false, device_needs_reset: false, driver_terminated: false }"
146        );
147    }
148}