mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-12-22 13:45:20 +00:00
virtio-devices: Handle virtio queues interrupts from transport layer
Instead of relying on the virtio-queue crate to store the information about the MSI-X vectors for each queue, we handle this directly from the PCI transport layer. This is the first step in getting closer to the upstream version of virtio-queue so that we can eventually move fully to the upstream version. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
d3081ff50c
commit
de3e003e3e
@ -139,8 +139,7 @@ pub struct NoopVirtioInterrupt {}
|
||||
impl VirtioInterrupt for NoopVirtioInterrupt {
|
||||
fn trigger(
|
||||
&self,
|
||||
_int_type: &VirtioInterruptType,
|
||||
_queue: Option<&Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
_int_type: VirtioInterruptType,
|
||||
) -> std::result::Result<(), std::io::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -165,12 +165,8 @@ struct BalloonEpollHandler {
|
||||
}
|
||||
|
||||
impl BalloonEpollHandler {
|
||||
fn signal(
|
||||
&self,
|
||||
int_type: &VirtioInterruptType,
|
||||
queue: Option<&Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
) -> result::Result<(), Error> {
|
||||
self.interrupt_cb.trigger(int_type, queue).map_err(|e| {
|
||||
fn signal(&self, int_type: VirtioInterruptType) -> result::Result<(), Error> {
|
||||
self.interrupt_cb.trigger(int_type).map_err(|e| {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
Error::FailedSignal(e)
|
||||
})
|
||||
@ -268,7 +264,7 @@ impl BalloonEpollHandler {
|
||||
.map_err(Error::QueueAddUsed)?;
|
||||
}
|
||||
if used_count > 0 {
|
||||
self.signal(&VirtioInterruptType::Queue, Some(&self.queues[queue_index]))?;
|
||||
self.signal(VirtioInterruptType::Queue(queue_index as u16))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -303,7 +299,7 @@ impl EpollHelperHandler for BalloonEpollHandler {
|
||||
let mut config = self.config.lock().unwrap();
|
||||
config.num_pages =
|
||||
(self.resize_receiver.get_size() >> VIRTIO_BALLOON_PFN_SHIFT) as u32;
|
||||
if let Err(e) = self.signal(&VirtioInterruptType::Config, None) {
|
||||
if let Err(e) = self.signal(VirtioInterruptType::Config) {
|
||||
signal_error = true;
|
||||
Err(e)
|
||||
} else {
|
||||
|
@ -82,6 +82,7 @@ pub struct BlockCounters {
|
||||
}
|
||||
|
||||
struct BlockEpollHandler {
|
||||
queue_index: u16,
|
||||
queue: Queue<GuestMemoryAtomic<GuestMemoryMmap>>,
|
||||
mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
disk_image: Box<dyn AsyncIo>,
|
||||
@ -258,7 +259,7 @@ impl BlockEpollHandler {
|
||||
|
||||
fn signal_used_queue(&self) -> result::Result<(), DeviceError> {
|
||||
self.interrupt_cb
|
||||
.trigger(&VirtioInterruptType::Queue, Some(&self.queue))
|
||||
.trigger(VirtioInterruptType::Queue(self.queue_index))
|
||||
.map_err(|e| {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
DeviceError::FailedSignalingUsedQueue(e)
|
||||
@ -605,6 +606,7 @@ impl VirtioDevice for Block {
|
||||
.map_err(ActivateError::CreateRateLimiter)?;
|
||||
|
||||
let mut handler = BlockEpollHandler {
|
||||
queue_index: i as u16,
|
||||
queue,
|
||||
mem: mem.clone(),
|
||||
disk_image: self
|
||||
|
@ -199,9 +199,9 @@ impl ConsoleEpollHandler {
|
||||
used_count > 0
|
||||
}
|
||||
|
||||
fn signal_used_queue(&self) -> result::Result<(), DeviceError> {
|
||||
fn signal_used_queue(&self, queue_index: u16) -> result::Result<(), DeviceError> {
|
||||
self.interrupt_cb
|
||||
.trigger(&VirtioInterruptType::Queue, Some(&self.queues[0]))
|
||||
.trigger(VirtioInterruptType::Queue(queue_index))
|
||||
.map_err(|e| {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
DeviceError::FailedSignalingUsedQueue(e)
|
||||
@ -239,7 +239,7 @@ impl EpollHelperHandler for ConsoleEpollHandler {
|
||||
error!("Failed to get queue event: {:?}", e);
|
||||
return true;
|
||||
} else if self.process_input_queue() {
|
||||
if let Err(e) = self.signal_used_queue() {
|
||||
if let Err(e) = self.signal_used_queue(0) {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
@ -249,8 +249,11 @@ impl EpollHelperHandler for ConsoleEpollHandler {
|
||||
if let Err(e) = self.output_queue_evt.read() {
|
||||
error!("Failed to get queue event: {:?}", e);
|
||||
return true;
|
||||
} else {
|
||||
self.process_output_queue();
|
||||
} else if self.process_output_queue() {
|
||||
if let Err(e) = self.signal_used_queue(1) {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
INPUT_EVENT => {
|
||||
@ -258,7 +261,7 @@ impl EpollHelperHandler for ConsoleEpollHandler {
|
||||
error!("Failed to get input event: {:?}", e);
|
||||
return true;
|
||||
} else if self.process_input_queue() {
|
||||
if let Err(e) = self.signal_used_queue() {
|
||||
if let Err(e) = self.signal_used_queue(0) {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
@ -268,10 +271,7 @@ impl EpollHelperHandler for ConsoleEpollHandler {
|
||||
if let Err(e) = self.config_evt.read() {
|
||||
error!("Failed to get config event: {:?}", e);
|
||||
return true;
|
||||
} else if let Err(e) = self
|
||||
.interrupt_cb
|
||||
.trigger(&VirtioInterruptType::Config, None)
|
||||
{
|
||||
} else if let Err(e) = self.interrupt_cb.trigger(VirtioInterruptType::Config) {
|
||||
error!("Failed to signal console driver: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
@ -293,7 +293,7 @@ impl EpollHelperHandler for ConsoleEpollHandler {
|
||||
}
|
||||
|
||||
if self.process_input_queue() {
|
||||
if let Err(e) = self.signal_used_queue() {
|
||||
if let Err(e) = self.signal_used_queue(0) {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
@ -492,7 +492,7 @@ impl VirtioDevice for Console {
|
||||
.store(self.common.acked_features, Ordering::Relaxed);
|
||||
|
||||
if self.common.feature_acked(VIRTIO_CONSOLE_F_SIZE) {
|
||||
if let Err(e) = interrupt_cb.trigger(&VirtioInterruptType::Config, None) {
|
||||
if let Err(e) = interrupt_cb.trigger(VirtioInterruptType::Config) {
|
||||
error!("Failed to signal console driver: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
@ -25,20 +25,12 @@ use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
pub enum VirtioInterruptType {
|
||||
Config,
|
||||
Queue,
|
||||
Queue(u16),
|
||||
}
|
||||
|
||||
pub trait VirtioInterrupt: Send + Sync {
|
||||
fn trigger(
|
||||
&self,
|
||||
int_type: &VirtioInterruptType,
|
||||
queue: Option<&Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
) -> std::result::Result<(), std::io::Error>;
|
||||
fn notifier(
|
||||
&self,
|
||||
_int_type: &VirtioInterruptType,
|
||||
_queue: Option<&Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
) -> Option<EventFd> {
|
||||
fn trigger(&self, int_type: VirtioInterruptType) -> std::result::Result<(), std::io::Error>;
|
||||
fn notifier(&self, _int_type: VirtioInterruptType) -> Option<EventFd> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
@ -609,12 +609,9 @@ impl IommuEpollHandler {
|
||||
false
|
||||
}
|
||||
|
||||
fn signal_used_queue(
|
||||
&self,
|
||||
queue: &Queue<GuestMemoryAtomic<GuestMemoryMmap>>,
|
||||
) -> result::Result<(), DeviceError> {
|
||||
fn signal_used_queue(&self, queue_index: u16) -> result::Result<(), DeviceError> {
|
||||
self.interrupt_cb
|
||||
.trigger(&VirtioInterruptType::Queue, Some(queue))
|
||||
.trigger(VirtioInterruptType::Queue(queue_index))
|
||||
.map_err(|e| {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
DeviceError::FailedSignalingUsedQueue(e)
|
||||
@ -644,7 +641,7 @@ impl EpollHelperHandler for IommuEpollHandler {
|
||||
error!("Failed to get queue event: {:?}", e);
|
||||
return true;
|
||||
} else if self.request_queue() {
|
||||
if let Err(e) = self.signal_used_queue(&self.queues[0]) {
|
||||
if let Err(e) = self.signal_used_queue(0) {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
@ -655,7 +652,7 @@ impl EpollHelperHandler for IommuEpollHandler {
|
||||
error!("Failed to get queue event: {:?}", e);
|
||||
return true;
|
||||
} else if self.event_queue() {
|
||||
if let Err(e) = self.signal_used_queue(&self.queues[1]) {
|
||||
if let Err(e) = self.signal_used_queue(1) {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
|
@ -644,13 +644,11 @@ impl MemEpollHandler {
|
||||
(resp_type, resp_state)
|
||||
}
|
||||
|
||||
fn signal(&self, int_type: &VirtioInterruptType) -> result::Result<(), DeviceError> {
|
||||
self.interrupt_cb
|
||||
.trigger(int_type, Some(&self.queue))
|
||||
.map_err(|e| {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
DeviceError::FailedSignalingUsedQueue(e)
|
||||
})
|
||||
fn signal(&self, int_type: VirtioInterruptType) -> result::Result<(), DeviceError> {
|
||||
self.interrupt_cb.trigger(int_type).map_err(|e| {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
DeviceError::FailedSignalingUsedQueue(e)
|
||||
})
|
||||
}
|
||||
|
||||
fn process_queue(&mut self) -> bool {
|
||||
@ -734,7 +732,7 @@ impl EpollHelperHandler for MemEpollHandler {
|
||||
let mut r = config.resize(size);
|
||||
r = match r {
|
||||
Err(e) => Err(e),
|
||||
_ => match self.signal(&VirtioInterruptType::Config) {
|
||||
_ => match self.signal(VirtioInterruptType::Config) {
|
||||
Err(e) => {
|
||||
signal_error = true;
|
||||
Err(Error::ResizeTriggerFail(e))
|
||||
@ -756,7 +754,7 @@ impl EpollHelperHandler for MemEpollHandler {
|
||||
error!("Failed to get queue event: {:?}", e);
|
||||
return true;
|
||||
} else if self.process_queue() {
|
||||
if let Err(e) = self.signal(&VirtioInterruptType::Queue) {
|
||||
if let Err(e) = self.signal(VirtioInterruptType::Queue(0)) {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
|
@ -124,6 +124,7 @@ struct NetEpollHandler {
|
||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||
kill_evt: EventFd,
|
||||
pause_evt: EventFd,
|
||||
queue_index_base: u16,
|
||||
queue_pair: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
queue_evt_pair: Vec<EventFd>,
|
||||
// Always generate interrupts until the driver has signalled to the device.
|
||||
@ -134,12 +135,9 @@ struct NetEpollHandler {
|
||||
}
|
||||
|
||||
impl NetEpollHandler {
|
||||
fn signal_used_queue(
|
||||
&self,
|
||||
queue: &Queue<GuestMemoryAtomic<GuestMemoryMmap>>,
|
||||
) -> result::Result<(), DeviceError> {
|
||||
fn signal_used_queue(&self, queue_index: u16) -> result::Result<(), DeviceError> {
|
||||
self.interrupt_cb
|
||||
.trigger(&VirtioInterruptType::Queue, Some(queue))
|
||||
.trigger(VirtioInterruptType::Queue(queue_index))
|
||||
.map_err(|e| {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
DeviceError::FailedSignalingUsedQueue(e)
|
||||
@ -182,7 +180,7 @@ impl NetEpollHandler {
|
||||
.map_err(DeviceError::NetQueuePair)?
|
||||
|| !self.driver_awake
|
||||
{
|
||||
self.signal_used_queue(&self.queue_pair[1])?;
|
||||
self.signal_used_queue(self.queue_index_base + 1)?;
|
||||
debug!("Signalling TX queue");
|
||||
} else {
|
||||
debug!("Not signalling TX queue");
|
||||
@ -211,7 +209,7 @@ impl NetEpollHandler {
|
||||
.map_err(DeviceError::NetQueuePair)?
|
||||
|| !self.driver_awake
|
||||
{
|
||||
self.signal_used_queue(&self.queue_pair[0])?;
|
||||
self.signal_used_queue(self.queue_index_base)?;
|
||||
debug!("Signalling RX queue");
|
||||
} else {
|
||||
debug!("Not signalling RX queue");
|
||||
@ -651,6 +649,7 @@ impl VirtioDevice for Net {
|
||||
rx_rate_limiter,
|
||||
tx_rate_limiter,
|
||||
},
|
||||
queue_index_base: (i * 2) as u16,
|
||||
queue_pair,
|
||||
queue_evt_pair,
|
||||
interrupt_cb: interrupt_cb.clone(),
|
||||
|
@ -213,7 +213,7 @@ impl PmemEpollHandler {
|
||||
|
||||
fn signal_used_queue(&self) -> result::Result<(), DeviceError> {
|
||||
self.interrupt_cb
|
||||
.trigger(&VirtioInterruptType::Queue, Some(&self.queue))
|
||||
.trigger(VirtioInterruptType::Queue(0))
|
||||
.map_err(|e| {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
DeviceError::FailedSignalingUsedQueue(e)
|
||||
|
@ -76,7 +76,7 @@ impl RngEpollHandler {
|
||||
|
||||
fn signal_used_queue(&self) -> result::Result<(), DeviceError> {
|
||||
self.interrupt_cb
|
||||
.trigger(&VirtioInterruptType::Queue, Some(&self.queues[0]))
|
||||
.trigger(VirtioInterruptType::Queue(0))
|
||||
.map_err(|e| {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
DeviceError::FailedSignalingUsedQueue(e)
|
||||
|
@ -24,6 +24,7 @@ pub struct VirtioPciCommonConfigState {
|
||||
pub driver_feature_select: u32,
|
||||
pub queue_select: u16,
|
||||
pub msix_config: u16,
|
||||
pub msix_queues: Vec<u16>,
|
||||
}
|
||||
|
||||
impl VersionMapped for VirtioPciCommonConfigState {}
|
||||
@ -57,6 +58,7 @@ pub struct VirtioPciCommonConfig {
|
||||
pub driver_feature_select: u32,
|
||||
pub queue_select: u16,
|
||||
pub msix_config: Arc<AtomicU16>,
|
||||
pub msix_queues: Arc<Mutex<Vec<u16>>>,
|
||||
}
|
||||
|
||||
impl VirtioPciCommonConfig {
|
||||
@ -68,6 +70,7 @@ impl VirtioPciCommonConfig {
|
||||
driver_feature_select: self.driver_feature_select,
|
||||
queue_select: self.queue_select,
|
||||
msix_config: self.msix_config.load(Ordering::Acquire),
|
||||
msix_queues: self.msix_queues.lock().unwrap().clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,6 +81,7 @@ impl VirtioPciCommonConfig {
|
||||
self.driver_feature_select = state.driver_feature_select;
|
||||
self.queue_select = state.queue_select;
|
||||
self.msix_config.store(state.msix_config, Ordering::Release);
|
||||
*(self.msix_queues.lock().unwrap()) = state.msix_queues.clone();
|
||||
}
|
||||
|
||||
pub fn read(
|
||||
@ -164,7 +168,7 @@ impl VirtioPciCommonConfig {
|
||||
0x12 => queues.len() as u16, // num_queues
|
||||
0x16 => self.queue_select,
|
||||
0x18 => self.with_queue(queues, |q| q.state.size).unwrap_or(0),
|
||||
0x1a => self.with_queue(queues, |q| q.state.vector).unwrap_or(0),
|
||||
0x1a => self.msix_queues.lock().unwrap()[self.queue_select as usize],
|
||||
0x1c => {
|
||||
if self.with_queue(queues, |q| q.state.ready).unwrap_or(false) {
|
||||
1
|
||||
@ -191,7 +195,7 @@ impl VirtioPciCommonConfig {
|
||||
0x10 => self.msix_config.store(value, Ordering::Release),
|
||||
0x16 => self.queue_select = value,
|
||||
0x18 => self.with_queue_mut(queues, |q| q.state.size = value),
|
||||
0x1a => self.with_queue_mut(queues, |q| q.state.vector = value),
|
||||
0x1a => self.msix_queues.lock().unwrap()[self.queue_select as usize] = value,
|
||||
0x1c => self.with_queue_mut(queues, |q| q.enable(value == 1)),
|
||||
_ => {
|
||||
warn!("invalid virtio register word write: 0x{:x}", offset);
|
||||
@ -376,6 +380,7 @@ mod tests {
|
||||
driver_feature_select: 0x0,
|
||||
queue_select: 0xff,
|
||||
msix_config: Arc::new(AtomicU16::new(0)),
|
||||
msix_queues: Arc::new(Mutex::new(vec![0; 3])),
|
||||
};
|
||||
|
||||
let dev = Arc::new(Mutex::new(DummyDevice(0)));
|
||||
|
@ -267,7 +267,6 @@ struct QueueState {
|
||||
max_size: u16,
|
||||
size: u16,
|
||||
ready: bool,
|
||||
vector: u16,
|
||||
desc_table: u64,
|
||||
avail_ring: u64,
|
||||
used_ring: u64,
|
||||
@ -358,6 +357,7 @@ impl VirtioPciDevice {
|
||||
for _ in locked_device.queue_max_sizes().iter() {
|
||||
queue_evts.push(EventFd::new(EFD_NONBLOCK)?)
|
||||
}
|
||||
let num_queues = locked_device.queue_max_sizes().len();
|
||||
let queues = locked_device
|
||||
.queue_max_sizes()
|
||||
.iter()
|
||||
@ -429,6 +429,7 @@ impl VirtioPciDevice {
|
||||
driver_feature_select: 0,
|
||||
queue_select: 0,
|
||||
msix_config: Arc::new(AtomicU16::new(VIRTQ_MSI_NO_VECTOR)),
|
||||
msix_queues: Arc::new(Mutex::new(vec![VIRTQ_MSI_NO_VECTOR; num_queues])),
|
||||
},
|
||||
msix_config,
|
||||
msix_num,
|
||||
@ -453,6 +454,7 @@ impl VirtioPciDevice {
|
||||
virtio_pci_device.virtio_interrupt = Some(Arc::new(VirtioInterruptMsix::new(
|
||||
msix_config.clone(),
|
||||
virtio_pci_device.common_config.msix_config.clone(),
|
||||
virtio_pci_device.common_config.msix_queues.clone(),
|
||||
virtio_pci_device.interrupt_source_group.clone(),
|
||||
)));
|
||||
}
|
||||
@ -471,7 +473,6 @@ impl VirtioPciDevice {
|
||||
max_size: q.max_size(),
|
||||
size: q.state.size,
|
||||
ready: q.state.ready,
|
||||
vector: q.state.vector,
|
||||
desc_table: q.state.desc_table.0,
|
||||
avail_ring: q.state.avail_ring.0,
|
||||
used_ring: q.state.used_ring.0,
|
||||
@ -490,7 +491,6 @@ impl VirtioPciDevice {
|
||||
for (i, queue) in self.queues.iter_mut().enumerate() {
|
||||
queue.state.size = state.queues[i].size;
|
||||
queue.state.ready = state.queues[i].ready;
|
||||
queue.state.vector = state.queues[i].vector;
|
||||
queue.state.desc_table = GuestAddress(state.queues[i].desc_table);
|
||||
queue.state.avail_ring = GuestAddress(state.queues[i].avail_ring);
|
||||
queue.state.used_ring = GuestAddress(state.queues[i].used_ring);
|
||||
@ -716,6 +716,7 @@ impl VirtioTransport for VirtioPciDevice {
|
||||
pub struct VirtioInterruptMsix {
|
||||
msix_config: Arc<Mutex<MsixConfig>>,
|
||||
config_vector: Arc<AtomicU16>,
|
||||
queues_vectors: Arc<Mutex<Vec<u16>>>,
|
||||
interrupt_source_group: Arc<dyn InterruptSourceGroup>,
|
||||
}
|
||||
|
||||
@ -723,30 +724,24 @@ impl VirtioInterruptMsix {
|
||||
pub fn new(
|
||||
msix_config: Arc<Mutex<MsixConfig>>,
|
||||
config_vector: Arc<AtomicU16>,
|
||||
queues_vectors: Arc<Mutex<Vec<u16>>>,
|
||||
interrupt_source_group: Arc<dyn InterruptSourceGroup>,
|
||||
) -> Self {
|
||||
VirtioInterruptMsix {
|
||||
msix_config,
|
||||
config_vector,
|
||||
queues_vectors,
|
||||
interrupt_source_group,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VirtioInterrupt for VirtioInterruptMsix {
|
||||
fn trigger(
|
||||
&self,
|
||||
int_type: &VirtioInterruptType,
|
||||
queue: Option<&Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
) -> std::result::Result<(), std::io::Error> {
|
||||
fn trigger(&self, int_type: VirtioInterruptType) -> std::result::Result<(), std::io::Error> {
|
||||
let vector = match int_type {
|
||||
VirtioInterruptType::Config => self.config_vector.load(Ordering::Acquire),
|
||||
VirtioInterruptType::Queue => {
|
||||
if let Some(q) = queue {
|
||||
q.state.vector
|
||||
} else {
|
||||
0
|
||||
}
|
||||
VirtioInterruptType::Queue(queue_index) => {
|
||||
self.queues_vectors.lock().unwrap()[queue_index as usize]
|
||||
}
|
||||
};
|
||||
|
||||
@ -770,19 +765,11 @@ impl VirtioInterrupt for VirtioInterruptMsix {
|
||||
.trigger(vector as InterruptIndex)
|
||||
}
|
||||
|
||||
fn notifier(
|
||||
&self,
|
||||
int_type: &VirtioInterruptType,
|
||||
queue: Option<&Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
) -> Option<EventFd> {
|
||||
fn notifier(&self, int_type: VirtioInterruptType) -> Option<EventFd> {
|
||||
let vector = match int_type {
|
||||
VirtioInterruptType::Config => self.config_vector.load(Ordering::Acquire),
|
||||
VirtioInterruptType::Queue => {
|
||||
if let Some(q) = queue {
|
||||
q.state.vector
|
||||
} else {
|
||||
0
|
||||
}
|
||||
VirtioInterruptType::Queue(queue_index) => {
|
||||
self.queues_vectors.lock().unwrap()[queue_index as usize]
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -253,7 +253,7 @@ impl VhostUserHandle {
|
||||
.map_err(Error::VhostUserSetVringBase)?;
|
||||
|
||||
if let Some(eventfd) =
|
||||
virtio_interrupt.notifier(&VirtioInterruptType::Queue, Some(&queue))
|
||||
virtio_interrupt.notifier(VirtioInterruptType::Queue(queue_index as u16))
|
||||
{
|
||||
self.vu
|
||||
.set_vring_call(queue_index, &eventfd)
|
||||
|
@ -102,14 +102,11 @@ where
|
||||
/// Signal the guest driver that we've used some virtio buffers that it had previously made
|
||||
/// available.
|
||||
///
|
||||
fn signal_used_queue(
|
||||
&self,
|
||||
queue: &Queue<GuestMemoryAtomic<GuestMemoryMmap>>,
|
||||
) -> result::Result<(), DeviceError> {
|
||||
fn signal_used_queue(&self, queue_index: u16) -> result::Result<(), DeviceError> {
|
||||
debug!("vsock: raising IRQ");
|
||||
|
||||
self.interrupt_cb
|
||||
.trigger(&VirtioInterruptType::Queue, Some(queue))
|
||||
.trigger(VirtioInterruptType::Queue(queue_index))
|
||||
.map_err(|e| {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
DeviceError::FailedSignalingUsedQueue(e)
|
||||
@ -155,7 +152,7 @@ where
|
||||
}
|
||||
|
||||
if used_count > 0 {
|
||||
self.signal_used_queue(&self.queues[0])
|
||||
self.signal_used_queue(0)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
@ -198,7 +195,7 @@ where
|
||||
}
|
||||
|
||||
if used_count > 0 {
|
||||
self.signal_used_queue(&self.queues[1])
|
||||
self.signal_used_queue(1)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
@ -617,8 +614,8 @@ mod tests {
|
||||
let ctx = test_ctx.create_epoll_handler_context();
|
||||
let memory = GuestMemoryAtomic::new(test_ctx.mem.clone());
|
||||
|
||||
let queue = Queue::new(memory, 256);
|
||||
assert!(ctx.handler.signal_used_queue(&queue).is_ok());
|
||||
let _queue: Queue<GuestMemoryAtomic<GuestMemoryMmap>> = Queue::new(memory, 256);
|
||||
assert!(ctx.handler.signal_used_queue(0).is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,7 +170,7 @@ mod tests {
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use virtio_queue::{defs::VIRTQ_DESC_F_NEXT, defs::VIRTQ_DESC_F_WRITE, Queue};
|
||||
use virtio_queue::{defs::VIRTQ_DESC_F_NEXT, defs::VIRTQ_DESC_F_WRITE};
|
||||
use vm_memory::{GuestAddress, GuestMemoryAtomic};
|
||||
use vm_virtio::queue::testing::VirtQueue as GuestQ;
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
@ -180,8 +180,7 @@ mod tests {
|
||||
impl VirtioInterrupt for NoopVirtioInterrupt {
|
||||
fn trigger(
|
||||
&self,
|
||||
_int_type: &VirtioInterruptType,
|
||||
_queue: Option<&Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
|
||||
_int_type: VirtioInterruptType,
|
||||
) -> std::result::Result<(), std::io::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ impl WatchdogEpollHandler {
|
||||
|
||||
fn signal_used_queue(&self) -> result::Result<(), DeviceError> {
|
||||
self.interrupt_cb
|
||||
.trigger(&VirtioInterruptType::Queue, Some(&self.queues[0]))
|
||||
.trigger(VirtioInterruptType::Queue(0))
|
||||
.map_err(|e| {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
DeviceError::FailedSignalingUsedQueue(e)
|
||||
|
@ -17,8 +17,8 @@ use vm_memory::{Address, Bytes, GuestAddress, GuestMemory};
|
||||
use crate::defs::{
|
||||
DEFAULT_AVAIL_RING_ADDR, DEFAULT_DESC_TABLE_ADDR, DEFAULT_USED_RING_ADDR,
|
||||
VIRTQ_AVAIL_ELEMENT_SIZE, VIRTQ_AVAIL_RING_HEADER_SIZE, VIRTQ_AVAIL_RING_META_SIZE,
|
||||
VIRTQ_MSI_NO_VECTOR, VIRTQ_USED_ELEMENT_SIZE, VIRTQ_USED_F_NO_NOTIFY,
|
||||
VIRTQ_USED_RING_HEADER_SIZE, VIRTQ_USED_RING_META_SIZE,
|
||||
VIRTQ_USED_ELEMENT_SIZE, VIRTQ_USED_F_NO_NOTIFY, VIRTQ_USED_RING_HEADER_SIZE,
|
||||
VIRTQ_USED_RING_META_SIZE,
|
||||
};
|
||||
use crate::{
|
||||
error, AccessPlatform, AvailIter, Descriptor, Error, QueueStateGuard, QueueStateT,
|
||||
@ -58,9 +58,6 @@ pub struct QueueState {
|
||||
/// Guest physical address of the used ring.
|
||||
pub used_ring: GuestAddress,
|
||||
|
||||
/// Interrupt vector
|
||||
pub vector: u16,
|
||||
|
||||
/// Access platform handler
|
||||
pub access_platform: Option<Arc<dyn AccessPlatform>>,
|
||||
}
|
||||
@ -200,7 +197,6 @@ impl QueueStateT for QueueState {
|
||||
next_used: Wrapping(0),
|
||||
event_idx_enabled: false,
|
||||
signalled_used: None,
|
||||
vector: VIRTQ_MSI_NO_VECTOR,
|
||||
access_platform: None,
|
||||
}
|
||||
}
|
||||
@ -266,7 +262,6 @@ impl QueueStateT for QueueState {
|
||||
self.next_used = Wrapping(0);
|
||||
self.signalled_used = None;
|
||||
self.event_idx_enabled = false;
|
||||
self.vector = VIRTQ_MSI_NO_VECTOR;
|
||||
}
|
||||
|
||||
fn lock(&mut self) -> <Self as QueueStateGuard>::G {
|
||||
|
Loading…
Reference in New Issue
Block a user