From: Yi Min Zhao <zyi...@linux.vnet.ibm.com> According to the s390 architecture, any mpcifc, pcilg, pcistg, pcistb and rpcit instructions issued to disabled PCI functions are rejected, and the instruction completes by setting condition code 3. In addition, any DMA and MSIX interruption operations are ignored.
Signed-off-by: Yi Min Zhao <zyi...@linux.vnet.ibm.com> Reviewed-by: Cornelia Huck <cornelia.h...@de.ibm.com> Signed-off-by: Cornelia Huck <cornelia.h...@de.ibm.com> --- hw/s390x/s390-pci-bus.c | 6 +++++- hw/s390x/s390-pci-bus.h | 1 + hw/s390x/s390-pci-inst.c | 11 +++++------ 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 8de35ff..132588b 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -317,7 +317,7 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr, .perm = IOMMU_NONE, }; - if (!pbdev->configured || !pbdev->pdev) { + if (!pbdev->configured || !pbdev->pdev || !(pbdev->fh & FH_ENABLED)) { return ret; } @@ -428,6 +428,10 @@ static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data, return; } + if (!(pbdev->fh & FH_ENABLED)) { + return; + } + ind_bit = pbdev->routes.adapter.ind_offset; sum_bit = pbdev->routes.adapter.summary_offset; diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h index 80345da..d8ddb77 100644 --- a/hw/s390x/s390-pci-bus.h +++ b/hw/s390x/s390-pci-bus.h @@ -23,6 +23,7 @@ #define TYPE_S390_PCI_HOST_BRIDGE "s390-pcihost" #define FH_VIRT 0x00ff0000 #define ENABLE_BIT_OFFSET 31 +#define FH_ENABLED (1 << ENABLE_BIT_OFFSET) #define S390_PCIPT_ADAPTER 2 #define S390_PCI_HOST_BRIDGE(obj) \ diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 8c1dc82..df57a7d 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -313,7 +313,7 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) offset = env->regs[r2 + 1]; pbdev = s390_pci_find_dev_by_fh(fh); - if (!pbdev) { + if (!pbdev || !(pbdev->fh & FH_ENABLED)) { DPRINTF("pcilg no pci dev\n"); setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); return 0; @@ -430,7 +430,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) offset = env->regs[r2 + 1]; pbdev = s390_pci_find_dev_by_fh(fh); - if (!pbdev) { + if (!pbdev || !(pbdev->fh & FH_ENABLED)) { DPRINTF("pcistg no pci dev\n"); setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); return 0; @@ -521,8 +521,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) end = start + env->regs[r2 + 1]; pbdev = s390_pci_find_dev_by_fh(fh); - - if (!pbdev) { + if (!pbdev || !(pbdev->fh & FH_ENABLED)) { DPRINTF("rpcit no pci dev\n"); setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); goto out; @@ -586,7 +585,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, } pbdev = s390_pci_find_dev_by_fh(fh); - if (!pbdev) { + if (!pbdev || !(pbdev->fh & FH_ENABLED)) { DPRINTF("pcistb no pci dev fh 0x%x\n", fh); setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); return 0; @@ -727,7 +726,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) } pbdev = s390_pci_find_dev_by_fh(fh); - if (!pbdev) { + if (!pbdev || !(pbdev->fh & FH_ENABLED)) { DPRINTF("mpcifc no pci dev fh 0x%x\n", fh); setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); return 0; -- 2.7.0