virtio: fix dev_id initialization for virtio-pci and vfio device on aarch64 platform vfio: fix the problem of dma mapping failed syscall: add syscall "newfstatat" in x86_64-unknown-linux-gnu target kernel_config: update kernel config 5.10 on aarch64 platform machine/standard_vm: fix inappropriate file open permissions migration: fix an errors during the PL011 device state restore migration: fix an error during migration interface on aarch64 fix spelling errors in project (cherry picked from commit a12a13829fa5d788667e11b886c254760e6a4579)
615 lines
24 KiB
Diff
615 lines
24 KiB
Diff
From 4ba032f8967c660b8eafb3adaf9b44b95474c7c3 Mon Sep 17 00:00:00 2001
|
|
From: Ming Yang <yangming73@huawei.com>
|
|
Date: Wed, 11 Aug 2021 14:52:26 +0800
|
|
Subject: [PATCH 8/8] virtio: fix dev_id initialization for virtio-pci and vfio
|
|
device on aarch64 platform
|
|
|
|
On aarch64 platform, dev_id information is necessary for virtio-pci device
|
|
to send msix.
|
|
|
|
This commit fixes the dev_id initialization in virtio_pci transport module,
|
|
and set dev_id information according to the number of bus where the device
|
|
is attached to.
|
|
|
|
Signed-off-by: Ming Yang <yangming73@huawei.com>
|
|
---
|
|
pci/src/config.rs | 2 +
|
|
pci/src/msix.rs | 63 ++++++++++++++------
|
|
pci/src/root_port.rs | 10 +---
|
|
vfio/src/vfio_pci.rs | 34 +++++++----
|
|
virtio/src/virtio_pci.rs | 123 ++++++++++++++++++++++++---------------
|
|
5 files changed, 150 insertions(+), 82 deletions(-)
|
|
|
|
diff --git a/pci/src/config.rs b/pci/src/config.rs
|
|
index d7bd348..873fe7a 100644
|
|
--- a/pci/src/config.rs
|
|
+++ b/pci/src/config.rs
|
|
@@ -221,6 +221,7 @@ pub enum RegionType {
|
|
}
|
|
|
|
/// Registered bar.
|
|
+#[derive(Clone)]
|
|
pub struct Bar {
|
|
region_type: RegionType,
|
|
address: u64,
|
|
@@ -266,6 +267,7 @@ pub enum PcieDevType {
|
|
}
|
|
|
|
/// Configuration space of PCI/PCIe device.
|
|
+#[derive(Clone)]
|
|
pub struct PciConfig {
|
|
/// Configuration space data.
|
|
pub config: Vec<u8>,
|
|
diff --git a/pci/src/msix.rs b/pci/src/msix.rs
|
|
index 2831af4..5c04575 100644
|
|
--- a/pci/src/msix.rs
|
|
+++ b/pci/src/msix.rs
|
|
@@ -10,16 +10,19 @@
|
|
// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
// See the Mulan PSL v2 for more details.
|
|
|
|
-use std::sync::{Arc, Mutex};
|
|
+use std::sync::atomic::{AtomicU16, Ordering};
|
|
+use std::sync::{Arc, Mutex, Weak};
|
|
|
|
use address_space::{GuestAddress, Region, RegionOps};
|
|
use hypervisor::{MsiVector, KVM_FDS};
|
|
use migration::{DeviceStateDesc, FieldDesc, MigrationHook, MigrationManager, StateTransfer};
|
|
use util::{byte_code::ByteCode, num_ops::round_up};
|
|
|
|
-use crate::config::{CapId, PciConfig, RegionType};
|
|
+use crate::config::{CapId, PciConfig, RegionType, SECONDARY_BUS_NUM};
|
|
use crate::errors::{Result, ResultExt};
|
|
-use crate::{le_read_u16, le_read_u32, le_read_u64, le_write_u16, le_write_u32, le_write_u64};
|
|
+use crate::{
|
|
+ le_read_u16, le_read_u32, le_read_u64, le_write_u16, le_write_u32, le_write_u64, PciBus,
|
|
+};
|
|
|
|
pub const MSIX_TABLE_ENTRY_SIZE: u16 = 16;
|
|
pub const MSIX_TABLE_SIZE_MAX: u16 = 0x7ff;
|
|
@@ -71,7 +74,7 @@ pub struct Msix {
|
|
pub func_masked: bool,
|
|
pub enabled: bool,
|
|
pub msix_cap_offset: u16,
|
|
- pub dev_id: u16,
|
|
+ pub dev_id: Arc<AtomicU16>,
|
|
}
|
|
|
|
impl Msix {
|
|
@@ -90,7 +93,7 @@ impl Msix {
|
|
func_masked: true,
|
|
enabled: true,
|
|
msix_cap_offset,
|
|
- dev_id,
|
|
+ dev_id: Arc::new(AtomicU16::new(dev_id)),
|
|
};
|
|
msix.mask_all_vectors();
|
|
msix
|
|
@@ -148,7 +151,11 @@ impl Msix {
|
|
le_write_u64(&mut self.pba, offset, old_val & pending_bit).unwrap();
|
|
}
|
|
|
|
- fn register_memory_region(msix: Arc<Mutex<Self>>, region: &Region, dev_id: u16) -> Result<()> {
|
|
+ fn register_memory_region(
|
|
+ msix: Arc<Mutex<Self>>,
|
|
+ region: &Region,
|
|
+ dev_id: Arc<AtomicU16>,
|
|
+ ) -> Result<()> {
|
|
let locked_msix = msix.lock().unwrap();
|
|
let table_size = locked_msix.table.len() as u64;
|
|
let pba_size = locked_msix.pba.len() as u64;
|
|
@@ -170,7 +177,7 @@ impl Msix {
|
|
let is_masked: bool = locked_msix.is_vector_masked(vector);
|
|
if was_masked && !is_masked {
|
|
locked_msix.clear_pending_vector(vector);
|
|
- locked_msix.notify(vector, dev_id);
|
|
+ locked_msix.notify(vector, dev_id.load(Ordering::Acquire));
|
|
}
|
|
|
|
true
|
|
@@ -264,7 +271,7 @@ impl StateTransfer for Msix {
|
|
state.func_masked = self.func_masked;
|
|
state.enabled = self.enabled;
|
|
state.msix_cap_offset = self.msix_cap_offset;
|
|
- state.dev_id = self.dev_id;
|
|
+ state.dev_id = self.dev_id.load(Ordering::Acquire);
|
|
|
|
Ok(state.as_bytes().to_vec())
|
|
}
|
|
@@ -280,7 +287,7 @@ impl StateTransfer for Msix {
|
|
self.func_masked = msix_state.func_masked;
|
|
self.enabled = msix_state.enabled;
|
|
self.msix_cap_offset = msix_state.msix_cap_offset;
|
|
- self.dev_id = msix_state.dev_id;
|
|
+ self.dev_id = Arc::new(AtomicU16::new(msix_state.dev_id));
|
|
|
|
Ok(())
|
|
}
|
|
@@ -318,7 +325,7 @@ impl MigrationHook for Msix {
|
|
msg_data: msg.data,
|
|
masked: false,
|
|
#[cfg(target_arch = "aarch64")]
|
|
- dev_id: self.dev_id as u32,
|
|
+ dev_id: self.dev_id.load(Ordering::Acquire) as u32,
|
|
};
|
|
if let Err(e) = locked_irq_table.add_msi_route(allocated_gsi, msi_vector) {
|
|
bail!("Failed to add msi route to global irq routing table: {}", e);
|
|
@@ -330,7 +337,7 @@ impl MigrationHook for Msix {
|
|
|
|
if self.is_vector_pending(vector) {
|
|
self.clear_pending_vector(vector);
|
|
- send_msix(msg, self.dev_id);
|
|
+ send_msix(msg, self.dev_id.load(Ordering::Acquire));
|
|
}
|
|
}
|
|
}
|
|
@@ -377,7 +384,12 @@ fn send_msix(msg: Message, dev_id: u16) {
|
|
}
|
|
|
|
/// MSI-X initialization.
|
|
-pub fn init_msix(bar_id: usize, vector_nr: u32, config: &mut PciConfig, dev_id: u16) -> Result<()> {
|
|
+pub fn init_msix(
|
|
+ bar_id: usize,
|
|
+ vector_nr: u32,
|
|
+ config: &mut PciConfig,
|
|
+ dev_id: Arc<AtomicU16>,
|
|
+) -> Result<()> {
|
|
if vector_nr > MSIX_TABLE_SIZE_MAX as u32 + 1 {
|
|
bail!("Too many msix vectors.");
|
|
}
|
|
@@ -401,7 +413,7 @@ pub fn init_msix(bar_id: usize, vector_nr: u32, config: &mut PciConfig, dev_id:
|
|
table_size,
|
|
pba_size,
|
|
msix_cap_offset as u16,
|
|
- dev_id,
|
|
+ dev_id.load(Ordering::Acquire),
|
|
)));
|
|
let bar_size = ((table_size + pba_size) as u64).next_power_of_two();
|
|
let region = Region::init_container_region(bar_size);
|
|
@@ -415,6 +427,17 @@ pub fn init_msix(bar_id: usize, vector_nr: u32, config: &mut PciConfig, dev_id:
|
|
Ok(())
|
|
}
|
|
|
|
+pub fn update_dev_id(parent_bus: &Weak<Mutex<PciBus>>, devfn: u8, dev_id: &Arc<AtomicU16>) {
|
|
+ let bus_num = parent_bus
|
|
+ .upgrade()
|
|
+ .unwrap()
|
|
+ .lock()
|
|
+ .unwrap()
|
|
+ .number(SECONDARY_BUS_NUM as usize);
|
|
+ let device_id = ((bus_num as u16) << 8) | (devfn as u16);
|
|
+ dev_id.store(device_id, Ordering::Release);
|
|
+}
|
|
+
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
@@ -425,9 +448,15 @@ mod tests {
|
|
let mut pci_config = PciConfig::new(PCI_CONFIG_SPACE_SIZE, 2);
|
|
|
|
// Too many vectors.
|
|
- assert!(init_msix(0, MSIX_TABLE_SIZE_MAX as u32 + 2, &mut pci_config, 0).is_err());
|
|
-
|
|
- init_msix(1, 2, &mut pci_config, 0).unwrap();
|
|
+ assert!(init_msix(
|
|
+ 0,
|
|
+ MSIX_TABLE_SIZE_MAX as u32 + 2,
|
|
+ &mut pci_config,
|
|
+ Arc::new(AtomicU16::new(0))
|
|
+ )
|
|
+ .is_err());
|
|
+
|
|
+ init_msix(1, 2, &mut pci_config, Arc::new(AtomicU16::new(0))).unwrap();
|
|
let msix_cap_start = 64_u8;
|
|
assert_eq!(pci_config.last_cap_end, 64 + MSIX_CAP_SIZE as u16);
|
|
// Capabilities pointer
|
|
@@ -492,7 +521,7 @@ mod tests {
|
|
#[test]
|
|
fn test_write_config() {
|
|
let mut pci_config = PciConfig::new(PCI_CONFIG_SPACE_SIZE, 2);
|
|
- init_msix(0, 2, &mut pci_config, 0).unwrap();
|
|
+ init_msix(0, 2, &mut pci_config, Arc::new(AtomicU16::new(0))).unwrap();
|
|
let msix = pci_config.msix.as_ref().unwrap();
|
|
let mut locked_msix = msix.lock().unwrap();
|
|
locked_msix.enabled = false;
|
|
diff --git a/pci/src/root_port.rs b/pci/src/root_port.rs
|
|
index ba1b5f7..948e31d 100644
|
|
--- a/pci/src/root_port.rs
|
|
+++ b/pci/src/root_port.rs
|
|
@@ -10,6 +10,7 @@
|
|
// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
// See the Mulan PSL v2 for more details.
|
|
|
|
+use std::sync::atomic::AtomicU16;
|
|
use std::sync::{Arc, Mutex, Weak};
|
|
|
|
use address_space::Region;
|
|
@@ -117,13 +118,8 @@ impl PciDevOps for RootPort {
|
|
config_space[PREF_MEMORY_LIMIT as usize] = PREF_MEM_RANGE_64BIT;
|
|
self.config
|
|
.add_pcie_cap(self.devfn, self.port_num, PcieDevType::RootPort as u8)?;
|
|
- #[cfg(target_arch = "aarch64")]
|
|
- {
|
|
- self.dev_id = self.set_dev_id(0, self.devfn);
|
|
- init_msix(0, 1, &mut self.config, self.dev_id)?;
|
|
- }
|
|
- #[cfg(target_arch = "x86_64")]
|
|
- init_msix(0, 1, &mut self.config, 0)?;
|
|
+
|
|
+ init_msix(0, 1, &mut self.config, Arc::new(AtomicU16::new(0)))?;
|
|
|
|
let parent_bus = self.parent_bus.upgrade().unwrap();
|
|
let mut locked_parent_bus = parent_bus.lock().unwrap();
|
|
diff --git a/vfio/src/vfio_pci.rs b/vfio/src/vfio_pci.rs
|
|
index 5cc674a..640ff20 100644
|
|
--- a/vfio/src/vfio_pci.rs
|
|
+++ b/vfio/src/vfio_pci.rs
|
|
@@ -14,6 +14,7 @@ use std::collections::HashMap;
|
|
use std::mem::size_of;
|
|
use std::os::unix::io::{AsRawFd, RawFd};
|
|
use std::path::Path;
|
|
+use std::sync::atomic::{AtomicU16, Ordering};
|
|
use std::sync::{Arc, Mutex, Weak};
|
|
|
|
use byteorder::{ByteOrder, LittleEndian};
|
|
@@ -36,9 +37,9 @@ use pci::config::{
|
|
};
|
|
use pci::errors::Result as PciResult;
|
|
use pci::msix::{
|
|
- is_msix_enabled, Msix, MSIX_CAP_CONTROL, MSIX_CAP_ENABLE, MSIX_CAP_FUNC_MASK, MSIX_CAP_ID,
|
|
- MSIX_CAP_SIZE, MSIX_CAP_TABLE, MSIX_TABLE_BIR, MSIX_TABLE_ENTRY_SIZE, MSIX_TABLE_OFFSET,
|
|
- MSIX_TABLE_SIZE_MAX,
|
|
+ is_msix_enabled, update_dev_id, Msix, MSIX_CAP_CONTROL, MSIX_CAP_ENABLE, MSIX_CAP_FUNC_MASK,
|
|
+ MSIX_CAP_ID, MSIX_CAP_SIZE, MSIX_CAP_TABLE, MSIX_TABLE_BIR, MSIX_TABLE_ENTRY_SIZE,
|
|
+ MSIX_TABLE_OFFSET, MSIX_TABLE_SIZE_MAX,
|
|
};
|
|
use pci::{
|
|
le_read_u16, le_read_u32, le_write_u16, le_write_u32, ranges_overlap, PciBus, PciDevOps,
|
|
@@ -93,7 +94,7 @@ pub struct VfioPciDevice {
|
|
// Maintains a list of GSI with irqfds that are registered to kvm.
|
|
gsi_msi_routes: Arc<Mutex<Vec<GsiMsiRoute>>>,
|
|
devfn: u8,
|
|
- dev_id: u16,
|
|
+ dev_id: Arc<AtomicU16>,
|
|
name: String,
|
|
parent_bus: Weak<Mutex<PciBus>>,
|
|
}
|
|
@@ -119,7 +120,7 @@ impl VfioPciDevice {
|
|
vfio_bars: Arc::new(Mutex::new(Vec::with_capacity(PCI_NUM_BARS as usize))),
|
|
gsi_msi_routes: Arc::new(Mutex::new(Vec::new())),
|
|
devfn,
|
|
- dev_id: 0,
|
|
+ dev_id: Arc::new(AtomicU16::new(0)),
|
|
name,
|
|
parent_bus,
|
|
})
|
|
@@ -404,7 +405,7 @@ impl VfioPciDevice {
|
|
table_size,
|
|
table_size / 128,
|
|
cap_offset as u16,
|
|
- self.dev_id,
|
|
+ self.dev_id.load(Ordering::Acquire),
|
|
)));
|
|
self.pci_config.msix = Some(msix.clone());
|
|
|
|
@@ -418,6 +419,9 @@ impl VfioPciDevice {
|
|
|
|
let cloned_dev = self.vfio_device.clone();
|
|
let cloned_gsi_routes = self.gsi_msi_routes.clone();
|
|
+ let parent_bus = self.parent_bus.clone();
|
|
+ let dev_id = self.dev_id.clone();
|
|
+ let devfn = self.devfn;
|
|
let write = move |data: &[u8], _: GuestAddress, offset: u64| -> bool {
|
|
let mut locked_msix = msix.lock().unwrap();
|
|
locked_msix.table[offset as usize..(offset as usize + data.len())]
|
|
@@ -429,13 +433,15 @@ impl VfioPciDevice {
|
|
}
|
|
|
|
let entry = locked_msix.get_message(vector as u16);
|
|
+
|
|
+ update_dev_id(&parent_bus, devfn, &dev_id);
|
|
let msix_vector = MsiVector {
|
|
msg_addr_lo: entry.address_lo,
|
|
msg_addr_hi: entry.address_hi,
|
|
msg_data: entry.data,
|
|
masked: false,
|
|
#[cfg(target_arch = "aarch64")]
|
|
- dev_id: locked_msix.dev_id as u32,
|
|
+ dev_id: dev_id.load(Ordering::Acquire) as u32,
|
|
};
|
|
|
|
let mut locked_gsi_routes = cloned_gsi_routes.lock().unwrap();
|
|
@@ -707,7 +713,7 @@ impl PciDevOps for VfioPciDevice {
|
|
.lock()
|
|
.unwrap()
|
|
.number(SECONDARY_BUS_NUM as usize);
|
|
- self.dev_id = self.set_dev_id(bus_num, self.devfn);
|
|
+ self.dev_id = Arc::new(AtomicU16::new(self.set_dev_id(bus_num, self.devfn)));
|
|
}
|
|
|
|
self.msix_info = Some(PciResultExt::chain_err(self.get_msix_info(), || {
|
|
@@ -799,7 +805,8 @@ impl PciDevOps for VfioPciDevice {
|
|
}
|
|
|
|
if ranges_overlap(offset, end, COMMAND as usize, COMMAND as usize + 4) {
|
|
- self.pci_config.write(offset, data, self.dev_id);
|
|
+ self.pci_config
|
|
+ .write(offset, data, self.dev_id.load(Ordering::Acquire));
|
|
|
|
if le_read_u32(&self.pci_config.config, offset).unwrap() & COMMAND_MEMORY_SPACE as u32
|
|
!= 0
|
|
@@ -822,7 +829,8 @@ impl PciDevOps for VfioPciDevice {
|
|
}
|
|
}
|
|
} else if ranges_overlap(offset, end, BAR_0 as usize, (BAR_5 as usize) + REG_SIZE) {
|
|
- self.pci_config.write(offset, data, self.dev_id);
|
|
+ self.pci_config
|
|
+ .write(offset, data, self.dev_id.load(Ordering::Acquire));
|
|
|
|
if size == 4 && LittleEndian::read_u32(data) != 0xffff_ffff {
|
|
let parent_bus = self.parent_bus.upgrade().unwrap();
|
|
@@ -838,7 +846,8 @@ impl PciDevOps for VfioPciDevice {
|
|
}
|
|
} else if ranges_overlap(offset, end, cap_offset, cap_offset + MSIX_CAP_SIZE as usize) {
|
|
let was_enable = is_msix_enabled(cap_offset, &self.pci_config.config);
|
|
- self.pci_config.write(offset, data, self.dev_id);
|
|
+ self.pci_config
|
|
+ .write(offset, data, self.dev_id.load(Ordering::Acquire));
|
|
let is_enable = is_msix_enabled(cap_offset, &self.pci_config.config);
|
|
|
|
if !was_enable && is_enable {
|
|
@@ -853,7 +862,8 @@ impl PciDevOps for VfioPciDevice {
|
|
}
|
|
}
|
|
} else {
|
|
- self.pci_config.write(offset, data, self.dev_id);
|
|
+ self.pci_config
|
|
+ .write(offset, data, self.dev_id.load(Ordering::Acquire));
|
|
}
|
|
}
|
|
|
|
diff --git a/virtio/src/virtio_pci.rs b/virtio/src/virtio_pci.rs
|
|
index 03645dc..aaf009e 100644
|
|
--- a/virtio/src/virtio_pci.rs
|
|
+++ b/virtio/src/virtio_pci.rs
|
|
@@ -24,6 +24,7 @@ use pci::config::{
|
|
VENDOR_ID,
|
|
};
|
|
use pci::errors::{ErrorKind, Result as PciResult, ResultExt};
|
|
+use pci::msix::update_dev_id;
|
|
use pci::{config::PciConfig, init_msix, le_write_u16, ranges_overlap, PciBus, PciDevOps};
|
|
use util::byte_code::ByteCode;
|
|
use vmm_sys_util::eventfd::EventFd;
|
|
@@ -459,13 +460,14 @@ pub struct VirtioPciState {
|
|
}
|
|
|
|
/// Virtio-PCI device structure
|
|
+#[derive(Clone)]
|
|
pub struct VirtioPciDevice {
|
|
/// Name of this device
|
|
name: String,
|
|
/// The entity of virtio device
|
|
device: Arc<Mutex<dyn VirtioDevice>>,
|
|
/// Device id
|
|
- dev_id: u16,
|
|
+ dev_id: Arc<AtomicU16>,
|
|
/// Devfn
|
|
devfn: u8,
|
|
/// If this device is activated or not.
|
|
@@ -500,7 +502,7 @@ impl VirtioPciDevice {
|
|
VirtioPciDevice {
|
|
name,
|
|
device,
|
|
- dev_id: 0_u16,
|
|
+ dev_id: Arc::new(AtomicU16::new(0)),
|
|
devfn,
|
|
device_activated: Arc::new(AtomicBool::new(false)),
|
|
sys_mem,
|
|
@@ -518,7 +520,7 @@ impl VirtioPciDevice {
|
|
fn assign_interrupt_cb(&mut self) {
|
|
let cloned_common_cfg = self.common_config.clone();
|
|
let cloned_msix = self.config.msix.clone();
|
|
- let dev_id = self.dev_id;
|
|
+ let dev_id = self.dev_id.clone();
|
|
let cb = Arc::new(Box::new(
|
|
move |int_type: &VirtioInterruptType, queue: Option<&Queue>| {
|
|
let vector = match int_type {
|
|
@@ -533,7 +535,9 @@ impl VirtioPciDevice {
|
|
};
|
|
|
|
if let Some(msix) = &cloned_msix {
|
|
- msix.lock().unwrap().notify(vector, dev_id);
|
|
+ msix.lock()
|
|
+ .unwrap()
|
|
+ .notify(vector, dev_id.load(Ordering::Acquire));
|
|
} else {
|
|
bail!("Failed to send interrupt, msix does not exist");
|
|
}
|
|
@@ -618,14 +622,7 @@ impl VirtioPciDevice {
|
|
true
|
|
};
|
|
|
|
- let cloned_virtio_dev = self.device.clone();
|
|
- let cloned_common_cfg = self.common_config.clone();
|
|
- let cloned_virtio_queue = self.queues.clone();
|
|
- let cloned_activated_flag = self.device_activated.clone();
|
|
- let cloned_notify_evts = self.notify_eventfds.clone();
|
|
- let cloned_sys_mem = self.sys_mem.clone();
|
|
- let cloned_int_cb = self.interrupt_cb.clone();
|
|
- let cloned_msix = self.config.msix.as_ref().unwrap().clone();
|
|
+ let cloned_pci_device = self.clone();
|
|
let common_write = move |data: &[u8], _addr: GuestAddress, offset: u64| -> bool {
|
|
let value = match data.len() {
|
|
1 => data[0] as u32,
|
|
@@ -639,13 +636,18 @@ impl VirtioPciDevice {
|
|
return false;
|
|
}
|
|
};
|
|
- let old_dev_status = cloned_common_cfg.lock().unwrap().device_status;
|
|
+ let old_dev_status = cloned_pci_device
|
|
+ .common_config
|
|
+ .lock()
|
|
+ .unwrap()
|
|
+ .device_status;
|
|
|
|
- if let Err(e) = cloned_common_cfg.lock().unwrap().write_common_config(
|
|
- &cloned_virtio_dev,
|
|
- offset,
|
|
- value,
|
|
- ) {
|
|
+ if let Err(e) = cloned_pci_device
|
|
+ .common_config
|
|
+ .lock()
|
|
+ .unwrap()
|
|
+ .write_common_config(&cloned_pci_device.device.clone(), offset, value)
|
|
+ {
|
|
error!(
|
|
"Failed to read common config of virtio-pci device, error is {}",
|
|
e.display_chain(),
|
|
@@ -653,21 +655,29 @@ impl VirtioPciDevice {
|
|
return false;
|
|
}
|
|
|
|
- if !cloned_activated_flag.load(Ordering::Acquire)
|
|
- && cloned_common_cfg.lock().unwrap().check_device_status(
|
|
- CONFIG_STATUS_ACKNOWLEDGE
|
|
- | CONFIG_STATUS_DRIVER
|
|
- | CONFIG_STATUS_DRIVER_OK
|
|
- | CONFIG_STATUS_FEATURES_OK,
|
|
- CONFIG_STATUS_FAILED,
|
|
- )
|
|
+ if !cloned_pci_device.device_activated.load(Ordering::Acquire)
|
|
+ && cloned_pci_device
|
|
+ .common_config
|
|
+ .lock()
|
|
+ .unwrap()
|
|
+ .check_device_status(
|
|
+ CONFIG_STATUS_ACKNOWLEDGE
|
|
+ | CONFIG_STATUS_DRIVER
|
|
+ | CONFIG_STATUS_DRIVER_OK
|
|
+ | CONFIG_STATUS_FEATURES_OK,
|
|
+ CONFIG_STATUS_FAILED,
|
|
+ )
|
|
{
|
|
- let queue_type = cloned_common_cfg.lock().unwrap().queue_type;
|
|
- let queues_config = &cloned_common_cfg.lock().unwrap().queues_config;
|
|
- let mut locked_queues = cloned_virtio_queue.lock().unwrap();
|
|
+ let queue_type = cloned_pci_device.common_config.lock().unwrap().queue_type;
|
|
+ let queues_config = &cloned_pci_device
|
|
+ .common_config
|
|
+ .lock()
|
|
+ .unwrap()
|
|
+ .queues_config;
|
|
+ let mut locked_queues = cloned_pci_device.queues.lock().unwrap();
|
|
for q_config in queues_config.iter() {
|
|
let queue = Queue::new(*q_config, queue_type).unwrap();
|
|
- if !queue.is_valid(&cloned_sys_mem) {
|
|
+ if !queue.is_valid(&cloned_pci_device.sys_mem) {
|
|
error!("Failed to activate device: Invalid queue");
|
|
return false;
|
|
}
|
|
@@ -675,10 +685,10 @@ impl VirtioPciDevice {
|
|
locked_queues.push(arc_queue.clone());
|
|
}
|
|
|
|
- let queue_evts = cloned_notify_evts.clone().events;
|
|
- if let Some(cb) = cloned_int_cb.clone() {
|
|
- if let Err(e) = cloned_virtio_dev.lock().unwrap().activate(
|
|
- cloned_sys_mem.clone(),
|
|
+ let queue_evts = cloned_pci_device.notify_eventfds.clone().events;
|
|
+ if let Some(cb) = cloned_pci_device.interrupt_cb.clone() {
|
|
+ if let Err(e) = cloned_pci_device.device.lock().unwrap().activate(
|
|
+ cloned_pci_device.sys_mem.clone(),
|
|
cb,
|
|
&locked_queues,
|
|
queue_evts,
|
|
@@ -689,20 +699,43 @@ impl VirtioPciDevice {
|
|
error!("Failed to activate device: No interrupt callback");
|
|
return false;
|
|
}
|
|
- cloned_activated_flag.store(true, Ordering::Release);
|
|
+ cloned_pci_device
|
|
+ .device_activated
|
|
+ .store(true, Ordering::Release);
|
|
+
|
|
+ update_dev_id(
|
|
+ &cloned_pci_device.parent_bus,
|
|
+ cloned_pci_device.devfn,
|
|
+ &cloned_pci_device.dev_id,
|
|
+ );
|
|
}
|
|
|
|
- if old_dev_status != 0 && cloned_common_cfg.lock().unwrap().device_status == 0 {
|
|
- let mut locked_queues = cloned_virtio_queue.lock().unwrap();
|
|
+ if old_dev_status != 0
|
|
+ && cloned_pci_device
|
|
+ .common_config
|
|
+ .lock()
|
|
+ .unwrap()
|
|
+ .device_status
|
|
+ == 0
|
|
+ {
|
|
+ let mut locked_queues = cloned_pci_device.queues.lock().unwrap();
|
|
locked_queues.clear();
|
|
- cloned_activated_flag.store(false, Ordering::Release);
|
|
+ cloned_pci_device
|
|
+ .device_activated
|
|
+ .store(false, Ordering::Release);
|
|
+ let cloned_msix = cloned_pci_device.config.msix.as_ref().unwrap().clone();
|
|
cloned_msix.lock().unwrap().reset();
|
|
- if let Err(e) = cloned_virtio_dev.lock().unwrap().reset() {
|
|
+ if let Err(e) = cloned_pci_device.device.lock().unwrap().reset() {
|
|
error!(
|
|
"Failed to reset virtio device, error is {}",
|
|
e.display_chain()
|
|
);
|
|
}
|
|
+ update_dev_id(
|
|
+ &cloned_pci_device.parent_bus,
|
|
+ cloned_pci_device.devfn,
|
|
+ &cloned_pci_device.dev_id,
|
|
+ );
|
|
}
|
|
|
|
true
|
|
@@ -874,15 +907,12 @@ impl PciDevOps for VirtioPciDevice {
|
|
self.modern_mem_region_map(notify_cap)?;
|
|
|
|
let nvectors = self.device.lock().unwrap().queue_num() + 1;
|
|
- #[cfg(target_arch = "aarch64")]
|
|
- {
|
|
- self.dev_id = self.set_dev_id(0, self.devfn);
|
|
- }
|
|
+
|
|
init_msix(
|
|
VIRTIO_PCI_MSIX_BAR_IDX as usize,
|
|
nvectors as u32,
|
|
&mut self.config,
|
|
- self.dev_id,
|
|
+ self.dev_id.clone(),
|
|
)?;
|
|
|
|
self.assign_interrupt_cb();
|
|
@@ -950,7 +980,8 @@ impl PciDevOps for VirtioPciDevice {
|
|
return;
|
|
}
|
|
|
|
- self.config.write(offset, data, self.dev_id);
|
|
+ self.config
|
|
+ .write(offset, data, self.dev_id.clone().load(Ordering::Acquire));
|
|
if ranges_overlap(
|
|
offset,
|
|
end,
|
|
@@ -1388,7 +1419,7 @@ mod tests {
|
|
VIRTIO_PCI_MSIX_BAR_IDX as usize,
|
|
virtio_pci.device.lock().unwrap().queue_num() as u32 + 1,
|
|
&mut virtio_pci.config,
|
|
- virtio_pci.dev_id,
|
|
+ virtio_pci.dev_id.clone(),
|
|
)
|
|
.unwrap();
|
|
// Prepare valid queue config
|
|
--
|
|
2.25.1
|
|
|