From nobody Mon Feb 9 20:31:44 2026 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.zohomail.com; dkim=fail; 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 1499958035637300.9152678903471; Thu, 13 Jul 2017 08:00:35 -0700 (PDT) Received: from localhost ([::1]:60536 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dVfbU-0000xR-4U for importer@patchew.org; Thu, 13 Jul 2017 11:00:32 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51843) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dVf4Y-000201-JK for qemu-devel@nongnu.org; Thu, 13 Jul 2017 10:26:33 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dVf4V-0004O2-Oq for qemu-devel@nongnu.org; Thu, 13 Jul 2017 10:26:30 -0400 Received: from mail-wm0-f65.google.com ([74.125.82.65]:35553) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dVf4V-0004Nf-C4 for qemu-devel@nongnu.org; Thu, 13 Jul 2017 10:26:27 -0400 Received: by mail-wm0-f65.google.com with SMTP id u23so5458277wma.2 for ; Thu, 13 Jul 2017 07:26:27 -0700 (PDT) Received: from 640k.lan (94-39-191-51.adsl-ull.clienti.tiscali.it. [94.39.191.51]) by smtp.gmail.com with ESMTPSA id k75sm6042448wmh.10.2017.07.13.07.25.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 13 Jul 2017 07:25:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=EI0FWF2UVnn53z0uiUOL58vho4sfK6h6a0x9KAR4G8E=; b=elDpHI7oG/c6eaEiIeyl6YQJ5/SL276rT6XAkTdVxR3mvMcyq+Y2GWYASNkBI+NjrT aC1ov6gzEe4wYtQNs9PQnUC3rk4GE+6v/6/lvwVQNhdWllMcae4A6ps4ar6bAQfC9Pn9 LXzvME6hSwF8loRSFWG+ypibXqYq6FKXmjdhsv9ZlkN6iVzJ0AOc+DvvN+MnPIMNLPrh 7QxLU4SAPKE5yZSr4NQ8v0lvPGuDfTjmS4ipml2pk8pKSYcOAd/uhKv7L+5Z+vfdL/Tu 0W9jmT2sgXHnvfT4CD1cANKzuFiHBOKb+bgr2vj1BKF3uoYzPVH6HneNRH1Eq96t58TP Fsng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=EI0FWF2UVnn53z0uiUOL58vho4sfK6h6a0x9KAR4G8E=; b=fjlKRf1fVX0zQFfQKx0BldHfe3WikWeGlYik107JUDOklsAFTjoxYWLNl4CnYhm9/C Q73nr8y2ToJ4qRUzMjGjr+DiAmpPk3gLdHoOlBnPnFtjsK2GIjHQSshU85FSUzmf8oKt lZy+uOAVibRkLiAgo30XYwm5zOkQoQQiNgfcZ1nvc3qnI6YkQGBzaF6VOKGevjr9LXJM ljgmSwr7cmn0/10luJm5i5IBMxyYIi1nljZBebc6FIeTlNWi2oKxveDPtValck7aUtwF PCL3M5kh5Vo88224Dsn/2AaC5Z2lEls5ASboQcokLa1Fdvnh+uhEabd7Xb6u8MQFY/Rt lIhw== X-Gm-Message-State: AIVw112Xrq/adJ4bYVS2O98xKgXzQ3DymOEa/KdVWYeZto6rybFx2LmR SgJyNZv/MVMRdhs37QQ= X-Received: by 10.28.232.141 with SMTP id f13mr2270645wmi.59.1499955925736; Thu, 13 Jul 2017 07:25:25 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 13 Jul 2017 16:24:23 +0200 Message-Id: <1499955874-10954-31-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1499955874-10954-1-git-send-email-pbonzini@redhat.com> References: <1499955874-10954-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 74.125.82.65 Subject: [Qemu-devel] [PULL 30/41] memory/iommu: introduce IOMMUMemoryRegionClass 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 Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Alexey Kardashevskiy This finishes QOM'fication of IOMMUMemoryRegion by introducing a IOMMUMemoryRegionClass. This also provides a fastpath analog for IOMMU_MEMORY_REGION_GET_CLASS(). This makes IOMMUMemoryRegion an abstract class. Signed-off-by: Alexey Kardashevskiy Message-Id: <20170711035620.4232-3-aik@ozlabs.ru> Acked-by: Cornelia Huck Signed-off-by: Paolo Bonzini --- exec.c | 6 ++++-- hw/alpha/typhoon.c | 23 +++++++++++++++++----- hw/dma/rc4030.c | 26 +++++++++++++++++++------ hw/i386/amd_iommu.c | 24 +++++++++++++++++++---- hw/i386/amd_iommu.h | 5 ++--- hw/i386/intel_iommu.c | 25 +++++++++++++++++++----- hw/pci-host/apb.c | 23 +++++++++++++++++----- hw/ppc/spapr_iommu.c | 26 ++++++++++++++++++------- hw/s390x/s390-pci-bus.c | 23 ++++++++++++++++------ hw/s390x/s390-pci-bus.h | 1 + hw/s390x/s390-pci-inst.c | 5 ++++- include/exec/memory.h | 45 +++++++++++++++++++++++++++++++++------= ---- include/hw/i386/intel_iommu.h | 3 ++- include/hw/ppc/spapr.h | 4 ++++ memory.c | 36 +++++++++++++++++++--------------- 15 files changed, 205 insertions(+), 70 deletions(-) diff --git a/exec.c b/exec.c index 2aa8be5..b3c080f 100644 --- a/exec.c +++ b/exec.c @@ -481,6 +481,7 @@ static MemoryRegionSection address_space_do_translate(A= ddressSpace *as, IOMMUTLBEntry iotlb; MemoryRegionSection *section; IOMMUMemoryRegion *iommu_mr; + IOMMUMemoryRegionClass *imrc; =20 for (;;) { AddressSpaceDispatch *d =3D atomic_rcu_read(&as->dispatch); @@ -490,9 +491,10 @@ static MemoryRegionSection address_space_do_translate(= AddressSpace *as, if (!iommu_mr) { break; } + imrc =3D memory_region_get_iommu_class_nocheck(iommu_mr); =20 - iotlb =3D iommu_mr->iommu_ops->translate(iommu_mr, addr, is_write ? - IOMMU_WO : IOMMU_RO); + iotlb =3D imrc->translate(iommu_mr, addr, is_write ? + IOMMU_WO : IOMMU_RO); addr =3D ((iotlb.translated_addr & ~iotlb.addr_mask) | (addr & iotlb.addr_mask)); *plen =3D MIN(*plen, (addr | iotlb.addr_mask) - addr + 1); diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c index dd47b45..ae11e01 100644 --- a/hw/alpha/typhoon.c +++ b/hw/alpha/typhoon.c @@ -17,6 +17,7 @@ =20 =20 #define TYPE_TYPHOON_PCI_HOST_BRIDGE "typhoon-pcihost" +#define TYPE_TYPHOON_IOMMU_MEMORY_REGION "typhoon-iommu-memory-region" =20 typedef struct TyphoonCchip { MemoryRegion region; @@ -725,10 +726,6 @@ static IOMMUTLBEntry typhoon_translate_iommu(IOMMUMemo= ryRegion *iommu, return ret; } =20 -static const MemoryRegionIOMMUOps typhoon_iommu_ops =3D { - .translate =3D typhoon_translate_iommu, -}; - static AddressSpace *typhoon_pci_dma_iommu(PCIBus *bus, void *opaque, int = devfn) { TyphoonState *s =3D opaque; @@ -892,7 +889,8 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_= bus, qdev_init_nofail(dev); =20 /* Host memory as seen from the PCI side, via the IOMMU. */ - memory_region_init_iommu(&s->pchip.iommu, OBJECT(s), &typhoon_iommu_op= s, + memory_region_init_iommu(&s->pchip.iommu, sizeof(s->pchip.iommu), + TYPE_TYPHOON_IOMMU_MEMORY_REGION, OBJECT(s), "iommu-typhoon", UINT64_MAX); address_space_init(&s->pchip.iommu_as, MEMORY_REGION(&s->pchip.iommu), "pchip0-pci"); @@ -953,9 +951,24 @@ static const TypeInfo typhoon_pcihost_info =3D { .class_init =3D typhoon_pcihost_class_init, }; =20 +static void typhoon_iommu_memory_region_class_init(ObjectClass *klass, + void *data) +{ + IOMMUMemoryRegionClass *imrc =3D IOMMU_MEMORY_REGION_CLASS(klass); + + imrc->translate =3D typhoon_translate_iommu; +} + +static const TypeInfo typhoon_iommu_memory_region_info =3D { + .parent =3D TYPE_IOMMU_MEMORY_REGION, + .name =3D TYPE_TYPHOON_IOMMU_MEMORY_REGION, + .class_init =3D typhoon_iommu_memory_region_class_init, +}; + static void typhoon_register_types(void) { type_register_static(&typhoon_pcihost_info); + type_register_static(&typhoon_iommu_memory_region_info); } =20 type_init(typhoon_register_types) diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c index 32c0676..5d4833e 100644 --- a/hw/dma/rc4030.c +++ b/hw/dma/rc4030.c @@ -54,6 +54,8 @@ typedef struct dma_pagetable_entry { #define RC4030(obj) \ OBJECT_CHECK(rc4030State, (obj), TYPE_RC4030) =20 +#define TYPE_RC4030_IOMMU_MEMORY_REGION "rc4030-iommu-memory-region" + typedef struct rc4030State { SysBusDevice parent; @@ -516,10 +518,6 @@ static IOMMUTLBEntry rc4030_dma_translate(IOMMUMemoryR= egion *iommu, hwaddr addr, return ret; } =20 -static const MemoryRegionIOMMUOps rc4030_dma_ops =3D { - .translate =3D rc4030_dma_translate, -}; - static void rc4030_reset(DeviceState *dev) { rc4030State *s =3D RC4030(dev); @@ -677,8 +675,9 @@ static void rc4030_realize(DeviceState *dev, Error **er= rp) memory_region_init_io(&s->iomem_jazzio, NULL, &jazzio_ops, s, "rc4030.jazzio", 0x00001000); =20 - memory_region_init_iommu(&s->dma_mr, o, &rc4030_dma_ops, - "rc4030.dma", UINT32_MAX); + memory_region_init_iommu(&s->dma_mr, sizeof(s->dma_mr), + TYPE_RC4030_IOMMU_MEMORY_REGION, + o, "rc4030.dma", UINT32_MAX); address_space_init(&s->dma_as, MEMORY_REGION(&s->dma_mr), "rc4030-dma"= ); } =20 @@ -710,9 +709,24 @@ static const TypeInfo rc4030_info =3D { .class_init =3D rc4030_class_init, }; =20 +static void rc4030_iommu_memory_region_class_init(ObjectClass *klass, + void *data) +{ + IOMMUMemoryRegionClass *imrc =3D IOMMU_MEMORY_REGION_CLASS(klass); + + imrc->translate =3D rc4030_dma_translate; +} + +static const TypeInfo rc4030_iommu_memory_region_info =3D { + .parent =3D TYPE_IOMMU_MEMORY_REGION, + .name =3D TYPE_RC4030_IOMMU_MEMORY_REGION, + .class_init =3D rc4030_iommu_memory_region_class_init, +}; + static void rc4030_register_types(void) { type_register_static(&rc4030_info); + type_register_static(&rc4030_iommu_memory_region_info); } =20 type_init(rc4030_register_types) diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c index 7a67c57..334938a 100644 --- a/hw/i386/amd_iommu.c +++ b/hw/i386/amd_iommu.c @@ -1044,8 +1044,11 @@ static AddressSpace *amdvi_host_dma_iommu(PCIBus *bu= s, void *opaque, int devfn) iommu_as[devfn]->devfn =3D (uint8_t)devfn; iommu_as[devfn]->iommu_state =3D s; =20 - memory_region_init_iommu(&iommu_as[devfn]->iommu, OBJECT(s), - &s->iommu_ops, "amd-iommu", UINT64_MAX); + memory_region_init_iommu(&iommu_as[devfn]->iommu, + sizeof(iommu_as[devfn]->iommu), + TYPE_AMD_IOMMU_MEMORY_REGION, + OBJECT(s), + "amd-iommu", UINT64_MAX); address_space_init(&iommu_as[devfn]->as, MEMORY_REGION(&iommu_as[devfn]->iommu), "amd-iommu"); @@ -1086,8 +1089,6 @@ static void amdvi_init(AMDVIState *s) { amdvi_iotlb_reset(s); =20 - s->iommu_ops.translate =3D amdvi_translate; - s->iommu_ops.notify_flag_changed =3D amdvi_iommu_notify_flag_changed; s->devtab_len =3D 0; s->cmdbuf_len =3D 0; s->cmdbuf_head =3D 0; @@ -1228,10 +1229,25 @@ static const TypeInfo amdviPCI =3D { .instance_size =3D sizeof(AMDVIPCIState), }; =20 +static void amdvi_iommu_memory_region_class_init(ObjectClass *klass, void = *data) +{ + IOMMUMemoryRegionClass *imrc =3D IOMMU_MEMORY_REGION_CLASS(klass); + + imrc->translate =3D amdvi_translate; + imrc->notify_flag_changed =3D amdvi_iommu_notify_flag_changed; +} + +static const TypeInfo amdvi_iommu_memory_region_info =3D { + .parent =3D TYPE_IOMMU_MEMORY_REGION, + .name =3D TYPE_AMD_IOMMU_MEMORY_REGION, + .class_init =3D amdvi_iommu_memory_region_class_init, +}; + static void amdviPCI_register_types(void) { type_register_static(&amdviPCI); type_register_static(&amdvi); + type_register_static(&amdvi_iommu_memory_region_info); } =20 type_init(amdviPCI_register_types); diff --git a/hw/i386/amd_iommu.h b/hw/i386/amd_iommu.h index 0d3dc6a..d370ae3 100644 --- a/hw/i386/amd_iommu.h +++ b/hw/i386/amd_iommu.h @@ -220,6 +220,8 @@ =20 #define TYPE_AMD_IOMMU_PCI "AMDVI-PCI" =20 +#define TYPE_AMD_IOMMU_MEMORY_REGION "amd-iommu-iommu-memory-region" + typedef struct AMDVIAddressSpace AMDVIAddressSpace; =20 /* functions to steal PCI config space */ @@ -276,9 +278,6 @@ typedef struct AMDVIState { uint8_t romask[AMDVI_MMIO_SIZE]; /* MMIO read/only mask */ bool mmio_enabled; =20 - /* IOMMU function */ - MemoryRegionIOMMUOps iommu_ops; - /* for each served device */ AMDVIAddressSpace **address_spaces[PCI_BUS_MAX]; =20 diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 11dba0e..e398746 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -2718,8 +2718,9 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, = PCIBus *bus, int devfn) * vtd_sys_alias and intel_iommu regions. IR region is always * enabled. */ - memory_region_init_iommu(&vtd_dev_as->iommu, OBJECT(s), - &s->iommu_ops, "intel_iommu_dmar", + memory_region_init_iommu(&vtd_dev_as->iommu, sizeof(vtd_dev_as->io= mmu), + TYPE_INTEL_IOMMU_MEMORY_REGION, OBJECT(s), + "intel_iommu_dmar", UINT64_MAX); memory_region_init_alias(&vtd_dev_as->sys_alias, OBJECT(s), "vtd_sys_alias", get_system_memory(), @@ -2857,9 +2858,6 @@ static void vtd_init(IntelIOMMUState *s) memset(s->w1cmask, 0, DMAR_REG_SIZE); memset(s->womask, 0, DMAR_REG_SIZE); =20 - s->iommu_ops.translate =3D vtd_iommu_translate; - s->iommu_ops.notify_flag_changed =3D vtd_iommu_notify_flag_changed; - s->iommu_ops.replay =3D vtd_iommu_replay; s->root =3D 0; s->root_extended =3D false; s->dmar_enabled =3D false; @@ -3074,9 +3072,26 @@ static const TypeInfo vtd_info =3D { .class_init =3D vtd_class_init, }; =20 +static void vtd_iommu_memory_region_class_init(ObjectClass *klass, + void *data) +{ + IOMMUMemoryRegionClass *imrc =3D IOMMU_MEMORY_REGION_CLASS(klass); + + imrc->translate =3D vtd_iommu_translate; + imrc->notify_flag_changed =3D vtd_iommu_notify_flag_changed; + imrc->replay =3D vtd_iommu_replay; +} + +static const TypeInfo vtd_iommu_memory_region_info =3D { + .parent =3D TYPE_IOMMU_MEMORY_REGION, + .name =3D TYPE_INTEL_IOMMU_MEMORY_REGION, + .class_init =3D vtd_iommu_memory_region_class_init, +}; + static void vtd_register_types(void) { type_register_static(&vtd_info); + type_register_static(&vtd_iommu_memory_region_info); } =20 type_init(vtd_register_types) diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index 76a56ae..96e5d0b 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -133,6 +133,8 @@ typedef struct IOMMUState { #define APB_DEVICE(obj) \ OBJECT_CHECK(APBState, (obj), TYPE_APB) =20 +#define TYPE_APB_IOMMU_MEMORY_REGION "pbm-iommu-memory-region" + typedef struct APBState { PCIHostState parent_obj; =20 @@ -322,10 +324,6 @@ static IOMMUTLBEntry pbm_translate_iommu(IOMMUMemoryRe= gion *iommu, hwaddr addr, return ret; } =20 -static MemoryRegionIOMMUOps pbm_iommu_ops =3D { - .translate =3D pbm_translate_iommu, -}; - static void iommu_config_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { @@ -697,7 +695,8 @@ PCIBus *pci_apb_init(hwaddr special_base, is =3D &d->iommu; memset(is, 0, sizeof(IOMMUState)); =20 - memory_region_init_iommu(&is->iommu, OBJECT(dev), &pbm_iommu_ops, + memory_region_init_iommu(&is->iommu, sizeof(is->iommu), + TYPE_APB_IOMMU_MEMORY_REGION, OBJECT(dev), "iommu-apb", UINT64_MAX); address_space_init(&is->iommu_as, MEMORY_REGION(&is->iommu), "pbm-as"); pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, is); @@ -860,11 +859,25 @@ static const TypeInfo pbm_pci_bridge_info =3D { .class_init =3D pbm_pci_bridge_class_init, }; =20 +static void pbm_iommu_memory_region_class_init(ObjectClass *klass, void *d= ata) +{ + IOMMUMemoryRegionClass *imrc =3D IOMMU_MEMORY_REGION_CLASS(klass); + + imrc->translate =3D pbm_translate_iommu; +} + +static const TypeInfo pbm_iommu_memory_region_info =3D { + .parent =3D TYPE_IOMMU_MEMORY_REGION, + .name =3D TYPE_APB_IOMMU_MEMORY_REGION, + .class_init =3D pbm_iommu_memory_region_class_init, +}; + static void pbm_register_types(void) { type_register_static(&pbm_host_info); type_register_static(&pbm_pci_host_info); type_register_static(&pbm_pci_bridge_info); + type_register_static(&pbm_iommu_memory_region_info); } =20 type_init(pbm_register_types) diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c index 6b6ced5..d07b4b4 100644 --- a/hw/ppc/spapr_iommu.c +++ b/hw/ppc/spapr_iommu.c @@ -248,12 +248,6 @@ static const VMStateDescription vmstate_spapr_tce_tabl= e =3D { } }; =20 -static MemoryRegionIOMMUOps spapr_iommu_ops =3D { - .translate =3D spapr_tce_translate_iommu, - .get_min_page_size =3D spapr_tce_get_min_page_size, - .notify_flag_changed =3D spapr_tce_notify_flag_changed, -}; - static int spapr_tce_table_realize(DeviceState *dev) { sPAPRTCETable *tcet =3D SPAPR_TCE_TABLE(dev); @@ -266,7 +260,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(&tcet->iommu, sizeof(tcet->iommu), + TYPE_SPAPR_IOMMU_MEMORY_REGION, + tcetobj, tmp, 0); =20 QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list); =20 @@ -639,9 +635,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 *klass, void = *data) +{ + IOMMUMemoryRegionClass *imrc =3D IOMMU_MEMORY_REGION_CLASS(klass); + + imrc->translate =3D spapr_tce_translate_iommu; + imrc->get_min_page_size =3D spapr_tce_get_min_page_size; + imrc->notify_flag_changed =3D spapr_tce_notify_flag_changed; +} + +static const TypeInfo spapr_iommu_memory_region_info =3D { + .parent =3D TYPE_IOMMU_MEMORY_REGION, + .name =3D TYPE_SPAPR_IOMMU_MEMORY_REGION, + .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); diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index e4fc82c..903b3ca 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -407,10 +407,6 @@ static IOMMUTLBEntry s390_translate_iommu(IOMMUMemoryR= egion *mr, hwaddr addr, return ret; } =20 -static const MemoryRegionIOMMUOps s390_iommu_ops =3D { - .translate =3D s390_translate_iommu, -}; - static S390PCIIOMMU *s390_pci_get_iommu(S390pciState *s, PCIBus *bus, int devfn) { @@ -522,8 +518,9 @@ static const MemoryRegionOps s390_msi_ctrl_ops =3D { void s390_pci_iommu_enable(S390PCIIOMMU *iommu) { char *name =3D g_strdup_printf("iommu-s390-%04x", iommu->pbdev->uid); - memory_region_init_iommu(&iommu->iommu_mr, OBJECT(&iommu->mr), - &s390_iommu_ops, name, iommu->pal + 1); + memory_region_init_iommu(&iommu->iommu_mr, sizeof(iommu->iommu_mr), + TYPE_S390_IOMMU_MEMORY_REGION, OBJECT(&iommu-= >mr), + name, iommu->pal + 1); iommu->enabled =3D true; memory_region_add_subregion(&iommu->mr, 0, MEMORY_REGION(&iommu->iommu= _mr)); g_free(name); @@ -1058,12 +1055,26 @@ static TypeInfo s390_pci_iommu_info =3D { .instance_size =3D sizeof(S390PCIIOMMU), }; =20 +static void s390_iommu_memory_region_class_init(ObjectClass *klass, void *= data) +{ + IOMMUMemoryRegionClass *imrc =3D IOMMU_MEMORY_REGION_CLASS(klass); + + imrc->translate =3D s390_translate_iommu; +} + +static const TypeInfo s390_iommu_memory_region_info =3D { + .parent =3D TYPE_IOMMU_MEMORY_REGION, + .name =3D TYPE_S390_IOMMU_MEMORY_REGION, + .class_init =3D s390_iommu_memory_region_class_init, +}; + static void s390_pci_register_types(void) { type_register_static(&s390_pcihost_info); type_register_static(&s390_pcibus_info); type_register_static(&s390_pci_device_info); type_register_static(&s390_pci_iommu_info); + type_register_static(&s390_iommu_memory_region_info); } =20 type_init(s390_pci_register_types) diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h index 6a599ed..67af2c1 100644 --- a/hw/s390x/s390-pci-bus.h +++ b/hw/s390x/s390-pci-bus.h @@ -24,6 +24,7 @@ #define TYPE_S390_PCI_BUS "s390-pcibus" #define TYPE_S390_PCI_DEVICE "zpci" #define TYPE_S390_PCI_IOMMU "s390-pci-iommu" +#define TYPE_S390_IOMMU_MEMORY_REGION "s390-iommu-memory-region" #define FH_MASK_ENABLE 0x80000000 #define FH_MASK_INSTANCE 0x7f000000 #define FH_MASK_SHM 0x00ff0000 diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index a53c29c..b7beb8c 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -564,6 +564,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_= t r2) hwaddr start, end; IOMMUTLBEntry entry; IOMMUMemoryRegion *iommu_mr; + IOMMUMemoryRegionClass *imrc; =20 cpu_synchronize_state(CPU(cpu)); =20 @@ -623,8 +624,10 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8= _t r2) } =20 iommu_mr =3D &iommu->iommu_mr; + imrc =3D IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr); + while (start < end) { - entry =3D iommu_mr->iommu_ops->translate(iommu_mr, start, IOMMU_NO= NE); + entry =3D imrc->translate(iommu_mr, start, IOMMU_NONE); =20 if (!entry.translated_addr) { pbdev->state =3D ZPCI_FS_ERROR; diff --git a/include/exec/memory.h b/include/exec/memory.h index 92980ab..b796601 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -25,6 +25,7 @@ #include "qemu/notify.h" #include "qom/object.h" #include "qemu/rcu.h" +#include "hw/qdev-core.h" =20 #define RAM_ADDR_INVALID (~(ram_addr_t)0) =20 @@ -38,6 +39,12 @@ #define TYPE_IOMMU_MEMORY_REGION "qemu:iommu-memory-region" #define IOMMU_MEMORY_REGION(obj) \ OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_IOMMU_MEMORY_REGION) +#define IOMMU_MEMORY_REGION_CLASS(klass) \ + OBJECT_CLASS_CHECK(IOMMUMemoryRegionClass, (klass), \ + TYPE_IOMMU_MEMORY_REGION) +#define IOMMU_MEMORY_REGION_GET_CLASS(obj) \ + OBJECT_GET_CLASS(IOMMUMemoryRegionClass, (obj), \ + TYPE_IOMMU_MEMORY_REGION) =20 typedef struct MemoryRegionOps MemoryRegionOps; typedef struct MemoryRegionMmio MemoryRegionMmio; @@ -193,9 +200,10 @@ struct MemoryRegionOps { const MemoryRegionMmio old_mmio; }; =20 -typedef struct MemoryRegionIOMMUOps MemoryRegionIOMMUOps; +typedef struct IOMMUMemoryRegionClass { + /* private */ + struct DeviceClass parent_class; =20 -struct MemoryRegionIOMMUOps { /* * Return a TLB entry that contains a given address. Flag should * be the access permission of this translation operation. We can @@ -212,7 +220,7 @@ struct MemoryRegionIOMMUOps { IOMMUNotifierFlag new_flags); /* Set this up to provide customized IOMMU replay function */ void (*replay)(IOMMUMemoryRegion *iommu, IOMMUNotifier *notifier); -}; +} IOMMUMemoryRegionClass; =20 typedef struct CoalescedMemoryRange CoalescedMemoryRange; typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd; @@ -261,7 +269,6 @@ struct MemoryRegion { struct IOMMUMemoryRegion { MemoryRegion parent_obj; =20 - const MemoryRegionIOMMUOps *iommu_ops; QLIST_HEAD(, IOMMUNotifier) iommu_notify; IOMMUNotifierFlag iommu_notify_flags; }; @@ -622,21 +629,24 @@ static inline void memory_region_init_reservation(Mem= oryRegion *mr, } =20 /** - * memory_region_init_iommu: Initialize a memory region that translates - * addresses + * memory_region_init_iommu: Initialize a memory region of a custom type + * that translates addresses * * An IOMMU region translates addresses and forwards accesses to a target * memory region. * - * @iommu_mr: the #IOMMUMemoryRegion to be initialized + * @typename: QOM class name + * @_iommu_mr: the #IOMMUMemoryRegion to be initialized + * @instance_size: the IOMMUMemoryRegion subclass instance size * @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(IOMMUMemoryRegion *iommu_mr, - struct Object *owner, - const MemoryRegionIOMMUOps *ops, +void memory_region_init_iommu(void *_iommu_mr, + size_t instance_size, + const char *mrtypename, + Object *owner, const char *name, uint64_t size); =20 @@ -707,6 +717,21 @@ static inline IOMMUMemoryRegion *memory_region_get_iom= mu(MemoryRegion *mr) return NULL; } =20 +/** + * memory_region_get_iommu_class_nocheck: returns iommu memory region class + * if an iommu or NULL if not + * + * Returns pointer to IOMMUMemoryRegioniClass if a memory region is an iom= mu, + * otherwise NULL. This is fast path avoinding QOM checking, use with caut= ion. + * + * @mr: the memory region being queried + */ +static inline IOMMUMemoryRegionClass *memory_region_get_iommu_class_nochec= k( + IOMMUMemoryRegion *iommu_mr) +{ + return (IOMMUMemoryRegionClass *) (((Object *)iommu_mr)->class); +} + #define memory_region_is_iommu(mr) (memory_region_get_iommu(mr) !=3D NULL) =20 /** diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h index 45fba4f..08d8a26 100644 --- a/include/hw/i386/intel_iommu.h +++ b/include/hw/i386/intel_iommu.h @@ -32,6 +32,8 @@ #define INTEL_IOMMU_DEVICE(obj) \ OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE) =20 +#define TYPE_INTEL_IOMMU_MEMORY_REGION "intel-iommu-iommu-memory-region" + /* DMAR Hardware Unit Definition address (IOMMU unit) */ #define Q35_HOST_BRIDGE_IOMMU_ADDR 0xfed90000ULL =20 @@ -289,7 +291,6 @@ struct IntelIOMMUState { uint32_t context_cache_gen; /* Should be in [1,MAX] */ GHashTable *iotlb; /* IOTLB */ =20 - MemoryRegionIOMMUOps iommu_ops; GHashTable *vtd_as_by_busptr; /* VTDBus objects indexed by PCIBus* r= eference */ VTDBus *vtd_as_by_bus_num[VTD_PCI_BUS_MAX]; /* VTDBus objects indexed = by bus number */ /* list of registered notifiers */ diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index b353dff..5f708ee 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -582,6 +582,10 @@ typedef struct sPAPRTCETable sPAPRTCETable; #define SPAPR_TCE_TABLE(obj) \ OBJECT_CHECK(sPAPRTCETable, (obj), TYPE_SPAPR_TCE_TABLE) =20 +#define TYPE_SPAPR_IOMMU_MEMORY_REGION "spapr-iommu-memory-region" +#define SPAPR_IOMMU_MEMORY_REGION(obj) \ + OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_SPAPR_IOMMU_MEMORY_REG= ION) + struct sPAPRTCETable { DeviceState parent; uint32_t liobn; diff --git a/memory.c b/memory.c index 45e10e2..69f697c 100644 --- a/memory.c +++ b/memory.c @@ -1506,19 +1506,20 @@ void memory_region_init_rom_device(MemoryRegion *mr, mr->ram_block =3D qemu_ram_alloc(size, mr, errp); } =20 -void memory_region_init_iommu(IOMMUMemoryRegion *iommu_mr, +void memory_region_init_iommu(void *_iommu_mr, + size_t instance_size, + const char *mrtypename, Object *owner, - const MemoryRegionIOMMUOps *ops, const char *name, uint64_t size) { + struct IOMMUMemoryRegion *iommu_mr; struct MemoryRegion *mr; =20 - object_initialize(iommu_mr, sizeof(*iommu_mr), TYPE_IOMMU_MEMORY_REGIO= N); - mr =3D MEMORY_REGION(iommu_mr); + object_initialize(_iommu_mr, instance_size, mrtypename); + mr =3D MEMORY_REGION(_iommu_mr); memory_region_do_init(mr, owner, name, size); iommu_mr =3D IOMMU_MEMORY_REGION(mr); - iommu_mr->iommu_ops =3D ops, mr->terminates =3D true; /* then re-forwards */ QLIST_INIT(&iommu_mr->iommu_notify); iommu_mr->iommu_notify_flags =3D IOMMU_NOTIFIER_NONE; @@ -1620,16 +1621,16 @@ static void memory_region_update_iommu_notify_flags= (IOMMUMemoryRegion *iommu_mr) { IOMMUNotifierFlag flags =3D IOMMU_NOTIFIER_NONE; IOMMUNotifier *iommu_notifier; + IOMMUMemoryRegionClass *imrc =3D IOMMU_MEMORY_REGION_GET_CLASS(iommu_m= r); =20 IOMMU_NOTIFIER_FOREACH(iommu_notifier, iommu_mr) { flags |=3D iommu_notifier->notifier_flags; } =20 - if (flags !=3D iommu_mr->iommu_notify_flags && - iommu_mr->iommu_ops->notify_flag_changed) { - iommu_mr->iommu_ops->notify_flag_changed(iommu_mr, - iommu_mr->iommu_notify_fla= gs, - flags); + if (flags !=3D iommu_mr->iommu_notify_flags && imrc->notify_flag_chang= ed) { + imrc->notify_flag_changed(iommu_mr, + iommu_mr->iommu_notify_flags, + flags); } =20 iommu_mr->iommu_notify_flags =3D flags; @@ -1655,8 +1656,10 @@ void memory_region_register_iommu_notifier(MemoryReg= ion *mr, =20 uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommu_mr) { - if (iommu_mr->iommu_ops && iommu_mr->iommu_ops->get_min_page_size) { - return iommu_mr->iommu_ops->get_min_page_size(iommu_mr); + IOMMUMemoryRegionClass *imrc =3D IOMMU_MEMORY_REGION_GET_CLASS(iommu_m= r); + + if (imrc->get_min_page_size) { + return imrc->get_min_page_size(iommu_mr); } return TARGET_PAGE_SIZE; } @@ -1664,19 +1667,20 @@ uint64_t memory_region_iommu_get_min_page_size(IOMM= UMemoryRegion *iommu_mr) void memory_region_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier= *n) { MemoryRegion *mr =3D MEMORY_REGION(iommu_mr); + IOMMUMemoryRegionClass *imrc =3D IOMMU_MEMORY_REGION_GET_CLASS(iommu_m= r); hwaddr addr, granularity; IOMMUTLBEntry iotlb; =20 /* If the IOMMU has its own replay callback, override */ - if (iommu_mr->iommu_ops->replay) { - iommu_mr->iommu_ops->replay(iommu_mr, n); + if (imrc->replay) { + imrc->replay(iommu_mr, n); return; } =20 granularity =3D memory_region_iommu_get_min_page_size(iommu_mr); =20 for (addr =3D 0; addr < memory_region_size(mr); addr +=3D granularity)= { - iotlb =3D iommu_mr->iommu_ops->translate(iommu_mr, addr, IOMMU_NON= E); + iotlb =3D imrc->translate(iommu_mr, addr, IOMMU_NONE); if (iotlb.perm !=3D IOMMU_NONE) { n->notify(n, &iotlb); } @@ -2855,8 +2859,10 @@ static const TypeInfo memory_region_info =3D { static const TypeInfo iommu_memory_region_info =3D { .parent =3D TYPE_MEMORY_REGION, .name =3D TYPE_IOMMU_MEMORY_REGION, + .class_size =3D sizeof(IOMMUMemoryRegionClass), .instance_size =3D sizeof(IOMMUMemoryRegion), .instance_init =3D iommu_memory_region_initfn, + .abstract =3D true, }; =20 static void memory_register_types(void) --=20 1.8.3.1