lkml.org 
[lkml]   [2018]   [Sep]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.18 138/158] iommu/arm-smmu-v3: Abort all transactions if SMMU is enabled in kdump kernel
    Date
    4.18-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Will Deacon <will.deacon@arm.com>

    [ Upstream commit b63b3439b85609338e4faabd5d2588dbda137e5c ]

    If we find that the SMMU is enabled during probe, we reset it by
    re-initialising its registers and either enabling translation or placing
    it into bypass based on the disable_bypass commandline option.

    In the case of a kdump kernel, the SMMU won't have been shutdown cleanly
    by the previous kernel and there may be concurrent DMA through the SMMU.
    Rather than reset the SMMU to bypass, which would likely lead to rampant
    data corruption, we can instead configure the SMMU to abort all incoming
    transactions when we find that it is enabled from within a kdump kernel.

    Reported-by: Sameer Goel <sgoel@codeaurora.org>
    Signed-off-by: Will Deacon <will.deacon@arm.com>
    Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/iommu/arm-smmu-v3.c | 22 ++++++++++++++++------
    1 file changed, 16 insertions(+), 6 deletions(-)

    --- a/drivers/iommu/arm-smmu-v3.c
    +++ b/drivers/iommu/arm-smmu-v3.c
    @@ -24,6 +24,7 @@
    #include <linux/acpi_iort.h>
    #include <linux/bitfield.h>
    #include <linux/bitops.h>
    +#include <linux/crash_dump.h>
    #include <linux/delay.h>
    #include <linux/dma-iommu.h>
    #include <linux/err.h>
    @@ -2211,8 +2212,12 @@ static int arm_smmu_update_gbpa(struct a
    reg &= ~clr;
    reg |= set;
    writel_relaxed(reg | GBPA_UPDATE, gbpa);
    - return readl_relaxed_poll_timeout(gbpa, reg, !(reg & GBPA_UPDATE),
    - 1, ARM_SMMU_POLL_TIMEOUT_US);
    + ret = readl_relaxed_poll_timeout(gbpa, reg, !(reg & GBPA_UPDATE),
    + 1, ARM_SMMU_POLL_TIMEOUT_US);
    +
    + if (ret)
    + dev_err(smmu->dev, "GBPA not responding to update\n");
    + return ret;
    }

    static void arm_smmu_free_msis(void *data)
    @@ -2392,8 +2397,15 @@ static int arm_smmu_device_reset(struct

    /* Clear CR0 and sync (disables SMMU and queue processing) */
    reg = readl_relaxed(smmu->base + ARM_SMMU_CR0);
    - if (reg & CR0_SMMUEN)
    + if (reg & CR0_SMMUEN) {
    + if (is_kdump_kernel()) {
    + arm_smmu_update_gbpa(smmu, GBPA_ABORT, 0);
    + arm_smmu_device_disable(smmu);
    + return -EBUSY;
    + }
    +
    dev_warn(smmu->dev, "SMMU currently enabled! Resetting...\n");
    + }

    ret = arm_smmu_device_disable(smmu);
    if (ret)
    @@ -2491,10 +2503,8 @@ static int arm_smmu_device_reset(struct
    enables |= CR0_SMMUEN;
    } else {
    ret = arm_smmu_update_gbpa(smmu, 0, GBPA_ABORT);
    - if (ret) {
    - dev_err(smmu->dev, "GBPA not responding to update\n");
    + if (ret)
    return ret;
    - }
    }
    ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
    ARM_SMMU_CR0ACK);

    \
     
     \ /
      Last update: 2018-09-18 01:17    [W:4.098 / U:0.900 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site