hv: vpci: an assign PT device should support FLR or PM reset
Before we assign a PT device to post-launched VM, we should reset the PCI device first. However, ACRN hypervisor doesn't plan to support PCIe hot-plug and doesn't support PCIe bridge Secondary Bus Reset. So the PT device must support FLR or PM reset. This patch do this check when assigning a PT device to post-launched VM. Tracked-On: #3465 Signed-off-by: Li Fei1 <fei1.li@intel.com>
This commit is contained in:
parent
e74a9f397d
commit
21b405d109
|
@ -827,10 +827,11 @@ int32_t hcall_gpa_to_hpa(struct acrn_vm *vm, uint16_t vmid, uint64_t param)
|
||||||
*/
|
*/
|
||||||
int32_t hcall_assign_ptdev(struct acrn_vm *vm, uint16_t vmid, uint64_t param)
|
int32_t hcall_assign_ptdev(struct acrn_vm *vm, uint16_t vmid, uint64_t param)
|
||||||
{
|
{
|
||||||
int32_t ret;
|
int32_t ret = 0;
|
||||||
union pci_bdf bdf;
|
union pci_bdf bdf;
|
||||||
struct acrn_vm *target_vm = get_vm_from_vmid(vmid);
|
struct acrn_vm *target_vm = get_vm_from_vmid(vmid);
|
||||||
bool bdf_valid = true;
|
bool bdf_valid = true;
|
||||||
|
struct pci_vdev *vdev;
|
||||||
|
|
||||||
if (!is_poweroff_vm(target_vm) && is_postlaunched_vm(target_vm)) {
|
if (!is_poweroff_vm(target_vm) && is_postlaunched_vm(target_vm)) {
|
||||||
if (param < 0x10000UL) {
|
if (param < 0x10000UL) {
|
||||||
|
@ -845,7 +846,22 @@ int32_t hcall_assign_ptdev(struct acrn_vm *vm, uint16_t vmid, uint64_t param)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bdf_valid) {
|
if (bdf_valid) {
|
||||||
ret = move_pt_device(vm->iommu, target_vm->iommu, bdf.fields.bus, bdf.fields.devfun);
|
spinlock_obtain(&vm->vpci.lock);
|
||||||
|
vdev = pci_find_vdev(&vm->vpci, bdf);
|
||||||
|
if (vdev == NULL) {
|
||||||
|
pr_fatal("%s %x:%x.%x not found\n", __func__, bdf.bits.b, bdf.bits.d, bdf.bits.f);
|
||||||
|
ret = -EPERM;
|
||||||
|
} else {
|
||||||
|
/* ToDo: Each PT device must support one type reset */
|
||||||
|
if (!vdev->pdev->has_pm_reset && !vdev->pdev->has_flr && !vdev->pdev->has_af_flr) {
|
||||||
|
pr_fatal("%s %x:%x.%x not support FLR or not support PM reset\n",
|
||||||
|
__func__, bdf.bits.b, bdf.bits.d, bdf.bits.f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spinlock_release(&vm->vpci.lock);
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = move_pt_device(vm->iommu, target_vm->iommu, bdf.fields.bus, bdf.fields.devfun);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pr_err("%s, target vm is invalid\n", __func__);
|
pr_err("%s, target vm is invalid\n", __func__);
|
||||||
|
|
|
@ -143,8 +143,6 @@ void deinit_vmsix(const struct pci_vdev *vdev);
|
||||||
uint32_t pci_vdev_read_cfg(const struct pci_vdev *vdev, uint32_t offset, uint32_t bytes);
|
uint32_t pci_vdev_read_cfg(const struct pci_vdev *vdev, uint32_t offset, uint32_t bytes);
|
||||||
void pci_vdev_write_cfg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t val);
|
void pci_vdev_write_cfg(struct pci_vdev *vdev, uint32_t offset, uint32_t bytes, uint32_t val);
|
||||||
|
|
||||||
struct pci_vdev *pci_find_vdev(struct acrn_vpci *vpci, union pci_bdf vbdf);
|
|
||||||
|
|
||||||
uint32_t pci_vdev_read_bar(const struct pci_vdev *vdev, uint32_t idx);
|
uint32_t pci_vdev_read_bar(const struct pci_vdev *vdev, uint32_t idx);
|
||||||
void pci_vdev_write_bar(struct pci_vdev *vdev, uint32_t idx, uint32_t val);
|
void pci_vdev_write_bar(struct pci_vdev *vdev, uint32_t idx, uint32_t val);
|
||||||
#endif /* VPCI_PRIV_H_ */
|
#endif /* VPCI_PRIV_H_ */
|
||||||
|
|
|
@ -130,6 +130,7 @@ struct acrn_vpci {
|
||||||
extern const struct pci_vdev_ops vhostbridge_ops;
|
extern const struct pci_vdev_ops vhostbridge_ops;
|
||||||
void vpci_init(struct acrn_vm *vm);
|
void vpci_init(struct acrn_vm *vm);
|
||||||
void vpci_cleanup(struct acrn_vm *vm);
|
void vpci_cleanup(struct acrn_vm *vm);
|
||||||
|
struct pci_vdev *pci_find_vdev(struct acrn_vpci *vpci, union pci_bdf vbdf);
|
||||||
void vpci_set_ptdev_intr_info(struct acrn_vm *target_vm, uint16_t vbdf, uint16_t pbdf);
|
void vpci_set_ptdev_intr_info(struct acrn_vm *target_vm, uint16_t vbdf, uint16_t pbdf);
|
||||||
void vpci_reset_ptdev_intr_info(struct acrn_vm *target_vm, uint16_t vbdf, uint16_t pbdf);
|
void vpci_reset_ptdev_intr_info(struct acrn_vm *target_vm, uint16_t vbdf, uint16_t pbdf);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue