From nobody Thu May 2 01:34:02 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1490878296305141.95366892081927; Thu, 30 Mar 2017 05:51:36 -0700 (PDT) Received: from localhost ([::1]:35464 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ctZY6-0003e2-Vd for importer@patchew.org; Thu, 30 Mar 2017 08:51:35 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50849) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ctZUT-0000m8-2F for qemu-devel@nongnu.org; Thu, 30 Mar 2017 08:47:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ctZUP-0006AE-7l for qemu-devel@nongnu.org; Thu, 30 Mar 2017 08:47:49 -0400 Received: from ozlabs.ru ([107.173.13.209]:57790) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ctZUO-00069O-PE; Thu, 30 Mar 2017 08:47:45 -0400 Received: from vpl2.ozlabs.ibm.com (localhost [IPv6:::1]) by ozlabs.ru (Postfix) with ESMTP id 275813A60181; Thu, 30 Mar 2017 08:47:18 -0400 (EDT) From: Alexey Kardashevskiy To: qemu-devel@nongnu.org Date: Thu, 30 Mar 2017 23:47:03 +1100 Message-Id: <20170330124707.28142-2-aik@ozlabs.ru> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170330124707.28142-1-aik@ozlabs.ru> References: <20170330124707.28142-1-aik@ozlabs.ru> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 107.173.13.209 Subject: [Qemu-devel] [RFC PATCH qemu 1/5] memory/iommu: QOM'fy IOMMU MemoryRegion X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alexey Kardashevskiy , Paolo Bonzini , Alex Williamson , qemu-ppc@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Alexey Kardashevskiy --- include/exec/memory.h | 50 ++++++++++++++++---- include/hw/ppc/spapr.h | 3 +- include/hw/vfio/vfio-common.h | 2 +- include/qemu/typedefs.h | 1 + exec.c | 16 +++++-- hw/ppc/spapr_iommu.c | 20 ++++---- hw/vfio/common.c | 12 +++-- hw/vfio/spapr.c | 3 +- memory.c | 106 ++++++++++++++++++++++++++++----------= ---- 9 files changed, 148 insertions(+), 65 deletions(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index e39256ad03..479d8fbfe2 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -37,6 +37,10 @@ #define MEMORY_REGION(obj) \ OBJECT_CHECK(MemoryRegion, (obj), TYPE_MEMORY_REGION) =20 +#define TYPE_IOMMU_MEMORY_REGION "qemu:iommu-memory-region" +#define IOMMU_MEMORY_REGION(obj) \ + OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_IOMMU_MEMORY_REGION) + typedef struct MemoryRegionOps MemoryRegionOps; typedef struct MemoryRegionMmio MemoryRegionMmio; =20 @@ -167,11 +171,12 @@ typedef struct MemoryRegionIOMMUOps MemoryRegionIOMMU= Ops; =20 struct MemoryRegionIOMMUOps { /* Return a TLB entry that contains a given address. */ - IOMMUTLBEntry (*translate)(MemoryRegion *iommu, hwaddr addr, bool is_w= rite); + IOMMUTLBEntry (*translate)(IOMMUMemoryRegion *iommu, hwaddr addr, + bool is_write); /* Returns minimum supported page size */ - uint64_t (*get_min_page_size)(MemoryRegion *iommu); + uint64_t (*get_min_page_size)(IOMMUMemoryRegion *iommu); /* Called when IOMMU Notifier flag changed */ - void (*notify_flag_changed)(MemoryRegion *iommu, + void (*notify_flag_changed)(IOMMUMemoryRegion *iommu, IOMMUNotifierFlag old_flags, IOMMUNotifierFlag new_flags); }; @@ -195,7 +200,6 @@ struct MemoryRegion { uint8_t dirty_log_mask; RAMBlock *ram_block; Object *owner; - const MemoryRegionIOMMUOps *iommu_ops; =20 const MemoryRegionOps *ops; void *opaque; @@ -218,6 +222,12 @@ struct MemoryRegion { const char *name; unsigned ioeventfd_nb; MemoryRegionIoeventfd *ioeventfds; +}; + +struct IOMMUMemoryRegion { + MemoryRegion parent_obj; + + const MemoryRegionIOMMUOps *iommu_ops; QLIST_HEAD(, IOMMUNotifier) iommu_notify; IOMMUNotifierFlag iommu_notify_flags; }; @@ -555,19 +565,39 @@ static inline void memory_region_init_reservation(Mem= oryRegion *mr, } =20 /** + * memory_region_init_iommu_type: Initialize a memory region of a custom t= ype + * that translates addresses + * + * An IOMMU region translates addresses and forwards accesses to a target + * memory region. + * + * @typename: QOM class name + * @mr: the #IOMMUMemoryRegion to be initialized + * @owner: the object that tracks the region's reference count + * @ops: a function that translates addresses into the @target region + * @name: used for debugging; not visible to the user or ABI + * @size: size of the region. + */ +void memory_region_init_iommu_type(const char *mrtypename, + IOMMUMemoryRegion *iommumr, + Object *owner, + const MemoryRegionIOMMUOps *ops, + const char *name, + uint64_t size); +/** * memory_region_init_iommu: Initialize a memory region that translates * addresses * * An IOMMU region translates addresses and forwards accesses to a target * memory region. * - * @mr: the #MemoryRegion to be initialized + * @mr: the #IOMMUMemoryRegion to be initialized * @owner: the object that tracks the region's reference count * @ops: a function that translates addresses into the @target region * @name: used for debugging; not visible to the user or ABI * @size: size of the region. */ -void memory_region_init_iommu(MemoryRegion *mr, +void memory_region_init_iommu(IOMMUMemoryRegion *iommumr, struct Object *owner, const MemoryRegionIOMMUOps *ops, const char *name, @@ -633,7 +663,7 @@ static inline bool memory_region_is_iommu(MemoryRegion = *mr) if (mr->alias) { return memory_region_is_iommu(mr->alias); } - return mr->iommu_ops; + return object_dynamic_cast(OBJECT(mr), TYPE_IOMMU_MEMORY_REGION) !=3D = NULL; } =20 =20 @@ -645,7 +675,7 @@ static inline bool memory_region_is_iommu(MemoryRegion = *mr) * * @mr: the memory region being queried */ -uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr); +uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *mr); =20 /** * memory_region_notify_iommu: notify a change in an IOMMU translation ent= ry. @@ -664,7 +694,7 @@ uint64_t memory_region_iommu_get_min_page_size(MemoryRe= gion *mr); * replaces all old entries for the same virtual I/O address range. * Deleted entries have .@perm =3D=3D 0. */ -void memory_region_notify_iommu(MemoryRegion *mr, +void memory_region_notify_iommu(IOMMUMemoryRegion *mr, IOMMUTLBEntry entry); =20 /** @@ -689,7 +719,7 @@ void memory_region_register_iommu_notifier(MemoryRegion= *mr, * @is_write: Whether to treat the replay as a translate "write" * through the iommu */ -void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n, +void memory_region_iommu_replay(IOMMUMemoryRegion *mr, IOMMUNotifier *n, bool is_write); =20 /** diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index e27de64d31..6997ed7e98 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -590,7 +590,8 @@ struct sPAPRTCETable { bool bypass; bool need_vfio; int fd; - MemoryRegion root, iommu; + MemoryRegion root; + IOMMUMemoryRegion iommu; struct VIOsPAPRDevice *vdev; /* for @bypass migration compatibility on= ly */ QLIST_ENTRY(sPAPRTCETable) list; }; diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index c582de18c9..7a4135ae6f 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -94,7 +94,7 @@ typedef struct VFIOContainer { =20 typedef struct VFIOGuestIOMMU { VFIOContainer *container; - MemoryRegion *iommu; + IOMMUMemoryRegion *iommu; hwaddr iommu_offset; IOMMUNotifier n; QLIST_ENTRY(VFIOGuestIOMMU) giommu_next; diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index e95f28cfec..b45f71ec11 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -45,6 +45,7 @@ typedef struct MachineState MachineState; typedef struct MemoryListener MemoryListener; typedef struct MemoryMappingList MemoryMappingList; typedef struct MemoryRegion MemoryRegion; +typedef struct IOMMUMemoryRegion IOMMUMemoryRegion; typedef struct MemoryRegionCache MemoryRegionCache; typedef struct MemoryRegionSection MemoryRegionSection; typedef struct MigrationIncomingState MigrationIncomingState; diff --git a/exec.c b/exec.c index e57a8a2178..3b47dad1f8 100644 --- a/exec.c +++ b/exec.c @@ -463,6 +463,7 @@ IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpac= e *as, hwaddr addr, IOMMUTLBEntry iotlb =3D {0}; MemoryRegionSection *section; MemoryRegion *mr; + IOMMUMemoryRegion *iommumr; =20 for (;;) { AddressSpaceDispatch *d =3D atomic_rcu_read(&as->dispatch); @@ -471,11 +472,13 @@ IOMMUTLBEntry address_space_get_iotlb_entry(AddressSp= ace *as, hwaddr addr, + section->offset_within_region; mr =3D section->mr; =20 - if (!mr->iommu_ops) { + if (!memory_region_is_iommu(mr)) { break; } =20 - iotlb =3D mr->iommu_ops->translate(mr, addr, is_write); + iommumr =3D IOMMU_MEMORY_REGION(mr); + + iotlb =3D iommumr->iommu_ops->translate(iommumr, addr, is_write); if (!(iotlb.perm & (1 << is_write))) { iotlb.target_as =3D NULL; break; @@ -497,17 +500,20 @@ MemoryRegion *address_space_translate(AddressSpace *a= s, hwaddr addr, IOMMUTLBEntry iotlb; MemoryRegionSection *section; MemoryRegion *mr; + IOMMUMemoryRegion *iommumr; =20 for (;;) { AddressSpaceDispatch *d =3D atomic_rcu_read(&as->dispatch); section =3D address_space_translate_internal(d, addr, &addr, plen,= true); mr =3D section->mr; =20 - if (!mr->iommu_ops) { + if (!memory_region_is_iommu(mr)) { break; } =20 - iotlb =3D mr->iommu_ops->translate(mr, addr, is_write); + iommumr =3D IOMMU_MEMORY_REGION(mr); + + iotlb =3D iommumr->iommu_ops->translate(iommumr, addr, is_write); addr =3D ((iotlb.translated_addr & ~iotlb.addr_mask) | (addr & iotlb.addr_mask)); *plen =3D MIN(*plen, (addr | iotlb.addr_mask) - addr + 1); @@ -538,7 +544,7 @@ address_space_translate_for_iotlb(CPUState *cpu, int as= idx, hwaddr addr, =20 section =3D address_space_translate_internal(d, addr, xlat, plen, fals= e); =20 - assert(!section->mr->iommu_ops); + assert(!memory_region_is_iommu(section->mr)); return section; } #endif diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c index 9e30e148d6..5051110b9d 100644 --- a/hw/ppc/spapr_iommu.c +++ b/hw/ppc/spapr_iommu.c @@ -110,7 +110,8 @@ static void spapr_tce_free_table(uint64_t *table, int f= d, uint32_t nb_table) } =20 /* Called from RCU critical section */ -static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr= addr, +static IOMMUTLBEntry spapr_tce_translate_iommu(IOMMUMemoryRegion *iommu, + hwaddr addr, bool is_write) { sPAPRTCETable *tcet =3D container_of(iommu, sPAPRTCETable, iommu); @@ -150,14 +151,14 @@ static void spapr_tce_table_pre_save(void *opaque) tcet->bus_offset, tcet->page_shift); } =20 -static uint64_t spapr_tce_get_min_page_size(MemoryRegion *iommu) +static uint64_t spapr_tce_get_min_page_size(IOMMUMemoryRegion *iommu) { sPAPRTCETable *tcet =3D container_of(iommu, sPAPRTCETable, iommu); =20 return 1ULL << tcet->page_shift; } =20 -static void spapr_tce_notify_flag_changed(MemoryRegion *iommu, +static void spapr_tce_notify_flag_changed(IOMMUMemoryRegion *iommu, IOMMUNotifierFlag old, IOMMUNotifierFlag new) { @@ -265,7 +266,9 @@ static int spapr_tce_table_realize(DeviceState *dev) memory_region_init(&tcet->root, tcetobj, tmp, UINT64_MAX); =20 snprintf(tmp, sizeof(tmp), "tce-iommu-%x", tcet->liobn); - memory_region_init_iommu(&tcet->iommu, tcetobj, &spapr_iommu_ops, tmp,= 0); + memory_region_init_iommu_type(TYPE_IOMMU_MEMORY_REGION, + &tcet->iommu, tcetobj, &spapr_iommu_ops, + tmp, 0); =20 QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list); =20 @@ -341,9 +344,10 @@ void spapr_tce_table_enable(sPAPRTCETable *tcet, &tcet->fd, tcet->need_vfio); =20 - memory_region_set_size(&tcet->iommu, + memory_region_set_size(MEMORY_REGION(&tcet->iommu), (uint64_t)tcet->nb_table << tcet->page_shift); - memory_region_add_subregion(&tcet->root, tcet->bus_offset, &tcet->iomm= u); + memory_region_add_subregion(&tcet->root, tcet->bus_offset, + MEMORY_REGION(&tcet->iommu)); } =20 void spapr_tce_table_disable(sPAPRTCETable *tcet) @@ -352,8 +356,8 @@ void spapr_tce_table_disable(sPAPRTCETable *tcet) return; } =20 - memory_region_del_subregion(&tcet->root, &tcet->iommu); - memory_region_set_size(&tcet->iommu, 0); + memory_region_del_subregion(&tcet->root, MEMORY_REGION(&tcet->iommu)); + memory_region_set_size(MEMORY_REGION(&tcet->iommu), 0); =20 spapr_tce_free_table(tcet->table, tcet->fd, tcet->nb_table); tcet->fd =3D -1; diff --git a/hw/vfio/common.c b/hw/vfio/common.c index f3ba9b9007..ab95db689c 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -465,6 +465,7 @@ static void vfio_listener_region_add(MemoryListener *li= stener, =20 if (memory_region_is_iommu(section->mr)) { VFIOGuestIOMMU *giommu; + IOMMUMemoryRegion *iommumr =3D IOMMU_MEMORY_REGION(section->mr); =20 trace_vfio_listener_region_add_iommu(iova, end); /* @@ -474,7 +475,7 @@ static void vfio_listener_region_add(MemoryListener *li= stener, * device emulation the VFIO iommu handles to use). */ giommu =3D g_malloc0(sizeof(*giommu)); - giommu->iommu =3D section->mr; + giommu->iommu =3D iommumr; giommu->iommu_offset =3D section->offset_within_address_space - section->offset_within_region; giommu->container =3D container; @@ -482,7 +483,7 @@ static void vfio_listener_region_add(MemoryListener *li= stener, giommu->n.notifier_flags =3D IOMMU_NOTIFIER_ALL; QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next); =20 - memory_region_register_iommu_notifier(giommu->iommu, &giommu->n); + memory_region_register_iommu_notifier(section->mr, &giommu->n); memory_region_iommu_replay(giommu->iommu, &giommu->n, false); =20 return; @@ -550,8 +551,8 @@ static void vfio_listener_region_del(MemoryListener *li= stener, VFIOGuestIOMMU *giommu; =20 QLIST_FOREACH(giommu, &container->giommu_list, giommu_next) { - if (giommu->iommu =3D=3D section->mr) { - memory_region_unregister_iommu_notifier(giommu->iommu, + if (MEMORY_REGION(giommu->iommu) =3D=3D section->mr) { + memory_region_unregister_iommu_notifier(section->mr, &giommu->n); QLIST_REMOVE(giommu, giommu_next); g_free(giommu); @@ -1141,7 +1142,8 @@ static void vfio_disconnect_container(VFIOGroup *grou= p) QLIST_REMOVE(container, next); =20 QLIST_FOREACH_SAFE(giommu, &container->giommu_list, giommu_next, t= mp) { - memory_region_unregister_iommu_notifier(giommu->iommu, &giommu= ->n); + memory_region_unregister_iommu_notifier( + MEMORY_REGION(giommu->iommu), &giommu->n); QLIST_REMOVE(giommu, giommu_next); g_free(giommu); } diff --git a/hw/vfio/spapr.c b/hw/vfio/spapr.c index 4409bcc0d7..551870d46b 100644 --- a/hw/vfio/spapr.c +++ b/hw/vfio/spapr.c @@ -143,7 +143,8 @@ int vfio_spapr_create_window(VFIOContainer *container, hwaddr *pgsize) { int ret; - unsigned pagesize =3D memory_region_iommu_get_min_page_size(section->m= r); + IOMMUMemoryRegion *iommumr =3D IOMMU_MEMORY_REGION(section->mr); + unsigned pagesize =3D memory_region_iommu_get_min_page_size(iommumr); unsigned entries, pages; struct vfio_iommu_spapr_tce_create create =3D { .argsz =3D sizeof(crea= te) }; =20 diff --git a/memory.c b/memory.c index 4c95aaf39c..036abd78dc 100644 --- a/memory.c +++ b/memory.c @@ -975,12 +975,11 @@ static char *memory_region_escape_name(const char *na= me) return escaped; } =20 -void memory_region_init(MemoryRegion *mr, - Object *owner, - const char *name, - uint64_t size) +static void memory_region_do_init(MemoryRegion *mr, + Object *owner, + const char *name, + uint64_t size) { - object_initialize(mr, sizeof(*mr), TYPE_MEMORY_REGION); mr->size =3D int128_make64(size); if (size =3D=3D UINT64_MAX) { mr->size =3D int128_2_64(); @@ -1004,6 +1003,15 @@ void memory_region_init(MemoryRegion *mr, } } =20 +void memory_region_init(MemoryRegion *mr, + Object *owner, + const char *name, + uint64_t size) +{ + object_initialize(mr, sizeof(*mr), TYPE_MEMORY_REGION); + memory_region_do_init(mr, owner, name, size); +} + static void memory_region_get_addr(Object *obj, Visitor *v, const char *na= me, void *opaque, Error **errp) { @@ -1473,17 +1481,33 @@ void memory_region_init_rom_device(MemoryRegion *mr, mr->ram_block =3D qemu_ram_alloc(size, mr, errp); } =20 -void memory_region_init_iommu(MemoryRegion *mr, - Object *owner, - const MemoryRegionIOMMUOps *ops, - const char *name, - uint64_t size) +void memory_region_init_iommu_type(const char *mrtypename, + IOMMUMemoryRegion *iommumr, + Object *owner, + const MemoryRegionIOMMUOps *ops, + const char *name, + uint64_t size) { - memory_region_init(mr, owner, name, size); - mr->iommu_ops =3D ops, + struct MemoryRegion *mr; + size_t instance_size =3D object_type_get_instance_size(mrtypename); + + object_initialize(iommumr, instance_size, mrtypename); + mr =3D MEMORY_REGION(iommumr); + memory_region_do_init(mr, owner, name, size); + iommumr->iommu_ops =3D ops, mr->terminates =3D true; /* then re-forwards */ - QLIST_INIT(&mr->iommu_notify); - mr->iommu_notify_flags =3D IOMMU_NOTIFIER_NONE; + QLIST_INIT(&iommumr->iommu_notify); + iommumr->iommu_notify_flags =3D IOMMU_NOTIFIER_NONE; +} + +void memory_region_init_iommu(IOMMUMemoryRegion *iommumr, + Object *owner, + const MemoryRegionIOMMUOps *ops, + const char *name, + uint64_t size) +{ + memory_region_init_iommu_type(TYPE_IOMMU_MEMORY_REGION, iommumr, + owner, ops, name, size); } =20 static void memory_region_finalize(Object *obj) @@ -1578,57 +1602,61 @@ bool memory_region_is_logging(MemoryRegion *mr, uin= t8_t client) return memory_region_get_dirty_log_mask(mr) & (1 << client); } =20 -static void memory_region_update_iommu_notify_flags(MemoryRegion *mr) +static void memory_region_update_iommu_notify_flags(IOMMUMemoryRegion *iom= mumr) { IOMMUNotifierFlag flags =3D IOMMU_NOTIFIER_NONE; IOMMUNotifier *iommu_notifier; =20 - QLIST_FOREACH(iommu_notifier, &mr->iommu_notify, node) { + QLIST_FOREACH(iommu_notifier, &iommumr->iommu_notify, node) { flags |=3D iommu_notifier->notifier_flags; } =20 - if (flags !=3D mr->iommu_notify_flags && - mr->iommu_ops->notify_flag_changed) { - mr->iommu_ops->notify_flag_changed(mr, mr->iommu_notify_flags, - flags); + if (flags !=3D iommumr->iommu_notify_flags && + iommumr->iommu_ops->notify_flag_changed) { + iommumr->iommu_ops->notify_flag_changed(iommumr, + iommumr->iommu_notify_flag= s, + flags); } =20 - mr->iommu_notify_flags =3D flags; + iommumr->iommu_notify_flags =3D flags; } =20 void memory_region_register_iommu_notifier(MemoryRegion *mr, IOMMUNotifier *n) { + IOMMUMemoryRegion *iommumr; + if (mr->alias) { memory_region_register_iommu_notifier(mr->alias, n); return; } =20 /* We need to register for at least one bitfield */ + iommumr =3D IOMMU_MEMORY_REGION(mr); assert(n->notifier_flags !=3D IOMMU_NOTIFIER_NONE); - QLIST_INSERT_HEAD(&mr->iommu_notify, n, node); - memory_region_update_iommu_notify_flags(mr); + QLIST_INSERT_HEAD(&iommumr->iommu_notify, n, node); + memory_region_update_iommu_notify_flags(iommumr); } =20 -uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr) +uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommumr) { - assert(memory_region_is_iommu(mr)); - if (mr->iommu_ops && mr->iommu_ops->get_min_page_size) { - return mr->iommu_ops->get_min_page_size(mr); + if (iommumr->iommu_ops && iommumr->iommu_ops->get_min_page_size) { + return iommumr->iommu_ops->get_min_page_size(iommumr); } return TARGET_PAGE_SIZE; } =20 -void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n, +void memory_region_iommu_replay(IOMMUMemoryRegion *iommumr, IOMMUNotifier = *n, bool is_write) { + MemoryRegion *mr =3D MEMORY_REGION(iommumr); hwaddr addr, granularity; IOMMUTLBEntry iotlb; =20 - granularity =3D memory_region_iommu_get_min_page_size(mr); + granularity =3D memory_region_iommu_get_min_page_size(iommumr); =20 for (addr =3D 0; addr < memory_region_size(mr); addr +=3D granularity)= { - iotlb =3D mr->iommu_ops->translate(mr, addr, is_write); + iotlb =3D iommumr->iommu_ops->translate(iommumr, addr, is_write); if (iotlb.perm !=3D IOMMU_NONE) { n->notify(n, &iotlb); } @@ -1644,21 +1672,24 @@ void memory_region_iommu_replay(MemoryRegion *mr, I= OMMUNotifier *n, void memory_region_unregister_iommu_notifier(MemoryRegion *mr, IOMMUNotifier *n) { + IOMMUMemoryRegion *iommumr; + if (mr->alias) { memory_region_unregister_iommu_notifier(mr->alias, n); return; } QLIST_REMOVE(n, node); - memory_region_update_iommu_notify_flags(mr); + iommumr =3D IOMMU_MEMORY_REGION(mr); + memory_region_update_iommu_notify_flags(iommumr); } =20 -void memory_region_notify_iommu(MemoryRegion *mr, +void memory_region_notify_iommu(IOMMUMemoryRegion *iommumr, IOMMUTLBEntry entry) { IOMMUNotifier *iommu_notifier; IOMMUNotifierFlag request_flags; =20 - assert(memory_region_is_iommu(mr)); + assert(memory_region_is_iommu(MEMORY_REGION(iommumr))); =20 if (entry.perm & IOMMU_RW) { request_flags =3D IOMMU_NOTIFIER_MAP; @@ -1666,7 +1697,7 @@ void memory_region_notify_iommu(MemoryRegion *mr, request_flags =3D IOMMU_NOTIFIER_UNMAP; } =20 - QLIST_FOREACH(iommu_notifier, &mr->iommu_notify, node) { + QLIST_FOREACH(iommu_notifier, &iommumr->iommu_notify, node) { if (iommu_notifier->notifier_flags & request_flags) { iommu_notifier->notify(iommu_notifier, &entry); } @@ -2660,9 +2691,16 @@ static const TypeInfo memory_region_info =3D { .instance_finalize =3D memory_region_finalize, }; =20 +static const TypeInfo iommu_memory_region_info =3D { + .parent =3D TYPE_MEMORY_REGION, + .name =3D TYPE_IOMMU_MEMORY_REGION, + .instance_size =3D sizeof(IOMMUMemoryRegion), +}; + static void memory_register_types(void) { type_register_static(&memory_region_info); + type_register_static(&iommu_memory_region_info); } =20 type_init(memory_register_types) --=20 2.11.0 From nobody Thu May 2 01:34:02 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 149087817607513.034718403793022; Thu, 30 Mar 2017 05:49:36 -0700 (PDT) Received: from localhost ([::1]:35449 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ctZWA-0001zK-L2 for importer@patchew.org; Thu, 30 Mar 2017 08:49:34 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50847) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ctZUT-0000m6-1d for qemu-devel@nongnu.org; Thu, 30 Mar 2017 08:47:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ctZUQ-0006Am-U0 for qemu-devel@nongnu.org; Thu, 30 Mar 2017 08:47:49 -0400 Received: from ozlabs.ru ([107.173.13.209]:57982) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ctZUQ-0006AX-Kb; Thu, 30 Mar 2017 08:47:46 -0400 Received: from vpl2.ozlabs.ibm.com (localhost [IPv6:::1]) by ozlabs.ru (Postfix) with ESMTP id F03CA3A6018E; Thu, 30 Mar 2017 08:47:20 -0400 (EDT) From: Alexey Kardashevskiy To: qemu-devel@nongnu.org Date: Thu, 30 Mar 2017 23:47:04 +1100 Message-Id: <20170330124707.28142-3-aik@ozlabs.ru> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170330124707.28142-1-aik@ozlabs.ru> References: <20170330124707.28142-1-aik@ozlabs.ru> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 107.173.13.209 Subject: [Qemu-devel] [RFC PATCH qemu 2/5] spapr-iommu: Subclass TYPE_IOMMU_MEMORY_REGION X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alexey Kardashevskiy , Paolo Bonzini , Alex Williamson , qemu-ppc@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Alexey Kardashevskiy --- include/hw/ppc/spapr.h | 22 ++++++++++++++++++++++ hw/ppc/spapr_iommu.c | 25 ++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 6997ed7e98..5d5ce4dd2b 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -573,11 +573,25 @@ void spapr_load_rtas(sPAPRMachineState *spapr, void *= fdt, hwaddr addr); #define RTAS_EVENT_SCAN_RATE 1 =20 typedef struct sPAPRTCETable sPAPRTCETable; +typedef struct sPAPRIOMMUMemoryRegionClass sPAPRIOMMUMemoryRegionClass; =20 #define TYPE_SPAPR_TCE_TABLE "spapr-tce-table" #define SPAPR_TCE_TABLE(obj) \ OBJECT_CHECK(sPAPRTCETable, (obj), TYPE_SPAPR_TCE_TABLE) =20 +#define TYPE_SPAPR_IOMMU_MEMORY_REGION "qemu:spapr_iommu-memory-region" +#define SPAPR_IOMMU_MEMORY_REGION(obj) \ + OBJECT_CHECK(IOMMUMemoryRegion, (obj), \ + TYPE_SPAPR_IOMMU_MEMORY_REGION) + +#define SPAPR_IOMMU_MEMORY_REGION_CLASS(k) \ + OBJECT_CLASS_CHECK(sPAPRIOMMUMemoryRegionClass, (k), \ + TYPE_SPAPR_IOMMU_MEMORY_REGION) + +#define SPAPR_IOMMU_MEMORY_REGION_GET_CLASS(obj) \ + OBJECT_GET_CLASS(sPAPRIOMMUMemoryRegionClass, (obj), \ + TYPE_SPAPR_IOMMU_MEMORY_REGION) + struct sPAPRTCETable { DeviceState parent; uint32_t liobn; @@ -596,6 +610,14 @@ struct sPAPRTCETable { QLIST_ENTRY(sPAPRTCETable) list; }; =20 +struct sPAPRIOMMUMemoryRegionClass { + /*< private >*/ + ObjectClass parent_class; + /*< public >*/ + + int (*get_fd)(IOMMUMemoryRegion *iommu); +}; + sPAPRTCETable *spapr_tce_find_by_liobn(target_ulong liobn); =20 struct sPAPREventLogEntry { diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c index 5051110b9d..5b0eee1be4 100644 --- a/hw/ppc/spapr_iommu.c +++ b/hw/ppc/spapr_iommu.c @@ -171,6 +171,13 @@ static void spapr_tce_notify_flag_changed(IOMMUMemoryR= egion *iommu, } } =20 +static int spapr_tce_get_fd(IOMMUMemoryRegion *iommu) +{ + sPAPRTCETable *tcet =3D container_of(iommu, sPAPRTCETable, iommu); + + return tcet->fd; +} + static int spapr_tce_table_post_load(void *opaque, int version_id) { sPAPRTCETable *tcet =3D SPAPR_TCE_TABLE(opaque); @@ -266,7 +273,7 @@ static int spapr_tce_table_realize(DeviceState *dev) memory_region_init(&tcet->root, tcetobj, tmp, UINT64_MAX); =20 snprintf(tmp, sizeof(tmp), "tce-iommu-%x", tcet->liobn); - memory_region_init_iommu_type(TYPE_IOMMU_MEMORY_REGION, + memory_region_init_iommu_type(TYPE_SPAPR_IOMMU_MEMORY_REGION, &tcet->iommu, tcetobj, &spapr_iommu_ops, tmp, 0); =20 @@ -634,9 +641,25 @@ static TypeInfo spapr_tce_table_info =3D { .class_init =3D spapr_tce_table_class_init, }; =20 +static void spapr_iommu_memory_region_class_init(ObjectClass *k, void *dat= a) +{ + sPAPRIOMMUMemoryRegionClass *smrc =3D SPAPR_IOMMU_MEMORY_REGION_CLASS(= k); + + smrc->get_fd =3D spapr_tce_get_fd; +} + +static const TypeInfo spapr_iommu_memory_region_info =3D { + .parent =3D TYPE_IOMMU_MEMORY_REGION, + .name =3D TYPE_SPAPR_IOMMU_MEMORY_REGION, + .instance_size =3D sizeof(IOMMUMemoryRegion), + .class_size =3D sizeof(sPAPRIOMMUMemoryRegionClass), + .class_init =3D spapr_iommu_memory_region_class_init, +}; + static void register_types(void) { type_register_static(&spapr_tce_table_info); + type_register_static(&spapr_iommu_memory_region_info); } =20 type_init(register_types); --=20 2.11.0 From nobody Thu May 2 01:34:02 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1490878264445577.4497943095748; Thu, 30 Mar 2017 05:51:04 -0700 (PDT) Received: from localhost ([::1]:35462 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ctZXb-0003IO-1O for importer@patchew.org; Thu, 30 Mar 2017 08:51:03 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50745) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ctZU4-0000Vn-8z for qemu-devel@nongnu.org; Thu, 30 Mar 2017 08:47:25 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ctZTz-0005yQ-L0 for qemu-devel@nongnu.org; Thu, 30 Mar 2017 08:47:24 -0400 Received: from ozlabs.ru ([107.173.13.209]:54672) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ctZTz-0005yD-Fq; Thu, 30 Mar 2017 08:47:19 -0400 Received: from vpl2.ozlabs.ibm.com (localhost [IPv6:::1]) by ozlabs.ru (Postfix) with ESMTP id C49E53A6018F; Thu, 30 Mar 2017 08:47:22 -0400 (EDT) From: Alexey Kardashevskiy To: qemu-devel@nongnu.org Date: Thu, 30 Mar 2017 23:47:05 +1100 Message-Id: <20170330124707.28142-4-aik@ozlabs.ru> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170330124707.28142-1-aik@ozlabs.ru> References: <20170330124707.28142-1-aik@ozlabs.ru> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 107.173.13.209 Subject: [Qemu-devel] [RFC PATCH qemu 3/5] vfio-pci: Reorder group-to-container attaching X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alexey Kardashevskiy , Paolo Bonzini , Alex Williamson , qemu-ppc@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" At the moment VFIO PCI device initialization works as follows: vfio_realize vfio_get_group vfio_connect_container register memory listeners (1) update QEMU groups lists vfio_kvm_device_add_group Then (example for pseries) the machine reset hook triggers region_add() for all regions where listeners from (1) are listening: ppc_spapr_reset spapr_phb_reset spapr_tce_table_enable memory_region_add_subregion vfio_listener_region_add vfio_spapr_create_window This scheme works fine until we need to handle VFIO PCI device hotplug _and_ we want to enable in-kernel acceleration on, i.e. after PCI hotplug we need a place to call ioctl(vfio_kvm_device_fd, KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE). Since the ioctl needs a LIOBN fd (from sPAPRTCETable) and a IOMMU group fd (from VFIOGroup), vfio_listener_region_add() seems to be the only place for this ioctl(). However this only works during boot time because the machine reset happens strictly after all devices are finalized. When hotplug happens, vfio_listener_region_add() is called when a memory listener is registered but when this happens: 1. new group is not added to the container->group_list yet; 2. VFIO KVM device is unaware of the new IOMMU group. This moves bits around to have all necessary VFIO infrastructure in place for both initial startup and hotplug cases. Signed-off-by: Alexey Kardashevskiy --- Changes: v2: * moved container->initialized back to its correct location * added missing QLIST_REMOVE() --- hw/vfio/common.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index ab95db689c..e8188eb3d5 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -1087,6 +1087,14 @@ static int vfio_connect_container(VFIOGroup *group, = AddressSpace *as, goto free_container_exit; } =20 + vfio_kvm_device_add_group(group); + + QLIST_INIT(&container->group_list); + QLIST_INSERT_HEAD(&space->containers, container, next); + + group->container =3D container; + QLIST_INSERT_HEAD(&container->group_list, group, container_next); + container->listener =3D vfio_memory_listener; =20 memory_listener_register(&container->listener, container->space->as); @@ -1100,14 +1108,11 @@ static int vfio_connect_container(VFIOGroup *group,= AddressSpace *as, =20 container->initialized =3D true; =20 - QLIST_INIT(&container->group_list); - QLIST_INSERT_HEAD(&space->containers, container, next); - - group->container =3D container; - QLIST_INSERT_HEAD(&container->group_list, group, container_next); - return 0; listener_release_exit: + QLIST_REMOVE(group, container_next); + QLIST_REMOVE(container, next); + vfio_kvm_device_del_group(group); vfio_listener_release(container); =20 free_container_exit: @@ -1212,8 +1217,6 @@ VFIOGroup *vfio_get_group(int groupid, AddressSpace *= as, Error **errp) =20 QLIST_INSERT_HEAD(&vfio_group_list, group, next); =20 - vfio_kvm_device_add_group(group); - return group; =20 close_fd_exit: --=20 2.11.0 From nobody Thu May 2 01:34:02 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1490878178897419.6638918672554; Thu, 30 Mar 2017 05:49:38 -0700 (PDT) Received: from localhost ([::1]:35451 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ctZWD-00021l-O2 for importer@patchew.org; Thu, 30 Mar 2017 08:49:37 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50898) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ctZUV-0000nl-Du for qemu-devel@nongnu.org; Thu, 30 Mar 2017 08:47:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ctZUU-0006Cb-HO for qemu-devel@nongnu.org; Thu, 30 Mar 2017 08:47:51 -0400 Received: from ozlabs.ru ([107.173.13.209]:58368) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ctZUU-0006CL-8P; Thu, 30 Mar 2017 08:47:50 -0400 Received: from vpl2.ozlabs.ibm.com (localhost [IPv6:::1]) by ozlabs.ru (Postfix) with ESMTP id 992573A60190; Thu, 30 Mar 2017 08:47:24 -0400 (EDT) From: Alexey Kardashevskiy To: qemu-devel@nongnu.org Date: Thu, 30 Mar 2017 23:47:06 +1100 Message-Id: <20170330124707.28142-5-aik@ozlabs.ru> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170330124707.28142-1-aik@ozlabs.ru> References: <20170330124707.28142-1-aik@ozlabs.ru> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 107.173.13.209 Subject: [Qemu-devel] [RFC PATCH qemu 4/5] vfio/spapr: Add a notifier for PPC64 HV/PR KVM about new group attached to LIOBN X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alexey Kardashevskiy , Paolo Bonzini , Alex Williamson , qemu-ppc@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This implements a notification for a new IOMMU group attached to sPAPR's logical IO bus (LIOBN) to enable in-kernel TCE acceleration. Signed-off-by: Alexey Kardashevskiy --- include/hw/vfio/vfio-common.h | 1 + hw/vfio/common.c | 10 ++++++++++ hw/vfio/spapr.c | 32 ++++++++++++++++++++++++++++++++ hw/vfio/trace-events | 1 + 4 files changed, 44 insertions(+) diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index 7a4135ae6f..9662cb29a0 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -175,6 +175,7 @@ extern const MemoryListener vfio_prereg_listener; int vfio_spapr_create_window(VFIOContainer *container, MemoryRegionSection *section, hwaddr *pgsize); +int vfio_spapr_notify_kvm(int vfio_kvm_device_fd, int groupfd, int tablefd= ); int vfio_spapr_remove_window(VFIOContainer *container, hwaddr offset_within_address_space); =20 diff --git a/hw/vfio/common.c b/hw/vfio/common.c index e8188eb3d5..b94b29be15 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -440,6 +440,16 @@ static void vfio_listener_region_add(MemoryListener *l= istener, goto fail; } =20 +#ifdef CONFIG_KVM + if (kvm_enabled()) { + VFIOGroup *group; + + QLIST_FOREACH(group, &container->group_list, container_next) { + vfio_spapr_notify_kvm(vfio_kvm_device_fd, group->fd, + IOMMU_MEMORY_REGION(section->mr)); + } + } +#endif vfio_host_win_add(container, section->offset_within_address_space, section->offset_within_address_space + int128_get64(section->size) - 1, pgsize); diff --git a/hw/vfio/spapr.c b/hw/vfio/spapr.c index 551870d46b..bab808b837 100644 --- a/hw/vfio/spapr.c +++ b/hw/vfio/spapr.c @@ -15,8 +15,12 @@ =20 #include "hw/vfio/vfio-common.h" #include "hw/hw.h" +#include "hw/ppc/spapr.h" #include "qemu/error-report.h" #include "trace.h" +#ifdef CONFIG_KVM +#include "linux/kvm.h" +#endif =20 static bool vfio_prereg_listener_skipped_section(MemoryRegionSection *sect= ion) { @@ -188,6 +192,34 @@ int vfio_spapr_create_window(VFIOContainer *container, return 0; } =20 +int vfio_spapr_notify_kvm(int vfio_kvm_device_fd, int groupfd, + IOMMUMemoryRegion *iommumr) +{ +#ifdef CONFIG_KVM + struct kvm_vfio_spapr_tce param =3D { + .groupfd =3D groupfd, + }; + struct kvm_device_attr attr =3D { + .group =3D KVM_DEV_VFIO_GROUP, + .attr =3D KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE, + .addr =3D (uint64_t)(unsigned long)¶m, + }; + sPAPRIOMMUMemoryRegionClass *spmc =3D + SPAPR_IOMMU_MEMORY_REGION_GET_CLASS(iommumr); + + param.tablefd =3D spmc->get_fd(iommumr); + if (param.tablefd !=3D -1) { + if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) { + error_report("vfio: failed to setup fd %d for a group with fd = %d: %s", + param.tablefd, param.groupfd, strerror(errno)); + return -errno; + } + } + trace_vfio_spapr_notify_kvm(groupfd, param.tablefd); +#endif + return 0; +} + int vfio_spapr_remove_window(VFIOContainer *container, hwaddr offset_within_address_space) { diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events index 2561c6d31a..084a92f7c2 100644 --- a/hw/vfio/trace-events +++ b/hw/vfio/trace-events @@ -123,3 +123,4 @@ vfio_prereg_register(uint64_t va, uint64_t size, int re= t) "va=3D%"PRIx64" size=3D%"P vfio_prereg_unregister(uint64_t va, uint64_t size, int ret) "va=3D%"PRIx64= " size=3D%"PRIx64" ret=3D%d" vfio_spapr_create_window(int ps, uint64_t ws, uint64_t off) "pageshift=3D0= x%x winsize=3D0x%"PRIx64" offset=3D0x%"PRIx64 vfio_spapr_remove_window(uint64_t off) "offset=3D%"PRIx64 +vfio_spapr_notify_kvm(int groupfd, int tablefd) "Attached groupfd %d to li= obn fd %d" --=20 2.11.0 From nobody Thu May 2 01:34:02 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1490878130584957.4249748237024; Thu, 30 Mar 2017 05:48:50 -0700 (PDT) Received: from localhost ([::1]:35447 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ctZVR-0001O7-6F for importer@patchew.org; Thu, 30 Mar 2017 08:48:49 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50740) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ctZU3-0000Vl-IJ for qemu-devel@nongnu.org; Thu, 30 Mar 2017 08:47:24 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ctZU2-0005yo-3c for qemu-devel@nongnu.org; Thu, 30 Mar 2017 08:47:23 -0400 Received: from ozlabs.ru ([107.173.13.209]:55162) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ctZU1-0005yi-To; Thu, 30 Mar 2017 08:47:22 -0400 Received: from vpl2.ozlabs.ibm.com (localhost [IPv6:::1]) by ozlabs.ru (Postfix) with ESMTP id 6D9B43A6024B; Thu, 30 Mar 2017 08:47:26 -0400 (EDT) From: Alexey Kardashevskiy To: qemu-devel@nongnu.org Date: Thu, 30 Mar 2017 23:47:07 +1100 Message-Id: <20170330124707.28142-6-aik@ozlabs.ru> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170330124707.28142-1-aik@ozlabs.ru> References: <20170330124707.28142-1-aik@ozlabs.ru> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 107.173.13.209 Subject: [Qemu-devel] [RFC PATCH qemu 5/5] spapr/iommu: Enable in-kernel TCE acceleration via VFIO KVM device X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alexey Kardashevskiy , Paolo Bonzini , Alex Williamson , qemu-ppc@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This uses new kernel KVM_CAP_SPAPR_TCE_VFIO capability to enable in-kernel acceleration of TCE update requests which will go via the VFIO KVM device. Signed-off-by: Alexey Kardashevskiy --- target/ppc/kvm_ppc.h | 6 ++++++ hw/ppc/spapr_iommu.c | 4 ++++ target/ppc/kvm.c | 7 ++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h index f48243d13f..ce7327a4e0 100644 --- a/target/ppc/kvm_ppc.h +++ b/target/ppc/kvm_ppc.h @@ -46,6 +46,7 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t pa= ge_shift, int kvmppc_remove_spapr_tce(void *table, int pfd, uint32_t window_size); int kvmppc_reset_htab(int shift_hint); uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift); +bool kvmppc_has_cap_spapr_vfio(void); #endif /* !CONFIG_USER_ONLY */ bool kvmppc_has_cap_epr(void); int kvmppc_define_rtas_kernel_token(uint32_t token, const char *function); @@ -216,6 +217,11 @@ static inline bool kvmppc_is_mem_backend_page_size_ok(= char *obj_path) return true; } =20 +static inline bool kvmppc_has_cap_spapr_vfio(void) +{ + return false; +} + #endif /* !CONFIG_USER_ONLY */ =20 static inline bool kvmppc_has_cap_epr(void) diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c index 5b0eee1be4..bfc2b71ca3 100644 --- a/hw/ppc/spapr_iommu.c +++ b/hw/ppc/spapr_iommu.c @@ -295,6 +295,10 @@ void spapr_tce_set_need_vfio(sPAPRTCETable *tcet, bool= need_vfio) =20 tcet->need_vfio =3D need_vfio; =20 + if (!need_vfio || (tcet->fd !=3D -1 && kvmppc_has_cap_spapr_vfio())) { + return; + } + oldtable =3D tcet->table; =20 tcet->table =3D spapr_tce_alloc_table(tcet->liobn, diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index abf4cb23b1..82886b669f 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -131,7 +131,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) cap_spapr_tce =3D kvm_check_extension(s, KVM_CAP_SPAPR_TCE); cap_spapr_tce_64 =3D kvm_check_extension(s, KVM_CAP_SPAPR_TCE_64); cap_spapr_multitce =3D kvm_check_extension(s, KVM_CAP_SPAPR_MULTITCE); - cap_spapr_vfio =3D false; + cap_spapr_vfio =3D kvm_check_extension(s, KVM_CAP_SPAPR_TCE_VFIO); cap_one_reg =3D kvm_check_extension(s, KVM_CAP_ONE_REG); cap_hior =3D kvm_check_extension(s, KVM_CAP_PPC_HIOR); cap_epr =3D kvm_check_extension(s, KVM_CAP_PPC_EPR); @@ -2418,6 +2418,11 @@ bool kvmppc_has_cap_mmu_hash_v3(void) return cap_mmu_hash_v3; } =20 +bool kvmppc_has_cap_spapr_vfio(void) +{ + return cap_spapr_vfio; +} + static PowerPCCPUClass *ppc_cpu_get_family_class(PowerPCCPUClass *pcc) { ObjectClass *oc =3D OBJECT_CLASS(pcc); --=20 2.11.0