* [Qemu-devel] [PATCH v2 1/9] spapr: Enable dynamic change of the supported hypercalls list
2014-05-22 11:19 [Qemu-devel] [PATCH v2 0/9] spapr_pci: Prepare for VFIO Alexey Kardashevskiy
@ 2014-05-22 11:19 ` Alexey Kardashevskiy
2014-05-22 11:19 ` [Qemu-devel] [PATCH v2 2/9] spapr_iommu: Enable multiple TCE requests Alexey Kardashevskiy
` (7 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Alexey Kardashevskiy @ 2014-05-22 11:19 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Kardashevskiy, qemu-ppc, Alexander Graf
At the moment the "ibm,hypertas-functions" list is fixed. However some
calls should be listed there if they are supported by QEMU or the host
kernel.
This enables hyperrtas_prop to grow on stack by adding
a SPAPR_HYPERRTAS_ADD macro. "qemu,hypertas-functions" is converted as well.
The first user of this is going to be a "multi-tce" property.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
Changes:
v2:
* replaced alloca() with GString
* removed "inline" from add_str() definition
---
hw/ppc/spapr.c | 30 +++++++++++++++++++++++-------
1 file changed, 23 insertions(+), 7 deletions(-)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 0a61246..a16945d 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -293,6 +293,10 @@ static size_t create_page_sizes_prop(CPUPPCState *env, uint32_t *prop,
} \
} while (0)
+static void add_str(GString *s, const gchar *s1)
+{
+ g_string_append_len(s, s1, strlen(s1) + 1);
+}
static void *spapr_create_fdt_skel(hwaddr initrd_base,
hwaddr initrd_size,
@@ -306,9 +310,8 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
CPUState *cs;
uint32_t start_prop = cpu_to_be32(initrd_base);
uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
- char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt"
- "\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk\0hcall-set-mode";
- char qemu_hypertas_prop[] = "hcall-memop1";
+ GString *hypertas = g_string_sized_new(256);
+ GString *qemu_hypertas = g_string_sized_new(256);
uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)};
uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
int i, smt = kvmppc_smt_threads();
@@ -317,6 +320,17 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
unsigned sockets = opts ? qemu_opt_get_number(opts, "sockets", 0) : 0;
uint32_t cpus_per_socket = sockets ? (smp_cpus / sockets) : 1;
+ add_str(hypertas, "hcall-pft");
+ add_str(hypertas, "hcall-term");
+ add_str(hypertas, "hcall-dabr");
+ add_str(hypertas, "hcall-interrupt");
+ add_str(hypertas, "hcall-tce");
+ add_str(hypertas, "hcall-vio");
+ add_str(hypertas, "hcall-splpar");
+ add_str(hypertas, "hcall-bulk");
+ add_str(hypertas, "hcall-set-mode");
+ add_str(qemu_hypertas, "hcall-memop1");
+
fdt = g_malloc0(FDT_MAX_SIZE);
_FDT((fdt_create(fdt, FDT_MAX_SIZE)));
@@ -484,10 +498,12 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
/* RTAS */
_FDT((fdt_begin_node(fdt, "rtas")));
- _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas_prop,
- sizeof(hypertas_prop))));
- _FDT((fdt_property(fdt, "qemu,hypertas-functions", qemu_hypertas_prop,
- sizeof(qemu_hypertas_prop))));
+ _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas->str,
+ hypertas->len)));
+ g_string_free(hypertas, TRUE);
+ _FDT((fdt_property(fdt, "qemu,hypertas-functions", qemu_hypertas->str,
+ qemu_hypertas->len)));
+ g_string_free(qemu_hypertas, TRUE);
_FDT((fdt_property(fdt, "ibm,associativity-reference-points",
refpoints, sizeof(refpoints))));
--
1.9.rc0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH v2 2/9] spapr_iommu: Enable multiple TCE requests
2014-05-22 11:19 [Qemu-devel] [PATCH v2 0/9] spapr_pci: Prepare for VFIO Alexey Kardashevskiy
2014-05-22 11:19 ` [Qemu-devel] [PATCH v2 1/9] spapr: Enable dynamic change of the supported hypercalls list Alexey Kardashevskiy
@ 2014-05-22 11:19 ` Alexey Kardashevskiy
2014-05-22 11:19 ` [Qemu-devel] [PATCH v2 3/9] spapr_pci: Introduce a finish_realize() callback Alexey Kardashevskiy
` (6 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Alexey Kardashevskiy @ 2014-05-22 11:19 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Kardashevskiy, qemu-ppc, Alexander Graf
Currently only single TCE entry per request is supported (H_PUT_TCE).
However PAPR+ specification allows multiple entry requests such as
H_PUT_TCE_INDIRECT and H_STUFF_TCE. Having less transitions to the host
kernel via ioctls, support of these calls can accelerate IOMMU operations.
This implements H_STUFF_TCE and H_PUT_TCE_INDIRECT.
This advertises "multi-tce" capability to the guest if the host kernel
supports it (KVM_CAP_SPAPR_MULTITCE) or guest is running in TCG mode.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
Changes:
v2:
* multi-tce enabled explicitely for TCG, it was implicit
* kvmppc_spapr_use_multitce() does not handle TCG anymore
v1:
* removed checks for liobn as the check is performed already in
spapr_tce_find_by_liobn
* added hcall-multi-tce if the host kernel supports the capability
---
hw/ppc/spapr.c | 3 ++
hw/ppc/spapr_iommu.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++
target-ppc/kvm.c | 7 +++++
target-ppc/kvm_ppc.h | 6 ++++
trace-events | 2 ++
5 files changed, 96 insertions(+)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index a16945d..921fe5d 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -498,6 +498,9 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
/* RTAS */
_FDT((fdt_begin_node(fdt, "rtas")));
+ if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {
+ add_str(hypertas, "hcall-multi-tce");
+ }
_FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas->str,
hypertas->len)));
g_string_free(hypertas, TRUE);
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 72493d8..ab5037c 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -224,6 +224,82 @@ static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
return H_SUCCESS;
}
+static target_ulong h_put_tce_indirect(PowerPCCPU *cpu,
+ sPAPREnvironment *spapr,
+ target_ulong opcode, target_ulong *args)
+{
+ int i;
+ target_ulong liobn = args[0];
+ target_ulong ioba = args[1];
+ target_ulong ioba1 = ioba;
+ target_ulong tce_list = args[2];
+ target_ulong npages = args[3];
+ target_ulong ret = H_PARAMETER;
+ sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);
+ CPUState *cs = CPU(cpu);
+
+ if (!tcet) {
+ return H_PARAMETER;
+ }
+
+ if (npages > 512) {
+ return H_PARAMETER;
+ }
+
+ ioba &= ~SPAPR_TCE_PAGE_MASK;
+ tce_list &= ~SPAPR_TCE_PAGE_MASK;
+
+ 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;
+ }
+ }
+
+ /* Trace last successful or the first problematic entry */
+ i = i ? (i - 1) : 0;
+ trace_spapr_iommu_indirect(liobn, ioba1, tce_list, i,
+ ldq_phys(cs->as,
+ tce_list + i * sizeof(target_ulong)),
+ ret);
+
+ return ret;
+}
+
+static target_ulong h_stuff_tce(PowerPCCPU *cpu, sPAPREnvironment *spapr,
+ target_ulong opcode, target_ulong *args)
+{
+ int i;
+ target_ulong liobn = args[0];
+ target_ulong ioba = args[1];
+ target_ulong tce_value = args[2];
+ target_ulong npages = args[3];
+ target_ulong ret = H_PARAMETER;
+ sPAPRTCETable *tcet = spapr_tce_find_by_liobn(liobn);
+
+ if (!tcet) {
+ return H_PARAMETER;
+ }
+
+ if (npages > tcet->nb_table) {
+ return H_PARAMETER;
+ }
+
+ ioba &= ~SPAPR_TCE_PAGE_MASK;
+
+ for (i = 0; i < npages; ++i, ioba += SPAPR_TCE_PAGE_SIZE) {
+ ret = put_tce_emu(tcet, ioba, tce_value);
+ if (ret) {
+ break;
+ }
+ }
+ trace_spapr_iommu_stuff(liobn, ioba, tce_value, npages, ret);
+
+ return ret;
+}
+
static target_ulong h_put_tce(PowerPCCPU *cpu, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
@@ -332,6 +408,8 @@ static void spapr_tce_table_class_init(ObjectClass *klass, void *data)
/* hcall-tce */
spapr_register_hypercall(H_PUT_TCE, h_put_tce);
spapr_register_hypercall(H_GET_TCE, h_get_tce);
+ spapr_register_hypercall(H_PUT_TCE_INDIRECT, h_put_tce_indirect);
+ spapr_register_hypercall(H_STUFF_TCE, h_stuff_tce);
}
static TypeInfo spapr_tce_table_info = {
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index ca31027..bcf2db8 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -62,6 +62,7 @@ static int cap_booke_sregs;
static int cap_ppc_smt;
static int cap_ppc_rma;
static int cap_spapr_tce;
+static int cap_spapr_multitce;
static int cap_hior;
static int cap_one_reg;
static int cap_epr;
@@ -98,6 +99,7 @@ int kvm_arch_init(KVMState *s)
cap_ppc_smt = kvm_check_extension(s, KVM_CAP_PPC_SMT);
cap_ppc_rma = kvm_check_extension(s, KVM_CAP_PPC_RMA);
cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE);
+ cap_spapr_multitce = kvm_check_extension(s, KVM_CAP_SPAPR_MULTITCE);
cap_one_reg = kvm_check_extension(s, KVM_CAP_ONE_REG);
cap_hior = kvm_check_extension(s, KVM_CAP_PPC_HIOR);
cap_epr = kvm_check_extension(s, KVM_CAP_PPC_EPR);
@@ -1608,6 +1610,11 @@ uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift)
}
#endif
+bool kvmppc_spapr_use_multitce(void)
+{
+ return cap_spapr_multitce;
+}
+
void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd)
{
struct kvm_create_spapr_tce args = {
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index ff077ec..b90d31b 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -31,6 +31,7 @@ int kvmppc_set_tcr(PowerPCCPU *cpu);
int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu);
#ifndef CONFIG_USER_ONLY
off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem);
+bool kvmppc_spapr_use_multitce(void);
void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd);
int kvmppc_remove_spapr_tce(void *table, int pfd, uint32_t window_size);
int kvmppc_reset_htab(int shift_hint);
@@ -130,6 +131,11 @@ static inline off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem)
return 0;
}
+static inline bool kvmppc_spapr_use_multitce(void)
+{
+ return false;
+}
+
static inline void *kvmppc_create_spapr_tce(uint32_t liobn,
uint32_t window_size, int *fd)
{
diff --git a/trace-events b/trace-events
index 5997846..89719c7 100644
--- a/trace-events
+++ b/trace-events
@@ -1186,6 +1186,8 @@ xics_ics_eoi(int nr) "ics_eoi: irq %#x"
# hw/ppc/spapr_iommu.c
spapr_iommu_put(uint64_t liobn, uint64_t ioba, uint64_t tce, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tce=0x%"PRIx64" ret=%"PRId64
spapr_iommu_get(uint64_t liobn, uint64_t ioba, uint64_t ret, uint64_t tce) "liobn=%"PRIx64" ioba=0x%"PRIx64" ret=%"PRId64" tce=0x%"PRIx64
+spapr_iommu_indirect(uint64_t liobn, uint64_t ioba, uint64_t tce, uint64_t iobaN, uint64_t tceN, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tcelist=0x%"PRIx64" iobaN=0x%"PRIx64" tceN=0x%"PRIx64" ret=%"PRId64
+spapr_iommu_stuff(uint64_t liobn, uint64_t ioba, uint64_t tce_value, uint64_t npages, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tcevalue=0x%"PRIx64" npages=%"PRId64" ret=%"PRId64
spapr_iommu_xlate(uint64_t liobn, uint64_t ioba, uint64_t tce, unsigned perm, unsigned pgsize) "liobn=%"PRIx64" 0x%"PRIx64" -> 0x%"PRIx64" perm=%u mask=%x"
spapr_iommu_new_table(uint64_t liobn, void *tcet, void *table, int fd) "liobn=%"PRIx64" tcet=%p table=%p fd=%d"
--
1.9.rc0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH v2 3/9] spapr_pci: Introduce a finish_realize() callback
2014-05-22 11:19 [Qemu-devel] [PATCH v2 0/9] spapr_pci: Prepare for VFIO Alexey Kardashevskiy
2014-05-22 11:19 ` [Qemu-devel] [PATCH v2 1/9] spapr: Enable dynamic change of the supported hypercalls list Alexey Kardashevskiy
2014-05-22 11:19 ` [Qemu-devel] [PATCH v2 2/9] spapr_iommu: Enable multiple TCE requests Alexey Kardashevskiy
@ 2014-05-22 11:19 ` Alexey Kardashevskiy
2014-05-22 11:19 ` [Qemu-devel] [PATCH v2 4/9] spapr_pci: spapr_iommu: Make DMA window a subregion Alexey Kardashevskiy
` (5 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Alexey Kardashevskiy @ 2014-05-22 11:19 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Kardashevskiy, qemu-ppc, Alexander Graf
The spapr-pci PHB initializes IOMMU for emulated devices only.
The upcoming VFIO support will do it different. However both emulated
and VFIO PHB types share most of the initialization code.
For the type specific things a new finish_realize() callback is
introduced.
This introduces sPAPRPHBClass derived from PCIHostBridgeClass and
adds the callback pointer.
This implements finish_realize() for emulated devices.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
The difference to VFIO is that for VFIO we have to ask the kernel
about DMA window size before calling spapr_tce_new_table() and
then we have to tell VFIO KVM device about LIOBN <-> IOMMU link.
---
hw/ppc/spapr_pci.c | 38 ++++++++++++++++++++++++++------------
include/hw/pci-host/spapr.h | 14 ++++++++++++++
2 files changed, 40 insertions(+), 12 deletions(-)
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 1db73f2..b141e83 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -528,6 +528,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
SysBusDevice *s = SYS_BUS_DEVICE(dev);
sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
PCIHostState *phb = PCI_HOST_BRIDGE(s);
+ sPAPRPHBClass *info = SPAPR_PCI_HOST_BRIDGE_GET_CLASS(s);
char *namebuf;
int i;
PCIBus *bus;
@@ -609,18 +610,6 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
PCI_DEVFN(0, 0), PCI_NUM_PINS, TYPE_PCI_BUS);
phb->bus = bus;
- sphb->dma_window_start = 0;
- sphb->dma_window_size = 0x40000000;
- sphb->tcet = spapr_tce_new_table(dev, sphb->dma_liobn,
- sphb->dma_window_size);
- if (!sphb->tcet) {
- error_setg(errp, "Unable to create TCE table for %s",
- sphb->dtbusname);
- return;
- }
- address_space_init(&sphb->iommu_as, spapr_tce_get_iommu(sphb->tcet),
- sphb->dtbusname);
-
pci_setup_iommu(bus, spapr_pci_dma_iommu, sphb);
pci_bus_set_route_irq_fn(bus, spapr_route_intx_pin_to_irq);
@@ -639,6 +628,28 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
sphb->lsi_table[i].irq = irq;
}
+
+ if (!info->finish_realize) {
+ error_setg(errp, "finish_realize not defined");
+ return;
+ }
+
+ info->finish_realize(sphb, errp);
+}
+
+static void spapr_phb_finish_realize(sPAPRPHBState *sphb, Error **errp)
+{
+ sphb->dma_window_start = 0;
+ sphb->dma_window_size = 0x40000000;
+ sphb->tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn,
+ sphb->dma_window_size);
+ if (!sphb->tcet) {
+ error_setg(errp, "Unable to create TCE table for %s",
+ sphb->dtbusname);
+ return ;
+ }
+ address_space_init(&sphb->iommu_as, spapr_tce_get_iommu(sphb->tcet),
+ sphb->dtbusname);
}
static void spapr_phb_reset(DeviceState *qdev)
@@ -722,6 +733,7 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data)
{
PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
+ sPAPRPHBClass *spc = SPAPR_PCI_HOST_BRIDGE_CLASS(klass);
hc->root_bus_path = spapr_phb_root_bus_path;
dc->realize = spapr_phb_realize;
@@ -730,6 +742,7 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data)
dc->vmsd = &vmstate_spapr_pci;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
dc->cannot_instantiate_with_device_add_yet = false;
+ spc->finish_realize = spapr_phb_finish_realize;
}
static const TypeInfo spapr_phb_info = {
@@ -737,6 +750,7 @@ static const TypeInfo spapr_phb_info = {
.parent = TYPE_PCI_HOST_BRIDGE,
.instance_size = sizeof(sPAPRPHBState),
.class_init = spapr_phb_class_init,
+ .class_size = sizeof(sPAPRPHBClass),
};
PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index)
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index 970b4a9..ab29281 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -34,6 +34,20 @@
#define SPAPR_PCI_HOST_BRIDGE(obj) \
OBJECT_CHECK(sPAPRPHBState, (obj), TYPE_SPAPR_PCI_HOST_BRIDGE)
+#define SPAPR_PCI_HOST_BRIDGE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(sPAPRPHBClass, (klass), TYPE_SPAPR_PCI_HOST_BRIDGE)
+#define SPAPR_PCI_HOST_BRIDGE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(sPAPRPHBClass, (obj), TYPE_SPAPR_PCI_HOST_BRIDGE)
+
+typedef struct sPAPRPHBClass sPAPRPHBClass;
+typedef struct sPAPRPHBState sPAPRPHBState;
+
+struct sPAPRPHBClass {
+ PCIHostBridgeClass parent_class;
+
+ void (*finish_realize)(sPAPRPHBState *sphb, Error **errp);
+};
+
typedef struct sPAPRPHBState {
PCIHostState parent_obj;
--
1.9.rc0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH v2 4/9] spapr_pci: spapr_iommu: Make DMA window a subregion
2014-05-22 11:19 [Qemu-devel] [PATCH v2 0/9] spapr_pci: Prepare for VFIO Alexey Kardashevskiy
` (2 preceding siblings ...)
2014-05-22 11:19 ` [Qemu-devel] [PATCH v2 3/9] spapr_pci: Introduce a finish_realize() callback Alexey Kardashevskiy
@ 2014-05-22 11:19 ` Alexey Kardashevskiy
2014-05-22 11:19 ` [Qemu-devel] [PATCH v2 5/9] spapr_pci: Allow multiple TCE tables per PHB Alexey Kardashevskiy
` (4 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Alexey Kardashevskiy @ 2014-05-22 11:19 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Kardashevskiy, qemu-ppc, Alexander Graf
Currently the default DMA window is represented by a single MemoryRegion.
However there can be more than just one window so we need
a "root" memory region to be separated from the actual DMA window(s).
This introduces a "root" IOMMU memory region and adds a subregion for
the default DMA 32bit window. Following patches will add other
subregion(s).
This initializes a default DMA window subregion size to the guest RAM
size as this window can be switched into "bypass" mode which implements
direct DMA mapping.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
hw/ppc/spapr_iommu.c | 2 +-
hw/ppc/spapr_pci.c | 20 ++++++++++++++++++--
include/hw/pci-host/spapr.h | 1 +
3 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index ab5037c..241ceeb 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -136,7 +136,7 @@ static int spapr_tce_table_realize(DeviceState *dev)
trace_spapr_iommu_new_table(tcet->liobn, tcet, tcet->table, tcet->fd);
memory_region_init_iommu(&tcet->iommu, OBJECT(dev), &spapr_iommu_ops,
- "iommu-spapr", UINT64_MAX);
+ "iommu-spapr", ram_size);
QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index b141e83..f1684c2 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -610,6 +610,20 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
PCI_DEVFN(0, 0), PCI_NUM_PINS, TYPE_PCI_BUS);
phb->bus = bus;
+ /*
+ * Initialize PHB address space.
+ * By default there will be at least one subregion for default
+ * 32bit DMA window.
+ * Later the guest might want to create another DMA window
+ * which will become another memory subregion.
+ */
+ sprintf(namebuf, "%s.iommu-root", sphb->dtbusname);
+
+ memory_region_init(&sphb->iommu_root, OBJECT(sphb),
+ namebuf, UINT64_MAX);
+ address_space_init(&sphb->iommu_as, &sphb->iommu_root,
+ sphb->dtbusname);
+
pci_setup_iommu(bus, spapr_pci_dma_iommu, sphb);
pci_bus_set_route_irq_fn(bus, spapr_route_intx_pin_to_irq);
@@ -648,8 +662,10 @@ static void spapr_phb_finish_realize(sPAPRPHBState *sphb, Error **errp)
sphb->dtbusname);
return ;
}
- address_space_init(&sphb->iommu_as, spapr_tce_get_iommu(sphb->tcet),
- sphb->dtbusname);
+
+ /* Register default 32bit DMA window */
+ memory_region_add_subregion(&sphb->iommu_root, 0,
+ spapr_tce_get_iommu(sphb->tcet));
}
static void spapr_phb_reset(DeviceState *qdev)
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index ab29281..c98ebdf 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -64,6 +64,7 @@ typedef struct sPAPRPHBState {
uint64_t dma_window_size;
sPAPRTCETable *tcet;
AddressSpace iommu_as;
+ MemoryRegion iommu_root;
struct spapr_pci_lsi {
uint32_t irq;
--
1.9.rc0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH v2 5/9] spapr_pci: Allow multiple TCE tables per PHB
2014-05-22 11:19 [Qemu-devel] [PATCH v2 0/9] spapr_pci: Prepare for VFIO Alexey Kardashevskiy
` (3 preceding siblings ...)
2014-05-22 11:19 ` [Qemu-devel] [PATCH v2 4/9] spapr_pci: spapr_iommu: Make DMA window a subregion Alexey Kardashevskiy
@ 2014-05-22 11:19 ` Alexey Kardashevskiy
2014-05-22 11:19 ` [Qemu-devel] [PATCH v2 6/9] spapr_iommu: Convert old qdev_init_nofail() to object_property_set_bool Alexey Kardashevskiy
` (3 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Alexey Kardashevskiy @ 2014-05-22 11:19 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Kardashevskiy, qemu-ppc, Alexander Graf
At the moment sPAPRPHBState contains a @tcet pointer to the only
TCE table. However sPAPR spec allows having more than one DMA window.
Since the TCE object is already a child of SPAPR PHB object, there is
no need to keep an additional pointer to it in sPAPRPHBState so remove it.
This changes the way sPAPRPHBState::reset performs reset of sPAPRTCETable
objects.
This changes the default DMA window properties calculation.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
The only reason for sPAPRPHBState to keep a pointer to sPAPRTCETable is
to have a direct link to calculate default 32bit window properties.
So I decided to replace the link with a spapr_phb_children_dt() loop
and use first TCE table for default window. Is that ok or ugly?
---
hw/ppc/spapr_pci.c | 54 ++++++++++++++++++++++++++++++++++++---------
include/hw/pci-host/spapr.h | 1 -
2 files changed, 43 insertions(+), 12 deletions(-)
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index f1684c2..aa29116 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -653,11 +653,13 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
static void spapr_phb_finish_realize(sPAPRPHBState *sphb, Error **errp)
{
+ sPAPRTCETable *tcet;
+
sphb->dma_window_start = 0;
sphb->dma_window_size = 0x40000000;
- sphb->tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn,
- sphb->dma_window_size);
- if (!sphb->tcet) {
+ tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn,
+ sphb->dma_window_size);
+ if (!tcet) {
error_setg(errp, "Unable to create TCE table for %s",
sphb->dtbusname);
return ;
@@ -665,16 +667,24 @@ static void spapr_phb_finish_realize(sPAPRPHBState *sphb, Error **errp)
/* Register default 32bit DMA window */
memory_region_add_subregion(&sphb->iommu_root, 0,
- spapr_tce_get_iommu(sphb->tcet));
+ spapr_tce_get_iommu(tcet));
+}
+
+static int spapr_phb_children_reset(Object *child, void *opaque)
+{
+ DeviceState *dev = (DeviceState *) object_dynamic_cast(child, TYPE_DEVICE);
+
+ if (dev) {
+ device_reset(dev);
+ }
+
+ return 0;
}
static void spapr_phb_reset(DeviceState *qdev)
{
- SysBusDevice *s = SYS_BUS_DEVICE(qdev);
- sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
-
/* Reset the IOMMU state */
- device_reset(DEVICE(sphb->tcet));
+ object_child_foreach(OBJECT(qdev), spapr_phb_children_reset, NULL);
}
static Property spapr_phb_properties[] = {
@@ -791,6 +801,29 @@ PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index)
#define b_fff(x) b_x((x), 8, 3) /* function number */
#define b_rrrrrrrr(x) b_x((x), 0, 8) /* register number */
+typedef struct sPAPRTCEDT {
+ void *fdt;
+ int node_off;
+} sPAPRTCEDT;
+
+static int spapr_phb_children_dt(Object *child, void *opaque)
+{
+ sPAPRTCEDT *p = opaque;
+ sPAPRTCETable *tcet;
+
+ tcet = (sPAPRTCETable *) object_dynamic_cast(child, TYPE_SPAPR_TCE_TABLE);
+ if (!tcet) {
+ return 0;
+ }
+
+ spapr_dma_dt(p->fdt, p->node_off, "ibm,dma-window",
+ tcet->liobn, 0,
+ tcet->window_size);
+ /* Stop after the first window */
+
+ return 1;
+}
+
int spapr_populate_pci_dt(sPAPRPHBState *phb,
uint32_t xics_phandle,
void *fdt)
@@ -870,9 +903,8 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
_FDT(fdt_setprop(fdt, bus_off, "interrupt-map", &interrupt_map,
sizeof(interrupt_map)));
- spapr_dma_dt(fdt, bus_off, "ibm,dma-window",
- phb->dma_liobn, phb->dma_window_start,
- phb->dma_window_size);
+ object_child_foreach(OBJECT(phb), spapr_phb_children_dt,
+ &((sPAPRTCEDT){ .fdt = fdt, .node_off = bus_off }));
return 0;
}
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index c98ebdf..5ea4745 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -62,7 +62,6 @@ typedef struct sPAPRPHBState {
uint32_t dma_liobn;
uint64_t dma_window_start;
uint64_t dma_window_size;
- sPAPRTCETable *tcet;
AddressSpace iommu_as;
MemoryRegion iommu_root;
--
1.9.rc0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH v2 6/9] spapr_iommu: Convert old qdev_init_nofail() to object_property_set_bool
2014-05-22 11:19 [Qemu-devel] [PATCH v2 0/9] spapr_pci: Prepare for VFIO Alexey Kardashevskiy
` (4 preceding siblings ...)
2014-05-22 11:19 ` [Qemu-devel] [PATCH v2 5/9] spapr_pci: Allow multiple TCE tables per PHB Alexey Kardashevskiy
@ 2014-05-22 11:19 ` Alexey Kardashevskiy
2014-05-22 11:19 ` [Qemu-devel] [PATCH v2 7/9] spapr_iommu: Get rid of window_size in sPAPRTCETable Alexey Kardashevskiy
` (2 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Alexey Kardashevskiy @ 2014-05-22 11:19 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Kardashevskiy, qemu-ppc, Alexander Graf
qdev_init_nofail() was replaced by object_property_set_bool("realized")
all over the QEMU so do we.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
hw/ppc/spapr_iommu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 241ceeb..0dd6509 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -163,7 +163,7 @@ sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn, size_t wi
object_property_add_child(OBJECT(owner), "tce-table", OBJECT(tcet), NULL);
- qdev_init_nofail(DEVICE(tcet));
+ object_property_set_bool(OBJECT(tcet), true, "realized", NULL);
return tcet;
}
--
1.9.rc0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH v2 7/9] spapr_iommu: Get rid of window_size in sPAPRTCETable
2014-05-22 11:19 [Qemu-devel] [PATCH v2 0/9] spapr_pci: Prepare for VFIO Alexey Kardashevskiy
` (5 preceding siblings ...)
2014-05-22 11:19 ` [Qemu-devel] [PATCH v2 6/9] spapr_iommu: Convert old qdev_init_nofail() to object_property_set_bool Alexey Kardashevskiy
@ 2014-05-22 11:19 ` Alexey Kardashevskiy
2014-05-22 11:19 ` [Qemu-devel] [PATCH v2 8/9] spapr_iommu: Introduce page_shift " Alexey Kardashevskiy
2014-05-22 11:19 ` [Qemu-devel] [PATCH v2 9/9] spapr_iommu: Introduce bus_offset " Alexey Kardashevskiy
8 siblings, 0 replies; 11+ messages in thread
From: Alexey Kardashevskiy @ 2014-05-22 11:19 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Kardashevskiy, qemu-ppc, Alexander Graf
This removes window_size as it is basically a copy of nb_table
shifted by SPAPR_TCE_PAGE_SHIFT. As new dynamic DMA windows are
going to support windows as big as the entire RAM and this number
will be bigger that 32 capacity, we will have to do something
about @window_size anyway and removal seems to be the right way to go.
This removes dma_window_start/dma_window_size from sPAPRPHBState as
they are no longer used.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
Changes:
v2:
* bumped minimum version in VMState descriptor
---
hw/ppc/spapr_iommu.c | 43 ++++++++++++++++---------------------------
hw/ppc/spapr_pci.c | 6 ++----
hw/ppc/spapr_vio.c | 4 +++-
include/hw/pci-host/spapr.h | 2 --
include/hw/ppc/spapr.h | 3 +--
target-ppc/kvm.c | 4 ++--
target-ppc/kvm_ppc.h | 2 +-
7 files changed, 25 insertions(+), 39 deletions(-)
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 0dd6509..99d1d6e 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -70,7 +70,7 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr)
if (tcet->bypass) {
ret.perm = IOMMU_RW;
- } else if (addr < tcet->window_size) {
+ } else if ((addr >> SPAPR_TCE_PAGE_SHIFT) < tcet->nb_table) {
/* Check if we are in bound */
tce = tcet->table[addr >> SPAPR_TCE_PAGE_SHIFT];
ret.iova = addr & ~SPAPR_TCE_PAGE_MASK;
@@ -84,25 +84,15 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr)
return ret;
}
-static int spapr_tce_table_pre_load(void *opaque)
-{
- sPAPRTCETable *tcet = SPAPR_TCE_TABLE(opaque);
-
- tcet->nb_table = tcet->window_size >> SPAPR_TCE_PAGE_SHIFT;
-
- return 0;
-}
-
static const VMStateDescription vmstate_spapr_tce_table = {
.name = "spapr_iommu",
- .version_id = 1,
- .minimum_version_id = 1,
+ .version_id = 2,
+ .minimum_version_id = 2,
.minimum_version_id_old = 1,
- .pre_load = spapr_tce_table_pre_load,
.fields = (VMStateField []) {
/* Sanity check */
VMSTATE_UINT32_EQUAL(liobn, sPAPRTCETable),
- VMSTATE_UINT32_EQUAL(window_size, sPAPRTCETable),
+ VMSTATE_UINT32_EQUAL(nb_table, sPAPRTCETable),
/* IOMMU state */
VMSTATE_BOOL(bypass, sPAPRTCETable),
@@ -122,16 +112,15 @@ static int spapr_tce_table_realize(DeviceState *dev)
if (kvm_enabled()) {
tcet->table = kvmppc_create_spapr_tce(tcet->liobn,
- tcet->window_size,
+ tcet->nb_table <<
+ SPAPR_TCE_PAGE_SHIFT,
&tcet->fd);
}
if (!tcet->table) {
- size_t table_size = (tcet->window_size >> SPAPR_TCE_PAGE_SHIFT)
- * sizeof(uint64_t);
+ size_t table_size = tcet->nb_table * sizeof(uint64_t);
tcet->table = g_malloc0(table_size);
}
- tcet->nb_table = tcet->window_size >> SPAPR_TCE_PAGE_SHIFT;
trace_spapr_iommu_new_table(tcet->liobn, tcet, tcet->table, tcet->fd);
@@ -143,7 +132,8 @@ static int spapr_tce_table_realize(DeviceState *dev)
return 0;
}
-sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn, size_t window_size)
+sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
+ uint32_t nb_table)
{
sPAPRTCETable *tcet;
@@ -153,13 +143,13 @@ sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn, size_t wi
return NULL;
}
- if (!window_size) {
+ if (!nb_table) {
return NULL;
}
tcet = SPAPR_TCE_TABLE(object_new(TYPE_SPAPR_TCE_TABLE));
tcet->liobn = liobn;
- tcet->window_size = window_size;
+ tcet->nb_table = nb_table;
object_property_add_child(OBJECT(owner), "tce-table", OBJECT(tcet), NULL);
@@ -176,7 +166,7 @@ static void spapr_tce_table_finalize(Object *obj)
if (!kvm_enabled() ||
(kvmppc_remove_spapr_tce(tcet->table, tcet->fd,
- tcet->window_size) != 0)) {
+ tcet->nb_table) != 0)) {
g_free(tcet->table);
}
}
@@ -194,8 +184,7 @@ void spapr_tce_set_bypass(sPAPRTCETable *tcet, bool bypass)
static void spapr_tce_reset(DeviceState *dev)
{
sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
- size_t table_size = (tcet->window_size >> SPAPR_TCE_PAGE_SHIFT)
- * sizeof(uint64_t);
+ size_t table_size = tcet->nb_table * sizeof(uint64_t);
tcet->bypass = false;
memset(tcet->table, 0, table_size);
@@ -206,7 +195,7 @@ static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
{
IOMMUTLBEntry entry;
- if (ioba >= tcet->window_size) {
+ if ((ioba >> SPAPR_TCE_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;
@@ -322,7 +311,7 @@ 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 >= tcet->window_size) {
+ if ((ioba >> SPAPR_TCE_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;
@@ -393,7 +382,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->window_size);
+ tcet->liobn, 0, tcet->nb_table << SPAPR_TCE_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 aa29116..fdd4c07 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -655,10 +655,8 @@ static void spapr_phb_finish_realize(sPAPRPHBState *sphb, Error **errp)
{
sPAPRTCETable *tcet;
- sphb->dma_window_start = 0;
- sphb->dma_window_size = 0x40000000;
tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn,
- sphb->dma_window_size);
+ 0x40000000 >> SPAPR_TCE_PAGE_SHIFT);
if (!tcet) {
error_setg(errp, "Unable to create TCE table for %s",
sphb->dtbusname);
@@ -818,7 +816,7 @@ static int spapr_phb_children_dt(Object *child, void *opaque)
spapr_dma_dt(p->fdt, p->node_off, "ibm,dma-window",
tcet->liobn, 0,
- tcet->window_size);
+ tcet->nb_table << SPAPR_TCE_PAGE_SHIFT);
/* Stop after the first window */
return 1;
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index 2ae06a3..b84e481 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -456,7 +456,9 @@ 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, pc->rtce_window_size);
+ dev->tcet = spapr_tce_new_table(qdev, liobn,
+ pc->rtce_window_size >>
+ SPAPR_TCE_PAGE_SHIFT);
address_space_init(&dev->as, spapr_tce_get_iommu(dev->tcet), qdev->id);
}
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index 5ea4745..07ba7cf 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -60,8 +60,6 @@ typedef struct sPAPRPHBState {
MemoryRegion memwindow, iowindow;
uint32_t dma_liobn;
- uint64_t dma_window_start;
- uint64_t dma_window_size;
AddressSpace iommu_as;
MemoryRegion iommu_root;
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 9f8bb89..5f7791d 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -391,7 +391,6 @@ typedef struct sPAPRTCETable sPAPRTCETable;
struct sPAPRTCETable {
DeviceState parent;
uint32_t liobn;
- uint32_t window_size;
uint32_t nb_table;
uint64_t *table;
bool bypass;
@@ -403,7 +402,7 @@ struct sPAPRTCETable {
void spapr_events_init(sPAPREnvironment *spapr);
void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq);
sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
- size_t window_size);
+ uint32_t nb_table);
MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet);
void spapr_tce_set_bypass(sPAPRTCETable *tcet, bool bypass);
int spapr_dma_dt(void *fdt, int node_off, const char *propname,
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index bcf2db8..2fab09f 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -1655,7 +1655,7 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd)
return table;
}
-int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t window_size)
+int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t nb_table)
{
long len;
@@ -1663,7 +1663,7 @@ int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t window_size)
return -1;
}
- len = (window_size / SPAPR_TCE_PAGE_SIZE)*sizeof(uint64_t);
+ len = nb_table * sizeof(uint64_t);
if ((munmap(table, len) < 0) ||
(close(fd) < 0)) {
fprintf(stderr, "KVM: Unexpected error removing TCE table: %s",
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index b90d31b..f1255af 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -143,7 +143,7 @@ static inline void *kvmppc_create_spapr_tce(uint32_t liobn,
}
static inline int kvmppc_remove_spapr_tce(void *table, int pfd,
- uint32_t window_size)
+ uint32_t nb_table)
{
return -1;
}
--
1.9.rc0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH v2 8/9] spapr_iommu: Introduce page_shift in sPAPRTCETable
2014-05-22 11:19 [Qemu-devel] [PATCH v2 0/9] spapr_pci: Prepare for VFIO Alexey Kardashevskiy
` (6 preceding siblings ...)
2014-05-22 11:19 ` [Qemu-devel] [PATCH v2 7/9] spapr_iommu: Get rid of window_size in sPAPRTCETable Alexey Kardashevskiy
@ 2014-05-22 11:19 ` Alexey Kardashevskiy
2014-05-23 13:39 ` Alexander Graf
2014-05-22 11:19 ` [Qemu-devel] [PATCH v2 9/9] spapr_iommu: Introduce bus_offset " Alexey Kardashevskiy
8 siblings, 1 reply; 11+ messages in thread
From: Alexey Kardashevskiy @ 2014-05-22 11:19 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Kardashevskiy, qemu-ppc, Alexander Graf
At the moment only 4K pages are supported by sPAPRTCETable. Since sPAPR
spec allows other page sizes and we are going to implement them, we need
page size to be configrable.
This adds @page_shift into sPAPRTCETable and replaces SPAPR_TCE_PAGE_SHIFT
with it whereever it is possible.
This removes SPAPR_TCE_PAGE_MASK as it is no longer used.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
Changes:
v2:
* target_ulong for "mask" replaced with hwaddr
* added page_mask and page_size local variables where possible
---
hw/ppc/spapr_iommu.c | 66 +++++++++++++++++++++++++++++++-------------------
hw/ppc/spapr_pci.c | 1 +
hw/ppc/spapr_vio.c | 1 +
include/hw/ppc/spapr.h | 3 ++-
4 files changed, 45 insertions(+), 26 deletions(-)
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 99d1d6e..65f9a89 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -70,12 +70,14 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr)
if (tcet->bypass) {
ret.perm = IOMMU_RW;
- } else if ((addr >> SPAPR_TCE_PAGE_SHIFT) < tcet->nb_table) {
+ } else if ((addr >> tcet->page_shift) < tcet->nb_table) {
/* Check if we are in bound */
- tce = tcet->table[addr >> SPAPR_TCE_PAGE_SHIFT];
- ret.iova = addr & ~SPAPR_TCE_PAGE_MASK;
- ret.translated_addr = tce & ~SPAPR_TCE_PAGE_MASK;
- ret.addr_mask = SPAPR_TCE_PAGE_MASK;
+ hwaddr page_mask = ~((1 << tcet->page_shift) - 1);
+
+ tce = tcet->table[addr >> tcet->page_shift];
+ ret.iova = addr & page_mask;
+ ret.translated_addr = tce & page_mask;
+ ret.addr_mask = ~page_mask;
ret.perm = tce;
}
trace_spapr_iommu_xlate(tcet->liobn, addr, ret.iova, ret.perm,
@@ -113,7 +115,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 +135,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 +152,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 +198,20 @@ static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
target_ulong tce)
{
IOMMUTLBEntry entry;
+ hwaddr page_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 & page_mask;
+ entry.translated_addr = tce & page_mask;
+ entry.addr_mask = ~page_mask;
entry.perm = tce;
memory_region_notify_iommu(&tcet->iommu, entry);
@@ -226,6 +231,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);
+ hwaddr page_mask, page_size;
if (!tcet) {
return H_PARAMETER;
@@ -235,12 +241,15 @@ static target_ulong h_put_tce_indirect(PowerPCCPU *cpu,
return H_PARAMETER;
}
- ioba &= ~SPAPR_TCE_PAGE_MASK;
- tce_list &= ~SPAPR_TCE_PAGE_MASK;
+ page_mask = ~((1 << tcet->page_shift) - 1);
+ page_size = (1 << tcet->page_shift);
+ ioba &= page_mask;
+
+ for (i = 0; i < npages; ++i, ioba += page_size) {
+ 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;
@@ -267,6 +276,7 @@ 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);
+ hwaddr page_mask, page_size;
if (!tcet) {
return H_PARAMETER;
@@ -276,9 +286,11 @@ static target_ulong h_stuff_tce(PowerPCCPU *cpu, sPAPREnvironment *spapr,
return H_PARAMETER;
}
- ioba &= ~SPAPR_TCE_PAGE_MASK;
+ page_mask = ~((1 << tcet->page_shift) - 1);
+ page_size = (1 << tcet->page_shift);
+ ioba &= page_mask;
- for (i = 0; i < npages; ++i, ioba += SPAPR_TCE_PAGE_SIZE) {
+ for (i = 0; i < npages; ++i, ioba += page_size) {
ret = put_tce_emu(tcet, ioba, tce_value);
if (ret) {
break;
@@ -297,10 +309,12 @@ 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);
-
- ioba &= ~(SPAPR_TCE_PAGE_SIZE - 1);
+ hwaddr page_mask;
if (tcet) {
+ page_mask = ~((1 << tcet->page_shift) - 1);
+ ioba &= page_mask;
+
ret = put_tce_emu(tcet, ioba, tce);
}
trace_spapr_iommu_put(liobn, ioba, tce, ret);
@@ -311,13 +325,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,10 +344,12 @@ 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);
-
- ioba &= ~(SPAPR_TCE_PAGE_SIZE - 1);
+ hwaddr page_mask;
if (tcet) {
+ page_mask = ~((1 << tcet->page_shift) - 1);
+ ioba &= page_mask;
+
ret = get_tce_emu(tcet, ioba, &tce);
if (!ret) {
args[0] = tce;
@@ -382,7 +398,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,
pc->rtce_window_size >>
SPAPR_TCE_PAGE_SHIFT);
address_space_init(&dev->as, spapr_tce_get_iommu(dev->tcet), qdev->id);
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 5f7791d..2e88e52 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -375,7 +375,6 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
#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)
#define SPAPR_VIO_BASE_LIOBN 0x00000000
#define SPAPR_PCI_BASE_LIOBN 0x80000000
@@ -392,6 +391,7 @@ struct sPAPRTCETable {
DeviceState parent;
uint32_t liobn;
uint32_t nb_table;
+ uint32_t page_shift;
uint64_t *table;
bool bypass;
int fd;
@@ -402,6 +402,7 @@ struct sPAPRTCETable {
void spapr_events_init(sPAPREnvironment *spapr);
void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq);
sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
+ uint32_t page_shift,
uint32_t nb_table);
MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet);
void spapr_tce_set_bypass(sPAPRTCETable *tcet, bool bypass);
--
1.9.rc0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [Qemu-devel] [PATCH v2 8/9] spapr_iommu: Introduce page_shift in sPAPRTCETable
2014-05-22 11:19 ` [Qemu-devel] [PATCH v2 8/9] spapr_iommu: Introduce page_shift " Alexey Kardashevskiy
@ 2014-05-23 13:39 ` Alexander Graf
0 siblings, 0 replies; 11+ messages in thread
From: Alexander Graf @ 2014-05-23 13:39 UTC (permalink / raw)
To: Alexey Kardashevskiy, qemu-devel; +Cc: qemu-ppc
On 22.05.14 13:19, Alexey Kardashevskiy wrote:
> At the moment only 4K pages are supported by sPAPRTCETable. Since sPAPR
> spec allows other page sizes and we are going to implement them, we need
> page size to be configrable.
>
> This adds @page_shift into sPAPRTCETable and replaces SPAPR_TCE_PAGE_SHIFT
> with it whereever it is possible.
>
> This removes SPAPR_TCE_PAGE_MASK as it is no longer used.
>
> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
> ---
> Changes:
> v2:
> * target_ulong for "mask" replaced with hwaddr
> * added page_mask and page_size local variables where possible
> ---
> hw/ppc/spapr_iommu.c | 66 +++++++++++++++++++++++++++++++-------------------
> hw/ppc/spapr_pci.c | 1 +
> hw/ppc/spapr_vio.c | 1 +
> include/hw/ppc/spapr.h | 3 ++-
> 4 files changed, 45 insertions(+), 26 deletions(-)
>
> diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
> index 99d1d6e..65f9a89 100644
> --- a/hw/ppc/spapr_iommu.c
> +++ b/hw/ppc/spapr_iommu.c
> @@ -70,12 +70,14 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr)
>
> if (tcet->bypass) {
> ret.perm = IOMMU_RW;
> - } else if ((addr >> SPAPR_TCE_PAGE_SHIFT) < tcet->nb_table) {
> + } else if ((addr >> tcet->page_shift) < tcet->nb_table) {
> /* Check if we are in bound */
> - tce = tcet->table[addr >> SPAPR_TCE_PAGE_SHIFT];
> - ret.iova = addr & ~SPAPR_TCE_PAGE_MASK;
> - ret.translated_addr = tce & ~SPAPR_TCE_PAGE_MASK;
> - ret.addr_mask = SPAPR_TCE_PAGE_MASK;
> + hwaddr page_mask = ~((1 << tcet->page_shift) - 1);
1ULL
> +
> + tce = tcet->table[addr >> tcet->page_shift];
> + ret.iova = addr & page_mask;
> + ret.translated_addr = tce & page_mask;
> + ret.addr_mask = ~page_mask;
> ret.perm = tce;
> }
> trace_spapr_iommu_xlate(tcet->liobn, addr, ret.iova, ret.perm,
> @@ -113,7 +115,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 +135,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 +152,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 +198,20 @@ static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
> target_ulong tce)
> {
> IOMMUTLBEntry entry;
> + hwaddr page_mask = ~((1 << tcet->page_shift) - 1);
...
Alex
^ permalink raw reply [flat|nested] 11+ messages in thread
* [Qemu-devel] [PATCH v2 9/9] spapr_iommu: Introduce bus_offset in sPAPRTCETable
2014-05-22 11:19 [Qemu-devel] [PATCH v2 0/9] spapr_pci: Prepare for VFIO Alexey Kardashevskiy
` (7 preceding siblings ...)
2014-05-22 11:19 ` [Qemu-devel] [PATCH v2 8/9] spapr_iommu: Introduce page_shift " Alexey Kardashevskiy
@ 2014-05-22 11:19 ` Alexey Kardashevskiy
8 siblings, 0 replies; 11+ messages in thread
From: Alexey Kardashevskiy @ 2014-05-22 11:19 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Kardashevskiy, qemu-ppc, Alexander Graf
This adds @bus_offset into sPAPRTCETable to tell where TCE table starts
from. It is set to 0 for emulated devices. Dynamic DMA windows will use
other offset.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
hw/ppc/spapr_iommu.c | 13 +++++++++----
hw/ppc/spapr_pci.c | 5 +++--
hw/ppc/spapr_vio.c | 1 +
include/hw/ppc/spapr.h | 2 ++
4 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 65f9a89..1c69cf7 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -135,6 +135,7 @@ static int spapr_tce_table_realize(DeviceState *dev)
}
sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
+ uint64_t bus_offset,
uint32_t page_shift,
uint32_t nb_table)
{
@@ -152,6 +153,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->bus_offset = bus_offset;
tcet->page_shift = page_shift;
tcet->nb_table = nb_table;
@@ -199,14 +201,15 @@ static target_ulong put_tce_emu(sPAPRTCETable *tcet, target_ulong ioba,
{
IOMMUTLBEntry entry;
hwaddr page_mask = ~((1 << tcet->page_shift) - 1);
+ unsigned long index = (ioba - tcet->bus_offset) >> tcet->page_shift;
- if ((ioba >> tcet->page_shift) >= tcet->nb_table) {
+ if (index >= 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 >> tcet->page_shift] = tce;
+ tcet->table[index] = tce;
entry.target_as = &address_space_memory,
entry.iova = ioba & page_mask;
@@ -325,13 +328,15 @@ 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 >> tcet->page_shift) >= tcet->nb_table) {
+ unsigned long index = (ioba - tcet->bus_offset) >> tcet->page_shift;
+
+ if (index >= 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 >> tcet->page_shift];
+ *tce = tcet->table[index];
return H_SUCCESS;
}
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index c9850d4..ddfd8bb 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,
+ 0,
SPAPR_TCE_PAGE_SHIFT,
0x40000000 >> SPAPR_TCE_PAGE_SHIFT);
if (!tcet) {
@@ -816,8 +817,8 @@ static int spapr_phb_children_dt(Object *child, void *opaque)
}
spapr_dma_dt(p->fdt, p->node_off, "ibm,dma-window",
- tcet->liobn, 0,
- tcet->nb_table << SPAPR_TCE_PAGE_SHIFT);
+ tcet->liobn, tcet->bus_offset,
+ tcet->nb_table << tcet->page_shift);
/* Stop after the first window */
return 1;
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index d7e9e6a..48b0125 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,
+ 0,
SPAPR_TCE_PAGE_SHIFT,
pc->rtce_window_size >>
SPAPR_TCE_PAGE_SHIFT);
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 2e88e52..c848c50 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -391,6 +391,7 @@ struct sPAPRTCETable {
DeviceState parent;
uint32_t liobn;
uint32_t nb_table;
+ uint64_t bus_offset;
uint32_t page_shift;
uint64_t *table;
bool bypass;
@@ -402,6 +403,7 @@ struct sPAPRTCETable {
void spapr_events_init(sPAPREnvironment *spapr);
void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq);
sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
+ uint64_t bus_offset,
uint32_t page_shift,
uint32_t nb_table);
MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet);
--
1.9.rc0
^ permalink raw reply related [flat|nested] 11+ messages in thread