diff --git a/hypervisor/dm/vpci/pci_vdev.c b/hypervisor/dm/vpci/partition_mode.c similarity index 51% rename from hypervisor/dm/vpci/pci_vdev.c rename to hypervisor/dm/vpci/partition_mode.c index 9f1547927..3e9dcb8ba 100644 --- a/hypervisor/dm/vpci/pci_vdev.c +++ b/hypervisor/dm/vpci/partition_mode.c @@ -32,8 +32,7 @@ #include #include "pci_priv.h" - -static struct pci_vdev *pci_vdev_find(struct vpci *vpci, union pci_bdf vbdf) +static struct pci_vdev *partition_mode_find_vdev(struct vpci *vpci, union pci_bdf vbdf) { struct vpci_vdev_array *vdev_array; struct pci_vdev *vdev; @@ -50,31 +49,71 @@ static struct pci_vdev *pci_vdev_find(struct vpci *vpci, union pci_bdf vbdf) return NULL; } -/* PCI cfg vm-exit handler */ -void pci_vdev_cfg_handler(struct vpci *vpci, uint32_t in, union pci_bdf vbdf, - uint32_t offset, uint32_t bytes, uint32_t *val) +static int partition_mode_vpci_init(struct vm *vm) { + struct vpci_vdev_array *vdev_array; + struct vpci *vpci = &vm->vpci; struct pci_vdev *vdev; - int ret; + int i; - vdev = pci_vdev_find(vpci, vbdf); - if (vdev == NULL) { - return; - } + vdev_array = vm->vm_desc->vpci_vdev_array; - ret = -EINVAL; - if (in == 1U) { - if ((vdev->ops != NULL) && (vdev->ops->cfgread != NULL)) { - ret = vdev->ops->cfgread(vdev, offset, bytes, val); - } - } else { - if ((vdev->ops != NULL) && (vdev->ops->cfgwrite != NULL)) { - ret = vdev->ops->cfgwrite(vdev, offset, bytes, *val); + for (i = 0; i < vdev_array->num_pci_vdev; i++) { + vdev = &vdev_array->vpci_vdev_list[i]; + vdev->vpci = vpci; + + if ((vdev->ops != NULL) && (vdev->ops->init != NULL)) { + if (vdev->ops->init(vdev) != 0U) { + pr_err("%s() failed at PCI device (bdf %x)!", __func__, + vdev->vbdf); + } } } - if (ret != 0) { - pr_dbg("pci_vdev_cfg_handler failed, ret=%d", ret); + return 0; +} + +static void partition_mode_vpci_deinit(struct vm *vm) +{ + struct vpci_vdev_array *vdev_array; + struct pci_vdev *vdev; + int i; + + vdev_array = vm->vm_desc->vpci_vdev_array; + + for (i = 0; i < vdev_array->num_pci_vdev; i++) { + vdev = &vdev_array->vpci_vdev_list[i]; + if ((vdev->ops != NULL) && (vdev->ops->deinit != NULL)) { + if (vdev->ops->deinit(vdev) != 0U) { + pr_err("vdev->ops->deinit failed!"); + } + } } } +static void partition_mode_cfgread(struct vpci *vpci, union pci_bdf vbdf, + uint32_t offset, uint32_t bytes, uint32_t *val) +{ + struct pci_vdev *vdev = partition_mode_find_vdev(vpci, vbdf); + if ((vdev != NULL) && (vdev->ops != NULL) + && (vdev->ops->cfgread != NULL)) { + (void)vdev->ops->cfgread(vdev, offset, bytes, val); + } +} + +static void partition_mode_cfgwrite(struct vpci *vpci, union pci_bdf vbdf, + uint32_t offset, uint32_t bytes, uint32_t val) +{ + struct pci_vdev *vdev = partition_mode_find_vdev(vpci, vbdf); + if ((vdev != NULL) && (vdev->ops != NULL) + && (vdev->ops->cfgwrite != NULL)) { + (void)vdev->ops->cfgwrite(vdev, offset, bytes, val); + } +} + +struct vpci_ops partition_mode_vpci_ops = { + .init = partition_mode_vpci_init, + .deinit = partition_mode_vpci_deinit, + .cfgread = partition_mode_cfgread, + .cfgwrite = partition_mode_cfgwrite, +}; diff --git a/hypervisor/dm/vpci/pci_priv.h b/hypervisor/dm/vpci/pci_priv.h index 6b7cecef4..030eff203 100644 --- a/hypervisor/dm/vpci/pci_priv.h +++ b/hypervisor/dm/vpci/pci_priv.h @@ -68,10 +68,9 @@ pci_vdev_write_cfg_u32(struct pci_vdev *vdev, uint32_t offset, uint32_t val) *(uint32_t *)(vdev->cfgdata + offset) = val; } +extern struct vpci_ops partition_mode_vpci_ops; + uint32_t pci_vdev_read_cfg(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_cfg_handler(struct vpci *vpci, uint32_t in, union pci_bdf vbdf, uint32_t offset, - uint32_t bytes, uint32_t *val); - #endif /* PCI_PRIV_H_ */ diff --git a/hypervisor/dm/vpci/vpci.c b/hypervisor/dm/vpci/vpci.c index a1a3e90eb..b365213b1 100644 --- a/hypervisor/dm/vpci/vpci.c +++ b/hypervisor/dm/vpci/vpci.c @@ -68,12 +68,14 @@ static uint32_t pci_cfg_io_read(struct vm *vm, uint16_t addr, size_t bytes) if (pi->cached_enable) { uint16_t offset = addr - PCI_CONFIG_DATA; - pci_vdev_cfg_handler(vpci, 1U, pi->cached_bdf, - pi->cached_reg + offset, bytes, &val); + if ((vpci->ops != NULL) && (vpci->ops->cfgread != NULL)) { + vpci->ops->cfgread(vpci, pi->cached_bdf, + pi->cached_reg + offset, bytes, &val); + } pci_cfg_clear_cache(pi); } - } else { + } else { val = 0xFFFFFFFFU; } @@ -89,9 +91,9 @@ static void pci_cfg_io_write(struct vm *vm, uint16_t addr, size_t bytes, if (is_cfg_addr(addr)) { /* TODO: handling the non 4 bytes access */ if (bytes == 4U) { - pi->cached_bdf.bits.b = (val >> 16U) & PCI_BUSMAX; - pi->cached_bdf.bits.d = (val >> 11U) & PCI_SLOTMAX; - pi->cached_bdf.bits.f = (val >> 8U) & PCI_FUNCMAX; + pi->cached_bdf.bits.b = (uint8_t)(val >> 16U) & PCI_BUSMAX; + pi->cached_bdf.bits.d = (uint8_t)(val >> 11U) & PCI_SLOTMAX; + pi->cached_bdf.bits.f = (uint8_t)(val >> 8U) & PCI_FUNCMAX; pi->cached_reg = val & PCI_REGMAX; pi->cached_enable = @@ -101,62 +103,40 @@ static void pci_cfg_io_write(struct vm *vm, uint16_t addr, size_t bytes, if (pi->cached_enable) { uint16_t offset = addr - PCI_CONFIG_DATA; - pci_vdev_cfg_handler(vpci, 0U, pi->cached_bdf, - pi->cached_reg + offset, bytes, &val); - + if ((vpci->ops != NULL) && (vpci->ops->cfgwrite != NULL)) { + vpci->ops->cfgwrite(vpci, pi->cached_bdf, + pi->cached_reg + offset, bytes, val); + } pci_cfg_clear_cache(pi); } } else { pr_err("Not PCI cfg data/addr port access!"); } - } void vpci_init(struct vm *vm) { struct vpci *vpci = &vm->vpci; - struct vpci_vdev_array *vdev_array; - struct pci_vdev *vdev; - int i; - int ret; - struct vm_io_range pci_cfg_range = {.flags = IO_ATTR_RW, - .base = PCI_CONFIG_ADDR, .len = 8U}; + struct vm_io_range pci_cfg_range = { + .flags = IO_ATTR_RW, + .base = PCI_CONFIG_ADDR, + .len = 8U + }; vpci->vm = vm; - vdev_array = vm->vm_desc->vpci_vdev_array; + vpci->ops = &partition_mode_vpci_ops; - for (i = 0; i < vdev_array->num_pci_vdev; i++) { - vdev = &vdev_array->vpci_vdev_list[i]; - vdev->vpci = vpci; - - if ((vdev->ops != NULL) && (vdev->ops->init != NULL)) { - ret = vdev->ops->init(vdev); - if (ret != 0) { - pr_err("vdev->ops->init failed!"); - } - } + if ((vpci->ops->init != NULL) && (vpci->ops->init(vm) == 0)) { + register_io_emulation_handler(vm, &pci_cfg_range, + &pci_cfg_io_read, &pci_cfg_io_write); } - - register_io_emulation_handler(vm, &pci_cfg_range, - &pci_cfg_io_read, &pci_cfg_io_write); } void vpci_cleanup(struct vm *vm) { - struct vpci_vdev_array *vdev_array; - struct pci_vdev *vdev; - int i; - int ret; + struct vpci *vpci = &vm->vpci; - vdev_array = vm->vm_desc->vpci_vdev_array; - - for (i = 0; i < vdev_array->num_pci_vdev; i++) { - vdev = &vdev_array->vpci_vdev_list[i]; - if ((vdev->ops != NULL) && (vdev->ops->deinit != NULL)) { - ret = vdev->ops->deinit(vdev); - if (ret != 0) { - pr_err("vdev->ops->deinit failed!"); - } - } + if ((vpci->ops != NULL) && (vpci->ops->deinit != NULL)) { + vpci->ops->deinit(vm); } } diff --git a/hypervisor/include/dm/vpci.h b/hypervisor/include/dm/vpci.h index abdb0f2bd..ba7e105db 100644 --- a/hypervisor/include/dm/vpci.h +++ b/hypervisor/include/dm/vpci.h @@ -78,9 +78,20 @@ struct pci_addr_info { uint32_t cached_reg, cached_enable; }; +struct vpci_ops { + int (*init)(struct vm *vm); + void (*deinit)(struct vm *vm); + void (*cfgread)(struct vpci *vpci, union pci_bdf vbdf, uint32_t offset, + uint32_t bytes, uint32_t *val); + void (*cfgwrite)(struct vpci *vpci, union pci_bdf vbdf, uint32_t offset, + uint32_t bytes, uint32_t val); +}; + + struct vpci { struct vm *vm; struct pci_addr_info addr_info; + struct vpci_ops *ops; }; extern struct pci_vdev_ops pci_ops_vdev_hostbridge;