Re: [Intel-gfx] [PATCH v3 0/6] Convert the intel iommu driver to the dma-iommu api

2020-09-18 Thread Logan Gunthorpe
Hi Lu,

On 2020-09-11 9:21 p.m., Lu Baolu wrote:
> Tom Murphy has almost done all the work. His latest patch series was
> posted here.
>
> https://lore.kernel.org/linux-iommu/20200903201839.7327-1-murph...@tcd.ie/
>
> Thanks a lot!
>
> This series is a follow-up with below changes:
>
> 1. Add a quirk for the i915 driver issue described in Tom's cover
> letter.
> 2. Fix several bugs in patch "iommu: Allow the dma-iommu api to use
> bounce buffers" to make the bounce buffer work for untrusted devices.
> 3. Several cleanups in iommu/vt-d driver after the conversion.
>

I'm trying to test this on an old Sandy Bridge, but found that I get
spammed with warnings on boot. I've put a sample of a few of them below.
They all seem to be related to ioat.

I had the same issue with Tom's v2 but never saw this on his v1.

Thanks,

Logan


[   44.057877] [ cut here ]
[   44.063167] WARNING: CPU: 4 PID: 84 at drivers/iommu/dma-iommu.c:496 
__iommu_dma_unmap+0x115/0x130
[   44.073351] Modules linked in:
[   44.076882] CPU: 4 PID: 84 Comm: kworker/4:1 Tainted: GW 
5.9.0-rc4-6-g110da1e703a2 #216
[   44.087935] Hardware name: Supermicro SYS-7047GR-TRF/X9DRG-QF, BIOS 3.0a 
12/05/2013
[   44.096650] Workqueue: events work_for_cpu_fn
[   44.101644] RIP: 0010:__iommu_dma_unmap+0x115/0x130
[   44.107225] Code: 48 8b 0c 24 48 c7 44 24 10 00 00 00 00 48 c7 44 24 18 00 
00 00 00 48 c7 44 24 20 00 00 00 00 48 c7 44 24 08 ff ff ff ff eb 8d <0f> 0b e9 
74 ff ff ff e8 1f 36 66 00 66 66 2e 0f 1f 84 00 00 00 00
[   44.128443] RSP: :c90002397c38 EFLAGS: 00010206
[   44.134413] RAX: 0020 RBX: 0008 RCX: 
[   44.144487] RDX: 0403 RSI: 82a7fb20 RDI: 888477804f30
[   44.152613] RBP: fec0 R08: 000fec00 R09: 000fedff
[   44.160733] R10: 0002 R11: 0004 R12: 888270c39000
[   44.168861] R13: 888472d85ee8 R14: 0008 R15: 
[   44.176980] FS:  () GS:88847980() 
knlGS:
[   44.186198] CS:  0010 DS:  ES:  CR0: 80050033
[   44.192761] CR2:  CR3: 02a20001 CR4: 000606e0
[   44.200871] Call Trace:
[   44.203716]  ? lockdep_hardirqs_on_prepare+0xad/0x180
[   44.209509]  iommu_dma_free+0x18/0x30
[   44.213734]  ioat_free_chan_resources+0x19e/0x300
[   44.219133]  ioat_dma_self_test+0x2a0/0x3d0
[   44.223964]  ioat_pci_probe+0x60e/0x903
[   44.228387]  local_pci_probe+0x42/0x80
[   44.232721]  work_for_cpu_fn+0x16/0x20
[   44.237037]  process_one_work+0x292/0x630
[   44.241644]  ? __schedule+0x344/0x970
[   44.245868]  worker_thread+0x227/0x3e0
[   44.250185]  ? process_one_work+0x630/0x630
[   44.254989]  kthread+0x136/0x150
[   44.258718]  ? kthread_use_mm+0x100/0x100
[   44.263334]  ret_from_fork+0x22/0x30
[   44.267474] irq event stamp: 1881262
[   44.271602] hardirqs last  enabled at (1881272): [] 
console_unlock+0x435/0x570
[   44.281593] hardirqs last disabled at (1881281): [] 
console_unlock+0x42b/0x570
[   44.291588] softirqs last  enabled at (1747140): [] 
ioat_cleanup+0x65/0x470
[   44.301285] softirqs last disabled at (1747144): [] 
ioat_free_chan_resources+0x6a/0x300
[   44.312153] ---[ end trace ed0f88fd959a5a39 ]---
[   44.353963] [ cut here ]
[   44.359291] WARNING: CPU: 4 PID: 84 at drivers/iommu/dma-iommu.c:496 
__iommu_dma_unmap+0x115/0x130
[   44.369482] Modules linked in:
[   44.373030] CPU: 4 PID: 84 Comm: kworker/4:1 Tainted: GW 
5.9.0-rc4-6-g110da1e703a2 #216
[   44.384097] Hardware name: Supermicro SYS-7047GR-TRF/X9DRG-QF, BIOS 3.0a 
12/05/2013
[   44.392825] Workqueue: events work_for_cpu_fn
[   44.397831] RIP: 0010:__iommu_dma_unmap+0x115/0x130
[   44.403421] Code: 48 8b 0c 24 48 c7 44 24 10 00 00 00 00 48 c7 44 24 18 00 
00 00 00 48 c7 44 24 20 00 00 00 00 48 c7 44 24 08 ff ff ff ff eb 8d <0f> 0b e9 
74 ff ff ff e8 1f 36 66 00 66 66 2e 0f 1f 84 00 00 00 00
[   44.424644] RSP: :c90002397c38 EFLAGS: 00010206
[   44.430627] RAX: 0020 RBX: 0008 RCX: 
[   44.438770] RDX: 0403 RSI: 82a7fb20 RDI: 888477804f30
[   44.446885] RBP: ffc0 R08: 000ffc00 R09: 000ffdff
[   44.455000] R10: 0002 R11: 0004 R12: 888270c55000
[   44.463119] R13: 888472dc7268 R14: 0008 R15: 
[   44.471235] FS:  () GS:88847980() 
knlGS:
[   44.480440] CS:  0010 DS:  ES:  CR0: 80050033
[   44.487004] CR2:  CR3: 02a20001 CR4: 000606e0
[   44.495128] Call Trace:
[   44.498008]  iommu_dma_free+0x18/0x30
[   44.502230]  ioat_free_chan_resources+0x19e/0x300
[   44.507631]  ioat_dma_self_test+0x2a0/0x3d0
[   44.512466]  ioat_pci_probe+0x60e/0x903
[   44.516889]  local_pci_probe+0x42/0x80
[   

Re: [PATCH v9 1/7] docs: IOMMU user API

2020-09-18 Thread Jacob Pan
Hi Randy,

Thanks for the review.

On Wed, 16 Sep 2020 11:26:00 -0700, Randy Dunlap 
wrote:

> On 9/11/20 2:57 PM, Jacob Pan wrote:
> > IOMMU UAPI is newly introduced to support communications between guest
> > virtual IOMMU and host IOMMU. There has been lots of discussions on how
> > it should work with VFIO UAPI and userspace in general.
> > 
> > This document is intended to clarify the UAPI design and usage. The
> > mechanics of how future extensions should be achieved are also covered
> > in this documentation.
> > 
> > Reviewed-by: Eric Auger 
> > Signed-off-by: Liu Yi L 
> > Signed-off-by: Jacob Pan 
> > ---
> >  Documentation/userspace-api/iommu.rst | 211
> > ++
> > MAINTAINERS   |   1 + 2 files changed, 212
> > insertions(+) create mode 100644 Documentation/userspace-api/iommu.rst  
> 
> Hi,
> I have a few edit changes for you below:
> 
> 
> > diff --git a/Documentation/userspace-api/iommu.rst
> > b/Documentation/userspace-api/iommu.rst new file mode 100644
> > index ..1e68e8f05bb3
> > --- /dev/null
> > +++ b/Documentation/userspace-api/iommu.rst
> > @@ -0,0 +1,211 @@
> > +.. SPDX-License-Identifier: GPL-2.0
> > +.. iommu:
> > +
> > +=
> > +IOMMU Userspace API
> > +=
> > +
> > +IOMMU UAPI is used for virtualization cases where communications are
> > +needed between physical and virtual IOMMU drivers. For baremetal
> > +usage, the IOMMU is a system device which does not need to communicate
> > +with user space directly.  
> 
> userspace
> 
> for consistency
> 
got it

> > +
> > +The primary use cases are guest Shared Virtual Address (SVA) and
> > +guest IO virtual address (IOVA), wherin the vIOMMU implementation  
> 
> wherein
> 
right

> > +relies on the physical IOMMU and for this reason requires interactions
> > +with the host driver.
> > +
> > +.. contents:: :local:
> > +
> > +Functionalities
> > +===
> > +Communications of user and kernel involve both directions. The
> > +supported user-kernel APIs are as follows:
> > +
> > +1. Alloc/Free PASID
> > +2. Bind/Unbind guest PASID (e.g. Intel VT-d)
> > +3. Bind/Unbind guest PASID table (e.g. ARM SMMU)
> > +4. Invalidate IOMMU caches upon guest requests
> > +5. Report errors to the guest and serve page requests
> > +
> > +Requirements
> > +
> > +The IOMMU UAPIs are generic and extensible to meet the following
> > +requirements:
> > +
> > +1. Emulated and para-virtualised vIOMMUs
> > +2. Multiple vendors (Intel VT-d, ARM SMMU, etc.)
> > +3. Extensions to the UAPI shall not break existing user space  
> 
>   userspace
> 
ditto

> > +
> > +Interfaces
> > +==
> > +Although the data structures defined in IOMMU UAPI are self-contained,
> > +there is no user API functions introduced. Instead, IOMMU UAPI is  
> 
>there are no
> 
right

> > +designed to work with existing user driver frameworks such as VFIO.
> > +
> > +Extension Rules & Precautions
> > +-
> > +When IOMMU UAPI gets extended, the data structures can *only* be
> > +modified in two ways:
> > +
> > +1. Adding new fields by re-purposing the padding[] field. No size
> > change. +2. Adding new union members at the end. May increase the
> > structure sizes. +
> > +No new fields can be added *after* the variable sized union in that it
> > +will break backward compatibility when offset moves. A new flag must
> > +be introduced whenever a change affects the structure using either
> > +method. The IOMMU driver processes the data based on flags which
> > +ensures backward compatibility.
> > +
> > +Version field is only reserved for the unlikely event of UAPI upgrade
> > +at its entirety.
> > +
> > +It's *always* the caller's responsibility to indicate the size of the
> > +structure passed by setting argsz appropriately.
> > +Though at the same time, argsz is user provided data which is not
> > +trusted. The argsz field allows the user app to indicate how much data
> > +it is providing, it's still the kernel's responsibility to validate  
> 
>  providing;
> 
yes. good separation.

> > +whether it's correct and sufficient for the requested operation.
> > +
> > +Compatibility Checking
> > +--
> > +When IOMMU UAPI extension results in some structure size increase,
> > +IOMMU UAPI code shall handle the following cases:
> > +
> > +1. User and kernel has exact size match
> > +2. An older user with older kernel header (smaller UAPI size) running
> > on a
> > +   newer kernel (larger UAPI size)
> > +3. A newer user with newer kernel header (larger UAPI size) running
> > +   on an older kernel.
> > +4. A malicious/misbehaving user pass illegal/invalid size but within  
> 
>passing
> 
got it

> > +   range. The data may contain garbage.
> > +
> > +Feature 

Re: [git pull] IOMMU Fixes for Linux v5.9-rc5

2020-09-18 Thread pr-tracker-bot
The pull request you sent on Fri, 18 Sep 2020 17:10:56 +0200:

> git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git 
> tags/iommu-fixes-v5.9-rc5

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/1fd79656f7d59b2ccfc8d7ec8136db60d21f1e0a

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v9 0/7] IOMMU user API enhancement

2020-09-18 Thread Jacob Pan
Hi Joerg,

On Fri, 18 Sep 2020 12:02:36 +0200, Joerg Roedel  wrote:

> Hi Jacob,
> 
> On Fri, Sep 11, 2020 at 02:57:49PM -0700, Jacob Pan wrote:
> > IOMMU user API header was introduced to support nested DMA translation
> > and related fault handling. The current UAPI data structures consist of
> > three areas that cover the interactions between host kernel and guest:
> >  - fault handling
> >  - cache invalidation
> >  - bind guest page tables, i.e. guest PASID
> > 
> > Future extensions are likely to support more architectures and vIOMMU
> > features.
> > 
> > In the previous discussion, using user-filled data size and feature
> > flags is made a preferred approach over a unified version number.
> > https://lkml.org/lkml/2020/1/29/45
> > 
> > In addition to introduce argsz field to data structures, this patchset
> > is also trying to document the UAPI design, usage, and extension rules.
> > VT-d driver changes to utilize the new argsz field is included, VFIO
> > usage is to follow.
> > 
> > This set is available at:
> > https://github.com/jacobpan/linux.git vsva_v5.9_uapi_v9  
> 
> This changes user visible structs in incompatible ways, are you sure
> those are not used yet anywhere?
> 
These structs are not used yet in that IOMMU UAPI does not provide
direct user IOCTLs. For guest SVA of assigned devices, VFIO is used. Yi's
companion patches are here.
https://lore.kernel.org/linux-iommu/5dd95fbf-054c-3bbc-e76b-2d5636214...@redhat.com/T/#t

These user structs can also be used by other framework in the future, such
as vDPA.

> Please address Randy's comments on patch 1 and my comment about the
> build-time checking and repost with linux-...@vger.kernel.org on Cc.
> 
Will do.

> Regards,
> 
>   Joerg


Thanks,

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


Re: [PATCH v9 3/7] iommu/uapi: Introduce enum type for PASID data format

2020-09-18 Thread Jacob Pan
Hi Joerg,

On Fri, 18 Sep 2020 11:44:50 +0200, Joerg Roedel  wrote:

> On Fri, Sep 11, 2020 at 02:57:52PM -0700, Jacob Pan wrote:
> > There can be multiple vendor-specific PASID data formats used in UAPI
> > structures. This patch adds enum type with a last entry which makes
> > range checking much easier.  
> 
> But it also makes it much easier to screw up the numbers (which are ABI)
> by inserting a new value into the middle. I prefer defines here, or
> alternativly BUILD_BUG_ON() checks for the numbers.
> 
I am not following, the purpose of IOMMU_PASID_FORMAT_LAST *is* for
preparing the future insertion of new value into the middle.
The checking against IOMMU_PASID_FORMAT_LAST is to protect ABI
compatibility by making sure that out of range format are rejected in all
versions of the ABI.
For example, in v5.10, ABI has IOMMU_PASID_FORMAT_LAST = 2, then user data
with format = 2 will be rejected. So this user app will not work or
released.

Now say in v5.11, we add one more format in the middle and set
IOMMU_PASID_FORMAT_LAST = 3. Then user data with the new format = 2 can be 
supported.

Without the checking for IOMMU_PASID_FORMAT_LAST, at v5.10 time the user
binary may succeed and become legacy binary that we cannot break in v5.11.
This renders format = 2 unusable for v5.11.

I thought enum makes it less susceptible to programming errors than defines
by making sure the ascending order. I might have missed your point, could
you elaborate?

> Regards,
> 
>   Joerg
> 
> > 
> > Suggested-by: Alex Williamson 
> > Reviewed-by: Eric Auger 
> > Signed-off-by: Jacob Pan 
> > ---
> >  include/uapi/linux/iommu.h | 8 ++--
> >  1 file changed, 6 insertions(+), 2 deletions(-)
> > 
> > diff --git a/include/uapi/linux/iommu.h b/include/uapi/linux/iommu.h
> > index b42acc8fe007..7cc6ee6c41f7 100644
> > --- a/include/uapi/linux/iommu.h
> > +++ b/include/uapi/linux/iommu.h
> > @@ -298,11 +298,16 @@ struct iommu_gpasid_bind_data_vtd {
> >  IOMMU_SVA_VTD_GPASID_PCD |  \
> >  IOMMU_SVA_VTD_GPASID_PWT)
> >  
> > +enum iommu_pasid_data_format {
> > +   IOMMU_PASID_FORMAT_INTEL_VTD = 1,
> > +   IOMMU_PASID_FORMAT_LAST,
> > +};
> > +
> >  /**
> >   * struct iommu_gpasid_bind_data - Information about device and guest
> > PASID binding
> >   * @argsz: User filled size of this data
> >   * @version:   Version of this data structure
> > - * @format:PASID table entry format
> > + * @format:PASID table entry format of enum
> > iommu_pasid_data_format type
> >   * @flags: Additional information on guest bind request
> >   * @gpgd:  Guest page directory base of the guest mm to bind
> >   * @hpasid:Process address space ID used for the guest mm in
> > host IOMMU @@ -321,7 +326,6 @@ struct iommu_gpasid_bind_data {
> > __u32 argsz;
> >  #define IOMMU_GPASID_BIND_VERSION_11
> > __u32 version;
> > -#define IOMMU_PASID_FORMAT_INTEL_VTD   1
> > __u32 format;
> > __u32 addr_width;
> >  #define IOMMU_SVA_GPASID_VAL   (1 << 0) /* guest PASID valid */
> > -- 
> > 2.7.4  


Thanks,

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


Re: [PATCH v8 3/9] Documentation/x86: Add documentation for SVA (Shared Virtual Addressing)

2020-09-18 Thread Fenghua Yu
On Thu, Sep 17, 2020 at 07:30:41PM +0200, Borislav Petkov wrote:
> On Thu, Sep 17, 2020 at 10:22:39AM -0700, Raj, Ashok wrote:
> > s/translation again/translation
> 
> Ok, last one. Now stop looking at that text because you'll find more.
> 
> :-)))

Thank you very much for taking care of the series, Boris!

I tested the tip:x86/pasid branch and everything works fine by my tests.
I'll enable more tests for the branch.

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


Re: [PATCH v2 01/23] dt-bindings: iommu: mediatek: Convert IOMMU to DT schema

2020-09-18 Thread Rob Herring
On Mon, Sep 14, 2020 at 11:51 PM Yong Wu  wrote:
>
> On Mon, 2020-09-14 at 17:22 -0600, Rob Herring wrote:
> > On Sat, Sep 05, 2020 at 04:08:58PM +0800, Yong Wu wrote:
> > > Convert MediaTek IOMMU to DT schema.
> > >
> > > Signed-off-by: Yong Wu 
> > > ---
>
> [...]
>
> > > +properties:
> > > +  compatible:
> > > +enum:
> > > +  - mediatek,mt2701-m4u #mt2701 generation one HW
> > > +  - mediatek,mt2712-m4u #mt2712 generation two HW
> > > +  - mediatek,mt6779-m4u #mt6779 generation two HW
> > > +  - mediatek,mt7623-m4u, mediatek,mt2701-m4u #mt7623 generation one 
> > > HW
> >
> > This is not right.
> >
> > items:
> >   - const: mediatek,mt7623-m4u
> >   - const: mediatek,mt2701-m4u
> >
> > And that has to be under a 'oneOf' with the rest of this.
>
> Thanks for the review. Is this OK?
>
>   compatible:
> oneOf:
>   - const: mediatek,mt2701-m4u # mt2701 generation one HW
>   - const: mediatek,mt2712-m4u # mt2712 generation two HW
>   - const: mediatek,mt6779-m4u # mt6779 generation two HW
>   - const: mediatek,mt8173-m4u # mt8173 generation two HW
>   - const: mediatek,mt8183-m4u # mt8183 generation two HW
>   - const: mediatek,mt8192-m4u # mt8192 generation two HW

It is correct, but I prefer all these to be a single enum. So 'oneOf'
would have 2 entries.

>   - description: mt7623 generation one HW
> items:
>   - const: mediatek,mt7623-m4u
>   - const: mediatek,mt2701-m4u
>
> >
> > > +  - mediatek,mt8173-m4u #mt8173 generation two HW
> > > +  - mediatek,mt8183-m4u #mt8183 generation two HW
> > > +
> > > +  reg:
> > > +maxItems: 1
>
> [snip]
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH] iommu/exynos: add missing put_device() call in exynos_iommu_of_xlate()

2020-09-18 Thread Marek Szyprowski
Hi

On 18.09.2020 03:13, Yu Kuai wrote:
> if of_find_device_by_node() succeed, exynos_iommu_of_xlate() doesn't have
> a corresponding put_device(). Thus add put_device() to fix the exception
> handling for this function implementation.
>
> Fixes: aa759fd376fb ("iommu/exynos: Add callback for initializing devices 
> from device tree")
> Signed-off-by: Yu Kuai 

Thanks for the fix!

Acked-by: Marek Szyprowski 

> ---
>   drivers/iommu/exynos-iommu.c | 8 ++--
>   1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
> index bad3c0ce10cb..de324b4eedfe 100644
> --- a/drivers/iommu/exynos-iommu.c
> +++ b/drivers/iommu/exynos-iommu.c
> @@ -1295,13 +1295,17 @@ static int exynos_iommu_of_xlate(struct device *dev,
>   return -ENODEV;
>   
>   data = platform_get_drvdata(sysmmu);
> - if (!data)
> + if (!data) {
> + put_device(>dev);
>   return -ENODEV;
> + }
>   
>   if (!owner) {
>   owner = kzalloc(sizeof(*owner), GFP_KERNEL);
> - if (!owner)
> + if (!owner) {
> + put_device(>dev);
>   return -ENOMEM;
> + }
>   
>   INIT_LIST_HEAD(>controllers);
>   mutex_init(>rpm_lock);

Best regards
-- 
Marek Szyprowski, PhD
Samsung R Institute Poland

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


Re: [PATCH] iommu/qcom: add missing put_device() call in qcom_iommu_of_xlate()

2020-09-18 Thread Markus Elfring
…
> +++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
…
> @@ -595,6 +597,7 @@ static int qcom_iommu_of_xlate(struct device *dev, struct 
> of_phandle_args *args)
>* banks are ok, but multiple devices are not:
>*/
>   if (WARN_ON(qcom_iommu != dev_iommu_priv_get(dev)))
> + put_device(_pdev->dev);
>   return -EINVAL;
>   }

* Would there be a need to use curly brackets for such an if branch?

* I suggest to add a jump target so that a bit of common exception handling code
  can be better reused for this function implementation.

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

Re: [PATCH] Handle init_iova_flush_queue failure in dma-iommu path

2020-09-18 Thread Joerg Roedel
On Thu, Sep 10, 2020 at 01:25:38PM +0100, Tom Murphy wrote:
> init_iova_flush_queue can fail if we run out of memory. Fall back to noflush
>  queue if it fails.
> 
> Signed-off-by: Tom Murphy 
> ---
>  drivers/iommu/dma-iommu.c | 7 +--
>  1 file changed, 5 insertions(+), 2 deletions(-)

Applied, thanks Tom.

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


Re: [PATCH 00/18] Convert arch/arm to use iommu-dma

2020-09-18 Thread Marek Szyprowski
Hi all,

On 24.08.2020 13:40, Marek Szyprowski wrote:
> On 20.08.2020 17:08, Robin Murphy wrote:
>> After 5 years or so of intending to get round to this, finally the
>> time comes! The changes themselves actualy turn out to be relatively
>> mechanical; the bigger concern appears to be how to get everything
>> merged across about 5 diffferent trees given the dependencies.
>>
>> I've lightly boot-tested things on Rockchip RK3288 and Exynos 4412
>> (Odroid-U3), to the degree that their display drivers should be using
>> IOMMU-backed buffers and don't explode (the Odroid doesn't manage to
>> send a working HDMI signal to the one monitor I have that it actually
>> detects, but that's a pre-existing condition...) Confirmation that the
>> Mediatek, OMAP and Tegra changes work will be most welcome.
>>
>> Patches are based on 5.9-rc1, branch available here:
>>
>>    git://linux-arm.org/linux-rm arm/dma
>
> Well, my first proposal for the ARM and ARM64 DMA-mapping unification 
> has been posted long time ago: https://lkml.org/lkml/2016/2/19/79
>
> Thanks for resurrecting it! :)
>
> I've tested this patchset on various ARM32bit Exynos based boards (not 
> only Exynos4412) and most of them works fine after your conversion. 
> However there are issues you cannot learn from the code.
>
> Conversion of the Exynos DRM was straightforward (thanks!), but there 
> are other Exynos drivers that depends on the old ARM implementation. 
> The S5P-MFC (only for the v5 hardware) and Exynos4 FIMC-ISP drivers 
> depends on the first-fit IOVA allocation algorithm in the old ARM 
> DMA-mapping. This was the main reason I've didn't continue my initial 
> conversion attempt.
>
> Both drivers allocate a buffer for their firmware and then in the 
> hardware registers address video buffers as an offset from the 
> begginning of the firmware. This doesn't work when underlying 
> DMA-mapping allocates IOVA with the last-fit algorithm, what the 
> drivers/iommu/dma-iommu.c does. So far I didn't find a good solution 
> for that issue.
>
> I'm open for suggestions. One more limitation for the S5P-MFC driver 
> is that the hardware is capable only for addressing 128MiB. They will 
> probably need to call IOMMU API directly, but I would like to keep as 
> much from the IOMMU/DMA-mapping code as possible.

Just for the record. I've finally managed to add needed workarounds to 
the both problematic Exynos4 drivers, so they work fine with this 
patchset. It turned out that it wasn't that hard:

https://lore.kernel.org/linux-samsung-soc/20200918144833.14618-1-m.szyprow...@samsung.com/T/#t

So from my side you have a green light to go ahead and switch ARM 32bit 
to generic code. Time to say good bye to the one of my biggest 
architecture related things merged once to mainline Linux. ;)

Best regards
-- 
Marek Szyprowski, PhD
Samsung R Institute Poland

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

Re: [PATCH] iommu/arm-smmu-v3: Fix endianness annotations

2020-09-18 Thread Jean-Philippe Brucker
On Fri, Sep 18, 2020 at 04:02:26PM +0100, Robin Murphy wrote:
> On 2020-09-18 15:18, Jean-Philippe Brucker wrote:
> > When building with C=1, sparse reports some issues regarding endianness
> > annotations:
> > 
> > arm-smmu-v3.c:221:26: warning: cast to restricted __le64
> > arm-smmu-v3.c:221:24: warning: incorrect type in assignment (different base 
> > types)
> > arm-smmu-v3.c:221:24:expected restricted __le64 [usertype]
> > arm-smmu-v3.c:221:24:got unsigned long long [usertype]
> > arm-smmu-v3.c:229:20: warning: incorrect type in argument 1 (different base 
> > types)
> > arm-smmu-v3.c:229:20:expected restricted __le64 [usertype] *[assigned] 
> > dst
> > arm-smmu-v3.c:229:20:got unsigned long long [usertype] *ent
> > arm-smmu-v3.c:229:25: warning: incorrect type in argument 2 (different base 
> > types)
> > arm-smmu-v3.c:229:25:expected unsigned long long [usertype] *[assigned] 
> > src
> > arm-smmu-v3.c:229:25:got restricted __le64 [usertype] *
> > arm-smmu-v3.c:396:20: warning: incorrect type in argument 1 (different base 
> > types)
> > arm-smmu-v3.c:396:20:expected restricted __le64 [usertype] *[assigned] 
> > dst
> > arm-smmu-v3.c:396:20:got unsigned long long *
> > arm-smmu-v3.c:396:25: warning: incorrect type in argument 2 (different base 
> > types)
> > arm-smmu-v3.c:396:25:expected unsigned long long [usertype] *[assigned] 
> > src
> > arm-smmu-v3.c:396:25:got restricted __le64 [usertype] *
> > arm-smmu-v3.c:1349:32: warning: invalid assignment: |=
> > arm-smmu-v3.c:1349:32:left side has type restricted __le64
> > arm-smmu-v3.c:1349:32:right side has type unsigned long
> > arm-smmu-v3.c:1396:53: warning: incorrect type in argument 3 (different 
> > base types)
> > arm-smmu-v3.c:1396:53:expected restricted __le64 [usertype] *dst
> > arm-smmu-v3.c:1396:53:got unsigned long long [usertype] *strtab
> > arm-smmu-v3.c:1424:39: warning: incorrect type in argument 1 (different 
> > base types)
> > arm-smmu-v3.c:1424:39:expected unsigned long long [usertype] 
> > *[assigned] strtab
> > arm-smmu-v3.c:1424:39:got restricted __le64 [usertype] *l2ptr
> > 
> > While harmless, they are incorrect and could hide actual errors during
> > development. Fix them.
> 
> Reviewed-by: Robin Murphy 

Thanks!

> > Signed-off-by: Jean-Philippe Brucker 
> > ---
> > 
> > There is another false positive due to passing INT_MIN to cmpxchg, and
> > __cmpxchg* to truncate them to u8 and u16:
> > 
> > arch/arm64/include/asm/cmpxchg.h:172:1: warning: cast truncates bits from 
> > constant value (8000 becomes 0)
> > arch/arm64/include/asm/cmpxchg.h:172:1: warning: cast truncates bits from 
> > constant value (8000 becomes 0)
> > 
> > I haven't found a satisfying fix so far, except adding __force to
> > __cmpxchg_case* which could hide actual bugs.
> 
> I guess that's a general issue with the switch(sizeof()) idiom of sparse not
> being aware that those cases are unreachable?

Precisely. I wondered if _Generic could help, but it looks like the
problem is the same.

Thanks,
Jean

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


[git pull] IOMMU Fixes for Linux v5.9-rc5

2020-09-18 Thread Joerg Roedel
Hi Linus,

The following changes since commit 856deb866d16e29bd65952e0289066f6078af773:

  Linux 5.9-rc5 (2020-09-13 16:06:00 -0700)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git 
tags/iommu-fixes-v5.9-rc5

for you to fetch changes up to e97685abd5d711c885053d4949178f7ab9acbaef:

  iommu/amd: Restore IRTE.RemapEn bit for amd_iommu_activate_guest_mode 
(2020-09-18 11:17:19 +0200)


IOMMU Fixes for Linux v5.9-rc5

Two fixes for the AMD IOMMU driver:

- Fix a potential NULL-ptr dereference found by smatch

- Fix interrupt remapping when a device is assigned to a guest
  and AVIC is enabled.


Joao Martins (1):
  iommu/amd: Fix potential @entry null deref

Suravee Suthikulpanit (1):
  iommu/amd: Restore IRTE.RemapEn bit for amd_iommu_activate_guest_mode

 drivers/iommu/amd/iommu.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

Please pull.

Thanks,

Joerg


signature.asc
Description: Digital signature
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCH] iommu/arm-smmu-v3: Fix endianness annotations

2020-09-18 Thread Robin Murphy

On 2020-09-18 15:18, Jean-Philippe Brucker wrote:

When building with C=1, sparse reports some issues regarding endianness
annotations:

arm-smmu-v3.c:221:26: warning: cast to restricted __le64
arm-smmu-v3.c:221:24: warning: incorrect type in assignment (different base 
types)
arm-smmu-v3.c:221:24:expected restricted __le64 [usertype]
arm-smmu-v3.c:221:24:got unsigned long long [usertype]
arm-smmu-v3.c:229:20: warning: incorrect type in argument 1 (different base 
types)
arm-smmu-v3.c:229:20:expected restricted __le64 [usertype] *[assigned] dst
arm-smmu-v3.c:229:20:got unsigned long long [usertype] *ent
arm-smmu-v3.c:229:25: warning: incorrect type in argument 2 (different base 
types)
arm-smmu-v3.c:229:25:expected unsigned long long [usertype] *[assigned] src
arm-smmu-v3.c:229:25:got restricted __le64 [usertype] *
arm-smmu-v3.c:396:20: warning: incorrect type in argument 1 (different base 
types)
arm-smmu-v3.c:396:20:expected restricted __le64 [usertype] *[assigned] dst
arm-smmu-v3.c:396:20:got unsigned long long *
arm-smmu-v3.c:396:25: warning: incorrect type in argument 2 (different base 
types)
arm-smmu-v3.c:396:25:expected unsigned long long [usertype] *[assigned] src
arm-smmu-v3.c:396:25:got restricted __le64 [usertype] *
arm-smmu-v3.c:1349:32: warning: invalid assignment: |=
arm-smmu-v3.c:1349:32:left side has type restricted __le64
arm-smmu-v3.c:1349:32:right side has type unsigned long
arm-smmu-v3.c:1396:53: warning: incorrect type in argument 3 (different base 
types)
arm-smmu-v3.c:1396:53:expected restricted __le64 [usertype] *dst
arm-smmu-v3.c:1396:53:got unsigned long long [usertype] *strtab
arm-smmu-v3.c:1424:39: warning: incorrect type in argument 1 (different base 
types)
arm-smmu-v3.c:1424:39:expected unsigned long long [usertype] *[assigned] 
strtab
arm-smmu-v3.c:1424:39:got restricted __le64 [usertype] *l2ptr

While harmless, they are incorrect and could hide actual errors during
development. Fix them.


Reviewed-by: Robin Murphy 


Signed-off-by: Jean-Philippe Brucker 
---

There is another false positive due to passing INT_MIN to cmpxchg, and
__cmpxchg* to truncate them to u8 and u16:

arch/arm64/include/asm/cmpxchg.h:172:1: warning: cast truncates bits from 
constant value (8000 becomes 0)
arch/arm64/include/asm/cmpxchg.h:172:1: warning: cast truncates bits from 
constant value (8000 becomes 0)

I haven't found a satisfying fix so far, except adding __force to
__cmpxchg_case* which could hide actual bugs.


I guess that's a general issue with the switch(sizeof()) idiom of sparse 
not being aware that those cases are unreachable?


Robin.


---
  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index c192544e874b..83acc1e5888e 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -867,7 +867,7 @@ static void queue_write(__le64 *dst, u64 *src, size_t 
n_dwords)
*dst++ = cpu_to_le64(*src++);
  }
  
-static void queue_read(__le64 *dst, u64 *src, size_t n_dwords)

+static void queue_read(u64 *dst, __le64 *src, size_t n_dwords)
  {
int i;
  
@@ -1939,7 +1939,7 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,

arm_smmu_cmdq_issue_cmd(smmu, _cmd);
  }
  
-static void arm_smmu_init_bypass_stes(u64 *strtab, unsigned int nent)

+static void arm_smmu_init_bypass_stes(__le64 *strtab, unsigned int nent)
  {
unsigned int i;
  


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


Re: [PATCH v2 2/2] iommu/iova: Free global iova rcache on iova alloc failure

2020-09-18 Thread Robin Murphy

On 2020-08-20 13:49, vji...@codeaurora.org wrote:

From: Vijayanand Jitta 

When ever an iova alloc request fails we free the iova
ranges present in the percpu iova rcaches and then retry
but the global iova rcache is not freed as a result we could
still see iova alloc failure even after retry as global
rcache is holding the iova's which can cause fragmentation.
So, free the global iova rcache as well and then go for the
retry.

Signed-off-by: Vijayanand Jitta 
---
  drivers/iommu/iova.c | 23 +++
  include/linux/iova.h |  6 ++
  2 files changed, 29 insertions(+)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 4e77116..5836c87 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -442,6 +442,7 @@ struct iova *find_iova(struct iova_domain *iovad, unsigned 
long pfn)
flush_rcache = false;
for_each_online_cpu(cpu)
free_cpu_cached_iovas(cpu, iovad);
+   free_global_cached_iovas(iovad);
goto retry;
}
  
@@ -1055,5 +1056,27 @@ void free_cpu_cached_iovas(unsigned int cpu, struct iova_domain *iovad)

}
  }
  
+/*

+ * free all the IOVA ranges of global cache
+ */
+void free_global_cached_iovas(struct iova_domain *iovad)


As John pointed out last time, this should be static and the header 
changes dropped.


(TBH we should probably register our own hotplug notifier instance for a 
flush queue, so that external code has no need to poke at the per-CPU 
caches either)


Robin.


+{
+   struct iova_rcache *rcache;
+   unsigned long flags;
+   int i, j;
+
+   for (i = 0; i < IOVA_RANGE_CACHE_MAX_SIZE; ++i) {
+   rcache = >rcaches[i];
+   spin_lock_irqsave(>lock, flags);
+   for (j = 0; j < rcache->depot_size; ++j) {
+   iova_magazine_free_pfns(rcache->depot[j], iovad);
+   iova_magazine_free(rcache->depot[j]);
+   rcache->depot[j] = NULL;
+   }
+   rcache->depot_size = 0;
+   spin_unlock_irqrestore(>lock, flags);
+   }
+}
+
  MODULE_AUTHOR("Anil S Keshavamurthy ");
  MODULE_LICENSE("GPL");
diff --git a/include/linux/iova.h b/include/linux/iova.h
index a0637ab..a905726 100644
--- a/include/linux/iova.h
+++ b/include/linux/iova.h
@@ -163,6 +163,7 @@ int init_iova_flush_queue(struct iova_domain *iovad,
  struct iova *split_and_remove_iova(struct iova_domain *iovad,
struct iova *iova, unsigned long pfn_lo, unsigned long pfn_hi);
  void free_cpu_cached_iovas(unsigned int cpu, struct iova_domain *iovad);
+void free_global_cached_iovas(struct iova_domain *iovad);
  #else
  static inline int iova_cache_get(void)
  {
@@ -270,6 +271,11 @@ static inline void free_cpu_cached_iovas(unsigned int cpu,
 struct iova_domain *iovad)
  {
  }
+
+static inline void free_global_cached_iovas(struct iova_domain *iovad)
+{
+}
+
  #endif
  
  #endif



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


Re: [PATCH 14/18] drm/exynos: Consolidate IOMMU mapping code

2020-09-18 Thread Marek Szyprowski
Hi Robin,

On 20.08.2020 17:08, Robin Murphy wrote:
> Now that arch/arm is wired up for default domains and iommu-dma, we can
> consolidate the shared mapping code onto the generic IOMMU API version,
> and retire the arch-specific implementation.
>
> Signed-off-by: Robin Murphy 
>
> ---
> This is a cheeky revert of 07dc3678bacc ("drm/exynos: Fix cleanup of
> IOMMU related objects"), plus removal of the remaining arm_iommu_*
> references on top.

I have one more suggestion to this patch. Please rename 
exynos_drm_private->mapping to exynos_drm_private->domain and change its 
type from "void *" to "struct iommu_domain *". The "void *" was there to 
support both old-ARM and ARM64 IOMMU/DMA-mapping frameworks, but now we 
can use the proper pointer types.

> ---
>   drivers/gpu/drm/exynos/exynos5433_drm_decon.c |  5 +-
>   drivers/gpu/drm/exynos/exynos7_drm_decon.c|  5 +-
>   drivers/gpu/drm/exynos/exynos_drm_dma.c   | 61 +++
>   drivers/gpu/drm/exynos/exynos_drm_drv.h   |  6 +-
>   drivers/gpu/drm/exynos/exynos_drm_fimc.c  |  5 +-
>   drivers/gpu/drm/exynos/exynos_drm_fimd.c  |  5 +-
>   drivers/gpu/drm/exynos/exynos_drm_g2d.c   |  5 +-
>   drivers/gpu/drm/exynos/exynos_drm_gsc.c   |  5 +-
>   drivers/gpu/drm/exynos/exynos_drm_rotator.c   |  5 +-
>   drivers/gpu/drm/exynos/exynos_drm_scaler.c|  6 +-
>   drivers/gpu/drm/exynos/exynos_mixer.c |  7 +--
>   11 files changed, 29 insertions(+), 86 deletions(-)
>
> diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c 
> b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
> index 1f79bc2a881e..8428ae12dfa5 100644
> --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
> +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
> @@ -55,7 +55,6 @@ static const char * const decon_clks_name[] = {
>   struct decon_context {
>   struct device   *dev;
>   struct drm_device   *drm_dev;
> - void*dma_priv;
>   struct exynos_drm_crtc  *crtc;
>   struct exynos_drm_plane planes[WINDOWS_NR];
>   struct exynos_drm_plane_config  configs[WINDOWS_NR];
> @@ -645,7 +644,7 @@ static int decon_bind(struct device *dev, struct device 
> *master, void *data)
>   
>   decon_clear_channels(ctx->crtc);
>   
> - return exynos_drm_register_dma(drm_dev, dev, >dma_priv);
> + return exynos_drm_register_dma(drm_dev, dev);
>   }
>   
>   static void decon_unbind(struct device *dev, struct device *master, void 
> *data)
> @@ -655,7 +654,7 @@ static void decon_unbind(struct device *dev, struct 
> device *master, void *data)
>   decon_atomic_disable(ctx->crtc);
>   
>   /* detach this sub driver from iommu mapping if supported. */
> - exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev, >dma_priv);
> + exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev);
>   }
>   
>   static const struct component_ops decon_component_ops = {
> diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c 
> b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
> index f2d87a7445c7..e7b58097ccdc 100644
> --- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
> +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
> @@ -40,7 +40,6 @@
>   struct decon_context {
>   struct device   *dev;
>   struct drm_device   *drm_dev;
> - void*dma_priv;
>   struct exynos_drm_crtc  *crtc;
>   struct exynos_drm_plane planes[WINDOWS_NR];
>   struct exynos_drm_plane_config  configs[WINDOWS_NR];
> @@ -128,13 +127,13 @@ static int decon_ctx_initialize(struct decon_context 
> *ctx,
>   
>   decon_clear_channels(ctx->crtc);
>   
> - return exynos_drm_register_dma(drm_dev, ctx->dev, >dma_priv);
> + return exynos_drm_register_dma(drm_dev, ctx->dev);
>   }
>   
>   static void decon_ctx_remove(struct decon_context *ctx)
>   {
>   /* detach this sub driver from iommu mapping if supported. */
> - exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev, >dma_priv);
> + exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev);
>   }
>   
>   static u32 decon_calc_clkdiv(struct decon_context *ctx,
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_dma.c 
> b/drivers/gpu/drm/exynos/exynos_drm_dma.c
> index 58b89ec11b0e..fd5f9bcf1857 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_dma.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_dma.c
> @@ -14,19 +14,6 @@
>   
>   #include "exynos_drm_drv.h"
>   
> -#if defined(CONFIG_ARM_DMA_USE_IOMMU)
> -#include 
> -#else
> -#define arm_iommu_create_mapping(...)({ NULL; })
> -#define arm_iommu_attach_device(...) ({ -ENODEV; })
> -#define arm_iommu_release_mapping(...)   ({ })
> -#define arm_iommu_detach_device(...) ({ })
> -#define to_dma_iommu_mapping(dev) NULL
> -#endif
> -
> -#if !defined(CONFIG_IOMMU_DMA)
> -#define iommu_dma_init_domain(...) ({ -EINVAL; })
> -#endif
>   
>   #define EXYNOS_DEV_ADDR_START   0x2000
>   #define EXYNOS_DEV_ADDR_SIZE  

[PATCH] iommu/arm-smmu-v3: Fix endianness annotations

2020-09-18 Thread Jean-Philippe Brucker
When building with C=1, sparse reports some issues regarding endianness
annotations:

arm-smmu-v3.c:221:26: warning: cast to restricted __le64
arm-smmu-v3.c:221:24: warning: incorrect type in assignment (different base 
types)
arm-smmu-v3.c:221:24:expected restricted __le64 [usertype]
arm-smmu-v3.c:221:24:got unsigned long long [usertype]
arm-smmu-v3.c:229:20: warning: incorrect type in argument 1 (different base 
types)
arm-smmu-v3.c:229:20:expected restricted __le64 [usertype] *[assigned] dst
arm-smmu-v3.c:229:20:got unsigned long long [usertype] *ent
arm-smmu-v3.c:229:25: warning: incorrect type in argument 2 (different base 
types)
arm-smmu-v3.c:229:25:expected unsigned long long [usertype] *[assigned] src
arm-smmu-v3.c:229:25:got restricted __le64 [usertype] *
arm-smmu-v3.c:396:20: warning: incorrect type in argument 1 (different base 
types)
arm-smmu-v3.c:396:20:expected restricted __le64 [usertype] *[assigned] dst
arm-smmu-v3.c:396:20:got unsigned long long *
arm-smmu-v3.c:396:25: warning: incorrect type in argument 2 (different base 
types)
arm-smmu-v3.c:396:25:expected unsigned long long [usertype] *[assigned] src
arm-smmu-v3.c:396:25:got restricted __le64 [usertype] *
arm-smmu-v3.c:1349:32: warning: invalid assignment: |=
arm-smmu-v3.c:1349:32:left side has type restricted __le64
arm-smmu-v3.c:1349:32:right side has type unsigned long
arm-smmu-v3.c:1396:53: warning: incorrect type in argument 3 (different base 
types)
arm-smmu-v3.c:1396:53:expected restricted __le64 [usertype] *dst
arm-smmu-v3.c:1396:53:got unsigned long long [usertype] *strtab
arm-smmu-v3.c:1424:39: warning: incorrect type in argument 1 (different base 
types)
arm-smmu-v3.c:1424:39:expected unsigned long long [usertype] *[assigned] 
strtab
arm-smmu-v3.c:1424:39:got restricted __le64 [usertype] *l2ptr

While harmless, they are incorrect and could hide actual errors during
development. Fix them.

Signed-off-by: Jean-Philippe Brucker 
---

There is another false positive due to passing INT_MIN to cmpxchg, and
__cmpxchg* to truncate them to u8 and u16:

arch/arm64/include/asm/cmpxchg.h:172:1: warning: cast truncates bits from 
constant value (8000 becomes 0)
arch/arm64/include/asm/cmpxchg.h:172:1: warning: cast truncates bits from 
constant value (8000 becomes 0)

I haven't found a satisfying fix so far, except adding __force to
__cmpxchg_case* which could hide actual bugs.
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index c192544e874b..83acc1e5888e 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -867,7 +867,7 @@ static void queue_write(__le64 *dst, u64 *src, size_t 
n_dwords)
*dst++ = cpu_to_le64(*src++);
 }
 
-static void queue_read(__le64 *dst, u64 *src, size_t n_dwords)
+static void queue_read(u64 *dst, __le64 *src, size_t n_dwords)
 {
int i;
 
@@ -1939,7 +1939,7 @@ static void arm_smmu_write_strtab_ent(struct 
arm_smmu_master *master, u32 sid,
arm_smmu_cmdq_issue_cmd(smmu, _cmd);
 }
 
-static void arm_smmu_init_bypass_stes(u64 *strtab, unsigned int nent)
+static void arm_smmu_init_bypass_stes(__le64 *strtab, unsigned int nent)
 {
unsigned int i;
 
-- 
2.28.0

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


Re: [PATCH v2 1/2] iommu/iova: Retry from last rb tree node if iova search fails

2020-09-18 Thread Robin Murphy

On 2020-08-20 13:49, vji...@codeaurora.org wrote:

From: Vijayanand Jitta 

When ever a new iova alloc request comes iova is always searched
from the cached node and the nodes which are previous to cached
node. So, even if there is free iova space available in the nodes
which are next to the cached node iova allocation can still fail
because of this approach.

Consider the following sequence of iova alloc and frees on
1GB of iova space

1) alloc - 500MB
2) alloc - 12MB
3) alloc - 499MB
4) free -  12MB which was allocated in step 2
5) alloc - 13MB

After the above sequence we will have 12MB of free iova space and
cached node will be pointing to the iova pfn of last alloc of 13MB
which will be the lowest iova pfn of that iova space. Now if we get an
alloc request of 2MB we just search from cached node and then look
for lower iova pfn's for free iova and as they aren't any, iova alloc
fails though there is 12MB of free iova space.

To avoid such iova search failures do a retry from the last rb tree node
when iova search fails, this will search the entire tree and get an iova
if its available.

Signed-off-by: Vijayanand Jitta 
---
  drivers/iommu/iova.c | 23 +--
  1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 49fc01f..4e77116 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -184,8 +184,9 @@ static int __alloc_and_insert_iova_range(struct iova_domain 
*iovad,
struct rb_node *curr, *prev;
struct iova *curr_iova;
unsigned long flags;
-   unsigned long new_pfn;
+   unsigned long new_pfn, low_pfn_new;
unsigned long align_mask = ~0UL;
+   unsigned long high_pfn = limit_pfn, low_pfn = iovad->start_pfn;
  
  	if (size_aligned)

align_mask <<= fls_long(size - 1);
@@ -198,15 +199,25 @@ static int __alloc_and_insert_iova_range(struct 
iova_domain *iovad,
  
  	curr = __get_cached_rbnode(iovad, limit_pfn);

curr_iova = rb_entry(curr, struct iova, node);
+   low_pfn_new = curr_iova->pfn_hi + 1;


Could we call "low_pfn_new" something like "retry_pfn" instead? This 
code already has unavoidable readability struggles with so many 
different "pfn"s in play, so having two different meanings of "new" 
really doesn't help.


Other than that, I think this looks OK (IIRC it's basically what I 
originally suggested), so with the naming tweaked,


Reviewed-by: Robin Murphy 


+
+retry:
do {
-   limit_pfn = min(limit_pfn, curr_iova->pfn_lo);
-   new_pfn = (limit_pfn - size) & align_mask;
+   high_pfn = min(high_pfn, curr_iova->pfn_lo);
+   new_pfn = (high_pfn - size) & align_mask;
prev = curr;
curr = rb_prev(curr);
curr_iova = rb_entry(curr, struct iova, node);
-   } while (curr && new_pfn <= curr_iova->pfn_hi);
-
-   if (limit_pfn < size || new_pfn < iovad->start_pfn) {
+   } while (curr && new_pfn <= curr_iova->pfn_hi && new_pfn >= low_pfn);
+
+   if (high_pfn < size || new_pfn < low_pfn) {
+   if (low_pfn == iovad->start_pfn && low_pfn_new < limit_pfn) {
+   high_pfn = limit_pfn;
+   low_pfn = low_pfn_new;
+   curr = >anchor.node;
+   curr_iova = rb_entry(curr, struct iova, node);
+   goto retry;
+   }
iovad->max32_alloc_size = size;
goto iova32_full;
}


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


Re: [PATCH] Handle init_iova_flush_queue failure in dma-iommu path

2020-09-18 Thread Robin Murphy

On 2020-09-18 09:55, Joerg Roedel wrote:

On Thu, Sep 10, 2020 at 01:25:38PM +0100, Tom Murphy wrote:

init_iova_flush_queue can fail if we run out of memory. Fall back to noflush
  queue if it fails.

Signed-off-by: Tom Murphy 
---
  drivers/iommu/dma-iommu.c | 7 +--
  1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 4959f5df21bd..5f69126f3e91 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -343,8 +343,11 @@ static int iommu_dma_init_domain(struct iommu_domain 
*domain, dma_addr_t base,
  
  	if (!cookie->fq_domain && !iommu_domain_get_attr(domain,

DOMAIN_ATTR_DMA_USE_FLUSH_QUEUE, ) && attr) {
-   cookie->fq_domain = domain;
-   init_iova_flush_queue(iovad, iommu_dma_flush_iotlb_all, NULL);
+   if (init_iova_flush_queue(iovad, iommu_dma_flush_iotlb_all,
+   NULL))
+   pr_warn("iova flush queue initialization failed\n");
+   else
+   cookie->fq_domain = domain;
}
  
  	if (!dev)


Looks good to me, but Robin should also have a look.


Yup, seems reasonable, thanks Tom!

Reviewed-by: Robin Murphy 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v10 00/13] iommu: Shared Virtual Addressing for SMMUv3 (PT sharing part)

2020-09-18 Thread Jonathan Cameron
On Fri, 18 Sep 2020 12:18:40 +0200
Jean-Philippe Brucker  wrote:

> This is version 10 of the page table sharing support for Arm SMMUv3.
> Patch 1 still needs an Ack from mm maintainers. However patches 4-11 do
> not depend on it, and could get merged for v5.10 regardless.

Hi Jean-Philippe,

It's been a rather long time since I last looked at this stuff (about v4
I think!), but I just had a read through this set and they all look good to me.

FWIW:
Reviewed-by: Jonathan Cameron 

Thanks,

Jonathan

> 
> v10:
> * Fix patches 3, 8, 9 and 10 following Eric's review.
> 
> v9 resend: 
> https://lore.kernel.org/linux-iommu/20200817171558.325917-1-jean-phili...@linaro.org/
> * Rebased onto v5.9-rc1. Moved to drivers/iommu/arm/arm-smmu-v3/ as a
>   result.
> 
> v9: 
> https://lore.kernel.org/linux-iommu/20200723145724.3014766-1-jean-phili...@linaro.org/
> * Moved most of the SVA code to arm-smmu-v3-sva.c. This required moving
>   struct definitions and macros to arm-smmu-v3.h (patch 7), hence the
>   new 700 insertions/deletions in the diffstat.
> * Updated patches 4 and 8 following review.
> * Fixed a bug when replacing a private ASID.
> 
> v8: 
> https://lore.kernel.org/linux-iommu/20200618155125.1548969-1-jean-phili...@linaro.org/
> * Split SVA series into three parts: page table sharing, I/O page
>   faults, and additional features (DVM, VHE and HTTU).
> 
> Fenghua Yu (1):
>   mm: Define pasid in mm
> 
> Jean-Philippe Brucker (12):
>   iommu/ioasid: Add ioasid references
>   iommu/sva: Add PASID helpers
>   arm64: mm: Pin down ASIDs for sharing mm with devices
>   iommu/io-pgtable-arm: Move some definitions to a header
>   arm64: cpufeature: Export symbol read_sanitised_ftr_reg()
>   iommu/arm-smmu-v3: Move definitions to a header
>   iommu/arm-smmu-v3: Share process page tables
>   iommu/arm-smmu-v3: Seize private ASID
>   iommu/arm-smmu-v3: Check for SVA features
>   iommu/arm-smmu-v3: Add SVA device feature
>   iommu/arm-smmu-v3: Implement iommu_sva_bind/unbind()
>   iommu/arm-smmu-v3: Hook up ATC invalidation to mm ops
> 
>  drivers/iommu/Kconfig |  17 +
>  drivers/iommu/Makefile|   1 +
>  drivers/iommu/arm/arm-smmu-v3/Makefile|   5 +-
>  arch/arm64/include/asm/mmu.h  |   3 +
>  arch/arm64/include/asm/mmu_context.h  |  11 +-
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   | 752 +++
>  drivers/iommu/io-pgtable-arm.h|  30 +
>  drivers/iommu/iommu-sva-lib.h |  15 +
>  include/linux/ioasid.h|  10 +-
>  include/linux/mm_types.h  |   4 +
>  arch/arm64/kernel/cpufeature.c|   1 +
>  arch/arm64/mm/context.c   | 105 ++-
>  .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c   | 488 ++
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   | 860 --
>  drivers/iommu/intel/iommu.c   |   4 +-
>  drivers/iommu/intel/svm.c |   6 +-
>  drivers/iommu/io-pgtable-arm.c|  27 +-
>  drivers/iommu/ioasid.c|  38 +-
>  drivers/iommu/iommu-sva-lib.c |  86 ++
>  MAINTAINERS   |   3 +-
>  20 files changed, 1731 insertions(+), 735 deletions(-)
>  create mode 100644 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
>  create mode 100644 drivers/iommu/io-pgtable-arm.h
>  create mode 100644 drivers/iommu/iommu-sva-lib.h
>  create mode 100644 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
>  create mode 100644 drivers/iommu/iommu-sva-lib.c
> 


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


Re: [PATCH v10 09/13] iommu/arm-smmu-v3: Seize private ASID

2020-09-18 Thread Jonathan Cameron
On Fri, 18 Sep 2020 12:18:49 +0200
Jean-Philippe Brucker  wrote:

> The SMMU has a single ASID space, the union of shared and private ASID
> sets. This means that the SMMU driver competes with the arch allocator
> for ASIDs. Shared ASIDs are those of Linux processes, allocated by the
> arch, and contribute in broadcast TLB maintenance. Private ASIDs are
> allocated by the SMMU driver and used for "classic" map/unmap DMA. They
> require command-queue TLB invalidations.
> 
> When we pin down an mm_context and get an ASID that is already in use by
> the SMMU, it belongs to a private context. We used to simply abort the
> bind, but this is unfair to users that would be unable to bind a few
> seemingly random processes. Try to allocate a new private ASID for the
> context, and make the old ASID shared.
> 
> Signed-off-by: Jean-Philippe Brucker 
Hi,

One totally trivial comment inline that might have ever so slightly
improved reviewability of the patch.

However it is only minor so don't bother respinning for that.

Thanks,

Jonathan

> ---
> v10: fix ASID limit, small comment update
> ---
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |  3 ++
>  .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c   | 35 +--
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   | 34 +++---
>  3 files changed, 57 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h 
> b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> index 6b06a6f19604..90c08f156b43 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> @@ -678,6 +678,9 @@ struct arm_smmu_domain {
>  extern struct xarray arm_smmu_asid_xa;
>  extern struct mutex arm_smmu_asid_lock;
>  
> +int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
> + struct arm_smmu_ctx_desc *cd);
> +void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid);
>  bool arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd);
>  
>  #endif /* _ARM_SMMU_V3_H */
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c 
> b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
> index 6c1113059632..ef3fcfa72187 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
> @@ -10,10 +10,18 @@
>  #include "arm-smmu-v3.h"
>  #include "../../io-pgtable-arm.h"
>  
> +/*
> + * Check if the CPU ASID is available on the SMMU side. If a private context
> + * descriptor is using it, try to replace it.
> + */
>  static struct arm_smmu_ctx_desc *
>  arm_smmu_share_asid(struct mm_struct *mm, u16 asid)
>  {
> + int ret;
> + u32 new_asid;
>   struct arm_smmu_ctx_desc *cd;
> + struct arm_smmu_device *smmu;
> + struct arm_smmu_domain *smmu_domain;
>  
>   cd = xa_load(_smmu_asid_xa, asid);
>   if (!cd)
> @@ -27,8 +35,31 @@ arm_smmu_share_asid(struct mm_struct *mm, u16 asid)
>   return cd;
>   }
>  
> - /* Ouch, ASID is already in use for a private cd. */
> - return ERR_PTR(-EBUSY);
> + smmu_domain = container_of(cd, struct arm_smmu_domain, s1_cfg.cd);
> + smmu = smmu_domain->smmu;
> +
> + ret = xa_alloc(_smmu_asid_xa, _asid, cd,
> +XA_LIMIT(1, (1 << smmu->asid_bits) - 1), GFP_KERNEL);
> + if (ret)
> + return ERR_PTR(-ENOSPC);
> + /*
> +  * Race with unmap: TLB invalidations will start targeting the new ASID,
> +  * which isn't assigned yet. We'll do an invalidate-all on the old ASID
> +  * later, so it doesn't matter.
> +  */
> + cd->asid = new_asid;
> + /*
> +  * Update ASID and invalidate CD in all associated masters. There will
> +  * be some overlap between use of both ASIDs, until we invalidate the
> +  * TLB.
> +  */
> + arm_smmu_write_ctx_desc(smmu_domain, 0, cd);
> +
> + /* Invalidate TLB entries previously associated with that context */
> + arm_smmu_tlb_inv_asid(smmu, asid);
> +
> + xa_erase(_smmu_asid_xa, asid);
> + return NULL;
>  }
>  
>  __maybe_unused
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
> b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> index 19af27fd183b..e99ebdd4c841 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> @@ -872,6 +872,17 @@ static int arm_smmu_cmdq_batch_submit(struct 
> arm_smmu_device *smmu,
>  }
>  
>  /* Context descriptor manipulation functions */
> +void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid)
> +{
> + struct arm_smmu_cmdq_ent cmd = {
> + .opcode = CMDQ_OP_TLBI_NH_ASID,
> + .tlbi.asid = asid,
> + };
> +
> + arm_smmu_cmdq_issue_cmd(smmu, );
> + arm_smmu_cmdq_issue_sync(smmu);
> +}
> +
>  static void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain,
>int ssid, bool leaf)
>  {
> @@ -952,8 +963,8 @@ static __le64 *arm_smmu_get_cd_ptr(struct 

[PATCH v10 13/13] iommu/arm-smmu-v3: Hook up ATC invalidation to mm ops

2020-09-18 Thread Jean-Philippe Brucker
The invalidate_range() notifier is called for any change to the address
space. Perform the required ATC invalidations.

Signed-off-by: Jean-Philippe Brucker 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h|  2 ++
 .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c| 16 +++-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c| 18 --
 3 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 6365c81a4614..baa80498ad9f 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -694,6 +694,8 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_domain 
*smmu_domain, int ssid,
struct arm_smmu_ctx_desc *cd);
 void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid);
 bool arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd);
+int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, int ssid,
+   unsigned long iova, size_t size);
 
 #ifdef CONFIG_ARM_SMMU_V3_SVA
 bool arm_smmu_sva_supported(struct arm_smmu_device *smmu);
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
index f57c2bde68a4..7af980dbfd6d 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
@@ -177,6 +177,16 @@ static void arm_smmu_free_shared_cd(struct 
arm_smmu_ctx_desc *cd)
}
 }
 
+static void arm_smmu_mm_invalidate_range(struct mmu_notifier *mn,
+struct mm_struct *mm,
+unsigned long start, unsigned long end)
+{
+   struct arm_smmu_mmu_notifier *smmu_mn = mn_to_smmu(mn);
+
+   arm_smmu_atc_inv_domain(smmu_mn->domain, mm->pasid, start,
+   end - start + 1);
+}
+
 static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
 {
struct arm_smmu_mmu_notifier *smmu_mn = mn_to_smmu(mn);
@@ -195,6 +205,7 @@ static void arm_smmu_mm_release(struct mmu_notifier *mn, 
struct mm_struct *mm)
arm_smmu_write_ctx_desc(smmu_domain, mm->pasid, _cd);
 
arm_smmu_tlb_inv_asid(smmu_domain->smmu, smmu_mn->cd->asid);
+   arm_smmu_atc_inv_domain(smmu_domain, mm->pasid, 0, 0);
 
smmu_mn->cleared = true;
mutex_unlock(_lock);
@@ -206,6 +217,7 @@ static void arm_smmu_mmu_notifier_free(struct mmu_notifier 
*mn)
 }
 
 static struct mmu_notifier_ops arm_smmu_mmu_notifier_ops = {
+   .invalidate_range   = arm_smmu_mm_invalidate_range,
.release= arm_smmu_mm_release,
.free_notifier  = arm_smmu_mmu_notifier_free,
 };
@@ -278,8 +290,10 @@ static void arm_smmu_mmu_notifier_put(struct 
arm_smmu_mmu_notifier *smmu_mn)
 * If we went through clear(), we've already invalidated, and no
 * new TLB entry can have been formed.
 */
-   if (!smmu_mn->cleared)
+   if (!smmu_mn->cleared) {
arm_smmu_tlb_inv_asid(smmu_domain->smmu, cd->asid);
+   arm_smmu_atc_inv_domain(smmu_domain, mm->pasid, 0, 0);
+   }
 
/* Frees smmu_mn */
mmu_notifier_put(_mn->mn);
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index b43d874ab2e5..576a16a3e8aa 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1514,6 +1514,20 @@ arm_smmu_atc_inv_to_cmd(int ssid, unsigned long iova, 
size_t size,
size_t inval_grain_shift = 12;
unsigned long page_start, page_end;
 
+   /*
+* ATS and PASID:
+*
+* If substream_valid is clear, the PCIe TLP is sent without a PASID
+* prefix. In that case all ATC entries within the address range are
+* invalidated, including those that were requested with a PASID! There
+* is no way to invalidate only entries without PASID.
+*
+* When using STRTAB_STE_1_S1DSS_SSID0 (reserving CD 0 for non-PASID
+* traffic), translation requests without PASID create ATC entries
+* without PASID, which must be invalidated with substream_valid clear.
+* This has the unpleasant side-effect of invalidating all PASID-tagged
+* ATC entries within the address range.
+*/
*cmd = (struct arm_smmu_cmdq_ent) {
.opcode = CMDQ_OP_ATC_INV,
.substream_valid= !!ssid,
@@ -1572,8 +1586,8 @@ static int arm_smmu_atc_inv_master(struct arm_smmu_master 
*master)
return arm_smmu_cmdq_issue_sync(master->smmu);
 }
 
-static int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain,
-  int ssid, unsigned long iova, size_t size)
+int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, int ssid,
+   

[PATCH v10 02/13] iommu/ioasid: Add ioasid references

2020-09-18 Thread Jean-Philippe Brucker
Let IOASID users take references to existing ioasids with ioasid_get().
ioasid_put() drops a reference and only frees the ioasid when its
reference number is zero. It returns true if the ioasid was freed.
For drivers that don't call ioasid_get(), ioasid_put() is the same as
ioasid_free().

Reviewed-by: Eric Auger 
Reviewed-by: Lu Baolu 
Signed-off-by: Jean-Philippe Brucker 
---
 include/linux/ioasid.h  | 10 --
 drivers/iommu/intel/iommu.c |  4 ++--
 drivers/iommu/intel/svm.c   |  6 +++---
 drivers/iommu/ioasid.c  | 38 +
 4 files changed, 47 insertions(+), 11 deletions(-)

