[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] RE: [PATCH] iommu: add preemption support to iommu_{un,}map()
Hi, It seems that this patch has been stale for a month, with actions needed from the author. So sending this email as a gentle reminder. Thanks! Kind regards, Henry > -----Original Message----- > Subject: [PATCH] iommu: add preemption support to iommu_{un,}map() > > The loop in iommu_{un,}map() can be arbitrary large, and as such it > needs to handle preemption. Introduce a new parameter that allow > returning the number of pages that have been processed, and which > presence also signals whether the function should do preemption > checks. > > Note that the cleanup done in iommu_map() can now be incomplete if > preemption has happened, and hence callers would need to take care of > unmapping the whole range (ie: ranges already mapped by previously > preempted calls). So far none of the callers care about having those > ranges unmapped, so error handling in iommu_memory_setup() and > arch_iommu_hwdom_init() can be kept as-is. > > Note that iommu_legacy_{un,}map() is left without preemption handling: > callers of those interfaces are not modified to pass bigger chunks, > and hence the functions won't be modified as are legacy and should be > replaced with iommu_{un,}map() instead if preemption is required. > > Fixes: f3185c165d ('IOMMU/x86: perform PV Dom0 mappings in batches') > Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> > --- > xen/arch/x86/pv/dom0_build.c | 15 ++++++++++++--- > xen/drivers/passthrough/iommu.c | 26 +++++++++++++++++++------- > xen/drivers/passthrough/x86/iommu.c | 13 +++++++++++-- > xen/include/xen/iommu.h | 4 ++-- > 4 files changed, 44 insertions(+), 14 deletions(-) > > diff --git a/xen/arch/x86/pv/dom0_build.c b/xen/arch/x86/pv/dom0_build.c > index 04a4ea3c18..e5a42870ec 100644 > --- a/xen/arch/x86/pv/dom0_build.c > +++ b/xen/arch/x86/pv/dom0_build.c > @@ -77,7 +77,8 @@ static __init void mark_pv_pt_pages_rdonly(struct > domain *d, > * iommu_memory_setup() ended up mapping them. > */ > if ( need_iommu_pt_sync(d) && > - iommu_unmap(d, _dfn(mfn_x(page_to_mfn(page))), 1, flush_flags) ) > + iommu_unmap(d, _dfn(mfn_x(page_to_mfn(page))), 1, flush_flags, > + NULL) ) > BUG(); > > /* Read-only mapping + PGC_allocated + page-table page. */ > @@ -121,13 +122,21 @@ static void __init iommu_memory_setup(struct > domain *d, const char *what, > unsigned int *flush_flags) > { > int rc; > + unsigned long done; > mfn_t mfn = page_to_mfn(page); > > if ( !need_iommu_pt_sync(d) ) > return; > > - rc = iommu_map(d, _dfn(mfn_x(mfn)), mfn, nr, > - IOMMUF_readable | IOMMUF_writable, flush_flags); > + while ( (rc = iommu_map(d, _dfn(mfn_x(mfn)), mfn, nr, > + IOMMUF_readable | IOMMUF_writable, > + flush_flags, &done)) == -ERESTART ) > + { > + mfn_add(mfn, done); > + nr -= done; > + process_pending_softirqs(); > + } > + > if ( rc ) > { > printk(XENLOG_ERR "pre-mapping %s MFN [%lx,%lx) into IOMMU > failed: %d\n", > diff --git a/xen/drivers/passthrough/iommu.c > b/xen/drivers/passthrough/iommu.c > index 75df3aa8dd..5c2a341112 100644 > --- a/xen/drivers/passthrough/iommu.c > +++ b/xen/drivers/passthrough/iommu.c > @@ -310,11 +310,11 @@ static unsigned int mapping_order(const struct > domain_iommu *hd, > > int iommu_map(struct domain *d, dfn_t dfn0, mfn_t mfn0, > unsigned long page_count, unsigned int flags, > - unsigned int *flush_flags) > + unsigned int *flush_flags, unsigned long *done) > { > const struct domain_iommu *hd = dom_iommu(d); > unsigned long i; > - unsigned int order; > + unsigned int order, j = 0; > int rc = 0; > > if ( !is_iommu_enabled(d) ) > @@ -327,6 +327,12 @@ int iommu_map(struct domain *d, dfn_t dfn0, > mfn_t mfn0, > dfn_t dfn = dfn_add(dfn0, i); > mfn_t mfn = mfn_add(mfn0, i); > > + if ( done && !(++j & 0xfffff) && general_preempt_check() ) > + { > + *done = i; > + return -ERESTART; > + } > + > order = mapping_order(hd, dfn, mfn, page_count - i); > > rc = iommu_call(hd->platform_ops, map_page, d, dfn, mfn, > @@ -341,7 +347,7 @@ int iommu_map(struct domain *d, dfn_t dfn0, mfn_t > mfn0, > d->domain_id, dfn_x(dfn), mfn_x(mfn), rc); > > /* while statement to satisfy __must_check */ > - while ( iommu_unmap(d, dfn0, i, flush_flags) ) > + while ( iommu_unmap(d, dfn0, i, flush_flags, NULL) ) > break; > > if ( !is_hardware_domain(d) ) > @@ -365,7 +371,7 @@ int iommu_legacy_map(struct domain *d, dfn_t dfn, > mfn_t mfn, > unsigned long page_count, unsigned int flags) > { > unsigned int flush_flags = 0; > - int rc = iommu_map(d, dfn, mfn, page_count, flags, &flush_flags); > + int rc = iommu_map(d, dfn, mfn, page_count, flags, &flush_flags, NULL); > > if ( !this_cpu(iommu_dont_flush_iotlb) && !rc ) > rc = iommu_iotlb_flush(d, dfn, page_count, flush_flags); > @@ -374,11 +380,11 @@ int iommu_legacy_map(struct domain *d, dfn_t > dfn, mfn_t mfn, > } > > int iommu_unmap(struct domain *d, dfn_t dfn0, unsigned long page_count, > - unsigned int *flush_flags) > + unsigned int *flush_flags, unsigned long *done) > { > const struct domain_iommu *hd = dom_iommu(d); > unsigned long i; > - unsigned int order; > + unsigned int order, j = 0; > int rc = 0; > > if ( !is_iommu_enabled(d) ) > @@ -389,6 +395,12 @@ int iommu_unmap(struct domain *d, dfn_t dfn0, > unsigned long page_count, > dfn_t dfn = dfn_add(dfn0, i); > int err; > > + if ( done && !(++j & 0xfffff) && general_preempt_check() ) > + { > + *done = i; > + return -ERESTART; > + } > + > order = mapping_order(hd, dfn, _mfn(0), page_count - i); > err = iommu_call(hd->platform_ops, unmap_page, d, dfn, > order, flush_flags); > @@ -425,7 +437,7 @@ int iommu_unmap(struct domain *d, dfn_t dfn0, > unsigned long page_count, > int iommu_legacy_unmap(struct domain *d, dfn_t dfn, unsigned long > page_count) > { > unsigned int flush_flags = 0; > - int rc = iommu_unmap(d, dfn, page_count, &flush_flags); > + int rc = iommu_unmap(d, dfn, page_count, &flush_flags, NULL); > > if ( !this_cpu(iommu_dont_flush_iotlb) && !rc ) > rc = iommu_iotlb_flush(d, dfn, page_count, flush_flags); > diff --git a/xen/drivers/passthrough/x86/iommu.c > b/xen/drivers/passthrough/x86/iommu.c > index 11a4f244e4..546e6dbe2a 100644 > --- a/xen/drivers/passthrough/x86/iommu.c > +++ b/xen/drivers/passthrough/x86/iommu.c > @@ -403,9 +403,18 @@ void __hwdom_init > arch_iommu_hwdom_init(struct domain *d) > } > else if ( pfn != start + count || perms != start_perms ) > { > + unsigned long done; > + > commit: > - rc = iommu_map(d, _dfn(start), _mfn(start), count, start_perms, > - &flush_flags); > + while ( (rc = iommu_map(d, _dfn(start), _mfn(start), count, > + start_perms, &flush_flags, > + &done)) == -ERESTART ) > + { > + start += done; > + count -= done; > + process_pending_softirqs(); > + } > + > if ( rc ) > printk(XENLOG_WARNING > "%pd: IOMMU identity mapping of [%lx,%lx) failed: > %d\n", > diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h > index 79529adf1f..e6643bcc1c 100644 > --- a/xen/include/xen/iommu.h > +++ b/xen/include/xen/iommu.h > @@ -155,10 +155,10 @@ enum > > int __must_check iommu_map(struct domain *d, dfn_t dfn, mfn_t mfn, > unsigned long page_count, unsigned int flags, > - unsigned int *flush_flags); > + unsigned int *flush_flags, unsigned long *done); > int __must_check iommu_unmap(struct domain *d, dfn_t dfn, > unsigned long page_count, > - unsigned int *flush_flags); > + unsigned int *flush_flags, unsigned long *done); > > int __must_check iommu_legacy_map(struct domain *d, dfn_t dfn, mfn_t > mfn, > unsigned long page_count, > -- > 2.36.1 >
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |