Extract the pba, pal and g_iota checks from reg_ioat() into a function. Make it external so that it can also be used in a follow up change.
Signed-off-by: Konstantin Shkolnyy <[email protected]> --- hw/s390x/s390-pci-inst.c | 52 ++++++++++++++++++++------------ include/hw/s390x/s390-pci-inst.h | 2 ++ 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 98380526d1..b0af15ff15 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -1028,32 +1028,22 @@ bool s390_pci_is_translation_enabled(uint64_t g_iota) return ((g_iota >> 11) & 0x1) != 0; /* "T" bit */ } -static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib, - uintptr_t ra) +bool s390_pci_ioat_validate(S390PCIBusDevice *pbdev, uint64_t pba, + uint64_t pal, uint64_t g_iota, Error **errp) { - uint64_t pba = ldq_be_p(&fib.pba); - uint64_t pal = ldq_be_p(&fib.pal); - uint64_t g_iota = ldq_be_p(&fib.iota); uint8_t dt = (g_iota >> 2) & 0x7; bool t = s390_pci_is_translation_enabled(g_iota); - pba &= ~0xfff; - pal |= 0xfff; if (pba > pal || pba < pbdev->zpci_fn.sdma || pal > pbdev->zpci_fn.edma) { - s390_program_interrupt(env, PGM_OPERAND, ra); - return -EINVAL; + return false; } - /* currently we only support designation type 1 with translation */ if (t && dt != ZPCI_IOTA_RTTO) { - qemu_log_mask(LOG_GUEST_ERROR, - "unsupported ioat dt %d t %d\n", dt, t); - s390_program_interrupt(env, PGM_OPERAND, ra); - return -EINVAL; + error_setg(errp, "unsupported ioat dt %d t %d", dt, t); + return false; } else if (!t && !pbdev->rtr_avail) { - qemu_log_mask(LOG_GUEST_ERROR, "relaxed translation not allowed\n"); - s390_program_interrupt(env, PGM_OPERAND, ra); - return -EINVAL; + error_setg(errp, "relaxed translation not allowed"); + return false; } /* @@ -1064,9 +1054,31 @@ static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib, * to QEMU for additional IOAT regions. */ if (t && pal >= ZPCI_TABLE_SIZE_RT) { - qemu_log_mask(LOG_GUEST_ERROR, - "ioat pal 0x%"PRIx64" exceeds max translatable address\n", - pal); + error_setg(errp, + "ioat pal 0x%"PRIx64" exceeds max translatable address", + pal); + return false; + } + return true; +} + +static int reg_ioat(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib, + uintptr_t ra) +{ + Error *err = NULL; + uint64_t pba = ldq_be_p(&fib.pba); + uint64_t pal = ldq_be_p(&fib.pal); + uint64_t g_iota = ldq_be_p(&fib.iota); + bool t = s390_pci_is_translation_enabled(g_iota); + + pba &= ~0xfff; + pal |= 0xfff; + + if (!s390_pci_ioat_validate(pbdev, pba, pal, g_iota, &err)) { + if (err) { + qemu_log_mask(LOG_GUEST_ERROR, "%s\n", error_get_pretty(err)); + error_free(err); + } s390_program_interrupt(env, PGM_OPERAND, ra); return -EINVAL; } diff --git a/include/hw/s390x/s390-pci-inst.h b/include/hw/s390x/s390-pci-inst.h index 38268c256e..3493d2ced0 100644 --- a/include/hw/s390x/s390-pci-inst.h +++ b/include/hw/s390x/s390-pci-inst.h @@ -100,6 +100,8 @@ typedef struct ZpciFib { int pci_dereg_irqs(S390PCIBusDevice *pbdev); void pci_dereg_ioat(S390PCIBusDevice *pbdev); +bool s390_pci_ioat_validate(S390PCIBusDevice *pbdev, uint64_t pba, + uint64_t pal, uint64_t g_iota, Error **errp); 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); -- 2.34.1
