diff options
author | Xiong Zhang <xiong.y.zhang@intel.corp-partner.google.com> | 2019-06-06 10:04:03 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-12-17 10:25:05 +0000 |
commit | 5aef6474862a94c85ac90757fe8ba7376a3ed1d6 (patch) | |
tree | 21858b0dfb8d0a76da1630d35e9b37e2805d5ba1 /devices/src/pci/vfio_pci.rs | |
parent | 0f4c5fff7a9a4283572b23d5ad9c9af6c125bb15 (diff) | |
download | crosvm-5aef6474862a94c85ac90757fe8ba7376a3ed1d6.tar crosvm-5aef6474862a94c85ac90757fe8ba7376a3ed1d6.tar.gz crosvm-5aef6474862a94c85ac90757fe8ba7376a3ed1d6.tar.bz2 crosvm-5aef6474862a94c85ac90757fe8ba7376a3ed1d6.tar.lz crosvm-5aef6474862a94c85ac90757fe8ba7376a3ed1d6.tar.xz crosvm-5aef6474862a94c85ac90757fe8ba7376a3ed1d6.tar.zst crosvm-5aef6474862a94c85ac90757fe8ba7376a3ed1d6.zip |
vfio: Disable igd stolen memory
igd stolen memory isn't a standard pci resource, so guest couldn't access it. Once guest i915 driver see its size is zero, i915 won't use it. Here sotlen memory's size register PciCfg 0x51 is forced to zero. BUG=chromium:992270 TEST=crosvm run --vfio=/sys/devices/pci0000:00/0000:00:02.0, pass through host igd into linux guest. The physical local display lightup and show linux desktop. Change-Id: I1a0a6edda5d92d32307ea8025ef96677ca62c125 Signed-off-by: Xiong Zhang <xiong.y.zhang@intel.corp-partner.google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1688368 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Diffstat (limited to 'devices/src/pci/vfio_pci.rs')
-rw-r--r-- | devices/src/pci/vfio_pci.rs | 53 |
1 files changed, 49 insertions, 4 deletions
diff --git a/devices/src/pci/vfio_pci.rs b/devices/src/pci/vfio_pci.rs index 07c7b60..f0cebde 100644 --- a/devices/src/pci/vfio_pci.rs +++ b/devices/src/pci/vfio_pci.rs @@ -18,10 +18,16 @@ use vm_control::{ }; use crate::pci::pci_device::{Error as PciDeviceError, PciDevice}; -use crate::pci::PciInterruptPin; +use crate::pci::{PciClassCode, PciInterruptPin}; use crate::vfio::{VfioDevice, VfioIrqType}; +const PCI_VENDOR_ID: u32 = 0x0; +const INTEL_VENDOR_ID: u16 = 0x8086; +const PCI_COMMAND: u32 = 0x4; +const PCI_COMMAND_MEMORY: u8 = 0x2; +const PCI_BASE_CLASS_CODE: u32 = 0x0B; + const PCI_INTERRUPT_PIN: u32 = 0x3D; struct VfioPciConfig { @@ -298,6 +304,10 @@ struct IoInfo { bar_index: u32, } +enum DeviceData { + IntelGfxData, +} + /// Implements the Vfio Pci device, then a pci device is added into vm pub struct VfioPciDevice { device: Arc<VfioDevice>, @@ -310,6 +320,7 @@ pub struct VfioPciDevice { msi_cap: Option<VfioMsiCap>, irq_type: Option<VfioIrqType>, vm_socket_mem: VmMemoryControlRequestSocket, + device_data: Option<DeviceData>, // scratch MemoryMapping to avoid unmap beform vm exit mem: Vec<MemoryMapping>, @@ -326,6 +337,17 @@ impl VfioPciDevice { let config = VfioPciConfig::new(Arc::clone(&dev)); let msi_cap = VfioMsiCap::new(&config, vfio_device_socket_irq); + let vendor_id = config.read_config_word(PCI_VENDOR_ID); + let class_code = config.read_config_byte(PCI_BASE_CLASS_CODE); + + let is_intel_gfx = vendor_id == INTEL_VENDOR_ID + && class_code == PciClassCode::DisplayController.get_register_value(); + let device_data = if is_intel_gfx { + Some(DeviceData::IntelGfxData) + } else { + None + }; + VfioPciDevice { device: dev, config, @@ -337,10 +359,23 @@ impl VfioPciDevice { msi_cap, irq_type: None, vm_socket_mem: vfio_device_socket_mem, + device_data, mem: Vec::new(), } } + fn is_intel_gfx(&self) -> bool { + let mut ret = false; + + if let Some(device_data) = &self.device_data { + match *device_data { + DeviceData::IntelGfxData => ret = true, + } + } + + ret + } + fn find_region(&self, addr: u64) -> Option<MmioInfo> { for mmio_info in self.mmio_regions.iter() { if addr >= mmio_info.start && addr < mmio_info.start + mmio_info.length { @@ -510,9 +545,6 @@ impl VfioPciDevice { } } -const PCI_COMMAND: u8 = 0x4; -const PCI_COMMAND_MEMORY: u8 = 0x2; - impl PciDevice for VfioPciDevice { fn debug_label(&self) -> String { "vfio pci device".to_string() @@ -641,6 +673,14 @@ impl PciDevice for VfioPciDevice { ); } + // Quirk, enable igd memory for guest vga arbitrate, otherwise kernel vga arbitrate + // driver doesn't claim this vga device, then xorg couldn't boot up. + if self.is_intel_gfx() { + let mut cmd = self.config.read_config_byte(PCI_COMMAND); + cmd |= PCI_COMMAND_MEMORY; + self.config.write_config_byte(cmd, PCI_COMMAND); + } + Ok(ranges) } @@ -673,6 +713,11 @@ impl PciDevice for VfioPciDevice { } } + // Quirk for intel graphic, set stolen memory size to 0 in pci_cfg[0x51] + if self.is_intel_gfx() && reg == 0x50 { + config &= 0xffff00ff; + } + config } |