+ tce = tcet->table[addr >> tcet->page_shift];
+ ret.iova = addr & mask;
+ ret.translated_addr = tce & mask;
+ ret.addr_mask = ~mask;
ret.perm = tce;
}
trace_spapr_iommu_xlate(tcet->liobn, addr, ret.iova, ret.perm,
@@ -113,7 +114,7 @@ static int spapr_tce_table_realize(DeviceState *dev)
if (kvm_enabled()) {
tcet->table = kvmppc_create_spapr_tce(tcet->liobn,
tcet->nb_table <<
- SPAPR_TCE_PAGE_SHIFT,
+ tcet->page_shift,
&tcet->fd);
}
@@ -133,6 +134,7 @@ static int spapr_tce_table_realize(DeviceState *dev)
}
sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
+ uint32_t page_shift,
uint32_t nb_table)
{
sPAPRTCETable *tcet;
@@ -149,6 +151,7 @@ sPAPRTCETable *spapr_tce_new_table(DeviceState *owner,
uint32_t liobn,
tcet = SPAPR_TCE_TABLE(object_new(TYPE_SPAPR_TCE_TABLE));
tcet->liobn = liobn;
+ tcet->page_shift = page_shift;
tcet->nb_table = nb_table;
object_property_add_child(OBJECT(owner), "tce-table", OBJECT(tcet), NULL);
@@ -194,19 +197,20 @@ static target_ulong put_tce_emu(sPAPRTCETable *tcet,
target_ulong ioba,
target_ulong tce)
{
IOMMUTLBEntry entry;
+ target_ulong mask = ~((1 << tcet->page_shift) - 1);
- if ((ioba >> SPAPR_TCE_PAGE_SHIFT) >= tcet->nb_table) {
+ if ((ioba >> tcet->page_shift) >= tcet->nb_table) {
hcall_dprintf("spapr_vio_put_tce on out-of-bounds IOBA 0x"
TARGET_FMT_lx "\n", ioba);
return H_PARAMETER;
}
- tcet->table[ioba >> SPAPR_TCE_PAGE_SHIFT] = tce;
+ tcet->table[ioba >> tcet->page_shift] = tce;
entry.target_as = &address_space_memory,
- entry.iova = ioba & ~SPAPR_TCE_PAGE_MASK;
- entry.translated_addr = tce & ~SPAPR_TCE_PAGE_MASK;
- entry.addr_mask = SPAPR_TCE_PAGE_MASK;
+ entry.iova = ioba & mask;
+ entry.translated_addr = tce & mask;
+ entry.addr_mask = ~mask;
entry.perm = tce;
memory_region_notify_iommu(&tcet->iommu, entry);
@@ -226,6 +230,7 @@ static target_ulong h_put_tce_indirect(PowerPCCPU *cpu,
target_ulong ret = H_PARAMETER;
sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);
CPUState *cs = CPU(cpu);
+ target_ulong mask;
if (!tcet) {
return H_PARAMETER;
@@ -235,12 +240,14 @@ static target_ulong h_put_tce_indirect(PowerPCCPU *cpu,
return H_PARAMETER;
}
- ioba &= ~SPAPR_TCE_PAGE_MASK;
- tce_list &= ~SPAPR_TCE_PAGE_MASK;
+ mask = ~((1 << tcet->page_shift) - 1);
+ ioba &= mask;
+
+ for (i = 0; i < npages; ++i, ioba += (1 << tcet->page_shift)) {
+ target_ulong off = (tce_list & ~SPAPR_TCE_RW) +
+ i * sizeof(target_ulong);
+ target_ulong tce = ldq_phys(cs->as, off);
- for (i = 0; i < npages; ++i, ioba += SPAPR_TCE_PAGE_SIZE) {
- target_ulong tce = ldq_phys(cs->as, tce_list +
- i * sizeof(target_ulong));
ret = put_tce_emu(tcet, ioba, tce);
if (ret) {
break;
@@ -276,9 +283,9 @@ static target_ulong h_stuff_tce(PowerPCCPU *cpu,
sPAPREnvironment *spapr,
return H_PARAMETER;
}
- ioba &= ~SPAPR_TCE_PAGE_MASK;
+ ioba &= ~((1 << tcet->page_shift) - 1);
- for (i = 0; i < npages; ++i, ioba += SPAPR_TCE_PAGE_SIZE) {
+ for (i = 0; i < npages; ++i, ioba += (1 << tcet->page_shift)) {
ret = put_tce_emu(tcet, ioba, tce_value);
if (ret) {
break;
@@ -298,7 +305,7 @@ static target_ulong h_put_tce(PowerPCCPU *cpu,
sPAPREnvironment *spapr,
target_ulong ret = H_PARAMETER;
sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);
- ioba &= ~(SPAPR_TCE_PAGE_SIZE - 1);
+ ioba &= ~((1 << tcet->page_shift) - 1);
if (tcet) {
ret = put_tce_emu(tcet, ioba, tce);
@@ -311,13 +318,13 @@ static target_ulong h_put_tce(PowerPCCPU *cpu,
sPAPREnvironment *spapr,
static target_ulong get_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
target_ulong *tce)
{
- if ((ioba >> SPAPR_TCE_PAGE_SHIFT) >= tcet->nb_table) {
+ if ((ioba >> tcet->page_shift) >= tcet->nb_table) {
hcall_dprintf("spapr_iommu_get_tce on out-of-bounds IOBA 0x"
TARGET_FMT_lx "\n", ioba);
return H_PARAMETER;
}
- *tce = tcet->table[ioba >> SPAPR_TCE_PAGE_SHIFT];
+ *tce = tcet->table[ioba >> tcet->page_shift];
return H_SUCCESS;
}
@@ -330,8 +337,9 @@ static target_ulong h_get_tce(PowerPCCPU *cpu,
sPAPREnvironment *spapr,
target_ulong tce = 0;
target_ulong ret = H_PARAMETER;
sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);
+ const target_ulong mask = ~((1 << tcet->page_shift) - 1);
- ioba &= ~(SPAPR_TCE_PAGE_SIZE - 1);
+ ioba &= mask;
if (tcet) {
ret = get_tce_emu(tcet, ioba, &tce);
@@ -382,7 +390,7 @@ int spapr_tcet_dma_dt(void *fdt, int node_off, const char
*propname,
}
return spapr_dma_dt(fdt, node_off, propname,
- tcet->liobn, 0, tcet->nb_table <<
SPAPR_TCE_PAGE_SHIFT);
+ tcet->liobn, 0, tcet->nb_table << tcet->page_shift);
}
static void spapr_tce_table_class_init(ObjectClass *klass, void *data)
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index fdd4c07..c9850d4 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -656,6 +656,7 @@ static void spapr_phb_finish_realize(sPAPRPHBState *sphb,
Error **errp)
sPAPRTCETable *tcet;
tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn,
+ SPAPR_TCE_PAGE_SHIFT,
0x40000000 >> SPAPR_TCE_PAGE_SHIFT);
if (!tcet) {
error_setg(errp, "Unable to create TCE table for %s",
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index b84e481..d7e9e6a 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -457,6 +457,7 @@ static int spapr_vio_busdev_init(DeviceState *qdev)
if (pc->rtce_window_size) {
uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg;
dev->tcet = spapr_tce_new_table(qdev, liobn,
+ SPAPR_TCE_PAGE_SHIFT,