iommu/arm-smmu-v3: Avoid memory corruption from Hisilicon MSI payloads
authorZhen Lei <thunder.leizhen@huawei.com>
Wed, 31 Oct 2018 04:02:07 +0000 (12:02 +0800)
committerWill Deacon <will.deacon@arm.com>
Mon, 10 Dec 2018 14:55:58 +0000 (14:55 +0000)
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>
drivers/iommu/arm-smmu-v3.c

index 71eda42..62ef4af 100644 (file)
@@ -576,7 +576,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;