]> git.proxmox.com Git - qemu.git/blobdiff - hw/spapr_iommu.c
virtio-blk: hide VIRTIO_BLK_F_CONFIG_WCE from old machine types
[qemu.git] / hw / spapr_iommu.c
index 5a769b9f4ab54f629823964720dd3ba3734cf9c5..53b731773abc1f7e6d79fa3acd16a401f48771d7 100644 (file)
@@ -162,6 +162,22 @@ void spapr_tce_free(DMAContext *dma)
     }
 }
 
+static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
+                                target_ulong tce)
+{
+    sPAPRTCE *tcep;
+
+    if (ioba >= tcet->window_size) {
+        hcall_dprintf("spapr_vio_put_tce on out-of-boards IOBA 0x"
+                      TARGET_FMT_lx "\n", ioba);
+        return H_PARAMETER;
+    }
+
+    tcep = tcet->table + (ioba >> SPAPR_TCE_PAGE_SHIFT);
+    tcep->tce = tce;
+
+    return H_SUCCESS;
+}
 
 static target_ulong h_put_tce(CPUPPCState *env, sPAPREnvironment *spapr,
                               target_ulong opcode, target_ulong *args)
@@ -170,37 +186,25 @@ static target_ulong h_put_tce(CPUPPCState *env, sPAPREnvironment *spapr,
     target_ulong ioba = args[1];
     target_ulong tce = args[2];
     sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);
-    sPAPRTCE *tcep;
 
     if (liobn & 0xFFFFFFFF00000000ULL) {
         hcall_dprintf("spapr_vio_put_tce on out-of-boundsw LIOBN "
                       TARGET_FMT_lx "\n", liobn);
         return H_PARAMETER;
     }
-    if (!tcet) {
-        hcall_dprintf("spapr_vio_put_tce on non-existent LIOBN "
-                      TARGET_FMT_lx "\n", liobn);
-        return H_PARAMETER;
-    }
 
     ioba &= ~(SPAPR_TCE_PAGE_SIZE - 1);
 
+    if (tcet) {
+        return put_tce_emu(tcet, ioba, tce);
+    }
 #ifdef DEBUG_TCE
-    fprintf(stderr, "spapr_vio_put_tce on liobn=" TARGET_FMT_lx /*%s*/
+    fprintf(stderr, "%s on liobn=" TARGET_FMT_lx /*%s*/
             "  ioba 0x" TARGET_FMT_lx "  TCE 0x" TARGET_FMT_lx "\n",
-            liobn, /*dev->qdev.id, */ioba, tce);
+            __func__, liobn, /*dev->qdev.id, */ioba, tce);
 #endif
 
-    if (ioba >= tcet->window_size) {
-        hcall_dprintf("spapr_vio_put_tce on out-of-boards IOBA 0x"
-                      TARGET_FMT_lx "\n", ioba);
-        return H_PARAMETER;
-    }
-
-    tcep = tcet->table + (ioba >> SPAPR_TCE_PAGE_SHIFT);
-    tcep->tce = tce;
-
-    return H_SUCCESS;
+    return H_PARAMETER;
 }
 
 void spapr_iommu_init(void)
@@ -212,31 +216,47 @@ void spapr_iommu_init(void)
 }
 
 int spapr_dma_dt(void *fdt, int node_off, const char *propname,
-                 DMAContext *dma)
+                 uint32_t liobn, uint64_t window, uint32_t size)
 {
-    if (dma) {
-        sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
-        uint32_t dma_prop[] = {cpu_to_be32(tcet->liobn),
-                               0, 0,
-                               0, cpu_to_be32(tcet->window_size)};
-        int ret;
-
-        ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-address-cells", 2);
-        if (ret < 0) {
-            return ret;
-        }
+    uint32_t dma_prop[5];
+    int ret;
+
+    dma_prop[0] = cpu_to_be32(liobn);
+    dma_prop[1] = cpu_to_be32(window >> 32);
+    dma_prop[2] = cpu_to_be32(window & 0xFFFFFFFF);
+    dma_prop[3] = 0; /* window size is 32 bits */
+    dma_prop[4] = cpu_to_be32(size);
+
+    ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-address-cells", 2);
+    if (ret < 0) {
+        return ret;
+    }
 
-        ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-size-cells", 2);
-        if (ret < 0) {
-            return ret;
-        }
+    ret = fdt_setprop_cell(fdt, node_off, "ibm,#dma-size-cells", 2);
+    if (ret < 0) {
+        return ret;
+    }
 
-        ret = fdt_setprop(fdt, node_off, propname, dma_prop,
-                          sizeof(dma_prop));
-        if (ret < 0) {
-            return ret;
-        }
+    ret = fdt_setprop(fdt, node_off, propname, dma_prop, sizeof(dma_prop));
+    if (ret < 0) {
+        return ret;
     }
 
     return 0;
 }
+
+int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
+                      DMAContext *iommu)
+{
+    if (!iommu) {
+        return 0;
+    }
+
+    if (iommu->translate == spapr_tce_translate) {
+        sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, iommu);
+        return spapr_dma_dt(fdt, node_off, propname,
+                tcet->liobn, 0, tcet->window_size);
+    }
+
+    return -1;
+}