diff --git a/memory-Add-new-fields-in-IOTLBEntry.patch b/memory-Add-new-fields-in-IOTLBEntry.patch new file mode 100644 index 0000000..5a85dbf --- /dev/null +++ b/memory-Add-new-fields-in-IOTLBEntry.patch @@ -0,0 +1,184 @@ +From da97cef20d4ee5a8f3942953836b35e7f7dd974f Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Tue, 4 Sep 2018 08:43:05 -0400 +Subject: [PATCH] memory: Add new fields in IOTLBEntry + +The current IOTLBEntry becomes too simple to interact with +some physical IOMMUs. IOTLBs can be invalidated with different +granularities: domain, pasid, addr. Current IOTLB entry only offers +page selective invalidation. Let's add a granularity field +that conveys this information. + +TLB entries are usually tagged with some ids such as the asid +or pasid. When propagating an invalidation command from the +guest to the host, we need to pass those IDs. + +Also we add a leaf field which indicates, in case of invalidation +notification, whether only cache entries for the last level of +translation are required to be invalidated. + +A flag field is introduced to inform whether those fields are set. + +To enforce all existing users do not use those new fields, +initialize the IOMMUTLBEvents when needed. + +Signed-off-by: Eric Auger +Signed-off-by: Kunkun Jiang +--- + hw/arm/smmu-common.c | 2 +- + hw/arm/smmuv3.c | 2 +- + hw/i386/intel_iommu.c | 6 +++--- + hw/ppc/spapr_iommu.c | 2 +- + hw/virtio/virtio-iommu.c | 4 ++-- + include/exec/memory.h | 36 +++++++++++++++++++++++++++++++++++- + 6 files changed, 43 insertions(+), 9 deletions(-) + +diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c +index 0459850a93..3a1ecf81d6 100644 +--- a/hw/arm/smmu-common.c ++++ b/hw/arm/smmu-common.c +@@ -470,7 +470,7 @@ IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid) + /* Unmap the whole notifier's range */ + static void smmu_unmap_notifier_range(IOMMUNotifier *n) + { +- IOMMUTLBEvent event; ++ IOMMUTLBEvent event = {}; + + event.type = IOMMU_NOTIFIER_UNMAP; + event.entry.target_as = &address_space_memory; +diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c +index 01b60bee49..94e2c658f8 100644 +--- a/hw/arm/smmuv3.c ++++ b/hw/arm/smmuv3.c +@@ -802,7 +802,7 @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr, + uint8_t tg, uint64_t num_pages) + { + SMMUDevice *sdev = container_of(mr, SMMUDevice, iommu); +- IOMMUTLBEvent event; ++ IOMMUTLBEvent event = {}; + uint8_t granule; + + if (!tg) { +diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c +index f584449d8d..fae282ef5e 100644 +--- a/hw/i386/intel_iommu.c ++++ b/hw/i386/intel_iommu.c +@@ -1193,7 +1193,7 @@ static int vtd_page_walk_level(dma_addr_t addr, uint64_t start, + uint32_t offset; + uint64_t slpte; + uint64_t subpage_size, subpage_mask; +- IOMMUTLBEvent event; ++ IOMMUTLBEvent event = {}; + uint64_t iova = start; + uint64_t iova_next; + int ret = 0; +@@ -2425,7 +2425,7 @@ static bool vtd_process_device_iotlb_desc(IntelIOMMUState *s, + VTDInvDesc *inv_desc) + { + VTDAddressSpace *vtd_dev_as; +- IOMMUTLBEvent event; ++ IOMMUTLBEvent event = {}; + struct VTDBus *vtd_bus; + hwaddr addr; + uint64_t sz; +@@ -3481,7 +3481,7 @@ static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n) + size = remain = end - start + 1; + + while (remain >= VTD_PAGE_SIZE) { +- IOMMUTLBEvent event; ++ IOMMUTLBEvent event = {}; + uint64_t mask = dma_aligned_pow2_mask(start, end, s->aw_bits); + uint64_t size = mask + 1; + +diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c +index db01071858..454df25d44 100644 +--- a/hw/ppc/spapr_iommu.c ++++ b/hw/ppc/spapr_iommu.c +@@ -449,7 +449,7 @@ static void spapr_tce_reset(DeviceState *dev) + static target_ulong put_tce_emu(SpaprTceTable *tcet, target_ulong ioba, + target_ulong tce) + { +- IOMMUTLBEvent event; ++ IOMMUTLBEvent event = {}; + hwaddr page_mask = IOMMU_PAGE_MASK(tcet->page_shift); + unsigned long index = (ioba - tcet->bus_offset) >> tcet->page_shift; + +diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c +index 1b23e8e18c..83ed2b82e6 100644 +--- a/hw/virtio/virtio-iommu.c ++++ b/hw/virtio/virtio-iommu.c +@@ -129,7 +129,7 @@ static void virtio_iommu_notify_map(IOMMUMemoryRegion *mr, hwaddr virt_start, + hwaddr virt_end, hwaddr paddr, + uint32_t flags) + { +- IOMMUTLBEvent event; ++ IOMMUTLBEvent event = {}; + IOMMUAccessFlags perm = IOMMU_ACCESS_FLAG(flags & VIRTIO_IOMMU_MAP_F_READ, + flags & VIRTIO_IOMMU_MAP_F_WRITE); + +@@ -154,7 +154,7 @@ static void virtio_iommu_notify_map(IOMMUMemoryRegion *mr, hwaddr virt_start, + static void virtio_iommu_notify_unmap(IOMMUMemoryRegion *mr, hwaddr virt_start, + hwaddr virt_end) + { +- IOMMUTLBEvent event; ++ IOMMUTLBEvent event = {}; + uint64_t delta = virt_end - virt_start; + + if (!(mr->iommu_notify_flags & IOMMU_NOTIFIER_UNMAP)) { +diff --git a/include/exec/memory.h b/include/exec/memory.h +index 20f1b27377..c3180075e1 100644 +--- a/include/exec/memory.h ++++ b/include/exec/memory.h +@@ -113,14 +113,48 @@ typedef enum { + IOMMU_RW = 3, + } IOMMUAccessFlags; + ++/* Granularity of the cache invalidation */ ++typedef enum { ++ IOMMU_INV_GRAN_ADDR = 0, ++ IOMMU_INV_GRAN_PASID, ++ IOMMU_INV_GRAN_DOMAIN, ++} IOMMUInvGranularity; ++ + #define IOMMU_ACCESS_FLAG(r, w) (((r) ? IOMMU_RO : 0) | ((w) ? IOMMU_WO : 0)) + ++/** ++ * struct IOMMUTLBEntry - IOMMU TLB entry ++ * ++ * Structure used when performing a translation or when notifying MAP or ++ * UNMAP (invalidation) events ++ * ++ * @target_as: target address space ++ * @iova: IO virtual address (input) ++ * @translated_addr: translated address (output) ++ * @addr_mask: address mask (0xfff means 4K binding), must be multiple of 2 ++ * @perm: permission flag of the mapping (NONE encodes no mapping or ++ * invalidation notification) ++ * @granularity: granularity of the invalidation ++ * @flags: informs whether the following fields are set ++ * @arch_id: architecture specific ID tagging the TLB ++ * @pasid: PASID tagging the TLB ++ * @leaf: when @perm is NONE, indicates whether only caches for the last ++ * level of translation need to be invalidated. ++ */ + struct IOMMUTLBEntry { + AddressSpace *target_as; + hwaddr iova; + hwaddr translated_addr; +- hwaddr addr_mask; /* 0xfff = 4k translation */ ++ hwaddr addr_mask; + IOMMUAccessFlags perm; ++ IOMMUInvGranularity granularity; ++#define IOMMU_INV_FLAGS_PASID (1 << 0) ++#define IOMMU_INV_FLAGS_ARCHID (1 << 1) ++#define IOMMU_INV_FLAGS_LEAF (1 << 2) ++ uint32_t flags; ++ uint32_t arch_id; ++ uint32_t pasid; ++ bool leaf; + }; + + /* +-- +2.27.0 +