memory/iommu: introduce IOMMUMemoryRegionClass
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 <aik@ozlabs.ru> Message-Id: <20170711035620.4232-3-aik@ozlabs.ru> Acked-by: Cornelia Huck <cohuck@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
		
							parent
							
								
									3df9d74806
								
							
						
					
					
						commit
						1221a47467
					
				
							
								
								
									
										6
									
								
								exec.c
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								exec.c
									
									
									
									
									
								
							| @ -481,6 +481,7 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as, | ||||
|     IOMMUTLBEntry iotlb; | ||||
|     MemoryRegionSection *section; | ||||
|     IOMMUMemoryRegion *iommu_mr; | ||||
|     IOMMUMemoryRegionClass *imrc; | ||||
| 
 | ||||
|     for (;;) { | ||||
|         AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch); | ||||
| @ -490,9 +491,10 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as, | ||||
|         if (!iommu_mr) { | ||||
|             break; | ||||
|         } | ||||
|         imrc = memory_region_get_iommu_class_nocheck(iommu_mr); | ||||
| 
 | ||||
|         iotlb = iommu_mr->iommu_ops->translate(iommu_mr, addr, is_write ? | ||||
|                                                IOMMU_WO : IOMMU_RO); | ||||
|         iotlb = imrc->translate(iommu_mr, addr, is_write ? | ||||
|                                 IOMMU_WO : IOMMU_RO); | ||||
|         addr = ((iotlb.translated_addr & ~iotlb.addr_mask) | ||||
|                 | (addr & iotlb.addr_mask)); | ||||
|         *plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1); | ||||
|  | ||||
| @ -17,6 +17,7 @@ | ||||
| 
 | ||||
| 
 | ||||
| #define TYPE_TYPHOON_PCI_HOST_BRIDGE "typhoon-pcihost" | ||||
| #define TYPE_TYPHOON_IOMMU_MEMORY_REGION "typhoon-iommu-memory-region" | ||||
| 
 | ||||
| typedef struct TyphoonCchip { | ||||
|     MemoryRegion region; | ||||
| @ -725,10 +726,6 @@ static IOMMUTLBEntry typhoon_translate_iommu(IOMMUMemoryRegion *iommu, | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static const MemoryRegionIOMMUOps typhoon_iommu_ops = { | ||||
|     .translate = typhoon_translate_iommu, | ||||
| }; | ||||
| 
 | ||||
| static AddressSpace *typhoon_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn) | ||||
| { | ||||
|     TyphoonState *s = opaque; | ||||
| @ -892,7 +889,8 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, | ||||
|     qdev_init_nofail(dev); | ||||
| 
 | ||||
|     /* Host memory as seen from the PCI side, via the IOMMU.  */ | ||||
|     memory_region_init_iommu(&s->pchip.iommu, OBJECT(s), &typhoon_iommu_ops, | ||||
|     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 = { | ||||
|     .class_init    = typhoon_pcihost_class_init, | ||||
| }; | ||||
| 
 | ||||
| static void typhoon_iommu_memory_region_class_init(ObjectClass *klass, | ||||
|                                                    void *data) | ||||
| { | ||||
|     IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass); | ||||
| 
 | ||||
|     imrc->translate = typhoon_translate_iommu; | ||||
| } | ||||
| 
 | ||||
| static const TypeInfo typhoon_iommu_memory_region_info = { | ||||
|     .parent = TYPE_IOMMU_MEMORY_REGION, | ||||
|     .name = TYPE_TYPHOON_IOMMU_MEMORY_REGION, | ||||
|     .class_init = 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); | ||||
| } | ||||
| 
 | ||||
| type_init(typhoon_register_types) | ||||
|  | ||||
| @ -54,6 +54,8 @@ typedef struct dma_pagetable_entry { | ||||
| #define RC4030(obj) \ | ||||
|     OBJECT_CHECK(rc4030State, (obj), TYPE_RC4030) | ||||
| 
 | ||||
| #define TYPE_RC4030_IOMMU_MEMORY_REGION "rc4030-iommu-memory-region" | ||||
| 
 | ||||
| typedef struct rc4030State | ||||
| { | ||||
|     SysBusDevice parent; | ||||
| @ -516,10 +518,6 @@ static IOMMUTLBEntry rc4030_dma_translate(IOMMUMemoryRegion *iommu, hwaddr addr, | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static const MemoryRegionIOMMUOps rc4030_dma_ops = { | ||||
|     .translate = rc4030_dma_translate, | ||||
| }; | ||||
| 
 | ||||
| static void rc4030_reset(DeviceState *dev) | ||||
| { | ||||
|     rc4030State *s = RC4030(dev); | ||||
| @ -677,8 +675,9 @@ static void rc4030_realize(DeviceState *dev, Error **errp) | ||||
|     memory_region_init_io(&s->iomem_jazzio, NULL, &jazzio_ops, s, | ||||
|                           "rc4030.jazzio", 0x00001000); | ||||
| 
 | ||||
|     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"); | ||||
| } | ||||
| 
 | ||||
| @ -710,9 +709,24 @@ static const TypeInfo rc4030_info = { | ||||
|     .class_init = rc4030_class_init, | ||||
| }; | ||||
| 
 | ||||
| static void rc4030_iommu_memory_region_class_init(ObjectClass *klass, | ||||
|                                                   void *data) | ||||
| { | ||||
|     IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass); | ||||
| 
 | ||||
|     imrc->translate = rc4030_dma_translate; | ||||
| } | ||||
| 
 | ||||
| static const TypeInfo rc4030_iommu_memory_region_info = { | ||||
|     .parent = TYPE_IOMMU_MEMORY_REGION, | ||||
|     .name = TYPE_RC4030_IOMMU_MEMORY_REGION, | ||||
|     .class_init = 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); | ||||
| } | ||||
| 
 | ||||
| type_init(rc4030_register_types) | ||||
|  | ||||
| @ -1044,8 +1044,11 @@ static AddressSpace *amdvi_host_dma_iommu(PCIBus *bus, void *opaque, int devfn) | ||||
|         iommu_as[devfn]->devfn = (uint8_t)devfn; | ||||
|         iommu_as[devfn]->iommu_state = s; | ||||
| 
 | ||||
|         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); | ||||
| 
 | ||||
|     s->iommu_ops.translate = amdvi_translate; | ||||
|     s->iommu_ops.notify_flag_changed = amdvi_iommu_notify_flag_changed; | ||||
|     s->devtab_len = 0; | ||||
|     s->cmdbuf_len = 0; | ||||
|     s->cmdbuf_head = 0; | ||||
| @ -1228,10 +1229,25 @@ static const TypeInfo amdviPCI = { | ||||
|     .instance_size = sizeof(AMDVIPCIState), | ||||
| }; | ||||
| 
 | ||||
| static void amdvi_iommu_memory_region_class_init(ObjectClass *klass, void *data) | ||||
| { | ||||
|     IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass); | ||||
| 
 | ||||
|     imrc->translate = amdvi_translate; | ||||
|     imrc->notify_flag_changed = amdvi_iommu_notify_flag_changed; | ||||
| } | ||||
| 
 | ||||
| static const TypeInfo amdvi_iommu_memory_region_info = { | ||||
|     .parent = TYPE_IOMMU_MEMORY_REGION, | ||||
|     .name = TYPE_AMD_IOMMU_MEMORY_REGION, | ||||
|     .class_init = 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); | ||||
| } | ||||
| 
 | ||||
| type_init(amdviPCI_register_types); | ||||
|  | ||||
| @ -220,6 +220,8 @@ | ||||
| 
 | ||||
| #define TYPE_AMD_IOMMU_PCI "AMDVI-PCI" | ||||
| 
 | ||||
| #define TYPE_AMD_IOMMU_MEMORY_REGION "amd-iommu-iommu-memory-region" | ||||
| 
 | ||||
