virtio-devices: wire driver_status to EpollHandler

Signed-off-by: Peter Oskolkov <posk@google.com>
This commit is contained in:
Peter Oskolkov
2026-03-12 09:55:03 -07:00
committed by Bo Chen
parent 21bd3ae916
commit b5053ae4de
15 changed files with 34 additions and 4 deletions

View File

@@ -103,6 +103,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus {
(1, deflate_q, deflate_evt), (1, deflate_q, deflate_evt),
(2, reporting_q, reporting_evt), (2, reporting_q, reporting_evt),
], ],
device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)),
}) })
.ok(); .ok();

View File

@@ -95,6 +95,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus {
mem: guest_memory, mem: guest_memory,
interrupt_cb: Arc::new(NoopVirtioInterrupt {}), interrupt_cb: Arc::new(NoopVirtioInterrupt {}),
queues: vec![(0, q, evt)], queues: vec![(0, q, evt)],
device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)),
}) })
.ok(); .ok();

View File

@@ -132,6 +132,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus {
mem: guest_memory, mem: guest_memory,
interrupt_cb: Arc::new(NoopVirtioInterrupt {}), interrupt_cb: Arc::new(NoopVirtioInterrupt {}),
queues: vec![(0, input_queue, input_evt), (1, output_queue, output_evt)], queues: vec![(0, input_queue, input_evt), (1, output_queue, output_evt)],
device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)),
}) })
.unwrap(); .unwrap();

View File

@@ -114,6 +114,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus {
(0, request_queue, request_evt), (0, request_queue, request_evt),
(0, _event_queue, _event_evt), (0, _event_queue, _event_evt),
], ],
device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)),
}) })
.ok(); .ok();

View File

@@ -109,6 +109,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus {
mem: guest_memory, mem: guest_memory,
interrupt_cb: Arc::new(NoopVirtioInterrupt {}), interrupt_cb: Arc::new(NoopVirtioInterrupt {}),
queues: vec![(0, q, evt)], queues: vec![(0, q, evt)],
device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)),
}) })
.ok(); .ok();

View File

@@ -147,6 +147,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus {
mem: guest_memory, mem: guest_memory,
interrupt_cb: Arc::new(NoopVirtioInterrupt {}), interrupt_cb: Arc::new(NoopVirtioInterrupt {}),
queues: vec![(0, input_queue, input_evt), (1, output_queue, output_evt)], queues: vec![(0, input_queue, input_evt), (1, output_queue, output_evt)],
device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)),
}) })
.unwrap(); .unwrap();

View File

@@ -65,6 +65,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus {
mem: guest_memory, mem: guest_memory,
interrupt_cb: Arc::new(NoopVirtioInterrupt {}), interrupt_cb: Arc::new(NoopVirtioInterrupt {}),
queues: vec![(0, q, evt)], queues: vec![(0, q, evt)],
device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)),
}) })
.ok(); .ok();

View File

@@ -103,6 +103,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus {
mem: guest_memory, mem: guest_memory,
interrupt_cb: Arc::new(NoopVirtioInterrupt {}), interrupt_cb: Arc::new(NoopVirtioInterrupt {}),
queues: vec![(0, q, evt)], queues: vec![(0, q, evt)],
device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)),
}) })
.ok(); .ok();

View File

@@ -112,6 +112,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus {
mem: guest_memory, mem: guest_memory,
interrupt_cb: Arc::new(NoopVirtioInterrupt {}), interrupt_cb: Arc::new(NoopVirtioInterrupt {}),
queues: vec![(0, q, evt)], queues: vec![(0, q, evt)],
device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)),
}) })
.ok(); .ok();

View File

@@ -68,6 +68,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus {
mem: guest_memory, mem: guest_memory,
interrupt_cb: Arc::new(NoopVirtioInterrupt {}), interrupt_cb: Arc::new(NoopVirtioInterrupt {}),
queues: vec![(0, q, evt)], queues: vec![(0, q, evt)],
device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)),
}) })
.ok(); .ok();

View File

@@ -13,7 +13,7 @@ use std::num::Wrapping;
use std::ops::Deref; use std::ops::Deref;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::sync::atomic::{AtomicBool, AtomicU8, AtomicU64, Ordering};
use std::sync::{Arc, Barrier}; use std::sync::{Arc, Barrier};
use std::{io, result}; use std::{io, result};
@@ -161,6 +161,8 @@ struct BlockEpollHandler {
host_cpus: Option<Vec<usize>>, host_cpus: Option<Vec<usize>>,
acked_features: u64, acked_features: u64,
disable_sector0_writes: bool, disable_sector0_writes: bool,
#[allow(unused)]
device_status: Arc<AtomicU8>,
} }
fn has_feature(features: u64, feature_flag: u64) -> bool { fn has_feature(features: u64, feature_flag: u64) -> bool {
@@ -666,6 +668,7 @@ pub struct Block {
queue_affinity: BTreeMap<u16, Vec<usize>>, queue_affinity: BTreeMap<u16, Vec<usize>>,
disable_sector0_writes: bool, disable_sector0_writes: bool,
lock_granularity_choice: LockGranularityChoice, lock_granularity_choice: LockGranularityChoice,
device_status: Arc<AtomicU8>,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@@ -813,6 +816,7 @@ impl Block {
queue_affinity, queue_affinity,
disable_sector0_writes, disable_sector0_writes,
lock_granularity_choice: lock_granularity, lock_granularity_choice: lock_granularity,
device_status: Arc::new(AtomicU8::new(0)),
}) })
} }
@@ -1013,7 +1017,9 @@ impl VirtioDevice for Block {
mem, mem,
interrupt_cb, interrupt_cb,
mut queues, mut queues,
device_status,
} = context; } = context;
self.device_status = device_status;
// See if the guest didn't ack the device being read-only. // See if the guest didn't ack the device being read-only.
// If so, warn and pretend it did. // If so, warn and pretend it did.
let original_acked_features = self.common.acked_features; let original_acked_features = self.common.acked_features;
@@ -1069,6 +1075,7 @@ impl VirtioDevice for Block {
host_cpus: self.queue_affinity.get(&queue_idx).cloned(), host_cpus: self.queue_affinity.get(&queue_idx).cloned(),
acked_features: self.common.acked_features, acked_features: self.common.acked_features,
disable_sector0_writes: self.disable_sector0_writes, disable_sector0_writes: self.disable_sector0_writes,
device_status: self.device_status.clone(),
}; };
let paused = self.common.paused.clone(); let paused = self.common.paused.clone();

View File

@@ -9,7 +9,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::io::Write; use std::io::Write;
use std::num::Wrapping; use std::num::Wrapping;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, AtomicU8, Ordering};
use std::sync::{Arc, Barrier}; use std::sync::{Arc, Barrier};
use std::thread; use std::thread;
@@ -57,6 +57,7 @@ pub struct ActivationContext {
pub mem: GuestMemoryAtomic<GuestMemoryMmap>, pub mem: GuestMemoryAtomic<GuestMemoryMmap>,
pub interrupt_cb: Arc<dyn VirtioInterrupt>, pub interrupt_cb: Arc<dyn VirtioInterrupt>,
pub queues: Vec<(usize, Queue, EventFd)>, pub queues: Vec<(usize, Queue, EventFd)>,
pub device_status: Arc<AtomicU8>,
} }
/// Trait for virtio devices to be driven by a virtio transport. /// Trait for virtio devices to be driven by a virtio transport.

View File

