Re: [PATCH 1/7] powerpc: Add interface to get msi region information
On Thu, Sep 19, 2013 at 12:59:17PM +0530, Bharat Bhushan wrote: > This patch adds interface to get following information > - Number of MSI regions (which is number of MSI banks for powerpc). > - Get the region address range: Physical page which have the > address/addresses used for generating MSI interrupt > and size of the page. > > These are required to create IOMMU (Freescale PAMU) mapping for > devices which are directly assigned using VFIO. > > Signed-off-by: Bharat Bhushan > --- > arch/powerpc/include/asm/machdep.h |8 +++ > arch/powerpc/include/asm/pci.h |2 + > arch/powerpc/kernel/msi.c | 18 > arch/powerpc/sysdev/fsl_msi.c | 39 +-- > arch/powerpc/sysdev/fsl_msi.h | 11 - > drivers/pci/msi.c | 26 > include/linux/msi.h|8 +++ > include/linux/pci.h| 13 > 8 files changed, 120 insertions(+), 5 deletions(-) > > ... > diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c > index aca7578..6d85c15 100644 > --- a/drivers/pci/msi.c > +++ b/drivers/pci/msi.c > @@ -30,6 +30,20 @@ static int pci_msi_enable = 1; > > /* Arch hooks */ > > +#ifndef arch_msi_get_region_count > +int arch_msi_get_region_count(void) > +{ > + return 0; > +} > +#endif > + > +#ifndef arch_msi_get_region > +int arch_msi_get_region(int region_num, struct msi_region *region) > +{ > + return 0; > +} > +#endif This #define strategy is gone; see 4287d824 ("PCI: use weak functions for MSI arch-specific functions"). Please use the weak function strategy for your new MSI region functions. > + > #ifndef arch_msi_check_device > int arch_msi_check_device(struct pci_dev *dev, int nvec, int type) > { > @@ -903,6 +917,18 @@ void pci_disable_msi(struct pci_dev *dev) > } > EXPORT_SYMBOL(pci_disable_msi); > > +int msi_get_region_count(void) > +{ > + return arch_msi_get_region_count(); > +} > +EXPORT_SYMBOL(msi_get_region_count); > + > +int msi_get_region(int region_num, struct msi_region *region) > +{ > + return arch_msi_get_region(region_num, region); > +} > +EXPORT_SYMBOL(msi_get_region); Please split these interface additions, i.e., the drivers/pci/msi.c, include/linux/msi.h, and include/linux/pci.h changes, into a separate patch. I don't know enough about VFIO to understand why these new interfaces are needed. Is this the first VFIO IOMMU driver? I see vfio_iommu_spapr_tce.c and vfio_iommu_type1.c but I don't know if they're comparable to the Freescale PAMU. Do other VFIO IOMMU implementations support MSI? If so, do they handle the problem of mapping the MSI regions in a different way? > /** > * pci_msix_table_size - return the number of device's MSI-X table entries > * @dev: pointer to the pci_dev data structure of MSI-X device function > diff --git a/include/linux/msi.h b/include/linux/msi.h > index ee66f3a..ae32601 100644 > --- a/include/linux/msi.h > +++ b/include/linux/msi.h > @@ -50,6 +50,12 @@ struct msi_desc { > struct kobject kobj; > }; > > +struct msi_region { > + int region_num; > + dma_addr_t addr; > + size_t size; > +}; This needs some sort of explanatory comment. > /* > * The arch hook for setup up msi irqs > */ > @@ -58,5 +64,7 @@ void arch_teardown_msi_irq(unsigned int irq); > int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); > void arch_teardown_msi_irqs(struct pci_dev *dev); > int arch_msi_check_device(struct pci_dev* dev, int nvec, int type); > +int arch_msi_get_region_count(void); > +int arch_msi_get_region(int region_num, struct msi_region *region); > > #endif /* LINUX_MSI_H */ > diff --git a/include/linux/pci.h b/include/linux/pci.h > index 186540d..2b26a59 100644 > --- a/include/linux/pci.h > +++ b/include/linux/pci.h > @@ -1126,6 +1126,7 @@ struct msix_entry { > u16 entry; /* driver uses to specify entry, OS writes */ > }; > > +struct msi_region; > > #ifndef CONFIG_PCI_MSI > static inline int pci_enable_msi_block(struct pci_dev *dev, unsigned int > nvec) > @@ -1168,6 +1169,16 @@ static inline int pci_msi_enabled(void) > { > return 0; > } > + > +static inline int msi_get_region_count(void) > +{ > + return 0; > +} > + > +static inline int msi_get_region(int region_num, struct msi_region *region) > +{ > + return 0; > +} > #else > int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec); > int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec); > @@ -1180,6 +1191,8 @@ void pci_disable_msix(struct pci_dev *dev); > void msi_remove_pci_irq_vectors(struct pci_dev *dev); > void pci_restore_msi_state(struct pci_dev *dev); > int pci_msi_enabled(void); > +int msi_get_region_count(void); > +int msi_get_region(int region_num, struct msi_region *region); > #endif > > #ifdef CONFIG_PCIEPORTBUS > -- > 1.7.0.4 > > > -- > To unsubscribe from this list: send the line "uns
[PATCH v4 2/2] iommu: Change iommu driver to call io_page_fault trace event
Change iommu driver call io_page_fault trace event. This iommu_error class event can be enabled to trigger when an iommu error occurs. Trace information includes driver name, device name, iova, and flags. Testing: Added trace calls to iommu_prepare_identity_map() for testing some of the conditions that are hard to trigger. Here is the trace from the testing: swapper/0-1 [003] 2.003774: io_page_fault: IOMMU:pci :00:02.0 iova=0xcb80 flags=0x0002 swapper/0-1 [003] 2.004098: io_page_fault: IOMMU:pci :00:1d.0 iova=0xcadc6000 flags=0x0002 swapper/0-1 [003] 2.004115: io_page_fault: IOMMU:pci :00:1a.0 iova=0xcadc6000 flags=0x0002 swapper/0-1 [003] 2.004129: io_page_fault: IOMMU:pci :00:1f.0 iova=0x flags=0x0002 Signed-off-by: Shuah Khan --- include/linux/iommu.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 7ea319e..a444c79 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -22,6 +22,7 @@ #include #include #include +#include #define IOMMU_READ (1) #define IOMMU_WRITE(2) @@ -227,6 +228,7 @@ static inline int report_iommu_fault(struct iommu_domain *domain, ret = domain->handler(domain, dev, iova, flags, domain->handler_token); + trace_io_page_fault(dev, iova, flags); return ret; } -- 1.8.1.2 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v4 1/2] iommu: Add iommu_error class event to iommu trace
iommu_error class event can be enabled to trigger when an iommu error occurs. This trace event is intended to be called to report the error information. Trace information includes driver name, device name, iova, and flags. iommu_error:io_page_fault Signed-off-by: Shuah Khan --- drivers/iommu/iommu-traces.c | 3 +++ include/trace/events/iommu.h | 33 + 2 files changed, 36 insertions(+) diff --git a/drivers/iommu/iommu-traces.c b/drivers/iommu/iommu-traces.c index a2af60f..71ac5fa 100644 --- a/drivers/iommu/iommu-traces.c +++ b/drivers/iommu/iommu-traces.c @@ -22,3 +22,6 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(detach_device_from_domain); /* iommu_map_unmap */ EXPORT_TRACEPOINT_SYMBOL_GPL(map); EXPORT_TRACEPOINT_SYMBOL_GPL(unmap); + +/* iommu_error */ +EXPORT_TRACEPOINT_SYMBOL_GPL(io_page_fault); diff --git a/include/trace/events/iommu.h b/include/trace/events/iommu.h index 86bcc5a..a8f5c32 100644 --- a/include/trace/events/iommu.h +++ b/include/trace/events/iommu.h @@ -123,6 +123,39 @@ DEFINE_EVENT_PRINT(iommu_map_unmap, unmap, __entry->iova, __entry->size ) ); + +DECLARE_EVENT_CLASS(iommu_error, + + TP_PROTO(struct device *dev, unsigned long iova, int flags), + + TP_ARGS(dev, iova, flags), + + TP_STRUCT__entry( + __string(device, dev_name(dev)) + __string(driver, dev_driver_string(dev)) + __field(u64, iova) + __field(int, flags) + ), + + TP_fast_assign( + __assign_str(device, dev_name(dev)); + __assign_str(driver, dev_driver_string(dev)); + __entry->iova = iova; + __entry->flags = flags; + ), + + TP_printk("IOMMU:%s %s iova=0x%016llx flags=0x%04x", + __get_str(driver), __get_str(device), + __entry->iova, __entry->flags + ) +); + +DEFINE_EVENT(iommu_error, io_page_fault, + + TP_PROTO(struct device *dev, unsigned long iova, int flags), + + TP_ARGS(dev, iova, flags) +); #endif /* _TRACE_IOMMU_H */ /* This part must be outside protection */ -- 1.8.1.2 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH v4 0/2] iommu: Add iommu_error class event to iommu trace
This patch set adds iommu_error class event to iommu trace. iommu_error class event can be enabled to trigger when an iommu error occurs. This trace event is intended to be called to report the error information. Trace information includes driver name, device name, iova, and flags. iommu_error:io_page_fault This patch set depends on the previous patch set that added iommu tracing feature. Reference: http://www.kernelhub.org/?msg=313155&p=2 http://www.kernelhub.org/?msg=313156&p=2 Shuah Khan (2): iommu: Add iommu_error class event to iommu trace iommu: Change iommu driver to call io_page_fault trace event drivers/iommu/iommu-traces.c | 3 +++ include/linux/iommu.h| 2 ++ include/trace/events/iommu.h | 33 + 3 files changed, 38 insertions(+) -- 1.8.1.2 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 7/7] iommu/arm-smmu: Clear global and context bank fault status and syndrome registers
On Tue, Sep 24, 2013 at 11:42:52AM -0400, Will Deacon wrote: > On Tue, Sep 24, 2013 at 04:07:01PM +0100, Andreas Herrmann wrote: > > Signed-off-by: Andreas Herrmann > > --- > > drivers/iommu/arm-smmu.c |9 + > > 1 file changed, 9 insertions(+) > > > > diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c > > index 251564e..a499146 100644 > > --- a/drivers/iommu/arm-smmu.c > > +++ b/drivers/iommu/arm-smmu.c > > @@ -645,6 +645,10 @@ static void arm_smmu_init_context_bank(struct > > arm_smmu_domain *smmu_domain) > > stage1 = root_cfg->cbar != CBAR_TYPE_S2_TRANS; > > cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, root_cfg->cbndx); > > > > + /* clear fsr */ > > + writel_relaxed(0x, cb_base + ARM_SMMU_CB_FSR); > > + writel_relaxed(0, cb_base + ARM_SMMU_CB_FSYNR0); > > + > > /* CBAR */ > > reg = root_cfg->cbar; > > if (smmu->version == 1) > > @@ -1570,6 +1574,11 @@ static void arm_smmu_device_reset(struct > > arm_smmu_device *smmu) > > int i = 0; > > u32 scr0 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sCR0); > > > > + /* clear global FSRs */ > > + writel(0x, gr0_base + ARM_SMMU_GR0_sGFSR); > > + writel(0, gr0_base + ARM_SMMU_GR0_sGFSYNR0); > > + writel(0, gr0_base + ARM_SMMU_GR0_sGFSYNR1); > > Why do you need this? According to the spec the status and syndrome registers have unknown/unpredictable reset values. So better set known values before we start to use these registers (ie. handle faults where we read them). No? Andreas ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/7] iommu/arm-smmu: Calculate SMMU_CB_BASE from smmu register values
On Tue, Sep 24, 2013 at 11:34:57AM -0400, Will Deacon wrote: > On Tue, Sep 24, 2013 at 04:06:56PM +0100, Andreas Herrmann wrote: > > Currently it is derived from smmu resource size. If the resource size > > is wrongly specified (e.g. too large) this leads to a miscalculation > > and can cause undefined behaviour when context bank registers are > > modified. > > > > Signed-off-by: Andreas Herrmann > > --- > > drivers/iommu/arm-smmu.c |7 +-- > > 1 file changed, 5 insertions(+), 2 deletions(-) > > > > diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c > > index 97b764b..f5a856e 100644 > > --- a/drivers/iommu/arm-smmu.c > > +++ b/drivers/iommu/arm-smmu.c > > @@ -207,7 +207,7 @@ > > #define CBA2R_RW64_64BIT (1 << 0) > > > > /* Translation context bank */ > > -#define ARM_SMMU_CB_BASE(smmu) ((smmu)->base + ((smmu)->size > > >> 1)) > > +#define ARM_SMMU_CB_BASE(smmu) ((smmu)->cb_base) > > #define ARM_SMMU_CB(smmu, n) ((n) * (smmu)->pagesize) > > > > #define ARM_SMMU_CB_SCTLR 0x0 > > @@ -339,6 +339,7 @@ struct arm_smmu_device { > > struct device_node *parent_of_node; > > > > void __iomem*base; > > + void __iomem*cb_base; > > unsigned long size; > > unsigned long pagesize; > > > > @@ -1701,7 +1702,9 @@ static int arm_smmu_device_cfg_probe(struct > > arm_smmu_device *smmu) > > > > /* Check that we ioremapped enough */ > > size = 1 << (((id >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + > > 1); > > - size *= (smmu->pagesize << 1); > > + size *= smmu->pagesize; > > + smmu->cb_base = smmu->base + size; > > + size *= 2; > > if (smmu->size < size) > > dev_warn(smmu->dev, > > "device is 0x%lx bytes but only mapped 0x%lx!\n", > > Hmm, this is a tricky one. We know that we have an inconsistency (i.e. the > DT and the hardware don't agree on the size of the device) but we warn and > attempt to continue with the value from the DT. I don't think that trusting > the hardware is the right thing to do in this case, since it's not possible > to change so we should let the DT act as an override. > In other words: if the device tree is wrong, go fix it. Yes, I've found this issue with a wrong DT. With the original code there was some weirdness when setting certain context bank registers. (Identifying the root cause was not straight forward.) I think it's somehow odd not to trust the hardware values in the first place and to add (right from the beginning) a quirk for potential implementation bugs. Are there already implementations that use wrong register values that are required to determine the partitioning of the SMMU address space? If there is a mismatch it's hard to say which value is the correct one. I think there are three options: (1) just print a warning about the mismatch (2) print a warning + override based on DT (3) print a warning + override based on DT + have an option to switch off the override So, what's your choice? Andreas ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 3/7] ARM: dma-mapping: Always pass proper prot flags to iommu_map()
On Tue, Sep 24, 2013 at 11:36:25AM -0400, Will Deacon wrote: > On Tue, Sep 24, 2013 at 04:06:57PM +0100, Andreas Herrmann wrote: > > ... otherwise it is impossible for the low level iommu driver to > > figure out which pte flags should be used. > > > > In __map_sg_chunk we can derive the flags from dma_data_direction. > > > > In __iommu_create_mapping we should treat the memory like > > DMA_BIDIRECTIONAL and pass both IOMMU_READ and IOMMU_WRITE to > > iommu_map. > > __iommu_create_mapping is used during dma_alloc_coherent (via > > arm_iommu_alloc_attrs). AFAIK dma_alloc_coherent is responsible for > > allocation _and_ mapping. I think this implies that access to the > > mapped pages should be allowed. > > > > Cc: Marek Szyprowski > > Signed-off-by: Andreas Herrmann > > --- > > arch/arm/mm/dma-mapping.c | 20 ++-- > > 1 file changed, 18 insertions(+), 2 deletions(-) > > > > diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c > > index f5e1a84..95abed8 100644 > > --- a/arch/arm/mm/dma-mapping.c > > +++ b/arch/arm/mm/dma-mapping.c > > @@ -1232,7 +1232,8 @@ __iommu_create_mapping(struct device *dev, struct > > page **pages, size_t size) > > break; > > > > len = (j - i) << PAGE_SHIFT; > > - ret = iommu_map(mapping->domain, iova, phys, len, 0); > > + ret = iommu_map(mapping->domain, iova, phys, len, > > + IOMMU_READ|IOMMU_WRITE); > > if (ret < 0) > > goto fail; > > iova += len; > > @@ -1444,6 +1445,7 @@ static int __map_sg_chunk(struct device *dev, struct > > scatterlist *sg, > > int ret = 0; > > unsigned int count; > > struct scatterlist *s; > > + int prot; > > > > size = PAGE_ALIGN(size); > > *handle = DMA_ERROR_CODE; > > @@ -1460,7 +1462,21 @@ static int __map_sg_chunk(struct device *dev, struct > > scatterlist *sg, > > !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs)) > > __dma_page_cpu_to_dev(sg_page(s), s->offset, s->length, > > dir); > > > > - ret = iommu_map(mapping->domain, iova, phys, len, 0); > > + switch (dir) { > > + case DMA_BIDIRECTIONAL: > > + prot = IOMMU_READ | IOMMU_WRITE; > > + break; > > + case DMA_TO_DEVICE: > > + prot = IOMMU_READ; > > + break; > > + case DMA_FROM_DEVICE: > > + prot = IOMMU_WRITE; > > + break; > > + default: > > + prot = 0; > > + } > > + > > + ret = iommu_map(mapping->domain, iova, phys, len, prot); > > I already added this code to arm_coherent_iommu_map_page but forgot to > update the rest of the time. Could you shift the switch into a helper and > call that instead of inlining it explicitly? Yes, will do so. Andreas ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 7/7] iommu/arm-smmu: Clear global and context bank fault status and syndrome registers
On Tue, Sep 24, 2013 at 04:07:01PM +0100, Andreas Herrmann wrote: > Signed-off-by: Andreas Herrmann > --- > drivers/iommu/arm-smmu.c |9 + > 1 file changed, 9 insertions(+) > > diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c > index 251564e..a499146 100644 > --- a/drivers/iommu/arm-smmu.c > +++ b/drivers/iommu/arm-smmu.c > @@ -645,6 +645,10 @@ static void arm_smmu_init_context_bank(struct > arm_smmu_domain *smmu_domain) > stage1 = root_cfg->cbar != CBAR_TYPE_S2_TRANS; > cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, root_cfg->cbndx); > > + /* clear fsr */ > + writel_relaxed(0x, cb_base + ARM_SMMU_CB_FSR); > + writel_relaxed(0, cb_base + ARM_SMMU_CB_FSYNR0); > + > /* CBAR */ > reg = root_cfg->cbar; > if (smmu->version == 1) > @@ -1570,6 +1574,11 @@ static void arm_smmu_device_reset(struct > arm_smmu_device *smmu) > int i = 0; > u32 scr0 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sCR0); > > + /* clear global FSRs */ > + writel(0x, gr0_base + ARM_SMMU_GR0_sGFSR); > + writel(0, gr0_base + ARM_SMMU_GR0_sGFSYNR0); > + writel(0, gr0_base + ARM_SMMU_GR0_sGFSYNR1); Why do you need this? Will ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 6/7] iommu/arm-smmu: Add module parameter arm-smmu=off|force_isolation
On Tue, Sep 24, 2013 at 04:07:00PM +0100, Andreas Herrmann wrote: > arm-smmu= arm-smmu driver option > > off Disable arm-smmu driver (ie. ignore available SMMUs) > > force_isolation > Try to attach each master device on every SMMU to a > separate iommu_domain. > > Default is that driver detects SMMUs but no translation is configured > (transactions just bypass translation process). > > Signed-off-by: Andreas Herrmann > --- > drivers/iommu/arm-smmu.c | 26 ++ > 1 file changed, 26 insertions(+) > > diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c > index 3eb2259..251564e 100644 > --- a/drivers/iommu/arm-smmu.c > +++ b/drivers/iommu/arm-smmu.c > @@ -399,6 +399,9 @@ struct arm_smmu_domain { > static DEFINE_SPINLOCK(arm_smmu_devices_lock); > static LIST_HEAD(arm_smmu_devices); > > +static bool arm_smmu_disabled; > +static bool arm_smmu_force_isolation; > + > static struct arm_smmu_master *find_smmu_master(struct arm_smmu_device *smmu, > struct device_node *dev_node) > { > @@ -1837,6 +1840,9 @@ static int arm_smmu_device_dt_probe(struct > platform_device *pdev) > struct of_phandle_args masterspec; > int num_irqs, i, err; > > + if (arm_smmu_disabled) > + return -ENODEV; > + > smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL); > if (!smmu) { > dev_err(dev, "failed to allocate arm_smmu_device\n"); > @@ -2022,6 +2028,23 @@ static struct platform_driver arm_smmu_driver = { > .remove = arm_smmu_device_remove, > }; > > +static int __init arm_smmu_parse_options(char *str) > +{ > + if (*str) { > + str++; > + if (!strncmp(str, "off", 3)) > + arm_smmu_disabled = true; > + else if(!strncmp(str, "force_isolation", 15)) > + arm_smmu_force_isolation = true; > + else { > + pr_warn("arm_smmu: invalid parameter (\"%s\")\n", str); > + return 0; > + } > + } > + return 1; > +} > +__setup("arm-smmu", arm_smmu_parse_options); If this is going to be a common function for IOMMUs, let's instead move the command-line parsing out into the generic IOMMU layer, then have an optional callback into the low-level IOMMU driver for enabling/disabling it. Will ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 3/7] ARM: dma-mapping: Always pass proper prot flags to iommu_map()
On Tue, Sep 24, 2013 at 04:06:57PM +0100, Andreas Herrmann wrote: > ... otherwise it is impossible for the low level iommu driver to > figure out which pte flags should be used. > > In __map_sg_chunk we can derive the flags from dma_data_direction. > > In __iommu_create_mapping we should treat the memory like > DMA_BIDIRECTIONAL and pass both IOMMU_READ and IOMMU_WRITE to > iommu_map. > __iommu_create_mapping is used during dma_alloc_coherent (via > arm_iommu_alloc_attrs). AFAIK dma_alloc_coherent is responsible for > allocation _and_ mapping. I think this implies that access to the > mapped pages should be allowed. > > Cc: Marek Szyprowski > Signed-off-by: Andreas Herrmann > --- > arch/arm/mm/dma-mapping.c | 20 ++-- > 1 file changed, 18 insertions(+), 2 deletions(-) > > diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c > index f5e1a84..95abed8 100644 > --- a/arch/arm/mm/dma-mapping.c > +++ b/arch/arm/mm/dma-mapping.c > @@ -1232,7 +1232,8 @@ __iommu_create_mapping(struct device *dev, struct page > **pages, size_t size) > break; > > len = (j - i) << PAGE_SHIFT; > - ret = iommu_map(mapping->domain, iova, phys, len, 0); > + ret = iommu_map(mapping->domain, iova, phys, len, > + IOMMU_READ|IOMMU_WRITE); > if (ret < 0) > goto fail; > iova += len; > @@ -1444,6 +1445,7 @@ static int __map_sg_chunk(struct device *dev, struct > scatterlist *sg, > int ret = 0; > unsigned int count; > struct scatterlist *s; > + int prot; > > size = PAGE_ALIGN(size); > *handle = DMA_ERROR_CODE; > @@ -1460,7 +1462,21 @@ static int __map_sg_chunk(struct device *dev, struct > scatterlist *sg, > !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs)) > __dma_page_cpu_to_dev(sg_page(s), s->offset, s->length, > dir); > > - ret = iommu_map(mapping->domain, iova, phys, len, 0); > + switch (dir) { > + case DMA_BIDIRECTIONAL: > + prot = IOMMU_READ | IOMMU_WRITE; > + break; > + case DMA_TO_DEVICE: > + prot = IOMMU_READ; > + break; > + case DMA_FROM_DEVICE: > + prot = IOMMU_WRITE; > + break; > + default: > + prot = 0; > + } > + > + ret = iommu_map(mapping->domain, iova, phys, len, prot); I already added this code to arm_coherent_iommu_map_page but forgot to update the rest of the time. Could you shift the switch into a helper and call that instead of inlining it explicitly? Cheers, Will ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 4/7] iommu/arm-smmu: Check for num_context_irqs > 0 to avoid divide by zero exception
On Tue, Sep 24, 2013 at 04:06:58PM +0100, Andreas Herrmann wrote: > With the right (or wrong;-) definition of v1 SMMU node in DTB it is > possible to trigger a division by zero in arm_smmu_init_domain_context > (if number of context irqs is 0): > >if (smmu->version == 1) { >root_cfg->irptndx = atomic_inc_return(&smmu->irptndx); > → root_cfg->irptndx %= smmu->num_context_irqs; >} else { > > Avoid this by checking for num_context_irqs > 0 before trying to > assign interrupts to contexts. > > Signed-off-by: Andreas Herrmann > --- > drivers/iommu/arm-smmu.c | 31 +-- > 1 file changed, 17 insertions(+), 14 deletions(-) > > diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c > index f5a856e..0dfd255 100644 > --- a/drivers/iommu/arm-smmu.c > +++ b/drivers/iommu/arm-smmu.c > @@ -828,21 +828,24 @@ static int arm_smmu_init_domain_context(struct > iommu_domain *domain, > return ret; > > root_cfg->cbndx = ret; > - if (smmu->version == 1) { > - root_cfg->irptndx = atomic_inc_return(&smmu->irptndx); > - root_cfg->irptndx %= smmu->num_context_irqs; > - } else { > - root_cfg->irptndx = root_cfg->cbndx; > - } > > - irq = smmu->irqs[smmu->num_global_irqs + root_cfg->irptndx]; > - ret = request_irq(irq, arm_smmu_context_fault, IRQF_SHARED, > - "arm-smmu-context-fault", domain); > - if (IS_ERR_VALUE(ret)) { > - dev_err(smmu->dev, "failed to request context IRQ %d (%u)\n", > - root_cfg->irptndx, irq); > - root_cfg->irptndx = -1; > - goto out_free_context; > + if (smmu->num_context_irqs) { Can we move this check to probe time, to avoid re-evaluating it every time we initialise a new domain? Will ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/7] iommu/arm-smmu: Calculate SMMU_CB_BASE from smmu register values
On Tue, Sep 24, 2013 at 04:06:56PM +0100, Andreas Herrmann wrote: > Currently it is derived from smmu resource size. If the resource size > is wrongly specified (e.g. too large) this leads to a miscalculation > and can cause undefined behaviour when context bank registers are > modified. > > Signed-off-by: Andreas Herrmann > --- > drivers/iommu/arm-smmu.c |7 +-- > 1 file changed, 5 insertions(+), 2 deletions(-) > > diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c > index 97b764b..f5a856e 100644 > --- a/drivers/iommu/arm-smmu.c > +++ b/drivers/iommu/arm-smmu.c > @@ -207,7 +207,7 @@ > #define CBA2R_RW64_64BIT (1 << 0) > > /* Translation context bank */ > -#define ARM_SMMU_CB_BASE(smmu) ((smmu)->base + ((smmu)->size > >> 1)) > +#define ARM_SMMU_CB_BASE(smmu) ((smmu)->cb_base) > #define ARM_SMMU_CB(smmu, n) ((n) * (smmu)->pagesize) > > #define ARM_SMMU_CB_SCTLR0x0 > @@ -339,6 +339,7 @@ struct arm_smmu_device { > struct device_node *parent_of_node; > > void __iomem*base; > + void __iomem*cb_base; > unsigned long size; > unsigned long pagesize; > > @@ -1701,7 +1702,9 @@ static int arm_smmu_device_cfg_probe(struct > arm_smmu_device *smmu) > > /* Check that we ioremapped enough */ > size = 1 << (((id >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + > 1); > - size *= (smmu->pagesize << 1); > + size *= smmu->pagesize; > + smmu->cb_base = smmu->base + size; > + size *= 2; > if (smmu->size < size) > dev_warn(smmu->dev, >"device is 0x%lx bytes but only mapped 0x%lx!\n", Hmm, this is a tricky one. We know that we have an inconsistency (i.e. the DT and the hardware don't agree on the size of the device) but we warn and attempt to continue with the value from the DT. I don't think that trusting the hardware is the right thing to do in this case, since it's not possible to change so we should let the DT act as an override. In other words: if the device tree is wrong, go fix it. Will ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 0/7]: iommu/arm-smmu: Misc fixes/adaptions
On Tue, Sep 24, 2013 at 04:06:54PM +0100, Andreas Herrmann wrote: > Hi, Hi Andreas, > Following patches fix misc issues, that I've seen when using arm-smmu > driver with MMU-400. Thanks for the patches! I'll respond to each one in turn. Will ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 1/7] iommu/arm-smmu: Switch to arch_initcall for driver registration
iommu/arm-smmu: Remove bogus semicolon from if conditions Those prevented proper registration of arm_smmu_ops. Signed-off-by: Andreas Herrmann --- drivers/iommu/arm-smmu.c |4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) Will, It seems that I've managed to exclude the very first patch of the series. Here it is. Regards, Andreas diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index f417e89..be56846 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1966,10 +1966,10 @@ static int __init arm_smmu_init(void) return ret; /* Oh, for a proper bus abstraction */ - if (!iommu_present(&platform_bus_type)); + if (!iommu_present(&platform_bus_type)) bus_set_iommu(&platform_bus_type, &arm_smmu_ops); - if (!iommu_present(&amba_bustype)); + if (!iommu_present(&amba_bustype)) bus_set_iommu(&amba_bustype, &arm_smmu_ops); return 0; -- 1.7.9.5 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 1/7] iommu/arm-smmu: Switch to arch_initcall for driver registration
On Tue, Sep 24, 2013 at 04:14:30PM +0100, Andreas Herrmann wrote: > iommu/arm-smmu: Remove bogus semicolon from if conditions > > Those prevented proper registration of arm_smmu_ops. > > Signed-off-by: Andreas Herrmann > --- > drivers/iommu/arm-smmu.c |4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > Will, > > It seems that I've managed to exclude the very first patch of the > series. Here it is. No worries; I already have a fix for this and Joerg pulled it today. Will ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 0/7]: iommu/arm-smmu: Misc fixes/adaptions
Hi, Following patches fix misc issues, that I've seen when using arm-smmu driver with MMU-400. I also suggest to add an option to automatically create domains for each master of detected SMMUs. (Similar to what is available for other iommu driver(s).) Comments welcome. Regards, Andreas PS: Patches are against v3.12-rc1-336-gd8524ae (and yes I probably need to rebase against Joerg's or your smmu tree but I wanted to sent this out to get feedback as soon as possible.) ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 2/7] iommu/arm-smmu: Calculate SMMU_CB_BASE from smmu register values
Currently it is derived from smmu resource size. If the resource size is wrongly specified (e.g. too large) this leads to a miscalculation and can cause undefined behaviour when context bank registers are modified. Signed-off-by: Andreas Herrmann --- drivers/iommu/arm-smmu.c |7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 97b764b..f5a856e 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -207,7 +207,7 @@ #define CBA2R_RW64_64BIT (1 << 0) /* Translation context bank */ -#define ARM_SMMU_CB_BASE(smmu) ((smmu)->base + ((smmu)->size >> 1)) +#define ARM_SMMU_CB_BASE(smmu) ((smmu)->cb_base) #define ARM_SMMU_CB(smmu, n) ((n) * (smmu)->pagesize) #define ARM_SMMU_CB_SCTLR 0x0 @@ -339,6 +339,7 @@ struct arm_smmu_device { struct device_node *parent_of_node; void __iomem*base; + void __iomem*cb_base; unsigned long size; unsigned long pagesize; @@ -1701,7 +1702,9 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) /* Check that we ioremapped enough */ size = 1 << (((id >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1); - size *= (smmu->pagesize << 1); + size *= smmu->pagesize; + smmu->cb_base = smmu->base + size; + size *= 2; if (smmu->size < size) dev_warn(smmu->dev, "device is 0x%lx bytes but only mapped 0x%lx!\n", -- 1.7.9.5 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 1/7] iommu/arm-smmu: Switch to arch_initcall for driver registration
This should ensure that arm-smmu is initialized before other drivers start handling devices that propably need smmu support. Also remove module_exit function as we most likely never want to unload this driver. Signed-off-by: Andreas Herrmann --- drivers/iommu/arm-smmu.c |8 +--- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index be56846..97b764b 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1975,13 +1975,7 @@ static int __init arm_smmu_init(void) return 0; } -static void __exit arm_smmu_exit(void) -{ - return platform_driver_unregister(&arm_smmu_driver); -} - -module_init(arm_smmu_init); -module_exit(arm_smmu_exit); +arch_initcall(arm_smmu_init); MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations"); MODULE_AUTHOR("Will Deacon "); -- 1.7.9.5 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 6/7] iommu/arm-smmu: Add module parameter arm-smmu=off|force_isolation
arm-smmu= arm-smmu driver option off Disable arm-smmu driver (ie. ignore available SMMUs) force_isolation Try to attach each master device on every SMMU to a separate iommu_domain. Default is that driver detects SMMUs but no translation is configured (transactions just bypass translation process). Signed-off-by: Andreas Herrmann --- drivers/iommu/arm-smmu.c | 26 ++ 1 file changed, 26 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 3eb2259..251564e 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -399,6 +399,9 @@ struct arm_smmu_domain { static DEFINE_SPINLOCK(arm_smmu_devices_lock); static LIST_HEAD(arm_smmu_devices); +static bool arm_smmu_disabled; +static bool arm_smmu_force_isolation; + static struct arm_smmu_master *find_smmu_master(struct arm_smmu_device *smmu, struct device_node *dev_node) { @@ -1837,6 +1840,9 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) struct of_phandle_args masterspec; int num_irqs, i, err; + if (arm_smmu_disabled) + return -ENODEV; + smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL); if (!smmu) { dev_err(dev, "failed to allocate arm_smmu_device\n"); @@ -2022,6 +2028,23 @@ static struct platform_driver arm_smmu_driver = { .remove = arm_smmu_device_remove, }; +static int __init arm_smmu_parse_options(char *str) +{ + if (*str) { + str++; + if (!strncmp(str, "off", 3)) + arm_smmu_disabled = true; + else if(!strncmp(str, "force_isolation", 15)) + arm_smmu_force_isolation = true; + else { + pr_warn("arm_smmu: invalid parameter (\"%s\")\n", str); + return 0; + } + } + return 1; +} +__setup("arm-smmu", arm_smmu_parse_options); + static int __init arm_smmu_init(void) { int ret; @@ -2037,6 +2060,9 @@ static int __init arm_smmu_init(void) if (!iommu_present(&amba_bustype)) bus_set_iommu(&amba_bustype, &arm_smmu_ops); + if (arm_smmu_force_isolation) + arm_smmu_isolate_devices(); + return 0; } -- 1.7.9.5 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 3/7] ARM: dma-mapping: Always pass proper prot flags to iommu_map()
... otherwise it is impossible for the low level iommu driver to figure out which pte flags should be used. In __map_sg_chunk we can derive the flags from dma_data_direction. In __iommu_create_mapping we should treat the memory like DMA_BIDIRECTIONAL and pass both IOMMU_READ and IOMMU_WRITE to iommu_map. __iommu_create_mapping is used during dma_alloc_coherent (via arm_iommu_alloc_attrs). AFAIK dma_alloc_coherent is responsible for allocation _and_ mapping. I think this implies that access to the mapped pages should be allowed. Cc: Marek Szyprowski Signed-off-by: Andreas Herrmann --- arch/arm/mm/dma-mapping.c | 20 ++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index f5e1a84..95abed8 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -1232,7 +1232,8 @@ __iommu_create_mapping(struct device *dev, struct page **pages, size_t size) break; len = (j - i) << PAGE_SHIFT; - ret = iommu_map(mapping->domain, iova, phys, len, 0); + ret = iommu_map(mapping->domain, iova, phys, len, + IOMMU_READ|IOMMU_WRITE); if (ret < 0) goto fail; iova += len; @@ -1444,6 +1445,7 @@ static int __map_sg_chunk(struct device *dev, struct scatterlist *sg, int ret = 0; unsigned int count; struct scatterlist *s; + int prot; size = PAGE_ALIGN(size); *handle = DMA_ERROR_CODE; @@ -1460,7 +1462,21 @@ static int __map_sg_chunk(struct device *dev, struct scatterlist *sg, !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs)) __dma_page_cpu_to_dev(sg_page(s), s->offset, s->length, dir); - ret = iommu_map(mapping->domain, iova, phys, len, 0); + switch (dir) { + case DMA_BIDIRECTIONAL: + prot = IOMMU_READ | IOMMU_WRITE; + break; + case DMA_TO_DEVICE: + prot = IOMMU_READ; + break; + case DMA_FROM_DEVICE: + prot = IOMMU_WRITE; + break; + default: + prot = 0; + } + + ret = iommu_map(mapping->domain, iova, phys, len, prot); if (ret < 0) goto fail; count += len >> PAGE_SHIFT; -- 1.7.9.5 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 5/7] iommu/arm-smmu: Add function that isolates all masters for all SMMUs
Each device is put into its own protection domain (if possible). For configuration with one or just a view masters per SMMU that is easy to achieve. In case of many devices per SMMU (e.g. MMU-500 with it's distributed translation support) isolation of each device might not be possible -- depending on number of available SMR groups and/or context banks. Derive dma_base and size from (coherent_)dma_mask of device Signed-off-by: Andreas Herrmann --- drivers/iommu/arm-smmu.c | 59 ++ 1 file changed, 59 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 0dfd255..3eb2259 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -46,6 +46,7 @@ #include #include +#include /* Maximum number of stream IDs assigned to a single device */ #define MAX_MASTER_STREAMIDS 8 @@ -1768,6 +1769,64 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) return 0; } +extern struct platform_device *of_find_device_by_node(struct device_node *np); + +static int arm_smmu_isolate_devices(void) +{ + struct dma_iommu_mapping *mapping; + struct arm_smmu_device *smmu; + struct rb_node *rbn; + struct arm_smmu_master *master; + struct platform_device *pdev; + struct device *dev; + void __iomem *gr0_base; + u32 cr0; + int ret = 0; + size_t size; + + list_for_each_entry(smmu, &arm_smmu_devices, list) { + rbn = rb_first(&smmu->masters); + while (rbn) { + master = container_of(rbn, struct arm_smmu_master, node); + pdev = of_find_device_by_node(master->of_node); + if (!pdev) + break; + dev = &pdev->dev; + + size = (size_t) dev->coherent_dma_mask; + size = size ? : (unsigned long) dev->dma_mask; + if (!size) { + dev_warn(dev, "(coherent_)dma_mask not set\n"); + continue; + } + + mapping = arm_iommu_create_mapping(&platform_bus_type, + 0, size, 0); + if (IS_ERR(mapping)) { + ret = PTR_ERR(mapping); + dev_info(dev, "arm_iommu_create_mapping failed\n"); + goto out; + } + + ret = arm_iommu_attach_device(dev, mapping); + if (ret < 0) { + dev_info(dev, "arm_iommu_attach_device failed\n"); + arm_iommu_release_mapping(mapping); + } + rbn = rb_next(rbn); + } + + gr0_base = ARM_SMMU_GR0(smmu); + cr0 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sCR0); + cr0 |= sCR0_USFCFG; + writel(cr0, gr0_base + ARM_SMMU_GR0_sCR0); + } + +out: + return ret; +} + + static int arm_smmu_device_dt_probe(struct platform_device *pdev) { struct resource *res; -- 1.7.9.5 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 4/7] iommu/arm-smmu: Check for num_context_irqs > 0 to avoid divide by zero exception
With the right (or wrong;-) definition of v1 SMMU node in DTB it is possible to trigger a division by zero in arm_smmu_init_domain_context (if number of context irqs is 0): if (smmu->version == 1) { root_cfg->irptndx = atomic_inc_return(&smmu->irptndx); → root_cfg->irptndx %= smmu->num_context_irqs; } else { Avoid this by checking for num_context_irqs > 0 before trying to assign interrupts to contexts. Signed-off-by: Andreas Herrmann --- drivers/iommu/arm-smmu.c | 31 +-- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index f5a856e..0dfd255 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -828,21 +828,24 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain, return ret; root_cfg->cbndx = ret; - if (smmu->version == 1) { - root_cfg->irptndx = atomic_inc_return(&smmu->irptndx); - root_cfg->irptndx %= smmu->num_context_irqs; - } else { - root_cfg->irptndx = root_cfg->cbndx; - } - irq = smmu->irqs[smmu->num_global_irqs + root_cfg->irptndx]; - ret = request_irq(irq, arm_smmu_context_fault, IRQF_SHARED, - "arm-smmu-context-fault", domain); - if (IS_ERR_VALUE(ret)) { - dev_err(smmu->dev, "failed to request context IRQ %d (%u)\n", - root_cfg->irptndx, irq); - root_cfg->irptndx = -1; - goto out_free_context; + if (smmu->num_context_irqs) { + if (smmu->version == 1) { + root_cfg->irptndx = atomic_inc_return(&smmu->irptndx); + root_cfg->irptndx %= smmu->num_context_irqs; + } else { + root_cfg->irptndx = root_cfg->cbndx; + } + + irq = smmu->irqs[smmu->num_global_irqs + root_cfg->irptndx]; + ret = request_irq(irq, arm_smmu_context_fault, IRQF_SHARED, + "arm-smmu-context-fault", domain); + if (IS_ERR_VALUE(ret)) { + dev_err(smmu->dev, "failed to request context IRQ %d (%u)\n", + root_cfg->irptndx, irq); + root_cfg->irptndx = -1; + goto out_free_context; + } } root_cfg->smmu = smmu; -- 1.7.9.5 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 7/7] iommu/arm-smmu: Clear global and context bank fault status and syndrome registers
Signed-off-by: Andreas Herrmann --- drivers/iommu/arm-smmu.c |9 + 1 file changed, 9 insertions(+) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 251564e..a499146 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -645,6 +645,10 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) stage1 = root_cfg->cbar != CBAR_TYPE_S2_TRANS; cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, root_cfg->cbndx); + /* clear fsr */ + writel_relaxed(0x, cb_base + ARM_SMMU_CB_FSR); + writel_relaxed(0, cb_base + ARM_SMMU_CB_FSYNR0); + /* CBAR */ reg = root_cfg->cbar; if (smmu->version == 1) @@ -1570,6 +1574,11 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu) int i = 0; u32 scr0 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sCR0); + /* clear global FSRs */ + writel(0x, gr0_base + ARM_SMMU_GR0_sGFSR); + writel(0, gr0_base + ARM_SMMU_GR0_sGFSYNR0); + writel(0, gr0_base + ARM_SMMU_GR0_sGFSYNR1); + /* Mark all SMRn as invalid and all S2CRn as bypass */ for (i = 0; i < smmu->num_mapping_groups; ++i) { writel_relaxed(~SMR_VALID, gr0_base + ARM_SMMU_GR0_SMR(i)); -- 1.7.9.5 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v2] intel-iommu: Quiesce devices before disabling IOMMU
On Tue, 2013-09-24 at 15:16 +0200, Joerg Roedel wrote: > > I am not convinced that this is the right approach. If a device wasn't > translated by VT-d in the old kernel doesn't mean it will not be > translated in the new kernel. How about unconditionally resetting all > PCI busses and/or functions here before IOMMU initialization proceeds? Forget the IOMMU. If a device is doing DMA in the old kernel, and *continues* doing DMA under the new kernel, surely something ought to shut it down? It's the generic kexec or machine_shutdown code which should be doing this, not IOMMU code. *Especially* not Intel-specific IOMMU code. It does not live here. If anything, the IOMMU gives you a way to *survive* this kind of thing and means that you might get away without quiescing devices when otherwise you would have died. -- dwmw2 smime.p7s Description: S/MIME cryptographic signature ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v2] intel-iommu: Quiesce devices before disabling IOMMU
On Wed, Sep 18, 2013 at 03:09:01PM +0900, Takao Indoh wrote: > + /* > + * In the case of kdump, ioremap is needed because root-entry table > + * exists in first kernel's memory area which is not mapped in second > + * kernel > + */ > + root = (struct root_entry *)ioremap(addr, PAGE_SIZE); > + if (!root) > + return; > + > + for (bus = 0; bus < ROOT_ENTRY_NR; bus++) { > + if (!root_present(&root[bus])) > + continue; > + > + context = (struct context_entry *)ioremap( > + root[bus].val & VTD_PAGE_MASK, PAGE_SIZE); > + if (!context) > + continue; > + > + for (devfn = 0; devfn < CONTEXT_ENTRY_NR; devfn++) { > + if (!context_present(&context[devfn])) > + continue; > + > + dev = pci_get_domain_bus_and_slot(segment, bus, devfn); > + if (!dev) > + continue; > + > + if (!pci_reset_bus(dev->bus)) /* go to next bus */ > + break; > + else /* Try per-function reset */ > + pci_reset_function(dev); > + > + } > + iounmap(context); > + } > + iounmap(root); I am not convinced that this is the right approach. If a device wasn't translated by VT-d in the old kernel doesn't mean it will not be translated in the new kernel. How about unconditionally resetting all PCI busses and/or functions here before IOMMU initialization proceeds? Joerg ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 1/2] iommu: Add iommu_fault class event to iommu trace
On 09/24/2013 04:48 AM, Joerg Roedel wrote: On Fri, Aug 16, 2013 at 11:20:16AM -0600, Shuah Khan wrote: +DEFINE_EVENT(iommu_fault, report_fault, + + TP_PROTO(struct device *dev, unsigned long iova, int flags), + + TP_ARGS(dev, iova, flags) +); I am not entirely happy with the naming. It is better to name the class iommu_error and the page-fault event io_page_fault. This makes it more clear what kind of fault it is. Joerg Joerg, Yes, iommu_error and io_page_fault sounds better. I will rename and send the updated patch. -- Shuah -- Shuah Khan Senior Linux Kernel Developer - Open Source Group Samsung Research America(Silicon Valley) shuah...@samsung.com | (970) 672-0658 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 1/1] x86/iommu: correct ICS register offset
On Tue, Sep 17, 2013 at 04:38:29PM +0800, ZhenHua wrote: > Hi Guys, > Though DMAR_ICS_REG is not used yet, I think this patch is > necessary. So please take a look at it. You are right, my Spec says the same. It doesn't matter much since the register seems to be unused in the VT-d driver. I applied the patch to iommu/fixes anyway. Joerg ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 1/2] iommu: Add iommu_fault class event to iommu trace
On Fri, Aug 16, 2013 at 11:20:16AM -0600, Shuah Khan wrote: > +DEFINE_EVENT(iommu_fault, report_fault, > + > + TP_PROTO(struct device *dev, unsigned long iova, int flags), > + > + TP_ARGS(dev, iova, flags) > +); I am not entirely happy with the naming. It is better to name the class iommu_error and the page-fault event io_page_fault. This makes it more clear what kind of fault it is. Joerg ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 0/7] iommu: Add event tracing feature to iommu
On Thu, Aug 15, 2013 at 11:59:22AM -0600, Shuah Khan wrote: > Shuah Khan (7): > iommu: Add event tracing feature to iommu > iommu: Change iommu driver to call add_device_to_group trace event > iommu: Change iommu driver to call remove_device_to_group trace event > iommu: Change iommu driver to call attach_device_to_domain trace > event > iommu: Change iommu driver to call detach_device_to_domain trace > event > iommu: Change iommu driver to call map trace event > iommu: Change iommu driver to call unmap trace event Applied to tracing branch, thanks Shuah. ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH] MAINTAINERS: add overall IOMMU section
On Fri, Sep 13, 2013 at 01:10:27PM -0600, Stephen Warren wrote: > I believe that Joerg Roedel is at least the path through which > drivers/iommu changes should be merged. Add a MAINTAINERS entry to > make this clear, so that he's Cd'd on all relevant patches. This is > relevant for non-AMD/Intel IOMMUs, where get_maintainers.pl doesn't > currently remind anyone to Cc Joerg on patches. Applied to iommu/fixes, thanks Stephen. I always hesitated a bit to do that, but if it makes me Cc'ed on all iommu patches from now on it is probably ok ;) Joerg ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [GIT PULL] iommu/arm-smmu: fixes for 3.12
On Tue, Sep 17, 2013 at 02:19:49PM +0100, Will Deacon wrote: > The following changes since commit 272b98c6455f00884f0350f775c5342358ebb73f: > > Linux 3.12-rc1 (2013-09-16 16:17:51 -0400) > > are available in the git repository at: > > git://git.kernel.org/pub/scm/linux/kernel/git/will/linux.git > for-joerg/arm-smmu/fixes Pulled, thanks Will. ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu