Re: [PATCH 1/7] iommu/arm-smmu: Introduce driver option handling

2013-10-10 Thread Will Deacon
On Wed, Oct 09, 2013 at 11:38:00PM +0100, Andreas Herrmann wrote:
 Introduce handling of driver options. Options are set based on DT
 information when probing an SMMU device. The first option introduced
 is arm,smmu-isolate-devices. (It will be used in the bus notifier
 block.)
 
 Signed-off-by: Andreas Herrmann andreas.herrm...@calxeda.com
 ---

Looks good to me, thanks Andreas!

Will
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 4/7] iommu/arm-smmu: Support buggy implementations where all config accesses are secure

2013-10-10 Thread Will Deacon
On Wed, Oct 09, 2013 at 11:38:03PM +0100, Andreas Herrmann wrote:
 In such a case we have to use secure aliases of some non-secure
 registers.
 
 This handling is switched on by DT property
 arm,smmu-secure-config-access for an SMMU node.
 
 Signed-off-by: Andreas Herrmann andreas.herrm...@calxeda.com
 ---
  drivers/iommu/arm-smmu.c |   30 +-
  1 file changed, 21 insertions(+), 9 deletions(-)
 
 diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
 index f877d02..91316a8 100644
 --- a/drivers/iommu/arm-smmu.c
 +++ b/drivers/iommu/arm-smmu.c
 @@ -51,6 +51,7 @@
  /* Driver options */
  #define ARM_SMMU_OPT_ISOLATE_DEVICES (1  0)
  #define ARM_SMMU_OPT_MASK_STREAM_IDS (1  1)
 +#define ARM_SMMU_OPT_SECURE_CONFIG_ACCESS(1  2)
  
  /* Maximum number of stream IDs assigned to a single device */
  #define MAX_MASTER_STREAMIDS 8
 @@ -65,6 +66,15 @@
  #define ARM_SMMU_GR0(smmu)   ((smmu)-base)
  #define ARM_SMMU_GR1(smmu)   ((smmu)-base + (smmu)-pagesize)
  
 +/*
 + * SMMU global address space with conditional offset to access secure 
 aliases of
 + * non-secure registers (e.g. nsCR0: 0x400, nsGFSR: 0x448, nsGFSYNR0: 0x450)
 + */
 +#define ARM_SMMU_GR0_NS(smmu)
 \
 + ((smmu)-base + \
 + ((smmu-options  ARM_SMMU_OPT_SECURE_CONFIG_ACCESS)\
 + ? 0x400 : 0))

You have a slight issue with the ordering of your patches, as this macro is
used by the stream masking patch, but this patch is based on top of the
latter.

Can you introduce this patch first please? I think it's ok for merging, but
I still have reservations with the other one.

Will
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 4/7] iommu/arm-smmu: Support buggy implementations where all config accesses are secure

2013-10-10 Thread Andreas Herrmann
On Thu, Oct 10, 2013 at 11:47:27AM -0400, Will Deacon wrote:
 On Wed, Oct 09, 2013 at 11:38:03PM +0100, Andreas Herrmann wrote:
  In such a case we have to use secure aliases of some non-secure
  registers.
  
  This handling is switched on by DT property
  arm,smmu-secure-config-access for an SMMU node.
  
  Signed-off-by: Andreas Herrmann andreas.herrm...@calxeda.com
  ---
   drivers/iommu/arm-smmu.c |   30 +-
   1 file changed, 21 insertions(+), 9 deletions(-)
  
  diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
  index f877d02..91316a8 100644
  --- a/drivers/iommu/arm-smmu.c
  +++ b/drivers/iommu/arm-smmu.c
  @@ -51,6 +51,7 @@
   /* Driver options */
   #define ARM_SMMU_OPT_ISOLATE_DEVICES   (1  0)
   #define ARM_SMMU_OPT_MASK_STREAM_IDS   (1  1)
  +#define ARM_SMMU_OPT_SECURE_CONFIG_ACCESS  (1  2)
   
   /* Maximum number of stream IDs assigned to a single device */
   #define MAX_MASTER_STREAMIDS   8
  @@ -65,6 +66,15 @@
   #define ARM_SMMU_GR0(smmu) ((smmu)-base)
   #define ARM_SMMU_GR1(smmu) ((smmu)-base + (smmu)-pagesize)
   
  +/*
  + * SMMU global address space with conditional offset to access secure 
  aliases of
  + * non-secure registers (e.g. nsCR0: 0x400, nsGFSR: 0x448, nsGFSYNR0: 
  0x450)
  + */
  +#define ARM_SMMU_GR0_NS(smmu)  
  \
  +   ((smmu)-base + \
  +   ((smmu-options  ARM_SMMU_OPT_SECURE_CONFIG_ACCESS)\
  +   ? 0x400 : 0))
 
 You have a slight issue with the ordering of your patches, as this macro is
 used by the stream masking patch, but this patch is based on top of the
 latter.
 
 Can you introduce this patch first please? I think it's ok for merging, but
 I still have reservations with the other one.

