From 80f905f2177cfc789722f147ce0fb3978861d84b Mon Sep 17 00:00:00 2001 From: Jian Jun Chen Date: Wed, 23 Sep 2020 04:37:29 +0000 Subject: [PATCH] hv: pci: Hide PCI bridge 00:1c.0 from SOS It is found that SOS will reset the PCI devices under PCI bridge 00:1c.0 when 00:1c.0 is exposed to SOS. If a PCI device under 00:1c.0 is passed through to pre-launched VM, it will be reset by SOS at startup hence the passthrough will not work properly. This patch provides a workaround by hiding PCI bridge 00:1c.0 from SOS in this case. Tracked-On: #5346 Signed-off-by: Jian Jun Chen --- hypervisor/arch/x86/configs/pci_dev.c | 53 ++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/hypervisor/arch/x86/configs/pci_dev.c b/hypervisor/arch/x86/configs/pci_dev.c index b341c6f03..2b914f7bb 100644 --- a/hypervisor/arch/x86/configs/pci_dev.c +++ b/hypervisor/arch/x86/configs/pci_dev.c @@ -8,6 +8,7 @@ #include #include #include +#include /* * @pre pdev != NULL; @@ -38,6 +39,56 @@ static bool is_allocated_to_prelaunched_vm(struct pci_pdev *pdev) return found; } +static bool is_pbus_allocated_to_prelaunched_vm(uint8_t bus) +{ + bool found = false; + uint16_t vmid; + uint32_t pci_idx; + struct acrn_vm_config *vm_config; + struct acrn_vm_pci_dev_config *dev_config; + + for (vmid = 0U; (vmid < CONFIG_MAX_VM_NUM) && !found; vmid++) { + vm_config = get_vm_config(vmid); + if (vm_config->load_order == PRE_LAUNCHED_VM) { + for (pci_idx = 0U; pci_idx < vm_config->pci_dev_num; pci_idx++) { + dev_config = &vm_config->pci_devs[pci_idx]; + if ((dev_config->emu_type == PCI_DEV_TYPE_PTDEV) && + (dev_config->pbdf.bits.b == bus)) { + found = true; + break; + } + } + } + } + + return found; +} + +static bool need_hide_from_sos(struct pci_pdev *pdev) +{ + const union pci_bdf bdf = {.bits.b = 0U, .bits.d = 0x1cU, .bits.f = 0U}; + uint8_t hdr_type, hdr_layout, sec_busno; + uint32_t vid, pid; + bool ret = false; + + if (bdf_is_equal(bdf, pdev->bdf)) { + vid = pci_pdev_read_cfg(pdev->bdf, PCIR_VENDOR, 2U); + pid = pci_pdev_read_cfg(pdev->bdf, PCIR_DEVICE, 2U); + hdr_type = (uint8_t)pci_pdev_read_cfg(pdev->bdf, PCIR_HDRTYPE, 1U); + hdr_layout = (hdr_type & PCIM_HDRTYPE); + + if ((vid == 0x8086) && (pid == 0xa0bc) && (hdr_layout == PCIM_HDRTYPE_BRIDGE)) { + sec_busno = (uint8_t)pci_pdev_read_cfg(pdev->bdf, PCIR_SECBUS_1, 1U); + ret = is_pbus_allocated_to_prelaunched_vm(sec_busno); + if (ret) { + pr_acrnlog("%s: [%x:%x.%x] is hidden from SOS", + __func__, bdf.bits.b, bdf.bits.d, bdf.bits.f); + } + } + } + + return ret; +} /* * @brief Initialize a acrn_vm_pci_dev_config structure @@ -56,7 +107,7 @@ struct acrn_vm_pci_dev_config *init_one_dev_config(struct pci_pdev *pdev) struct acrn_vm_config *vm_config; struct acrn_vm_pci_dev_config *dev_config = NULL; - if (!is_allocated_to_prelaunched_vm(pdev)) { + if (!is_allocated_to_prelaunched_vm(pdev) && !need_hide_from_sos(pdev)) { for (vmid = 0U; vmid < CONFIG_MAX_VM_NUM; vmid++) { vm_config = get_vm_config(vmid); if (vm_config->load_order != SOS_VM) {