mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-06 17:23:56 -06:00
s390x/pci: rework PCI STORE BLOCK
Enhance the fault detection. Fixup the precedence to check the destination path existance before checking for the source accessibility. Add the maxstbl entry to both the Query PCI Function Group response and the PCIBusDevice structure. Initialize the maxstbl to 128 per default until we get the actual data from the hardware. Signed-off-by: Pierre Morel <pmorel@linux.vnet.ibm.com> Reviewed-by: Yi Min Zhao <zyimin@linux.vnet.ibm.com> Message-Id: <1512046530-17773-5-git-send-email-pmorel@linux.vnet.ibm.com> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
This commit is contained in:
parent
8cbd6aab95
commit
0e7c259adf
3 changed files with 41 additions and 25 deletions
|
@ -297,6 +297,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra)
|
|||
stq_p(&resgrp->msia, ZPCI_MSI_ADDR);
|
||||
stw_p(&resgrp->mui, 0);
|
||||
stw_p(&resgrp->i, 128);
|
||||
stw_p(&resgrp->maxstbl, 128);
|
||||
resgrp->version = 0;
|
||||
|
||||
stw_p(&resgrp->hdr.rsp, CLP_RC_OK);
|
||||
|
@ -652,6 +653,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
|
|||
S390PCIBusDevice *pbdev;
|
||||
MemoryRegion *mr;
|
||||
MemTxResult result;
|
||||
uint64_t offset;
|
||||
int i;
|
||||
uint32_t fh;
|
||||
uint8_t pcias;
|
||||
|
@ -666,22 +668,10 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
|
|||
fh = env->regs[r1] >> 32;
|
||||
pcias = (env->regs[r1] >> 16) & 0xf;
|
||||
len = env->regs[r1] & 0xff;
|
||||
offset = env->regs[r3];
|
||||
|
||||
if (pcias > 5) {
|
||||
DPRINTF("pcistb invalid space\n");
|
||||
setcc(cpu, ZPCI_PCI_LS_ERR);
|
||||
s390_set_status_code(env, r1, ZPCI_PCI_ST_INVAL_AS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (len) {
|
||||
case 16:
|
||||
case 32:
|
||||
case 64:
|
||||
case 128:
|
||||
break;
|
||||
default:
|
||||
s390_program_interrupt(env, PGM_SPECIFICATION, 6, ra);
|
||||
if (!(fh & FH_MASK_ENABLE)) {
|
||||
setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -693,12 +683,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
|
|||
}
|
||||
|
||||
switch (pbdev->state) {
|
||||
case ZPCI_FS_RESERVED:
|
||||
case ZPCI_FS_STANDBY:
|
||||
case ZPCI_FS_DISABLED:
|
||||
case ZPCI_FS_PERMANENT_ERROR:
|
||||
setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
|
||||
return 0;
|
||||
case ZPCI_FS_ERROR:
|
||||
setcc(cpu, ZPCI_PCI_LS_ERR);
|
||||
s390_set_status_code(env, r1, ZPCI_PCI_ST_BLOCKED);
|
||||
|
@ -707,8 +692,34 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
|
|||
break;
|
||||
}
|
||||
|
||||
if (pcias > ZPCI_IO_BAR_MAX) {
|
||||
DPRINTF("pcistb invalid space\n");
|
||||
setcc(cpu, ZPCI_PCI_LS_ERR);
|
||||
s390_set_status_code(env, r1, ZPCI_PCI_ST_INVAL_AS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Verify the address, offset and length */
|
||||
/* offset must be a multiple of 8 */
|
||||
if (offset % 8) {
|
||||
goto specification_error;
|
||||
}
|
||||
/* Length must be greater than 8, a multiple of 8 */
|
||||
/* and not greater than maxstbl */
|
||||
if ((len <= 8) || (len % 8) || (len > pbdev->maxstbl)) {
|
||||
goto specification_error;
|
||||
}
|
||||
/* Do not cross a 4K-byte boundary */
|
||||
if (((offset & 0xfff) + len) > 0x1000) {
|
||||
goto specification_error;
|
||||
}
|
||||
/* Guest address must be double word aligned */
|
||||
if (gaddr & 0x07UL) {
|
||||
goto specification_error;
|
||||
}
|
||||
|
||||
mr = pbdev->pdev->io_regions[pcias].memory;
|
||||
if (!memory_region_access_valid(mr, env->regs[r3], len, true)) {
|
||||
if (!memory_region_access_valid(mr, offset, len, true)) {
|
||||
s390_program_interrupt(env, PGM_OPERAND, 6, ra);
|
||||
return 0;
|
||||
}
|
||||
|
@ -719,9 +730,9 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
|
|||
}
|
||||
|
||||
for (i = 0; i < len / 8; i++) {
|
||||
result = memory_region_dispatch_write(mr, env->regs[r3] + i * 8,
|
||||
ldq_p(buffer + i * 8), 8,
|
||||
MEMTXATTRS_UNSPECIFIED);
|
||||
result = memory_region_dispatch_write(mr, offset + i * 8,
|
||||
ldq_p(buffer + i * 8), 8,
|
||||
MEMTXATTRS_UNSPECIFIED);
|
||||
if (result != MEMTX_OK) {
|
||||
s390_program_interrupt(env, PGM_OPERAND, 6, ra);
|
||||
return 0;
|
||||
|
@ -730,6 +741,10 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
|
|||
|
||||
setcc(cpu, ZPCI_PCI_LS_OK);
|
||||
return 0;
|
||||
|
||||
specification_error:
|
||||
s390_program_interrupt(env, PGM_SPECIFICATION, 6, ra);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int reg_irqs(CPUS390XState *env, S390PCIBusDevice *pbdev, ZpciFib fib)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue