On 3/29/19 10:10 AM, Joerg Roedel wrote:
> From: Joerg Roedel <[email protected]>
> 
> If a device has an exclusion range specified in the IVRS
> table, this region needs to be reserved in the iova-domain
> of that device. This hasn't happened until now and can cause
> data corruption on data transfered with these devices.
> 
> Treat exclusion ranges as reserved regions in the iommu-core
> to fix the problem.

Reviewed-by: Gary R Hook <[email protected]>

> 
> Fixes: be2a022c0dd0 ('x86, AMD IOMMU: add functions to parse IOMMU memory 
> mapping requirements for devices')
> Signed-off-by: Joerg Roedel <[email protected]>
> ---
>   drivers/iommu/amd_iommu.c       | 9 ++++++---
>   drivers/iommu/amd_iommu_init.c  | 7 ++++---
>   drivers/iommu/amd_iommu_types.h | 2 ++
>   3 files changed, 12 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
> index 21cb088d6687..f7cdd2ab7f11 100644
> --- a/drivers/iommu/amd_iommu.c
> +++ b/drivers/iommu/amd_iommu.c
> @@ -3169,21 +3169,24 @@ static void amd_iommu_get_resv_regions(struct device 
> *dev,
>               return;
>   
>       list_for_each_entry(entry, &amd_iommu_unity_map, list) {
> +             int type, prot = 0;
>               size_t length;
> -             int prot = 0;
>   
>               if (devid < entry->devid_start || devid > entry->devid_end)
>                       continue;
>   
> +             type   = IOMMU_RESV_DIRECT;
>               length = entry->address_end - entry->address_start;
>               if (entry->prot & IOMMU_PROT_IR)
>                       prot |= IOMMU_READ;
>               if (entry->prot & IOMMU_PROT_IW)
>                       prot |= IOMMU_WRITE;
> +             if (entry->prot & IOMMU_UNITY_MAP_FLAG_EXCL_RANGE)
> +                     /* Exclusion range */
> +                     type = IOMMU_RESV_RESERVED;
>   
>               region = iommu_alloc_resv_region(entry->address_start,
> -                                              length, prot,
> -                                              IOMMU_RESV_DIRECT);
> +                                              length, prot, type);
>               if (!region) {
>                       dev_err(dev, "Out of memory allocating dm-regions\n");
>                       return;
> diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
> index f773792d77fd..1b1378619fc9 100644
> --- a/drivers/iommu/amd_iommu_init.c
> +++ b/drivers/iommu/amd_iommu_init.c
> @@ -2013,6 +2013,9 @@ static int __init init_unity_map_range(struct 
> ivmd_header *m)
>       if (e == NULL)
>               return -ENOMEM;
>   
> +     if (m->flags & IVMD_FLAG_EXCL_RANGE)
> +             init_exclusion_range(m);
> +
>       switch (m->type) {
>       default:
>               kfree(e);
> @@ -2059,9 +2062,7 @@ static int __init init_memory_definitions(struct 
> acpi_table_header *table)
>   
>       while (p < end) {
>               m = (struct ivmd_header *)p;
> -             if (m->flags & IVMD_FLAG_EXCL_RANGE)
> -                     init_exclusion_range(m);
> -             else if (m->flags & IVMD_FLAG_UNITY_MAP)
> +             if (m->flags & (IVMD_FLAG_UNITY_MAP | IVMD_FLAG_EXCL_RANGE))
>                       init_unity_map_range(m);
>   
>               p += m->length;
> diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
> index eae0741f72dc..87965e4d9647 100644
> --- a/drivers/iommu/amd_iommu_types.h
> +++ b/drivers/iommu/amd_iommu_types.h
> @@ -374,6 +374,8 @@
>   #define IOMMU_PROT_IR 0x01
>   #define IOMMU_PROT_IW 0x02
>   
> +#define IOMMU_UNITY_MAP_FLAG_EXCL_RANGE      (1 << 2)
> +
>   /* IOMMU capabilities */
>   #define IOMMU_CAP_IOTLB   24
>   #define IOMMU_CAP_NPCACHE 26
> 

_______________________________________________
iommu mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to