]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
iommu/arm-smmu-v3: Avoid memory corruption from Hisilicon MSI payloads
authorZhen Lei <thunder.leizhen@huawei.com>
Tue, 12 Mar 2019 18:19:27 +0000 (12:19 -0600)
committerStefan Bader <stefan.bader@canonical.com>
Mon, 1 Apr 2019 12:37:29 +0000 (14:37 +0200)
BugLink: https://bugs.launchpad.net/bugs/1819546
The GITS_TRANSLATER MMIO doorbell register in the ITS hardware is
architected to be 4 bytes in size, yet on hi1620 and earlier, Hisilicon
have allocated the adjacent 4 bytes to carry some IMPDEF sideband
information which results in an 8-byte MSI payload being delivered when
signalling an interrupt:

MSIAddr:
 |----4bytes----|----4bytes----|
 |    MSIData   |    IMPDEF    |

This poses no problem for the ITS hardware because the adjacent 4 bytes
are reserved in the memory map. However, when delivering MSIs to memory,
as we do in the SMMUv3 driver for signalling the completion of a SYNC
command, the extended payload will corrupt the 4 bytes adjacent to the
"sync_count" member in struct arm_smmu_device. Fortunately, the current
layout allocates these bytes to padding, but this is fragile and we
should make this explicit.

Reviewed-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com>
[will: Rewrote commit message and comment]
Signed-off-by: Will Deacon <will.deacon@arm.com>
(cherry picked from commit 84a9a75774961612d0c7dd34a1777e8f98a65abd)
Signed-off-by: dann frazier <dann.frazier@canonical.com>
Acked-by: Khalid Elmously <khalid.elmously@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
drivers/iommu/arm-smmu-v3.c

index 0367432de584db1d0ef341c6a01bdb5e0fa726c6..c6e844ca416b4269debe9da0a607ab2d37191b05 100644 (file)
@@ -642,7 +642,11 @@ struct arm_smmu_device {
 
        struct arm_smmu_strtab_cfg      strtab_cfg;
 
-       u32                             sync_count;
+       /* Hi16xx adds an extra 32 bits of goodness to its MSI payload */
+       union {
+               u32                     sync_count;
+               u64                     padding;
+       };
 
        /* IOMMU core code handle */
        struct iommu_device             iommu;