aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/ppc/Makefile.objs2
-rw-r--r--hw/spapr.c3
-rw-r--r--hw/spapr.h17
-rw-r--r--hw/spapr_iommu.c242
-rw-r--r--hw/spapr_llan.c63
-rw-r--r--hw/spapr_vio.c281
-rw-r--r--hw/spapr_vio.h73
-rw-r--r--hw/spapr_vscsi.c26
-rw-r--r--hw/spapr_vty.c2
-rw-r--r--target-ppc/kvm.c4
10 files changed, 370 insertions, 343 deletions
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index d18dbaf6cc..aa4bbeb664 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -10,7 +10,7 @@ obj-y += ppc_newworld.o
# IBM pSeries (sPAPR)
obj-$(CONFIG_PSERIES) += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
obj-$(CONFIG_PSERIES) += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o
-obj-$(CONFIG_PSERIES) += spapr_pci.o pci-hotplug.o
+obj-$(CONFIG_PSERIES) += spapr_pci.o pci-hotplug.o spapr_iommu.o
# PowerPC 4xx boards
obj-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
obj-y += ppc440_bamboo.o
diff --git a/hw/spapr.c b/hw/spapr.c
index 09a23ff092..81c9343ca5 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -674,6 +674,9 @@ static void ppc_spapr_init(ram_addr_t ram_size,
spapr->icp = xics_system_init(XICS_IRQS);
spapr->next_irq = 16;
+ /* Set up IOMMU */
+ spapr_iommu_init();
+
/* Set up VIO bus */
spapr->vio_bus = spapr_vio_bus_init();
diff --git a/hw/spapr.h b/hw/spapr.h
index c75172e0c0..1c4d85f977 100644
--- a/hw/spapr.h
+++ b/hw/spapr.h
@@ -1,6 +1,7 @@
#if !defined(__HW_SPAPR_H__)
#define __HW_SPAPR_H__
+#include "dma.h"
#include "hw/xics.h"
struct VIOsPAPRBus;
@@ -320,4 +321,20 @@ target_ulong spapr_rtas_call(sPAPREnvironment *spapr,
int spapr_rtas_device_tree_setup(void *fdt, target_phys_addr_t rtas_addr,
target_phys_addr_t rtas_size);
+#define SPAPR_TCE_PAGE_SHIFT 12
+#define SPAPR_TCE_PAGE_SIZE (1ULL << SPAPR_TCE_PAGE_SHIFT)
+#define SPAPR_TCE_PAGE_MASK (SPAPR_TCE_PAGE_SIZE - 1)
+
+typedef struct sPAPRTCE {
+ uint64_t tce;
+} sPAPRTCE;
+
+#define SPAPR_VIO_BASE_LIOBN 0x00000000
+
+void spapr_iommu_init(void);
+DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size);
+void spapr_tce_free(DMAContext *dma);
+int spapr_dma_dt(void *fdt, int node_off, const char *propname,
+ DMAContext *dma);
+
#endif /* !defined (__HW_SPAPR_H__) */
diff --git a/hw/spapr_iommu.c b/hw/spapr_iommu.c
new file mode 100644
index 0000000000..5a769b9f4a
--- /dev/null
+++ b/hw/spapr_iommu.c
@@ -0,0 +1,242 @@
+/*
+ * QEMU sPAPR IOMMU (TCE) code
+ *
+ * Copyright (c) 2010 David Gibson, IBM Corporation <dwg@au1.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "hw.h"
+#include "kvm.h"
+#include "qdev.h"
+#include "kvm_ppc.h"
+#include "dma.h"
+
+#include "hw/spapr.h"
+
+#include <libfdt.h>
+
+/* #define DEBUG_TCE */
+
+enum sPAPRTCEAccess {
+ SPAPR_TCE_FAULT = 0,
+ SPAPR_TCE_RO = 1,
+ SPAPR_TCE_WO = 2,
+ SPAPR_TCE_RW = 3,
+};
+
+typedef struct sPAPRTCETable sPAPRTCETable;
+
+struct sPAPRTCETable {
+ DMAContext dma;
+ uint32_t liobn;
+ uint32_t window_size;
+ sPAPRTCE *table;
+ int fd;
+ QLIST_ENTRY(sPAPRTCETable) list;
+};
+
+
+QLIST_HEAD(spapr_tce_tables, sPAPRTCETable) spapr_tce_tables;
+
+static sPAPRTCETable *spapr_tce_find_by_liobn(uint32_t liobn)
+{
+ sPAPRTCETable *tcet;
+
+ QLIST_FOREACH(tcet, &spapr_tce_tables, list) {
+ if (tcet->liobn == liobn) {
+ return tcet;
+ }
+ }
+
+ return NULL;
+}
+
+static int spapr_tce_translate(DMAContext *dma,
+ dma_addr_t addr,
+ target_phys_addr_t *paddr,
+ target_phys_addr_t *len,
+ DMADirection dir)
+{
+ sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
+ enum sPAPRTCEAccess access = (dir == DMA_DIRECTION_FROM_DEVICE)
+ ? SPAPR_TCE_WO : SPAPR_TCE_RO;
+ uint64_t tce;
+
+#ifdef DEBUG_TCE
+ fprintf(stderr, "spapr_tce_translate liobn=0x%" PRIx32 " addr=0x"
+ DMA_ADDR_FMT "\n", tcet->liobn, addr);
+#endif
+
+ /* Check if we are in bound */
+ if (addr >= tcet->window_size) {
+#ifdef DEBUG_TCE
+ fprintf(stderr, "spapr_tce_translate out of bounds\n");
+#endif
+ return -EFAULT;
+ }
+
+ tce = tcet->table[addr >> SPAPR_TCE_PAGE_SHIFT].tce;
+
+ /* Check TCE */
+ if (!(tce & access)) {
+ return -EPERM;
+ }
+
+ /* How much til end of page ? */
+ *len = ((~addr) & SPAPR_TCE_PAGE_MASK) + 1;
+
+ /* Translate */
+ *paddr = (tce & ~SPAPR_TCE_PAGE_MASK) |
+ (addr & SPAPR_TCE_PAGE_MASK);
+
+#ifdef DEBUG_TCE
+ fprintf(stderr, " -> *paddr=0x" TARGET_FMT_plx ", *len=0x"
+ TARGET_FMT_plx "\n", *paddr, *len);
+#endif
+
+ return 0;
+}
+
+DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size)
+{
+ sPAPRTCETable *tcet;
+
+ if (!window_size) {
+ return NULL;
+ }
+
+ tcet = g_malloc0(sizeof(*tcet));
+ dma_context_init(&tcet->dma, spapr_tce_translate, NULL, NULL);
+
+ tcet->liobn = liobn;
+ tcet->window_size = window_size;
+
+ if (kvm_enabled()) {
+ tcet->table = kvmppc_create_spapr_tce(liobn,
+ window_size,
+ &tcet->fd);
+ }
+
+ if (!tcet->table) {
+ size_t table_size = (window_size >> SPAPR_TCE_PAGE_SHIFT)
+ * sizeof(sPAPRTCE);
+ tcet->table = g_malloc0(table_size);
+ }
+
+#ifdef DEBUG_TCE
+ fprintf(stderr, "spapr_iommu: New TCE table, liobn=0x%x, context @ %p, "
+ "table @ %p, fd=%d\n", liobn, &tcet->dma, tcet->table, tcet->fd);
+#endif
+
+ QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);
+
+ return &tcet->dma;
+}
+
+void spapr_tce_free(DMAContext *dma)
+{
+
+ if (dma) {
+ sPAPRTCETable *tcet = DO_UPCAST(sPAPRTCETable, dma, dma);
+
+ QLIST_REMOVE(tcet, list);
+
+ if (!kvm_enabled() ||
+ (kvmppc_remove_spapr_tce(tcet->table, tcet->fd,
+ tcet->window_size) != 0)) {
+ g_free(tcet->table);
+ }
+
+ g_free(tcet);
+ }
+}
+
+
+static target_ulong h_put_tce(CPUPPCState *env, sPAPREnvironment *spapr,
+ target_ulong opcode, target_ulong *args)
+{
+ target_ulong liobn = args[0];
+ 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);
+
+#ifdef DEBUG_TCE
+ fprintf(stderr, "spapr_vio_put_tce on liobn=" TARGET_FMT_lx /*%s*/
+ " ioba 0x" TARGET_FMT_lx " TCE 0x" TARGET_FMT_lx "\n",
+ 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;
+}
+
+void spapr_iommu_init(void)
+{
+ QLIST_INIT(&spapr_tce_tables);
+
+ /* hcall-tce */
+ spapr_register_hypercall(H_PUT_TCE, h_put_tce);
+}
+
+int spapr_dma_dt(void *fdt, int node_off, const char *propname,
+ DMAContext *dma)
+{
+ 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;
+ }
+
+ 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;
+ }
+ }
+
+ return 0;
+}
diff --git a/hw/spapr_llan.c b/hw/spapr_llan.c
index 8313043652..d26fe9fea3 100644
--- a/hw/spapr_llan.c
+++ b/hw/spapr_llan.c
@@ -71,7 +71,7 @@ typedef uint64_t vlan_bd_t;
#define VLAN_RXQ_BD_OFF 0
#define VLAN_FILTER_BD_OFF 8
#define VLAN_RX_BDS_OFF 16
-#define VLAN_MAX_BUFS ((SPAPR_VIO_TCE_PAGE_SIZE - VLAN_RX_BDS_OFF) / 8)
+#define VLAN_MAX_BUFS ((SPAPR_TCE_PAGE_SIZE - VLAN_RX_BDS_OFF) / 8)
typedef struct VIOsPAPRVLANDevice {
VIOsPAPRDevice sdev;
@@ -95,7 +95,7 @@ static ssize_t spapr_vlan_receive(VLANClientState *nc, const uint8_t *buf,
{
VIOsPAPRDevice *sdev = DO_UPCAST(NICState, nc, nc)->opaque;
VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev;
- vlan_bd_t rxq_bd = ldq_tce(sdev, dev->buf_list + VLAN_RXQ_BD_OFF);
+ vlan_bd_t rxq_bd = vio_ldq(sdev, dev->buf_list + VLAN_RXQ_BD_OFF);
vlan_bd_t bd;
int buf_ptr = dev->use_buf_ptr;
uint64_t handle;
@@ -114,11 +114,11 @@ static ssize_t spapr_vlan_receive(VLANClientState *nc, const uint8_t *buf,
do {
buf_ptr += 8;
- if (buf_ptr >= SPAPR_VIO_TCE_PAGE_SIZE) {
+ if (buf_ptr >= SPAPR_TCE_PAGE_SIZE) {
buf_ptr = VLAN_RX_BDS_OFF;
}
- bd = ldq_tce(sdev, dev->buf_list + buf_ptr);
+ bd = vio_ldq(sdev, dev->buf_list + buf_ptr);
dprintf("use_buf_ptr=%d bd=0x%016llx\n",
buf_ptr, (unsigned long long)bd);
} while ((!(bd & VLAN_BD_VALID) || (VLAN_BD_LEN(bd) < (size + 8)))
@@ -132,12 +132,12 @@ static ssize_t spapr_vlan_receive(VLANClientState *nc, const uint8_t *buf,
/* Remove the buffer from the pool */
dev->rx_bufs--;
dev->use_buf_ptr = buf_ptr;
- stq_tce(sdev, dev->buf_list + dev->use_buf_ptr, 0);
+ vio_stq(sdev, dev->buf_list + dev->use_buf_ptr, 0);
dprintf("Found buffer: ptr=%d num=%d\n", dev->use_buf_ptr, dev->rx_bufs);
/* Transfer the packet data */
- if (spapr_tce_dma_write(sdev, VLAN_BD_ADDR(bd) + 8, buf, size) < 0) {
+ if (spapr_vio_dma_write(sdev, VLAN_BD_ADDR(bd) + 8, buf, size) < 0) {
return -1;
}
@@ -149,23 +149,23 @@ static ssize_t spapr_vlan_receive(VLANClientState *nc, const uint8_t *buf,
control ^= VLAN_RXQC_TOGGLE;
}
- handle = ldq_tce(sdev, VLAN_BD_ADDR(bd));
- stq_tce(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 8, handle);
- stw_tce(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 4, size);
- sth_tce(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 2, 8);
- stb_tce(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr, control);
+ handle = vio_ldq(sdev, VLAN_BD_ADDR(bd));
+ vio_stq(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 8, handle);
+ vio_stl(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 4, size);
+ vio_sth(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 2, 8);
+ vio_stb(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr, control);
dprintf("wrote rxq entry (ptr=0x%llx): 0x%016llx 0x%016llx\n",
(unsigned long long)dev->rxq_ptr,
- (unsigned long long)ldq_tce(sdev, VLAN_BD_ADDR(rxq_bd) +
+ (unsigned long long)vio_ldq(sdev, VLAN_BD_ADDR(rxq_bd) +
dev->rxq_ptr),
- (unsigned long long)ldq_tce(sdev, VLAN_BD_ADDR(rxq_bd) +
+ (unsigned long long)vio_ldq(sdev, VLAN_BD_ADDR(rxq_bd) +
dev->rxq_ptr + 8));
dev->rxq_ptr += 16;
if (dev->rxq_ptr >= VLAN_BD_LEN(rxq_bd)) {
dev->rxq_ptr = 0;
- stq_tce(sdev, dev->buf_list + VLAN_RXQ_BD_OFF, rxq_bd ^ VLAN_BD_TOGGLE);
+ vio_stq(sdev, dev->buf_list + VLAN_RXQ_BD_OFF, rxq_bd ^ VLAN_BD_TOGGLE);
}
if (sdev->signal_state & 1) {
@@ -254,8 +254,10 @@ static int check_bd(VIOsPAPRVLANDevice *dev, vlan_bd_t bd,
return -1;
}
- if (spapr_vio_check_tces(&dev->sdev, VLAN_BD_ADDR(bd),
- VLAN_BD_LEN(bd), SPAPR_TCE_RW) != 0) {
+ if (!spapr_vio_dma_valid(&dev->sdev, VLAN_BD_ADDR(bd),
+ VLAN_BD_LEN(bd), DMA_DIRECTION_FROM_DEVICE)
+ || !spapr_vio_dma_valid(&dev->sdev, VLAN_BD_ADDR(bd),
+ VLAN_BD_LEN(bd), DMA_DIRECTION_TO_DEVICE)) {
return -1;
}
@@ -285,14 +287,14 @@ static target_ulong h_register_logical_lan(CPUPPCState *env,
return H_RESOURCE;
}
- if (check_bd(dev, VLAN_VALID_BD(buf_list, SPAPR_VIO_TCE_PAGE_SIZE),
- SPAPR_VIO_TCE_PAGE_SIZE) < 0) {
+ if (check_bd(dev, VLAN_VALID_BD(buf_list, SPAPR_TCE_PAGE_SIZE),
+ SPAPR_TCE_PAGE_SIZE) < 0) {
hcall_dprintf("Bad buf_list 0x" TARGET_FMT_lx "\n", buf_list);
return H_PARAMETER;
}
- filter_list_bd = VLAN_VALID_BD(filter_list, SPAPR_VIO_TCE_PAGE_SIZE);
- if (check_bd(dev, filter_list_bd, SPAPR_VIO_TCE_PAGE_SIZE) < 0) {
+ filter_list_bd = VLAN_VALID_BD(filter_list, SPAPR_TCE_PAGE_SIZE);
+ if (check_bd(dev, filter_list_bd, SPAPR_TCE_PAGE_SIZE) < 0) {
hcall_dprintf("Bad filter_list 0x" TARGET_FMT_lx "\n", filter_list);
return H_PARAMETER;
}
@@ -309,17 +311,17 @@ static target_ulong h_register_logical_lan(CPUPPCState *env,
rec_queue &= ~VLAN_BD_TOGGLE;
/* Initialize the buffer list */
- stq_tce(sdev, buf_list, rec_queue);
- stq_tce(sdev, buf_list + 8, filter_list_bd);
- spapr_tce_dma_zero(sdev, buf_list + VLAN_RX_BDS_OFF,
- SPAPR_VIO_TCE_PAGE_SIZE - VLAN_RX_BDS_OFF);
+ vio_stq(sdev, buf_list, rec_queue);
+ vio_stq(sdev, buf_list + 8, filter_list_bd);
+ spapr_vio_dma_set(sdev, buf_list + VLAN_RX_BDS_OFF, 0,
+ SPAPR_TCE_PAGE_SIZE - VLAN_RX_BDS_OFF);
dev->add_buf_ptr = VLAN_RX_BDS_OFF - 8;
dev->use_buf_ptr = VLAN_RX_BDS_OFF - 8;
dev->rx_bufs = 0;
dev->rxq_ptr = 0;
/* Initialize the receive queue */
- spapr_tce_dma_zero(sdev, VLAN_BD_ADDR(rec_queue), VLAN_BD_LEN(rec_queue));
+ spapr_vio_dma_set(sdev, VLAN_BD_ADDR(rec_queue), 0, VLAN_BD_LEN(rec_queue));
dev->isopen = 1;
return H_SUCCESS;
@@ -378,14 +380,14 @@ static target_ulong h_add_logical_lan_buffer(CPUPPCState *env,
do {
dev->add_buf_ptr += 8;
- if (dev->add_buf_ptr >= SPAPR_VIO_TCE_PAGE_SIZE) {
+ if (dev->add_buf_ptr >= SPAPR_TCE_PAGE_SIZE) {
dev->add_buf_ptr = VLAN_RX_BDS_OFF;
}
- bd = ldq_tce(sdev, dev->buf_list + dev->add_buf_ptr);
+ bd = vio_ldq(sdev, dev->buf_list + dev->add_buf_ptr);
} while (bd & VLAN_BD_VALID);
- stq_tce(sdev, dev->buf_list + dev->add_buf_ptr, buf);
+ vio_stq(sdev, dev->buf_list + dev->add_buf_ptr, buf);
dev->rx_bufs++;
@@ -451,7 +453,7 @@ static target_ulong h_send_logical_lan(CPUPPCState *env, sPAPREnvironment *spapr
lbuf = alloca(total_len);
p = lbuf;
for (i = 0; i < nbufs; i++) {
- ret = spapr_tce_dma_read(sdev, VLAN_BD_ADDR(bufs[i]),
+ ret = spapr_vio_dma_read(sdev, VLAN_BD_ADDR(bufs[i]),
p, VLAN_BD_LEN(bufs[i]));
if (ret < 0) {
return ret;
@@ -479,7 +481,7 @@ static target_ulong h_multicast_ctrl(CPUPPCState *env, sPAPREnvironment *spapr,
}
static Property spapr_vlan_properties[] = {
- DEFINE_SPAPR_PROPERTIES(VIOsPAPRVLANDevice, sdev, 0x10000000),
+ DEFINE_SPAPR_PROPERTIES(VIOsPAPRVLANDevice, sdev),
DEFINE_NIC_PROPERTIES(VIOsPAPRVLANDevice, nicconf),
DEFINE_PROP_END_OF_LIST(),
};
@@ -497,6 +499,7 @@ static void spapr_vlan_class_init(ObjectClass *klass, void *data)
k->dt_compatible = "IBM,l-lan";
k->signal_mask = 0x1;
dc->props = spapr_vlan_properties;
+ k->rtce_window_size = 0x10000000;
}
static TypeInfo spapr_vlan_info = {
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index c8271c626c..05b55032a9 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -39,7 +39,6 @@
#endif /* CONFIG_FDT */
/* #define DEBUG_SPAPR */
-/* #define DEBUG_TCE */
#ifdef DEBUG_SPAPR
#define dprintf(fmt, ...) \
@@ -143,26 +142,9 @@ static int vio_make_devnode(VIOsPAPRDevice *dev,
}
}
- if (dev->rtce_window_size) {
- uint32_t dma_prop[] = {cpu_to_be32(dev->reg),
- 0, 0,
- 0, cpu_to_be32(dev->rtce_window_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(fdt, node_off, "ibm,my-dma-window", dma_prop,
- sizeof(dma_prop));
- if (ret < 0) {
- return ret;
- }
+ ret = spapr_dma_dt(fdt, node_off, "ibm,my-dma-window", dev->dma);
+ if (ret < 0) {
+ return ret;
}
if (pc->devnode) {
@@ -177,232 +159,6 @@ static int vio_make_devnode(VIOsPAPRDevice *dev,
#endif /* CONFIG_FDT */
/*
- * RTCE handling
- */
-
-static void rtce_init(VIOsPAPRDevice *dev)
-{
- size_t size = (dev->rtce_window_size >> SPAPR_VIO_TCE_PAGE_SHIFT)
- * sizeof(VIOsPAPR_RTCE);
-
- if (size) {
- dev->rtce_table = kvmppc_create_spapr_tce(dev->reg,
- dev->rtce_window_size,
- &dev->kvmtce_fd);
-
- if (!dev->rtce_table) {
- dev->rtce_table = g_malloc0(size);
- }
- }
-}
-
-static target_ulong h_put_tce(CPUPPCState *env, sPAPREnvironment *spapr,
- target_ulong opcode, target_ulong *args)
-{
- target_ulong liobn = args[0];
- target_ulong ioba = args[1];
- target_ulong tce = args[2];
- VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, liobn);
- VIOsPAPR_RTCE *rtce;
-
- if (!dev) {
- hcall_dprintf("LIOBN 0x" TARGET_FMT_lx " does not exist\n", liobn);
- return H_PARAMETER;
- }
-
- ioba &= ~(SPAPR_VIO_TCE_PAGE_SIZE - 1);
-
-#ifdef DEBUG_TCE
- fprintf(stderr, "spapr_vio_put_tce on %s ioba 0x" TARGET_FMT_lx
- " TCE 0x" TARGET_FMT_lx "\n", dev->qdev.id, ioba, tce);
-#endif
-
- if (ioba >= dev->rtce_window_size) {
- hcall_dprintf("Out-of-bounds IOBA 0x" TARGET_FMT_lx "\n", ioba);
- return H_PARAMETER;
- }
-
- rtce = dev->rtce_table + (ioba >> SPAPR_VIO_TCE_PAGE_SHIFT);
- rtce->tce = tce;
-
- return H_SUCCESS;
-}
-
-int spapr_vio_check_tces(VIOsPAPRDevice *dev, target_ulong ioba,
- target_ulong len, enum VIOsPAPR_TCEAccess access)
-{
- int start, end, i;
-
- start = ioba >> SPAPR_VIO_TCE_PAGE_SHIFT;
- end = (ioba + len - 1) >> SPAPR_VIO_TCE_PAGE_SHIFT;
-
- for (i = start; i <= end; i++) {
- if ((dev->rtce_table[i].tce & access) != access) {
-#ifdef DEBUG_TCE
- fprintf(stderr, "FAIL on %d\n", i);
-#endif
- return -1;
- }
- }
-
- return 0;
-}
-
-int spapr_tce_dma_write(VIOsPAPRDevice *dev, uint64_t taddr, const void *buf,
- uint32_t size)
-{
-#ifdef DEBUG_TCE
- fprintf(stderr, "spapr_tce_dma_write taddr=0x%llx size=0x%x\n",
- (unsigned long long)taddr, size);
-#endif
-
- /* Check for bypass */
- if (dev->flags & VIO_PAPR_FLAG_DMA_BYPASS) {
- cpu_physical_memory_write(taddr, buf, size);
- return 0;
- }
-
- while (size) {
- uint64_t tce;
- uint32_t lsize;
- uint64_t txaddr;
-
- /* Check if we are in bound */
- if (taddr >= dev->rtce_window_size) {
-#ifdef DEBUG_TCE
- fprintf(stderr, "spapr_tce_dma_write out of bounds\n");
-#endif
- return H_DEST_PARM;
- }
- tce = dev->rtce_table[taddr >> SPAPR_VIO_TCE_PAGE_SHIFT].tce;
-
- /* How much til end of page ? */
- lsize = MIN(size, ((~taddr) & SPAPR_VIO_TCE_PAGE_MASK) + 1);
-
- /* Check TCE */
- if (!(tce & 2)) {
- return H_DEST_PARM;
- }
-
- /* Translate */
- txaddr = (tce & ~SPAPR_VIO_TCE_PAGE_MASK) |
- (taddr & SPAPR_VIO_TCE_PAGE_MASK);
-
-#ifdef DEBUG_TCE
- fprintf(stderr, " -> write to txaddr=0x%llx, size=0x%x\n",
- (unsigned long long)txaddr, lsize);
-#endif
-
- /* Do it */
- cpu_physical_memory_write(txaddr, buf, lsize);
- buf += lsize;
- taddr += lsize;
- size -= lsize;
- }
- return 0;
-}
-
-int spapr_tce_dma_zero(VIOsPAPRDevice *dev, uint64_t taddr, uint32_t size)
-{
- /* FIXME: allocating a temp buffer is nasty, but just stepping
- * through writing zeroes is awkward. This will do for now. */
- uint8_t zeroes[size];
-
-#ifdef DEBUG_TCE
- fprintf(stderr, "spapr_tce_dma_zero taddr=0x%llx size=0x%x\n",
- (unsigned long long)taddr, size);
-#endif
-
- memset(zeroes, 0, size);
- return spapr_tce_dma_write(dev, taddr, zeroes, size);
-}
-
-void stb_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint8_t val)
-{
- spapr_tce_dma_write(dev, taddr, &val, sizeof(val));
-}
-
-void sth_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint16_t val)
-{
- val = tswap16(val);
- spapr_tce_dma_write(dev, taddr, &val, sizeof(val));
-}
-
-
-void stw_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint32_t val)
-{
- val = tswap32(val);
- spapr_tce_dma_write(dev, taddr, &val, sizeof(val));
-}
-
-void stq_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint64_t val)
-{
- val = tswap64(val);
- spapr_tce_dma_write(dev, taddr, &val, sizeof(val));
-}
-
-int spapr_tce_dma_read(VIOsPAPRDevice *dev, uint64_t taddr, void *buf,
- uint32_t size)
-{
-#ifdef DEBUG_TCE
- fprintf(stderr, "spapr_tce_dma_write taddr=0x%llx size=0x%x\n",
- (unsigned long long)taddr, size);
-#endif
-
- /* Check for bypass */
- if (dev->flags & VIO_PAPR_FLAG_DMA_BYPASS) {
- cpu_physical_memory_read(taddr, buf, size);
- return 0;
- }
-
- while (size) {
- uint64_t tce;
- uint32_t lsize;
- uint64_t txaddr;
-
- /* Check if we are in bound */
- if (taddr >= dev->rtce_window_size) {
-#ifdef DEBUG_TCE
- fprintf(stderr, "spapr_tce_dma_read out of bounds\n");
-#endif
- return H_DEST_PARM;
- }
- tce = dev->rtce_table[taddr >> SPAPR_VIO_TCE_PAGE_SHIFT].tce;
-
- /* How much til end of page ? */
- lsize = MIN(size, ((~taddr) & SPAPR_VIO_TCE_PAGE_MASK) + 1);
-
- /* Check TCE */
- if (!(tce & 1)) {
- return H_DEST_PARM;
- }
-
- /* Translate */
- txaddr = (tce & ~SPAPR_VIO_TCE_PAGE_MASK) |
- (taddr & SPAPR_VIO_TCE_PAGE_MASK);
-
-#ifdef DEBUG_TCE
- fprintf(stderr, " -> write to txaddr=0x%llx, size=0x%x\n",
- (unsigned long long)txaddr, lsize);
-#endif
- /* Do it */
- cpu_physical_memory_read(txaddr, buf, lsize);
- buf += lsize;
- taddr += lsize;
- size -= lsize;
- }
- return H_SUCCESS;
-}
-
-uint64_t ldq_tce(VIOsPAPRDevice *dev, uint64_t taddr)
-{
- uint64_t val;
-
- spapr_tce_dma_read(dev, taddr, &val, sizeof(val));
- return tswap64(val);
-}
-
-/*
* CRQ handling
*/
static target_ulong h_reg_crq(CPUPPCState *env, sPAPREnvironment *spapr,
@@ -526,7 +282,7 @@ int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq)
}
/* Maybe do a fast path for KVM just writing to the pages */
- rc = spapr_tce_dma_read(dev, dev->crq.qladdr + dev->crq.qnext, &byte, 1);
+ rc = spapr_vio_dma_read(dev, dev->crq.qladdr + dev->crq.qnext, &byte, 1);
if (rc) {
return rc;
}
@@ -534,7 +290,7 @@ int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq)
return 1;
}
- rc = spapr_tce_dma_write(dev, dev->crq.qladdr + dev->crq.qnext + 8,
+ rc = spapr_vio_dma_write(dev, dev->crq.qladdr + dev->crq.qnext + 8,
&crq[8], 8);
if (rc) {
return rc;
@@ -542,7 +298,7 @@ int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq)
kvmppc_eieio();
- rc = spapr_tce_dma_write(dev, dev->crq.qladdr + dev->crq.qnext, crq, 8);
+ rc = spapr_vio_dma_write(dev, dev->crq.qladdr + dev->crq.qnext, crq, 8);
if (rc) {
return rc;
}
@@ -560,13 +316,13 @@ int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq)
static void spapr_vio_quiesce_one(VIOsPAPRDevice *dev)
{
- dev->flags &= ~VIO_PAPR_FLAG_DMA_BYPASS;
+ VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+ uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg;
- if (dev->rtce_table) {
- size_t size = (dev->rtce_window_size >> SPAPR_VIO_TCE_PAGE_SHIFT)
- * sizeof(VIOsPAPR_RTCE);
- memset(dev->rtce_table, 0, size);
+ if (dev->dma) {
+ spapr_tce_free(dev->dma);
}
+ dev->dma = spapr_tce_new_dma_context(liobn, pc->rtce_window_size);
dev->crq.qladdr = 0;
dev->crq.qsize = 0;
@@ -593,9 +349,13 @@ static void rtas_set_tce_bypass(sPAPREnvironment *spapr, uint32_t token,
return;
}
if (enable) {
- dev->flags |= VIO_PAPR_FLAG_DMA_BYPASS;
+ spapr_tce_free(dev->dma);
+ dev->dma = NULL;
} else {
- dev->flags &= ~VIO_PAPR_FLAG_DMA_BYPASS;
+ VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+ uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg;
+
+ dev->dma = spapr_tce_new_dma_context(liobn, pc->rtce_window_size);
}
rtas_st(rets, 0, 0);
@@ -662,6 +422,7 @@ static int spapr_vio_busdev_init(DeviceState *qdev)
{
VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
VIOsPAPRDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+ uint32_t liobn;
char *id;
if (dev->reg != -1) {
@@ -703,7 +464,8 @@ static int spapr_vio_busdev_init(DeviceState *qdev)
return -1;
}
- rtce_init(dev);
+ liobn = SPAPR_VIO_BASE_LIOBN | dev->reg;
+ dev->dma = spapr_tce_new_dma_context(liobn, pc->rtce_window_size);
return pc->init(dev);
}
@@ -751,9 +513,6 @@ VIOsPAPRBus *spapr_vio_bus_init(void)
/* hcall-vio */
spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal);
- /* hcall-tce */
- spapr_register_hypercall(H_PUT_TCE, h_put_tce);
-
/* hcall-crq */
spapr_register_hypercall(H_REG_CRQ, h_reg_crq);
spapr_register_hypercall(H_FREE_CRQ, h_free_crq);
diff --git a/hw/spapr_vio.h b/hw/spapr_vio.h
index 2adad77d02..6f9a498ccd 100644
--- a/hw/spapr_vio.h
+++ b/hw/spapr_vio.h
@@ -21,16 +21,7 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#define SPAPR_VIO_TCE_PAGE_SHIFT 12
-#define SPAPR_VIO_TCE_PAGE_SIZE (1ULL << SPAPR_VIO_TCE_PAGE_SHIFT)
-#define SPAPR_VIO_TCE_PAGE_MASK (SPAPR_VIO_TCE_PAGE_SIZE - 1)
-
-enum VIOsPAPR_TCEAccess {
- SPAPR_TCE_FAULT = 0,
- SPAPR_TCE_RO = 1,
- SPAPR_TCE_WO = 2,
- SPAPR_TCE_RW = 3,
-};
+#include "dma.h"
#define TYPE_VIO_SPAPR_DEVICE "vio-spapr-device"
#define VIO_SPAPR_DEVICE(obj) \
@@ -45,10 +36,6 @@ enum VIOsPAPR_TCEAccess {
struct VIOsPAPRDevice;
-typedef struct VIOsPAPR_RTCE {
- uint64_t tce;
-} VIOsPAPR_RTCE;
-
typedef struct VIOsPAPR_CRQ {
uint64_t qladdr;
uint32_t qsize;
@@ -64,6 +51,7 @@ typedef struct VIOsPAPRDeviceClass {
const char *dt_name, *dt_type, *dt_compatible;
target_ulong signal_mask;
+ uint32_t rtce_window_size;
int (*init)(VIOsPAPRDevice *dev);
void (*reset)(VIOsPAPRDevice *dev);
int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off);
@@ -73,20 +61,15 @@ struct VIOsPAPRDevice {
DeviceState qdev;
uint32_t reg;
uint32_t flags;
-#define VIO_PAPR_FLAG_DMA_BYPASS 0x1
qemu_irq qirq;
uint32_t vio_irq_num;
target_ulong signal_state;
- uint32_t rtce_window_size;
- VIOsPAPR_RTCE *rtce_table;
- int kvmtce_fd;
VIOsPAPR_CRQ crq;
+ DMAContext *dma;
};
-#define DEFINE_SPAPR_PROPERTIES(type, field, default_dma_window) \
- DEFINE_PROP_UINT32("reg", type, field.reg, -1), \
- DEFINE_PROP_UINT32("dma-window", type, field.rtce_window_size, \
- default_dma_window)
+#define DEFINE_SPAPR_PROPERTIES(type, field) \
+ DEFINE_PROP_UINT32("reg", type, field.reg, -1)
struct VIOsPAPRBus {
BusState bus;
@@ -102,20 +85,38 @@ extern int spapr_populate_chosen_stdout(void *fdt, VIOsPAPRBus *bus);
extern int spapr_vio_signal(VIOsPAPRDevice *dev, target_ulong mode);
-int spapr_vio_check_tces(VIOsPAPRDevice *dev, target_ulong ioba,
- target_ulong len,
- enum VIOsPAPR_TCEAccess access);
-
-int spapr_tce_dma_read(VIOsPAPRDevice *dev, uint64_t taddr,
- void *buf, uint32_t size);
-int spapr_tce_dma_write(VIOsPAPRDevice *dev, uint64_t taddr,
- const void *buf, uint32_t size);
-int spapr_tce_dma_zero(VIOsPAPRDevice *dev, uint64_t taddr, uint32_t size);
-void stb_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint8_t val);
-void sth_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint16_t val);
-void stw_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint32_t val);
-void stq_tce(VIOsPAPRDevice *dev, uint64_t taddr, uint64_t val);
-uint64_t ldq_tce(VIOsPAPRDevice *dev, uint64_t taddr);
+static inline bool spapr_vio_dma_valid(VIOsPAPRDevice *dev, uint64_t taddr,
+ uint32_t size, DMADirection dir)
+{
+ return dma_memory_valid(dev->dma, taddr, size, dir);
+}
+
+static inline int spapr_vio_dma_read(VIOsPAPRDevice *dev, uint64_t taddr,
+ void *buf, uint32_t size)
+{
+ return (dma_memory_read(dev->dma, taddr, buf, size) != 0) ?
+ H_DEST_PARM : H_SUCCESS;
+}
+
+static inline int spapr_vio_dma_write(VIOsPAPRDevice *dev, uint64_t taddr,
+ const void *buf, uint32_t size)
+{
+ return (dma_memory_write(dev->dma, taddr, buf, size) != 0) ?
+ H_DEST_PARM : H_SUCCESS;
+}
+
+static inline int spapr_vio_dma_set(VIOsPAPRDevice *dev, uint64_t taddr,
+ uint8_t c, uint32_t size)
+{
+ return (dma_memory_set(dev->dma, taddr, c, size) != 0) ?
+ H_DEST_PARM : H_SUCCESS;
+}
+
+#define vio_stb(_dev, _addr, _val) (stb_dma((_dev)->dma, (_addr), (_val)))
+#define vio_sth(_dev, _addr, _val) (stw_be_dma((_dev)->dma, (_addr), (_val)))
+#define vio_stl(_dev, _addr, _val) (stl_be_dma((_dev)->dma, (_addr), (_val)))
+#define vio_stq(_dev, _addr, _val) (stq_be_dma((_dev)->dma, (_addr), (_val)))
+#define vio_ldq(_dev, _addr) (ldq_be_dma((_dev)->dma, (_addr)))
int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq);
diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index 2f09616dd5..3cf5844e0f 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -165,7 +165,7 @@ static int vscsi_send_iu(VSCSIState *s, vscsi_req *req,
long rc, rc1;
/* First copy the SRP */
- rc = spapr_tce_dma_write(&s->vdev, req->crq.s.IU_data_ptr,
+ rc = spapr_vio_dma_write(&s->vdev, req->crq.s.IU_data_ptr,
&req->iu, length);
if (rc) {
fprintf(stderr, "vscsi_send_iu: DMA write failure !\n");
@@ -281,9 +281,9 @@ static int vscsi_srp_direct_data(VSCSIState *s, vscsi_req *req,
llen = MIN(len, md->len);
if (llen) {
if (req->writing) { /* writing = to device = reading from memory */
- rc = spapr_tce_dma_read(&s->vdev, md->va, buf, llen);
+ rc = spapr_vio_dma_read(&s->vdev, md->va, buf, llen);
} else {
- rc = spapr_tce_dma_write(&s->vdev, md->va, buf, llen);
+ rc = spapr_vio_dma_write(&s->vdev, md->va, buf, llen);
}
}
md->len -= llen;
@@ -329,10 +329,11 @@ static int vscsi_srp_indirect_data(VSCSIState *s, vscsi_req *req,
md = req->cur_desc = &req->ext_desc;
dprintf("VSCSI: Reading desc from 0x%llx\n",
(unsigned long long)td->va);
- rc = spapr_tce_dma_read(&s->vdev, td->va, md,
+ rc = spapr_vio_dma_read(&s->vdev, td->va, md,
sizeof(struct srp_direct_buf));
if (rc) {
- dprintf("VSCSI: tce_dma_read -> %d reading ext_desc\n", rc);
+ dprintf("VSCSI: spapr_vio_dma_read -> %d reading ext_desc\n",
+ rc);
break;
}
vscsi_swap_desc(md);
@@ -345,12 +346,12 @@ static int vscsi_srp_indirect_data(VSCSIState *s, vscsi_req *req,
/* Perform transfer */
llen = MIN(len, md->len);
if (req->writing) { /* writing = to device = reading from memory */
- rc = spapr_tce_dma_read(&s->vdev, md->va, buf, llen);
+ rc = spapr_vio_dma_read(&s->vdev, md->va, buf, llen);
} else {
- rc = spapr_tce_dma_write(&s->vdev, md->va, buf, llen);
+ rc = spapr_vio_dma_write(&s->vdev, md->va, buf, llen);
}
if (rc) {
- dprintf("VSCSI: tce_dma_r/w(%d) -> %d\n", req->writing, rc);
+ dprintf("VSCSI: spapr_vio_dma_r/w(%d) -> %d\n", req->writing, rc);
break;
}
dprintf("VSCSI: data: %02x %02x %02x %02x...\n",
@@ -728,7 +729,7 @@ static int vscsi_send_adapter_info(VSCSIState *s, vscsi_req *req)
sinfo = &req->iu.mad.adapter_info;
#if 0 /* What for ? */
- rc = spapr_tce_dma_read(&s->vdev, be64_to_cpu(sinfo->buffer),
+ rc = spapr_vio_dma_read(&s->vdev, be64_to_cpu(sinfo->buffer),
&info, be16_to_cpu(sinfo->common.length));
if (rc) {
fprintf(stderr, "vscsi_send_adapter_info: DMA read failure !\n");
@@ -742,7 +743,7 @@ static int vscsi_send_adapter_info(VSCSIState *s, vscsi_req *req)
info.os_type = cpu_to_be32(2);
info.port_max_txu[0] = cpu_to_be32(VSCSI_MAX_SECTORS << 9);
- rc = spapr_tce_dma_write(&s->vdev, be64_to_cpu(sinfo->buffer),
+ rc = spapr_vio_dma_write(&s->vdev, be64_to_cpu(sinfo->buffer),
&info, be16_to_cpu(sinfo->common.length));
if (rc) {
fprintf(stderr, "vscsi_send_adapter_info: DMA write failure !\n");
@@ -805,7 +806,7 @@ static void vscsi_got_payload(VSCSIState *s, vscsi_crq *crq)
}
/* XXX Handle failure differently ? */
- if (spapr_tce_dma_read(&s->vdev, crq->s.IU_data_ptr, &req->iu,
+ if (spapr_vio_dma_read(&s->vdev, crq->s.IU_data_ptr, &req->iu,
crq->s.IU_length)) {
fprintf(stderr, "vscsi_got_payload: DMA read failure !\n");
vscsi_put_req(req);
@@ -947,7 +948,7 @@ static int spapr_vscsi_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off)
}
static Property spapr_vscsi_properties[] = {
- DEFINE_SPAPR_PROPERTIES(VSCSIState, vdev, 0x10000000),
+ DEFINE_SPAPR_PROPERTIES(VSCSIState, vdev),
DEFINE_PROP_END_OF_LIST(),
};
@@ -964,6 +965,7 @@ static void spapr_vscsi_class_init(ObjectClass *klass, void *data)
k->dt_compatible = "IBM,v-scsi";
k->signal_mask = 0x00000001;
dc->props = spapr_vscsi_properties;
+ k->rtce_window_size = 0x10000000;
}
static TypeInfo spapr_vscsi_info = {
diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
index f340b83237..99e52cc6b7 100644
--- a/hw/spapr_vty.c
+++ b/hw/spapr_vty.c
@@ -133,7 +133,7 @@ void spapr_vty_create(VIOsPAPRBus *bus, CharDriverState *chardev)
}
static Property spapr_vty_properties[] = {
- DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev, 0),
+ DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev),
DEFINE_PROP_CHR("chardev", VIOsPAPRVTYDevice, chardev),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index b6ef72d16b..829e180f8b 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -1067,7 +1067,7 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd)
return NULL;
}
- len = (window_size / SPAPR_VIO_TCE_PAGE_SIZE) * sizeof(VIOsPAPR_RTCE);
+ len = (window_size / SPAPR_TCE_PAGE_SIZE) * sizeof(sPAPRTCE);
/* FIXME: round this up to page size */
table = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
@@ -1090,7 +1090,7 @@ int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t window_size)
return -1;
}
- len = (window_size / SPAPR_VIO_TCE_PAGE_SIZE)*sizeof(VIOsPAPR_RTCE);
+ len = (window_size / SPAPR_TCE_PAGE_SIZE)*sizeof(sPAPRTCE);
if ((munmap(table, len) < 0) ||
(close(fd) < 0)) {
fprintf(stderr, "KVM: Unexpected error removing TCE table: %s",