[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [RFC PATCH 2/9] iommu: Add ability to map/unmap the number of pages
Hi Oleksandr, On 15/03/17 20:05, Oleksandr Tyshchenko wrote: From: Oleksandr Tyshchenko <oleksandr_tyshchenko@xxxxxxxx> Extend the IOMMU code with new APIs and platform callbacks. These new map_pages/unmap_pages API do almost the same thing as existing map_page/unmap_page ones except the formers can handle the number of pages. So do new platform callbacks. Currently, this patch requires to modify neither existing IOMMU drivers nor P2M code. But, the patch might be rewritten to replace existing single-page stuff with the multi-page one followed by modifications of all related parts. Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@xxxxxxxx> --- xen/drivers/passthrough/iommu.c | 50 ++++++++++++++++++++++++++++++++--------- xen/include/xen/iommu.h | 16 ++++++++++--- 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c index 5e81813..115698f 100644 --- a/xen/drivers/passthrough/iommu.c +++ b/xen/drivers/passthrough/iommu.c @@ -249,22 +249,37 @@ void iommu_domain_destroy(struct domain *d) arch_iommu_domain_destroy(d); } -int iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn, - unsigned int flags) +int iommu_map_pages(struct domain *d, unsigned long gfn, unsigned long mfn, + unsigned long page_count, unsigned int flags) It would be nice if you can use mfn_t and gfn_t instead of unsigned long for any new functions. They are typesafe and avoid confusion between gfn and mfn. { const struct domain_iommu *hd = dom_iommu(d); - int rc; + int rc = 0; + unsigned long i; if ( !iommu_enabled || !hd->platform_ops ) return 0; - rc = hd->platform_ops->map_page(d, gfn, mfn, flags); + if ( hd->platform_ops->map_pages ) + rc = hd->platform_ops->map_pages(d, gfn, mfn, page_count, flags); + else + { + for ( i = 0; i < page_count; i++ ) + { + rc = hd->platform_ops->map_page(d, gfn + i, mfn + i, flags); + if ( unlikely(rc) ) + { + /* TODO Do we need to unmap if map failed? */ + break; + } + } + } + if ( unlikely(rc) ) { if ( !d->is_shutting_down && printk_ratelimit() ) printk(XENLOG_ERR - "d%d: IOMMU mapping gfn %#lx to mfn %#lx failed: %d\n", - d->domain_id, gfn, mfn, rc); + "d%d: IOMMU mapping gfn %#lx to mfn %#lx page count %lu failed: %d\n", + d->domain_id, gfn, mfn, page_count, rc); if ( !is_hardware_domain(d) ) domain_crash(d); @@ -273,21 +288,34 @@ int iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn, return rc; } -int iommu_unmap_page(struct domain *d, unsigned long gfn) +int iommu_unmap_pages(struct domain *d, unsigned long gfn, + unsigned long page_count) { const struct domain_iommu *hd = dom_iommu(d); - int rc; + int ret, rc = 0; + unsigned long i; if ( !iommu_enabled || !hd->platform_ops ) return 0; - rc = hd->platform_ops->unmap_page(d, gfn); + if ( hd->platform_ops->unmap_pages ) + rc = hd->platform_ops->unmap_pages(d, gfn, page_count); + else + { + for ( i = 0; i < page_count; i++ ) + { + ret = hd->platform_ops->unmap_page(d, gfn + i); + if ( likely(!rc) ) + rc = ret; + } + } + if ( unlikely(rc) ) { if ( !d->is_shutting_down && printk_ratelimit() ) printk(XENLOG_ERR - "d%d: IOMMU unmapping gfn %#lx failed: %d\n", - d->domain_id, gfn, rc); + "d%d: IOMMU unmapping gfn %#lx page count %lu failed: %d\n", + d->domain_id, gfn, page_count, rc); if ( !is_hardware_domain(d) ) domain_crash(d); diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h index 5803e3f..0446ed3 100644 --- a/xen/include/xen/iommu.h +++ b/xen/include/xen/iommu.h @@ -76,9 +76,14 @@ void iommu_teardown(struct domain *d); #define IOMMUF_readable (1u<<_IOMMUF_readable) #define _IOMMUF_writable 1 #define IOMMUF_writable (1u<<_IOMMUF_writable) -int __must_check iommu_map_page(struct domain *d, unsigned long gfn, - unsigned long mfn, unsigned int flags); -int __must_check iommu_unmap_page(struct domain *d, unsigned long gfn); +int __must_check iommu_map_pages(struct domain *d, unsigned long gfn, + unsigned long mfn, unsigned long page_count, + unsigned int flags); +int __must_check iommu_unmap_pages(struct domain *d, unsigned long gfn, + unsigned long page_count); + +#define iommu_map_page(d,gfn,mfn,flags) (iommu_map_pages(d,gfn,mfn,1,flags)) +#define iommu_unmap_page(d,gfn) (iommu_unmap_pages(d,gfn,1)) enum iommu_feature { @@ -170,7 +175,12 @@ struct iommu_ops { void (*teardown)(struct domain *d); int __must_check (*map_page)(struct domain *d, unsigned long gfn, unsigned long mfn, unsigned int flags); + int __must_check (*map_pages)(struct domain *d, unsigned long gfn, + unsigned long mfn, unsigned long page_count, + unsigned int flags); int __must_check (*unmap_page)(struct domain *d, unsigned long gfn); + int __must_check (*unmap_pages)(struct domain *d, unsigned long gfn, + unsigned long page_count); void (*free_page_table)(struct page_info *); #ifdef CONFIG_X86 void (*update_ire_from_apic)(unsigned int apic, unsigned int reg, unsigned int value); Cheers, -- Julien Grall _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |