lkml.org 
[lkml]   [2019]   [May]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.0 097/101] iommu/amd: Reserve exclusion range in iova-domain
    Date
    [ Upstream commit 8aafaaf2212192012f5bae305bb31cdf7681d777 ]

    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.

    Fixes: be2a022c0dd0 ('x86, AMD IOMMU: add functions to parse IOMMU memory mapping requirements for devices')
    Signed-off-by: Joerg Roedel <jroedel@suse.de>
    Reviewed-by: Gary R Hook <gary.hook@amd.com>
    Signed-off-by: Sasha Levin (Microsoft) <sashal@kernel.org>
    ---
    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 e628ef23418f..55b3e4b9d5dc 100644
    --- a/drivers/iommu/amd_iommu.c
    +++ b/drivers/iommu/amd_iommu.c
    @@ -3166,21 +3166,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) {
    pr_err("Out of memory allocating dm-regions for %s\n",
    dev_name(dev));
    diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
    index 66123b911ec8..84fa5b22371e 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
    --
    2.19.1


    \
     
     \ /
      Last update: 2019-05-02 17:34    [W:4.142 / U:0.056 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site