pci: Detect BAR reprogramming

Based on the value being written to the BAR, the implementation can
now detect if the BAR is being moved to another address. If that is the
case, it invokes move_bar() function from the DeviceRelocation trait.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf
2019-10-28 10:50:32 -07:00
committed by Samuel Ortiz
parent 04a449d3f3
commit 149b61b213
7 changed files with 197 additions and 28 deletions
+43 -10
View File
@@ -9,6 +9,7 @@ use crate::device::{DeviceRelocation, Error as PciDeviceError, PciDevice};
use byteorder::{ByteOrder, LittleEndian};
use devices::BusDevice;
use std;
use std::ops::DerefMut;
use std::sync::Arc;
use std::sync::Mutex;
use vm_memory::{Address, GuestAddress, GuestUsize};
@@ -75,7 +76,7 @@ pub struct PciBus {
/// Devices attached to this bus.
/// Device 0 is host bridge.
devices: Vec<Arc<Mutex<dyn PciDevice>>>,
_device_reloc: Arc<dyn DeviceRelocation>,
device_reloc: Arc<dyn DeviceRelocation>,
}
impl PciBus {
@@ -86,7 +87,7 @@ impl PciBus {
PciBus {
devices,
_device_reloc: device_reloc,
device_reloc,
}
}
@@ -185,10 +186,26 @@ impl PciConfigIo {
return;
}
if let Some(d) = self.pci_bus.lock().unwrap().devices.get(device) {
d.lock()
.unwrap()
.write_config_register(register, offset, data);
let pci_bus = self.pci_bus.lock().unwrap();
if let Some(d) = pci_bus.devices.get(device) {
let mut device = d.lock().unwrap();
// Find out if one of the device's BAR is being reprogrammed
let bar_reprog_params = device.detect_bar_reprogramming(register, data);
// Update the register value
device.write_config_register(register, offset, data);
// Reprogram the BAR if needed
if let Some(params) = bar_reprog_params {
pci_bus.device_reloc.move_bar(
params.old_base,
params.new_base,
params.len,
device.deref_mut(),
params.region_type,
);
}
}
}
@@ -285,10 +302,26 @@ impl PciConfigMmio {
return;
}
if let Some(d) = self.pci_bus.lock().unwrap().devices.get(device) {
d.lock()
.unwrap()
.write_config_register(register, offset, data);
let pci_bus = self.pci_bus.lock().unwrap();
if let Some(d) = pci_bus.devices.get(device) {
let mut device = d.lock().unwrap();
// Find out if one of the device's BAR is being reprogrammed
let bar_reprog_params = device.detect_bar_reprogramming(register, data);
// Update the register value
device.write_config_register(register, offset, data);
// Reprogram the BAR if needed
if let Some(params) = bar_reprog_params {
pci_bus.device_reloc.move_bar(
params.old_base,
params.new_base,
params.len,
device.deref_mut(),
params.region_type,
);
}
}
}
}