aboutsummaryrefslogtreecommitdiff
path: root/hw/s390x/s390-pci-vfio.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/s390x/s390-pci-vfio.c')
-rw-r--r--hw/s390x/s390-pci-vfio.c40
1 files changed, 37 insertions, 3 deletions
diff --git a/hw/s390x/s390-pci-vfio.c b/hw/s390x/s390-pci-vfio.c
index 08bcc55..338f436 100644
--- a/hw/s390x/s390-pci-vfio.c
+++ b/hw/s390x/s390-pci-vfio.c
@@ -150,13 +150,18 @@ static void s390_pci_read_group(S390PCIBusDevice *pbdev,
{
struct vfio_info_cap_header *hdr;
struct vfio_device_info_cap_zpci_group *cap;
+ S390pciState *s = s390_get_phb();
ClpRspQueryPciGrp *resgrp;
VFIOPCIDevice *vpci = container_of(pbdev->pdev, VFIOPCIDevice, pdev);
+ uint8_t start_gid = pbdev->zpci_fn.pfgid;
hdr = vfio_get_device_info_cap(info, VFIO_DEVICE_INFO_CAP_ZPCI_GROUP);
- /* If capability not provided, just use the default group */
- if (hdr == NULL) {
+ /*
+ * If capability not provided or the underlying hostdev is simulated, just
+ * use the default group.
+ */
+ if (hdr == NULL || pbdev->zpci_fn.pfgid >= ZPCI_SIM_GRP_START) {
trace_s390_pci_clp_cap(vpci->vbasedev.name,
VFIO_DEVICE_INFO_CAP_ZPCI_GROUP);
pbdev->zpci_fn.pfgid = ZPCI_DEFAULT_FN_GRP;
@@ -165,11 +170,40 @@ static void s390_pci_read_group(S390PCIBusDevice *pbdev,
}
cap = (void *) hdr;
+ /*
+ * For an intercept device, let's use an existing simulated group if one
+ * one was already created for other intercept devices in this group.
+ * If not, create a new simulated group if any are still available.
+ * If all else fails, just fall back on the default group.
+ */
+ if (!pbdev->interp) {
+ pbdev->pci_group = s390_group_find_host_sim(pbdev->zpci_fn.pfgid);
+ if (pbdev->pci_group) {
+ /* Use existing simulated group */
+ pbdev->zpci_fn.pfgid = pbdev->pci_group->id;
+ return;
+ } else {
+ if (s->next_sim_grp == ZPCI_DEFAULT_FN_GRP) {
+ /* All out of simulated groups, use default */
+ trace_s390_pci_clp_cap(vpci->vbasedev.name,
+ VFIO_DEVICE_INFO_CAP_ZPCI_GROUP);
+ pbdev->zpci_fn.pfgid = ZPCI_DEFAULT_FN_GRP;
+ pbdev->pci_group = s390_group_find(ZPCI_DEFAULT_FN_GRP);
+ return;
+ } else {
+ /* We can assign a new simulated group */
+ pbdev->zpci_fn.pfgid = s->next_sim_grp;
+ s->next_sim_grp++;
+ /* Fall through to create the new sim group using CLP info */
+ }
+ }
+ }
+
/* See if the PCI group is already defined, create if not */
pbdev->pci_group = s390_group_find(pbdev->zpci_fn.pfgid);
if (!pbdev->pci_group) {
- pbdev->pci_group = s390_group_create(pbdev->zpci_fn.pfgid);
+ pbdev->pci_group = s390_group_create(pbdev->zpci_fn.pfgid, start_gid);
resgrp = &pbdev->pci_group->zpci_group;
if (cap->flags & VFIO_DEVICE_INFO_ZPCI_FLAG_REFRESH) {