Message ID | 1567815389-18229-4-git-send-email-mjrosato@linux.ibm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Retrieving zPCI specific info from QEMU | expand |
On 07/09/2019 02.16, Matthew Rosato wrote: > From: Pierre Morel <pmorel@linux.ibm.com> > > We use a S390PCIGroup structure to hold the information > related to zPCI Function group. > > This allows us to be ready to support multiple groups and to retrieve > the group information from the host. > > Signed-off-by: Pierre Morel <pmorel@linux.ibm.com> > --- > hw/s390x/s390-pci-bus.c | 42 ++++++++++++++++++++++++++++++++++++++++++ > hw/s390x/s390-pci-bus.h | 11 ++++++++++- > hw/s390x/s390-pci-inst.c | 22 +++++++++++++--------- > 3 files changed, 65 insertions(+), 10 deletions(-) > > diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c > index 963a41c..e625217 100644 > --- a/hw/s390x/s390-pci-bus.c > +++ b/hw/s390x/s390-pci-bus.c > @@ -730,6 +730,46 @@ static void s390_pci_iommu_free(S390pciState *s, PCIBus *bus, int32_t devfn) > object_unref(OBJECT(iommu)); > } > > +static S390PCIGroup *s390_grp_create(int ug) > +{ > + S390PCIGroup *grp; > + S390pciState *s = s390_get_phb(); > + > + grp = g_new0(S390PCIGroup, 1); > + grp->ug = ug; > + QTAILQ_INSERT_TAIL(&s->zpci_grps, grp, link); > + return grp; > +} Maybe an ignorant question, but shouldn't there also be some kind of clean up function that also frees the memory again, e.g. during a machine reset? Or are these groups supposed to survive a machine reset? Thomas
On 9/9/19 1:18 AM, Thomas Huth wrote: > On 07/09/2019 02.16, Matthew Rosato wrote: >> From: Pierre Morel <pmorel@linux.ibm.com> >> >> We use a S390PCIGroup structure to hold the information >> related to zPCI Function group. >> >> This allows us to be ready to support multiple groups and to retrieve >> the group information from the host. >> >> Signed-off-by: Pierre Morel <pmorel@linux.ibm.com> >> --- >> hw/s390x/s390-pci-bus.c | 42 ++++++++++++++++++++++++++++++++++++++++++ >> hw/s390x/s390-pci-bus.h | 11 ++++++++++- >> hw/s390x/s390-pci-inst.c | 22 +++++++++++++--------- >> 3 files changed, 65 insertions(+), 10 deletions(-) >> >> diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c >> index 963a41c..e625217 100644 >> --- a/hw/s390x/s390-pci-bus.c >> +++ b/hw/s390x/s390-pci-bus.c >> @@ -730,6 +730,46 @@ static void s390_pci_iommu_free(S390pciState *s, PCIBus *bus, int32_t devfn) >> object_unref(OBJECT(iommu)); >> } >> >> +static S390PCIGroup *s390_grp_create(int ug) >> +{ >> + S390PCIGroup *grp; >> + S390pciState *s = s390_get_phb(); >> + >> + grp = g_new0(S390PCIGroup, 1); >> + grp->ug = ug; >> + QTAILQ_INSERT_TAIL(&s->zpci_grps, grp, link); >> + return grp; >> +} > > Maybe an ignorant question, but shouldn't there also be some kind of > clean up function that also frees the memory again, e.g. during a > machine reset? Or are these groups supposed to survive a machine reset? Hmm.. Well, I think it is in line with the way the devices themselves are handled during reset (they are not removed during a reset unless there was a pending unplug and their info persists). But you have a point in that it seems sketchy to leave the group information around, particularly in cases where the last device associated with the group has been unplugged. So yes, I think there is some work to be done here. I need to investigate whether a precautionary wiping of the list (minus the default group) at machine reset is really good enough or whether we need to remove group info sooner (device unplug). Thanks, Matt
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 963a41c..e625217 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -730,6 +730,46 @@ static void s390_pci_iommu_free(S390pciState *s, PCIBus *bus, int32_t devfn) object_unref(OBJECT(iommu)); } +static S390PCIGroup *s390_grp_create(int ug) +{ + S390PCIGroup *grp; + S390pciState *s = s390_get_phb(); + + grp = g_new0(S390PCIGroup, 1); + grp->ug = ug; + QTAILQ_INSERT_TAIL(&s->zpci_grps, grp, link); + return grp; +} + +S390PCIGroup *s390_grp_find(int ug) +{ + S390PCIGroup *grp; + S390pciState *s = s390_get_phb(); + + QTAILQ_FOREACH(grp, &s->zpci_grps, link) { + if ((grp->ug & CLP_REQ_QPCIG_MASK_PFGID) == ug) { + return grp; + } + } + return NULL; +} + +static void s390_pci_init_default_group(void) +{ + S390PCIGroup *grp; + ClpRspQueryPciGrp *resgrp; + + grp = s390_grp_create(ZPCI_DEFAULT_FN_GRP); + resgrp = &grp->zpci_grp; + resgrp->fr = 1; + stq_p(&resgrp->dasm, 0); + stq_p(&resgrp->msia, ZPCI_MSI_ADDR); + stw_p(&resgrp->mui, DEFAULT_MUI); + stw_p(&resgrp->i, 128); + stw_p(&resgrp->maxstbl, 128); + resgrp->version = 0; +} + static void s390_pcihost_realize(DeviceState *dev, Error **errp) { PCIBus *b; @@ -766,7 +806,9 @@ static void s390_pcihost_realize(DeviceState *dev, Error **errp) s->bus_no = 0; QTAILQ_INIT(&s->pending_sei); QTAILQ_INIT(&s->zpci_devs); + QTAILQ_INIT(&s->zpci_grps); + s390_pci_init_default_group(); css_register_io_adapters(CSS_IO_ADAPTER_PCI, true, false, S390_ADAPTER_SUPPRESSIBLE, &local_err); error_propagate(errp, local_err); diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h index a5d2049..e95a797 100644 --- a/hw/s390x/s390-pci-bus.h +++ b/hw/s390x/s390-pci-bus.h @@ -312,6 +312,14 @@ typedef struct ZpciFmb { } ZpciFmb; QEMU_BUILD_BUG_MSG(offsetof(ZpciFmb, fmt0) != 48, "padding in ZpciFmb"); +#define ZPCI_DEFAULT_FN_GRP 0x20 +typedef struct S390PCIGroup { + ClpRspQueryPciGrp zpci_grp; + int ug; + QTAILQ_ENTRY(S390PCIGroup) link; +} S390PCIGroup; +S390PCIGroup *s390_grp_find(int ug); + struct S390PCIBusDevice { DeviceState qdev; PCIDevice *pdev; @@ -327,8 +335,8 @@ struct S390PCIBusDevice { QEMUTimer *fmb_timer; uint8_t isc; uint16_t noi; - uint16_t maxstbl; uint8_t sum; + S390PCIGroup *pci_grp; S390MsixInfo msix; AdapterRoutes routes; S390PCIIOMMU *iommu; @@ -353,6 +361,7 @@ typedef struct S390pciState { GHashTable *zpci_table; QTAILQ_HEAD(, SeiContainer) pending_sei; QTAILQ_HEAD(, S390PCIBusDevice) zpci_devs; + QTAILQ_HEAD(, S390PCIGroup) zpci_grps; } S390pciState; S390pciState *s390_get_phb(void); diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 4b3bd4a..00dd176 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -284,21 +284,25 @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra) stq_p(&resquery->edma, ZPCI_EDMA_ADDR); stl_p(&resquery->fid, pbdev->fid); stw_p(&resquery->pchid, 0); - stw_p(&resquery->ug, 1); + stw_p(&resquery->ug, ZPCI_DEFAULT_FN_GRP); stl_p(&resquery->uid, pbdev->uid); stw_p(&resquery->hdr.rsp, CLP_RC_OK); break; } case CLP_QUERY_PCI_FNGRP: { ClpRspQueryPciGrp *resgrp = (ClpRspQueryPciGrp *)resh; - resgrp->fr = 1; - stq_p(&resgrp->dasm, 0); - stq_p(&resgrp->msia, ZPCI_MSI_ADDR); - stw_p(&resgrp->mui, DEFAULT_MUI); - stw_p(&resgrp->i, 128); - stw_p(&resgrp->maxstbl, 128); - resgrp->version = 0; + ClpReqQueryPciGrp *reqgrp = (ClpReqQueryPciGrp *)reqh; + S390PCIGroup *grp; + + grp = s390_grp_find(reqgrp->g); + if (!grp) { + /* We do not allow access to unknown groups */ + /* The group must have been obtained with a vfio device */ + stw_p(&resgrp->hdr.rsp, CLP_RC_QUERYPCIFG_PFGID); + goto out; + } + memcpy(resgrp, &grp->zpci_grp, sizeof(ClpRspQueryPciGrp)); stw_p(&resgrp->hdr.rsp, CLP_RC_OK); break; } @@ -754,7 +758,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, } /* Length must be greater than 8, a multiple of 8 */ /* and not greater than maxstbl */ - if ((len <= 8) || (len % 8) || (len > pbdev->maxstbl)) { + if ((len <= 8) || (len % 8) || (len > pbdev->pci_grp->zpci_grp.maxstbl)) { goto specification_error; } /* Do not cross a 4K-byte boundary */