[PATCH 9/9] iommu/vt-d: Avoid duplicate removing in __domain_mapping()
From: "Longpeng(Mike)" The __domain_mapping() always removes the pages in the range from 'iov_pfn' to 'end_pfn', but the 'end_pfn' is always the last pfn of the range that the caller wants to map. This would introduce too many duplicated removing and leads the map operation take too long, for example: Map iova=0x10,nr_pages=0x7d61800 iov_pfn: 0x10, end_pfn: 0x7e617ff iov_pfn: 0x14, end_pfn: 0x7e617ff iov_pfn: 0x18, end_pfn: 0x7e617ff iov_pfn: 0x1c, end_pfn: 0x7e617ff iov_pfn: 0x20, end_pfn: 0x7e617ff ... it takes about 50ms in total. We can reduce the cost by recalculate the 'end_pfn' and limit it to the boundary of the end of this pte page. Map iova=0x10,nr_pages=0x7d61800 iov_pfn: 0x10, end_pfn: 0x13 iov_pfn: 0x14, end_pfn: 0x17 iov_pfn: 0x18, end_pfn: 0x1b iov_pfn: 0x1c, end_pfn: 0x1f iov_pfn: 0x20, end_pfn: 0x23 ... it only need 9ms now. This also removes a meaningless BUG_ON() in __domain_mapping(). Signed-off-by: Longpeng(Mike) Tested-by: Liujunjie Link: https://lore.kernel.org/r/20211008000433.1115-1-longpe...@huawei.com Signed-off-by: Lu Baolu --- include/linux/intel-iommu.h | 6 ++ drivers/iommu/intel/iommu.c | 11 ++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index 52481625838c..69230fd695ea 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -710,6 +710,12 @@ static inline bool first_pte_in_page(struct dma_pte *pte) return IS_ALIGNED((unsigned long)pte, VTD_PAGE_SIZE); } +static inline int nr_pte_to_next_page(struct dma_pte *pte) +{ + return first_pte_in_page(pte) ? BIT_ULL(VTD_STRIDE_SHIFT) : + (struct dma_pte *)ALIGN((unsigned long)pte, VTD_PAGE_SIZE) - pte; +} + extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev); extern int dmar_find_matched_atsr_unit(struct pci_dev *dev); diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 16a35669a9d0..0bde0c8b4126 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -2479,12 +2479,17 @@ __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, return -ENOMEM; first_pte = pte; + lvl_pages = lvl_to_nr_pages(largepage_lvl); + /* It is large page*/ if (largepage_lvl > 1) { unsigned long end_pfn; + unsigned long pages_to_remove; pteval |= DMA_PTE_LARGE_PAGE; - end_pfn = ((iov_pfn + nr_pages) & level_mask(largepage_lvl)) - 1; + pages_to_remove = min_t(unsigned long, nr_pages, + nr_pte_to_next_page(pte) * lvl_pages); + end_pfn = iov_pfn + pages_to_remove - 1; switch_to_super_page(domain, iov_pfn, end_pfn, largepage_lvl); } else { pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE; @@ -2506,10 +2511,6 @@ __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, WARN_ON(1); } - lvl_pages = lvl_to_nr_pages(largepage_lvl); - - BUG_ON(nr_pages < lvl_pages); - nr_pages -= lvl_pages; iov_pfn += lvl_pages; phys_pfn += lvl_pages; -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 8/9] iommu/vt-d: Convert the return type of first_pte_in_page to bool
From: "Longpeng(Mike)" The first_pte_in_page() returns true or false, so let's convert its return type to bool. In addition, use 'IS_ALIGNED' to make the code more readable and neater. Signed-off-by: Longpeng(Mike) Link: https://lore.kernel.org/r/20211008000433.1115-1-longpe...@huawei.com Signed-off-by: Lu Baolu --- include/linux/intel-iommu.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index 65b15af3cf1a..52481625838c 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -705,9 +705,9 @@ static inline bool dma_pte_superpage(struct dma_pte *pte) return (pte->val & DMA_PTE_LARGE_PAGE); } -static inline int first_pte_in_page(struct dma_pte *pte) +static inline bool first_pte_in_page(struct dma_pte *pte) { - return !((unsigned long)pte & ~VTD_PAGE_MASK); + return IS_ALIGNED((unsigned long)pte, VTD_PAGE_SIZE); } extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev); -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 7/9] iommu/vt-d: Clean up unused PASID updating functions
From: Fenghua Yu update_pasid() and its call chain are currently unused in the tree because Thomas disabled the ENQCMD feature. The feature will be re-enabled shortly using a different approach and update_pasid() and its call chain will not be used in the new approach. Remove the useless functions. Signed-off-by: Fenghua Yu Reviewed-by: Tony Luck Link: https://lore.kernel.org/r/20210920192349.2602141-1-fenghua...@intel.com Signed-off-by: Lu Baolu --- arch/x86/include/asm/fpu/api.h | 2 -- drivers/iommu/intel/svm.c | 24 +--- 2 files changed, 1 insertion(+), 25 deletions(-) diff --git a/arch/x86/include/asm/fpu/api.h b/arch/x86/include/asm/fpu/api.h index 23bef08a8388..ca4d0dee1ecd 100644 --- a/arch/x86/include/asm/fpu/api.h +++ b/arch/x86/include/asm/fpu/api.h @@ -106,6 +106,4 @@ extern int cpu_has_xfeatures(u64 xfeatures_mask, const char **feature_name); */ #define PASID_DISABLED 0 -static inline void update_pasid(void) { } - #endif /* _ASM_X86_FPU_API_H */ diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c index 0c228787704f..5b5d69b04fcc 100644 --- a/drivers/iommu/intel/svm.c +++ b/drivers/iommu/intel/svm.c @@ -505,21 +505,6 @@ int intel_svm_unbind_gpasid(struct device *dev, u32 pasid) return ret; } -static void _load_pasid(void *unused) -{ - update_pasid(); -} - -static void load_pasid(struct mm_struct *mm, u32 pasid) -{ - mutex_lock(>context.lock); - - /* Update PASID MSR on all CPUs running the mm's tasks. */ - on_each_cpu_mask(mm_cpumask(mm), _load_pasid, NULL, true); - - mutex_unlock(>context.lock); -} - static int intel_svm_alloc_pasid(struct device *dev, struct mm_struct *mm, unsigned int flags) { @@ -614,10 +599,6 @@ static struct iommu_sva *intel_svm_bind_mm(struct intel_iommu *iommu, if (ret) goto free_sdev; - /* The newly allocated pasid is loaded to the mm. */ - if (!(flags & SVM_FLAG_SUPERVISOR_MODE) && list_empty(>devs)) - load_pasid(mm, svm->pasid); - list_add_rcu(>list, >devs); success: return >sva; @@ -670,11 +651,8 @@ static int intel_svm_unbind_mm(struct device *dev, u32 pasid) kfree_rcu(sdev, rcu); if (list_empty(>devs)) { - if (svm->notifier.ops) { + if (svm->notifier.ops) mmu_notifier_unregister(>notifier, mm); - /* Clear mm's pasid. */ - load_pasid(mm, PASID_DISABLED); - } pasid_private_remove(svm->pasid); /* We mandate that no page faults may be outstanding * for the PASID when intel_svm_unbind_mm() is called. -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 6/9] iommu/vt-d: Delete dev_has_feat callback
The commit 262948f8ba573 ("iommu: Delete iommu_dev_has_feature()") has deleted the iommu_dev_has_feature() interface. Remove the dev_has_feat callback to avoid dead code. Signed-off-by: Lu Baolu Link: https://lore.kernel.org/r/20210929072030.1330225-1-baolu...@linux.intel.com --- drivers/iommu/intel/iommu.c | 59 - 1 file changed, 5 insertions(+), 54 deletions(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 1c26a7a012ce..16a35669a9d0 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -5511,62 +5511,14 @@ static int intel_iommu_disable_sva(struct device *dev) return ret; } -/* - * A PCI express designated vendor specific extended capability is defined - * in the section 3.7 of Intel scalable I/O virtualization technical spec - * for system software and tools to detect endpoint devices supporting the - * Intel scalable IO virtualization without host driver dependency. - * - * Returns the address of the matching extended capability structure within - * the device's PCI configuration space or 0 if the device does not support - * it. - */ -static int siov_find_pci_dvsec(struct pci_dev *pdev) -{ - int pos; - u16 vendor, id; - - pos = pci_find_next_ext_capability(pdev, 0, 0x23); - while (pos) { - pci_read_config_word(pdev, pos + 4, ); - pci_read_config_word(pdev, pos + 8, ); - if (vendor == PCI_VENDOR_ID_INTEL && id == 5) - return pos; - - pos = pci_find_next_ext_capability(pdev, pos, 0x23); - } - - return 0; -} - -static bool -intel_iommu_dev_has_feat(struct device *dev, enum iommu_dev_features feat) +static int intel_iommu_enable_iopf(struct device *dev) { struct device_domain_info *info = get_domain_info(dev); - if (feat == IOMMU_DEV_FEAT_AUX) { - int ret; - - if (!dev_is_pci(dev) || dmar_disabled || - !scalable_mode_support() || !pasid_mode_support()) - return false; - - ret = pci_pasid_features(to_pci_dev(dev)); - if (ret < 0) - return false; - - return !!siov_find_pci_dvsec(to_pci_dev(dev)); - } - - if (feat == IOMMU_DEV_FEAT_IOPF) - return info && info->pri_supported; - - if (feat == IOMMU_DEV_FEAT_SVA) - return info && (info->iommu->flags & VTD_FLAG_SVM_CAPABLE) && - info->pasid_supported && info->pri_supported && - info->ats_supported; + if (info && info->pri_supported) + return 0; - return false; + return -ENODEV; } static int @@ -5577,7 +5529,7 @@ intel_iommu_dev_enable_feat(struct device *dev, enum iommu_dev_features feat) return intel_iommu_enable_auxd(dev); case IOMMU_DEV_FEAT_IOPF: - return intel_iommu_dev_has_feat(dev, feat) ? 0 : -ENODEV; + return intel_iommu_enable_iopf(dev); case IOMMU_DEV_FEAT_SVA: return intel_iommu_enable_sva(dev); @@ -5703,7 +5655,6 @@ const struct iommu_ops intel_iommu_ops = { .get_resv_regions = intel_iommu_get_resv_regions, .put_resv_regions = generic_iommu_put_resv_regions, .device_group = intel_iommu_device_group, - .dev_has_feat = intel_iommu_dev_has_feat, .dev_feat_enabled = intel_iommu_dev_feat_enabled, .dev_enable_feat= intel_iommu_dev_enable_feat, .dev_disable_feat = intel_iommu_dev_disable_feat, -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 5/9] iommu/vt-d: Use second level for GPA->HPA translation
The IOMMU VT-d implementation uses the first level for GPA->HPA translation by default. Although both the first level and the second level could handle the DMA translation, they're different in some way. For example, the second level translation has separate controls for the Access/Dirty page tracking. With the first level translation, there's no such control. On the other hand, the second level translation has the page-level control for forcing snoop, but the first level only has global control with pasid granularity. This uses the second level for GPA->HPA translation so that we can provide a consistent hardware interface for use cases like dirty page tracking for live migration. Signed-off-by: Lu Baolu Reviewed-by: Kevin Tian Link: https://lore.kernel.org/r/20210926114535.923263-1-baolu...@linux.intel.com --- drivers/iommu/intel/iommu.c | 15 --- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index ec9ceb2dcf57..1c26a7a012ce 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -1991,9 +1991,18 @@ static void free_dmar_iommu(struct intel_iommu *iommu) * Check and return whether first level is used by default for * DMA translation. */ -static bool first_level_by_default(void) +static bool first_level_by_default(unsigned int type) { - return scalable_mode_support() && intel_cap_flts_sanity(); + /* Only SL is available in legacy mode */ + if (!scalable_mode_support()) + return false; + + /* Only level (either FL or SL) is available, just use it */ + if (intel_cap_flts_sanity() ^ intel_cap_slts_sanity()) + return intel_cap_flts_sanity(); + + /* Both levels are available, decide it based on domain type */ + return type != IOMMU_DOMAIN_UNMANAGED; } static struct dmar_domain *alloc_domain(unsigned int type) @@ -2006,7 +2015,7 @@ static struct dmar_domain *alloc_domain(unsigned int type) memset(domain, 0, sizeof(*domain)); domain->nid = NUMA_NO_NODE; - if (first_level_by_default()) + if (first_level_by_default(type)) domain->flags |= DOMAIN_FLAG_USE_FIRST_LEVEL; domain->has_iotlb_device = false; INIT_LIST_HEAD(>devices); -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 4/9] iommu/vt-d: Check FL and SL capability sanity in scalable mode
An iommu domain could be allocated and mapped before it's attached to any device. This requires that in scalable mode, when the domain is allocated, the format (FL or SL) of the page table must be determined. In order to achieve this, the platform should support consistent SL or FL capabilities on all IOMMU's. This adds a check for this and aborts IOMMU probing if it doesn't meet this requirement. Signed-off-by: Lu Baolu Reviewed-by: Kevin Tian Link: https://lore.kernel.org/r/20210926114535.923263-1-baolu...@linux.intel.com --- drivers/iommu/intel/cap_audit.h | 1 + drivers/iommu/intel/cap_audit.c | 13 + 2 files changed, 14 insertions(+) diff --git a/drivers/iommu/intel/cap_audit.h b/drivers/iommu/intel/cap_audit.h index 74cfccae0e81..d07b75938961 100644 --- a/drivers/iommu/intel/cap_audit.h +++ b/drivers/iommu/intel/cap_audit.h @@ -111,6 +111,7 @@ bool intel_cap_smts_sanity(void); bool intel_cap_pasid_sanity(void); bool intel_cap_nest_sanity(void); bool intel_cap_flts_sanity(void); +bool intel_cap_slts_sanity(void); static inline bool scalable_mode_support(void) { diff --git a/drivers/iommu/intel/cap_audit.c b/drivers/iommu/intel/cap_audit.c index b12e421a2f1a..b39d223926a4 100644 --- a/drivers/iommu/intel/cap_audit.c +++ b/drivers/iommu/intel/cap_audit.c @@ -163,6 +163,14 @@ static int cap_audit_static(struct intel_iommu *iommu, enum cap_audit_type type) check_irq_capabilities(iommu, i); } + /* +* If the system is sane to support scalable mode, either SL or FL +* should be sane. +*/ + if (intel_cap_smts_sanity() && + !intel_cap_flts_sanity() && !intel_cap_slts_sanity()) + return -EOPNOTSUPP; + out: rcu_read_unlock(); return 0; @@ -203,3 +211,8 @@ bool intel_cap_flts_sanity(void) { return ecap_flts(intel_iommu_ecap_sanity); } + +bool intel_cap_slts_sanity(void) +{ + return ecap_slts(intel_iommu_ecap_sanity); +} -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 3/9] iommu/vt-d: Remove duplicate identity domain flag
The iommu_domain data structure already has the "type" field to keep the type of a domain. It's unnecessary to have the DOMAIN_FLAG_STATIC_IDENTITY flag in the vt-d implementation. This cleans it up with no functionality change. Signed-off-by: Lu Baolu Reviewed-by: Kevin Tian Link: https://lore.kernel.org/r/20210926114535.923263-1-baolu...@linux.intel.com --- include/linux/intel-iommu.h | 3 --- drivers/iommu/intel/iommu.c | 9 - 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index 05a65eb155f7..65b15af3cf1a 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -517,9 +517,6 @@ struct context_entry { u64 hi; }; -/* si_domain contains mulitple devices */ -#define DOMAIN_FLAG_STATIC_IDENTITYBIT(0) - /* * When VT-d works in the scalable mode, it allows DMA translation to * happen through either first level or second level page table. This diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index abb258b1..ec9ceb2dcf57 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -528,7 +528,7 @@ static inline void free_devinfo_mem(void *vaddr) static inline int domain_type_is_si(struct dmar_domain *domain) { - return domain->flags & DOMAIN_FLAG_STATIC_IDENTITY; + return domain->domain.type == IOMMU_DOMAIN_IDENTITY; } static inline bool domain_use_first_level(struct dmar_domain *domain) @@ -1996,7 +1996,7 @@ static bool first_level_by_default(void) return scalable_mode_support() && intel_cap_flts_sanity(); } -static struct dmar_domain *alloc_domain(int flags) +static struct dmar_domain *alloc_domain(unsigned int type) { struct dmar_domain *domain; @@ -2006,7 +2006,6 @@ static struct dmar_domain *alloc_domain(int flags) memset(domain, 0, sizeof(*domain)); domain->nid = NUMA_NO_NODE; - domain->flags = flags; if (first_level_by_default()) domain->flags |= DOMAIN_FLAG_USE_FIRST_LEVEL; domain->has_iotlb_device = false; @@ -2825,7 +2824,7 @@ static int __init si_domain_init(int hw) struct device *dev; int i, nid, ret; - si_domain = alloc_domain(DOMAIN_FLAG_STATIC_IDENTITY); + si_domain = alloc_domain(IOMMU_DOMAIN_IDENTITY); if (!si_domain) return -EFAULT; @@ -4634,7 +4633,7 @@ static struct iommu_domain *intel_iommu_domain_alloc(unsigned type) case IOMMU_DOMAIN_DMA: case IOMMU_DOMAIN_DMA_FQ: case IOMMU_DOMAIN_UNMANAGED: - dmar_domain = alloc_domain(0); + dmar_domain = alloc_domain(type); if (!dmar_domain) { pr_err("Can't allocate dmar_domain\n"); return NULL; -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 0/9] [PULL REQUEST] Intel IOMMU Updates for Linux v5.16
Hi Joerg, The patches queued in this series are for v5.16. It includes: - Dump DMAR translation structure when DMA fault occurs. - An optimization in the page table manipulation code. - Use second level for GPA->HPA translation. - Various cleanups Please pull. Best regards, Baolu Fenghua Yu (1): iommu/vt-d: Clean up unused PASID updating functions Kyung Min Park (1): iommu/vt-d: Dump DMAR translation structure when DMA fault occurs Longpeng(Mike) (2): iommu/vt-d: Convert the return type of first_pte_in_page to bool iommu/vt-d: Avoid duplicate removing in __domain_mapping() Lu Baolu (4): iommu/vt-d: Remove duplicate identity domain flag iommu/vt-d: Check FL and SL capability sanity in scalable mode iommu/vt-d: Use second level for GPA->HPA translation iommu/vt-d: Delete dev_has_feat callback Tvrtko Ursulin (1): iommu/vt-d: Do not falsely log intel_iommu is unsupported kernel option include/linux/dmar.h| 8 ++ include/linux/intel-iommu.h | 13 +- arch/x86/include/asm/fpu/api.h | 2 - drivers/iommu/intel/cap_audit.h | 1 + drivers/iommu/intel/cap_audit.c | 13 ++ drivers/iommu/intel/dmar.c | 10 +- drivers/iommu/intel/iommu.c | 213 ++-- drivers/iommu/intel/svm.c | 24 +--- drivers/iommu/intel/Kconfig | 4 + 9 files changed, 188 insertions(+), 100 deletions(-) -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 2/9] iommu/vt-d: Dump DMAR translation structure when DMA fault occurs
From: Kyung Min Park When the dmar translation fault happens, the kernel prints a single line fault reason with corresponding hexadecimal code defined in the Intel VT-d specification. Currently, when user wants to debug the translation fault in detail, debugfs is used for dumping the dmar_translation_struct, which is not available when the kernel failed to boot. Dump the DMAR translation structure, pagewalk the IO page table and print the page table entry when the fault happens. This takes effect only when CONFIG_DMAR_DEBUG is enabled. Signed-off-by: Kyung Min Park Link: https://lore.kernel.org/r/20210815203845.31287-1-kyung.min.p...@intel.com Signed-off-by: Lu Baolu --- include/linux/dmar.h| 8 +++ drivers/iommu/intel/dmar.c | 10 +++- drivers/iommu/intel/iommu.c | 113 drivers/iommu/intel/Kconfig | 4 ++ 4 files changed, 133 insertions(+), 2 deletions(-) diff --git a/include/linux/dmar.h b/include/linux/dmar.h index e04436a7ff27..45e903d84733 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -131,6 +131,14 @@ static inline int dmar_res_noop(struct acpi_dmar_header *hdr, void *arg) return 0; } +#ifdef CONFIG_DMAR_DEBUG +void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id, + unsigned long long addr, u32 pasid); +#else +static inline void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id, + unsigned long long addr, u32 pasid) {} +#endif + #ifdef CONFIG_INTEL_IOMMU extern int iommu_detected, no_iommu; extern int intel_iommu_init(void); diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c index b7708b93f3fa..915bff76fe96 100644 --- a/drivers/iommu/intel/dmar.c +++ b/drivers/iommu/intel/dmar.c @@ -1941,12 +1941,16 @@ static int dmar_fault_do_one(struct intel_iommu *iommu, int type, reason = dmar_get_fault_reason(fault_reason, _type); - if (fault_type == INTR_REMAP) + if (fault_type == INTR_REMAP) { pr_err("[INTR-REMAP] Request device [%02x:%02x.%d] fault index 0x%llx [fault reason 0x%02x] %s\n", source_id >> 8, PCI_SLOT(source_id & 0xFF), PCI_FUNC(source_id & 0xFF), addr >> 48, fault_reason, reason); - else if (pasid == INVALID_IOASID) + + return 0; + } + + if (pasid == INVALID_IOASID) pr_err("[%s NO_PASID] Request device [%02x:%02x.%d] fault addr 0x%llx [fault reason 0x%02x] %s\n", type ? "DMA Read" : "DMA Write", source_id >> 8, PCI_SLOT(source_id & 0xFF), @@ -1959,6 +1963,8 @@ static int dmar_fault_do_one(struct intel_iommu *iommu, int type, PCI_FUNC(source_id & 0xFF), addr, fault_reason, reason); + dmar_fault_dump_ptes(iommu, source_id, addr, pasid); + return 0; } diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 9a356075d345..abb258b1 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -156,6 +156,8 @@ static struct intel_iommu **g_iommus; static void __init check_tylersburg_isoch(void); static int rwbf_quirk; +static inline struct device_domain_info * +dmar_search_domain_by_dev_info(int segment, int bus, int devfn); /* * set to 1 to panic kernel if can't successfully enable VT-d @@ -996,6 +998,117 @@ static void free_context_table(struct intel_iommu *iommu) spin_unlock_irqrestore(>lock, flags); } +#ifdef CONFIG_DMAR_DEBUG +static void pgtable_walk(struct intel_iommu *iommu, unsigned long pfn, u8 bus, u8 devfn) +{ + struct device_domain_info *info; + struct dma_pte *parent, *pte; + struct dmar_domain *domain; + int offset, level; + + info = dmar_search_domain_by_dev_info(iommu->segment, bus, devfn); + if (!info || !info->domain) { + pr_info("device [%02x:%02x.%d] not probed\n", + bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + return; + } + + domain = info->domain; + level = agaw_to_level(domain->agaw); + parent = domain->pgd; + if (!parent) { + pr_info("no page table setup\n"); + return; + } + + while (1) { + offset = pfn_level_offset(pfn, level); + pte = [offset]; + if (!pte || (dma_pte_superpage(pte) || !dma_pte_present(pte))) { + pr_info("PTE not present at level %d\n", level); + break; + } + + pr_info("pte level: %d, pte value: 0x%016llx\n", level, pte->val); + + if (level == 1) + break; + + parent = phys_to_virt(dma_pte_addr(pte)); + level--; + } +} + +void dmar_fault_dump_ptes(struct intel_iommu *iommu, u16 source_id, +
[PATCH 1/9] iommu/vt-d: Do not falsely log intel_iommu is unsupported kernel option
From: Tvrtko Ursulin Handling of intel_iommu kernel command line option should return "true" to indicate option is valid and so avoid logging it as unknown by the core parsing code. Also log unknown sub-options at the notice level to let user know of potential typos or similar. Reported-by: Eero Tamminen Signed-off-by: Tvrtko Ursulin Link: https://lore.kernel.org/r/20210831112947.310080-1-tvrtko.ursu...@linux.intel.com Signed-off-by: Lu Baolu --- drivers/iommu/intel/iommu.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index d75f59ae28e6..9a356075d345 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -412,6 +412,7 @@ static int __init intel_iommu_setup(char *str) { if (!str) return -EINVAL; + while (*str) { if (!strncmp(str, "on", 2)) { dmar_disabled = 0; @@ -441,13 +442,16 @@ static int __init intel_iommu_setup(char *str) } else if (!strncmp(str, "tboot_noforce", 13)) { pr_info("Intel-IOMMU: not forcing on after tboot. This could expose security risk for tboot\n"); intel_iommu_tboot_noforce = 1; + } else { + pr_notice("Unknown option - '%s'\n", str); } str += strcspn(str, ","); while (*str == ',') str++; } - return 0; + + return 1; } __setup("intel_iommu=", intel_iommu_setup); -- 2.25.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
RE: [PATCH 2/5] iommu/virtio: Support bypass domains
> From: Tian, Kevin > Sent: Thursday, October 14, 2021 11:25 AM > > > From: Jean-Philippe Brucker > > Sent: Wednesday, October 13, 2021 8:11 PM > > > > The VIRTIO_IOMMU_F_BYPASS_CONFIG feature adds a new flag to the > > ATTACH > > request, that creates a bypass domain. Use it to enable identity > > domains. > > > > When VIRTIO_IOMMU_F_BYPASS_CONFIG is not supported by the device, > > we > > currently fail attaching to an identity domain. Future patches will > > instead create identity mappings in this case. > > > > Signed-off-by: Jean-Philippe Brucker > > --- > > drivers/iommu/virtio-iommu.c | 20 +++- > > 1 file changed, 19 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c > > index 80930ce04a16..ee8a7afd667b 100644 > > --- a/drivers/iommu/virtio-iommu.c > > +++ b/drivers/iommu/virtio-iommu.c > > @@ -71,6 +71,7 @@ struct viommu_domain { > > struct rb_root_cached mappings; > > > > unsigned long nr_endpoints; > > + boolbypass; > > }; > > > > struct viommu_endpoint { > > @@ -587,7 +588,9 @@ static struct iommu_domain > > *viommu_domain_alloc(unsigned type) > > { > > struct viommu_domain *vdomain; > > > > - if (type != IOMMU_DOMAIN_UNMANAGED && type != > > IOMMU_DOMAIN_DMA) > > + if (type != IOMMU_DOMAIN_UNMANAGED && > > + type != IOMMU_DOMAIN_DMA && > > + type != IOMMU_DOMAIN_IDENTITY) > > return NULL; > > > > vdomain = kzalloc(sizeof(*vdomain), GFP_KERNEL); > > @@ -630,6 +633,17 @@ static int viommu_domain_finalise(struct > > viommu_endpoint *vdev, > > vdomain->map_flags = viommu->map_flags; > > vdomain->viommu = viommu; > > > > + if (domain->type == IOMMU_DOMAIN_IDENTITY) { > > + if (!virtio_has_feature(viommu->vdev, > > + VIRTIO_IOMMU_F_BYPASS_CONFIG)) > > { > > + ida_free(>domain_ids, vdomain->id); > > + vdomain->viommu = 0; > > + return -EOPNOTSUPP; > > + } > > + > > + vdomain->bypass = true; > > + } > > + > > move to the start of the function, then no need for above cleanup. > forgot it as I see the reason now when looking at patch05 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
RE: [PATCH 2/5] iommu/virtio: Support bypass domains
> From: Jean-Philippe Brucker > Sent: Wednesday, October 13, 2021 8:11 PM > > The VIRTIO_IOMMU_F_BYPASS_CONFIG feature adds a new flag to the > ATTACH > request, that creates a bypass domain. Use it to enable identity > domains. > > When VIRTIO_IOMMU_F_BYPASS_CONFIG is not supported by the device, > we > currently fail attaching to an identity domain. Future patches will > instead create identity mappings in this case. > > Signed-off-by: Jean-Philippe Brucker > --- > drivers/iommu/virtio-iommu.c | 20 +++- > 1 file changed, 19 insertions(+), 1 deletion(-) > > diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c > index 80930ce04a16..ee8a7afd667b 100644 > --- a/drivers/iommu/virtio-iommu.c > +++ b/drivers/iommu/virtio-iommu.c > @@ -71,6 +71,7 @@ struct viommu_domain { > struct rb_root_cached mappings; > > unsigned long nr_endpoints; > + boolbypass; > }; > > struct viommu_endpoint { > @@ -587,7 +588,9 @@ static struct iommu_domain > *viommu_domain_alloc(unsigned type) > { > struct viommu_domain *vdomain; > > - if (type != IOMMU_DOMAIN_UNMANAGED && type != > IOMMU_DOMAIN_DMA) > + if (type != IOMMU_DOMAIN_UNMANAGED && > + type != IOMMU_DOMAIN_DMA && > + type != IOMMU_DOMAIN_IDENTITY) > return NULL; > > vdomain = kzalloc(sizeof(*vdomain), GFP_KERNEL); > @@ -630,6 +633,17 @@ static int viommu_domain_finalise(struct > viommu_endpoint *vdev, > vdomain->map_flags = viommu->map_flags; > vdomain->viommu = viommu; > > + if (domain->type == IOMMU_DOMAIN_IDENTITY) { > + if (!virtio_has_feature(viommu->vdev, > + VIRTIO_IOMMU_F_BYPASS_CONFIG)) > { > + ida_free(>domain_ids, vdomain->id); > + vdomain->viommu = 0; > + return -EOPNOTSUPP; > + } > + > + vdomain->bypass = true; > + } > + move to the start of the function, then no need for above cleanup. > return 0; > } > > @@ -691,6 +705,9 @@ static int viommu_attach_dev(struct iommu_domain > *domain, struct device *dev) > .domain = cpu_to_le32(vdomain->id), > }; > > + if (vdomain->bypass) > + req.flags |= > cpu_to_le32(VIRTIO_IOMMU_ATTACH_F_BYPASS); > + > for (i = 0; i < fwspec->num_ids; i++) { > req.endpoint = cpu_to_le32(fwspec->ids[i]); > > @@ -1132,6 +1149,7 @@ static unsigned int features[] = { > VIRTIO_IOMMU_F_DOMAIN_RANGE, > VIRTIO_IOMMU_F_PROBE, > VIRTIO_IOMMU_F_MMIO, > + VIRTIO_IOMMU_F_BYPASS_CONFIG, > }; > > static struct virtio_device_id id_table[] = { > -- > 2.33.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH] iommu/iova: Add support for IOVA max alignment tuning
Hi Georgi, I love your patch! Yet something to improve: [auto build test ERROR on joro-iommu/next] [also build test ERROR on hnaz-mm/master linus/master v5.15-rc5 next-20211013] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Georgi-Djakov/iommu-iova-Add-support-for-IOVA-max-alignment-tuning/20211014-021248 base: https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next config: i386-randconfig-a003-20211013 (attached as .config) compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project b6a8c695542b2987eb9a203d5663a0740cb4725f) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/dc4cf3ea22a4c30a8a2c395e830ea37dd819 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Georgi-Djakov/iommu-iova-Add-support-for-IOVA-max-alignment-tuning/20211014-021248 git checkout dc4cf3ea22a4c30a8a2c395e830ea37dd819 # save the attached .config to linux build tree mkdir build_dir COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=i386 SHELL=/bin/bash drivers/iommu/ If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot All error/warnings (new ones prefixed by >>): >> drivers/iommu/iova.c:52:13: error: expected parameter declarator early_param("iommu.max_align_shift", iommu_set_def_max_align_shift); ^ >> drivers/iommu/iova.c:52:13: error: expected ')' drivers/iommu/iova.c:52:12: note: to match this '(' early_param("iommu.max_align_shift", iommu_set_def_max_align_shift); ^ >> drivers/iommu/iova.c:52:1: warning: declaration specifier missing, >> defaulting to 'int' early_param("iommu.max_align_shift", iommu_set_def_max_align_shift); ^ int >> drivers/iommu/iova.c:52:12: error: this function declaration is not a >> prototype [-Werror,-Wstrict-prototypes] early_param("iommu.max_align_shift", iommu_set_def_max_align_shift); ^ void 1 warning and 3 errors generated. vim +52 drivers/iommu/iova.c 40 41 static int __init iommu_set_def_max_align_shift(char *str) 42 { 43 unsigned long max_align_shift; 44 45 int ret = kstrtoul(str, 10, _align_shift); 46 47 if (!ret) 48 iommu_max_align_shift = max_align_shift; 49 50 return 0; 51 } > 52 early_param("iommu.max_align_shift", iommu_set_def_max_align_shift); 53 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org .config.gz Description: application/gzip ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
RE: [PATCH 0/5] iommu/virtio: Add identity domains
> From: Jean-Philippe Brucker > Sent: Wednesday, October 13, 2021 8:11 PM > > Support identity domains, allowing to only enable IOMMU protection for a > subset of endpoints (those assigned to userspace, for example). Users > may enable identity domains at compile time > (CONFIG_IOMMU_DEFAULT_PASSTHROUGH), boot time > (iommu.passthrough=1) or > runtime (/sys/kernel/iommu_groups/*/type = identity). Do we want to use consistent terms between spec (bypass domain) and code (identity domain)? > > Patches 1-2 support identity domains using the optional > VIRTIO_IOMMU_F_BYPASS_CONFIG feature. The feature bit is not yet in the > spec, see [1] for the latest proposal. > > Patches 3-5 add a fallback to identity mappings, when the feature is not > supported. > > Note that this series doesn't touch the global bypass bit added by > VIRTIO_IOMMU_F_BYPASS_CONFIG. All endpoints managed by the IOMMU > should > be attached to a domain, so global bypass isn't in use after endpoints I saw a concept of deferred attach in iommu core. See iommu_is_ attach_deferred(). Currently this is vendor specific and I haven't looked into the exact reason why some vendor sets it now. Just be curious whether the same reason might be applied to virtio-iommu. > are probed. Before that, the global bypass policy is decided by the > hypervisor and firmware. So I don't think Linux needs to touch the This reminds me one thing. The spec says that the global bypass bit is sticky and not affected by reset. This implies that in the case of rebooting the VM into a different OS, the previous OS actually has the right to override this setting for the next OS. Is it a right design? Even the firmware itself is unable to identify the original setting enforced by the hypervisor after reboot. I feel the hypervisor setting should be recovered after reset since it reflects the security measure enforced by the virtual platform? > global bypass bit, but there are some patches available on my > virtio-iommu/bypass branch [2] to test it. > > QEMU patches are on my virtio-iommu/bypass branch [3] (and the list) > > [1] https://www.mail-archive.com/virtio-dev@lists.oasis- > open.org/msg07898.html > [2] https://jpbrucker.net/git/linux/log/?h=virtio-iommu/bypass > [3] https://jpbrucker.net/git/qemu/log/?h=virtio-iommu/bypass > > Jean-Philippe Brucker (5): > iommu/virtio: Add definitions for VIRTIO_IOMMU_F_BYPASS_CONFIG > iommu/virtio: Support bypass domains > iommu/virtio: Sort reserved regions > iommu/virtio: Pass end address to viommu_add_mapping() > iommu/virtio: Support identity-mapped domains > > include/uapi/linux/virtio_iommu.h | 8 ++- > drivers/iommu/virtio-iommu.c | 113 +- > 2 files changed, 101 insertions(+), 20 deletions(-) > > -- > 2.33.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH] iommu/arm: fix ARM_SMMU_QCOM compilation
On Wed, Oct 13, 2021 at 6:20 PM Will Deacon wrote: > On Wed, Oct 13, 2021 at 10:33:55AM +0200, Arnd Bergmann wrote: > > On Wed, Oct 13, 2021 at 9:58 AM Will Deacon wrote: > > > On Tue, Oct 12, 2021 at 05:18:00PM +0200, Arnd Bergmann wrote: > > I was hoping you and Joerg could just pick your preferred patch > > into the iommu fixes tree for v5.15. > > > > I currently have nothing else pending for my asm-generic tree that > > introduced the regression, but I can take it through there if that helps > > you. > > I also don't have any fixes pending, and I don't see any in Joerg's tree so > it's probably quickest if you send it on yourself. Is that ok? Sure, no problem. I ended up adding it to the arm/fixes branch of the soc tree, as I just merged some other fixes there, and it seems as good as any of the other trees. Arnd ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH] iommu/iova: Add support for IOVA max alignment tuning
On 2021-10-13 19:11, Georgi Djakov wrote: IOVAs are aligned to the smallest PAGE_SIZE order, where the requested IOVA can fit. But this might not work for all use-cases. It can cause IOVA fragmentation in some multimedia and 8K video use-cases that may require larger buffers to be allocated and mapped. When the above allocation pattern is used with the current alignment scheme, the IOVA space could be quickly exhausted for 32bit devices. In order to get better IOVA space utilization and reduce fragmentation, a new kernel command line parameter is introduced to make the alignment limit configurable by the user during boot. Signed-off-by: Georgi Djakov --- Documentation/admin-guide/kernel-parameters.txt | 8 drivers/iommu/iova.c| 26 - I see no good reason for the IOVA layer to lie to its callers. If they don't need an aligned IOVA, they shouldn't ask for one in the first place. If callers still need some intermediate degree of alignment then the IOVA API might want to grow something more expressive than "bool size_aligned", but it should still be the callers' responsibility to pass an appropriate value. Thanks, Robin. 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index ad94a2aa9819..630246dc691f 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2056,6 +2056,14 @@ forcing Dual Address Cycle for PCI cards supporting greater than 32-bit addressing. + iommu.max_align_shift= + [ARM64, X86] Limit the alignment of IOVAs to a maximum + PAGE_SIZE order. Larger IOVAs will be aligned to this + specified order. The order is expressed as a power of + two multiplied by the PAGE_SIZE. + Format: { "4" | "5" | "6" | "7" | "8" | "9" } + Default: 9 + iommu.strict= [ARM64, X86] Configure TLB invalidation behaviour Format: { "0" | "1" } 0 - Lazy mode. diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c index 9e8bc802ac05..5a8c86871735 100644 --- a/drivers/iommu/iova.c +++ b/drivers/iommu/iova.c @@ -15,6 +15,9 @@ /* The anchor node sits above the top of the usable address space */ #define IOVA_ANCHOR ~0UL +#define IOMMU_DEFAULT_IOVA_MAX_ALIGN_SHIFT 9 +static unsigned long iommu_max_align_shift __read_mostly = IOMMU_DEFAULT_IOVA_MAX_ALIGN_SHIFT; + static bool iova_rcache_insert(struct iova_domain *iovad, unsigned long pfn, unsigned long size); @@ -27,6 +30,27 @@ static void free_iova_rcaches(struct iova_domain *iovad); static void fq_destroy_all_entries(struct iova_domain *iovad); static void fq_flush_timeout(struct timer_list *t); +static unsigned long limit_align_shift(struct iova_domain *iovad, unsigned long shift) +{ + unsigned long max_align_shift; + + max_align_shift = iommu_max_align_shift + PAGE_SHIFT - iova_shift(iovad); + return min_t(unsigned long, max_align_shift, shift); +} + +static int __init iommu_set_def_max_align_shift(char *str) +{ + unsigned long max_align_shift; + + int ret = kstrtoul(str, 10, _align_shift); + + if (!ret) + iommu_max_align_shift = max_align_shift; + + return 0; +} +early_param("iommu.max_align_shift", iommu_set_def_max_align_shift); + static int iova_cpuhp_dead(unsigned int cpu, struct hlist_node *node) { struct iova_domain *iovad; @@ -242,7 +266,7 @@ static int __alloc_and_insert_iova_range(struct iova_domain *iovad, unsigned long high_pfn = limit_pfn, low_pfn = iovad->start_pfn; if (size_aligned) - align_mask <<= fls_long(size - 1); + align_mask <<= limit_align_shift(iovad, fls_long(size - 1)); /* Walk the tree backwards */ spin_lock_irqsave(>iova_rbtree_lock, flags); ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH] iommu/iova: Add support for IOVA max alignment tuning
IOVAs are aligned to the smallest PAGE_SIZE order, where the requested IOVA can fit. But this might not work for all use-cases. It can cause IOVA fragmentation in some multimedia and 8K video use-cases that may require larger buffers to be allocated and mapped. When the above allocation pattern is used with the current alignment scheme, the IOVA space could be quickly exhausted for 32bit devices. In order to get better IOVA space utilization and reduce fragmentation, a new kernel command line parameter is introduced to make the alignment limit configurable by the user during boot. Signed-off-by: Georgi Djakov --- Documentation/admin-guide/kernel-parameters.txt | 8 drivers/iommu/iova.c| 26 - 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index ad94a2aa9819..630246dc691f 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2056,6 +2056,14 @@ forcing Dual Address Cycle for PCI cards supporting greater than 32-bit addressing. + iommu.max_align_shift= + [ARM64, X86] Limit the alignment of IOVAs to a maximum + PAGE_SIZE order. Larger IOVAs will be aligned to this + specified order. The order is expressed as a power of + two multiplied by the PAGE_SIZE. + Format: { "4" | "5" | "6" | "7" | "8" | "9" } + Default: 9 + iommu.strict= [ARM64, X86] Configure TLB invalidation behaviour Format: { "0" | "1" } 0 - Lazy mode. diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c index 9e8bc802ac05..5a8c86871735 100644 --- a/drivers/iommu/iova.c +++ b/drivers/iommu/iova.c @@ -15,6 +15,9 @@ /* The anchor node sits above the top of the usable address space */ #define IOVA_ANCHOR~0UL +#define IOMMU_DEFAULT_IOVA_MAX_ALIGN_SHIFT 9 +static unsigned long iommu_max_align_shift __read_mostly = IOMMU_DEFAULT_IOVA_MAX_ALIGN_SHIFT; + static bool iova_rcache_insert(struct iova_domain *iovad, unsigned long pfn, unsigned long size); @@ -27,6 +30,27 @@ static void free_iova_rcaches(struct iova_domain *iovad); static void fq_destroy_all_entries(struct iova_domain *iovad); static void fq_flush_timeout(struct timer_list *t); +static unsigned long limit_align_shift(struct iova_domain *iovad, unsigned long shift) +{ + unsigned long max_align_shift; + + max_align_shift = iommu_max_align_shift + PAGE_SHIFT - iova_shift(iovad); + return min_t(unsigned long, max_align_shift, shift); +} + +static int __init iommu_set_def_max_align_shift(char *str) +{ + unsigned long max_align_shift; + + int ret = kstrtoul(str, 10, _align_shift); + + if (!ret) + iommu_max_align_shift = max_align_shift; + + return 0; +} +early_param("iommu.max_align_shift", iommu_set_def_max_align_shift); + static int iova_cpuhp_dead(unsigned int cpu, struct hlist_node *node) { struct iova_domain *iovad; @@ -242,7 +266,7 @@ static int __alloc_and_insert_iova_range(struct iova_domain *iovad, unsigned long high_pfn = limit_pfn, low_pfn = iovad->start_pfn; if (size_aligned) - align_mask <<= fls_long(size - 1); + align_mask <<= limit_align_shift(iovad, fls_long(size - 1)); /* Walk the tree backwards */ spin_lock_irqsave(>iova_rbtree_lock, flags); ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH RFC] virtio: wrap config->reset calls
On Wed, Oct 13, 2021 at 06:55:31AM -0400, Michael S. Tsirkin wrote: > This will enable cleanups down the road. > The idea is to disable cbs, then add "flush_queued_cbs" callback > as a parameter, this way drivers can flush any work > queued after callbacks have been disabled. > > Signed-off-by: Michael S. Tsirkin > --- > arch/um/drivers/virt-pci.c | 2 +- > drivers/block/virtio_blk.c | 4 ++-- > drivers/bluetooth/virtio_bt.c | 2 +- > drivers/char/hw_random/virtio-rng.c| 2 +- > drivers/char/virtio_console.c | 4 ++-- > drivers/crypto/virtio/virtio_crypto_core.c | 8 > drivers/firmware/arm_scmi/virtio.c | 2 +- > drivers/gpio/gpio-virtio.c | 2 +- > drivers/gpu/drm/virtio/virtgpu_kms.c | 2 +- > drivers/i2c/busses/i2c-virtio.c| 2 +- > drivers/iommu/virtio-iommu.c | 2 +- > drivers/net/caif/caif_virtio.c | 2 +- > drivers/net/virtio_net.c | 4 ++-- > drivers/net/wireless/mac80211_hwsim.c | 2 +- > drivers/nvdimm/virtio_pmem.c | 2 +- > drivers/rpmsg/virtio_rpmsg_bus.c | 2 +- > drivers/scsi/virtio_scsi.c | 2 +- > drivers/virtio/virtio.c| 5 + > drivers/virtio/virtio_balloon.c| 2 +- > drivers/virtio/virtio_input.c | 2 +- > drivers/virtio/virtio_mem.c| 2 +- > fs/fuse/virtio_fs.c| 4 ++-- > include/linux/virtio.h | 1 + > net/9p/trans_virtio.c | 2 +- > net/vmw_vsock/virtio_transport.c | 4 ++-- > sound/virtio/virtio_card.c | 4 ++-- > 26 files changed, 39 insertions(+), 33 deletions(-) > [snip] > diff --git a/drivers/firmware/arm_scmi/virtio.c > b/drivers/firmware/arm_scmi/virtio.c > index 11e8efb71375..6b8d93fe8848 100644 > --- a/drivers/firmware/arm_scmi/virtio.c > +++ b/drivers/firmware/arm_scmi/virtio.c > @@ -452,7 +452,7 @@ static void scmi_vio_remove(struct virtio_device *vdev) >* outstanding message on any vqueue to be ignored by complete_cb: now >* we can just stop processing buffers and destroy the vqueues. >*/ > - vdev->config->reset(vdev); > + virtio_reset_device(vdev); > vdev->config->del_vqs(vdev); > /* Ensure scmi_vdev is visible as NULL */ > smp_store_mb(scmi_vdev, NULL); Reviewed-by: Cristian Marussi Thanks, Cristian ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH RFC] virtio: wrap config->reset calls
> This will enable cleanups down the road. > The idea is to disable cbs, then add "flush_queued_cbs" callback > as a parameter, this way drivers can flush any work > queued after callbacks have been disabled. > > Signed-off-by: Michael S. Tsirkin > --- > arch/um/drivers/virt-pci.c | 2 +- > drivers/block/virtio_blk.c | 4 ++-- > drivers/bluetooth/virtio_bt.c | 2 +- > drivers/char/hw_random/virtio-rng.c| 2 +- > drivers/char/virtio_console.c | 4 ++-- > drivers/crypto/virtio/virtio_crypto_core.c | 8 > drivers/firmware/arm_scmi/virtio.c | 2 +- > drivers/gpio/gpio-virtio.c | 2 +- > drivers/gpu/drm/virtio/virtgpu_kms.c | 2 +- > drivers/i2c/busses/i2c-virtio.c| 2 +- > drivers/iommu/virtio-iommu.c | 2 +- > drivers/net/caif/caif_virtio.c | 2 +- > drivers/net/virtio_net.c | 4 ++-- > drivers/net/wireless/mac80211_hwsim.c | 2 +- > drivers/nvdimm/virtio_pmem.c | 2 +- > drivers/rpmsg/virtio_rpmsg_bus.c | 2 +- > drivers/scsi/virtio_scsi.c | 2 +- > drivers/virtio/virtio.c| 5 + > drivers/virtio/virtio_balloon.c| 2 +- > drivers/virtio/virtio_input.c | 2 +- > drivers/virtio/virtio_mem.c| 2 +- > fs/fuse/virtio_fs.c| 4 ++-- > include/linux/virtio.h | 1 + > net/9p/trans_virtio.c | 2 +- > net/vmw_vsock/virtio_transport.c | 4 ++-- > sound/virtio/virtio_card.c | 4 ++-- > 26 files changed, 39 insertions(+), 33 deletions(-) > > diff --git a/arch/um/drivers/virt-pci.c b/arch/um/drivers/virt-pci.c > index c08066633023..22c4d87c9c15 100644 > --- a/arch/um/drivers/virt-pci.c > +++ b/arch/um/drivers/virt-pci.c > @@ -616,7 +616,7 @@ static void um_pci_virtio_remove(struct virtio_device > *vdev) > int i; > > /* Stop all virtqueues */ > -vdev->config->reset(vdev); > +virtio_reset_device(vdev); > vdev->config->del_vqs(vdev); > > device_set_wakeup_enable(>dev, false); > diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c > index 303caf2d17d0..83d0af3fbf30 100644 > --- a/drivers/block/virtio_blk.c > +++ b/drivers/block/virtio_blk.c > @@ -910,7 +910,7 @@ static void virtblk_remove(struct virtio_device *vdev) > mutex_lock(>vdev_mutex); > > /* Stop all the virtqueues. */ > - vdev->config->reset(vdev); > + virtio_reset_device(vdev); > > /* Virtqueues are stopped, nothing can use vblk->vdev anymore. */ > vblk->vdev = NULL; > @@ -929,7 +929,7 @@ static int virtblk_freeze(struct virtio_device *vdev) > struct virtio_blk *vblk = vdev->priv; > > /* Ensure we don't receive any more interrupts */ > - vdev->config->reset(vdev); > + virtio_reset_device(vdev); > > /* Make sure no work handler is accessing the device. */ > flush_work(>config_work); > diff --git a/drivers/bluetooth/virtio_bt.c b/drivers/bluetooth/virtio_bt.c > index 57908ce4fae8..24a9258962fa 100644 > --- a/drivers/bluetooth/virtio_bt.c > +++ b/drivers/bluetooth/virtio_bt.c > @@ -364,7 +364,7 @@ static void virtbt_remove(struct virtio_device *vdev) > struct hci_dev *hdev = vbt->hdev; > > hci_unregister_dev(hdev); > - vdev->config->reset(vdev); > + virtio_reset_device(vdev); > > hci_free_dev(hdev); > vbt->hdev = NULL; > diff --git a/drivers/char/hw_random/virtio-rng.c > b/drivers/char/hw_random/virtio-rng.c > index a90001e02bf7..95980489514b 100644 > --- a/drivers/char/hw_random/virtio-rng.c > +++ b/drivers/char/hw_random/virtio-rng.c > @@ -134,7 +134,7 @@ static void remove_common(struct virtio_device *vdev) > vi->hwrng_removed = true; > vi->data_avail = 0; > complete(>have_data); > - vdev->config->reset(vdev); > + virtio_reset_device(vdev); > vi->busy = false; > if (vi->hwrng_register_done) > hwrng_unregister(>hwrng); > diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c > index 7eaf303a7a86..08bbd693436f 100644 > --- a/drivers/char/virtio_console.c > +++ b/drivers/char/virtio_console.c > @@ -1957,7 +1957,7 @@ static void virtcons_remove(struct virtio_device *vdev) > spin_unlock_irq(_lock); > > /* Disable interrupts for vqs */ > - vdev->config->reset(vdev); > + virtio_reset_device(vdev); > /* Finish up work that's lined up */ > if (use_multiport(portdev)) > cancel_work_sync(>control_work); > @@ -2139,7 +2139,7 @@ static int virtcons_freeze(struct virtio_device *vdev) > > portdev = vdev->priv; > > - vdev->config->reset(vdev); > + virtio_reset_device(vdev); > > if (use_multiport(portdev)) >
Re: [PATCH] iommu/arm: fix ARM_SMMU_QCOM compilation
Hi Arnd, On Wed, Oct 13, 2021 at 10:33:55AM +0200, Arnd Bergmann wrote: > On Wed, Oct 13, 2021 at 9:58 AM Will Deacon wrote: > > On Tue, Oct 12, 2021 at 05:18:00PM +0200, Arnd Bergmann wrote: > > > From: Arnd Bergmann > > > > > > My previous bugfix ended up making things worse for the QCOM IOMMU > > > driver when it forgot to add the Kconfig symbol that is getting used to > > > control the compilation of the SMMU implementation specific code > > > for Qualcomm. > > > > > > Fixes: 424953cf3c66 ("qcom_scm: hide Kconfig symbol") > > > Reported-by: Daniel Lezcano > > > Reported-by: Dmitry Baryshkov > > > Reported-by: John Stultz > > > Link: > > > https://lore.kernel.org/lkml/20211010023350.978638-1-dmitry.barysh...@linaro.org/ > > > Signed-off-by: Arnd Bergmann > > > --- > > > In case we want fix it this way after all, here is the patch > > > I made. Either this one or Dmitry patch from the link above > > > is required for v5.15 > > > --- > > > drivers/iommu/Kconfig | 8 > > > 1 file changed, 8 insertions(+) > > > > > > diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig > > > index c5c71b7ab7e8..3eb68fa1b8cc 100644 > > > --- a/drivers/iommu/Kconfig > > > +++ b/drivers/iommu/Kconfig > > > @@ -355,6 +355,14 @@ config ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT > > > 'arm-smmu.disable_bypass' will continue to override this > > > config. > > > > > > +config ARM_SMMU_QCOM > > > + def_tristate y > > > + depends on ARM_SMMU && ARCH_QCOM > > > + select QCOM_SCM > > > + help > > > + When running on a Qualcomm platform that has the custom variant > > > + of the ARM SMMU, this needs to be built into the SMMU driver. > > > + > > > > FWIW, I prefer this solution over changing the driver code, so: > > > > Acked-by: Will Deacon > > > > I assume you'll be getting this fixed for 5.15? > > I was hoping you and Joerg could just pick your preferred patch > into the iommu fixes tree for v5.15. > > I currently have nothing else pending for my asm-generic tree that > introduced the regression, but I can take it through there if that helps > you. I also don't have any fixes pending, and I don't see any in Joerg's tree so it's probably quickest if you send it on yourself. Is that ok? Cheers, Will ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH RFC] virtio: wrap config->reset calls
On 13.10.21 14:17, Michael S. Tsirkin wrote: > On Wed, Oct 13, 2021 at 01:03:46PM +0200, David Hildenbrand wrote: >> On 13.10.21 12:55, Michael S. Tsirkin wrote: >>> This will enable cleanups down the road. >>> The idea is to disable cbs, then add "flush_queued_cbs" callback >>> as a parameter, this way drivers can flush any work >>> queued after callbacks have been disabled. >>> >>> Signed-off-by: Michael S. Tsirkin >>> --- >>> arch/um/drivers/virt-pci.c | 2 +- >>> drivers/block/virtio_blk.c | 4 ++-- >>> drivers/bluetooth/virtio_bt.c | 2 +- >>> drivers/char/hw_random/virtio-rng.c| 2 +- >>> drivers/char/virtio_console.c | 4 ++-- >>> drivers/crypto/virtio/virtio_crypto_core.c | 8 >>> drivers/firmware/arm_scmi/virtio.c | 2 +- >>> drivers/gpio/gpio-virtio.c | 2 +- >>> drivers/gpu/drm/virtio/virtgpu_kms.c | 2 +- >>> drivers/i2c/busses/i2c-virtio.c| 2 +- >>> drivers/iommu/virtio-iommu.c | 2 +- >>> drivers/net/caif/caif_virtio.c | 2 +- >>> drivers/net/virtio_net.c | 4 ++-- >>> drivers/net/wireless/mac80211_hwsim.c | 2 +- >>> drivers/nvdimm/virtio_pmem.c | 2 +- >>> drivers/rpmsg/virtio_rpmsg_bus.c | 2 +- >>> drivers/scsi/virtio_scsi.c | 2 +- >>> drivers/virtio/virtio.c| 5 + >>> drivers/virtio/virtio_balloon.c| 2 +- >>> drivers/virtio/virtio_input.c | 2 +- >>> drivers/virtio/virtio_mem.c| 2 +- >>> fs/fuse/virtio_fs.c| 4 ++-- >>> include/linux/virtio.h | 1 + >>> net/9p/trans_virtio.c | 2 +- >>> net/vmw_vsock/virtio_transport.c | 4 ++-- >>> sound/virtio/virtio_card.c | 4 ++-- >>> 26 files changed, 39 insertions(+), 33 deletions(-) >>> >>> diff --git a/arch/um/drivers/virt-pci.c b/arch/um/drivers/virt-pci.c >>> index c08066633023..22c4d87c9c15 100644 >>> --- a/arch/um/drivers/virt-pci.c >>> +++ b/arch/um/drivers/virt-pci.c >>> @@ -616,7 +616,7 @@ static void um_pci_virtio_remove(struct virtio_device >>> *vdev) >>> int i; >>> /* Stop all virtqueues */ >>> -vdev->config->reset(vdev); >>> +virtio_reset_device(vdev); >>> vdev->config->del_vqs(vdev); >> >> Nit: virtio_device_reset()? >> >> Because I see: >> >> int virtio_device_freeze(struct virtio_device *dev); >> int virtio_device_restore(struct virtio_device *dev); >> void virtio_device_ready(struct virtio_device *dev) >> >> But well, there is: >> void virtio_break_device(struct virtio_device *dev); > > Exactly. I don't know what's best, so I opted for plain english :) Fair enough, LGTM Reviewed-by: David Hildenbrand -- Thanks, David / dhildenb ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH RFC] virtio: wrap config->reset calls
On Wed, Oct 13, 2021 at 06:55:31AM -0400, Michael S. Tsirkin wrote: > This will enable cleanups down the road. > The idea is to disable cbs, then add "flush_queued_cbs" callback > as a parameter, this way drivers can flush any work > queued after callbacks have been disabled. > > Signed-off-by: Michael S. Tsirkin > --- > arch/um/drivers/virt-pci.c | 2 +- > drivers/block/virtio_blk.c | 4 ++-- > drivers/bluetooth/virtio_bt.c | 2 +- > drivers/char/hw_random/virtio-rng.c| 2 +- > drivers/char/virtio_console.c | 4 ++-- > drivers/crypto/virtio/virtio_crypto_core.c | 8 > drivers/firmware/arm_scmi/virtio.c | 2 +- > drivers/gpio/gpio-virtio.c | 2 +- > drivers/gpu/drm/virtio/virtgpu_kms.c | 2 +- > drivers/i2c/busses/i2c-virtio.c| 2 +- > drivers/iommu/virtio-iommu.c | 2 +- > drivers/net/caif/caif_virtio.c | 2 +- > drivers/net/virtio_net.c | 4 ++-- > drivers/net/wireless/mac80211_hwsim.c | 2 +- > drivers/nvdimm/virtio_pmem.c | 2 +- > drivers/rpmsg/virtio_rpmsg_bus.c | 2 +- > drivers/scsi/virtio_scsi.c | 2 +- > drivers/virtio/virtio.c| 5 + > drivers/virtio/virtio_balloon.c| 2 +- > drivers/virtio/virtio_input.c | 2 +- > drivers/virtio/virtio_mem.c| 2 +- > fs/fuse/virtio_fs.c| 4 ++-- > include/linux/virtio.h | 1 + > net/9p/trans_virtio.c | 2 +- > net/vmw_vsock/virtio_transport.c | 4 ++-- > sound/virtio/virtio_card.c | 4 ++-- > 26 files changed, 39 insertions(+), 33 deletions(-) > > static struct virtio_driver virtio_pmem_driver = { > diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c > b/drivers/rpmsg/virtio_rpmsg_bus.c > index 8e49a3bacfc7..6a11952822df 100644 > --- a/drivers/rpmsg/virtio_rpmsg_bus.c > +++ b/drivers/rpmsg/virtio_rpmsg_bus.c > @@ -1015,7 +1015,7 @@ static void rpmsg_remove(struct virtio_device *vdev) > size_t total_buf_space = vrp->num_bufs * vrp->buf_size; > int ret; > > - vdev->config->reset(vdev); > + virtio_reset_device(vdev); > Reviewed-by: Mathieu Poirier > ret = device_for_each_child(>dev, NULL, rpmsg_remove_device); > if (ret) ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH] iommu/dart: use kmemdup instead of kzalloc and memcpy
Reviewed-by: Alyssa Rosenzweig On Wed, Oct 13, 2021 at 02:34:41AM -0400, Wan Jiabing wrote: > Fix following coccicheck warning: > drivers/iommu/apple-dart.c:704:20-27: WARNING opportunity for kmemdup > > Signed-off-by: Wan Jiabing > --- > drivers/iommu/apple-dart.c | 3 +-- > 1 file changed, 1 insertion(+), 2 deletions(-) > > diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c > index 280ff8df728d..5eeb8d6b72e2 100644 > --- a/drivers/iommu/apple-dart.c > +++ b/drivers/iommu/apple-dart.c > @@ -701,13 +701,12 @@ static struct iommu_group > *apple_dart_device_group(struct device *dev) > if (!group) > goto out; > > - group_master_cfg = kzalloc(sizeof(*group_master_cfg), GFP_KERNEL); > + group_master_cfg = kmemdup(cfg, sizeof(*group_master_cfg), GFP_KERNEL); > if (!group_master_cfg) { > iommu_group_put(group); > goto out; > } > > - memcpy(group_master_cfg, cfg, sizeof(*group_master_cfg)); > iommu_group_set_iommudata(group, group_master_cfg, > apple_dart_release_group); > > -- > 2.20.1 > ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH RFC] virtio: wrap config->reset calls
On Wed, Oct 13, 2021 at 06:55:31AM -0400, Michael S. Tsirkin wrote: > This will enable cleanups down the road. > The idea is to disable cbs, then add "flush_queued_cbs" callback > as a parameter, this way drivers can flush any work > queued after callbacks have been disabled. > > Signed-off-by: Michael S. Tsirkin > --- > arch/um/drivers/virt-pci.c | 2 +- > drivers/block/virtio_blk.c | 4 ++-- > drivers/bluetooth/virtio_bt.c | 2 +- > drivers/char/hw_random/virtio-rng.c| 2 +- > drivers/char/virtio_console.c | 4 ++-- > drivers/crypto/virtio/virtio_crypto_core.c | 8 > drivers/firmware/arm_scmi/virtio.c | 2 +- > drivers/gpio/gpio-virtio.c | 2 +- > drivers/gpu/drm/virtio/virtgpu_kms.c | 2 +- > drivers/i2c/busses/i2c-virtio.c| 2 +- > drivers/iommu/virtio-iommu.c | 2 +- > drivers/net/caif/caif_virtio.c | 2 +- > drivers/net/virtio_net.c | 4 ++-- > drivers/net/wireless/mac80211_hwsim.c | 2 +- > drivers/nvdimm/virtio_pmem.c | 2 +- > drivers/rpmsg/virtio_rpmsg_bus.c | 2 +- > drivers/scsi/virtio_scsi.c | 2 +- > drivers/virtio/virtio.c| 5 + > drivers/virtio/virtio_balloon.c| 2 +- > drivers/virtio/virtio_input.c | 2 +- > drivers/virtio/virtio_mem.c| 2 +- > fs/fuse/virtio_fs.c| 4 ++-- fs/fuse/virtio_fs.c changes look good to me. Reviewed-by: Vivek Goyal Vivek [..] > diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c > index 0ad89c6629d7..27c3b74070a2 100644 > --- a/fs/fuse/virtio_fs.c > +++ b/fs/fuse/virtio_fs.c > @@ -895,7 +895,7 @@ static int virtio_fs_probe(struct virtio_device *vdev) > return 0; > > out_vqs: > - vdev->config->reset(vdev); > + virtio_reset_device(vdev); > virtio_fs_cleanup_vqs(vdev, fs); > kfree(fs->vqs); > > @@ -927,7 +927,7 @@ static void virtio_fs_remove(struct virtio_device *vdev) > list_del_init(>list); > virtio_fs_stop_all_queues(fs); > virtio_fs_drain_all_queues_locked(fs); > - vdev->config->reset(vdev); > + virtio_reset_device(vdev); > virtio_fs_cleanup_vqs(vdev, fs); > > vdev->priv = NULL; Thanks Vivek ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH] iommu/dart: use kmemdup instead of kzalloc and memcpy
Fix following coccicheck warning: drivers/iommu/apple-dart.c:704:20-27: WARNING opportunity for kmemdup Signed-off-by: Wan Jiabing --- drivers/iommu/apple-dart.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c index 280ff8df728d..5eeb8d6b72e2 100644 --- a/drivers/iommu/apple-dart.c +++ b/drivers/iommu/apple-dart.c @@ -701,13 +701,12 @@ static struct iommu_group *apple_dart_device_group(struct device *dev) if (!group) goto out; - group_master_cfg = kzalloc(sizeof(*group_master_cfg), GFP_KERNEL); + group_master_cfg = kmemdup(cfg, sizeof(*group_master_cfg), GFP_KERNEL); if (!group_master_cfg) { iommu_group_put(group); goto out; } - memcpy(group_master_cfg, cfg, sizeof(*group_master_cfg)); iommu_group_set_iommudata(group, group_master_cfg, apple_dart_release_group); -- 2.20.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 5/5] iommu/virtio: Support identity-mapped domains
Support identity domains for devices that do not offer the VIRTIO_IOMMU_F_BYPASS_CONFIG feature, by creating 1:1 mappings between the virtual and physical address space. Identity domains created this way still perform noticeably better than DMA domains, because they don't have the overhead of setting up and tearing down mappings at runtime. The performance difference between this and bypass is minimal in comparison. It does not matter that the physical addresses in the identity mappings do not all correspond to memory. By enabling passthrough we are trusting the device driver and the device itself to only perform DMA to suitable locations. In some cases it may even be desirable to perform DMA to MMIO regions. Signed-off-by: Jean-Philippe Brucker --- drivers/iommu/virtio-iommu.c | 61 +--- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c index eceb9281c8c1..c9e8367d2962 100644 --- a/drivers/iommu/virtio-iommu.c +++ b/drivers/iommu/virtio-iommu.c @@ -375,6 +375,55 @@ static size_t viommu_del_mappings(struct viommu_domain *vdomain, return unmapped; } +/* + * Fill the domain with identity mappings, skipping the device's reserved + * regions. + */ +static int viommu_domain_map_identity(struct viommu_endpoint *vdev, + struct viommu_domain *vdomain) +{ + int ret; + struct iommu_resv_region *resv; + u64 iova = vdomain->domain.geometry.aperture_start; + u64 limit = vdomain->domain.geometry.aperture_end; + u32 flags = VIRTIO_IOMMU_MAP_F_READ | VIRTIO_IOMMU_MAP_F_WRITE; + unsigned long granule = 1UL << __ffs(vdomain->domain.pgsize_bitmap); + + iova = ALIGN(iova, granule); + limit = ALIGN_DOWN(limit + 1, granule) - 1; + + list_for_each_entry(resv, >resv_regions, list) { + u64 resv_start = ALIGN_DOWN(resv->start, granule); + u64 resv_end = ALIGN(resv->start + resv->length, granule) - 1; + + if (resv_end < iova || resv_start > limit) + /* No overlap */ + continue; + + if (resv_start > iova) { + ret = viommu_add_mapping(vdomain, iova, resv_start - 1, +(phys_addr_t)iova, flags); + if (ret) + goto err_unmap; + } + + if (resv_end >= limit) + return 0; + + iova = resv_end + 1; + } + + ret = viommu_add_mapping(vdomain, iova, limit, (phys_addr_t)iova, +flags); + if (ret) + goto err_unmap; + return 0; + +err_unmap: + viommu_del_mappings(vdomain, 0, iova); + return ret; +} + /* * viommu_replay_mappings - re-send MAP requests * @@ -637,14 +686,18 @@ static int viommu_domain_finalise(struct viommu_endpoint *vdev, vdomain->viommu = viommu; if (domain->type == IOMMU_DOMAIN_IDENTITY) { - if (!virtio_has_feature(viommu->vdev, - VIRTIO_IOMMU_F_BYPASS_CONFIG)) { + if (virtio_has_feature(viommu->vdev, + VIRTIO_IOMMU_F_BYPASS_CONFIG)) { + vdomain->bypass = true; + return 0; + } + + ret = viommu_domain_map_identity(vdev, vdomain); + if (ret) { ida_free(>domain_ids, vdomain->id); vdomain->viommu = 0; return -EOPNOTSUPP; } - - vdomain->bypass = true; } return 0; -- 2.33.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 4/5] iommu/virtio: Pass end address to viommu_add_mapping()
To support identity mappings, the virtio-iommu driver must be able to represent full 64-bit ranges internally. Pass (start, end) instead of (start, size) to viommu_add/del_mapping(). Clean comments. The one about the returned size was never true: when sweeping the whole address space the returned size will most certainly be smaller than 2^64. Signed-off-by: Jean-Philippe Brucker --- drivers/iommu/virtio-iommu.c | 31 +++ 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c index d63ec4d11b00..eceb9281c8c1 100644 --- a/drivers/iommu/virtio-iommu.c +++ b/drivers/iommu/virtio-iommu.c @@ -311,8 +311,8 @@ static int viommu_send_req_sync(struct viommu_dev *viommu, void *buf, * * On success, return the new mapping. Otherwise return NULL. */ -static int viommu_add_mapping(struct viommu_domain *vdomain, unsigned long iova, - phys_addr_t paddr, size_t size, u32 flags) +static int viommu_add_mapping(struct viommu_domain *vdomain, u64 iova, u64 end, + phys_addr_t paddr, u32 flags) { unsigned long irqflags; struct viommu_mapping *mapping; @@ -323,7 +323,7 @@ static int viommu_add_mapping(struct viommu_domain *vdomain, unsigned long iova, mapping->paddr = paddr; mapping->iova.start = iova; - mapping->iova.last = iova + size - 1; + mapping->iova.last = end; mapping->flags = flags; spin_lock_irqsave(>mappings_lock, irqflags); @@ -338,26 +338,24 @@ static int viommu_add_mapping(struct viommu_domain *vdomain, unsigned long iova, * * @vdomain: the domain * @iova: start of the range - * @size: size of the range. A size of 0 corresponds to the entire address - * space. + * @end: end of the range * - * On success, returns the number of unmapped bytes (>= size) + * On success, returns the number of unmapped bytes */ static size_t viommu_del_mappings(struct viommu_domain *vdomain, - unsigned long iova, size_t size) + u64 iova, u64 end) { size_t unmapped = 0; unsigned long flags; - unsigned long last = iova + size - 1; struct viommu_mapping *mapping = NULL; struct interval_tree_node *node, *next; spin_lock_irqsave(>mappings_lock, flags); - next = interval_tree_iter_first(>mappings, iova, last); + next = interval_tree_iter_first(>mappings, iova, end); while (next) { node = next; mapping = container_of(node, struct viommu_mapping, iova); - next = interval_tree_iter_next(node, iova, last); + next = interval_tree_iter_next(node, iova, end); /* Trying to split a mapping? */ if (mapping->iova.start < iova) @@ -656,8 +654,8 @@ static void viommu_domain_free(struct iommu_domain *domain) { struct viommu_domain *vdomain = to_viommu_domain(domain); - /* Free all remaining mappings (size 2^64) */ - viommu_del_mappings(vdomain, 0, 0); + /* Free all remaining mappings */ + viommu_del_mappings(vdomain, 0, ULLONG_MAX); if (vdomain->viommu) ida_free(>viommu->domain_ids, vdomain->id); @@ -742,6 +740,7 @@ static int viommu_map(struct iommu_domain *domain, unsigned long iova, { int ret; u32 flags; + u64 end = iova + size - 1; struct virtio_iommu_req_map map; struct viommu_domain *vdomain = to_viommu_domain(domain); @@ -752,7 +751,7 @@ static int viommu_map(struct iommu_domain *domain, unsigned long iova, if (flags & ~vdomain->map_flags) return -EINVAL; - ret = viommu_add_mapping(vdomain, iova, paddr, size, flags); + ret = viommu_add_mapping(vdomain, iova, end, paddr, flags); if (ret) return ret; @@ -761,7 +760,7 @@ static int viommu_map(struct iommu_domain *domain, unsigned long iova, .domain = cpu_to_le32(vdomain->id), .virt_start = cpu_to_le64(iova), .phys_start = cpu_to_le64(paddr), - .virt_end = cpu_to_le64(iova + size - 1), + .virt_end = cpu_to_le64(end), .flags = cpu_to_le32(flags), }; @@ -770,7 +769,7 @@ static int viommu_map(struct iommu_domain *domain, unsigned long iova, ret = viommu_send_req_sync(vdomain->viommu, , sizeof(map)); if (ret) - viommu_del_mappings(vdomain, iova, size); + viommu_del_mappings(vdomain, iova, end); return ret; } @@ -783,7 +782,7 @@ static size_t viommu_unmap(struct iommu_domain *domain, unsigned long iova, struct virtio_iommu_req_unmap unmap; struct viommu_domain *vdomain = to_viommu_domain(domain); - unmapped =
[PATCH 2/5] iommu/virtio: Support bypass domains
The VIRTIO_IOMMU_F_BYPASS_CONFIG feature adds a new flag to the ATTACH request, that creates a bypass domain. Use it to enable identity domains. When VIRTIO_IOMMU_F_BYPASS_CONFIG is not supported by the device, we currently fail attaching to an identity domain. Future patches will instead create identity mappings in this case. Signed-off-by: Jean-Philippe Brucker --- drivers/iommu/virtio-iommu.c | 20 +++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c index 80930ce04a16..ee8a7afd667b 100644 --- a/drivers/iommu/virtio-iommu.c +++ b/drivers/iommu/virtio-iommu.c @@ -71,6 +71,7 @@ struct viommu_domain { struct rb_root_cached mappings; unsigned long nr_endpoints; + boolbypass; }; struct viommu_endpoint { @@ -587,7 +588,9 @@ static struct iommu_domain *viommu_domain_alloc(unsigned type) { struct viommu_domain *vdomain; - if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA) + if (type != IOMMU_DOMAIN_UNMANAGED && + type != IOMMU_DOMAIN_DMA && + type != IOMMU_DOMAIN_IDENTITY) return NULL; vdomain = kzalloc(sizeof(*vdomain), GFP_KERNEL); @@ -630,6 +633,17 @@ static int viommu_domain_finalise(struct viommu_endpoint *vdev, vdomain->map_flags = viommu->map_flags; vdomain->viommu = viommu; + if (domain->type == IOMMU_DOMAIN_IDENTITY) { + if (!virtio_has_feature(viommu->vdev, + VIRTIO_IOMMU_F_BYPASS_CONFIG)) { + ida_free(>domain_ids, vdomain->id); + vdomain->viommu = 0; + return -EOPNOTSUPP; + } + + vdomain->bypass = true; + } + return 0; } @@ -691,6 +705,9 @@ static int viommu_attach_dev(struct iommu_domain *domain, struct device *dev) .domain = cpu_to_le32(vdomain->id), }; + if (vdomain->bypass) + req.flags |= cpu_to_le32(VIRTIO_IOMMU_ATTACH_F_BYPASS); + for (i = 0; i < fwspec->num_ids; i++) { req.endpoint = cpu_to_le32(fwspec->ids[i]); @@ -1132,6 +1149,7 @@ static unsigned int features[] = { VIRTIO_IOMMU_F_DOMAIN_RANGE, VIRTIO_IOMMU_F_PROBE, VIRTIO_IOMMU_F_MMIO, + VIRTIO_IOMMU_F_BYPASS_CONFIG, }; static struct virtio_device_id id_table[] = { -- 2.33.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 1/5] iommu/virtio: Add definitions for VIRTIO_IOMMU_F_BYPASS_CONFIG
Add definitions for the VIRTIO_IOMMU_F_BYPASS_CONFIG, which supersedes VIRTIO_IOMMU_F_BYPASS. Signed-off-by: Jean-Philippe Brucker --- include/uapi/linux/virtio_iommu.h | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/virtio_iommu.h b/include/uapi/linux/virtio_iommu.h index 237e36a280cb..cafd8cf7febf 100644 --- a/include/uapi/linux/virtio_iommu.h +++ b/include/uapi/linux/virtio_iommu.h @@ -16,6 +16,7 @@ #define VIRTIO_IOMMU_F_BYPASS 3 #define VIRTIO_IOMMU_F_PROBE 4 #define VIRTIO_IOMMU_F_MMIO5 +#define VIRTIO_IOMMU_F_BYPASS_CONFIG 6 struct virtio_iommu_range_64 { __le64 start; @@ -36,6 +37,8 @@ struct virtio_iommu_config { struct virtio_iommu_range_32domain_range; /* Probe buffer size */ __le32 probe_size; + __u8bypass; + __u8reserved[7]; }; /* Request types */ @@ -66,11 +69,14 @@ struct virtio_iommu_req_tail { __u8reserved[3]; }; +#define VIRTIO_IOMMU_ATTACH_F_BYPASS (1 << 0) + struct virtio_iommu_req_attach { struct virtio_iommu_req_headhead; __le32 domain; __le32 endpoint; - __u8reserved[8]; + __le32 flags; + __u8reserved[4]; struct virtio_iommu_req_tailtail; }; -- 2.33.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 0/5] iommu/virtio: Add identity domains
Support identity domains, allowing to only enable IOMMU protection for a subset of endpoints (those assigned to userspace, for example). Users may enable identity domains at compile time (CONFIG_IOMMU_DEFAULT_PASSTHROUGH), boot time (iommu.passthrough=1) or runtime (/sys/kernel/iommu_groups/*/type = identity). Patches 1-2 support identity domains using the optional VIRTIO_IOMMU_F_BYPASS_CONFIG feature. The feature bit is not yet in the spec, see [1] for the latest proposal. Patches 3-5 add a fallback to identity mappings, when the feature is not supported. Note that this series doesn't touch the global bypass bit added by VIRTIO_IOMMU_F_BYPASS_CONFIG. All endpoints managed by the IOMMU should be attached to a domain, so global bypass isn't in use after endpoints are probed. Before that, the global bypass policy is decided by the hypervisor and firmware. So I don't think Linux needs to touch the global bypass bit, but there are some patches available on my virtio-iommu/bypass branch [2] to test it. QEMU patches are on my virtio-iommu/bypass branch [3] (and the list) [1] https://www.mail-archive.com/virtio-dev@lists.oasis-open.org/msg07898.html [2] https://jpbrucker.net/git/linux/log/?h=virtio-iommu/bypass [3] https://jpbrucker.net/git/qemu/log/?h=virtio-iommu/bypass Jean-Philippe Brucker (5): iommu/virtio: Add definitions for VIRTIO_IOMMU_F_BYPASS_CONFIG iommu/virtio: Support bypass domains iommu/virtio: Sort reserved regions iommu/virtio: Pass end address to viommu_add_mapping() iommu/virtio: Support identity-mapped domains include/uapi/linux/virtio_iommu.h | 8 ++- drivers/iommu/virtio-iommu.c | 113 +- 2 files changed, 101 insertions(+), 20 deletions(-) -- 2.33.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 3/5] iommu/virtio: Sort reserved regions
To ease identity mapping support, keep the list of reserved regions sorted. Signed-off-by: Jean-Philippe Brucker --- drivers/iommu/virtio-iommu.c | 9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c index ee8a7afd667b..d63ec4d11b00 100644 --- a/drivers/iommu/virtio-iommu.c +++ b/drivers/iommu/virtio-iommu.c @@ -423,7 +423,7 @@ static int viommu_add_resv_mem(struct viommu_endpoint *vdev, size_t size; u64 start64, end64; phys_addr_t start, end; - struct iommu_resv_region *region = NULL; + struct iommu_resv_region *region = NULL, *next; unsigned long prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO; start = start64 = le64_to_cpu(mem->start); @@ -454,7 +454,12 @@ static int viommu_add_resv_mem(struct viommu_endpoint *vdev, if (!region) return -ENOMEM; - list_add(>list, >resv_regions); + /* Keep the list sorted */ + list_for_each_entry(next, >resv_regions, list) { + if (next->start > region->start) + break; + } + list_add_tail(>list, >list); return 0; } -- 2.33.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH RFC] virtio: wrap config->reset calls
On Wed, Oct 13, 2021 at 01:03:46PM +0200, David Hildenbrand wrote: > On 13.10.21 12:55, Michael S. Tsirkin wrote: > > This will enable cleanups down the road. > > The idea is to disable cbs, then add "flush_queued_cbs" callback > > as a parameter, this way drivers can flush any work > > queued after callbacks have been disabled. > > > > Signed-off-by: Michael S. Tsirkin > > --- > > arch/um/drivers/virt-pci.c | 2 +- > > drivers/block/virtio_blk.c | 4 ++-- > > drivers/bluetooth/virtio_bt.c | 2 +- > > drivers/char/hw_random/virtio-rng.c| 2 +- > > drivers/char/virtio_console.c | 4 ++-- > > drivers/crypto/virtio/virtio_crypto_core.c | 8 > > drivers/firmware/arm_scmi/virtio.c | 2 +- > > drivers/gpio/gpio-virtio.c | 2 +- > > drivers/gpu/drm/virtio/virtgpu_kms.c | 2 +- > > drivers/i2c/busses/i2c-virtio.c| 2 +- > > drivers/iommu/virtio-iommu.c | 2 +- > > drivers/net/caif/caif_virtio.c | 2 +- > > drivers/net/virtio_net.c | 4 ++-- > > drivers/net/wireless/mac80211_hwsim.c | 2 +- > > drivers/nvdimm/virtio_pmem.c | 2 +- > > drivers/rpmsg/virtio_rpmsg_bus.c | 2 +- > > drivers/scsi/virtio_scsi.c | 2 +- > > drivers/virtio/virtio.c| 5 + > > drivers/virtio/virtio_balloon.c| 2 +- > > drivers/virtio/virtio_input.c | 2 +- > > drivers/virtio/virtio_mem.c| 2 +- > > fs/fuse/virtio_fs.c| 4 ++-- > > include/linux/virtio.h | 1 + > > net/9p/trans_virtio.c | 2 +- > > net/vmw_vsock/virtio_transport.c | 4 ++-- > > sound/virtio/virtio_card.c | 4 ++-- > > 26 files changed, 39 insertions(+), 33 deletions(-) > > > > diff --git a/arch/um/drivers/virt-pci.c b/arch/um/drivers/virt-pci.c > > index c08066633023..22c4d87c9c15 100644 > > --- a/arch/um/drivers/virt-pci.c > > +++ b/arch/um/drivers/virt-pci.c > > @@ -616,7 +616,7 @@ static void um_pci_virtio_remove(struct virtio_device > > *vdev) > > int i; > > /* Stop all virtqueues */ > > -vdev->config->reset(vdev); > > +virtio_reset_device(vdev); > > vdev->config->del_vqs(vdev); > > Nit: virtio_device_reset()? > > Because I see: > > int virtio_device_freeze(struct virtio_device *dev); > int virtio_device_restore(struct virtio_device *dev); > void virtio_device_ready(struct virtio_device *dev) > > But well, there is: > void virtio_break_device(struct virtio_device *dev); Exactly. I don't know what's best, so I opted for plain english :) > -- > Thanks, > > David / dhildenb ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH RFC] virtio: wrap config->reset calls
On 13.10.21 12:55, Michael S. Tsirkin wrote: This will enable cleanups down the road. The idea is to disable cbs, then add "flush_queued_cbs" callback as a parameter, this way drivers can flush any work queued after callbacks have been disabled. Signed-off-by: Michael S. Tsirkin --- arch/um/drivers/virt-pci.c | 2 +- drivers/block/virtio_blk.c | 4 ++-- drivers/bluetooth/virtio_bt.c | 2 +- drivers/char/hw_random/virtio-rng.c| 2 +- drivers/char/virtio_console.c | 4 ++-- drivers/crypto/virtio/virtio_crypto_core.c | 8 drivers/firmware/arm_scmi/virtio.c | 2 +- drivers/gpio/gpio-virtio.c | 2 +- drivers/gpu/drm/virtio/virtgpu_kms.c | 2 +- drivers/i2c/busses/i2c-virtio.c| 2 +- drivers/iommu/virtio-iommu.c | 2 +- drivers/net/caif/caif_virtio.c | 2 +- drivers/net/virtio_net.c | 4 ++-- drivers/net/wireless/mac80211_hwsim.c | 2 +- drivers/nvdimm/virtio_pmem.c | 2 +- drivers/rpmsg/virtio_rpmsg_bus.c | 2 +- drivers/scsi/virtio_scsi.c | 2 +- drivers/virtio/virtio.c| 5 + drivers/virtio/virtio_balloon.c| 2 +- drivers/virtio/virtio_input.c | 2 +- drivers/virtio/virtio_mem.c| 2 +- fs/fuse/virtio_fs.c| 4 ++-- include/linux/virtio.h | 1 + net/9p/trans_virtio.c | 2 +- net/vmw_vsock/virtio_transport.c | 4 ++-- sound/virtio/virtio_card.c | 4 ++-- 26 files changed, 39 insertions(+), 33 deletions(-) diff --git a/arch/um/drivers/virt-pci.c b/arch/um/drivers/virt-pci.c index c08066633023..22c4d87c9c15 100644 --- a/arch/um/drivers/virt-pci.c +++ b/arch/um/drivers/virt-pci.c @@ -616,7 +616,7 @@ static void um_pci_virtio_remove(struct virtio_device *vdev) int i; /* Stop all virtqueues */ -vdev->config->reset(vdev); +virtio_reset_device(vdev); vdev->config->del_vqs(vdev); Nit: virtio_device_reset()? Because I see: int virtio_device_freeze(struct virtio_device *dev); int virtio_device_restore(struct virtio_device *dev); void virtio_device_ready(struct virtio_device *dev) But well, there is: void virtio_break_device(struct virtio_device *dev); -- Thanks, David / dhildenb ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH RFC] virtio: wrap config->reset calls
On 13-10-21, 06:55, Michael S. Tsirkin wrote: > This will enable cleanups down the road. > The idea is to disable cbs, then add "flush_queued_cbs" callback > as a parameter, this way drivers can flush any work > queued after callbacks have been disabled. > > Signed-off-by: Michael S. Tsirkin > --- > drivers/gpio/gpio-virtio.c | 2 +- > drivers/i2c/busses/i2c-virtio.c| 2 +- Reviewed-by: Viresh Kumar -- viresh ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH RFC] virtio: wrap config->reset calls
This will enable cleanups down the road. The idea is to disable cbs, then add "flush_queued_cbs" callback as a parameter, this way drivers can flush any work queued after callbacks have been disabled. Signed-off-by: Michael S. Tsirkin --- arch/um/drivers/virt-pci.c | 2 +- drivers/block/virtio_blk.c | 4 ++-- drivers/bluetooth/virtio_bt.c | 2 +- drivers/char/hw_random/virtio-rng.c| 2 +- drivers/char/virtio_console.c | 4 ++-- drivers/crypto/virtio/virtio_crypto_core.c | 8 drivers/firmware/arm_scmi/virtio.c | 2 +- drivers/gpio/gpio-virtio.c | 2 +- drivers/gpu/drm/virtio/virtgpu_kms.c | 2 +- drivers/i2c/busses/i2c-virtio.c| 2 +- drivers/iommu/virtio-iommu.c | 2 +- drivers/net/caif/caif_virtio.c | 2 +- drivers/net/virtio_net.c | 4 ++-- drivers/net/wireless/mac80211_hwsim.c | 2 +- drivers/nvdimm/virtio_pmem.c | 2 +- drivers/rpmsg/virtio_rpmsg_bus.c | 2 +- drivers/scsi/virtio_scsi.c | 2 +- drivers/virtio/virtio.c| 5 + drivers/virtio/virtio_balloon.c| 2 +- drivers/virtio/virtio_input.c | 2 +- drivers/virtio/virtio_mem.c| 2 +- fs/fuse/virtio_fs.c| 4 ++-- include/linux/virtio.h | 1 + net/9p/trans_virtio.c | 2 +- net/vmw_vsock/virtio_transport.c | 4 ++-- sound/virtio/virtio_card.c | 4 ++-- 26 files changed, 39 insertions(+), 33 deletions(-) diff --git a/arch/um/drivers/virt-pci.c b/arch/um/drivers/virt-pci.c index c08066633023..22c4d87c9c15 100644 --- a/arch/um/drivers/virt-pci.c +++ b/arch/um/drivers/virt-pci.c @@ -616,7 +616,7 @@ static void um_pci_virtio_remove(struct virtio_device *vdev) int i; /* Stop all virtqueues */ -vdev->config->reset(vdev); +virtio_reset_device(vdev); vdev->config->del_vqs(vdev); device_set_wakeup_enable(>dev, false); diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 303caf2d17d0..83d0af3fbf30 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -910,7 +910,7 @@ static void virtblk_remove(struct virtio_device *vdev) mutex_lock(>vdev_mutex); /* Stop all the virtqueues. */ - vdev->config->reset(vdev); + virtio_reset_device(vdev); /* Virtqueues are stopped, nothing can use vblk->vdev anymore. */ vblk->vdev = NULL; @@ -929,7 +929,7 @@ static int virtblk_freeze(struct virtio_device *vdev) struct virtio_blk *vblk = vdev->priv; /* Ensure we don't receive any more interrupts */ - vdev->config->reset(vdev); + virtio_reset_device(vdev); /* Make sure no work handler is accessing the device. */ flush_work(>config_work); diff --git a/drivers/bluetooth/virtio_bt.c b/drivers/bluetooth/virtio_bt.c index 57908ce4fae8..24a9258962fa 100644 --- a/drivers/bluetooth/virtio_bt.c +++ b/drivers/bluetooth/virtio_bt.c @@ -364,7 +364,7 @@ static void virtbt_remove(struct virtio_device *vdev) struct hci_dev *hdev = vbt->hdev; hci_unregister_dev(hdev); - vdev->config->reset(vdev); + virtio_reset_device(vdev); hci_free_dev(hdev); vbt->hdev = NULL; diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index a90001e02bf7..95980489514b 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c @@ -134,7 +134,7 @@ static void remove_common(struct virtio_device *vdev) vi->hwrng_removed = true; vi->data_avail = 0; complete(>have_data); - vdev->config->reset(vdev); + virtio_reset_device(vdev); vi->busy = false; if (vi->hwrng_register_done) hwrng_unregister(>hwrng); diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 7eaf303a7a86..08bbd693436f 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -1957,7 +1957,7 @@ static void virtcons_remove(struct virtio_device *vdev) spin_unlock_irq(_lock); /* Disable interrupts for vqs */ - vdev->config->reset(vdev); + virtio_reset_device(vdev); /* Finish up work that's lined up */ if (use_multiport(portdev)) cancel_work_sync(>control_work); @@ -2139,7 +2139,7 @@ static int virtcons_freeze(struct virtio_device *vdev) portdev = vdev->priv; - vdev->config->reset(vdev); + virtio_reset_device(vdev); if (use_multiport(portdev)) virtqueue_disable_cb(portdev->c_ivq); diff --git a/drivers/crypto/virtio/virtio_crypto_core.c b/drivers/crypto/virtio/virtio_crypto_core.c index e2375d992308..8e977b7627cb 100644 --- a/drivers/crypto/virtio/virtio_crypto_core.c +++
Re: [PATCH] iommu/arm: fix ARM_SMMU_QCOM compilation
On Wed, Oct 13, 2021 at 9:58 AM Will Deacon wrote: > On Tue, Oct 12, 2021 at 05:18:00PM +0200, Arnd Bergmann wrote: > > From: Arnd Bergmann > > > > My previous bugfix ended up making things worse for the QCOM IOMMU > > driver when it forgot to add the Kconfig symbol that is getting used to > > control the compilation of the SMMU implementation specific code > > for Qualcomm. > > > > Fixes: 424953cf3c66 ("qcom_scm: hide Kconfig symbol") > > Reported-by: Daniel Lezcano > > Reported-by: Dmitry Baryshkov > > Reported-by: John Stultz > > Link: > > https://lore.kernel.org/lkml/20211010023350.978638-1-dmitry.barysh...@linaro.org/ > > Signed-off-by: Arnd Bergmann > > --- > > In case we want fix it this way after all, here is the patch > > I made. Either this one or Dmitry patch from the link above > > is required for v5.15 > > --- > > drivers/iommu/Kconfig | 8 > > 1 file changed, 8 insertions(+) > > > > diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig > > index c5c71b7ab7e8..3eb68fa1b8cc 100644 > > --- a/drivers/iommu/Kconfig > > +++ b/drivers/iommu/Kconfig > > @@ -355,6 +355,14 @@ config ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT > > 'arm-smmu.disable_bypass' will continue to override this > > config. > > > > +config ARM_SMMU_QCOM > > + def_tristate y > > + depends on ARM_SMMU && ARCH_QCOM > > + select QCOM_SCM > > + help > > + When running on a Qualcomm platform that has the custom variant > > + of the ARM SMMU, this needs to be built into the SMMU driver. > > + > > FWIW, I prefer this solution over changing the driver code, so: > > Acked-by: Will Deacon > > I assume you'll be getting this fixed for 5.15? I was hoping you and Joerg could just pick your preferred patch into the iommu fixes tree for v5.15. I currently have nothing else pending for my asm-generic tree that introduced the regression, but I can take it through there if that helps you. Arnd ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH] iommu/arm: fix ARM_SMMU_QCOM compilation
On Tue, Oct 12, 2021 at 05:18:00PM +0200, Arnd Bergmann wrote: > From: Arnd Bergmann > > My previous bugfix ended up making things worse for the QCOM IOMMU > driver when it forgot to add the Kconfig symbol that is getting used to > control the compilation of the SMMU implementation specific code > for Qualcomm. > > Fixes: 424953cf3c66 ("qcom_scm: hide Kconfig symbol") > Reported-by: Daniel Lezcano > Reported-by: Dmitry Baryshkov > Reported-by: John Stultz > Link: > https://lore.kernel.org/lkml/20211010023350.978638-1-dmitry.barysh...@linaro.org/ > Signed-off-by: Arnd Bergmann > --- > In case we want fix it this way after all, here is the patch > I made. Either this one or Dmitry patch from the link above > is required for v5.15 > --- > drivers/iommu/Kconfig | 8 > 1 file changed, 8 insertions(+) > > diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig > index c5c71b7ab7e8..3eb68fa1b8cc 100644 > --- a/drivers/iommu/Kconfig > +++ b/drivers/iommu/Kconfig > @@ -355,6 +355,14 @@ config ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT > 'arm-smmu.disable_bypass' will continue to override this > config. > > +config ARM_SMMU_QCOM > + def_tristate y > + depends on ARM_SMMU && ARCH_QCOM > + select QCOM_SCM > + help > + When running on a Qualcomm platform that has the custom variant > + of the ARM SMMU, this needs to be built into the SMMU driver. > + FWIW, I prefer this solution over changing the driver code, so: Acked-by: Will Deacon I assume you'll be getting this fixed for 5.15? Cheers, Will ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
RE: [RFC 11/20] iommu/iommufd: Add IOMMU_IOASID_ALLOC/FREE
> From: Jean-Philippe Brucker > Sent: Tuesday, October 12, 2021 4:34 PM > > On Mon, Oct 11, 2021 at 08:38:17PM -0300, Jason Gunthorpe wrote: > > On Mon, Oct 11, 2021 at 09:49:57AM +0100, Jean-Philippe Brucker wrote: > > > > > Seems like we don't need the negotiation part? The host kernel > > > communicates available IOVA ranges to userspace including holes (patch > > > 17), and userspace can check that the ranges it needs are within the IOVA > > > space boundaries. That part is necessary for DPDK as well since it needs > > > to know about holes in the IOVA space where DMA wouldn't work as > expected > > > (MSI doorbells for example). > > > > I haven't looked super closely at DPDK, but the other simple VFIO app > > I am aware of struggled to properly implement this semantic (Indeed it > > wasn't even clear to the author this was even needed). > > > > It requires interval tree logic inside the application which is not a > > trivial algorithm to implement in C. > > > > I do wonder if the "simple" interface should have an option more like > > the DMA API where userspace just asks to DMA map some user memory > and > > gets back the dma_addr_t to use. Kernel manages the allocation > > space/etc. > > Agreed, it's tempting to use IOVA = VA but the two spaces aren't > necessarily compatible. An extension that plugs into the IOVA allocator > could be useful to userspace drivers. > Make sense. We can have a flag in IOMMUFD_MAP_DMA to tell whether the user provides vaddr or expects the kernel to allocate and return. Thanks Kevin ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
RE: [RFC 11/20] iommu/iommufd: Add IOMMU_IOASID_ALLOC/FREE
> From: Jean-Philippe Brucker > Sent: Monday, October 11, 2021 4:50 PM > > On Mon, Oct 11, 2021 at 05:02:01PM +1100, David Gibson wrote: > > qemu wants to emulate a PAPR vIOMMU, so it says (via interfaces yet to > > be determined) that it needs an IOAS where things can be mapped in the > > range 0..2GiB (for the 32-bit window) and 2^59..2^59+1TiB (for the > > 64-bit window). > > > > Ideally the host /dev/iommu will say "ok!", since both those ranges > > are within the 0..2^60 translated range of the host IOMMU, and don't > > touch the IO hole. When the guest calls the IO mapping hypercalls, > > qemu translates those into DMA_MAP operations, and since they're all > > within the previously verified windows, they should work fine. > > Seems like we don't need the negotiation part? The host kernel > communicates available IOVA ranges to userspace including holes (patch > 17), and userspace can check that the ranges it needs are within the IOVA > space boundaries. That part is necessary for DPDK as well since it needs > to know about holes in the IOVA space where DMA wouldn't work as > expected > (MSI doorbells for example). And there already is a negotiation happening, > when the host kernel rejects MAP ioctl outside the advertised area. > Agree. This can cover the ppc platforms with fixed reserved ranges. It's meaningless to have user further tell kernel that it is only willing to use a subset of advertised area. for ppc platforms with dynamic reserved ranges which are claimed by user, we can leave it out of the common set and handled in a different way, either leveraging ioas nesting if applied or having ppc specific cmd. Thanks Kevin ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
RE: [RFC 11/20] iommu/iommufd: Add IOMMU_IOASID_ALLOC/FREE
> From: David Gibson > Sent: Friday, October 1, 2021 2:11 PM > > On Sun, Sep 19, 2021 at 02:38:39PM +0800, Liu Yi L wrote: > > This patch adds IOASID allocation/free interface per iommufd. When > > allocating an IOASID, userspace is expected to specify the type and > > format information for the target I/O page table. > > > > This RFC supports only one type (IOMMU_IOASID_TYPE_KERNEL_TYPE1V2), > > implying a kernel-managed I/O page table with vfio type1v2 mapping > > semantics. For this type the user should specify the addr_width of > > the I/O address space and whether the I/O page table is created in > > an iommu enfore_snoop format. enforce_snoop must be true at this point, > > as the false setting requires additional contract with KVM on handling > > WBINVD emulation, which can be added later. > > > > Userspace is expected to call IOMMU_CHECK_EXTENSION (see next patch) > > for what formats can be specified when allocating an IOASID. > > > > Open: > > - Devices on PPC platform currently use a different iommu driver in vfio. > > Per previous discussion they can also use vfio type1v2 as long as there > > is a way to claim a specific iova range from a system-wide address space. > > This requirement doesn't sound PPC specific, as addr_width for pci > devices > > can be also represented by a range [0, 2^addr_width-1]. This RFC hasn't > > adopted this design yet. We hope to have formal alignment in v1 > discussion > > and then decide how to incorporate it in v2. > > Ok, there are several things we need for ppc. None of which are > inherently ppc specific and some of which will I think be useful for > most platforms. So, starting from most general to most specific > here's basically what's needed: > > 1. We need to represent the fact that the IOMMU can only translate >*some* IOVAs, not a full 64-bit range. You have the addr_width >already, but I'm entirely sure if the translatable range on ppc >(or other platforms) is always a power-of-2 size. It usually will >be, of course, but I'm not sure that's a hard requirement. So >using a size/max rather than just a number of bits might be safer. > >I think basically every platform will need this. Most platforms >don't actually implement full 64-bit translation in any case, but >rather some smaller number of bits that fits their page table >format. > > 2. The translatable range of IOVAs may not begin at 0. So we need to >advertise to userspace what the base address is, as well as the >size. POWER's main IOVA range begins at 2^59 (at least on the >models I know about). > >I think a number of platforms are likely to want this, though I >couldn't name them apart from POWER. Putting the translated IOVA >window at some huge address is a pretty obvious approach to making >an IOMMU which can translate a wide address range without colliding >with any legacy PCI addresses down low (the IOMMU can check if this >transaction is for it by just looking at some high bits in the >address). > > 3. There might be multiple translatable ranges. So, on POWER the >IOMMU can typically translate IOVAs from 0..2GiB, and also from >2^59..2^59+. The two ranges have completely separate IO >page tables, with (usually) different layouts. (The low range will >nearly always be a single-level page table with 4kiB or 64kiB >entries, the high one will be multiple levels depending on the size >of the range and pagesize). > >This may be less common, but I suspect POWER won't be the only >platform to do something like this. As above, using a high range >is a pretty obvious approach, but clearly won't handle older >devices which can't do 64-bit DMA. So adding a smaller range for >those devices is again a pretty obvious solution. Any platform >with an "IO hole" can be treated as having two ranges, one below >the hole and one above it (although in that case they may well not >have separate page tables 1-3 are common on all platforms with fixed reserved ranges. Current vfio already reports permitted iova ranges to user via VFIO_IOMMU_ TYPE1_INFO_CAP_IOVA_RANGE and the user is expected to construct maps only in those ranges. iommufd can follow the same logic for the baseline uAPI. For above cases a [base, max] hint can be provided by the user per Jason's recommendation. It is a hint as no additional restriction is imposed, since the kernel only cares about no violation on permitted ranges that it reports to the user. Underlying iommu driver may use this hint to optimize e.g. deciding how many levels are used for the kernel-managed page table according to max addr. > > 4. The translatable ranges might not be fixed. On ppc that 0..2GiB >and 2^59..whatever ranges are kernel conventions, not specified by >the hardware or firmware. When running as a guest (which is the >normal case on POWER), there are explicit hypercalls for >