diff --git a/include/linux/ioasid.h b/include/linux/ioasid.h
index 6f000d7a0ddc..e9dacd4b9f6b 100644
--- a/include/linux/ioasid.h
+++ b/include/linux/ioasid.h
@@ -34,7 +34,8 @@ struct ioasid_allocator_ops {
 #if IS_ENABLED(CONFIG_IOASID)
 ioasid_t ioasid_alloc(struct ioasid_set *set, ioasid_t min, ioasid_t max,
  void *private);
-void ioasid_free(ioasid_t ioasid);
+void ioasid_get(ioasid_t ioasid);
+bool ioasid_put(ioasid_t ioasid);
 void *ioasid_find(struct ioasid_set *set, ioasid_t ioasid,
  bool (*getter)(void *));
 int ioasid_register_allocator(struct ioasid_allocator_ops *allocator);
@@ -48,10 +49,15 @@ static inline ioasid_t ioasid_alloc(struct ioasid_set *set, 
ioasid_t min,
return INVALID_IOASID;
 }
 
-static inline void ioasid_free(ioasid_t ioasid)
+static inline void ioasid_get(ioasid_t ioasid)
 {
 }
 
+static inline bool ioasid_put(ioasid_t ioasid)
+{
+   return false;
+}
+
 static inline void *ioasid_find(struct ioasid_set *set, ioasid_t ioasid,
bool (*getter)(void *))
 {
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 87b17bac04c2..45d2f5191201 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -5158,7 +5158,7 @@ static void auxiliary_unlink_device(struct dmar_domain 
*domain,
domain->auxd_refcnt--;
 
if (!domain->auxd_refcnt && domain->default_pasid > 0)
-   ioasid_free(domain->default_pasid);
+   ioasid_put(domain->default_pasid);
 }
 
 static int aux_domain_add_dev(struct dmar_domain *domain,
@@ -5219,7 +5219,7 @@ static int aux_domain_add_dev(struct dmar_domain *domain,
spin_unlock(>lock);
spin_unlock_irqrestore(_domain_lock, flags);
if (!domain->auxd_refcnt && domain->default_pasid > 0)
-   ioasid_free(domain->default_pasid);
+   ioasid_put(domain->default_pasid);
 
return ret;
 }
diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
index 95c3164a2302..50897a2bd1da 100644
--- a/drivers/iommu/intel/svm.c
+++ b/drivers/iommu/intel/svm.c
@@ -565,7 +565,7 @@ intel_svm_bind_mm(struct device *dev, int flags, struct 
svm_dev_ops *ops,
if (mm) {
ret = mmu_notifier_register(>notifier, mm);
if (ret) {
-   ioasid_free(svm->pasid);
+   ioasid_put(svm->pasid);
kfree(svm);
kfree(sdev);
goto out;
@@ -583,7 +583,7 @@ intel_svm_bind_mm(struct device *dev, int flags, struct 
svm_dev_ops *ops,
if (ret) {
if (mm)
mmu_notifier_unregister(>notifier, mm);
-   ioasid_free(svm->pasid);
+   ioasid_put(svm->pasid);
kfree(svm);
kfree(sdev);
goto out;
@@ -652,7 +652,7 @@ static int intel_svm_unbind_mm(struct device *dev, int 
pasid)
kfree_rcu(sdev, rcu);
 
if (list_empty(>devs)) {
-   ioasid_free(svm->pasid);
+   ioasid_put(svm->pasid);
if (svm->mm)
mmu_notifier_unregister(>notifier, 
svm->mm);
list_del(>list);
diff --git a/drivers/iommu/ioasid.c b/drivers/iommu/ioasid.c
index 0f8dd377aada..50ee27bbd04e 100644
--- a/drivers/iommu/ioasid.c
+++ b/drivers/iommu/ioasid.c
@@ -2,7 +2,7 @@
 /*
  * I/O Address Space ID allocator. There is one global IOASID space, split into
  * subsets. Users create a subset with DECLARE_IOASID_SET, then allocate and
- * free IOASIDs with ioasid_alloc and ioasid_free.
+ * free IOASIDs with ioasid_alloc and ioasid_put.
  */
 #include 
 #include 
@@ -15,6 +15,7 @@ struct ioasid_data {
struct ioasid_set *set;
void *private;
struct rcu_head rcu;
+   refcount_t refs;
 };
 
 /*
@@ -314,6 +315,7 @@ ioasid_t ioasid_alloc(struct ioasid_set *set, ioasid_t min, 
ioasid_t max,
 
data->set = set;
data->private = private;
+   refcount_set(>refs, 1);
 
/*
 * Custom allocator needs 

[PATCH v10 04/13] arm64: mm: Pin down ASIDs for sharing mm with devices

2020-09-18 Thread Jean-Philippe Brucker
To enable address space sharing with the IOMMU, introduce
arm64_mm_context_get() and arm64_mm_context_put(), that pin down a
context and ensure that it will keep its ASID after a rollover. Export
the symbols to let the modular SMMUv3 driver use them.

Pinning is necessary because a device constantly needs a valid ASID,
unlike tasks that only require one when running. Without pinning, we would
need to notify the IOMMU when we're about to use a new ASID for a task,
and it would get complicated when a new task is assigned a shared ASID.
Consider the following scenario with no ASID pinned:

1. Task t1 is running on CPUx with shared ASID (gen=1, asid=1)
2. Task t2 is scheduled on CPUx, gets ASID (1, 2)
3. Task tn is scheduled on CPUy, a rollover occurs, tn gets ASID (2, 1)
   We would now have to immediately generate a new ASID for t1, notify
   the IOMMU, and finally enable task tn. We are holding the lock during
   all that time, since we can't afford having another CPU trigger a
   rollover. The IOMMU issues invalidation commands that can take tens of
   milliseconds.

It gets needlessly complicated. All we wanted to do was schedule task tn,
that has no business with the IOMMU. By letting the IOMMU pin tasks when
needed, we avoid stalling the slow path, and let the pinning fail when
we're out of shareable ASIDs.

After a rollover, the allocator expects at least one ASID to be available
in addition to the reserved ones (one per CPU). So (NR_ASIDS - NR_CPUS -
1) is the maximum number of ASIDs that can be shared with the IOMMU.

Signed-off-by: Jean-Philippe Brucker 
---
 arch/arm64/include/asm/mmu.h |   3 +
 arch/arm64/include/asm/mmu_context.h |  11 ++-
 arch/arm64/mm/context.c  | 105 +--
 3 files changed, 112 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index a7a5ecaa2e83..0fda85b2cc1b 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -17,11 +17,14 @@
 
 #ifndef __ASSEMBLY__
 
+#include 
+
 typedef struct {
atomic64_t  id;
 #ifdef CONFIG_COMPAT
void*sigpage;
 #endif
+   refcount_t  pinned;
void*vdso;
unsigned long   flags;
 } mm_context_t;
diff --git a/arch/arm64/include/asm/mmu_context.h 
b/arch/arm64/include/asm/mmu_context.h
index f2d7537d6f83..0672236e1aea 100644
--- a/arch/arm64/include/asm/mmu_context.h
+++ b/arch/arm64/include/asm/mmu_context.h
@@ -177,7 +177,13 @@ static inline void cpu_replace_ttbr1(pgd_t *pgdp)
 #define destroy_context(mm)do { } while(0)
 void check_and_switch_context(struct mm_struct *mm);
 
-#define init_new_context(tsk,mm)   ({ atomic64_set(&(mm)->context.id, 0); 
0; })
+static inline int
+init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+   atomic64_set(>context.id, 0);
+   refcount_set(>context.pinned, 0);
+   return 0;
+}
 
 #ifdef CONFIG_ARM64_SW_TTBR0_PAN
 static inline void update_saved_ttbr0(struct task_struct *tsk,
@@ -248,6 +254,9 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
 void verify_cpu_asid_bits(void);
 void post_ttbr_update_workaround(void);
 
+unsigned long arm64_mm_context_get(struct mm_struct *mm);
+void arm64_mm_context_put(struct mm_struct *mm);
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* !__ASM_MMU_CONTEXT_H */
diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c
index 9b11c096a042..001737a8f309 100644
--- a/arch/arm64/mm/context.c
+++ b/arch/arm64/mm/context.c
@@ -27,6 +27,10 @@ static DEFINE_PER_CPU(atomic64_t, active_asids);
 static DEFINE_PER_CPU(u64, reserved_asids);
 static cpumask_t tlb_flush_pending;
 
+static unsigned long max_pinned_asids;
+static unsigned long nr_pinned_asids;
+static unsigned long *pinned_asid_map;
+
 #define ASID_MASK  (~GENMASK(asid_bits - 1, 0))
 #define ASID_FIRST_VERSION (1UL << asid_bits)
 
@@ -72,7 +76,7 @@ void verify_cpu_asid_bits(void)
}
 }
 
-static void set_kpti_asid_bits(void)
+static void set_kpti_asid_bits(unsigned long *map)
 {
unsigned int len = BITS_TO_LONGS(NUM_USER_ASIDS) * sizeof(unsigned 
long);
/*
@@ -81,13 +85,15 @@ static void set_kpti_asid_bits(void)
 * is set, then the ASID will map only userspace. Thus
 * mark even as reserved for kernel.
 */
-   memset(asid_map, 0xaa, len);
+   memset(map, 0xaa, len);
 }
 
 static void set_reserved_asid_bits(void)
 {
-   if (arm64_kernel_unmapped_at_el0())
-   set_kpti_asid_bits();
+   if (pinned_asid_map)
+   bitmap_copy(asid_map, pinned_asid_map, NUM_USER_ASIDS);
+   else if (arm64_kernel_unmapped_at_el0())
+   set_kpti_asid_bits(asid_map);
else
bitmap_clear(asid_map, 0, NUM_USER_ASIDS);
 }
@@ -165,6 +171,14 @@ static u64 new_context(struct mm_struct *mm)
if (check_update_reserved_asid(asid, newasid))
return newasid;
 

[PATCH v10 01/13] mm: Define pasid in mm

2020-09-18 Thread Jean-Philippe Brucker
From: Fenghua Yu 

PASID is shared by all threads in a process. So the logical place to keep
track of it is in the "mm". Both ARM and X86 need to use the PASID in the
"mm".

Suggested-by: Christoph Hellwig 
Signed-off-by: Fenghua Yu 
Reviewed-by: Tony Luck 
---
https://lore.kernel.org/linux-iommu/1600187413-163670-8-git-send-email-fenghua...@intel.com/
---
 include/linux/mm_types.h | 4 
 1 file changed, 4 insertions(+)

diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 496c3ff97cce..1ff0615ef19f 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -542,6 +542,10 @@ struct mm_struct {
atomic_long_t hugetlb_usage;
 #endif
struct work_struct async_put_work;
+
+#ifdef CONFIG_IOMMU_SUPPORT
+   u32 pasid;
+#endif
} __randomize_layout;
 
/*
-- 
2.28.0

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


[PATCH v10 03/13] iommu/sva: Add PASID helpers

2020-09-18 Thread Jean-Philippe Brucker
Let IOMMU drivers allocate a single PASID per mm. Store the mm in the
IOASID set to allow refcounting and searching mm by PASID, when handling
an I/O page fault.

Reviewed-by: Lu Baolu 
Signed-off-by: Jean-Philippe Brucker 
---
v10: small comment updates
---
 drivers/iommu/Kconfig |  5 ++
 drivers/iommu/Makefile|  1 +
 drivers/iommu/iommu-sva-lib.h | 15 ++
 drivers/iommu/iommu-sva-lib.c | 86 +++
 4 files changed, 107 insertions(+)
 create mode 100644 drivers/iommu/iommu-sva-lib.h
 create mode 100644 drivers/iommu/iommu-sva-lib.c

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index bef5d75e306b..fb1787377eb6 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -103,6 +103,11 @@ config IOMMU_DMA
select IRQ_MSI_IOMMU
select NEED_SG_DMA_LENGTH
 
+# Shared Virtual Addressing library
+config IOMMU_SVA_LIB
+   bool
+   select IOASID
+
 config FSL_PAMU
bool "Freescale IOMMU support"
depends on PCI
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 11f1771104f3..61bd30cd8369 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -27,3 +27,4 @@ obj-$(CONFIG_FSL_PAMU) += fsl_pamu.o fsl_pamu_domain.o
 obj-$(CONFIG_S390_IOMMU) += s390-iommu.o
 obj-$(CONFIG_HYPERV_IOMMU) += hyperv-iommu.o
 obj-$(CONFIG_VIRTIO_IOMMU) += virtio-iommu.o
+obj-$(CONFIG_IOMMU_SVA_LIB) += iommu-sva-lib.o
diff --git a/drivers/iommu/iommu-sva-lib.h b/drivers/iommu/iommu-sva-lib.h
new file mode 100644
index ..b40990aef3fd
--- /dev/null
+++ b/drivers/iommu/iommu-sva-lib.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * SVA library for IOMMU drivers
+ */
+#ifndef _IOMMU_SVA_LIB_H
+#define _IOMMU_SVA_LIB_H
+
+#include 
+#include 
+
+int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t max);
+void iommu_sva_free_pasid(struct mm_struct *mm);
+struct mm_struct *iommu_sva_find(ioasid_t pasid);
+
+#endif /* _IOMMU_SVA_LIB_H */
diff --git a/drivers/iommu/iommu-sva-lib.c b/drivers/iommu/iommu-sva-lib.c
new file mode 100644
index ..bd41405d34e9
--- /dev/null
+++ b/drivers/iommu/iommu-sva-lib.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Helpers for IOMMU drivers implementing SVA
+ */
+#include 
+#include 
+
+#include "iommu-sva-lib.h"
+
+static DEFINE_MUTEX(iommu_sva_lock);
+static DECLARE_IOASID_SET(iommu_sva_pasid);
+
+/**
+ * iommu_sva_alloc_pasid - Allocate a PASID for the mm
+ * @mm: the mm
+ * @min: minimum PASID value (inclusive)
+ * @max: maximum PASID value (inclusive)
+ *
+ * Try to allocate a PASID for this mm, or take a reference to the existing one
+ * provided it fits within the [@min, @max] range. On success the PASID is
+ * available in mm->pasid, and must be released with iommu_sva_free_pasid().
+ * @min must be greater than 0, because 0 indicates an unused mm->pasid.
+ *
+ * Returns 0 on success and < 0 on error.
+ */
+int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t max)
+{
+   int ret = 0;
+   ioasid_t pasid;
+
+   if (min == INVALID_IOASID || max == INVALID_IOASID ||
+   min == 0 || max < min)
+   return -EINVAL;
+
+   mutex_lock(_sva_lock);
+   if (mm->pasid) {
+   if (mm->pasid >= min && mm->pasid <= max)
+   ioasid_get(mm->pasid);
+   else
+   ret = -EOVERFLOW;
+   } else {
+   pasid = ioasid_alloc(_sva_pasid, min, max, mm);
+   if (pasid == INVALID_IOASID)
+   ret = -ENOMEM;
+   else
+   mm->pasid = pasid;
+   }
+   mutex_unlock(_sva_lock);
+   return ret;
+}
+EXPORT_SYMBOL_GPL(iommu_sva_alloc_pasid);
+
+/**
+ * iommu_sva_free_pasid - Release the mm's PASID
+ * @mm: the mm
+ *
+ * Drop one reference to a PASID allocated with iommu_sva_alloc_pasid()
+ */
+void iommu_sva_free_pasid(struct mm_struct *mm)
+{
+   mutex_lock(_sva_lock);
+   if (ioasid_put(mm->pasid))
+   mm->pasid = 0;
+   mutex_unlock(_sva_lock);
+}
+EXPORT_SYMBOL_GPL(iommu_sva_free_pasid);
+
+/* ioasid_find getter() requires a void * argument */
+static bool __mmget_not_zero(void *mm)
+{
+   return mmget_not_zero(mm);
+}
+
+/**
+ * iommu_sva_find() - Find mm associated to the given PASID
+ * @pasid: Process Address Space ID assigned to the mm
+ *
+ * On success a reference to the mm is taken, and must be released with 
mmput().
+ *
+ * Returns the mm corresponding to this PASID, or an error if not found.
+ */
+struct mm_struct *iommu_sva_find(ioasid_t pasid)
+{
+   return ioasid_find(_sva_pasid, pasid, __mmget_not_zero);
+}
+EXPORT_SYMBOL_GPL(iommu_sva_find);
-- 
2.28.0

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


[PATCH v10 12/13] iommu/arm-smmu-v3: Implement iommu_sva_bind/unbind()

2020-09-18 Thread Jean-Philippe Brucker
The sva_bind() function allows devices to access process address spaces
using a PASID (aka SSID).

(1) bind() allocates or gets an existing MMU notifier tied to the
(domain, mm) pair. Each mm gets one PASID.

(2) Any change to the address space calls invalidate_range() which sends
ATC invalidations (in a subsequent patch).

(3) When the process address space dies, the release() notifier disables
the CD to allow reclaiming the page tables. Since release() has to
be light we do not instruct device drivers to stop DMA here, we just
ignore incoming page faults from this point onwards.

To avoid any event 0x0a print (C_BAD_CD) we disable translation
without clearing CD.V. PCIe Translation Requests and Page Requests
are silently denied. Don't clear the R bit because the S bit can't
be cleared when STALL_MODEL==0b10 (forced), and clearing R without
clearing S is useless. Faulting transactions will stall and will be
aborted by the IOPF handler.

(4) After stopping DMA, the device driver releases the bond by calling
unbind(). We release the MMU notifier, free the PASID and the bond.

Three structures keep track of bonds:
* arm_smmu_bond: one per {device, mm} pair, the handle returned to the
  device driver for a bind() request.
* arm_smmu_mmu_notifier: one per {domain, mm} pair, deals with ATS/TLB
  invalidations and clearing the context descriptor on mm exit.
* arm_smmu_ctx_desc: one per mm, holds the pinned ASID and pgd.

Signed-off-by: Jean-Philippe Brucker 
---
 drivers/iommu/Kconfig |   2 +
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |  28 +++
 .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c   | 230 +-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   |  32 ++-
 4 files changed, 282 insertions(+), 10 deletions(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index b1d592cd9984..a8eb8b7f35f7 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -316,6 +316,8 @@ config ARM_SMMU_V3
 config ARM_SMMU_V3_SVA
bool "Shared Virtual Addressing support for the ARM SMMUv3"
depends on ARM_SMMU_V3
+   select IOMMU_SVA_LIB
+   select MMU_NOTIFIER
help
  Support for sharing process address spaces with devices using the
  SMMUv3.
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index ba34914813ff..6365c81a4614 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -677,10 +677,18 @@ struct arm_smmu_domain {
 
struct list_headdevices;
spinlock_t  devices_lock;
+
+   struct list_headmmu_notifiers;
 };
 
+static inline struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
+{
+   return container_of(dom, struct arm_smmu_domain, domain);
+}
+
 extern struct xarray arm_smmu_asid_xa;
 extern struct mutex arm_smmu_asid_lock;
+extern struct arm_smmu_ctx_desc quiet_cd;
 
 int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
struct arm_smmu_ctx_desc *cd);
@@ -693,6 +701,11 @@ bool arm_smmu_master_sva_supported(struct arm_smmu_master 
*master);
 bool arm_smmu_master_sva_enabled(struct arm_smmu_master *master);
 int arm_smmu_master_enable_sva(struct arm_smmu_master *master);
 int arm_smmu_master_disable_sva(struct arm_smmu_master *master);
+struct iommu_sva *arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm,
+   void *drvdata);
+void arm_smmu_sva_unbind(struct iommu_sva *handle);
+int arm_smmu_sva_get_pasid(struct iommu_sva *handle);
+void arm_smmu_sva_notifier_synchronize(void);
 #else /* CONFIG_ARM_SMMU_V3_SVA */
 static inline bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
 {
@@ -718,5 +731,20 @@ static inline int arm_smmu_master_disable_sva(struct 
arm_smmu_master *master)
 {
return -ENODEV;
 }
+
+static inline struct iommu_sva *
+arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm, void *drvdata)
+{
+   return ERR_PTR(-ENODEV);
+}
+
+static inline void arm_smmu_sva_unbind(struct iommu_sva *handle) {}
+
+static inline int arm_smmu_sva_get_pasid(struct iommu_sva *handle)
+{
+   return IOMMU_PASID_INVALID;
+}
+
+static inline void arm_smmu_sva_notifier_synchronize(void) {}
 #endif /* CONFIG_ARM_SMMU_V3_SVA */
 #endif /* _ARM_SMMU_V3_H */
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
index 9255c9600fb8..f57c2bde68a4 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
@@ -5,11 +5,35 @@
 
 #include 
 #include 
+#include 
 #include 
 
 #include "arm-smmu-v3.h"
+#include "../../iommu-sva-lib.h"
 #include "../../io-pgtable-arm.h"
 
+struct arm_smmu_mmu_notifier {
+   struct mmu_notifier mn;
+   struct arm_smmu_ctx_desc

[PATCH v10 10/13] iommu/arm-smmu-v3: Check for SVA features

2020-09-18 Thread Jean-Philippe Brucker
Aggregate all sanity-checks for sharing CPU page tables with the SMMU
under a single ARM_SMMU_FEAT_SVA bit. For PCIe SVA, users also need to
check FEAT_ATS and FEAT_PRI. For platform SVA, they will have to check
FEAT_STALLS.

Introduce ARM_SMMU_FEAT_BTM (Broadcast TLB Maintenance), but don't
enable it at the moment. Since the entire VMID space is shared with the
CPU, enabling DVM (by clearing SMMU_CR2.PTM) could result in
over-invalidation and affect performance of stage-2 mappings.

Cc: Suzuki K Poulose 
Signed-off-by: Jean-Philippe Brucker 
---
v10:
* Check that 52-bit VA is supported on the SMMU side if vabits_actual
  requires it.
* Check arm64_kernel_unmapped_at_el0() instead of
  CONFIG_UNMAP_KERNEL_AT_EL0
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   | 10 +
 .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c   | 45 +++
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   |  3 ++
 3 files changed, 58 insertions(+)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 90c08f156b43..7b14b48a26c7 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -602,6 +602,8 @@ struct arm_smmu_device {
 #define ARM_SMMU_FEAT_STALL_FORCE  (1 << 13)
 #define ARM_SMMU_FEAT_VAX  (1 << 14)
 #define ARM_SMMU_FEAT_RANGE_INV(1 << 15)
+#define ARM_SMMU_FEAT_BTM  (1 << 16)
+#define ARM_SMMU_FEAT_SVA  (1 << 17)
u32 features;
 
 #define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0)
@@ -683,4 +685,12 @@ int arm_smmu_write_ctx_desc(struct arm_smmu_domain 
*smmu_domain, int ssid,
 void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid);
 bool arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd);
 
+#ifdef CONFIG_ARM_SMMU_V3_SVA
+bool arm_smmu_sva_supported(struct arm_smmu_device *smmu);
+#else /* CONFIG_ARM_SMMU_V3_SVA */
+static inline bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
+{
+   return false;
+}
+#endif /* CONFIG_ARM_SMMU_V3_SVA */
 #endif /* _ARM_SMMU_V3_H */
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
index ef3fcfa72187..cb94c0924196 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
@@ -152,3 +152,48 @@ static void arm_smmu_free_shared_cd(struct 
arm_smmu_ctx_desc *cd)
kfree(cd);
}
 }
+
+bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
+{
+   unsigned long reg, fld;
+   unsigned long oas;
+   unsigned long asid_bits;
+   u32 feat_mask = ARM_SMMU_FEAT_BTM | ARM_SMMU_FEAT_COHERENCY;
+
+   if (vabits_actual == 52)
+   feat_mask |= ARM_SMMU_FEAT_VAX;
+
+   if ((smmu->features & feat_mask) != feat_mask)
+   return false;
+
+   if (!(smmu->pgsize_bitmap & PAGE_SIZE))
+   return false;
+
+   /*
+* Get the smallest PA size of all CPUs (sanitized by cpufeature). We're
+* not even pretending to support AArch32 here. Abort if the MMU outputs
+* addresses larger than what we support.
+*/
+   reg = read_sanitised_ftr_reg(SYS_ID_AA64MMFR0_EL1);
+   fld = cpuid_feature_extract_unsigned_field(reg, 
ID_AA64MMFR0_PARANGE_SHIFT);
+   oas = id_aa64mmfr0_parange_to_phys_shift(fld);
+   if (smmu->oas < oas)
+   return false;
+
+   /* We can support bigger ASIDs than the CPU, but not smaller */
+   fld = cpuid_feature_extract_unsigned_field(reg, 
ID_AA64MMFR0_ASID_SHIFT);
+   asid_bits = fld ? 16 : 8;
+   if (smmu->asid_bits < asid_bits)
+   return false;
+
+   /*
+* See max_pinned_asids in arch/arm64/mm/context.c. The following is
+* generally the maximum number of bindable processes.
+*/
+   if (arm64_kernel_unmapped_at_el0())
+   asid_bits--;
+   dev_dbg(smmu->dev, "%d shared contexts\n", (1 << asid_bits) -
+   num_possible_cpus() - 2);
+
+   return true;
+}
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index e99ebdd4c841..44c57bcfe112 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -3257,6 +3257,9 @@ static int arm_smmu_device_hw_probe(struct 
arm_smmu_device *smmu)
 
smmu->ias = max(smmu->ias, smmu->oas);
 
+   if (arm_smmu_sva_supported(smmu))
+   smmu->features |= ARM_SMMU_FEAT_SVA;
+
dev_info(smmu->dev, "ias %lu-bit, oas %lu-bit (features 0x%08x)\n",
 smmu->ias, smmu->oas, smmu->features);
return 0;
-- 
2.28.0

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


[PATCH v10 05/13] iommu/io-pgtable-arm: Move some definitions to a header

2020-09-18 Thread Jean-Philippe Brucker
Extract some of the most generic TCR defines, so they can be reused by
the page table sharing code.

Acked-by: Will Deacon 
Signed-off-by: Jean-Philippe Brucker 
---
 drivers/iommu/io-pgtable-arm.h | 30 ++
 drivers/iommu/io-pgtable-arm.c | 27 ++-
 MAINTAINERS|  3 +--
 3 files changed, 33 insertions(+), 27 deletions(-)
 create mode 100644 drivers/iommu/io-pgtable-arm.h

diff --git a/drivers/iommu/io-pgtable-arm.h b/drivers/iommu/io-pgtable-arm.h
new file mode 100644
index ..ba7cfdf7afa0
--- /dev/null
+++ b/drivers/iommu/io-pgtable-arm.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef IO_PGTABLE_ARM_H_
+#define IO_PGTABLE_ARM_H_
+
+#define ARM_LPAE_TCR_TG0_4K0
+#define ARM_LPAE_TCR_TG0_64K   1
+#define ARM_LPAE_TCR_TG0_16K   2
+
+#define ARM_LPAE_TCR_TG1_16K   1
+#define ARM_LPAE_TCR_TG1_4K2
+#define ARM_LPAE_TCR_TG1_64K   3
+
+#define ARM_LPAE_TCR_SH_NS 0
+#define ARM_LPAE_TCR_SH_OS 2
+#define ARM_LPAE_TCR_SH_IS 3
+
+#define ARM_LPAE_TCR_RGN_NC0
+#define ARM_LPAE_TCR_RGN_WBWA  1
+#define ARM_LPAE_TCR_RGN_WT2
+#define ARM_LPAE_TCR_RGN_WB3
+
+#define ARM_LPAE_TCR_PS_32_BIT 0x0ULL
+#define ARM_LPAE_TCR_PS_36_BIT 0x1ULL
+#define ARM_LPAE_TCR_PS_40_BIT 0x2ULL
+#define ARM_LPAE_TCR_PS_42_BIT 0x3ULL
+#define ARM_LPAE_TCR_PS_44_BIT 0x4ULL
+#define ARM_LPAE_TCR_PS_48_BIT 0x5ULL
+#define ARM_LPAE_TCR_PS_52_BIT 0x6ULL
+
+#endif /* IO_PGTABLE_ARM_H_ */
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index dc7bcf858b6d..534810b6be77 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -20,6 +20,8 @@
 
 #include 
 
+#include "io-pgtable-arm.h"
+
 #define ARM_LPAE_MAX_ADDR_BITS 52
 #define ARM_LPAE_S2_MAX_CONCAT_PAGES   16
 #define ARM_LPAE_MAX_LEVELS4
@@ -100,23 +102,6 @@
 #define ARM_LPAE_PTE_MEMATTR_DEV   (((arm_lpae_iopte)0x1) << 2)
 
 /* Register bits */
-#define ARM_LPAE_TCR_TG0_4K0
-#define ARM_LPAE_TCR_TG0_64K   1
-#define ARM_LPAE_TCR_TG0_16K   2
-
-#define ARM_LPAE_TCR_TG1_16K   1
-#define ARM_LPAE_TCR_TG1_4K2
-#define ARM_LPAE_TCR_TG1_64K   3
-
-#define ARM_LPAE_TCR_SH_NS 0
-#define ARM_LPAE_TCR_SH_OS 2
-#define ARM_LPAE_TCR_SH_IS 3
-
-#define ARM_LPAE_TCR_RGN_NC0
-#define ARM_LPAE_TCR_RGN_WBWA  1
-#define ARM_LPAE_TCR_RGN_WT2
-#define ARM_LPAE_TCR_RGN_WB3
-
 #define ARM_LPAE_VTCR_SL0_MASK 0x3
 
 #define ARM_LPAE_TCR_T0SZ_SHIFT0
@@ -124,14 +109,6 @@
 #define ARM_LPAE_VTCR_PS_SHIFT 16
 #define ARM_LPAE_VTCR_PS_MASK  0x7
 
-#define ARM_LPAE_TCR_PS_32_BIT 0x0ULL
-#define ARM_LPAE_TCR_PS_36_BIT 0x1ULL
-#define ARM_LPAE_TCR_PS_40_BIT 0x2ULL
-#define ARM_LPAE_TCR_PS_42_BIT 0x3ULL
-#define ARM_LPAE_TCR_PS_44_BIT 0x4ULL
-#define ARM_LPAE_TCR_PS_48_BIT 0x5ULL
-#define ARM_LPAE_TCR_PS_52_BIT 0x6ULL
-
 #define ARM_LPAE_MAIR_ATTR_SHIFT(n)((n) << 3)
 #define ARM_LPAE_MAIR_ATTR_MASK0xff
 #define ARM_LPAE_MAIR_ATTR_DEVICE  0x04
diff --git a/MAINTAINERS b/MAINTAINERS
index 0d0862b19ce5..7b1bf8fda938 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1506,8 +1506,7 @@ L:linux-arm-ker...@lists.infradead.org (moderated 
for non-subscribers)
 S: Maintained
 F: Documentation/devicetree/bindings/iommu/arm,smmu*
 F: drivers/iommu/arm/
-F: drivers/iommu/io-pgtable-arm-v7s.c
-F: drivers/iommu/io-pgtable-arm.c
+F: drivers/iommu/io-pgtable-arm*
 
 ARM SUB-ARCHITECTURES
 L: linux-arm-ker...@lists.infradead.org (moderated for non-subscribers)
-- 
2.28.0

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


[PATCH v10 09/13] iommu/arm-smmu-v3: Seize private ASID

2020-09-18 Thread Jean-Philippe Brucker
The SMMU has a single ASID space, the union of shared and private ASID
sets. This means that the SMMU driver competes with the arch allocator
for ASIDs. Shared ASIDs are those of Linux processes, allocated by the
arch, and contribute in broadcast TLB maintenance. Private ASIDs are
allocated by the SMMU driver and used for "classic" map/unmap DMA. They
require command-queue TLB invalidations.

When we pin down an mm_context and get an ASID that is already in use by
the SMMU, it belongs to a private context. We used to simply abort the
bind, but this is unfair to users that would be unable to bind a few
seemingly random processes. Try to allocate a new private ASID for the
context, and make the old ASID shared.

Signed-off-by: Jean-Philippe Brucker 
---
v10: fix ASID limit, small comment update
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |  3 ++
 .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c   | 35 +--
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   | 34 +++---
 3 files changed, 57 insertions(+), 15 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 6b06a6f19604..90c08f156b43 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -678,6 +678,9 @@ struct arm_smmu_domain {
 extern struct xarray arm_smmu_asid_xa;
 extern struct mutex arm_smmu_asid_lock;
 
+int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
+   struct arm_smmu_ctx_desc *cd);
+void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid);
 bool arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd);
 
 #endif /* _ARM_SMMU_V3_H */
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
index 6c1113059632..ef3fcfa72187 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
@@ -10,10 +10,18 @@
 #include "arm-smmu-v3.h"
 #include "../../io-pgtable-arm.h"
 
+/*
+ * Check if the CPU ASID is available on the SMMU side. If a private context
+ * descriptor is using it, try to replace it.
+ */
 static struct arm_smmu_ctx_desc *
 arm_smmu_share_asid(struct mm_struct *mm, u16 asid)
 {
+   int ret;
+   u32 new_asid;
struct arm_smmu_ctx_desc *cd;
+   struct arm_smmu_device *smmu;
+   struct arm_smmu_domain *smmu_domain;
 
cd = xa_load(_smmu_asid_xa, asid);
if (!cd)
@@ -27,8 +35,31 @@ arm_smmu_share_asid(struct mm_struct *mm, u16 asid)
return cd;
}
 
-   /* Ouch, ASID is already in use for a private cd. */
-   return ERR_PTR(-EBUSY);
+   smmu_domain = container_of(cd, struct arm_smmu_domain, s1_cfg.cd);
+   smmu = smmu_domain->smmu;
+
+   ret = xa_alloc(_smmu_asid_xa, _asid, cd,
+  XA_LIMIT(1, (1 << smmu->asid_bits) - 1), GFP_KERNEL);
+   if (ret)
+   return ERR_PTR(-ENOSPC);
+   /*
+* Race with unmap: TLB invalidations will start targeting the new ASID,
+* which isn't assigned yet. We'll do an invalidate-all on the old ASID
+* later, so it doesn't matter.
+*/
+   cd->asid = new_asid;
+   /*
+* Update ASID and invalidate CD in all associated masters. There will
+* be some overlap between use of both ASIDs, until we invalidate the
+* TLB.
+*/
+   arm_smmu_write_ctx_desc(smmu_domain, 0, cd);
+
+   /* Invalidate TLB entries previously associated with that context */
+   arm_smmu_tlb_inv_asid(smmu, asid);
+
+   xa_erase(_smmu_asid_xa, asid);
+   return NULL;
 }
 
 __maybe_unused
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 19af27fd183b..e99ebdd4c841 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -872,6 +872,17 @@ static int arm_smmu_cmdq_batch_submit(struct 
arm_smmu_device *smmu,
 }
 
 /* Context descriptor manipulation functions */