| typedef struct AMDVIAddressSpace AMDVIAddressSpace; | ||||
| 
 | ||||
| /* 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; | ||||
| 
 | ||||
|     /* IOMMU function */ | ||||
|     MemoryRegionIOMMUOps iommu_ops; | ||||
| 
 | ||||
|     /* for each served device */ | ||||
|     AMDVIAddressSpace **address_spaces[PCI_BUS_MAX]; | ||||
| 
 | ||||
|  | ||||
| @ -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->iommu), | ||||
|                                  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); | ||||
| 
 | ||||
|     s->iommu_ops.translate = vtd_iommu_translate; | ||||
|     s->iommu_ops.notify_flag_changed = vtd_iommu_notify_flag_changed; | ||||
|     s->iommu_ops.replay = vtd_iommu_replay; | ||||
|     s->root = 0; | ||||
|     s->root_extended = false; | ||||
|     s->dmar_enabled = false; | ||||
| @ -3074,9 +3072,26 @@ static const TypeInfo vtd_info = { | ||||
|     .class_init    = vtd_class_init, | ||||
| }; | ||||
| 
 | ||||
| static void vtd_iommu_memory_region_class_init(ObjectClass *klass, | ||||
|                                                      void *data) | ||||
| { | ||||
|     IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass); | ||||
| 
 | ||||
|     imrc->translate = vtd_iommu_translate; | ||||
|     imrc->notify_flag_changed = vtd_iommu_notify_flag_changed; | ||||
|     imrc->replay = vtd_iommu_replay; | ||||
| } | ||||
| 
 | ||||
| static const TypeInfo vtd_iommu_memory_region_info = { | ||||
|     .parent = TYPE_IOMMU_MEMORY_REGION, | ||||
|     .name = TYPE_INTEL_IOMMU_MEMORY_REGION, | ||||
|     .class_init = 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); | ||||
| } | ||||
| 
 | ||||
| type_init(vtd_register_types) | ||||
|  | ||||
| @ -133,6 +133,8 @@ typedef struct IOMMUState { | ||||
| #define APB_DEVICE(obj) \ | ||||
|     OBJECT_CHECK(APBState, (obj), TYPE_APB) | ||||
| 
 | ||||
| #define TYPE_APB_IOMMU_MEMORY_REGION "pbm-iommu-memory-region" | ||||
| 
 | ||||
| typedef struct APBState { | ||||
|     PCIHostState parent_obj; | ||||
| 
 | ||||
| @ -322,10 +324,6 @@ static IOMMUTLBEntry pbm_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr, | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static MemoryRegionIOMMUOps pbm_iommu_ops = { | ||||
|     .translate = 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 = &d->iommu; | ||||
|     memset(is, 0, sizeof(IOMMUState)); | ||||
| 
 | ||||
|     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 = { | ||||
|     .class_init    = pbm_pci_bridge_class_init, | ||||
| }; | ||||
| 
 | ||||
| static void pbm_iommu_memory_region_class_init(ObjectClass *klass, void *data) | ||||
| { | ||||
|     IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass); | ||||
| 
 | ||||
|     imrc->translate = pbm_translate_iommu; | ||||
| } | ||||
| 
 | ||||
| static const TypeInfo pbm_iommu_memory_region_info = { | ||||
|     .parent = TYPE_IOMMU_MEMORY_REGION, | ||||
|     .name = TYPE_APB_IOMMU_MEMORY_REGION, | ||||
|     .class_init = 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); | ||||
| } | ||||
| 
 | ||||
| type_init(pbm_register_types) | ||||
|  | ||||
| @ -248,12 +248,6 @@ static const VMStateDescription vmstate_spapr_tce_table = { | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| static MemoryRegionIOMMUOps spapr_iommu_ops = { | ||||
|     .translate = spapr_tce_translate_iommu, | ||||
|     .get_min_page_size = spapr_tce_get_min_page_size, | ||||
|     .notify_flag_changed = spapr_tce_notify_flag_changed, | ||||
| }; | ||||
| 
 | ||||
| static int spapr_tce_table_realize(DeviceState *dev) | ||||
| { | ||||
|     sPAPRTCETable *tcet = 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); | ||||
| 
 | ||||
|     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); | ||||
| 
 | ||||
|     QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list); | ||||
| 
 | ||||
