1 /* 2 * Copyright (C) 2019-2022 Intel Corporation. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <asm/vm_config.h> 8 #include <pci.h> 9 #include <asm/pci_dev.h> 10 #include <vpci.h> 11 12 /* 13 * @pre pdev != NULL; 14 */ allocate_to_prelaunched_vm(struct pci_pdev * pdev)15static bool allocate_to_prelaunched_vm(struct pci_pdev *pdev) 16 { 17 bool found = false; 18 uint16_t vmid; 19 uint16_t pci_idx; 20 struct acrn_vm_config *vm_config; 21 struct acrn_vm_pci_dev_config *dev_config; 22 23 for (vmid = 0U; (vmid < CONFIG_MAX_VM_NUM) && !found; vmid++) { 24 vm_config = get_vm_config(vmid); 25 if (vm_config->load_order == PRE_LAUNCHED_VM) { 26 for (pci_idx = 0U; pci_idx < vm_config->pci_dev_num; pci_idx++) { 27 dev_config = &vm_config->pci_devs[pci_idx]; 28 if ((dev_config->emu_type == PCI_DEV_TYPE_PTDEV) && 29 bdf_is_equal(dev_config->pbdf, pdev->bdf)) { 30 dev_config->pdev = pdev; 31 found = true; 32 break; 33 } 34 } 35 } 36 } 37 38 return found; 39 } 40 41 42 /* 43 * @brief Initialize a acrn_vm_pci_dev_config structure 44 * 45 * Initialize a acrn_vm_pci_dev_config structure with a specified the pdev structure. 46 * A acrn_vm_pci_dev_config is used to store a PCI device configuration for a VM. The 47 * caller of the function init_one_dev_config should guarantee execution atomically. 48 * 49 * @pre pdev != NULL 50 * 51 * @return If there's a successfully initialized acrn_vm_pci_dev_config return it, otherwise return NULL; 52 */ init_one_dev_config(struct pci_pdev * pdev)53struct acrn_vm_pci_dev_config *init_one_dev_config(struct pci_pdev *pdev) 54 { 55 struct acrn_vm_pci_dev_config *dev_config = NULL; 56 bool is_allocated_to_prelaunched_vm = allocate_to_prelaunched_vm(pdev); 57 bool is_allocated_to_hv = is_hv_owned_pdev(pdev->bdf); 58 59 if (service_vm_config != NULL) { 60 dev_config = &service_vm_config->pci_devs[service_vm_config->pci_dev_num]; 61 62 if (is_allocated_to_hv) { 63 /* Service VM need to emulate the type1 pdevs owned by HV */ 64 dev_config->emu_type = PCI_DEV_TYPE_SERVICE_VM_EMUL; 65 if (is_bridge(pdev)) { 66 dev_config->vdev_ops = &vpci_bridge_ops; 67 } else if (is_host_bridge(pdev)) { 68 dev_config->vdev_ops = &vhostbridge_ops; 69 } else { 70 /* May have type0 device, E.g. debug pci uart */ 71 dev_config = NULL; 72 } 73 } else if (is_allocated_to_prelaunched_vm) { 74 dev_config = NULL; 75 } else { 76 dev_config->emu_type = PCI_DEV_TYPE_PTDEV; 77 } 78 79 if ((is_allocated_to_hv || is_allocated_to_prelaunched_vm) 80 && (dev_config == NULL) 81 && is_pci_cfg_multifunction(pdev->hdr_type) 82 && (pdev->bdf.bits.f == 0U)) 83 { 84 dev_config = &service_vm_config->pci_devs[service_vm_config->pci_dev_num]; 85 dev_config->emu_type = PCI_DEV_TYPE_DUMMY_MF_EMUL; 86 dev_config->vdev_ops = &vpci_mf_dev_ops; 87 } 88 } 89 90 if (dev_config != NULL) { 91 dev_config->vbdf.value = pdev->bdf.value; 92 dev_config->pbdf.value = pdev->bdf.value; 93 dev_config->pdev = pdev; 94 service_vm_config->pci_dev_num++; 95 } 96 return dev_config; 97 } 98