Message ID | 20211207210425.150923-11-mjrosato@linux.ibm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | s390x/pci: zPCI interpretation support | expand |
On 12/7/21 22:04, Matthew Rosato wrote: > Allow the underlying kvm host to handle the Refresh PCI Translation > instruction intercepts. > > Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com> > --- > hw/s390x/s390-pci-bus.c | 6 ++-- > hw/s390x/s390-pci-inst.c | 51 ++++++++++++++++++++++++++++++-- > hw/s390x/s390-pci-vfio.c | 33 +++++++++++++++++++++ > include/hw/s390x/s390-pci-inst.h | 2 +- > include/hw/s390x/s390-pci-vfio.h | 10 +++++++ > 5 files changed, 95 insertions(+), 7 deletions(-) > > diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c > index 1ae8792a26..ab442f17fb 100644 > --- a/hw/s390x/s390-pci-bus.c > +++ b/hw/s390x/s390-pci-bus.c > @@ -196,7 +196,7 @@ void s390_pci_sclp_deconfigure(SCCB *sccb) > pci_dereg_irqs(pbdev); > } > if (pbdev->iommu->enabled) { > - pci_dereg_ioat(pbdev->iommu); > + pci_dereg_ioat(pbdev); > } > pbdev->state = ZPCI_FS_STANDBY; > rc = SCLP_RC_NORMAL_COMPLETION; > @@ -1261,7 +1261,7 @@ static void s390_pcihost_reset(DeviceState *dev) > pci_dereg_irqs(pbdev); > } > if (pbdev->iommu->enabled) { > - pci_dereg_ioat(pbdev->iommu); > + pci_dereg_ioat(pbdev); > } > pbdev->state = ZPCI_FS_STANDBY; > s390_pci_perform_unplug(pbdev); > @@ -1402,7 +1402,7 @@ static void s390_pci_device_reset(DeviceState *dev) > pci_dereg_irqs(pbdev); > } > if (pbdev->iommu->enabled) { > - pci_dereg_ioat(pbdev->iommu); > + pci_dereg_ioat(pbdev); > } > > fmb_timer_free(pbdev); > diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c > index 02093e82f9..598e5a5d52 100644 > --- a/hw/s390x/s390-pci-inst.c > +++ b/hw/s390x/s390-pci-inst.c > @@ -978,6 +978,24 @@ int pci_dereg_irqs(S390PCIBusDevice *pbdev) > return 0; > } > > +static int reg_ioat_interp(S390PCIBusDevice *pbdev, uint64_t iota) > +{ > + int rc; > + > + rc = s390_pci_probe_ioat(pbdev); > + if (rc) { > + return rc; > + } > + > + rc = s390_pci_set_ioat(pbdev, iota); > + if (rc) { > + return rc; > + } > + > + pbdev->iommu->enabled = true; > + return 0; > +} > + > static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib, > uintptr_t ra) > { > @@ -995,6 +1013,16 @@ static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib, > return -EINVAL; > } > > + /* If this is an interpreted device, we must use the IOAT assist */ > + if (pbdev->interp) { > + if (reg_ioat_interp(pbdev, g_iota)) { > + error_report("failure starting ioat assist"); > + s390_program_interrupt(env, PGM_OPERAND, ra); > + return -EINVAL; > + } > + return 0; > + } > + > /* currently we only support designation type 1 with translation */ > if (!(dt == ZPCI_IOTA_RTTO && t)) { > error_report("unsupported ioat dt %d t %d", dt, t); > @@ -1011,8 +1039,25 @@ static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib, > return 0; > } > > -void pci_dereg_ioat(S390PCIIOMMU *iommu) > +static void dereg_ioat_interp(S390PCIBusDevice *pbdev) > { > + if (s390_pci_probe_ioat(pbdev) != 0) { > + return; > + } > + > + s390_pci_set_ioat(pbdev, 0); > + pbdev->iommu->enabled = false; > +} > + > +void pci_dereg_ioat(S390PCIBusDevice *pbdev) > +{ > + S390PCIIOMMU *iommu = pbdev->iommu; > + > + if (pbdev->interp) { > + dereg_ioat_interp(pbdev); > + return; > + } > + > s390_pci_iommu_disable(iommu); > iommu->pba = 0; > iommu->pal = 0; > @@ -1251,7 +1296,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar, > cc = ZPCI_PCI_LS_ERR; > s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE); > } else { > - pci_dereg_ioat(pbdev->iommu); > + pci_dereg_ioat(pbdev); > } > break; > case ZPCI_MOD_FC_REREG_IOAT: > @@ -1262,7 +1307,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar, > cc = ZPCI_PCI_LS_ERR; > s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE); > } else { > - pci_dereg_ioat(pbdev->iommu); > + pci_dereg_ioat(pbdev); > if (reg_ioat(env, pbdev, fib, ra)) { > cc = ZPCI_PCI_LS_ERR; > s390_set_status_code(env, r1, ZPCI_MOD_ST_INSUF_RES); > diff --git a/hw/s390x/s390-pci-vfio.c b/hw/s390x/s390-pci-vfio.c > index 6f9271df87..6fc03a858a 100644 > --- a/hw/s390x/s390-pci-vfio.c > +++ b/hw/s390x/s390-pci-vfio.c > @@ -240,6 +240,39 @@ int s390_pci_get_aif(S390PCIBusDevice *pbdev, bool enable, bool assist) > return rc; > } > > +int s390_pci_probe_ioat(S390PCIBusDevice *pbdev) > +{ > + VFIOPCIDevice *vdev = container_of(pbdev->pdev, VFIOPCIDevice, pdev); > + struct vfio_device_feature feat = { > + .argsz = sizeof(struct vfio_device_feature), > + .flags = VFIO_DEVICE_FEATURE_PROBE + VFIO_DEVICE_FEATURE_ZPCI_IOAT > + }; > + > + assert(vdev); > + > + return ioctl(vdev->vbasedev.fd, VFIO_DEVICE_FEATURE, &feat); > +} > + > +int s390_pci_set_ioat(S390PCIBusDevice *pbdev, uint64_t iota) > +{ > + VFIOPCIDevice *vdev = container_of(pbdev->pdev, VFIOPCIDevice, pdev); > + g_autofree struct vfio_device_feature *feat; > + struct vfio_device_zpci_ioat *data; > + int size; > + > + assert(vdev); Same comment as Thomas in the previous patch. > + > + size = sizeof(*feat) + sizeof(*data); > + feat = g_malloc0(size); > + feat->argsz = size; > + feat->flags = VFIO_DEVICE_FEATURE_SET + VFIO_DEVICE_FEATURE_ZPCI_IOAT; > + > + data = (struct vfio_device_zpci_ioat *)&feat->data; > + data->iota = iota; > + > + return ioctl(vdev->vbasedev.fd, VFIO_DEVICE_FEATURE, feat); > +} > + > static void s390_pci_read_base(S390PCIBusDevice *pbdev, > struct vfio_device_info *info) > { > diff --git a/include/hw/s390x/s390-pci-inst.h b/include/hw/s390x/s390-pci-inst.h > index a55c448aad..13566fb7b4 100644 > --- a/include/hw/s390x/s390-pci-inst.h > +++ b/include/hw/s390x/s390-pci-inst.h > @@ -99,7 +99,7 @@ typedef struct ZpciFib { > } QEMU_PACKED ZpciFib; > > int pci_dereg_irqs(S390PCIBusDevice *pbdev); > -void pci_dereg_ioat(S390PCIIOMMU *iommu); > +void pci_dereg_ioat(S390PCIBusDevice *pbdev); > int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra); > int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra); > int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra); > diff --git a/include/hw/s390x/s390-pci-vfio.h b/include/hw/s390x/s390-pci-vfio.h > index 6cec38a863..e7a2d8ff77 100644 > --- a/include/hw/s390x/s390-pci-vfio.h > +++ b/include/hw/s390x/s390-pci-vfio.h > @@ -28,6 +28,8 @@ int s390_pci_probe_aif(S390PCIBusDevice *pbdev); > int s390_pci_set_aif(S390PCIBusDevice *pbdev, ZpciFib *fib, bool enable, > bool assist); > int s390_pci_get_aif(S390PCIBusDevice *pbdev, bool enable, bool assist); > +int s390_pci_probe_ioat(S390PCIBusDevice *pbdev); > +int s390_pci_set_ioat(S390PCIBusDevice *pbdev, uint64_t iota); > > void s390_pci_get_clp_info(S390PCIBusDevice *pbdev); > #else > @@ -68,6 +70,14 @@ static inline int s390_pci_get_aif(S390PCIBusDevice *pbdev, bool enable, > { > return -EINVAL; > } > +static inline int s390_pci_probe_ioat(S390PCIBusDevice *pbdev) > +{ > + return -EINVAL; > +} > +static inline int s390_pci_set_ioat(S390PCIBusDevice *pbdev, uint64_t iota) > +{ > + return -EINVAL; > +} > static inline void s390_pci_get_clp_info(S390PCIBusDevice *pbdev) { } > #endif > > LGTM With the change Reviewed-by: Pierre Morel <pmorel@linux.ibm.com>
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 1ae8792a26..ab442f17fb 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -196,7 +196,7 @@ void s390_pci_sclp_deconfigure(SCCB *sccb) pci_dereg_irqs(pbdev); } if (pbdev->iommu->enabled) { - pci_dereg_ioat(pbdev->iommu); + pci_dereg_ioat(pbdev); } pbdev->state = ZPCI_FS_STANDBY; rc = SCLP_RC_NORMAL_COMPLETION; @@ -1261,7 +1261,7 @@ static void s390_pcihost_reset(DeviceState *dev) pci_dereg_irqs(pbdev); } if (pbdev->iommu->enabled) { - pci_dereg_ioat(pbdev->iommu); + pci_dereg_ioat(pbdev); } pbdev->state = ZPCI_FS_STANDBY; s390_pci_perform_unplug(pbdev); @@ -1402,7 +1402,7 @@ static void s390_pci_device_reset(DeviceState *dev) pci_dereg_irqs(pbdev); } if (pbdev->iommu->enabled) { - pci_dereg_ioat(pbdev->iommu); + pci_dereg_ioat(pbdev); } fmb_timer_free(pbdev); diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 02093e82f9..598e5a5d52 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -978,6 +978,24 @@ int pci_dereg_irqs(S390PCIBusDevice *pbdev) return 0; } +static int reg_ioat_interp(S390PCIBusDevice *pbdev, uint64_t iota) +{ + int rc; + + rc = s390_pci_probe_ioat(pbdev); + if (rc) { + return rc; + } + + rc = s390_pci_set_ioat(pbdev, iota); + if (rc) { + return rc; + } + + pbdev->iommu->enabled = true; + return 0; +} + static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib, uintptr_t ra) { @@ -995,6 +1013,16 @@ static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib, return -EINVAL; } + /* If this is an interpreted device, we must use the IOAT assist */ + if (pbdev->interp) { + if (reg_ioat_interp(pbdev, g_iota)) { + error_report("failure starting ioat assist"); + s390_program_interrupt(env, PGM_OPERAND, ra); + return -EINVAL; + } + return 0; + } + /* currently we only support designation type 1 with translation */ if (!(dt == ZPCI_IOTA_RTTO && t)) { error_report("unsupported ioat dt %d t %d", dt, t); @@ -1011,8 +1039,25 @@ static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib, return 0; } -void pci_dereg_ioat(S390PCIIOMMU *iommu) +static void dereg_ioat_interp(S390PCIBusDevice *pbdev) { + if (s390_pci_probe_ioat(pbdev) != 0) { + return; + } + + s390_pci_set_ioat(pbdev, 0); + pbdev->iommu->enabled = false; +} + +void pci_dereg_ioat(S390PCIBusDevice *pbdev) +{ + S390PCIIOMMU *iommu = pbdev->iommu; + + if (pbdev->interp) { + dereg_ioat_interp(pbdev); + return; + } + s390_pci_iommu_disable(iommu); iommu->pba = 0; iommu->pal = 0; @@ -1251,7 +1296,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar, cc = ZPCI_PCI_LS_ERR; s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE); } else { - pci_dereg_ioat(pbdev->iommu); + pci_dereg_ioat(pbdev); } break; case ZPCI_MOD_FC_REREG_IOAT: @@ -1262,7 +1307,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar, cc = ZPCI_PCI_LS_ERR; s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE); } else { - pci_dereg_ioat(pbdev->iommu); + pci_dereg_ioat(pbdev); if (reg_ioat(env, pbdev, fib, ra)) { cc = ZPCI_PCI_LS_ERR; s390_set_status_code(env, r1, ZPCI_MOD_ST_INSUF_RES); diff --git a/hw/s390x/s390-pci-vfio.c b/hw/s390x/s390-pci-vfio.c index 6f9271df87..6fc03a858a 100644 --- a/hw/s390x/s390-pci-vfio.c +++ b/hw/s390x/s390-pci-vfio.c @@ -240,6 +240,39 @@ int s390_pci_get_aif(S390PCIBusDevice *pbdev, bool enable, bool assist) return rc; } +int s390_pci_probe_ioat(S390PCIBusDevice *pbdev) +{ + VFIOPCIDevice *vdev = container_of(pbdev->pdev, VFIOPCIDevice, pdev); + struct vfio_device_feature feat = { + .argsz = sizeof(struct vfio_device_feature), + .flags = VFIO_DEVICE_FEATURE_PROBE + VFIO_DEVICE_FEATURE_ZPCI_IOAT + }; + + assert(vdev); + + return ioctl(vdev->vbasedev.fd, VFIO_DEVICE_FEATURE, &feat); +} + +int s390_pci_set_ioat(S390PCIBusDevice *pbdev, uint64_t iota) +{ + VFIOPCIDevice *vdev = container_of(pbdev->pdev, VFIOPCIDevice, pdev); + g_autofree struct vfio_device_feature *feat; + struct vfio_device_zpci_ioat *data; + int size; + + assert(vdev); + + size = sizeof(*feat) + sizeof(*data); + feat = g_malloc0(size); + feat->argsz = size; + feat->flags = VFIO_DEVICE_FEATURE_SET + VFIO_DEVICE_FEATURE_ZPCI_IOAT; + + data = (struct vfio_device_zpci_ioat *)&feat->data; + data->iota = iota; + + return ioctl(vdev->vbasedev.fd, VFIO_DEVICE_FEATURE, feat); +} + static void s390_pci_read_base(S390PCIBusDevice *pbdev, struct vfio_device_info *info) { diff --git a/include/hw/s390x/s390-pci-inst.h b/include/hw/s390x/s390-pci-inst.h index a55c448aad..13566fb7b4 100644 --- a/include/hw/s390x/s390-pci-inst.h +++ b/include/hw/s390x/s390-pci-inst.h @@ -99,7 +99,7 @@ typedef struct ZpciFib { } QEMU_PACKED ZpciFib; int pci_dereg_irqs(S390PCIBusDevice *pbdev); -void pci_dereg_ioat(S390PCIIOMMU *iommu); +void pci_dereg_ioat(S390PCIBusDevice *pbdev); int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra); int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra); int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra); diff --git a/include/hw/s390x/s390-pci-vfio.h b/include/hw/s390x/s390-pci-vfio.h index 6cec38a863..e7a2d8ff77 100644 --- a/include/hw/s390x/s390-pci-vfio.h +++ b/include/hw/s390x/s390-pci-vfio.h @@ -28,6 +28,8 @@ int s390_pci_probe_aif(S390PCIBusDevice *pbdev); int s390_pci_set_aif(S390PCIBusDevice *pbdev, ZpciFib *fib, bool enable, bool assist); int s390_pci_get_aif(S390PCIBusDevice *pbdev, bool enable, bool assist); +int s390_pci_probe_ioat(S390PCIBusDevice *pbdev); +int s390_pci_set_ioat(S390PCIBusDevice *pbdev, uint64_t iota); void s390_pci_get_clp_info(S390PCIBusDevice *pbdev); #else @@ -68,6 +70,14 @@ static inline int s390_pci_get_aif(S390PCIBusDevice *pbdev, bool enable, { return -EINVAL; } +static inline int s390_pci_probe_ioat(S390PCIBusDevice *pbdev) +{ + return -EINVAL; +} +static inline int s390_pci_set_ioat(S390PCIBusDevice *pbdev, uint64_t iota) +{ + return -EINVAL; +} static inline void s390_pci_get_clp_info(S390PCIBusDevice *pbdev) { } #endif
Allow the underlying kvm host to handle the Refresh PCI Translation instruction intercepts. Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com> --- hw/s390x/s390-pci-bus.c | 6 ++-- hw/s390x/s390-pci-inst.c | 51 ++++++++++++++++++++++++++++++-- hw/s390x/s390-pci-vfio.c | 33 +++++++++++++++++++++ include/hw/s390x/s390-pci-inst.h | 2 +- include/hw/s390x/s390-pci-vfio.h | 10 +++++++ 5 files changed, 95 insertions(+), 7 deletions(-)