From b8f151a55fd882375d6ba1ad069b0b0550eb734b Mon Sep 17 00:00:00 2001 From: Li Fei1 Date: Tue, 2 Jun 2020 09:27:40 +0800 Subject: [PATCH] hv: pci: check whether a PCI device is host bridge or not by class According PCI Code and ID Assignment Specification Revision 1.11, a PCI device whose Base Class is 06h and Sub-Class is 00h is a Host bridge. Tracked-On: #4550 Signed-off-by: Li Fei1 Acked-by: Eddie Dong --- hypervisor/arch/x86/configs/pci_dev.c | 34 ++++++++----------------- hypervisor/dm/vpci/vpci.c | 4 ++- hypervisor/hw/pci.c | 2 ++ hypervisor/include/arch/x86/pci_dev.h | 2 -- hypervisor/include/arch/x86/vm_config.h | 2 +- hypervisor/include/hw/pci.h | 12 +++++++++ 6 files changed, 29 insertions(+), 27 deletions(-) diff --git a/hypervisor/arch/x86/configs/pci_dev.c b/hypervisor/arch/x86/configs/pci_dev.c index 94401dc4e..b9054e5f6 100644 --- a/hypervisor/arch/x86/configs/pci_dev.c +++ b/hypervisor/arch/x86/configs/pci_dev.c @@ -9,13 +9,7 @@ #include #include -struct acrn_vm_pci_dev_config sos_pci_devs[CONFIG_MAX_PCI_DEV_NUM] = { - { - .emu_type = PCI_DEV_TYPE_HVEMUL, - .vbdf.bits = {.b = 0x00U, .d = 0x00U, .f = 0x00U}, - .vdev_ops = &vhostbridge_ops, - }, -}; +struct acrn_vm_pci_dev_config sos_pci_devs[CONFIG_MAX_PCI_DEV_NUM]; /* * @pre pdev != NULL; @@ -28,25 +22,19 @@ static bool is_allocated_to_prelaunched_vm(struct pci_pdev *pdev) struct acrn_vm_config *vm_config; struct acrn_vm_pci_dev_config *dev_config; - for (vmid = 0U; vmid < CONFIG_MAX_VM_NUM; vmid++) { + for (vmid = 0U; (vmid < CONFIG_MAX_VM_NUM) && !found; vmid++) { vm_config = get_vm_config(vmid); - if (vm_config->load_order != PRE_LAUNCHED_VM) { - continue; - } - - 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) && - bdf_is_equal(dev_config->pbdf, pdev->bdf)) { - dev_config->pdev = pdev; - found = true; - break; + 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) && + bdf_is_equal(dev_config->pbdf, pdev->bdf)) { + dev_config->pdev = pdev; + found = true; + break; + } } } - - if (found) { - break; - } } return found; diff --git a/hypervisor/dm/vpci/vpci.c b/hypervisor/dm/vpci/vpci.c index d3bbcd6ae..d7ed33307 100644 --- a/hypervisor/dm/vpci/vpci.c +++ b/hypervisor/dm/vpci/vpci.c @@ -624,8 +624,10 @@ struct pci_vdev *vpci_init_vdev(struct acrn_vpci *vpci, struct acrn_vm_pci_dev_c if (dev_config->vdev_ops != NULL) { vdev->vdev_ops = dev_config->vdev_ops; } else { - if (vdev->pdev->hdr_type == PCIM_HDRTYPE_BRIDGE) { + if (is_bridge(vdev->pdev)) { vdev->vdev_ops = &vpci_bridge_ops; + } else if (is_host_bridge(vdev->pdev)) { + vdev->vdev_ops = &vhostbridge_ops; } else { vdev->vdev_ops = &pci_pt_dev_ops; } diff --git a/hypervisor/hw/pci.c b/hypervisor/hw/pci.c index f6a004ee8..e0f891655 100644 --- a/hypervisor/hw/pci.c +++ b/hypervisor/hw/pci.c @@ -760,6 +760,8 @@ struct pci_pdev *init_pdev(uint16_t pbdf, uint32_t drhd_index) pdev = &pci_pdev_array[num_pci_pdev]; pdev->bdf.value = pbdf; pdev->hdr_type = hdr_type; + pdev->base_class = (uint8_t)pci_pdev_read_cfg(bdf, PCIR_CLASS, 1U); + pdev->sub_class = (uint8_t)pci_pdev_read_cfg(bdf, PCIR_SUBCLASS, 1U); pdev->nr_bars = pci_pdev_get_nr_bars(hdr_type); if (hdr_type == PCIM_HDRTYPE_NORMAL) { pdev_save_bar(pdev); diff --git a/hypervisor/include/arch/x86/pci_dev.h b/hypervisor/include/arch/x86/pci_dev.h index ce410c1ad..51e1bae9d 100644 --- a/hypervisor/include/arch/x86/pci_dev.h +++ b/hypervisor/include/arch/x86/pci_dev.h @@ -9,8 +9,6 @@ #include -#define SOS_EMULATED_PCI_DEV_NUM 1U - extern struct acrn_vm_pci_dev_config sos_pci_devs[CONFIG_MAX_PCI_DEV_NUM]; struct pci_pdev; diff --git a/hypervisor/include/arch/x86/vm_config.h b/hypervisor/include/arch/x86/vm_config.h index 5ae0a0544..66ae37b7f 100644 --- a/hypervisor/include/arch/x86/vm_config.h +++ b/hypervisor/include/arch/x86/vm_config.h @@ -36,7 +36,7 @@ #define CONFIG_SOS_VM .load_order = SOS_VM, \ .uuid = SOS_VM_UUID, \ .severity = SEVERITY_SOS, \ - .pci_dev_num = SOS_EMULATED_PCI_DEV_NUM, \ + .pci_dev_num = 0U, \ .pci_devs = sos_pci_devs #define CONFIG_SAFETY_VM(idx) .load_order = PRE_LAUNCHED_VM, \ diff --git a/hypervisor/include/hw/pci.h b/hypervisor/include/hw/pci.h index 345468421..0834aef41 100644 --- a/hypervisor/include/hw/pci.h +++ b/hypervisor/include/hw/pci.h @@ -223,6 +223,8 @@ struct pci_sriov_cap { struct pci_pdev { uint8_t hdr_type; + uint8_t base_class; + uint8_t sub_class; /* IOMMU responsible for DMA and Interrupt Remapping for this device */ uint32_t drhd_index; @@ -250,6 +252,16 @@ struct pci_cfg_ops { void (*pci_write_cfg)(union pci_bdf bdf, uint32_t offset, uint32_t bytes, uint32_t val); }; +static inline bool is_host_bridge(const struct pci_pdev *pdev) +{ + return (pdev->base_class == PCIC_BRIDGE) && (pdev->sub_class == PCIS_BRIDGE_HOST); +} + +static inline bool is_bridge(const struct pci_pdev *pdev) +{ + return pdev->hdr_type == PCIM_HDRTYPE_BRIDGE; +} + static inline uint32_t pci_bar_offset(uint32_t idx) { return PCIR_BARS + (idx << 2U);