Oops, I've done some shuffling to update the first patch in the
series. Obviously I mixed something up during this.

I'll fix this asap.


Andreas
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 2/7] iommu/arm-smmu: Introduce bus notifier block

2013-10-10 Thread Will Deacon
On Wed, Oct 09, 2013 at 11:38:01PM +0100, Andreas Herrmann wrote:
  drivers/iommu/arm-smmu.c |   53 
 ++
  1 file changed, 53 insertions(+)
 
 diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
 index 478c8ad..87239e8 100644
 --- a/drivers/iommu/arm-smmu.c
 +++ b/drivers/iommu/arm-smmu.c
 @@ -46,6 +46,7 @@
  #include linux/amba/bus.h
  
  #include asm/pgalloc.h
 +#include asm/dma-iommu.h
  
  /* Driver options */
  #define ARM_SMMU_OPT_ISOLATE_DEVICES (1  0)
 @@ -1983,6 +1984,56 @@ static int arm_smmu_device_remove(struct 
 platform_device *pdev)
   return 0;
  }
  
 +static int arm_smmu_device_notifier(struct notifier_block *nb,
 + unsigned long action, void *data)
 +{
 + struct device *dev = data;
 + struct dma_iommu_mapping *mapping;
 + struct arm_smmu_device *smmu;
 + void __iomem *gr0_base;
 + u32 cr0;
 + int ret;
 +
 + switch (action) {
 + case BUS_NOTIFY_BIND_DRIVER:
 +
 + arm_smmu_add_device(dev);
 + smmu = dev-archdata.iommu;
 + if (!smmu || !(smmu-options  ARM_SMMU_OPT_ISOLATE_DEVICES))
 + break;
 +
 + mapping = arm_iommu_create_mapping(platform_bus_type,
 + 0, SZ_128M, 0);

We need to find a better way of doing this; I'm really not happy hardcoding
that size limit and hoping for the best.

 + if (IS_ERR(mapping)) {
 + ret = PTR_ERR(mapping);
 + dev_info(dev, arm_iommu_create_mapping failed\n);
 + break;
 + }
 +
 + ret = arm_iommu_attach_device(dev, mapping);
 + if (ret  0) {
 + dev_info(dev, arm_iommu_attach_device failed\n);
 + arm_iommu_release_mapping(mapping);
 + }
 +
 + gr0_base = ARM_SMMU_GR0_NS(smmu);
 + cr0 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sCR0);
 + cr0 |= sCR0_USFCFG;
 + writel(cr0, gr0_base + ARM_SMMU_GR0_sCR0);

Why do you need to enable this flag? If no mapping is found, that means *we*
screwed something up, so we should report that and not rely on the hardware
potentially raising a fault. I also prefer to allow passthrough for devices
that don't hit in the stream table, because it allows people to ignore the SMMU
in their DT if they want to.

Will
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 2/7] iommu/arm-smmu: Introduce bus notifier block

