diff options
author | Pierre Morel | 2016-08-24 12:53:31 +0200 |
---|---|---|
committer | Cornelia Huck | 2016-10-31 10:02:09 +0100 |
commit | 88ee13c7b656e5504613b527f3a51591e9afae69 (patch) | |
tree | 5d18d4882e42970a09399f77b52c8a68d98a9793 /hw/s390x/s390-pci-inst.c | |
parent | s390x/pci: use generic interface to inject interrupt (diff) | |
download | qemu-88ee13c7b656e5504613b527f3a51591e9afae69.tar.gz qemu-88ee13c7b656e5504613b527f3a51591e9afae69.tar.xz qemu-88ee13c7b656e5504613b527f3a51591e9afae69.zip |
s390x/pci: Check memory region dispatching callbacks
The instructions PCI STORE, PCI LOAD and PCI STORE BLOCK
use calls to memory_region_dispatch_write() and
memory_region_dispatch_read() but do not test the return value.
Furthermore, the instruction PCI STORE BLOCK sets up a PGM_ADDRESSING
exception when the operand 3 is not within the designated PCI address
space instead of a PGM_OPERAND exception.
Let's setup a PGM_OPERAND exception in all of these failure cases.
Signed-off-by: Pierre Morel <pmorel@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Diffstat (limited to 'hw/s390x/s390-pci-inst.c')
-rw-r--r-- | hw/s390x/s390-pci-inst.c | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 80a51049ca..0864d9be12 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -316,6 +316,7 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) uint64_t offset; uint64_t data; MemoryRegion *mr; + MemTxResult result; uint8_t len; uint32_t fh; uint8_t pcias; @@ -365,8 +366,12 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) return 0; } mr = pbdev->pdev->io_regions[pcias].memory; - memory_region_dispatch_read(mr, offset, &data, len, - MEMTXATTRS_UNSPECIFIED); + result = memory_region_dispatch_read(mr, offset, &data, len, + MEMTXATTRS_UNSPECIFIED); + if (result != MEMTX_OK) { + program_interrupt(env, PGM_OPERAND, 4); + return 0; + } } else if (pcias == 15) { if ((4 - (offset & 0x3)) < len) { program_interrupt(env, PGM_OPERAND, 4); @@ -444,6 +449,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) uint64_t offset, data; S390PCIBusDevice *pbdev; MemoryRegion *mr; + MemTxResult result; uint8_t len; uint32_t fh; uint8_t pcias; @@ -502,8 +508,12 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) mr = pbdev->pdev->io_regions[pcias].memory; } - memory_region_dispatch_write(mr, offset, data, len, + result = memory_region_dispatch_write(mr, offset, data, len, MEMTXATTRS_UNSPECIFIED); + if (result != MEMTX_OK) { + program_interrupt(env, PGM_OPERAND, 4); + return 0; + } } else if (pcias == 15) { if ((4 - (offset & 0x3)) < len) { program_interrupt(env, PGM_OPERAND, 4); @@ -633,6 +643,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, CPUS390XState *env = &cpu->env; S390PCIBusDevice *pbdev; MemoryRegion *mr; + MemTxResult result; int i; uint32_t fh; uint8_t pcias; @@ -690,7 +701,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, mr = pbdev->pdev->io_regions[pcias].memory; if (!memory_region_access_valid(mr, env->regs[r3], len, true)) { - program_interrupt(env, PGM_ADDRESSING, 6); + program_interrupt(env, PGM_OPERAND, 6); return 0; } @@ -699,9 +710,13 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, } for (i = 0; i < len / 8; i++) { - memory_region_dispatch_write(mr, env->regs[r3] + i * 8, + result = memory_region_dispatch_write(mr, env->regs[r3] + i * 8, ldq_p(buffer + i * 8), 8, MEMTXATTRS_UNSPECIFIED); + if (result != MEMTX_OK) { + program_interrupt(env, PGM_OPERAND, 6); + return 0; + } } setcc(cpu, ZPCI_PCI_LS_OK); |