@@ -10,7 +10,7 @@ use std::net::IpAddr;
use std::num::Wrapping; use std::num::Wrapping;
use std::ops::Deref; use std::ops::Deref;
use std::os::unix::io::{AsRawFd, RawFd}; use std::os::unix::io::{AsRawFd, RawFd};
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, AtomicU8, Ordering};
use std::sync::{Arc, Barrier}; use std::sync::{Arc, Barrier};
use std::{result, thread}; use std::{result, thread};
@@ -179,6 +179,8 @@ struct NetEpollHandler {
// a restore as the vCPU thread isn't ready to handle the interrupt. This causes // a restore as the vCPU thread isn't ready to handle the interrupt. This causes
// issues when combined with VIRTIO_RING_F_EVENT_IDX interrupt suppression. // issues when combined with VIRTIO_RING_F_EVENT_IDX interrupt suppression.
driver_awake: bool, driver_awake: bool,
#[allow(unused)]
device_status: Arc<AtomicU8>,
} }
impl NetEpollHandler { impl NetEpollHandler {
@@ -414,6 +416,7 @@ pub struct Net {
seccomp_action: SeccompAction, seccomp_action: SeccompAction,
rate_limiter_config: Option<RateLimiterConfig>, rate_limiter_config: Option<RateLimiterConfig>,
exit_evt: EventFd, exit_evt: EventFd,
device_status: Arc<AtomicU8>,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@@ -535,6 +538,7 @@ impl Net {
seccomp_action, seccomp_action,
rate_limiter_config, rate_limiter_config,
exit_evt, exit_evt,
device_status: Arc::new(AtomicU8::new(0)),
}) })
} }
@@ -698,7 +702,9 @@ impl VirtioDevice for Net {
mem, mem,
interrupt_cb, interrupt_cb,
mut queues, mut queues,
device_status,
} = context; } = context;
self.device_status = device_status;
self.common.activate(&queues, interrupt_cb.clone())?; self.common.activate(&queues, interrupt_cb.clone())?;
let num_queues = queues.len(); let num_queues = queues.len();
@@ -803,6 +809,7 @@ impl VirtioDevice for Net {
kill_evt, kill_evt,
pause_evt, pause_evt,
driver_awake: false, driver_awake: false,
device_status: self.device_status.clone(),
}; };
let paused = self.common.paused.clone(); let paused = self.common.paused.clone();

View File

@@ -10,7 +10,7 @@ use std::any::Any;
use std::cmp; use std::cmp;
use std::io::Write; use std::io::Write;
use std::ops::Deref; use std::ops::Deref;
use std::sync::atomic::{AtomicBool, AtomicU16, AtomicUsize, Ordering}; use std::sync::atomic::{AtomicBool, AtomicU8, AtomicU16, AtomicUsize, Ordering};
use std::sync::{Arc, Barrier, Mutex}; use std::sync::{Arc, Barrier, Mutex};
use anyhow::anyhow; use anyhow::anyhow;
@@ -306,6 +306,7 @@ pub struct VirtioPciDeviceActivator {
queues: Option<Vec<(usize, Queue, EventFd)>>, queues: Option<Vec<(usize, Queue, EventFd)>>,
barrier: Option<Arc<Barrier>>, barrier: Option<Arc<Barrier>>,
id: String, id: String,
status: Arc<AtomicU8>,
} }
impl VirtioPciDeviceActivator { impl VirtioPciDeviceActivator {
@@ -315,6 +316,7 @@ impl VirtioPciDeviceActivator {
mem: self.memory.take().unwrap(), mem: self.memory.take().unwrap(),
interrupt_cb: self.interrupt.take().unwrap(), interrupt_cb: self.interrupt.take().unwrap(),
queues: self.queues.take().unwrap(), queues: self.queues.take().unwrap(),
device_status: self.status,
})?; })?;
self.device_activated.store(true, Ordering::SeqCst); self.device_activated.store(true, Ordering::SeqCst);
@@ -820,6 +822,7 @@ impl VirtioPciDevice {
device_activated: self.device_activated.clone(), device_activated: self.device_activated.clone(),
barrier, barrier,
id: self.id.clone(), id: self.id.clone(),
status: self.common_config.driver_status.clone(),
} }
} }

View File

@@ -598,6 +598,7 @@ mod unit_tests {
mem: memory.clone(), mem: memory.clone(),
interrupt_cb: Arc::new(NoopVirtioInterrupt {}), interrupt_cb: Arc::new(NoopVirtioInterrupt {}),
queues: Vec::new(), queues: Vec::new(),
device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)),
}); });
match bad_activate { match bad_activate {
Err(ActivateError::BadActivate) => (), Err(ActivateError::BadActivate) => (),
@@ -626,6 +627,7 @@ mod unit_tests {
EventFd::new(EFD_NONBLOCK).unwrap(), EventFd::new(EFD_NONBLOCK).unwrap(),
), ),
], ],
device_status: Arc::new(std::sync::atomic::AtomicU8::new(0)),
}) })
.unwrap(); .unwrap();
} }