Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion devices/src/pvmemcontrol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ impl PciDevice for PvmemcontrolPciDevice {
reg_idx: usize,
offset: u64,
data: &[u8],
) -> (Option<BarReprogrammingParams>, Option<Arc<Barrier>>) {
) -> (Vec<BarReprogrammingParams>, Option<Arc<Barrier>>) {
(
self.configuration
.write_config_register(reg_idx, offset, data),
Expand Down
4 changes: 2 additions & 2 deletions devices/src/pvpanic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ impl PvPanicDevice {
let command: [u8; 2] = [0x03, 0x01];
let bar_reprogram = configuration.write_config_register(1, 0, &command);
assert!(
bar_reprogram.is_none(),
bar_reprogram.is_empty(),
"No bar reprogrammig is expected from writing to the COMMAND register"
);

Expand Down Expand Up @@ -160,7 +160,7 @@ impl PciDevice for PvPanicDevice {
reg_idx: usize,
offset: u64,
data: &[u8],
) -> (Option<BarReprogrammingParams>, Option<Arc<Barrier>>) {
) -> (Vec<BarReprogrammingParams>, Option<Arc<Barrier>>) {
(
self.configuration
.write_config_register(reg_idx, offset, data),
Expand Down
6 changes: 3 additions & 3 deletions pci/src/bus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ impl PciDevice for PciRoot {
reg_idx: usize,
offset: u64,
data: &[u8],
) -> (Option<BarReprogrammingParams>, Option<Arc<Barrier>>) {
) -> (Vec<BarReprogrammingParams>, Option<Arc<Barrier>>) {
(
self.config.write_config_register(reg_idx, offset, data),
None,
Expand Down Expand Up @@ -262,7 +262,7 @@ impl PciConfigIo {
let (bar_reprogram, ret) = device.write_config_register(register, offset, data);

// Move the device's BAR if needed
if let Some(params) = bar_reprogram {
for params in &bar_reprogram {
if let Err(e) = pci_bus.device_reloc.move_bar(
params.old_base,
params.new_base,
Expand Down Expand Up @@ -387,7 +387,7 @@ impl PciConfigMmio {
let (bar_reprogram, _) = device.write_config_register(register, offset, data);

// Move the device's BAR if needed
if let Some(params) = bar_reprogram {
for params in &bar_reprogram {
if let Err(e) = pci_bus.device_reloc.move_bar(
params.old_base,
params.new_base,
Expand Down
40 changes: 37 additions & 3 deletions pci/src/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ use crate::{MsixConfig, PciInterruptPin};
// The number of 32bit registers in the config space, 4096 bytes.
const NUM_CONFIGURATION_REGISTERS: usize = 1024;

pub(crate) const COMMAND_REG: usize = 1;
pub(crate) const COMMAND_REG_MEMORY_SPACE_MASK: u32 = 0x0000_0002;
const STATUS_REG: usize = 1;
const STATUS_REG_CAPABILITIES_USED_MASK: u32 = 0x0010_0000;
const BAR0_REG: usize = 4;
Expand Down Expand Up @@ -436,6 +438,7 @@ pub struct PciConfiguration {
last_capability: Option<(usize, usize)>,
msix_cap_reg_idx: Option<usize>,
msix_config: Option<Arc<Mutex<MsixConfig>>>,
pending_bar_reprogram: Vec<BarReprogrammingParams>,
}

/// See pci_regs.h in kernel
Expand Down Expand Up @@ -630,6 +633,7 @@ impl PciConfiguration {
last_capability,
msix_cap_reg_idx,
msix_config,
pending_bar_reprogram: Vec::new(),
}
}

Expand Down Expand Up @@ -912,9 +916,9 @@ impl PciConfiguration {
reg_idx: usize,
offset: u64,
data: &[u8],
) -> Option<BarReprogrammingParams> {
) -> Vec<BarReprogrammingParams> {
if offset as usize + data.len() > 4 {
return None;
return Vec::new();
}

// Handle potential write to MSI-X message control register
Expand Down Expand Up @@ -944,7 +948,29 @@ impl PciConfiguration {
_ => (),
}

self.detect_bar_reprogramming(reg_idx, data)
if let Some(param) = self.detect_bar_reprogramming(reg_idx, data) {
self.pending_bar_reprogram.push(param);
}

if !self.pending_bar_reprogram.is_empty() {
// Return bar reprogramming only if the MSE bit is enabled;
if self.read_config_register(COMMAND_REG) & COMMAND_REG_MEMORY_SPACE_MASK
== COMMAND_REG_MEMORY_SPACE_MASK
{
info!(
"BAR reprogramming parameter is returned: {:x?}",
self.pending_bar_reprogram
);
return self.pending_bar_reprogram.drain(..).collect();
} else {
info!(
"MSE bit is disabled. No BAR reprogramming parameter is returned: {:x?}",
self.pending_bar_reprogram
);
}
}

Vec::new()
}

pub fn read_config_register(&self, reg_idx: usize) -> u32 {
Expand Down Expand Up @@ -1067,6 +1093,14 @@ impl PciConfiguration {

None
}

pub(crate) fn pending_bar_reprogram(&self) -> Vec<BarReprogrammingParams> {
self.pending_bar_reprogram.clone()
}

pub(crate) fn clear_pending_bar_reprogram(&mut self) {
self.pending_bar_reprogram = Vec::new();
}
}

impl Pausable for PciConfiguration {}
Expand Down
4 changes: 2 additions & 2 deletions pci/src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl Display for Error {
}
}

#[derive(Clone, Copy)]
#[derive(Clone, Copy, Debug)]
pub struct BarReprogrammingParams {
pub old_base: u64,
pub new_base: u64,
Expand Down Expand Up @@ -87,7 +87,7 @@ pub trait PciDevice: Send {
reg_idx: usize,
offset: u64,
data: &[u8],
) -> (Option<BarReprogrammingParams>, Option<Arc<Barrier>>);
) -> (Vec<BarReprogrammingParams>, Option<Arc<Barrier>>);
/// Gets a register from the configuration space.
/// * `reg_idx` - The index of the config register to read.
fn read_config_register(&mut self, reg_idx: usize) -> u32;
Expand Down
25 changes: 22 additions & 3 deletions pci/src/vfio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1242,7 +1242,7 @@ impl VfioCommon {
reg_idx: usize,
offset: u64,
data: &[u8],
) -> (Option<BarReprogrammingParams>, Option<Arc<Barrier>>) {
) -> (Vec<BarReprogrammingParams>, Option<Arc<Barrier>>) {
// When the guest wants to write to a BAR, we trap it into
// our local configuration space. We're not reprogramming
// VFIO device.
Expand Down Expand Up @@ -1292,7 +1292,26 @@ impl VfioCommon {
// to the device region to update the MSI Enable bit.
self.vfio_wrapper.write_config((reg + offset) as u32, data);

(None, None)
// Return pending BAR repgrogramming if MSE bit is set
let mut ret_param = self.configuration.pending_bar_reprogram();
if !ret_param.is_empty() {
if self.read_config_register(crate::configuration::COMMAND_REG)
& crate::configuration::COMMAND_REG_MEMORY_SPACE_MASK
== crate::configuration::COMMAND_REG_MEMORY_SPACE_MASK
{
info!("BAR reprogramming parameter is returned: {:x?}", ret_param);
self.configuration.clear_pending_bar_reprogram();
} else {
info!(
"MSE bit is disabled. No BAR reprogramming parameter is returned: {:x?}",
ret_param
);

ret_param = Vec::new();
}
}

(ret_param, None)
}

pub(crate) fn read_config_register(&mut self, reg_idx: usize) -> u32 {
Expand Down Expand Up @@ -1852,7 +1871,7 @@ impl PciDevice for VfioPciDevice {
reg_idx: usize,
offset: u64,
data: &[u8],
) -> (Option<BarReprogrammingParams>, Option<Arc<Barrier>>) {
) -> (Vec<BarReprogrammingParams>, Option<Arc<Barrier>>) {
self.common.write_config_register(reg_idx, offset, data)
}

Expand Down
2 changes: 1 addition & 1 deletion pci/src/vfio_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ impl PciDevice for VfioUserPciDevice {
reg_idx: usize,
offset: u64,
data: &[u8],
) -> (Option<BarReprogrammingParams>, Option<Arc<Barrier>>) {
) -> (Vec<BarReprogrammingParams>, Option<Arc<Barrier>>) {
self.common.write_config_register(reg_idx, offset, data)
}

Expand Down
4 changes: 2 additions & 2 deletions virtio-devices/src/transport/pci_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -912,7 +912,7 @@ impl PciDevice for VirtioPciDevice {
reg_idx: usize,
offset: u64,
data: &[u8],
) -> (Option<BarReprogrammingParams>, Option<Arc<Barrier>>) {
) -> (Vec<BarReprogrammingParams>, Option<Arc<Barrier>>) {
// Handle the special case where the capability VIRTIO_PCI_CAP_PCI_CFG
// is accessed. This capability has a special meaning as it allows the
// guest to access other capabilities without mapping the PCI BAR.
Expand All @@ -922,7 +922,7 @@ impl PciDevice for VirtioPciDevice {
<= self.cap_pci_cfg_info.offset + self.cap_pci_cfg_info.cap.bytes().len()
{
let offset = base + offset as usize - self.cap_pci_cfg_info.offset;
(None, self.write_cap_pci_cfg(offset, data))
(Vec::new(), self.write_cap_pci_cfg(offset, data))
} else {
(
self.configuration
Expand Down
Loading