diff --git a/hypervisor/Makefile b/hypervisor/Makefile index 029b4cfb4..d860a9a1d 100644 --- a/hypervisor/Makefile +++ b/hypervisor/Makefile @@ -315,6 +315,7 @@ VP_DM_C_SRCS += dm/vpci/vpci.c VP_DM_C_SRCS += dm/vpci/vhostbridge.c VP_DM_C_SRCS += dm/vpci/vroot_port.c VP_DM_C_SRCS += dm/vpci/vpci_bridge.c +VP_DM_C_SRCS += dm/vpci/vpci_mf_dev.c VP_DM_C_SRCS += dm/vpci/ivshmem.c VP_DM_C_SRCS += dm/vpci/pci_pt.c VP_DM_C_SRCS += dm/vpci/vmsi.c diff --git a/hypervisor/arch/x86/configs/pci_dev.c b/hypervisor/arch/x86/configs/pci_dev.c index 144b31253..0a1f4286d 100644 --- a/hypervisor/arch/x86/configs/pci_dev.c +++ b/hypervisor/arch/x86/configs/pci_dev.c @@ -75,6 +75,16 @@ struct acrn_vm_pci_dev_config *init_one_dev_config(struct pci_pdev *pdev) } else { dev_config->emu_type = PCI_DEV_TYPE_PTDEV; } + + if ((is_allocated_to_hv || is_allocated_to_prelaunched_vm) + && (dev_config == NULL) + && is_pci_cfg_multifunction(pdev->hdr_type) + && (pdev->bdf.bits.f == 0U)) + { + dev_config = &service_vm_config->pci_devs[service_vm_config->pci_dev_num]; + dev_config->emu_type = PCI_DEV_TYPE_DUMMY_MF_EMUL; + dev_config->vdev_ops = &vpci_mf_dev_ops; + } } if (dev_config != NULL) { diff --git a/hypervisor/dm/vpci/vpci_mf_dev.c b/hypervisor/dm/vpci/vpci_mf_dev.c new file mode 100644 index 000000000..ad958983d --- /dev/null +++ b/hypervisor/dm/vpci/vpci_mf_dev.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2018-2022 Intel Corporation. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include "vpci_priv.h" + +/* config space of dummy multifunction device */ +#define PCI_DUMMY_DEVICE_VENDOR 0x1D94U +#define PCI_DUMMY_DEVICE_ID 0x145AU +#define DUMMY_MF_REV 0x1U +#define DUMMY_MF_CLASS 0x0U + +static void init_vpci_mf_dev(struct pci_vdev *vdev) +{ + pci_vdev_write_vcfg(vdev, PCIR_VENDOR, 2U, PCI_DUMMY_DEVICE_VENDOR); + pci_vdev_write_vcfg(vdev, PCIR_DEVICE, 2U, PCI_DUMMY_DEVICE_ID); + pci_vdev_write_vcfg(vdev, PCIR_REVID, 1U, DUMMY_MF_REV); + pci_vdev_write_vcfg(vdev, PCIR_CLASS, 1U, DUMMY_MF_CLASS); + pci_vdev_write_vcfg(vdev, PCIR_HDRTYPE, 1U, PCIM_HDRTYPE_NORMAL | PCIM_MFDEV); + + vdev->parent_user = NULL; + vdev->user = vdev; +} + +static void deinit_vpci_mf_dev(struct pci_vdev *vdev) +{ + vdev->parent_user = NULL; + vdev->user = NULL; +} + +static int32_t read_vpci_mf_dev(struct pci_vdev *vdev, uint32_t offset, + uint32_t bytes, uint32_t *val) +{ + *val = pci_vdev_read_vcfg(vdev, offset, bytes); + + return 0; +} + +static int32_t write_vpci_mf_dev(__unused struct pci_vdev *vdev, __unused uint32_t offset, + __unused uint32_t bytes, __unused uint32_t val) +{ + return 0; +} + +const struct pci_vdev_ops vpci_mf_dev_ops = { + .init_vdev = init_vpci_mf_dev, + .deinit_vdev = deinit_vpci_mf_dev, + .write_vdev_cfg = write_vpci_mf_dev, + .read_vdev_cfg = read_vpci_mf_dev, +}; diff --git a/hypervisor/include/arch/x86/asm/vm_config.h b/hypervisor/include/arch/x86/asm/vm_config.h index 206ceb8b5..a489ab348 100644 --- a/hypervisor/include/arch/x86/asm/vm_config.h +++ b/hypervisor/include/arch/x86/asm/vm_config.h @@ -29,9 +29,11 @@ #define SERVICE_VM_IDLE "idle=halt " #endif +#define PCI_DEV_TYPE_NONE 0U #define PCI_DEV_TYPE_PTDEV (1U << 0U) #define PCI_DEV_TYPE_HVEMUL (1U << 1U) #define PCI_DEV_TYPE_SERVICE_VM_EMUL (1U << 2U) +#define PCI_DEV_TYPE_DUMMY_MF_EMUL (1U << 3U) #define MAX_MMIO_DEV_NUM 2U diff --git a/hypervisor/include/dm/vpci.h b/hypervisor/include/dm/vpci.h index 45a1c7ca4..9cbe86983 100644 --- a/hypervisor/include/dm/vpci.h +++ b/hypervisor/include/dm/vpci.h @@ -184,6 +184,7 @@ struct acrn_vm; extern const struct pci_vdev_ops vhostbridge_ops; extern const struct pci_vdev_ops vpci_bridge_ops; +extern const struct pci_vdev_ops vpci_mf_dev_ops; int32_t init_vpci(struct acrn_vm *vm); void deinit_vpci(struct acrn_vm *vm); struct pci_vdev *pci_find_vdev(struct acrn_vpci *vpci, union pci_bdf vbdf);