IOMMU Fixes for Linux v4.3-rc5
A few fixes piled up: * Fix for a suspend/resume issue where PCI probing code overwrote dev->irq for the MSI irq of the AMD IOMMU. * Fix for a kernel crash when a 32 bit PCI device was assigned to a KVM guest. * Fix for a possible memory leak in the VT-d driver * A couple of fixes for the ARM-SMMU driver -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJWHNdbAAoJECvwRC2XARrjB/YQAKouJaRMjBaehx6kbaZMhMJy hXDsh8Xl6TtCe6kLD2uXrvjLZAdu32kjrtzhhcM21EO5Ms2Weq6A60/98LwnJ4Eg AqftjfxQsIwf2G1PvHb+xepgcFxIAhW6a3nORzx6d2AGrNWmMtUhbLTSncYjmojf Td4dscuRmRPenJUV1JhcJQBR62QonknIHV99QmevaCSAoUdyuMH+t5kQVEgPjx7C GlMPNEZZmGl7J3NXSWRtDSkUxFZ1OU8MTKc1LmPPHHAOZk37wbePihQbLLySlHPH v4G1R05e2hG7C66yu959fyOleL87lDToUXhwQNFJMqEc+e7IzBzZsB3ANEHjpLQH UJC9COU+sf8mPafja4ge/KbyGDmgDg/OMQJDhU6+DSXUflwymeWJmXr7sLFQex6O nZO/SVzkbKj+PKxV7UnGD0sTeAAk0X6vfhFCL0l/acPpQg0T6Fpky5D5fUMv5dWS xxxvxfwBcDoI44fxWBhfPYvmLFT9f5da+bpbzeeGjVSNezOkPJ65AJcVk5An4kQu PRzJGoq3XpZHOeg5+O7IKzeuJ+3qc7Tz4wAzMxcaNFpVBl2qp1RUkTbmS9/YV1b5 ZOcIFBMLuUROE1ExsU19c5Uo0j1Bvh9jtdy6lNFCagQYzihtA0Jk19ucllx1jIjD sdv2hgDIauRToKF1d9xz =v5G4 -----END PGP SIGNATURE----- Merge tag 'iommu-fixes-v4.3-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu Pull IOMMU fixes from Joerg Roedel: "A few fixes piled up: - Fix for a suspend/resume issue where PCI probing code overwrote dev->irq for the MSI irq of the AMD IOMMU. - Fix for a kernel crash when a 32 bit PCI device was assigned to a KVM guest. - Fix for a possible memory leak in the VT-d driver - A couple of fixes for the ARM-SMMU driver" * tag 'iommu-fixes-v4.3-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: iommu/amd: Fix NULL pointer deref on device detach iommu/amd: Prevent binding other PCI drivers to IOMMU PCI devices iommu/vt-d: Fix memory leak in dmar_insert_one_dev_info() iommu/arm-smmu: Use correct address mask for CMD_TLBI_S2_IPA iommu/arm-smmu: Ensure IAS is set correctly for AArch32-capable SMMUs iommu/io-pgtable-arm: Don't use dma_to_phys()
This commit is contained in:
Коммит
7554225312
|
@ -23,8 +23,7 @@ config IOMMU_IO_PGTABLE
|
|||
config IOMMU_IO_PGTABLE_LPAE
|
||||
bool "ARMv7/v8 Long Descriptor Format"
|
||||
select IOMMU_IO_PGTABLE
|
||||
# SWIOTLB guarantees a dma_to_phys() implementation
|
||||
depends on ARM || ARM64 || (COMPILE_TEST && SWIOTLB)
|
||||
depends on HAS_DMA && (ARM || ARM64 || COMPILE_TEST)
|
||||
help
|
||||
Enable support for the ARM long descriptor pagetable format.
|
||||
This allocator supports 4K/2M/1G, 16K/32M and 64K/512M page
|
||||
|
|
|
@ -2006,6 +2006,15 @@ static void do_detach(struct iommu_dev_data *dev_data)
|
|||
{
|
||||
struct amd_iommu *iommu;
|
||||
|
||||
/*
|
||||
* First check if the device is still attached. It might already
|
||||
* be detached from its domain because the generic
|
||||
* iommu_detach_group code detached it and we try again here in
|
||||
* our alias handling.
|
||||
*/
|
||||
if (!dev_data->domain)
|
||||
return;
|
||||
|
||||
iommu = amd_iommu_rlookup_table[dev_data->devid];
|
||||
|
||||
/* decrease reference counters */
|
||||
|
|
|
@ -1256,6 +1256,9 @@ static int iommu_init_pci(struct amd_iommu *iommu)
|
|||
if (!iommu->dev)
|
||||
return -ENODEV;
|
||||
|
||||
/* Prevent binding other PCI device drivers to IOMMU devices */
|
||||
iommu->dev->match_driver = false;
|
||||
|
||||
pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET,
|
||||
&iommu->cap);
|
||||
pci_read_config_dword(iommu->dev, cap_ptr + MMIO_RANGE_OFFSET,
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#define IDR0_TTF_SHIFT 2
|
||||
#define IDR0_TTF_MASK 0x3
|
||||
#define IDR0_TTF_AARCH64 (2 << IDR0_TTF_SHIFT)
|
||||
#define IDR0_TTF_AARCH32_64 (3 << IDR0_TTF_SHIFT)
|
||||
#define IDR0_S1P (1 << 1)
|
||||
#define IDR0_S2P (1 << 0)
|
||||
|
||||
|
@ -342,7 +343,8 @@
|
|||
#define CMDQ_TLBI_0_VMID_SHIFT 32
|
||||
#define CMDQ_TLBI_0_ASID_SHIFT 48
|
||||
#define CMDQ_TLBI_1_LEAF (1UL << 0)
|
||||
#define CMDQ_TLBI_1_ADDR_MASK ~0xfffUL
|
||||
#define CMDQ_TLBI_1_VA_MASK ~0xfffUL
|
||||
#define CMDQ_TLBI_1_IPA_MASK 0xfffffffff000UL
|
||||
|
||||
#define CMDQ_PRI_0_SSID_SHIFT 12
|
||||
#define CMDQ_PRI_0_SSID_MASK 0xfffffUL
|
||||
|
@ -770,11 +772,13 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent)
|
|||
break;
|
||||
case CMDQ_OP_TLBI_NH_VA:
|
||||
cmd[0] |= (u64)ent->tlbi.asid << CMDQ_TLBI_0_ASID_SHIFT;
|
||||
/* Fallthrough */
|
||||
cmd[1] |= ent->tlbi.leaf ? CMDQ_TLBI_1_LEAF : 0;
|
||||
cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_VA_MASK;
|
||||
break;
|
||||
case CMDQ_OP_TLBI_S2_IPA:
|
||||
cmd[0] |= (u64)ent->tlbi.vmid << CMDQ_TLBI_0_VMID_SHIFT;
|
||||
cmd[1] |= ent->tlbi.leaf ? CMDQ_TLBI_1_LEAF : 0;
|
||||
cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_ADDR_MASK;
|
||||
cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_IPA_MASK;
|
||||
break;
|
||||
case CMDQ_OP_TLBI_NH_ASID:
|
||||
cmd[0] |= (u64)ent->tlbi.asid << CMDQ_TLBI_0_ASID_SHIFT;
|
||||
|
@ -2460,7 +2464,13 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
|
|||
}
|
||||
|
||||
/* We only support the AArch64 table format at present */
|
||||
if ((reg & IDR0_TTF_MASK << IDR0_TTF_SHIFT) < IDR0_TTF_AARCH64) {
|
||||
switch (reg & IDR0_TTF_MASK << IDR0_TTF_SHIFT) {
|
||||
case IDR0_TTF_AARCH32_64:
|
||||
smmu->ias = 40;
|
||||
/* Fallthrough */
|
||||
case IDR0_TTF_AARCH64:
|
||||
break;
|
||||
default:
|
||||
dev_err(smmu->dev, "AArch64 table format not supported!\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
@ -2541,8 +2551,7 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
|
|||
dev_warn(smmu->dev,
|
||||
"failed to set DMA mask for table walker\n");
|
||||
|
||||
if (!smmu->ias)
|
||||
smmu->ias = smmu->oas;
|
||||
smmu->ias = max(smmu->ias, smmu->oas);
|
||||
|
||||
dev_info(smmu->dev, "ias %lu-bit, oas %lu-bit (features 0x%08x)\n",
|
||||
smmu->ias, smmu->oas, smmu->features);
|
||||
|
|
|
@ -2301,6 +2301,7 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
|
|||
|
||||
if (ret) {
|
||||
spin_unlock_irqrestore(&device_domain_lock, flags);
|
||||
free_devinfo_mem(info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -202,9 +202,9 @@ typedef u64 arm_lpae_iopte;
|
|||
|
||||
static bool selftest_running = false;
|
||||
|
||||
static dma_addr_t __arm_lpae_dma_addr(struct device *dev, void *pages)
|
||||
static dma_addr_t __arm_lpae_dma_addr(void *pages)
|
||||
{
|
||||
return phys_to_dma(dev, virt_to_phys(pages));
|
||||
return (dma_addr_t)virt_to_phys(pages);
|
||||
}
|
||||
|
||||
static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
|
||||
|
@ -223,10 +223,10 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
|
|||
goto out_free;
|
||||
/*
|
||||
* We depend on the IOMMU being able to work with any physical
|
||||
* address directly, so if the DMA layer suggests it can't by
|
||||
* giving us back some translation, that bodes very badly...
|
||||
* address directly, so if the DMA layer suggests otherwise by
|
||||
* translating or truncating them, that bodes very badly...
|
||||
*/
|
||||
if (dma != __arm_lpae_dma_addr(dev, pages))
|
||||
if (dma != virt_to_phys(pages))
|
||||
goto out_unmap;
|
||||
}
|
||||
|
||||
|
@ -243,10 +243,8 @@ out_free:
|
|||
static void __arm_lpae_free_pages(void *pages, size_t size,
|
||||
struct io_pgtable_cfg *cfg)
|
||||
{
|
||||
struct device *dev = cfg->iommu_dev;
|
||||
|
||||
if (!selftest_running)
|
||||
dma_unmap_single(dev, __arm_lpae_dma_addr(dev, pages),
|
||||
dma_unmap_single(cfg->iommu_dev, __arm_lpae_dma_addr(pages),
|
||||
size, DMA_TO_DEVICE);
|
||||
free_pages_exact(pages, size);
|
||||
}
|
||||
|
@ -254,12 +252,11 @@ static void __arm_lpae_free_pages(void *pages, size_t size,
|
|||
static void __arm_lpae_set_pte(arm_lpae_iopte *ptep, arm_lpae_iopte pte,
|
||||
struct io_pgtable_cfg *cfg)
|
||||
{
|
||||
struct device *dev = cfg->iommu_dev;
|
||||
|
||||
*ptep = pte;
|
||||
|
||||
if (!selftest_running)
|
||||
dma_sync_single_for_device(dev, __arm_lpae_dma_addr(dev, ptep),
|
||||
dma_sync_single_for_device(cfg->iommu_dev,
|
||||
__arm_lpae_dma_addr(ptep),
|
||||
sizeof(pte), DMA_TO_DEVICE);
|
||||
}
|
||||
|
||||
|
@ -629,6 +626,11 @@ arm_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg)
|
|||
if (cfg->oas > ARM_LPAE_MAX_ADDR_BITS)
|
||||
return NULL;
|
||||
|
||||
if (!selftest_running && cfg->iommu_dev->dma_pfn_offset) {
|
||||
dev_err(cfg->iommu_dev, "Cannot accommodate DMA offset for IOMMU page tables\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = kmalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
|
Загрузка…
Ссылка в новой задаче