2013-10-10 Thread Andreas Herrmann
On Thu, Oct 10, 2013 at 12:12:17PM -0400, Will Deacon wrote:
 On Wed, Oct 09, 2013 at 11:38:01PM +0100, Andreas Herrmann wrote:
   drivers/iommu/arm-smmu.c |   53 
  ++
   1 file changed, 53 insertions(+)
  
  diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
  index 478c8ad..87239e8 100644
  --- a/drivers/iommu/arm-smmu.c
  +++ b/drivers/iommu/arm-smmu.c
  @@ -46,6 +46,7 @@
   #include linux/amba/bus.h
   
   #include asm/pgalloc.h
  +#include asm/dma-iommu.h
   
   /* Driver options */
   #define ARM_SMMU_OPT_ISOLATE_DEVICES   (1  0)
  @@ -1983,6 +1984,56 @@ static int arm_smmu_device_remove(struct 
  platform_device *pdev)
  return 0;
   }
   
  +static int arm_smmu_device_notifier(struct notifier_block *nb,
  +   unsigned long action, void *data)
  +{
  +   struct device *dev = data;
  +   struct dma_iommu_mapping *mapping;
  +   struct arm_smmu_device *smmu;
  +   void __iomem *gr0_base;
  +   u32 cr0;
  +   int ret;
  +
  +   switch (action) {
  +   case BUS_NOTIFY_BIND_DRIVER:
  +
  +   arm_smmu_add_device(dev);
  +   smmu = dev-archdata.iommu;
  +   if (!smmu || !(smmu-options  ARM_SMMU_OPT_ISOLATE_DEVICES))
  +   break;
  +
  +   mapping = arm_iommu_create_mapping(platform_bus_type,
  +   0, SZ_128M, 0);
 
 We need to find a better way of doing this; I'm really not happy hardcoding
 that size limit and hoping for the best.

Hmm, seems that mid-term we should try to enlarge this area by another
128M if a mapping fails due to this limit. I think Joerg's amd_iommu
driver does this.

(But at the same time I'd prefer to start with even a hardcoded value,
or to simply introduce some option to set this fixed limit per master
or per smmu.)

  +   if (IS_ERR(mapping)) {
  +   ret = PTR_ERR(mapping);
  +   dev_info(dev, arm_iommu_create_mapping failed\n);
  +   break;
  +   }
  +
  +   ret = arm_iommu_attach_device(dev, mapping);
  +   if (ret  0) {
  +   dev_info(dev, arm_iommu_attach_device failed\n);
  +   arm_iommu_release_mapping(mapping);
  +   }
  +
  +   gr0_base = ARM_SMMU_GR0_NS(smmu);
  +   cr0 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sCR0);
  +   cr0 |= sCR0_USFCFG;
  +   writel(cr0, gr0_base + ARM_SMMU_GR0_sCR0);
 
 Why do you need to enable this flag? If no mapping is found, that means *we*
 screwed something up, so we should report that and not rely on the hardware
 potentially raising a fault. I also prefer to allow passthrough for devices
 that don't hit in the stream table, because it allows people to ignore the 
 SMMU
 in their DT if they want to.

You are right that's not strictly required for device isolation.

(but it helped to learn about relevant stream-ids that were not
covered by by my DTS ;-)


Andreas
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 7/7] iommu/arm-smmu: Introduce automatic stream-id-masking

2013-10-10 Thread Andreas Herrmann
On Thu, Oct 10, 2013 at 12:05:39PM -0400, Will Deacon wrote:
 On Wed, Oct 09, 2013 at 11:38:06PM +0100, Andreas Herrmann wrote:
  Try to determine a mask that can be used for all StreamIDs of a master
  device. This allows to use just one SMR group instead of
  number-of-streamids SMR groups for a master device.
  
  Signed-off-by: Andreas Herrmann andreas.herrm...@calxeda.com
  ---
   drivers/iommu/arm-smmu.c |   79 
  --
   1 file changed, 63 insertions(+), 16 deletions(-)
  
  diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
  index 91316a8..4e8ceab 100644
  --- a/drivers/iommu/arm-smmu.c
  +++ b/drivers/iommu/arm-smmu.c
  @@ -28,6 +28,7 @@
* - Context fault reporting
*/
   
  +#define DEBUG
   #define pr_fmt(fmt) arm-smmu:  fmt
   
   #include linux/delay.h
  @@ -341,6 +342,9 @@ struct arm_smmu_master {
  struct rb_node  node;
  int num_streamids;
  u16 streamids[MAX_MASTER_STREAMIDS];
  +   int num_smrs;
 
 This is easy to confuse with smmu-num_mapping_groups, but is actually the
 number of SMRs in use by this master, right? Maybe tweaking the name
 (num_used_smrs?) would make this clearer.
 
  +   u16 smr_mask;
  +   u16 smr_id;
   
  /*
   * We only need to allocate these on the root SMMU, as we
  @@ -530,14 +534,11 @@ static int register_smmu_master(struct 
  arm_smmu_device *smmu,
  ARM_SMMU_OPT_MASK_STREAM_IDS));
  return -EINVAL;
  }
  -   /* set fixed streamid (0) that will be used for masking */
  -   master-num_streamids = 1;
  -   master-streamids[0] = 0;
  -   } else {
  -   for (i = 0; i  master-num_streamids; ++i)
  -   master-streamids[i] = masterspec-args[i];
  }
   
  +   for (i = 0; i  master-num_streamids; ++i)
  +   master-streamids[i] = masterspec-args[i];
  +
  return insert_smmu_master(smmu, master);
   }
   
  @@ -1049,6 +1050,41 @@ static void arm_smmu_domain_destroy(struct 
  iommu_domain *domain)
  kfree(smmu_domain);
   }
   
  +/*
  + * no duplicates streamids please
  + */
 
 We could probably check for that actually in register_smmu_master.
 
  +static void determine_smr_mapping(struct arm_smmu_device *smmu,
  +   struct arm_smmu_master *master)
  +{
  +   int nr_sid;
  +   u16 i, v1, v2, const_mask;
 
 The bitwise stuff later on could use some more meaningful identifiers
 (although the comments do help).
 
  +
  +   if (smmu-options  ARM_SMMU_OPT_MASK_STREAM_IDS) {
  +   master-smr_mask = smmu-smr_mask_bits;
  +   master-smr_id = 0;
  +   return;
  +   }
  +
  +   nr_sid = master-num_streamids;
  +   if (!is_power_of_2(nr_sid))
  +   return;
 
 As I mentioned before, we could do better than this if we forced the DT to
 contain complete topological information. Then we could round up to the next
 power of two and check that we didn't accidentally include another device.
 What is your opinion on this?
 
  +   v1 = 0;
  +   v2 = -1;
 
 I'd rather this was written as 0x;
 
  +   for (i = 0; i  nr_sid; i++) {
  +   v1 |= master-streamids[i]; /* for const 0 bits */
  +   v2 = ~(master-streamids[i]);  /* const 1 bits */
  +   }
  +   const_mask = (~v1) | v2;/* const bits (either 0 or 1) */
  +
  +   v1 = hweight16(~const_mask);
  +   if ((1  v1) == nr_sid) {
  +   /* if smr_mask is set, only 1 SMR group is used smr[0] = 0 */
  +   master-smr_mask = ~const_mask;
  +   master-smr_id = v1  const_mask;
  +   }
 
 Hehe, this is cool, nice one! I originally thought you could just xor stuff,
 but that ends up being slightly nasty because it all has to be done pairwise.
 
  +}
  +
   static int arm_smmu_master_configure_smrs(struct arm_smmu_device *smmu,
struct arm_smmu_master *master)
   {
  @@ -1062,15 +1098,22 @@ static int arm_smmu_master_configure_smrs(struct 
  arm_smmu_device *smmu,
  if (master-smrs)
  return -EEXIST;
   
  -   smrs = kmalloc(sizeof(*smrs) * master-num_streamids, GFP_KERNEL);
  +   determine_smr_mapping(smmu, master);
  +
  +   if (master-smr_mask)
  +   master-num_smrs = 1;
 
 So the next challenge would be to allocate one SMR using your power-of-2
 trick, then mop up what's left with individual SMR entries.

BTW, the coding style of this patch might be nasty. I had cut it out
of some later version of my prototype driver and adapted it to your
driver.

So you don't generally object and it seems you'd accept this patch (if
minor things fixed) and I should scrub the other mask-stream-id patch.

Sigh ... so I need to figure out how to do the mop-up.


Andreas

PS: Even w/o the mop-up I could get my sata-smmu 

RE: [PATCH 2/7] iommu: add api to get iommu_domain of a device

2013-10-10 Thread Sethi Varun-B16395


 -Original Message-
 From: iommu-boun...@lists.linux-foundation.org [mailto:iommu-
 boun...@lists.linux-foundation.org] On Behalf Of Alex Williamson
 Sent: Tuesday, October 08, 2013 8:43 AM
 To: Bhushan Bharat-R65777
 Cc: ag...@suse.de; Wood Scott-B07421; linux-...@vger.kernel.org;
 ga...@kernel.crashing.org; linux-ker...@vger.kernel.org;
 iommu@lists.linux-foundation.org; b...@kernel.crashing.org; linuxppc-
 d...@lists.ozlabs.org
 Subject: Re: [PATCH 2/7] iommu: add api to get iommu_domain of a device
 
 On Mon, 2013-10-07 at 05:46 +, Bhushan Bharat-R65777 wrote:
 
   -Original Message-
   From: Alex Williamson [mailto:alex.william...@redhat.com]
   Sent: Friday, October 04, 2013 11:42 PM
   To: Bhushan Bharat-R65777
   Cc: j...@8bytes.org; b...@kernel.crashing.org;
   ga...@kernel.crashing.org; linux- ker...@vger.kernel.org;
   linuxppc-...@lists.ozlabs.org; linux- p...@vger.kernel.org;
   ag...@suse.de; Wood Scott-B07421; iommu@lists.linux- foundation.org
   Subject: Re: [PATCH 2/7] iommu: add api to get iommu_domain of a
   device
  
   On Fri, 2013-10-04 at 17:23 +, Bhushan Bharat-R65777 wrote:
   
 -Original Message-
 From: Alex Williamson [mailto:alex.william...@redhat.com]
 Sent: Friday, October 04, 2013 10:43 PM
 To: Bhushan Bharat-R65777
 Cc: j...@8bytes.org; b...@kernel.crashing.org;
 ga...@kernel.crashing.org; linux- ker...@vger.kernel.org;
 linuxppc-...@lists.ozlabs.org; linux- p...@vger.kernel.org;
 ag...@suse.de; Wood Scott-B07421; iommu@lists.linux-
 foundation.org
 Subject: Re: [PATCH 2/7] iommu: add api to get iommu_domain of a
 device

 On Fri, 2013-10-04 at 16:47 +, Bhushan Bharat-R65777 wrote:
 
   -Original Message-
   From: Alex Williamson [mailto:alex.william...@redhat.com]
   Sent: Friday, October 04, 2013 9:15 PM
   To: Bhushan Bharat-R65777
   Cc: j...@8bytes.org; b...@kernel.crashing.org;
   ga...@kernel.crashing.org; linux- ker...@vger.kernel.org;
   linuxppc-...@lists.ozlabs.org; linux- p...@vger.kernel.org;
   ag...@suse.de; Wood Scott-B07421; iommu@lists.linux-
   foundation.org
   Subject: Re: [PATCH 2/7] iommu: add api to get iommu_domain
   of a device
  
   On Fri, 2013-10-04 at 09:54 +, Bhushan Bharat-R65777
 wrote:
   
 -Original Message-
 From: linux-pci-ow...@vger.kernel.org
 [mailto:linux-pci-ow...@vger.kernel.org]
 On Behalf Of Alex Williamson
 Sent: Wednesday, September 25, 2013 10:16 PM
 To: Bhushan Bharat-R65777
 Cc: j...@8bytes.org; b...@kernel.crashing.org;
 ga...@kernel.crashing.org; linux-
 ker...@vger.kernel.org; linuxppc-...@lists.ozlabs.org;
 linux- p...@vger.kernel.org; ag...@suse.de; Wood
 Scott-B07421; iommu@lists.linux- foundation.org; Bhushan
 Bharat-R65777
 Subject: Re: [PATCH 2/7] iommu: add api to get
 iommu_domain of a device

 On Thu, 2013-09-19 at 12:59 +0530, Bharat Bhushan wrote:
  This api return the iommu domain to which the device is
 attached.
  The iommu_domain is required for making API calls
  related to
   iommu.
  Follow up patches which use this API to know iommu
 maping.
 
  Signed-off-by: Bharat Bhushan
  bharat.bhus...@freescale.com
  ---
   drivers/iommu/iommu.c |   10 ++
   include/linux/iommu.h |7 +++
   2 files changed, 17 insertions(+), 0 deletions(-)
 
  diff --git a/drivers/iommu/iommu.c
  b/drivers/iommu/iommu.c index
  fbe9ca7..6ac5f50 100644
  --- a/drivers/iommu/iommu.c
  +++ b/drivers/iommu/iommu.c
  @@ -696,6 +696,16 @@ void iommu_detach_device(struct
  iommu_domain *domain, struct device *dev)  }
  EXPORT_SYMBOL_GPL(iommu_detach_device);
 
  +struct iommu_domain *iommu_get_dev_domain(struct
 device *dev) {
  +   struct iommu_ops *ops = dev-bus-iommu_ops;
  +
  +   if (unlikely(ops == NULL ||
  +ops-get_dev_iommu_domain ==
   NULL))
  +   return NULL;
  +
  +   return ops-get_dev_iommu_domain(dev); }
  +EXPORT_SYMBOL_GPL(iommu_get_dev_domain);

 What prevents this from racing iommu_domain_free()?
 There's no references acquired, so there's no reason for
 the caller to assume the
   pointer is valid.
   
Sorry for late query, somehow this email went into a
folder and escaped;
   
Just to be sure, there is not lock at generic struct
iommu_domain, but IP
   specific structure (link FSL domain) linked in
   iommu_domain-priv have a lock, so we need to ensure this
   race in FSL iommu code (say drivers/iommu/fsl_pamu_domain.c),
 right?
  
   No, it's not sufficient to make