| @ -639,9 +635,25 @@ static TypeInfo spapr_tce_table_info = { | ||||
|     .class_init = spapr_tce_table_class_init, | ||||
| }; | ||||
| 
 | ||||
| static void spapr_iommu_memory_region_class_init(ObjectClass *klass, void *data) | ||||
| { | ||||
|     IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass); | ||||
| 
 | ||||
|     imrc->translate = spapr_tce_translate_iommu; | ||||
|     imrc->get_min_page_size = spapr_tce_get_min_page_size; | ||||
|     imrc->notify_flag_changed = spapr_tce_notify_flag_changed; | ||||
| } | ||||
| 
 | ||||
| static const TypeInfo spapr_iommu_memory_region_info = { | ||||
|     .parent = TYPE_IOMMU_MEMORY_REGION, | ||||
|     .name = TYPE_SPAPR_IOMMU_MEMORY_REGION, | ||||
|     .class_init = 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); | ||||
| } | ||||
| 
 | ||||
| type_init(register_types); | ||||
|  | ||||
| @ -407,10 +407,6 @@ static IOMMUTLBEntry s390_translate_iommu(IOMMUMemoryRegion *mr, hwaddr addr, | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static const MemoryRegionIOMMUOps s390_iommu_ops = { | ||||
|     .translate = 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 = { | ||||
| void s390_pci_iommu_enable(S390PCIIOMMU *iommu) | ||||
| { | ||||
|     char *name = 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 = 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 = { | ||||
|     .instance_size = sizeof(S390PCIIOMMU), | ||||
| }; | ||||
| 
 | ||||
| static void s390_iommu_memory_region_class_init(ObjectClass *klass, void *data) | ||||
| { | ||||
|     IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass); | ||||
| 
 | ||||
|     imrc->translate = s390_translate_iommu; | ||||
| } | ||||
| 
 | ||||
| static const TypeInfo s390_iommu_memory_region_info = { | ||||
|     .parent = TYPE_IOMMU_MEMORY_REGION, | ||||
|     .name = TYPE_S390_IOMMU_MEMORY_REGION, | ||||
|     .class_init = 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); | ||||
| } | ||||
| 
 | ||||
| type_init(s390_pci_register_types) | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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; | ||||
| 
 | ||||
|     cpu_synchronize_state(CPU(cpu)); | ||||
| 
 | ||||
| @ -623,8 +624,10 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) | ||||
|     } | ||||
| 
 | ||||
|     iommu_mr = &iommu->iommu_mr; | ||||
|     imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr); | ||||
| 
 | ||||