+void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid)
+{
+   struct arm_smmu_cmdq_ent cmd = {
+   .opcode = CMDQ_OP_TLBI_NH_ASID,
+   .tlbi.asid = asid,
+   };
+
+   arm_smmu_cmdq_issue_cmd(smmu, );
+   arm_smmu_cmdq_issue_sync(smmu);
+}
+
 static void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain,
 int ssid, bool leaf)
 {
@@ -952,8 +963,8 @@ static __le64 *arm_smmu_get_cd_ptr(struct arm_smmu_domain 
*smmu_domain,
return l1_desc->l2ptr + idx * CTXDESC_CD_DWORDS;
 }
 
-static int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain,
-  int ssid, struct arm_smmu_ctx_desc *cd)
+int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
+   struct arm_smmu_ctx_desc *cd)
 {
/*
 * This function 

[PATCH v10 11/13] iommu/arm-smmu-v3: Add SVA device feature

2020-09-18 Thread Jean-Philippe Brucker
Implement the IOMMU device feature callbacks to support the SVA feature.
At the moment dev_has_feat() returns false since I/O Page Faults and BTM
aren't yet implemented.

Signed-off-by: Jean-Philippe Brucker 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   | 26 ++
 .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c   | 49 
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   | 79 +++
 3 files changed, 154 insertions(+)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 7b14b48a26c7..ba34914813ff 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -646,6 +646,8 @@ struct arm_smmu_master {
u32 *sids;
unsigned intnum_sids;
boolats_enabled;
+   boolsva_enabled;
+   struct list_headbonds;
unsigned intssid_bits;
 };
 
@@ -687,10 +689,34 @@ bool arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd);
 
 #ifdef CONFIG_ARM_SMMU_V3_SVA
 bool arm_smmu_sva_supported(struct arm_smmu_device *smmu);
+bool arm_smmu_master_sva_supported(struct arm_smmu_master *master);
+bool arm_smmu_master_sva_enabled(struct arm_smmu_master *master);
+int arm_smmu_master_enable_sva(struct arm_smmu_master *master);
+int arm_smmu_master_disable_sva(struct arm_smmu_master *master);
 #else /* CONFIG_ARM_SMMU_V3_SVA */
 static inline bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
 {
return false;
 }
+
+static inline bool arm_smmu_master_sva_supported(struct arm_smmu_master 
*master)
+{
+   return false;
+}
+
+static inline bool arm_smmu_master_sva_enabled(struct arm_smmu_master *master)
+{
+   return false;
+}
+
+static inline int arm_smmu_master_enable_sva(struct arm_smmu_master *master)
+{
+   return -ENODEV;
+}
+
+static inline int arm_smmu_master_disable_sva(struct arm_smmu_master *master)
+{
+   return -ENODEV;
+}
 #endif /* CONFIG_ARM_SMMU_V3_SVA */
 #endif /* _ARM_SMMU_V3_H */
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
index cb94c0924196..9255c9600fb8 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
@@ -10,6 +10,8 @@
 #include "arm-smmu-v3.h"
 #include "../../io-pgtable-arm.h"
 
+static DEFINE_MUTEX(sva_lock);
+
 /*
  * Check if the CPU ASID is available on the SMMU side. If a private context
  * descriptor is using it, try to replace it.
@@ -197,3 +199,50 @@ bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
 
return true;
 }
+
+static bool arm_smmu_iopf_supported(struct arm_smmu_master *master)
+{
+   return false;
+}
+
+bool arm_smmu_master_sva_supported(struct arm_smmu_master *master)
+{
+   if (!(master->smmu->features & ARM_SMMU_FEAT_SVA))
+   return false;
+
+   /* SSID and IOPF support are mandatory for the moment */
+   return master->ssid_bits && arm_smmu_iopf_supported(master);
+}
+
+bool arm_smmu_master_sva_enabled(struct arm_smmu_master *master)
+{
+   bool enabled;
+
+   mutex_lock(_lock);
+   enabled = master->sva_enabled;
+   mutex_unlock(_lock);
+   return enabled;
+}
+
+int arm_smmu_master_enable_sva(struct arm_smmu_master *master)
+{
+   mutex_lock(_lock);
+   master->sva_enabled = true;
+   mutex_unlock(_lock);
+
+   return 0;
+}
+
+int arm_smmu_master_disable_sva(struct arm_smmu_master *master)
+{
+   mutex_lock(_lock);
+   if (!list_empty(>bonds)) {
+   dev_err(master->dev, "cannot disable SVA, device is bound\n");
+   mutex_unlock(_lock);
+   return -EBUSY;
+   }
+   master->sva_enabled = false;
+   mutex_unlock(_lock);
+
+   return 0;
+}
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 44c57bcfe112..95f2e36a4f15 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2162,6 +2162,16 @@ static int arm_smmu_attach_dev(struct iommu_domain 
*domain, struct device *dev)
master = dev_iommu_priv_get(dev);
smmu = master->smmu;
 
+   /*
+* Checking that SVA is disabled ensures that this device isn't bound to
+* any mm, and can be safely detached from its old domain. Bonds cannot
+* be removed concurrently since we're holding the group mutex.
+*/
+   if (arm_smmu_master_sva_enabled(master)) {
+   dev_err(dev, "cannot attach - SVA enabled\n");
+   return -EBUSY;
+   }
+
arm_smmu_detach_dev(master);
 
mutex_lock(_domain->init_mutex);
@@ -2309,6 +2319,7 @@ static struct iommu_device *arm_smmu_probe_device(struct 
device *dev)
master->smmu = smmu;
master->sids = fwspec->ids;

[PATCH v10 06/13] arm64: cpufeature: Export symbol read_sanitised_ftr_reg()

2020-09-18 Thread Jean-Philippe Brucker
The SMMUv3 driver would like to read the MMFR0 PARANGE field in order to
share CPU page tables with devices. Allow the driver to be built as
module by exporting the read_sanitized_ftr_reg() cpufeature symbol.

Acked-by: Suzuki K Poulose 
Signed-off-by: Jean-Philippe Brucker 
---
 arch/arm64/kernel/cpufeature.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 6424584be01e..07f10ad8855c 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -,6 +,7 @@ u64 read_sanitised_ftr_reg(u32 id)
return 0;
return regp->sys_val;
 }
+EXPORT_SYMBOL_GPL(read_sanitised_ftr_reg);
 
 #define read_sysreg_case(r)\
case r: return read_sysreg_s(r)
-- 
2.28.0

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


[PATCH v10 07/13] iommu/arm-smmu-v3: Move definitions to a header

2020-09-18 Thread Jean-Philippe Brucker
Allow sharing structure definitions with the upcoming SVA support for
Arm SMMUv3, by moving them to a separate header. We could surgically
extract only what is needed but keeping all definitions in one place
looks nicer.

Reviewed-by: Eric Auger 
Signed-off-by: Jean-Philippe Brucker 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 675 
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 660 +--
 2 files changed, 676 insertions(+), 659 deletions(-)
 create mode 100644 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
new file mode 100644
index ..51a9ce07b2d6
--- /dev/null
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -0,0 +1,675 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * IOMMU API for ARM architected SMMUv3 implementations.
+ *
+ * Copyright (C) 2015 ARM Limited
+ */
+
+#ifndef _ARM_SMMU_V3_H
+#define _ARM_SMMU_V3_H
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* MMIO registers */
+#define ARM_SMMU_IDR0  0x0
+#define IDR0_ST_LVLGENMASK(28, 27)
+#define IDR0_ST_LVL_2LVL   1
+#define IDR0_STALL_MODEL   GENMASK(25, 24)
+#define IDR0_STALL_MODEL_STALL 0
+#define IDR0_STALL_MODEL_FORCE 2
+#define IDR0_TTENDIAN  GENMASK(22, 21)
+#define IDR0_TTENDIAN_MIXED0
+#define IDR0_TTENDIAN_LE   2
+#define IDR0_TTENDIAN_BE   3
+#define IDR0_CD2L  (1 << 19)
+#define IDR0_VMID16(1 << 18)
+#define IDR0_PRI   (1 << 16)
+#define IDR0_SEV   (1 << 14)
+#define IDR0_MSI   (1 << 13)
+#define IDR0_ASID16(1 << 12)
+#define IDR0_ATS   (1 << 10)
+#define IDR0_HYP   (1 << 9)
+#define IDR0_COHACC(1 << 4)
+#define IDR0_TTF   GENMASK(3, 2)
+#define IDR0_TTF_AARCH64   2
+#define IDR0_TTF_AARCH32_643
+#define IDR0_S1P   (1 << 1)
+#define IDR0_S2P   (1 << 0)
+
+#define ARM_SMMU_IDR1  0x4
+#define IDR1_TABLES_PRESET (1 << 30)
+#define IDR1_QUEUES_PRESET (1 << 29)
+#define IDR1_REL   (1 << 28)
+#define IDR1_CMDQS GENMASK(25, 21)
+#define IDR1_EVTQS GENMASK(20, 16)
+#define IDR1_PRIQS GENMASK(15, 11)
+#define IDR1_SSIDSIZE  GENMASK(10, 6)
+#define IDR1_SIDSIZE   GENMASK(5, 0)
+
+#define ARM_SMMU_IDR3  0xc
+#define IDR3_RIL   (1 << 10)
+
+#define ARM_SMMU_IDR5  0x14
+#define IDR5_STALL_MAX GENMASK(31, 16)
+#define IDR5_GRAN64K   (1 << 6)
+#define IDR5_GRAN16K   (1 << 5)
+#define IDR5_GRAN4K(1 << 4)
+#define IDR5_OAS   GENMASK(2, 0)
+#define IDR5_OAS_32_BIT0
+#define IDR5_OAS_36_BIT1
+#define IDR5_OAS_40_BIT2
+#define IDR5_OAS_42_BIT3
+#define IDR5_OAS_44_BIT4
+#define IDR5_OAS_48_BIT5
+#define IDR5_OAS_52_BIT6
+#define IDR5_VAX   GENMASK(11, 10)
+#define IDR5_VAX_52_BIT1
+
+#define ARM_SMMU_CR0   0x20
+#define CR0_ATSCHK (1 << 4)
+#define CR0_CMDQEN (1 << 3)
+#define CR0_EVTQEN (1 << 2)
+#define CR0_PRIQEN (1 << 1)
+#define CR0_SMMUEN (1 << 0)
+
+#define ARM_SMMU_CR0ACK0x24
+
+#define ARM_SMMU_CR1   0x28
+#define CR1_TABLE_SH   GENMASK(11, 10)
+#define CR1_TABLE_OC   GENMASK(9, 8)
+#define CR1_TABLE_IC   GENMASK(7, 6)
+#define CR1_QUEUE_SH   GENMASK(5, 4)
+#define CR1_QUEUE_OC   GENMASK(3, 2)
+#define CR1_QUEUE_IC   GENMASK(1, 0)
+/* CR1 cacheability fields don't quite follow the usual TCR-style encoding */
+#define CR1_CACHE_NC   0
+#define CR1_CACHE_WB   1
+#define CR1_CACHE_WT   2
+
+#define ARM_SMMU_CR2   0x2c
+#define CR2_PTM(1 << 2)
+#define CR2_RECINVSID  (1 << 1)
+#define CR2_E2H(1 << 0)
+
+#define ARM_SMMU_GBPA  0x44
+#define GBPA_UPDATE(1 << 31)
+#define GBPA_ABORT (1 << 20)
+
+#define ARM_SMMU_IRQ_CTRL  0x50
+#define IRQ_CTRL_EVTQ_IRQEN(1 << 2)
+#define IRQ_CTRL_PRIQ_IRQEN(1 << 1)
+#define 

[PATCH v10 08/13] iommu/arm-smmu-v3: Share process page tables

2020-09-18 Thread Jean-Philippe Brucker
With Shared Virtual Addressing (SVA), we need to mirror CPU TTBR, TCR,
MAIR and ASIDs in SMMU contexts. Each SMMU has a single ASID space split
into two sets, shared and private. Shared ASIDs correspond to those
obtained from the arch ASID allocator, and private ASIDs are used for
"classic" map/unmap DMA.

A possible conflict happens when trying to use a shared ASID that has
already been allocated for private use by the SMMU driver. This will be
addressed in a later patch by replacing the private ASID. At the
moment we return -EBUSY.

Each mm_struct shared with the SMMU will have a single context
descriptor. Add a refcount to keep track of this. It will be protected
by the global SVA lock.

Introduce a new arm-smmu-v3-sva.c file and the CONFIG_ARM_SMMU_V3_SVA
option to let users opt in SVA support.

Signed-off-by: Jean-Philippe Brucker 
---
v10: use vabits_actual instead of VA_BITS
---
 drivers/iommu/Kconfig |  10 ++
 drivers/iommu/arm/arm-smmu-v3/Makefile|   5 +-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |   8 ++
 .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c   | 123 ++
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   |  34 -
 5 files changed, 172 insertions(+), 8 deletions(-)
 create mode 100644 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index fb1787377eb6..b1d592cd9984 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -313,6 +313,16 @@ config ARM_SMMU_V3
  Say Y here if your system includes an IOMMU device implementing
  the ARM SMMUv3 architecture.
 
+config ARM_SMMU_V3_SVA
+   bool "Shared Virtual Addressing support for the ARM SMMUv3"
+   depends on ARM_SMMU_V3
+   help
+ Support for sharing process address spaces with devices using the
+ SMMUv3.
+
+ Say Y here if your system supports SVA extensions such as PCIe PASID
+ and PRI.
+
 config S390_IOMMU
def_bool y if S390 && PCI
depends on S390 && PCI
diff --git a/drivers/iommu/arm/arm-smmu-v3/Makefile 
b/drivers/iommu/arm/arm-smmu-v3/Makefile
index 569e24e9f162..54feb1ecccad 100644
--- a/drivers/iommu/arm/arm-smmu-v3/Makefile
+++ b/drivers/iommu/arm/arm-smmu-v3/Makefile
@@ -1,2 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o
+obj-$(CONFIG_ARM_SMMU_V3) += arm_smmu_v3.o
+arm_smmu_v3-objs-y += arm-smmu-v3.o
+arm_smmu_v3-objs-$(CONFIG_ARM_SMMU_V3_SVA) += arm-smmu-v3-sva.o
+arm_smmu_v3-objs := $(arm_smmu_v3-objs-y)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 51a9ce07b2d6..6b06a6f19604 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -540,6 +540,9 @@ struct arm_smmu_ctx_desc {
u64 ttbr;
u64 tcr;
u64 mair;
+
+   refcount_t  refs;
+   struct mm_struct*mm;
 };
 
 struct arm_smmu_l1_ctx_desc {
@@ -672,4 +675,9 @@ struct arm_smmu_domain {
spinlock_t  devices_lock;
 };
 
+extern struct xarray arm_smmu_asid_xa;
+extern struct mutex arm_smmu_asid_lock;
+
+bool arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd);
+
 #endif /* _ARM_SMMU_V3_H */
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
new file mode 100644
index ..6c1113059632
--- /dev/null
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Implementation of the IOMMU SVA API for the ARM SMMUv3
+ */
+
+#include 
+#include 
+#include 
+
+#include "arm-smmu-v3.h"
+#include "../../io-pgtable-arm.h"
+
+static struct arm_smmu_ctx_desc *
+arm_smmu_share_asid(struct mm_struct *mm, u16 asid)
+{
+   struct arm_smmu_ctx_desc *cd;
+
+   cd = xa_load(_smmu_asid_xa, asid);
+   if (!cd)
+   return NULL;
+
+   if (cd->mm) {
+   if (WARN_ON(cd->mm != mm))
+   return ERR_PTR(-EINVAL);
+   /* All devices bound to this mm use the same cd struct. */
+   refcount_inc(>refs);
+   return cd;
+   }
+
+   /* Ouch, ASID is already in use for a private cd. */
+   return ERR_PTR(-EBUSY);
+}
+
+__maybe_unused
+static struct arm_smmu_ctx_desc *arm_smmu_alloc_shared_cd(struct mm_struct *mm)
+{
+   u16 asid;
+   int err = 0;
+   u64 tcr, par, reg;
+   struct arm_smmu_ctx_desc *cd;
+   struct arm_smmu_ctx_desc *ret = NULL;
+
+   asid = arm64_mm_context_get(mm);
+   if (!asid)
+   return ERR_PTR(-ESRCH);
+
+   cd = kzalloc(sizeof(*cd), GFP_KERNEL);
+   if (!cd) {
+   err = -ENOMEM;
+   goto out_put_context;
+   }
+
+   refcount_set(>refs, 1);
+
+   

[PATCH v10 00/13] iommu: Shared Virtual Addressing for SMMUv3 (PT sharing part)

2020-09-18 Thread Jean-Philippe Brucker
This is version 10 of the page table sharing support for Arm SMMUv3.
Patch 1 still needs an Ack from mm maintainers. However patches 4-11 do
not depend on it, and could get merged for v5.10 regardless.

v10:
* Fix patches 3, 8, 9 and 10 following Eric's review.

v9 resend: 
https://lore.kernel.org/linux-iommu/20200817171558.325917-1-jean-phili...@linaro.org/
* Rebased onto v5.9-rc1. Moved to drivers/iommu/arm/arm-smmu-v3/ as a
  result.

v9: 
https://lore.kernel.org/linux-iommu/20200723145724.3014766-1-jean-phili...@linaro.org/
* Moved most of the SVA code to arm-smmu-v3-sva.c. This required moving
  struct definitions and macros to arm-smmu-v3.h (patch 7), hence the
  new 700 insertions/deletions in the diffstat.
* Updated patches 4 and 8 following review.
* Fixed a bug when replacing a private ASID.

v8: 
https://lore.kernel.org/linux-iommu/20200618155125.1548969-1-jean-phili...@linaro.org/
* Split SVA series into three parts: page table sharing, I/O page
  faults, and additional features (DVM, VHE and HTTU).

Fenghua Yu (1):
  mm: Define pasid in mm

Jean-Philippe Brucker (12):
  iommu/ioasid: Add ioasid references
  iommu/sva: Add PASID helpers
  arm64: mm: Pin down ASIDs for sharing mm with devices
  iommu/io-pgtable-arm: Move some definitions to a header
  arm64: cpufeature: Export symbol read_sanitised_ftr_reg()
  iommu/arm-smmu-v3: Move definitions to a header
  iommu/arm-smmu-v3: Share process page tables
  iommu/arm-smmu-v3: Seize private ASID
  iommu/arm-smmu-v3: Check for SVA features
  iommu/arm-smmu-v3: Add SVA device feature
  iommu/arm-smmu-v3: Implement iommu_sva_bind/unbind()
  iommu/arm-smmu-v3: Hook up ATC invalidation to mm ops

 drivers/iommu/Kconfig |  17 +
 drivers/iommu/Makefile|   1 +
 drivers/iommu/arm/arm-smmu-v3/Makefile|   5 +-
 arch/arm64/include/asm/mmu.h  |   3 +
 arch/arm64/include/asm/mmu_context.h  |  11 +-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   | 752 +++
 drivers/iommu/io-pgtable-arm.h|  30 +
 drivers/iommu/iommu-sva-lib.h |  15 +
 include/linux/ioasid.h|  10 +-
 include/linux/mm_types.h  |   4 +
 arch/arm64/kernel/cpufeature.c|   1 +
 arch/arm64/mm/context.c   | 105 ++-
 .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c   | 488 ++
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   | 860 --
 drivers/iommu/intel/iommu.c   |   4 +-
 drivers/iommu/intel/svm.c |   6 +-
 drivers/iommu/io-pgtable-arm.c|  27 +-
 drivers/iommu/ioasid.c|  38 +-
 drivers/iommu/iommu-sva-lib.c |  86 ++
 MAINTAINERS   |   3 +-
 20 files changed, 1731 insertions(+), 735 deletions(-)
 create mode 100644 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
 create mode 100644 drivers/iommu/io-pgtable-arm.h
 create mode 100644 drivers/iommu/iommu-sva-lib.h
 create mode 100644 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
 create mode 100644 drivers/iommu/iommu-sva-lib.c

-- 
2.28.0

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


Re: [PATCH v9 0/7] IOMMU user API enhancement

2020-09-18 Thread Joerg Roedel
Hi Jacob,

On Fri, Sep 11, 2020 at 02:57:49PM -0700, Jacob Pan wrote:
> IOMMU user API header was introduced to support nested DMA translation and
> related fault handling. The current UAPI data structures consist of three
> areas that cover the interactions between host kernel and guest:
>  - fault handling
>  - cache invalidation
>  - bind guest page tables, i.e. guest PASID
> 
> Future extensions are likely to support more architectures and vIOMMU 
> features.
> 
> In the previous discussion, using user-filled data size and feature flags is
> made a preferred approach over a unified version number.
> https://lkml.org/lkml/2020/1/29/45
> 
> In addition to introduce argsz field to data structures, this patchset is also
> trying to document the UAPI design, usage, and extension rules. VT-d driver
> changes to utilize the new argsz field is included, VFIO usage is to follow.
> 
> This set is available at:
> https://github.com/jacobpan/linux.git vsva_v5.9_uapi_v9

This changes user visible structs in incompatible ways, are you sure
those are not used yet anywhere?

Please address Randy's comments on patch 1 and my comment about the
build-time checking and repost with linux-...@vger.kernel.org on Cc.

Regards,

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


Re: [PATCH v9 3/7] iommu/uapi: Introduce enum type for PASID data format

2020-09-18 Thread Joerg Roedel
On Fri, Sep 11, 2020 at 02:57:52PM -0700, Jacob Pan wrote:
> There can be multiple vendor-specific PASID data formats used in UAPI
> structures. This patch adds enum type with a last entry which makes
> range checking much easier.

But it also makes it much easier to screw up the numbers (which are ABI)
by inserting a new value into the middle. I prefer defines here, or
alternativly BUILD_BUG_ON() checks for the numbers.

Regards,

Joerg

> 
> Suggested-by: Alex Williamson 
> Reviewed-by: Eric Auger 
> Signed-off-by: Jacob Pan 
> ---
>  include/uapi/linux/iommu.h | 8 ++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/include/uapi/linux/iommu.h b/include/uapi/linux/iommu.h
> index b42acc8fe007..7cc6ee6c41f7 100644
> --- a/include/uapi/linux/iommu.h
> +++ b/include/uapi/linux/iommu.h
> @@ -298,11 +298,16 @@ struct iommu_gpasid_bind_data_vtd {
>IOMMU_SVA_VTD_GPASID_PCD |  \
>IOMMU_SVA_VTD_GPASID_PWT)
>  
> +enum iommu_pasid_data_format {
> + IOMMU_PASID_FORMAT_INTEL_VTD = 1,
> + IOMMU_PASID_FORMAT_LAST,
> +};
> +
>  /**
>   * struct iommu_gpasid_bind_data - Information about device and guest PASID 
> binding
>   * @argsz:   User filled size of this data
>   * @version: Version of this data structure
> - * @format:  PASID table entry format
> + * @format:  PASID table entry format of enum iommu_pasid_data_format type
>   * @flags:   Additional information on guest bind request
>   * @gpgd:Guest page directory base of the guest mm to bind
>   * @hpasid:  Process address space ID used for the guest mm in host IOMMU
> @@ -321,7 +326,6 @@ struct iommu_gpasid_bind_data {
>   __u32 argsz;
>  #define IOMMU_GPASID_BIND_VERSION_1  1
>   __u32 version;
> -#define IOMMU_PASID_FORMAT_INTEL_VTD 1
>   __u32 format;
>   __u32 addr_width;
>  #define IOMMU_SVA_GPASID_VAL (1 << 0) /* guest PASID valid */
> -- 
> 2.7.4
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 2/3] iommu: amd: Add support for RMP_PAGE_FAULT and RMP_HW_ERR

2020-09-18 Thread Joerg Roedel
Hi Suravee,

On Wed, Sep 16, 2020 at 01:55:48PM +, Suravee Suthikulpanit wrote:
> +static void amd_iommu_report_rmp_hw_error(volatile u32 *event)
> +{
> + struct pci_dev *pdev;
> + struct iommu_dev_data *dev_data = NULL;
> + int devid = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK;
> + int vmg_tag   = (event[1]) & 0x;
> + int flags = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK;
> + u64 spa   = ((u64)event[3] << 32) | (event[2] & 0xFFF8);

Please write this as:

struct iommu_dev_data *dev_data = NULL;
int devid, vmg_tag, flags;
struct pci_dev *pdev;
u64 spa;

devid   = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK;
vmg_tag = (event[1]) & 0x;
flags   = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK;
spa = ((u64)event[3] << 32) | (event[2] & 0xFFF8);

Same applied the the next function.

> +
> + pdev = pci_get_domain_bus_and_slot(0, PCI_BUS_NUM(devid),
> +devid & 0xff);
> + if (pdev)
> + dev_data = dev_iommu_priv_get(>dev);
> +
> + if (dev_data && __ratelimit(_data->rs)) {
> + pci_err(pdev, "Event logged [RMP_HW_ERROR devid=0x%04x, 
> vmg_tag=0x%04x, spa=0x%llx, flags=0x%04x]\n",
> + devid, vmg_tag, spa, flags);

Printing the devid is not really needed here, no? Same issue in the next
function.

Regards,

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


Re: [PATCH v2] iommu/amd: Restore IRTE.RemapEn bit for amd_iommu_activate_guest_mode

2020-09-18 Thread Joerg Roedel
On Wed, Sep 16, 2020 at 11:17:20AM +, Suravee Suthikulpanit wrote:
> Commit e52d58d54a32 ("iommu/amd: Use cmpxchg_double() when updating
> 128-bit IRTE") removed an assumption that modify_irte_ga always set
> the valid bit, which requires the callers to set the appropriate value
> for the struct irte_ga.valid bit before calling the function.
> 
> Similar to the commit 26e495f34107 ("iommu/amd: Restore IRTE.RemapEn
> bit after programming IRTE"), which is for the function
> amd_iommu_deactivate_guest_mode().
> 
> The same change is also needed for the amd_iommu_activate_guest_mode().
> Otherwise, this could trigger IO_PAGE_FAULT for the VFIO based VMs with
> AVIC enabled.
> 
> Reported-by: Maxim Levitsky 
> Tested-by: Maxim Levitsky 
> Cc: Joao Martins 
> Fixes: e52d58d54a321 ("iommu/amd: Use cmpxchg_double() when updating 128-bit 
> IRTE")
> Signed-off-by: Suravee Suthikulpanit 
> ---
>  drivers/iommu/amd/iommu.c | 4 
>  1 file changed, 4 insertions(+)

Applied for v5.9, thanks.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH RFC v1 04/18] iommu/hyperv: don't setup IRQ remapping when running as root

2020-09-18 Thread Joerg Roedel
On Mon, Sep 14, 2020 at 11:27:48AM +, Wei Liu wrote:
> The IOMMU code needs more work. We're sure for now the IRQ remapping
> hooks are not applicable when Linux is the root.
> 
> Signed-off-by: Wei Liu 
> ---
>  drivers/iommu/hyperv-iommu.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)

Acked-by: Joerg Roedel 

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


Re: [RESEND][PATCH 0/2] iommu/tegra-smmu: Fix TLB line for Tegra210

2020-09-18 Thread Joerg Roedel
On Thu, Sep 17, 2020 at 04:31:53AM -0700, Nicolin Chen wrote:
> These two patches fix ACTIVE_TLB_LINES field setting in tegra-smmu
> driver for Tegra210 platforms.
> 
> This resend in series groups two previous seperate changes that're
> corelated, being pointed out by Thierry. Also adding his Acked-by.
> 
> Nicolin Chen (2):
>   iommu/tegra-smmu: Fix tlb_mask
>   memory: tegra: Correct num_tlb_lines for tegra210
> 
>  drivers/iommu/tegra-smmu.c  | 2 +-
>  drivers/memory/tegra/tegra210.c | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)

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


Re: [PATCH] iommu: fsl_pamu: Replace use of kzfree with kfree_sensitive

2020-09-18 Thread Joerg Roedel
On Fri, Sep 11, 2020 at 02:53:25PM +0100, Alex Dewar wrote:
> kzfree() is effectively deprecated as of commit 453431a54934 ("mm,
> treewide: rename kzfree() to kfree_sensitive()") and is now simply an
> alias for kfree_sensitive(). So just replace it with kfree_sensitive().
> 
> Signed-off-by: Alex Dewar 
> ---
>  drivers/iommu/fsl_pamu.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied, thanks.

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


Re: [PATCH] Handle init_iova_flush_queue failure in dma-iommu path

2020-09-18 Thread Joerg Roedel
On Thu, Sep 10, 2020 at 01:25:38PM +0100, Tom Murphy wrote:
> init_iova_flush_queue can fail if we run out of memory. Fall back to noflush
>  queue if it fails.
> 
> Signed-off-by: Tom Murphy 
> ---
>  drivers/iommu/dma-iommu.c | 7 +--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index 4959f5df21bd..5f69126f3e91 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -343,8 +343,11 @@ static int iommu_dma_init_domain(struct iommu_domain 
> *domain, dma_addr_t base,
>  
>   if (!cookie->fq_domain && !iommu_domain_get_attr(domain,
>   DOMAIN_ATTR_DMA_USE_FLUSH_QUEUE, ) && attr) {
> - cookie->fq_domain = domain;
> - init_iova_flush_queue(iovad, iommu_dma_flush_iotlb_all, NULL);
> + if (init_iova_flush_queue(iovad, iommu_dma_flush_iotlb_all,
> + NULL))
> + pr_warn("iova flush queue initialization failed\n");
> + else
> + cookie->fq_domain = domain;
>   }
>  
>   if (!dev)

Looks good to me, but Robin should also have a look.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH] iommu/amd: Add prefetch iommu pages command build function

2020-09-18 Thread Joerg Roedel
On Sat, Sep 05, 2020 at 03:14:20PM +0800, Wesley Sheng wrote:
> +static void build_pf_iommu_pages(struct iommu_cmd *cmd, u64 address,
> + u16 devid, int pfcnt, bool size,
> + bool inv)
> +{
> + memset(cmd, 0, sizeof(*cmd));
> +
> + address &= PAGE_MASK;
> +
> + cmd->data[0]  = devid;
> + cmd->data[0] |= (pfcnt & 0xff) << 24;
> + cmd->data[2]  = lower_32_bits(address);
> + cmd->data[3]  = upper_32_bits(address;
> + if (size)
> + cmd->data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK;
> + if (inv)
> + cmd->data[2] |= CMD_PF_IOMMU_PAGES_INV_MASK;
> + CMD_SET_TYPE(cmd, CMD_PF_IOMMU_PAGES);
> +}

This also needs to add a user of this function.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH] iommu: Kconfig: Update help description for IPMMU_VMSA config

2020-09-18 Thread Joerg Roedel
On Fri, Sep 11, 2020 at 11:19:12AM +0100, Lad Prabhakar wrote:
> ipmmu-vmsa driver is also used on Renesas RZ/G{1,2} Soc's, update the
> same to reflect the help description for IPMMU_VMSA config.
> 
> Signed-off-by: Lad Prabhakar 
> Reviewed-by: Chris Paterson 
> ---
>  drivers/iommu/Kconfig | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied, thanks.

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


Re: [PATCH] iommu/amd: Fix potential @entry null deref

2020-09-18 Thread Joerg Roedel
On Thu, Sep 10, 2020 at 06:16:21PM +0100, Joao Martins wrote:
> After commit 26e495f34107 ("iommu/amd: Restore IRTE.RemapEn bit after
> programming IRTE"), smatch warns:
> 
>   drivers/iommu/amd/iommu.c:3870 amd_iommu_deactivate_guest_mode()
> warn: variable dereferenced before check 'entry' (see line 3867)
> 
> Fix this by moving the @valid assignment to after @entry has been checked
> for NULL.
> 
> Cc: Suravee Suthikulpanit 
> Fixes: 26e495f34107 ("iommu/amd: Restore IRTE.RemapEn bit after programming 
> IRTE")
> Reported-by: Dan Carpenter 
> Signed-off-by: Joao Martins 
> ---
>  drivers/iommu/amd/iommu.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)

Applied for v5.9, thanks.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v4 1/3] dt-bindings: iommu: Add binding for MediaTek MT8167 IOMMU

2020-09-18 Thread Joerg Roedel
On Mon, Sep 07, 2020 at 12:16:47PM +0200, Fabien Parent wrote:
> This commit adds IOMMU binding documentation and larb port definitions
> for the MT8167 SoC.
> 
> Signed-off-by: Fabien Parent 
> Acked-by: Rob Herring 
> ---
> 
> V4:
>   * Added path to mt8167 larb header file
>   * Added Honghui Zhang in copyright header
> V3: Added mt8167-larb-port.h file for iommu port definitions
> V2: no change

Applied all, thanks.

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


Re: [PATCH v2 1/2] iommu/iova: Retry from last rb tree node if iova search fails

2020-09-18 Thread Joerg Roedel
On Mon, Sep 14, 2020 at 10:20:55AM +0530, Vijayanand Jitta wrote:
> ping ?

Robin needs to have a look first.

Regards,

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


dma_alloc_coherent not allocating memory from CMA Reserved.

2020-09-18 Thread ANKIT SONI



Hi All,
 
I am trying to allocate coherent memory for 33 MB in kerenl driver. and for that i have reserved CMA of 200 MB, but from dmesg, i can see that address reserved for cma is different and what i get with dma_alloc_coherent is different. My pc is x86 machine and tried in different motherboard, but this issue is occuring in some specific PCs. please help me in debugging the actual issue, below are kernel logs..at init i boot...
[ 0.014362] No NUMA configuration found[ 0.014363] Faking a node at [mem 0x-0x00021edf][ 0.014374] NODE_DATA(0) allocated [mem 0x21edd5000-0x21edf][ 0.014538] cma: Reserved 400 MiB at 0x000205c0[ 0.014541] Reserving 640MB of memory at 2512MB for crashkernel (System RAM: 8046MB)[ 0.014553] Zone ranges:[ 0.014554] DMA [mem 0x1000-0x00ff][ 0.014554] DMA32 [mem 0x0100-0x][ 0.014555] Normal [mem 0x0001-0x00021edf]
at dma_alloc_coherent call[ 27.816062] dev->dma_33M_addr is f800---and below are the logs in working case, at driver dma_alloc_coherent api call we have address which is in range of what reserved for cma.at boot i get..Faking a node at [mem 0x-0x00019fdf]NODE_DATA(0) allocated [mem 0x19fdd3000-0x19fdfdfff]cma: Reserved 800 MiB at 0x00016dc0Reserving 640MB of memory at 1792MB for crashkernel (System RAM: 6016MB)Zone ranges:DMA [mem 0x1000-0x00ff]DMA32 [mem 0x0100-0x]Normal [mem 0x0001-0x00019fdf]at dma_alloc_coherent calldev->dma_33M_addr is 16e20
 
Please help me in solving this iissue, or can suggest any alternative way to allocate big coherent memory.
 
Thanks and Regards,
Ankit Soni
 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu