From 7f7b8ef3b01372bdb8310ad4c843e80a98190371 Mon Sep 17 00:00:00 2001 From: Xiong Zhang Date: Wed, 15 Jun 2022 10:21:54 +0800 Subject: [PATCH] x86_64: Change each pci device's vcfg mmio size from 4k to 8k Extend pci device's vcfg mmio size frome 4k to 8k, the first page is trapped by crosvm, the second page is share memory between guest and crosvm, so that guest could read/write it directly without vm exit. BUG=b:194391459 TEST=check vcfg mmio size for each pci device Change-Id: If5ac75b4dc8a829cabce4370e7592f23600e4ef8 Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3813136 Reviewed-by: Daniel Verkamp Commit-Queue: Daniel Verkamp Reviewed-by: Victor Ding Tested-by: Daniel Verkamp --- devices/src/pci/pci_root.rs | 10 +++++++--- x86_64/src/lib.rs | 5 +++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/devices/src/pci/pci_root.rs b/devices/src/pci/pci_root.rs index 13dd91485d..7037112e9f 100644 --- a/devices/src/pci/pci_root.rs +++ b/devices/src/pci/pci_root.rs @@ -464,13 +464,17 @@ impl BusDevice for PciConfigMmio { } } -/// Inspired by PCI configuration space, CrosVM provides 1024 dword virtual registers (4KiB in +/// Inspired by PCI configuration space, CrosVM provides 2048 dword virtual registers (8KiB in /// total) for each PCI device. The guest can use these registers to exchange device-specific -/// information with CrosVM. +/// information with CrosVM. The first 4kB is trapped by crosvm and crosm supply these +/// register's emulation. The second 4KB is mapped into guest directly as shared memory, so +/// when guest access this 4KB, vm exit doesn't happen. /// All these virtual registers from all PCI devices locate in a contiguous memory region. /// The base address of this memory region is provided by an IntObj named VCFG in the ACPI DSDT. +/// Bit 12 is used to select the first trapped page or the second directly mapped page /// The offset of each register is calculated in the same way as PCIe ECAM; -/// i.e. offset = (bus << 20) | (device << 15) | (function << 12) | (register_index << 2) +/// i.e. offset = (bus << 21) | (device << 16) | (function << 13) | (page_select << 12) | +/// (register_index << 2) pub struct PciVirtualConfigMmio { /// PCI root bridge. pci_root: Arc>, diff --git a/x86_64/src/lib.rs b/x86_64/src/lib.rs index 2eb2223cf5..6f88917176 100644 --- a/x86_64/src/lib.rs +++ b/x86_64/src/lib.rs @@ -640,7 +640,7 @@ impl arch::LinuxArch for X8664arch { .insert(pcie_cfg_mmio, pcie_cfg_mmio_range.start, pcie_cfg_mmio_len) .unwrap(); - let pcie_vcfg_mmio = Arc::new(Mutex::new(PciVirtualConfigMmio::new(pci.clone(), 12))); + let pcie_vcfg_mmio = Arc::new(Mutex::new(PciVirtualConfigMmio::new(pci.clone(), 13))); let pcie_vcfg_range = Self::get_pcie_vcfg_mmio_range(&mem, &pcie_cfg_mmio_range); mmio_bus .insert( @@ -1467,7 +1467,8 @@ impl X8664arch { // Put PCIe VCFG region at a 2MB boundary after physical memory or 4gb, whichever is greater. let ram_end_round_2mb = (mem.end_addr().offset() + 2 * MB - 1) / (2 * MB) * (2 * MB); let start = std::cmp::max(ram_end_round_2mb, 4 * GB); - let end = start + pcie_cfg_mmio.len().unwrap() - 1; + // Each pci device's ECAM size is 4kb and its vcfg size is 8kb + let end = start + pcie_cfg_mmio.len().unwrap() * 2 - 1; AddressRange { start, end } }