[prev in list] [next in list] [prev in thread] [next in thread]
List: qemu-ppc
Subject: [Qemu-ppc] [PATCH v4 08/12] spapr_iommu: introduce SPAPR_TCE_TABLE class
From: Alexey Kardashevskiy <aik () ozlabs ! ru>
Date: 2013-08-30 10:15:34
Message-ID: 1377857738-14789-9-git-send-email-aik () ozlabs ! ru
[Download RAW message or body]
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 <aik@ozlabs.ru>
---
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
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic