[GIT PULL] dma-mapping fix for Linux 5.19
The following changes since commit a111daf0c53ae91e71fd2bfe7497862d14132e3e: Linux 5.19-rc3 (2022-06-19 15:06:47 -0500) are available in the Git repository at: git://git.infradead.org/users/hch/dma-mapping.git tags/dma-mapping-5.19-2022-06-26 for you to fetch changes up to 3be4562584bba603f33863a00c1c32eecf772ee6: dma-direct: use the correct size for dma_set_encrypted() (2022-06-23 15:26:59 +0200) dma-mapping fixes for Linux 5.19 - pass the correct size to dma_set_encrypted() when freeing memory (Dexuan Cui) Dexuan Cui (1): dma-direct: use the correct size for dma_set_encrypted() kernel/dma/direct.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v2 3/3] arch/*/: remove CONFIG_VIRT_TO_BUS
Arnd, Am 24.06.2022 um 21:10 schrieb Arnd Bergmann: On Sat, Jun 18, 2022 at 3:06 AM Michael Schmitz wrote: Am 18.06.2022 um 00:57 schrieb Arnd Bergmann: All architecture-independent users of virt_to_bus() and bus_to_virt() have been fixed to use the dma mapping interfaces or have been removed now. This means the definitions on most architectures, and the CONFIG_VIRT_TO_BUS symbol are now obsolete and can be removed. The only exceptions to this are a few network and scsi drivers for m68k Amiga and VME machines and ppc32 Macintosh. These drivers work correctly with the old interfaces and are probably not worth changing. The Amiga SCSI drivers are all old WD33C93 ones, and replacing virt_to_bus by virt_to_phys in the dma_setup() function there would cause no functional change at all. Ok, thanks for taking a look here. drivers/vme/bridges/vme_ca91cx42.c hasn't been used at all on m68k (it is a PCI-to-VME bridge chipset driver that would be needed on architectures that natively use a PCI bus). I haven't found anything that selects that driver, so not sure it is even still in use?? It's gone now, Greg has already taken my patches for this through the staging tree. One less to worry about, thanks. That would allow you to drop the remaining virt_to_bus define from arch/m68k/include/asm/virtconvert.h. I could submit a patch to convert the Amiga SCSI drivers to use virt_to_phys if Geert and the SCSI maintainers think it's worth the churn. I don't think using virt_to_phys() is an improvement here, as virt_to_bus() was originally meant as a better abstraction to replace the use of virt_to_phys() to make drivers portable, before it got replaced by the dma-mapping interface in turn. It looks like the Amiga SCSI drivers have an open-coded version of what dma_map_single() does, to do bounce buffering and cache management. The ideal solution would be to convert the drivers actually use the appropriate dma-mapping interfaces and remove this custom code. I've taken another look at these drivers' dma_setup() functions and they all look much more complex than the Amiga ESP drivers (which do use the dma-mapping interface for parts of the DMA setup). From my limited understanding, the difference between the ESP and WD33C93 drivers is that the former are used on 040/060 accelerator boards only (where the processor does do bus snooping and DMA can access all of RAM). The latter ones would need cache management, could only use non-coherent mappings and would require special case handling for DMA-inaccessible RAM inside a device-specific dma ops' map_page() function. That's several bridges too far for me ... I have no Amiga hardware whatsoever, and know no one who could test changes to WD33C93 drivers for me. What I have is a NCR5380 with the proverbial 'pathological DMA' integration example (and its driver was never changed to even use virt_to_bus()!). I might learn enough about using the dma-mapping API on that one eventually (though the requirement for at least 1 MB swiotlb bounce buffers looks hard to meet), and use that to convert the WD33C93 drivers, but it would still remain untested. > The same could be done for the two vme drivers (scsi/mvme147.c and ethernet/82596.c), which do the cache management but apparently don't need swiotlb bounce buffering. Rewriting the drivers to modern APIs is of course non-trivial, and if you want a shortcut here, I would suggest introducing platform specific helpers similar to isa_virt_to_bus() and call them amiga_virt_to_bus() and vme_virt_to_bus, respectively. I don't think Amiga and m68k VME differ at all in that respect, so might just call it m68k_virt_to_bus() for now. Putting these into a platform specific header file at least helps clarify that both the helper functions and the drivers using them are non-portable. There are no platform specific header files other than asm/amigahw.h and asm/mvme147hw.h, currently only holding register address definitions. Would it be OK to add m68k_virt_to_bus() in there if it can't remain in asm/virtconvert.h, Geert? 32bit powerpc is a different matter though. It's similar, but unrelated. The two apple ethernet drivers (bmac and mace) can again either get changed to use the dma-mapping interfaces, or get a custom pmac_virt_to_bus()/ pmac_bus_to_virt() helper. Hmmm - I see Finn had done the DMA API conversion on macmace.c which might give some hints on what to do about mace.c ... no idea about bmac.c though. And again, haven't got hardware to test, so custom helpers is it, then. Cheers, Michael There is also drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c, which I think just needs a trivial change, but I'm not sure how to do it correctly. Arnd ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v9 00/11] iommu: SVA and IOPF refactoring
Hi folks, On 2022/6/21 22:43, Lu Baolu wrote: Hi folks, The former part of this series refactors the IOMMU SVA code by assigning an SVA type of iommu_domain to a shared virtual address and replacing sva_bind/unbind iommu ops with set/block_dev_pasid domain ops. The latter part changes the existing I/O page fault handling framework from only serving SVA to a generic one. Any driver or component could handle the I/O page faults for its domain in its own way by installing an I/O page fault handler. This series has been functionally tested on an x86 machine and compile tested for all architectures. This series is also available on github: [2]https://github.com/LuBaolu/intel-iommu/commits/iommu-sva-refactoring-v9 Please review and suggest. Just a gentle ping on this series. Do you have further inputs? I am trying to see if we can merge this series for v5.20. The drivers also depend on it to enable their kernel DMA with PASID. Sorry to disturb you. Best regards, baolu ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: iommu_sva_bind_device question
On Sat, Jun 25, 2022 at 12:52:27PM -0700, Fenghua Yu wrote: > Hi, Jerry and Baolu, > > On Fri, Jun 24, 2022 at 07:47:30AM -0700, Jerry Snitselaar wrote: > > > > > > > Hi Baolu & Dave, > > > > > fails. > > > > > > > > > > You also will get the following warning if you don't have scalable > > > > > mode enabled (either not enabled by default, or if enabled by default > > > > > and passed intel_iommu=on,sm_off): > > > > > > > > If scalable mode is disabled, iommu_dev_enable_feature(IOMMU_SVA) will > > > > return failure, hence driver should not call iommu_sva_bind_device(). > > > > I guess below will disappear if above is fixed in the idxd driver. > > Yes, Jerry's patch fixes the WARNING as well. > > > > > > > > > Best regards, > > > > baolu > > > > > > > > > > It looks like there was a recent maintainer change, and Fenghua is now > > > the maintainer. Fenghua thoughts on this? With 42a1b73852c4 > > > ("dmaengine: idxd: Separate user and kernel pasid enabling") the code > > > no longer depends on iommu_dev_feature_enable succeeding. Testing with > > > something like this works (ran dmatest without sm_on, and > > > dsa_user_test_runner.sh with sm_on, plus booting with various > > > intel_iommu= combinations): > > > > > > diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c > > > index 355fb3ef4cbf..5b49fd5c1e25 100644 > > > --- a/drivers/dma/idxd/init.c > > > +++ b/drivers/dma/idxd/init.c > > > @@ -514,13 +514,14 @@ static int idxd_probe(struct idxd_device *idxd) > > > if (IS_ENABLED(CONFIG_INTEL_IDXD_SVM) && sva) { > > > if (iommu_dev_enable_feature(dev, IOMMU_DEV_FEAT_SVA)) > > > dev_warn(dev, "Unable to turn on user SVA > > > feature.\n"); > > > - else > > > + else { > > > set_bit(IDXD_FLAG_USER_PASID_ENABLED, > > > >flags); > > > > > > - if (idxd_enable_system_pasid(idxd)) > > Please add "{" after this if. > > > > - dev_warn(dev, "No in-kernel DMA with PASID.\n"); > > > - else > then "}" before this else. > > > > - set_bit(IDXD_FLAG_PASID_ENABLED, >flags); > > > + if (idxd_enable_system_pasid(idxd)) > > > + dev_warn(dev, "No in-kernel DMA with > > > PASID.\n"); > > > + else > > > + set_bit(IDXD_FLAG_PASID_ENABLED, > > > >flags); > > > + } > > > } else if (!sva) { > > > dev_warn(dev, "User forced SVA off via module param.\n"); > > > } > > The patch was copied/pasted here. So the tabs are lost at beginning of each > line. So it cannot be applied. Please change the tabs back. > > Could you please send this patch in a separate email so that it has a > right patch format and description and ready to be picked up? > Sure, if you feel this is the correct solution. Just to be clear you would like the end result to be: if (IS_ENABLED(CONFIG_INTEL_IDXD_SVM) && sva) { if (iommu_dev_enable_feature(dev, IOMMU_DEV_FEAT_SVA)) dev_warn(dev, "Unable to turn on user SVA feature.\n"); else { set_bit(IDXD_FLAG_USER_PASID_ENABLED, >flags); if (idxd_enable_system_pasid(idxd)) { dev_warn(dev, "No in-kernel DMA with PASID.\n"); } else set_bit(IDXD_FLAG_PASID_ENABLED, >flags); } } else if (!sva) { dev_warn(dev, "User forced SVA off via module param.\n"); } > > > > > > The commit description is a bit confusing, because it talks about there > > > being no dependency, but ties user pasid to enabling/disabling the SVA > > > feature, which system pasid would depend on as well. > > > > > > Regards, > > > Jerry > > > > Things like that warning message "Unable to turn on user SVA feature" when > > iommu_dev_enable_feature fails though seems to be misleading with user > > inserted in there. I'll leave it to the idxd folks to figure out. > > How about removing "user" from the warning message? So the message will > be "Unable to turn on SVA feature"? > I think what was confusing to me is it seemed to tie the SVA iommu feature to the user, and talked about independence of the kernel and user pasids. I understand the pasids themselves being independent, but both depend on the SVA feature being enabled. So idxd_enable_system_pasid can only happen if iommu_dev_feature_enable(dev, IOMMU_DEV_FEAT_SVA) has succeeded prior to it, and idxd_disable_system_pasid should be called if needed before there is a call to iommu_dev_feature_disable(dev, IOMMU_DEV_FEAT_SVA). When I looked at the code that seemed to be the case outside of this block in idxd_probe, but I wasn't sure if I was missing something else. Regards, Jerry > Thanks. > > -Fenghua
Re: iommu_sva_bind_device question
Hi, Jerry and Baolu, On Fri, Jun 24, 2022 at 07:47:30AM -0700, Jerry Snitselaar wrote: > > > > > > Hi Baolu & Dave, > > > > fails. > > > > > > > > You also will get the following warning if you don't have scalable > > > > mode enabled (either not enabled by default, or if enabled by default > > > > and passed intel_iommu=on,sm_off): > > > > > > If scalable mode is disabled, iommu_dev_enable_feature(IOMMU_SVA) will > > > return failure, hence driver should not call iommu_sva_bind_device(). > > > I guess below will disappear if above is fixed in the idxd driver. Yes, Jerry's patch fixes the WARNING as well. > > > > > > Best regards, > > > baolu > > > > > > > It looks like there was a recent maintainer change, and Fenghua is now > > the maintainer. Fenghua thoughts on this? With 42a1b73852c4 > > ("dmaengine: idxd: Separate user and kernel pasid enabling") the code > > no longer depends on iommu_dev_feature_enable succeeding. Testing with > > something like this works (ran dmatest without sm_on, and > > dsa_user_test_runner.sh with sm_on, plus booting with various > > intel_iommu= combinations): > > > > diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c > > index 355fb3ef4cbf..5b49fd5c1e25 100644 > > --- a/drivers/dma/idxd/init.c > > +++ b/drivers/dma/idxd/init.c > > @@ -514,13 +514,14 @@ static int idxd_probe(struct idxd_device *idxd) > > if (IS_ENABLED(CONFIG_INTEL_IDXD_SVM) && sva) { > > if (iommu_dev_enable_feature(dev, IOMMU_DEV_FEAT_SVA)) > > dev_warn(dev, "Unable to turn on user SVA > > feature.\n"); > > - else > > + else { > > set_bit(IDXD_FLAG_USER_PASID_ENABLED, >flags); > > > > - if (idxd_enable_system_pasid(idxd)) Please add "{" after this if. > > - dev_warn(dev, "No in-kernel DMA with PASID.\n"); > > - else then "}" before this else. > > - set_bit(IDXD_FLAG_PASID_ENABLED, >flags); > > + if (idxd_enable_system_pasid(idxd)) > > + dev_warn(dev, "No in-kernel DMA with > > PASID.\n"); > > + else > > + set_bit(IDXD_FLAG_PASID_ENABLED, > > >flags); > > + } > > } else if (!sva) { > > dev_warn(dev, "User forced SVA off via module param.\n"); > > } The patch was copied/pasted here. So the tabs are lost at beginning of each line. So it cannot be applied. Please change the tabs back. Could you please send this patch in a separate email so that it has a right patch format and description and ready to be picked up? > > > > The commit description is a bit confusing, because it talks about there > > being no dependency, but ties user pasid to enabling/disabling the SVA > > feature, which system pasid would depend on as well. > > > > Regards, > > Jerry > > Things like that warning message "Unable to turn on user SVA feature" when > iommu_dev_enable_feature fails though seems to be misleading with user > inserted in there. I'll leave it to the idxd folks to figure out. How about removing "user" from the warning message? So the message will be "Unable to turn on SVA feature"? Thanks. -Fenghua ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 1/1] iommu/vt-d: Fix RID2PASID setup/teardown failure
The IOMMU driver shares the pasid table for PCI alias devices. When the RID2PASID entry of the shared pasid table has been filled by the first device, the subsequent device will encounter the "DMAR: Setup RID2PASID failed" failure as the pasid entry has already been marked as present. As the result, the IOMMU probing process will be aborted. On the contrary, when any alias device is hot-removed from the system, for example, by writing to /sys/bus/pci/devices/.../remove, the shared RID2PASID will be cleared without any notifications to other devices. As the result, any DMAs from those rest devices are blocked. Sharing pasid table among PCI alias devices could save two memory pages for devices underneath the PCIe-to-PCI bridges. Anyway, considering that those devices are rare on modern platforms that support VT-d in scalable mode and the saved memory is negligible, it's reasonable to remove this part of immature code to make the driver feasible and stable. Fixes: ef848b7e5a6a0 ("iommu/vt-d: Setup pasid entry for RID2PASID support") Reported-by: Chenyi Qiang Reported-by: Ethan Zhao Signed-off-by: Lu Baolu Reviewed-by: Kevin Tian Reviewed-by: Ethan Zhao Cc: sta...@vger.kernel.org Link: https://lore.kernel.org/r/20220623065720.727849-1-baolu...@linux.intel.com --- include/linux/intel-iommu.h | 3 -- drivers/iommu/intel/pasid.h | 1 - drivers/iommu/intel/iommu.c | 24 - drivers/iommu/intel/pasid.c | 69 ++--- 4 files changed, 3 insertions(+), 94 deletions(-) diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index 4f29139bbfc3..5fcf89faa31a 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -612,7 +612,6 @@ struct intel_iommu { struct device_domain_info { struct list_head link; /* link to domain siblings */ struct list_head global; /* link to global list */ - struct list_head table; /* link to pasid table */ u32 segment;/* PCI segment number */ u8 bus; /* PCI bus number */ u8 devfn; /* PCI devfn number */ @@ -729,8 +728,6 @@ extern int dmar_ir_support(void); void *alloc_pgtable_page(int node); void free_pgtable_page(void *vaddr); struct intel_iommu *domain_get_iommu(struct dmar_domain *domain); -int for_each_device_domain(int (*fn)(struct device_domain_info *info, -void *data), void *data); void iommu_flush_write_buffer(struct intel_iommu *iommu); int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct device *dev); struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn); diff --git a/drivers/iommu/intel/pasid.h b/drivers/iommu/intel/pasid.h index 583ea67fc783..bf5b937848b4 100644 --- a/drivers/iommu/intel/pasid.h +++ b/drivers/iommu/intel/pasid.h @@ -74,7 +74,6 @@ struct pasid_table { void*table; /* pasid table pointer */ int order; /* page order of pasid table */ u32 max_pasid; /* max pasid */ - struct list_headdev;/* device list */ }; /* Get PRESENT bit of a PASID directory entry. */ diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 44016594831d..5c0dce78586a 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -320,30 +320,6 @@ EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped); DEFINE_SPINLOCK(device_domain_lock); static LIST_HEAD(device_domain_list); -/* - * Iterate over elements in device_domain_list and call the specified - * callback @fn against each element. - */ -int for_each_device_domain(int (*fn)(struct device_domain_info *info, -void *data), void *data) -{ - int ret = 0; - unsigned long flags; - struct device_domain_info *info; - - spin_lock_irqsave(_domain_lock, flags); - list_for_each_entry(info, _domain_list, global) { - ret = fn(info, data); - if (ret) { - spin_unlock_irqrestore(_domain_lock, flags); - return ret; - } - } - spin_unlock_irqrestore(_domain_lock, flags); - - return 0; -} - const struct iommu_ops intel_iommu_ops; static bool translation_pre_enabled(struct intel_iommu *iommu) diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c index cb4c1d0cf25c..17cad7c1f62d 100644 --- a/drivers/iommu/intel/pasid.c +++ b/drivers/iommu/intel/pasid.c @@ -86,54 +86,6 @@ void vcmd_free_pasid(struct intel_iommu *iommu, u32 pasid) /* * Per device pasid table management: */ -static inline void -device_attach_pasid_table(struct device_domain_info *info, - struct pasid_table *pasid_table) -{ - info->pasid_table = pasid_table; - list_add(>table, _table->dev); -} - -static inline void -device_detach_pasid_table(struct device_domain_info
[PATCH 0/1] iommu/vt-d: Fixes for v5.19-rc4
Hi Joerg, One fix is queued for v5.19. It aims to fix: - RID2PASID setup/teardown failures for pci alias devices Please consider it for the iommu/fix branch. Best regards, Lu Baolu Lu Baolu (1): iommu/vt-d: Fix RID2PASID setup/teardown failure include/linux/intel-iommu.h | 3 -- drivers/iommu/intel/pasid.h | 1 - drivers/iommu/intel/iommu.c | 24 - drivers/iommu/intel/pasid.c | 69 ++--- 4 files changed, 3 insertions(+), 94 deletions(-) -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 6/6] iommu/vt-d: Make DMAR_UNITS_SUPPORTED default 1024
If the available hardware exceeds DMAR_UNITS_SUPPORTED (previously set to MAX_IO_APICS, or 128), it causes these messages: "DMAR: Failed to allocate seq_id", "DMAR: Parse DMAR table failure.", and "x2apic: IRQ remapping doesn't support X2APIC mode x2apic disabled"; and the system fails to boot properly. To support up to 64 sockets with 10 DMAR units each (640), make the value of DMAR_UNITS_SUPPORTED default 1024. Signed-off-by: Steve Wahl Signed-off-by: Lu Baolu --- include/linux/dmar.h | 6 +- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/include/linux/dmar.h b/include/linux/dmar.h index cbd714a198a0..d81a51978d01 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -18,11 +18,7 @@ struct acpi_dmar_header; -#ifdef CONFIG_X86 -# define DMAR_UNITS_SUPPORTEDMAX_IO_APICS -#else -# define DMAR_UNITS_SUPPORTED64 -#endif +#define DMAR_UNITS_SUPPORTED 1024 /* DMAR Flags */ #define DMAR_INTR_REMAP0x1 -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 5/6] iommu/vt-d: Remove global g_iommus array
The g_iommus is not used anywhere. Remove it to avoid dead code. Signed-off-by: Lu Baolu --- drivers/iommu/intel/iommu.c | 42 - 1 file changed, 42 deletions(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index f6d7055cffd7..9a284394b2c5 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -126,9 +126,6 @@ static inline unsigned long virt_to_dma_pfn(void *p) return page_to_dma_pfn(virt_to_page(p)); } -/* global iommu list, set NULL for ignored DMAR units */ -static struct intel_iommu **g_iommus; - static void __init check_tylersburg_isoch(void); static int rwbf_quirk; @@ -287,9 +284,6 @@ static LIST_HEAD(dmar_satc_units); #define for_each_rmrr_units(rmrr) \ list_for_each_entry(rmrr, _rmrr_units, list) -/* bitmap for indexing intel_iommus */ -static int g_num_of_iommus; - static void dmar_remove_one_dev_info(struct device *dev); int dmar_disabled = !IS_ENABLED(CONFIG_INTEL_IOMMU_DEFAULT_ON); @@ -1694,7 +1688,6 @@ static void free_dmar_iommu(struct intel_iommu *iommu) iommu->domain_ids = NULL; } - g_iommus[iommu->seq_id] = NULL; iommu->flags &= ~VTD_FLAG_IOMMU_PROBED; /* free context mapping */ @@ -2899,36 +2892,6 @@ static int __init init_dmars(void) struct intel_iommu *iommu; int ret; - /* -* for each drhd -*allocate root -*initialize and program root entry to not present -* endfor -*/ - for_each_drhd_unit(drhd) { - /* -* lock not needed as this is only incremented in the single -* threaded kernel __init code path all other access are read -* only -*/ - if (g_num_of_iommus < DMAR_UNITS_SUPPORTED) { - g_num_of_iommus++; - continue; - } - pr_err_once("Exceeded %d IOMMUs\n", DMAR_UNITS_SUPPORTED); - } - - /* Preallocate enough resources for IOMMU hot-addition */ - if (g_num_of_iommus < DMAR_UNITS_SUPPORTED) - g_num_of_iommus = DMAR_UNITS_SUPPORTED; - - g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *), - GFP_KERNEL); - if (!g_iommus) { - ret = -ENOMEM; - goto error; - } - ret = intel_cap_audit(CAP_AUDIT_STATIC_DMAR, NULL); if (ret) goto free_iommu; @@ -2951,7 +2914,6 @@ static int __init init_dmars(void) intel_pasid_max_id); } - g_iommus[iommu->seq_id] = iommu; iommu->flags |= VTD_FLAG_IOMMU_PROBED; intel_iommu_init_qi(iommu); @@ -3079,9 +3041,6 @@ static int __init init_dmars(void) free_dmar_iommu(iommu); } - kfree(g_iommus); - -error: return ret; } @@ -3488,7 +3447,6 @@ static int intel_iommu_add(struct dmar_drhd_unit *dmaru) if (iommu->gcmd & DMA_GCMD_TE) iommu_disable_translation(iommu); - g_iommus[iommu->seq_id] = iommu; iommu->flags |= VTD_FLAG_IOMMU_PROBED; ret = iommu_init_domains(iommu); if (ret == 0) -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 4/6] iommu/vt-d: Add VTD_FLAG_IOMMU_PROBED flag
In the IOMMU hot-add path, there's a need to check whether an IOMMU has been probed. Instead of checking the IOMMU pointer in the global list, it's better to allocate a flag bit in iommu->flags for this purpose. Signed-off-by: Lu Baolu --- drivers/iommu/intel/iommu.h | 1 + drivers/iommu/intel/iommu.c | 5 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h index 56c3d1a9e155..105a1e7c60d9 100644 --- a/drivers/iommu/intel/iommu.h +++ b/drivers/iommu/intel/iommu.h @@ -479,6 +479,7 @@ enum { #define VTD_FLAG_TRANS_PRE_ENABLED (1 << 0) #define VTD_FLAG_IRQ_REMAP_PRE_ENABLED (1 << 1) #define VTD_FLAG_SVM_CAPABLE (1 << 2) +#define VTD_FLAG_IOMMU_PROBED (1 << 3) extern int intel_iommu_sm; diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 78b26fef685e..f6d7055cffd7 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -1695,6 +1695,7 @@ static void free_dmar_iommu(struct intel_iommu *iommu) } g_iommus[iommu->seq_id] = NULL; + iommu->flags &= ~VTD_FLAG_IOMMU_PROBED; /* free context mapping */ free_context_table(iommu); @@ -2951,6 +2952,7 @@ static int __init init_dmars(void) } g_iommus[iommu->seq_id] = iommu; + iommu->flags |= VTD_FLAG_IOMMU_PROBED; intel_iommu_init_qi(iommu); @@ -3460,7 +3462,7 @@ static int intel_iommu_add(struct dmar_drhd_unit *dmaru) int sp, ret; struct intel_iommu *iommu = dmaru->iommu; - if (g_iommus[iommu->seq_id]) + if (iommu->flags & VTD_FLAG_IOMMU_PROBED) return 0; ret = intel_cap_audit(CAP_AUDIT_HOTPLUG_DMAR, iommu); @@ -3487,6 +3489,7 @@ static int intel_iommu_add(struct dmar_drhd_unit *dmaru) iommu_disable_translation(iommu); g_iommus[iommu->seq_id] = iommu; + iommu->flags |= VTD_FLAG_IOMMU_PROBED; ret = iommu_init_domains(iommu); if (ret == 0) ret = iommu_alloc_root_entry(iommu); -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 3/6] iommu/vt-d: Refactor iommu information of each domain
When a DMA domain is attached to a device, it needs to allocate a domain ID from its IOMMU. Currently, the domain ID information is stored in two static arrays embedded in the domain structure. This can lead to memory waste when the driver is running on a small platform. This optimizes these static arrays by replacing them with an xarray and consuming memory on demand. Signed-off-by: Lu Baolu --- drivers/iommu/intel/iommu.h | 27 +--- drivers/iommu/intel/iommu.c | 123 drivers/iommu/intel/pasid.c | 2 +- drivers/iommu/intel/svm.c | 2 +- 4 files changed, 90 insertions(+), 64 deletions(-) diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h index 56e0d8cd2102..56c3d1a9e155 100644 --- a/drivers/iommu/intel/iommu.h +++ b/drivers/iommu/intel/iommu.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -524,17 +525,15 @@ struct context_entry { */ #define DOMAIN_FLAG_USE_FIRST_LEVELBIT(1) +struct iommu_domain_info { + struct intel_iommu *iommu; + unsigned int refcnt; + u16 did; +}; + struct dmar_domain { int nid;/* node id */ - - unsigned int iommu_refcnt[DMAR_UNITS_SUPPORTED]; - /* Refcount of devices per iommu */ - - - u16 iommu_did[DMAR_UNITS_SUPPORTED]; - /* Domain ids per IOMMU. Use u16 since -* domain ids are 16 bit wide according -* to VT-d spec, section 9.3 */ + struct xarray iommu_array; /* Attached IOMMU array */ u8 has_iotlb_device: 1; u8 iommu_coherency: 1; /* indicate coherency of iommu access */ @@ -640,6 +639,16 @@ static inline struct dmar_domain *to_dmar_domain(struct iommu_domain *dom) return container_of(dom, struct dmar_domain, domain); } +/* Retrieve the domain ID which has allocated to the domain */ +static inline u16 +domain_id_iommu(struct dmar_domain *domain, struct intel_iommu *iommu) +{ + struct iommu_domain_info *info = + xa_load(>iommu_array, iommu->seq_id); + + return info->did; +} + /* * 0: readable * 1: writable diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 781e060352e6..78b26fef685e 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -254,10 +254,6 @@ static inline void context_clear_entry(struct context_entry *context) static struct dmar_domain *si_domain; static int hw_pass_through = 1; -#define for_each_domain_iommu(idx, domain) \ - for (idx = 0; idx < g_num_of_iommus; idx++) \ - if (domain->iommu_refcnt[idx]) - struct dmar_rmrr_unit { struct list_head list; /* list of rmrr units */ struct acpi_dmar_header *hdr; /* ACPI header */ @@ -453,16 +449,16 @@ static inline bool iommu_paging_structure_coherency(struct intel_iommu *iommu) static void domain_update_iommu_coherency(struct dmar_domain *domain) { + struct iommu_domain_info *info; struct dmar_drhd_unit *drhd; struct intel_iommu *iommu; bool found = false; - int i; + unsigned long i; domain->iommu_coherency = true; - - for_each_domain_iommu(i, domain) { + xa_for_each(>iommu_array, i, info) { found = true; - if (!iommu_paging_structure_coherency(g_iommus[i])) { + if (!iommu_paging_structure_coherency(info->iommu)) { domain->iommu_coherency = false; break; } @@ -1495,7 +1491,7 @@ static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, unsigned int aligned_pages = __roundup_pow_of_two(pages); unsigned int mask = ilog2(aligned_pages); uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT; - u16 did = domain->iommu_did[iommu->seq_id]; + u16 did = domain_id_iommu(domain, iommu); BUG_ON(pages == 0); @@ -1565,11 +1561,12 @@ static inline void __mapping_notify_one(struct intel_iommu *iommu, static void intel_flush_iotlb_all(struct iommu_domain *domain) { struct dmar_domain *dmar_domain = to_dmar_domain(domain); - int idx; + struct iommu_domain_info *info; + unsigned long idx; - for_each_domain_iommu(idx, dmar_domain) { - struct intel_iommu *iommu = g_iommus[idx]; - u16 did = dmar_domain->iommu_did[iommu->seq_id]; + xa_for_each(_domain->iommu_array, idx, info) { + struct intel_iommu *iommu = info->iommu; + u16 did = domain_id_iommu(dmar_domain, iommu); if (domain_use_first_level(dmar_domain)) qi_flush_piotlb(iommu, did, PASID_RID2PASID, 0, -1, 0); @@ -1745,6 +1742,7 @@ static struct
[PATCH v1 1/6] iommu/vt-d: Remove unused domain_get_iommu()
It is not used anywhere. Remove it to avoid dead code. Signed-off-by: Lu Baolu --- drivers/iommu/intel/iommu.h | 1 - drivers/iommu/intel/iommu.c | 18 -- 2 files changed, 19 deletions(-) diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h index df64d3d9c49a..56e0d8cd2102 100644 --- a/drivers/iommu/intel/iommu.h +++ b/drivers/iommu/intel/iommu.h @@ -725,7 +725,6 @@ extern int dmar_ir_support(void); void *alloc_pgtable_page(int node); void free_pgtable_page(void *vaddr); -struct intel_iommu *domain_get_iommu(struct dmar_domain *domain); void iommu_flush_write_buffer(struct intel_iommu *iommu); int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct device *dev); struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn); diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index da6cfea0f0d6..781e060352e6 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -445,24 +445,6 @@ int iommu_calculate_agaw(struct intel_iommu *iommu) return __iommu_calculate_agaw(iommu, DEFAULT_DOMAIN_ADDRESS_WIDTH); } -/* This functionin only returns single iommu in a domain */ -struct intel_iommu *domain_get_iommu(struct dmar_domain *domain) -{ - int iommu_id; - - /* si_domain and vm domain should not get here. */ - if (WARN_ON(!iommu_is_dma_domain(>domain))) - return NULL; - - for_each_domain_iommu(iommu_id, domain) - break; - - if (iommu_id < 0 || iommu_id >= g_num_of_iommus) - return NULL; - - return g_iommus[iommu_id]; -} - static inline bool iommu_paging_structure_coherency(struct intel_iommu *iommu) { return sm_supported(iommu) ? -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 2/6] iommu/vt-d: Use IDA interface to manage iommu sequence id
Switch dmar unit sequence id allocation and release from bitmap to IDA interface. Signed-off-by: Lu Baolu --- drivers/iommu/intel/dmar.c | 33 +++-- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c index 2a5e0f91e647..bf43889b9d2a 100644 --- a/drivers/iommu/intel/dmar.c +++ b/drivers/iommu/intel/dmar.c @@ -60,7 +60,7 @@ LIST_HEAD(dmar_drhd_units); struct acpi_table_header * __initdata dmar_tbl; static int dmar_dev_scope_status = 1; -static unsigned long dmar_seq_ids[BITS_TO_LONGS(DMAR_UNITS_SUPPORTED)]; +static DEFINE_IDA(dmar_seq_ids); static int alloc_iommu(struct dmar_drhd_unit *drhd); static void free_iommu(struct intel_iommu *iommu); @@ -1023,28 +1023,6 @@ static int map_iommu(struct intel_iommu *iommu, u64 phys_addr) return err; } -static int dmar_alloc_seq_id(struct intel_iommu *iommu) -{ - iommu->seq_id = find_first_zero_bit(dmar_seq_ids, - DMAR_UNITS_SUPPORTED); - if (iommu->seq_id >= DMAR_UNITS_SUPPORTED) { - iommu->seq_id = -1; - } else { - set_bit(iommu->seq_id, dmar_seq_ids); - sprintf(iommu->name, "dmar%d", iommu->seq_id); - } - - return iommu->seq_id; -} - -static void dmar_free_seq_id(struct intel_iommu *iommu) -{ - if (iommu->seq_id >= 0) { - clear_bit(iommu->seq_id, dmar_seq_ids); - iommu->seq_id = -1; - } -} - static int alloc_iommu(struct dmar_drhd_unit *drhd) { struct intel_iommu *iommu; @@ -1062,11 +1040,14 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) if (!iommu) return -ENOMEM; - if (dmar_alloc_seq_id(iommu) < 0) { + iommu->seq_id = ida_alloc_range(_seq_ids, 0, + DMAR_UNITS_SUPPORTED, GFP_KERNEL); + if (iommu->seq_id < 0) { pr_err("Failed to allocate seq_id\n"); err = -ENOSPC; goto error; } + sprintf(iommu->name, "dmar%d", iommu->seq_id); err = map_iommu(iommu, drhd->reg_base_addr); if (err) { @@ -1150,7 +1131,7 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) err_unmap: unmap_iommu(iommu); error_free_seq_id: - dmar_free_seq_id(iommu); + ida_free(_seq_ids, iommu->seq_id); error: kfree(iommu); return err; @@ -1183,7 +1164,7 @@ static void free_iommu(struct intel_iommu *iommu) if (iommu->reg) unmap_iommu(iommu); - dmar_free_seq_id(iommu); + ida_free(_seq_ids, iommu->seq_id); kfree(iommu); } -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v1 0/6] iommu/vt-d: Reset DMAR_UNITS_SUPPORTED
Hi folks, This is a follow-up series of changes proposed by this patch: https://lore.kernel.org/linux-iommu/20220615183650.32075-1-steve.w...@hpe.com/ It removes several static arrays of size DMAR_UNITS_SUPPORTED and sets the DMAR_UNITS_SUPPORTED to 1024. Please help review and suggest. Best regards, baolu Lu Baolu (6): iommu/vt-d: Remove unused domain_get_iommu() iommu/vt-d: Use IDA interface to manage iommu sequence id iommu/vt-d: Refactor iommu information of each domain iommu/vt-d: Add VTD_FLAG_IOMMU_PROBED flag iommu/vt-d: Remove global g_iommus array iommu/vt-d: Make DMAR_UNITS_SUPPORTED default 1024 include/linux/dmar.h| 6 +- drivers/iommu/intel/iommu.h | 29 -- drivers/iommu/intel/dmar.c | 33 ++- drivers/iommu/intel/iommu.c | 188 ++-- drivers/iommu/intel/pasid.c | 2 +- drivers/iommu/intel/svm.c | 2 +- 6 files changed, 103 insertions(+), 157 deletions(-) -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu