Allow the underlying kvm host to handle the Refresh PCI Translation instruction intercepts. Signed-off-by: Matthew Rosato <mjrosato@xxxxxxxxxxxxx> --- hw/s390x/s390-pci-bus.c | 6 ++--- hw/s390x/s390-pci-inst.c | 42 +++++++++++++++++++++++++++++--- hw/s390x/s390-pci-kvm.c | 21 ++++++++++++++++ include/hw/s390x/s390-pci-inst.h | 2 +- include/hw/s390x/s390-pci-kvm.h | 10 ++++++++ 5 files changed, 74 insertions(+), 7 deletions(-) diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 513a276711..32894fbe9c 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -197,7 +197,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; @@ -1265,7 +1265,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); @@ -1406,7 +1406,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 f7b01e2059..86bb04e859 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -969,6 +969,19 @@ int pci_dereg_irqs(S390PCIBusDevice *pbdev) return 0; } +static int reg_ioat_interp(S390PCIBusDevice *pbdev, uint64_t iota) +{ + int rc; + + rc = s390_pci_kvm_ioat_enable(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) { @@ -986,6 +999,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); @@ -1002,8 +1025,21 @@ 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) +{ + s390_pci_kvm_ioat_disable(pbdev); + 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; @@ -1228,7 +1264,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: @@ -1239,7 +1275,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-kvm.c b/hw/s390x/s390-pci-kvm.c index ebb862abd0..2332efd676 100644 --- a/hw/s390x/s390-pci-kvm.c +++ b/hw/s390x/s390-pci-kvm.c @@ -137,3 +137,24 @@ int s390_pci_kvm_aif_disable(S390PCIBusDevice *pbdev) return kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, &args); } + +int s390_pci_kvm_ioat_enable(S390PCIBusDevice *pbdev, uint64_t iota) +{ + struct kvm_s390_zpci_op args = { + .fh = pbdev->fh, + .op = KVM_S390_ZPCIOP_REG_IOAT, + .u.reg_ioat.iota = iota + }; + + return kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, &args); +} + +int s390_pci_kvm_ioat_disable(S390PCIBusDevice *pbdev) +{ + struct kvm_s390_zpci_op args = { + .fh = pbdev->fh, + .op = KVM_S390_ZPCIOP_DEREG_IOAT + }; + + return kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, &args); +} 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-kvm.h b/include/hw/s390x/s390-pci-kvm.h index 09004d3f6c..e52e92d0f0 100644 --- a/include/hw/s390x/s390-pci-kvm.h +++ b/include/hw/s390x/s390-pci-kvm.h @@ -23,6 +23,8 @@ int s390_pci_kvm_interp_enable(S390PCIBusDevice *pbdev); int s390_pci_kvm_interp_disable(S390PCIBusDevice *pbdev); int s390_pci_kvm_aif_enable(S390PCIBusDevice *pbdev, ZpciFib *fib, bool assist); int s390_pci_kvm_aif_disable(S390PCIBusDevice *pbdev); +int s390_pci_kvm_ioat_enable(S390PCIBusDevice *pbdev, uint64_t iota); +int s390_pci_kvm_ioat_disable(S390PCIBusDevice *pbdev); #else static inline bool s390_pci_kvm_zpciop_allowed(void) { @@ -53,6 +55,14 @@ static inline int s390_pci_kvm_aif_disable(S390PCIBusDevice *pbdev) { return -EINVAL; } +int s390_pci_kvm_ioat_enable(S390PCIBusDevice *pbdev, uint64_t iota) +{ + return -EINVAL; +} +int s390_pci_kvm_ioat_disable(S390PCIBusDevice *pbdev) +{ + return -EINVAL; +} #endif #endif -- 2.27.0