From 8da7c13e261d323f5162eaab1d6f2c119dae10b1 Mon Sep 17 00:00:00 2001 From: Bo Chen Date: Mon, 12 May 2025 23:02:06 +0000 Subject: [PATCH] pci: Handle pending BAR reprogramming for VFIO devices properly The way how we handle PCI configuration space for vfio and vfio-user devices are different from the rest of PCI devices. Besides accesses to BAR registers (trapped to access the shadowing PCI config space we maintained), accesses to other registers (including the COMMAND register) are handled directly by the underline vfio or vfio-user device. This patch adds the proper handling of pending BAR reprogramming for vfio and vfio-user devices. Signed-off-by: Bo Chen --- pci/src/configuration.rs | 12 ++++++++++-- pci/src/vfio.rs | 21 ++++++++++++++++++++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/pci/src/configuration.rs b/pci/src/configuration.rs index 6d7d33efe..036894d8b 100644 --- a/pci/src/configuration.rs +++ b/pci/src/configuration.rs @@ -18,8 +18,8 @@ use crate::{MsixConfig, PciInterruptPin}; // The number of 32bit registers in the config space, 4096 bytes. const NUM_CONFIGURATION_REGISTERS: usize = 1024; -const COMMAND_REG: usize = 1; -const COMMAND_REG_MEMORY_SPACE_MASK: u32 = 0x0000_0002; +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; @@ -1093,6 +1093,14 @@ impl PciConfiguration { None } + + pub(crate) fn pending_bar_reprogram(&self) -> Vec { + self.pending_bar_reprogram.clone() + } + + pub(crate) fn clear_pending_bar_reprogram(&mut self) { + self.pending_bar_reprogram = Vec::new(); + } } impl Pausable for PciConfiguration {} diff --git a/pci/src/vfio.rs b/pci/src/vfio.rs index 671efef56..f4b2ce97c 100644 --- a/pci/src/vfio.rs +++ b/pci/src/vfio.rs @@ -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); - (Vec::new(), 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 {