qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v4 08/12] spapr_iommu: introduce SPAPR_TCE_TABLE cla


From: Alexey Kardashevskiy
Subject: [Qemu-devel] [PATCH v4 08/12] spapr_iommu: introduce SPAPR_TCE_TABLE class
Date: Fri, 30 Aug 2013 20:15:34 +1000

This introduces a SPAPR TCE TABLE device class with a put_tce() callback.
This reworks the H_PUT_TCE, H_PUT_TCE_INDIRECT, H_STUFF_TCE hypercall
handlers to make use of the new put_tce() callback.

Signed-off-by: Alexey Kardashevskiy <address@hidden>
---
 hw/ppc/spapr_iommu.c   | 76 +++++++++++++++++++++++++++++++++++++++-----------
 include/hw/ppc/spapr.h | 13 +++++++++
 2 files changed, 73 insertions(+), 16 deletions(-)

diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 022e268..0b235b3 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -235,17 +235,34 @@ static target_ulong h_put_tce_indirect(PowerPCCPU *cpu,
     target_ulong npages = args[3];
     target_ulong ret = H_PARAMETER;
     sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);
+    sPAPRTCETableClass *info;
+
+    if (!tcet) {
+        return H_PARAMETER;
+    }
+
+    info = SPAPR_TCE_TABLE_GET_CLASS(tcet);
+    if (!info || !info->put_tce) {
+        return H_PARAMETER;
+    }
+
+    if ((tce_list & SPAPR_TCE_PAGE_MASK) || (npages > 512)) {
+        return H_PARAMETER;
+    }
 
     ioba &= ~SPAPR_TCE_PAGE_MASK;
     tce_list &= ~SPAPR_TCE_PAGE_MASK;
+    if (liobn & 0xFFFFFFFF00000000ULL) {
+        hcall_dprintf("spapr_vio_put_tce on out-of-boundsw LIOBN "
+                      TARGET_FMT_lx "\n", liobn);
+        return H_PARAMETER;
+    }
 
-    if (tcet) {
-        for (i = 0; i < npages; i++, ioba += SPAPR_TCE_PAGE_SIZE) {
-            target_ulong tce = ldq_phys(tce_list + i * sizeof(target_ulong));
-            ret = put_tce_emu(tcet, ioba, tce);
-            if (ret) {
-                break;
-            }
+    for (i = 0; i < npages; ++i, ioba += SPAPR_TCE_PAGE_SIZE) {
+        target_ulong tce = ldq_phys(tce_list + i * sizeof(target_ulong));
+        ret = info->put_tce(tcet, ioba, tce);
+        if (ret) {
+            break;
         }
     }
     trace_spapr_iommu_indirect(liobn, ioba, tce_list, ret);
@@ -263,15 +280,29 @@ static target_ulong h_stuff_tce(PowerPCCPU *cpu, 
sPAPREnvironment *spapr,
     target_ulong npages = args[3];
     target_ulong ret = H_PARAMETER;
     sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);
+    sPAPRTCETableClass *info;
+
+    if (!tcet) {
+        return H_PARAMETER;
+    }
+
+    info = SPAPR_TCE_TABLE_GET_CLASS(tcet);
+    if (!info || !info->put_tce) {
+        return H_PARAMETER;
+    }
+
+    if (liobn & 0xFFFFFFFF00000000ULL) {
+        hcall_dprintf("spapr_vio_put_tce on out-of-boundsw LIOBN "
+                      TARGET_FMT_lx "\n", liobn);
+        return H_PARAMETER;
+    }
 
     ioba &= ~SPAPR_TCE_PAGE_MASK;
 
-    if (tcet) {
-        for (i = 0; i < npages; ++i, ioba += SPAPR_TCE_PAGE_SIZE) {
-            ret = put_tce_emu(tcet, ioba, tce_value);
-            if (ret) {
-                break;
-            }
+    for (i = 0; i < npages; ++i, ioba += SPAPR_TCE_PAGE_SIZE) {
+        ret = info->put_tce(tcet, ioba, tce_value);
+        if (ret) {
+            break;
         }
     }
     trace_spapr_iommu_stuff(liobn, ioba, tce_value, ret);
@@ -287,12 +318,21 @@ static target_ulong h_put_tce(PowerPCCPU *cpu, 
sPAPREnvironment *spapr,
     target_ulong tce = args[2];
     target_ulong ret = H_PARAMETER;
     sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);
+    sPAPRTCETableClass *info;
+
+    if (!tcet) {
+        return H_PARAMETER;
+    }
+
+    info = SPAPR_TCE_TABLE_GET_CLASS(tcet);
+    if (!info || !info->put_tce) {
+        return H_PARAMETER;
+    }
 
     ioba &= ~(SPAPR_TCE_PAGE_SIZE - 1);
 
-    if (tcet) {
-        ret = put_tce_emu(tcet, ioba, tce);
-    }
+    ret = info->put_tce(tcet, ioba, tce);
+
     trace_spapr_iommu_put(liobn, ioba, tce, ret);
 
     return ret;
@@ -342,9 +382,12 @@ int spapr_tcet_dma_dt(void *fdt, int node_off, const char 
*propname,
 static void spapr_tce_table_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
+    sPAPRTCETableClass *stc = SPAPR_TCE_TABLE_CLASS(klass);
+
     dc->vmsd = &vmstate_spapr_tce_table;
     dc->init = spapr_tce_table_realize;
     dc->reset = spapr_tce_reset;
+    stc->put_tce = put_tce_emu;
 
     QLIST_INIT(&spapr_tce_tables);
 
@@ -359,6 +402,7 @@ static TypeInfo spapr_tce_table_info = {
     .parent = TYPE_DEVICE,
     .instance_size = sizeof(sPAPRTCETable),
     .class_init = spapr_tce_table_class_init,
+    .class_size = sizeof(sPAPRTCETableClass),
     .instance_finalize = spapr_tce_table_finalize,
 };
 
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index ca175b0..a54de97 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -362,12 +362,25 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr 
rtas_addr,
 
 #define RTAS_ERROR_LOG_MAX      2048
 
+typedef struct sPAPRTCETableClass sPAPRTCETableClass;
 typedef struct sPAPRTCETable sPAPRTCETable;
 
 #define TYPE_SPAPR_TCE_TABLE "spapr-tce-table"
 #define SPAPR_TCE_TABLE(obj) \
     OBJECT_CHECK(sPAPRTCETable, (obj), TYPE_SPAPR_TCE_TABLE)
 
+#define SPAPR_TCE_TABLE_CLASS(klass) \
+     OBJECT_CLASS_CHECK(sPAPRTCETableClass, (klass), TYPE_SPAPR_TCE_TABLE)
+#define SPAPR_TCE_TABLE_GET_CLASS(obj) \
+     OBJECT_GET_CLASS(sPAPRTCETableClass, (obj), TYPE_SPAPR_TCE_TABLE)
+
+struct sPAPRTCETableClass {
+    DeviceClass parent_class;
+
+    target_ulong (*put_tce)(sPAPRTCETable *tcet, target_ulong ioba,
+                            target_ulong tce);
+};
+
 struct sPAPRTCETable {
     DeviceState parent;
     uint32_t liobn;
-- 
1.8.4.rc4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]