|     while (start < end) { | ||||
|         entry = iommu_mr->iommu_ops->translate(iommu_mr, start, IOMMU_NONE); | ||||
|         entry = imrc->translate(iommu_mr, start, IOMMU_NONE); | ||||
| 
 | ||||
|         if (!entry.translated_addr) { | ||||
|             pbdev->state = ZPCI_FS_ERROR; | ||||
|  | ||||
| @ -25,6 +25,7 @@ | ||||
| #include "qemu/notify.h" | ||||
| #include "qom/object.h" | ||||
| #include "qemu/rcu.h" | ||||
| #include "hw/qdev-core.h" | ||||
| 
 | ||||
| #define RAM_ADDR_INVALID (~(ram_addr_t)0) | ||||
| 
 | ||||
| @ -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) | ||||
| 
 | ||||
| typedef struct MemoryRegionOps MemoryRegionOps; | ||||
| typedef struct MemoryRegionMmio MemoryRegionMmio; | ||||
| @ -193,9 +200,10 @@ struct MemoryRegionOps { | ||||
|     const MemoryRegionMmio old_mmio; | ||||
| }; | ||||
| 
 | ||||
| typedef struct MemoryRegionIOMMUOps MemoryRegionIOMMUOps; | ||||
| typedef struct IOMMUMemoryRegionClass { | ||||
|     /* private */ | ||||
|     struct DeviceClass parent_class; | ||||
| 
 | ||||
| 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; | ||||
| 
 | ||||
| typedef struct CoalescedMemoryRange CoalescedMemoryRange; | ||||
| typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd; | ||||
| @ -261,7 +269,6 @@ struct MemoryRegion { | ||||
| struct IOMMUMemoryRegion { | ||||
|     MemoryRegion parent_obj; | ||||
| 
 | ||||
|     const MemoryRegionIOMMUOps *iommu_ops; | ||||
|     QLIST_HEAD(, IOMMUNotifier) iommu_notify; | ||||
|     IOMMUNotifierFlag iommu_notify_flags; | ||||
| }; | ||||
| @ -622,21 +629,24 @@ static inline void memory_region_init_reservation(MemoryRegion *mr, | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * 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); | ||||
| 
 | ||||
| @ -707,6 +717,21 @@ static inline IOMMUMemoryRegion *memory_region_get_iommu(MemoryRegion *mr) | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * 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 iommu, | ||||
|  * otherwise NULL. This is fast path avoinding QOM checking, use with caution. | ||||
|  * | ||||
|  * @mr: the memory region being queried | ||||
|  */ | ||||
| static inline IOMMUMemoryRegionClass *memory_region_get_iommu_class_nocheck( | ||||
|         IOMMUMemoryRegion *iommu_mr) | ||||
| { | ||||
|     return (IOMMUMemoryRegionClass *) (((Object *)iommu_mr)->class); | ||||
| } | ||||
| 
 | ||||
| #define memory_region_is_iommu(mr) (memory_region_get_iommu(mr) != NULL) | ||||
| 
 | ||||
| /**
 | ||||
|  | ||||
| @ -32,6 +32,8 @@ | ||||
| #define INTEL_IOMMU_DEVICE(obj) \ | ||||
|      OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE) | ||||
| 
 | ||||
| #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 | ||||
| 
 | ||||
| @ -289,7 +291,6 @@ struct IntelIOMMUState { | ||||
|     uint32_t context_cache_gen;     /* Should be in [1,MAX] */ | ||||
|     GHashTable *iotlb;              /* IOTLB */ | ||||
| 
 | ||||
|     MemoryRegionIOMMUOps iommu_ops; | ||||
|     GHashTable *vtd_as_by_busptr;   /* VTDBus objects indexed by PCIBus* reference */ | ||||
|     VTDBus *vtd_as_by_bus_num[VTD_PCI_BUS_MAX]; /* VTDBus objects indexed by bus number */ | ||||
|     /* list of registered notifiers */ | ||||
|  | ||||
| @ -582,6 +582,10 @@ typedef struct sPAPRTCETable sPAPRTCETable; | ||||
| #define SPAPR_TCE_TABLE(obj) \ | ||||
|     OBJECT_CHECK(sPAPRTCETable, (obj), TYPE_SPAPR_TCE_TABLE) | ||||
| 
 | ||||
| #define TYPE_SPAPR_IOMMU_MEMORY_REGION "spapr-iommu-memory-region" | ||||
| #define SPAPR_IOMMU_MEMORY_REGION(obj) \ | ||||
|         OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_SPAPR_IOMMU_MEMORY_REGION) | ||||
| 
 | ||||
| struct sPAPRTCETable { | ||||
|     DeviceState parent; | ||||
|     uint32_t liobn; | ||||
|  | ||||
							
								
								
									
										36
									
								
								memory.c
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								memory.c
									
									
									
									
									
								
							| @ -1506,19 +1506,20 @@ void memory_region_init_rom_device(MemoryRegion *mr, | ||||
|     mr->ram_block = qemu_ram_alloc(size, mr, errp); | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| 
 | ||||
|     object_initialize(iommu_mr, sizeof(*iommu_mr), TYPE_IOMMU_MEMORY_REGION); | ||||
|     mr = MEMORY_REGION(iommu_mr); | ||||
|     object_initialize(_iommu_mr, instance_size, mrtypename); | ||||
|     mr = MEMORY_REGION(_iommu_mr); | ||||
|     memory_region_do_init(mr, owner, name, size); | ||||
|     iommu_mr = IOMMU_MEMORY_REGION(mr); | ||||
|     iommu_mr->iommu_ops = ops, | ||||
|     mr->terminates = true;  /* then re-forwards */ | ||||
|     QLIST_INIT(&iommu_mr->iommu_notify); | ||||
|     iommu_mr->iommu_notify_flags = IOMMU_NOTIFIER_NONE; | ||||
| @ -1620,16 +1621,16 @@ static void memory_region_update_iommu_notify_flags(IOMMUMemoryRegion *iommu_mr) | ||||
| { | ||||
|     IOMMUNotifierFlag flags = IOMMU_NOTIFIER_NONE; | ||||
|     IOMMUNotifier *iommu_notifier; | ||||
|     IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr); | ||||
| 
 | ||||
|     IOMMU_NOTIFIER_FOREACH(iommu_notifier, iommu_mr) { | ||||
|         flags |= iommu_notifier->notifier_flags; | ||||
|     } | ||||
| 
 | ||||
|     if (flags != 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_flags, | ||||
|                                                 flags); | ||||
|     if (flags != iommu_mr->iommu_notify_flags && imrc->notify_flag_changed) { | ||||
|         imrc->notify_flag_changed(iommu_mr, | ||||
|                                   iommu_mr->iommu_notify_flags, | ||||
|                                   flags); | ||||
|     } | ||||
| 
 | ||||
|     iommu_mr->iommu_notify_flags = flags; | ||||
| @ -1655,8 +1656,10 @@ void memory_region_register_iommu_notifier(MemoryRegion *mr, | ||||
| 
 | ||||
| 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 = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr); | ||||
| 
 | ||||
|     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(IOMMUMemoryRegion *iommu_mr) | ||||
| void memory_region_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n) | ||||
| { | ||||
|     MemoryRegion *mr = MEMORY_REGION(iommu_mr); | ||||
|     IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr); | ||||
|     hwaddr addr, granularity; | ||||
|     IOMMUTLBEntry iotlb; | ||||
| 
 | ||||
|     /* 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; | ||||
|     } | ||||
| 
 | ||||
|     granularity = memory_region_iommu_get_min_page_size(iommu_mr); | ||||
| 
 | ||||
|     for (addr = 0; addr < memory_region_size(mr); addr += granularity) { | ||||
|         iotlb = iommu_mr->iommu_ops->translate(iommu_mr, addr, IOMMU_NONE); | ||||
|         iotlb = imrc->translate(iommu_mr, addr, IOMMU_NONE); | ||||
|         if (iotlb.perm != IOMMU_NONE) { | ||||
|             n->notify(n, &iotlb); | ||||
|         } | ||||
| @ -2855,8 +2859,10 @@ static const TypeInfo memory_region_info = { | ||||
| static const TypeInfo iommu_memory_region_info = { | ||||
|     .parent             = TYPE_MEMORY_REGION, | ||||
|     .name               = TYPE_IOMMU_MEMORY_REGION, | ||||
|     .class_size         = sizeof(IOMMUMemoryRegionClass), | ||||
|     .instance_size      = sizeof(IOMMUMemoryRegion), | ||||
|     .instance_init      = iommu_memory_region_initfn, | ||||
|     .abstract           = true, | ||||
| }; | ||||
| 
 | ||||
| static void memory_register_types(void) | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Alexey Kardashevskiy
						Alexey Kardashevskiy