[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v4 18/21] xen/arm: p2m: Clean cache PT when the IOMMU doesn't support coherent walk
I forgot to cc Jan and Xiantao on this patch. On 04/22/2014 02:14 PM, Julien Grall wrote: > Some IOMMU doesn't suppport coherent PT walk. When the p2m is shared with > the CPU, Xen has to make sure the PT changes have reached the memory. > > Introduce new IOMMU callback that will retrieve the IOMMU feature for a > specified domain. > > On ARM, the platform can contain multiple IOMMUs. Each of them may not > have the same set of feature. The domain parameter will be used to get the > set of features for IOMMUs used by this domain. > > Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx> > > --- > Changes in v4: > - Patch added > --- > xen/arch/arm/p2m.c | 24 ++++++++++++++++++------ > xen/drivers/passthrough/iommu.c | 11 +++++++++++ > xen/include/xen/iommu.h | 5 +++++ > 3 files changed, 34 insertions(+), 6 deletions(-) > > diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c > index 21219de..996d2bd 100644 > --- a/xen/arch/arm/p2m.c > +++ b/xen/arch/arm/p2m.c > @@ -274,6 +274,18 @@ enum p2m_operation { > CACHEFLUSH, > }; > > +static void unmap_coherent_domain_page(struct domain *d, const void *va) > +{ > + /* Some IOMMU doesn't support coherent PT walk. When the p2m is > + * shared with the CPU, Xen has to make sure that the PT changes have > + * reached the memory > + */ > + if ( need_iommu(d) && !iommu_has_feature(d, IOMMU_FEAT_COHERENT_WALK) ) > + clean_xen_dcache_va_range(va, PAGE_SIZE); > + > + unmap_domain_page(va); > +} > + > static int apply_p2m_changes(struct domain *d, > enum p2m_operation op, > paddr_t start_gpaddr, > @@ -301,7 +313,7 @@ static int apply_p2m_changes(struct domain *d, > { > if ( cur_first_page != p2m_first_level_index(addr) ) > { > - if ( first ) unmap_domain_page(first); > + if ( first ) unmap_coherent_domain_page(d, first); > first = p2m_map_first(p2m, addr); > if ( !first ) > { > @@ -331,7 +343,7 @@ static int apply_p2m_changes(struct domain *d, > > if ( cur_first_offset != first_table_offset(addr) ) > { > - if (second) unmap_domain_page(second); > + if (second) unmap_coherent_domain_page(d, second); > second = > map_domain_page(first[first_table_offset(addr)].p2m.base); > cur_first_offset = first_table_offset(addr); > } > @@ -357,7 +369,7 @@ static int apply_p2m_changes(struct domain *d, > if ( cur_second_offset != second_table_offset(addr) ) > { > /* map third level */ > - if (third) unmap_domain_page(third); > + if (third) unmap_coherent_domain_page(d, third); > third = > map_domain_page(second[second_table_offset(addr)].p2m.base); > cur_second_offset = second_table_offset(addr); > } > @@ -480,9 +492,9 @@ static int apply_p2m_changes(struct domain *d, > rc = 0; > > out: > - if (third) unmap_domain_page(third); > - if (second) unmap_domain_page(second); > - if (first) unmap_domain_page(first); > + if (third) unmap_coherent_domain_page(d, third); > + if (second) unmap_coherent_domain_page(d, second); > + if (first) unmap_coherent_domain_page(d, first); > > spin_unlock(&p2m->lock); > > diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c > index f93dc79..f24fb46 100644 > --- a/xen/drivers/passthrough/iommu.c > +++ b/xen/drivers/passthrough/iommu.c > @@ -344,6 +344,17 @@ void iommu_crash_shutdown(void) > iommu_enabled = iommu_intremap = 0; > } > > +bool_t iommu_has_feature(struct domain *d, uint32_t feature) > +{ > + const struct iommu_ops *ops = domain_hvm_iommu(d)->platform_ops; > + uint32_t features = 0; > + > + if ( iommu_enabled && ops && ops->features ) > + features = ops->features(d); > + > + return !!(features & feature); > +} > + > static void iommu_dump_p2m_table(unsigned char key) > { > struct domain *d; > diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h > index e119379..9ad909f 100644 > --- a/xen/include/xen/iommu.h > +++ b/xen/include/xen/iommu.h > @@ -67,6 +67,10 @@ int iommu_map_page(struct domain *d, unsigned long gfn, > unsigned long mfn, > unsigned int flags); > int iommu_unmap_page(struct domain *d, unsigned long gfn); > > +#define IOMMU_FEAT_COHERENT_WALK (1U<<0) > +bool_t iommu_has_feature(struct domain *d, uint32_t feature); > + > + > #ifdef HAS_PCI > void pt_pci_init(void); > > @@ -139,6 +143,7 @@ struct iommu_ops { > void (*iotlb_flush)(struct domain *d, unsigned long gfn, unsigned int > page_count); > void (*iotlb_flush_all)(struct domain *d); > void (*dump_p2m_table)(struct domain *d); > + uint32_t (*features)(struct domain *d); > }; > > void iommu_suspend(void); > -- Julien Grall _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |