lkml.org 
[lkml]   [2019]   [Jan]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.19 167/170] iommu/arm-smmu-v3: Fix big-endian CMD_SYNC writes
    Date
    4.19-stable review patch.  If anyone has any objections, please let me know.

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

    From: Robin Murphy <robin.murphy@arm.com>

    commit 3cd508a8c1379427afb5e16c2e0a7c986d907853 upstream.

    When we insert the sync sequence number into the CMD_SYNC.MSIData field,
    we do so in CPU-native byte order, before writing out the whole command
    as explicitly little-endian dwords. Thus on big-endian systems, the SMMU
    will receive and write back a byteswapped version of sync_nr, which would
    be perfect if it were targeting a similarly-little-endian ITS, but since
    it's actually writing back to memory being polled by the CPUs, they're
    going to end up seeing the wrong thing.

    Since the SMMU doesn't care what the MSIData actually contains, the
    minimal-overhead solution is to simply add an extra byteswap initially,
    such that it then writes back the big-endian format directly.

    Cc: <stable@vger.kernel.org>
    Fixes: 37de98f8f1cf ("iommu/arm-smmu-v3: Use CMD_SYNC completion MSI")
    Signed-off-by: Robin Murphy <robin.murphy@arm.com>
    Signed-off-by: Will Deacon <will.deacon@arm.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

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

    --- a/drivers/iommu/arm-smmu-v3.c
    +++ b/drivers/iommu/arm-smmu-v3.c
    @@ -837,7 +837,13 @@ static int arm_smmu_cmdq_build_cmd(u64 *
    cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_CS, CMDQ_SYNC_0_CS_SEV);
    cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_MSH, ARM_SMMU_SH_ISH);
    cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_MSIATTR, ARM_SMMU_MEMATTR_OIWB);
    - cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_MSIDATA, ent->sync.msidata);
    + /*
    + * Commands are written little-endian, but we want the SMMU to
    + * receive MSIData, and thus write it back to memory, in CPU
    + * byte order, so big-endian needs an extra byteswap here.
    + */
    + cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_MSIDATA,
    + cpu_to_le32(ent->sync.msidata));
    cmd[1] |= ent->sync.msiaddr & CMDQ_SYNC_1_MSIADDR_MASK;
    break;
    default:

    \
     
     \ /
      Last update: 2019-01-07 18:25    [W:4.129 / U:0.488 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site