]> www.infradead.org Git - users/dwmw2/qemu.git/commitdiff
s390x/pci: reject some operations to disabled PCI function
authorYi Min Zhao <zyimin@linux.vnet.ibm.com>
Mon, 14 Dec 2015 08:50:44 +0000 (16:50 +0800)
committerCornelia Huck <cornelia.huck@de.ibm.com>
Wed, 13 Jan 2016 09:53:42 +0000 (10:53 +0100)
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 <zyimin@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
hw/s390x/s390-pci-bus.c
hw/s390x/s390-pci-bus.h
hw/s390x/s390-pci-inst.c

index 8de35ffa057149dd96b520cd47fcd12a31d2dbd3..132588b758dbb3790502e85079155f24f2ff1262 100644 (file)
@@ -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;
 
index 80345dacb120400408243f1a5d57422895dd8472..d8ddb77281417ae93b3eb67b1982e92ce26bfdc1 100644 (file)
@@ -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) \
index 8c1dc82b1f8a6e57e65382006bc6c97a77b020b4..df57a7dfbf38ae14a0bc995d2437c36c3055dea8 100644 (file)
@@ -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;