mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-11-04 19:11:11 +00:00
virtio-devices: Pass a list of tuples for virtqueues
Instead of passing separately a list of Queues and the equivalent list of EventFds, we consolidate these two through a tuple along with the queue index. The queue index can be very useful if looking for the actual index related to the queue, no matter if other queues have been enabled or not. It's also convenient to have the EventFd associated with the Queue so that we don't have to carry two lists with the same amount of items. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
423c54eafe
commit
3f62a172b2
@ -84,9 +84,8 @@ fuzz_target!(|bytes| {
|
||||
q.state.ready = true;
|
||||
q.state.size = QUEUE_SIZE / 2;
|
||||
|
||||
let queue_evts: Vec<EventFd> = vec![EventFd::new(0).unwrap()];
|
||||
let queue_fd = queue_evts[0].as_raw_fd();
|
||||
let queue_evt = unsafe { EventFd::from_raw_fd(libc::dup(queue_fd)) };
|
||||
let evt = EventFd::new(0).unwrap();
|
||||
let queue_evt = unsafe { EventFd::from_raw_fd(libc::dup(evt.as_raw_fd())) };
|
||||
|
||||
let shm = memfd_create(&ffi::CString::new("fuzz").unwrap(), 0).unwrap();
|
||||
let disk_file: File = unsafe { File::from_raw_fd(shm) };
|
||||
@ -110,8 +109,7 @@ fuzz_target!(|bytes| {
|
||||
.activate(
|
||||
guest_memory,
|
||||
Arc::new(NoopVirtioInterrupt {}),
|
||||
vec![q],
|
||||
queue_evts,
|
||||
vec![(0, q, evt)],
|
||||
)
|
||||
.ok();
|
||||
|
||||
|
@ -542,17 +542,23 @@ impl VirtioDevice for Balloon {
|
||||
&mut self,
|
||||
_mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
mut queue_evts: Vec<EventFd>,
|
||||
mut queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
|
||||
) -> ActivateResult {
|
||||
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
||||
self.common.activate(&queues, &interrupt_cb)?;
|
||||
let (kill_evt, pause_evt) = self.common.dup_eventfds();
|
||||
|
||||
let inflate_queue_evt = queue_evts.remove(0);
|
||||
let deflate_queue_evt = queue_evts.remove(0);
|
||||
let mut virtqueues = Vec::new();
|
||||
let (_, queue, queue_evt) = queues.remove(0);
|
||||
virtqueues.push(queue);
|
||||
let inflate_queue_evt = queue_evt;
|
||||
let (_, queue, queue_evt) = queues.remove(0);
|
||||
virtqueues.push(queue);
|
||||
let deflate_queue_evt = queue_evt;
|
||||
let reporting_queue_evt =
|
||||
if self.common.feature_acked(VIRTIO_BALLOON_F_REPORTING) && !queue_evts.is_empty() {
|
||||
Some(queue_evts.remove(0))
|
||||
if self.common.feature_acked(VIRTIO_BALLOON_F_REPORTING) && !queues.is_empty() {
|
||||
let (_, queue, queue_evt) = queues.remove(0);
|
||||
virtqueues.push(queue);
|
||||
Some(queue_evt)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@ -563,7 +569,7 @@ impl VirtioDevice for Balloon {
|
||||
error!("failed to clone resize EventFd: {:?}", e);
|
||||
ActivateError::BadActivate
|
||||
})?,
|
||||
queues,
|
||||
queues: virtqueues,
|
||||
interrupt_cb,
|
||||
inflate_queue_evt,
|
||||
deflate_queue_evt,
|
||||
|
@ -587,18 +587,16 @@ impl VirtioDevice for Block {
|
||||
&mut self,
|
||||
mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||
mut queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
mut queue_evts: Vec<EventFd>,
|
||||
mut queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
|
||||
) -> ActivateResult {
|
||||
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
||||
self.common.activate(&queues, &interrupt_cb)?;
|
||||
|
||||
let disk_image_id = build_disk_image_id(&self.disk_path);
|
||||
self.update_writeback();
|
||||
|
||||
let mut epoll_threads = Vec::new();
|
||||
for i in 0..queues.len() {
|
||||
let queue_evt = queue_evts.remove(0);
|
||||
let queue = queues.remove(0);
|
||||
let (_, queue, queue_evt) = queues.remove(0);
|
||||
let queue_size = queue.state.size;
|
||||
let (kill_evt, pause_evt) = self.common.dup_eventfds();
|
||||
|
||||
|
@ -490,10 +490,9 @@ impl VirtioDevice for Console {
|
||||
&mut self,
|
||||
_mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
mut queue_evts: Vec<EventFd>,
|
||||
mut queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
|
||||
) -> ActivateResult {
|
||||
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
||||
self.common.activate(&queues, &interrupt_cb)?;
|
||||
self.resizer
|
||||
.acked_features
|
||||
.store(self.common.acked_features, Ordering::Relaxed);
|
||||
@ -507,13 +506,21 @@ impl VirtioDevice for Console {
|
||||
let (kill_evt, pause_evt) = self.common.dup_eventfds();
|
||||
let input_evt = EventFd::new(EFD_NONBLOCK).unwrap();
|
||||
|
||||
let mut virtqueues = Vec::new();
|
||||
let (_, queue, queue_evt) = queues.remove(0);
|
||||
virtqueues.push(queue);
|
||||
let input_queue_evt = queue_evt;
|
||||
let (_, queue, queue_evt) = queues.remove(0);
|
||||
virtqueues.push(queue);
|
||||
let output_queue_evt = queue_evt;
|
||||
|
||||
let mut handler = ConsoleEpollHandler {
|
||||
queues,
|
||||
queues: virtqueues,
|
||||
interrupt_cb,
|
||||
in_buffer: self.in_buffer.clone(),
|
||||
endpoint: self.endpoint.clone(),
|
||||
input_queue_evt: queue_evts.remove(0),
|
||||
output_queue_evt: queue_evts.remove(0),
|
||||
input_queue_evt,
|
||||
output_queue_evt,
|
||||
input_evt,
|
||||
config_evt: self.resizer.config_evt.try_clone().unwrap(),
|
||||
resize_pipe: self.resize_pipe.as_ref().map(|p| p.try_clone().unwrap()),
|
||||
|
@ -107,8 +107,7 @@ pub trait VirtioDevice: Send {
|
||||
&mut self,
|
||||
mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
interrupt_evt: Arc<dyn VirtioInterrupt>,
|
||||
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
queue_evts: Vec<EventFd>,
|
||||
queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
|
||||
) -> ActivateResult;
|
||||
|
||||
/// Optionally deactivates this device and returns ownership of the guest memory map, interrupt
|
||||
@ -251,19 +250,9 @@ impl VirtioCommon {
|
||||
|
||||
pub fn activate(
|
||||
&mut self,
|
||||
queues: &[Queue<GuestMemoryAtomic<GuestMemoryMmap>>],
|
||||
queue_evts: &[EventFd],
|
||||
queues: &[(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)],
|
||||
interrupt_cb: &Arc<dyn VirtioInterrupt>,
|
||||
) -> ActivateResult {
|
||||
if queues.len() != queue_evts.len() {
|
||||
error!(
|
||||
"Cannot activate: length mismatch: queue_evts={} queues={}",
|
||||
queue_evts.len(),
|
||||
queues.len()
|
||||
);
|
||||
return Err(ActivateError::BadActivate);
|
||||
}
|
||||
|
||||
if queues.len() < self.min_queues.into() {
|
||||
error!(
|
||||
"Number of enabled queues lower than min: {} vs {}",
|
||||
@ -290,7 +279,7 @@ impl VirtioCommon {
|
||||
self.interrupt_cb = Some(interrupt_cb.clone());
|
||||
|
||||
let mut tmp_queue_evts: Vec<EventFd> = Vec::new();
|
||||
for queue_evt in queue_evts.iter() {
|
||||
for (_, _, queue_evt) in queues.iter() {
|
||||
// Save the queue EventFD as we need to return it on reset
|
||||
// but clone it to pass into the thread.
|
||||
tmp_queue_evts.push(queue_evt.try_clone().map_err(|e| {
|
||||
|
@ -1052,13 +1052,20 @@ impl VirtioDevice for Iommu {
|
||||
&mut self,
|
||||
_mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
queue_evts: Vec<EventFd>,
|
||||
queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
|
||||
) -> ActivateResult {
|
||||
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
||||
self.common.activate(&queues, &interrupt_cb)?;
|
||||
let (kill_evt, pause_evt) = self.common.dup_eventfds();
|
||||
|
||||
let mut virtqueues = Vec::new();
|
||||
let mut queue_evts = Vec::new();
|
||||
for (_, queue, queue_evt) in queues {
|
||||
virtqueues.push(queue);
|
||||
queue_evts.push(queue_evt);
|
||||
}
|
||||
|
||||
let mut handler = IommuEpollHandler {
|
||||
queues,
|
||||
queues: virtqueues,
|
||||
interrupt_cb,
|
||||
queue_evts,
|
||||
kill_evt,
|
||||
|
@ -1004,20 +1004,22 @@ impl VirtioDevice for Mem {
|
||||
&mut self,
|
||||
_mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||
mut queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
mut queue_evts: Vec<EventFd>,
|
||||
mut queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
|
||||
) -> ActivateResult {
|
||||
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
||||
self.common.activate(&queues, &interrupt_cb)?;
|
||||
let (kill_evt, pause_evt) = self.common.dup_eventfds();
|
||||
|
||||
let (_, queue, queue_evt) = queues.remove(0);
|
||||
|
||||
let mut handler = MemEpollHandler {
|
||||
host_addr: self.host_addr,
|
||||
host_fd: self.host_fd,
|
||||
blocks_state: Arc::clone(&self.blocks_state),
|
||||
config: self.config.clone(),
|
||||
resize: self.resize.clone(),
|
||||
queue: queues.remove(0),
|
||||
queue,
|
||||
interrupt_cb,
|
||||
queue_evt: queue_evts.remove(0),
|
||||
queue_evt,
|
||||
kill_evt,
|
||||
pause_evt,
|
||||
hugepages: self.hugepages,
|
||||
|
@ -585,17 +585,15 @@ impl VirtioDevice for Net {
|
||||
&mut self,
|
||||
_mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||
mut queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
mut queue_evts: Vec<EventFd>,
|
||||
mut queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
|
||||
) -> ActivateResult {
|
||||
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
||||
self.common.activate(&queues, &interrupt_cb)?;
|
||||
|
||||
let num_queues = queues.len();
|
||||
let event_idx = self.common.feature_acked(VIRTIO_RING_F_EVENT_IDX.into());
|
||||
if self.common.feature_acked(VIRTIO_NET_F_CTRL_VQ.into()) && num_queues % 2 != 0 {
|
||||
let ctrl_queue_index = num_queues - 1;
|
||||
let mut ctrl_queue = queues.remove(ctrl_queue_index);
|
||||
let ctrl_queue_evt = queue_evts.remove(ctrl_queue_index);
|
||||
let (_, mut ctrl_queue, ctrl_queue_evt) = queues.remove(ctrl_queue_index);
|
||||
|
||||
ctrl_queue.set_event_idx(event_idx);
|
||||
|
||||
@ -641,11 +639,13 @@ impl VirtioDevice for Net {
|
||||
let tx = TxVirtio::new();
|
||||
let rx_tap_listening = false;
|
||||
|
||||
let mut queue_pair = vec![queues.remove(0), queues.remove(0)];
|
||||
let (_, queue_0, queue_evt_0) = queues.remove(0);
|
||||
let (_, queue_1, queue_evt_1) = queues.remove(0);
|
||||
let mut queue_pair = vec![queue_0, queue_1];
|
||||
queue_pair[0].set_event_idx(event_idx);
|
||||
queue_pair[1].set_event_idx(event_idx);
|
||||
|
||||
let queue_evt_pair = vec![queue_evts.remove(0), queue_evts.remove(0)];
|
||||
let queue_evt_pair = vec![queue_evt_0, queue_evt_1];
|
||||
|
||||
let (kill_evt, pause_evt) = self.common.dup_eventfds();
|
||||
|
||||
|
@ -379,21 +379,23 @@ impl VirtioDevice for Pmem {
|
||||
&mut self,
|
||||
_mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||
mut queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
mut queue_evts: Vec<EventFd>,
|
||||
mut queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
|
||||
) -> ActivateResult {
|
||||
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
||||
self.common.activate(&queues, &interrupt_cb)?;
|
||||
let (kill_evt, pause_evt) = self.common.dup_eventfds();
|
||||
if let Some(disk) = self.disk.as_ref() {
|
||||
let disk = disk.try_clone().map_err(|e| {
|
||||
error!("failed cloning pmem disk: {}", e);
|
||||
ActivateError::BadActivate
|
||||
})?;
|
||||
|
||||
let (_, queue, queue_evt) = queues.remove(0);
|
||||
|
||||
let mut handler = PmemEpollHandler {
|
||||
queue: queues.remove(0),
|
||||
queue,
|
||||
disk,
|
||||
interrupt_cb,
|
||||
queue_evt: queue_evts.remove(0),
|
||||
queue_evt,
|
||||
kill_evt,
|
||||
pause_evt,
|
||||
access_platform: self.common.access_platform.clone(),
|
||||
|
@ -35,7 +35,7 @@ const QUEUE_SIZES: &[u16] = &[QUEUE_SIZE];
|
||||
const QUEUE_AVAIL_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 1;
|
||||
|
||||
struct RngEpollHandler {
|
||||
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
queue: Queue<GuestMemoryAtomic<GuestMemoryMmap>>,
|
||||
random_file: File,
|
||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||
queue_evt: EventFd,
|
||||
@ -46,7 +46,7 @@ struct RngEpollHandler {
|
||||
|
||||
impl RngEpollHandler {
|
||||
fn process_queue(&mut self) -> bool {
|
||||
let queue = &mut self.queues[0];
|
||||
let queue = &mut self.queue;
|
||||
|
||||
let mut used_desc_heads = [(0, 0); QUEUE_SIZE as usize];
|
||||
let mut used_count = 0;
|
||||
@ -219,10 +219,9 @@ impl VirtioDevice for Rng {
|
||||
&mut self,
|
||||
_mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
mut queue_evts: Vec<EventFd>,
|
||||
mut queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
|
||||
) -> ActivateResult {
|
||||
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
||||
self.common.activate(&queues, &interrupt_cb)?;
|
||||
let (kill_evt, pause_evt) = self.common.dup_eventfds();
|
||||
|
||||
if let Some(file) = self.random_file.as_ref() {
|
||||
@ -230,11 +229,14 @@ impl VirtioDevice for Rng {
|
||||
error!("failed cloning rng source: {}", e);
|
||||
ActivateError::BadActivate
|
||||
})?;
|
||||
|
||||
let (_, queue, queue_evt) = queues.remove(0);
|
||||
|
||||
let mut handler = RngEpollHandler {
|
||||
queues,
|
||||
queue,
|
||||
random_file,
|
||||
interrupt_cb,
|
||||
queue_evt: queue_evts.remove(0),
|
||||
queue_evt,
|
||||
kill_evt,
|
||||
pause_evt,
|
||||
access_platform: self.common.access_platform.clone(),
|
||||
|
@ -385,8 +385,7 @@ mod tests {
|
||||
&mut self,
|
||||
_mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
_interrupt_evt: Arc<dyn VirtioInterrupt>,
|
||||
_queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
_queue_evts: Vec<EventFd>,
|
||||
_queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
|
||||
) -> ActivateResult {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -292,8 +292,8 @@ pub struct VirtioPciDeviceActivator {
|
||||
memory: Option<GuestMemoryAtomic<GuestMemoryMmap>>,
|
||||
device: Arc<Mutex<dyn VirtioDevice>>,
|
||||
device_activated: Arc<AtomicBool>,
|
||||
queues: Option<Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>>,
|
||||
queue_evts: Option<Vec<EventFd>>,
|
||||
#[allow(clippy::type_complexity)]
|
||||
queues: Option<Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>>,
|
||||
barrier: Option<Arc<Barrier>>,
|
||||
id: String,
|
||||
}
|
||||
@ -304,7 +304,6 @@ impl VirtioPciDeviceActivator {
|
||||
self.memory.take().unwrap(),
|
||||
self.interrupt.take().unwrap(),
|
||||
self.queues.take().unwrap(),
|
||||
self.queue_evts.take().unwrap(),
|
||||
)?;
|
||||
self.device_activated.store(true, Ordering::SeqCst);
|
||||
|
||||
@ -700,7 +699,6 @@ impl VirtioPciDevice {
|
||||
|
||||
fn prepare_activator(&mut self, barrier: Option<Arc<Barrier>>) -> VirtioPciDeviceActivator {
|
||||
let mut queues = Vec::new();
|
||||
let mut queue_evts = Vec::new();
|
||||
|
||||
for (queue_index, queue) in self.queues.iter().enumerate() {
|
||||
if !queue.state.ready {
|
||||
@ -711,8 +709,11 @@ impl VirtioPciDevice {
|
||||
error!("Queue {} is not valid", queue_index);
|
||||
}
|
||||
|
||||
queues.push(vm_virtio::clone_queue(queue));
|
||||
queue_evts.push(self.queue_evts[queue_index].try_clone().unwrap());
|
||||
queues.push((
|
||||
queue_index,
|
||||
vm_virtio::clone_queue(queue),
|
||||
self.queue_evts[queue_index].try_clone().unwrap(),
|
||||
));
|
||||
}
|
||||
|
||||
VirtioPciDeviceActivator {
|
||||
@ -721,7 +722,6 @@ impl VirtioPciDevice {
|
||||
device: self.device.clone(),
|
||||
queues: Some(queues),
|
||||
device_activated: self.device_activated.clone(),
|
||||
queue_evts: Some(queue_evts),
|
||||
barrier,
|
||||
id: self.id.clone(),
|
||||
}
|
||||
|
@ -145,8 +145,7 @@ impl Vdpa {
|
||||
&mut self,
|
||||
_mem: &GuestMemoryMmap,
|
||||
virtio_interrupt: &Arc<dyn VirtioInterrupt>,
|
||||
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
queue_evts: Vec<EventFd>,
|
||||
queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
|
||||
) -> Result<()> {
|
||||
self.vhost
|
||||
.set_features(self.common.acked_features)
|
||||
@ -155,11 +154,11 @@ impl Vdpa {
|
||||
.set_backend_features(self.backend_features)
|
||||
.map_err(Error::SetBackendFeatures)?;
|
||||
|
||||
for (queue_index, queue) in queues.iter().enumerate() {
|
||||
for (queue_index, queue, queue_evt) in queues.iter() {
|
||||
let queue_max_size = queue.max_size();
|
||||
let queue_size = queue.state.size;
|
||||
self.vhost
|
||||
.set_vring_num(queue_index, queue_size)
|
||||
.set_vring_num(*queue_index, queue_size)
|
||||
.map_err(Error::SetVringNum)?;
|
||||
|
||||
let config_data = VringConfigData {
|
||||
@ -194,11 +193,11 @@ impl Vdpa {
|
||||
};
|
||||
|
||||
self.vhost
|
||||
.set_vring_addr(queue_index, &config_data)
|
||||
.set_vring_addr(*queue_index, &config_data)
|
||||
.map_err(Error::SetVringAddr)?;
|
||||
self.vhost
|
||||
.set_vring_base(
|
||||
queue_index,
|
||||
*queue_index,
|
||||
queue
|
||||
.avail_idx(Ordering::Acquire)
|
||||
.map_err(Error::GetAvailableIndex)?
|
||||
@ -207,15 +206,15 @@ impl Vdpa {
|
||||
.map_err(Error::SetVringBase)?;
|
||||
|
||||
if let Some(eventfd) =
|
||||
virtio_interrupt.notifier(VirtioInterruptType::Queue(queue_index as u16))
|
||||
virtio_interrupt.notifier(VirtioInterruptType::Queue(*queue_index as u16))
|
||||
{
|
||||
self.vhost
|
||||
.set_vring_call(queue_index, &eventfd)
|
||||
.set_vring_call(*queue_index, &eventfd)
|
||||
.map_err(Error::SetVringCall)?;
|
||||
}
|
||||
|
||||
self.vhost
|
||||
.set_vring_kick(queue_index, &queue_evts[queue_index])
|
||||
.set_vring_kick(*queue_index, queue_evt)
|
||||
.map_err(Error::SetVringKick)?;
|
||||
}
|
||||
|
||||
@ -297,10 +296,9 @@ impl VirtioDevice for Vdpa {
|
||||
&mut self,
|
||||
mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
virtio_interrupt: Arc<dyn VirtioInterrupt>,
|
||||
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
queue_evts: Vec<EventFd>,
|
||||
queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
|
||||
) -> ActivateResult {
|
||||
self.activate_vdpa(&mem.memory(), &virtio_interrupt, queues, queue_evts)
|
||||
self.activate_vdpa(&mem.memory(), &virtio_interrupt, queues)
|
||||
.map_err(ActivateError::ActivateVdpa)?;
|
||||
|
||||
// Store the virtio interrupt handler as we need to return it on reset
|
||||
|
@ -292,10 +292,9 @@ impl VirtioDevice for Blk {
|
||||
&mut self,
|
||||
mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
queue_evts: Vec<EventFd>,
|
||||
queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
|
||||
) -> ActivateResult {
|
||||
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
||||
self.common.activate(&queues, &interrupt_cb)?;
|
||||
self.guest_memory = Some(mem.clone());
|
||||
|
||||
let slave_req_handler: Option<MasterReqHandler<SlaveReqHandler>> = None;
|
||||
@ -307,7 +306,6 @@ impl VirtioDevice for Blk {
|
||||
let mut handler = self.vu_common.activate(
|
||||
mem,
|
||||
queues,
|
||||
queue_evts,
|
||||
interrupt_cb,
|
||||
self.common.acked_features,
|
||||
slave_req_handler,
|
||||
|
@ -504,10 +504,9 @@ impl VirtioDevice for Fs {
|
||||
&mut self,
|
||||
mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
queue_evts: Vec<EventFd>,
|
||||
queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
|
||||
) -> ActivateResult {
|
||||
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
||||
self.common.activate(&queues, &interrupt_cb)?;
|
||||
self.guest_memory = Some(mem.clone());
|
||||
|
||||
// Initialize slave communication.
|
||||
@ -547,7 +546,6 @@ impl VirtioDevice for Fs {
|
||||
let mut handler = self.vu_common.activate(
|
||||
mem,
|
||||
queues,
|
||||
queue_evts,
|
||||
interrupt_cb,
|
||||
self.common.acked_features,
|
||||
slave_req_handler,
|
||||
|
@ -167,8 +167,7 @@ pub struct VhostUserEpollHandler<S: VhostUserMasterReqHandler> {
|
||||
pub mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
pub kill_evt: EventFd,
|
||||
pub pause_evt: EventFd,
|
||||
pub queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
pub queue_evts: Vec<EventFd>,
|
||||
pub queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
|
||||
pub virtio_interrupt: Arc<dyn VirtioInterrupt>,
|
||||
pub acked_features: u64,
|
||||
pub acked_protocol_features: u64,
|
||||
@ -224,10 +223,9 @@ impl<S: VhostUserMasterReqHandler> VhostUserEpollHandler<S> {
|
||||
vhost_user
|
||||
.reinitialize_vhost_user(
|
||||
self.mem.memory().deref(),
|
||||
self.queues.iter().map(vm_virtio::clone_queue).collect(),
|
||||
self.queue_evts
|
||||
self.queues
|
||||
.iter()
|
||||
.map(|q| q.try_clone().unwrap())
|
||||
.map(|(i, q, e)| (*i, vm_virtio::clone_queue(q), e.try_clone().unwrap()))
|
||||
.collect(),
|
||||
&self.virtio_interrupt,
|
||||
self.acked_features,
|
||||
@ -299,8 +297,7 @@ impl VhostUserCommon {
|
||||
pub fn activate<T: VhostUserMasterReqHandler>(
|
||||
&mut self,
|
||||
mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
queue_evts: Vec<EventFd>,
|
||||
queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
|
||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||
acked_features: u64,
|
||||
slave_req_handler: Option<MasterReqHandler<T>>,
|
||||
@ -324,8 +321,10 @@ impl VhostUserCommon {
|
||||
.unwrap()
|
||||
.setup_vhost_user(
|
||||
&mem.memory(),
|
||||
queues.iter().map(vm_virtio::clone_queue).collect(),
|
||||
queue_evts.iter().map(|q| q.try_clone().unwrap()).collect(),
|
||||
queues
|
||||
.iter()
|
||||
.map(|(i, q, e)| (*i, vm_virtio::clone_queue(q), e.try_clone().unwrap()))
|
||||
.collect(),
|
||||
&interrupt_cb,
|
||||
acked_features,
|
||||
&slave_req_handler,
|
||||
@ -339,7 +338,6 @@ impl VhostUserCommon {
|
||||
kill_evt,
|
||||
pause_evt,
|
||||
queues,
|
||||
queue_evts,
|
||||
virtio_interrupt: interrupt_cb,
|
||||
acked_features,
|
||||
acked_protocol_features: self.acked_protocol_features,
|
||||
|
@ -272,18 +272,16 @@ impl VirtioDevice for Net {
|
||||
&mut self,
|
||||
mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||
mut queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
mut queue_evts: Vec<EventFd>,
|
||||
mut queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
|
||||
) -> ActivateResult {
|
||||
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
||||
self.common.activate(&queues, &interrupt_cb)?;
|
||||
self.guest_memory = Some(mem.clone());
|
||||
|
||||
let num_queues = queues.len();
|
||||
let event_idx = self.common.feature_acked(VIRTIO_RING_F_EVENT_IDX.into());
|
||||
if self.common.feature_acked(VIRTIO_NET_F_CTRL_VQ.into()) && num_queues % 2 != 0 {
|
||||
let ctrl_queue_index = num_queues - 1;
|
||||
let mut ctrl_queue = queues.remove(ctrl_queue_index);
|
||||
let ctrl_queue_evt = queue_evts.remove(ctrl_queue_index);
|
||||
let (_, mut ctrl_queue, ctrl_queue_evt) = queues.remove(ctrl_queue_index);
|
||||
|
||||
ctrl_queue.set_event_idx(event_idx);
|
||||
|
||||
@ -336,7 +334,6 @@ impl VirtioDevice for Net {
|
||||
let mut handler = self.vu_common.activate(
|
||||
mem,
|
||||
queues,
|
||||
queue_evts,
|
||||
interrupt_cb,
|
||||
backend_acked_features,
|
||||
slave_req_handler,
|
||||
|
@ -151,8 +151,7 @@ impl VhostUserHandle {
|
||||
pub fn setup_vhost_user<S: VhostUserMasterReqHandler>(
|
||||
&mut self,
|
||||
mem: &GuestMemoryMmap,
|
||||
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
queue_evts: Vec<EventFd>,
|
||||
queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
|
||||
virtio_interrupt: &Arc<dyn VirtioInterrupt>,
|
||||
acked_features: u64,
|
||||
slave_req_handler: &Option<MasterReqHandler<S>>,
|
||||
@ -171,9 +170,9 @@ impl VhostUserHandle {
|
||||
// Send set_vring_num here, since it could tell backends, like SPDK,
|
||||
// how many virt queues to be handled, which backend required to know
|
||||
// at early stage.
|
||||
for (queue_index, queue) in queues.iter().enumerate() {
|
||||
for (queue_index, queue, _) in queues.iter() {
|
||||
self.vu
|
||||
.set_vring_num(queue_index, queue.state.size)
|
||||
.set_vring_num(*queue_index, queue.state.size)
|
||||
.map_err(Error::VhostUserSetVringNum)?;
|
||||
}
|
||||
|
||||
@ -184,7 +183,7 @@ impl VhostUserHandle {
|
||||
mmap_size: 0,
|
||||
mmap_offset: 0,
|
||||
num_queues: queues.len() as u16,
|
||||
queue_size: queues[0].state.size,
|
||||
queue_size: queues[0].1.state.size,
|
||||
};
|
||||
let (info, fd) = self
|
||||
.vu
|
||||
@ -202,7 +201,7 @@ impl VhostUserHandle {
|
||||
let num_queues = queues.len() as usize;
|
||||
|
||||
let mut vrings_info = Vec::new();
|
||||
for (queue_index, queue) in queues.into_iter().enumerate() {
|
||||
for (queue_index, queue, queue_evt) in queues.iter() {
|
||||
let actual_size: usize = queue.state.size.try_into().unwrap();
|
||||
|
||||
let config_data = VringConfigData {
|
||||
@ -240,11 +239,11 @@ impl VhostUserHandle {
|
||||
});
|
||||
|
||||
self.vu
|
||||
.set_vring_addr(queue_index, &config_data)
|
||||
.set_vring_addr(*queue_index, &config_data)
|
||||
.map_err(Error::VhostUserSetVringAddr)?;
|
||||
self.vu
|
||||
.set_vring_base(
|
||||
queue_index,
|
||||
*queue_index,
|
||||
queue
|
||||
.avail_idx(Ordering::Acquire)
|
||||
.map_err(Error::GetAvailableIndex)?
|
||||
@ -253,15 +252,15 @@ impl VhostUserHandle {
|
||||
.map_err(Error::VhostUserSetVringBase)?;
|
||||
|
||||
if let Some(eventfd) =
|
||||
virtio_interrupt.notifier(VirtioInterruptType::Queue(queue_index as u16))
|
||||
virtio_interrupt.notifier(VirtioInterruptType::Queue(*queue_index as u16))
|
||||
{
|
||||
self.vu
|
||||
.set_vring_call(queue_index, &eventfd)
|
||||
.set_vring_call(*queue_index, &eventfd)
|
||||
.map_err(Error::VhostUserSetVringCall)?;
|
||||
}
|
||||
|
||||
self.vu
|
||||
.set_vring_kick(queue_index, &queue_evts[queue_index])
|
||||
.set_vring_kick(*queue_index, queue_evt)
|
||||
.map_err(Error::VhostUserSetVringKick)?;
|
||||
}
|
||||
|
||||
@ -326,8 +325,7 @@ impl VhostUserHandle {
|
||||
pub fn reinitialize_vhost_user<S: VhostUserMasterReqHandler>(
|
||||
&mut self,
|
||||
mem: &GuestMemoryMmap,
|
||||
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
queue_evts: Vec<EventFd>,
|
||||
queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
|
||||
virtio_interrupt: &Arc<dyn VirtioInterrupt>,
|
||||
acked_features: u64,
|
||||
acked_protocol_features: u64,
|
||||
@ -339,7 +337,6 @@ impl VhostUserHandle {
|
||||
self.setup_vhost_user(
|
||||
mem,
|
||||
queues,
|
||||
queue_evts,
|
||||
virtio_interrupt,
|
||||
acked_features,
|
||||
slave_req_handler,
|
||||
|
@ -432,15 +432,21 @@ where
|
||||
&mut self,
|
||||
mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
queue_evts: Vec<EventFd>,
|
||||
queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
|
||||
) -> ActivateResult {
|
||||
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
||||
self.common.activate(&queues, &interrupt_cb)?;
|
||||
let (kill_evt, pause_evt) = self.common.dup_eventfds();
|
||||
|
||||
let mut virtqueues = Vec::new();
|
||||
let mut queue_evts = Vec::new();
|
||||
for (_, queue, queue_evt) in queues {
|
||||
virtqueues.push(queue);
|
||||
queue_evts.push(queue_evt);
|
||||
}
|
||||
|
||||
let mut handler = VsockEpollHandler {
|
||||
mem,
|
||||
queues,
|
||||
queues: virtqueues,
|
||||
queue_evts,
|
||||
kill_evt,
|
||||
pause_evt,
|
||||
@ -591,7 +597,6 @@ mod tests {
|
||||
GuestMemoryAtomic::new(ctx.mem.clone()),
|
||||
Arc::new(NoopVirtioInterrupt {}),
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
);
|
||||
match bad_activate {
|
||||
Err(ActivateError::BadActivate) => (),
|
||||
@ -606,14 +611,21 @@ mod tests {
|
||||
memory.clone(),
|
||||
Arc::new(NoopVirtioInterrupt {}),
|
||||
vec![
|
||||
Queue::new(memory.clone(), 256),
|
||||
Queue::new(memory.clone(), 256),
|
||||
Queue::new(memory, 256),
|
||||
],
|
||||
vec![
|
||||
EventFd::new(EFD_NONBLOCK).unwrap(),
|
||||
EventFd::new(EFD_NONBLOCK).unwrap(),
|
||||
EventFd::new(EFD_NONBLOCK).unwrap(),
|
||||
(
|
||||
0,
|
||||
Queue::new(memory.clone(), 256),
|
||||
EventFd::new(EFD_NONBLOCK).unwrap(),
|
||||
),
|
||||
(
|
||||
1,
|
||||
Queue::new(memory.clone(), 256),
|
||||
EventFd::new(EFD_NONBLOCK).unwrap(),
|
||||
),
|
||||
(
|
||||
2,
|
||||
Queue::new(memory, 256),
|
||||
EventFd::new(EFD_NONBLOCK).unwrap(),
|
||||
),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -47,7 +47,7 @@ const WATCHDOG_TIMER_INTERVAL: i64 = 15;
|
||||
const WATCHDOG_TIMEOUT: u64 = WATCHDOG_TIMER_INTERVAL as u64 + 5;
|
||||
|
||||
struct WatchdogEpollHandler {
|
||||
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
queue: Queue<GuestMemoryAtomic<GuestMemoryMmap>>,
|
||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||
queue_evt: EventFd,
|
||||
kill_evt: EventFd,
|
||||
@ -61,7 +61,7 @@ impl WatchdogEpollHandler {
|
||||
// The main queue is very simple - the driver "pings" the device by passing it a (write-only)
|
||||
// descriptor. In response the device writes a 1 into the descriptor and returns it to the driver
|
||||
fn process_queue(&mut self) -> bool {
|
||||
let queue = &mut self.queues[0];
|
||||
let queue = &mut self.queue;
|
||||
let mut used_desc_heads = [(0, 0); QUEUE_SIZE as usize];
|
||||
let mut used_count = 0;
|
||||
for mut desc_chain in queue.iter().unwrap() {
|
||||
@ -291,10 +291,9 @@ impl VirtioDevice for Watchdog {
|
||||
&mut self,
|
||||
_mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||
queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
mut queue_evts: Vec<EventFd>,
|
||||
mut queues: Vec<(usize, Queue<GuestMemoryAtomic<GuestMemoryMmap>>, EventFd)>,
|
||||
) -> ActivateResult {
|
||||
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
||||
self.common.activate(&queues, &interrupt_cb)?;
|
||||
let (kill_evt, pause_evt) = self.common.dup_eventfds();
|
||||
|
||||
let reset_evt = self.reset_evt.try_clone().map_err(|e| {
|
||||
@ -307,10 +306,12 @@ impl VirtioDevice for Watchdog {
|
||||
ActivateError::BadActivate
|
||||
})?;
|
||||
|
||||
let (_, queue, queue_evt) = queues.remove(0);
|
||||
|
||||
let mut handler = WatchdogEpollHandler {
|
||||
queues,
|
||||
queue,
|
||||
interrupt_cb,
|
||||
queue_evt: queue_evts.remove(0),
|
||||
queue_evt,
|
||||
kill_evt,
|
||||
pause_evt,
|
||||
timer,
|
||||
|
Loading…
Reference in New Issue
Block a user