Commit 75542253 authored by Linus Torvalds's avatar Linus Torvalds

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()
parents 06d1ee32 5adad991
...@@ -23,8 +23,7 @@ config IOMMU_IO_PGTABLE ...@@ -23,8 +23,7 @@ config IOMMU_IO_PGTABLE
config IOMMU_IO_PGTABLE_LPAE config IOMMU_IO_PGTABLE_LPAE
bool "ARMv7/v8 Long Descriptor Format" bool "ARMv7/v8 Long Descriptor Format"
select IOMMU_IO_PGTABLE select IOMMU_IO_PGTABLE
# SWIOTLB guarantees a dma_to_phys() implementation depends on HAS_DMA && (ARM || ARM64 || COMPILE_TEST)
depends on ARM || ARM64 || (COMPILE_TEST && SWIOTLB)
help help
Enable support for the ARM long descriptor pagetable format. Enable support for the ARM long descriptor pagetable format.
This allocator supports 4K/2M/1G, 16K/32M and 64K/512M page 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) ...@@ -2006,6 +2006,15 @@ static void do_detach(struct iommu_dev_data *dev_data)
{ {
struct amd_iommu *iommu; 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]; iommu = amd_iommu_rlookup_table[dev_data->devid];
/* decrease reference counters */ /* decrease reference counters */
......
...@@ -1256,6 +1256,9 @@ static int iommu_init_pci(struct amd_iommu *iommu) ...@@ -1256,6 +1256,9 @@ static int iommu_init_pci(struct amd_iommu *iommu)
if (!iommu->dev) if (!iommu->dev)
return -ENODEV; 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, pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET,
&iommu->cap); &iommu->cap);
pci_read_config_dword(iommu->dev, cap_ptr + MMIO_RANGE_OFFSET, pci_read_config_dword(iommu->dev, cap_ptr + MMIO_RANGE_OFFSET,
......
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
#define IDR0_TTF_SHIFT 2 #define IDR0_TTF_SHIFT 2
#define IDR0_TTF_MASK 0x3 #define IDR0_TTF_MASK 0x3
#define IDR0_TTF_AARCH64 (2 << IDR0_TTF_SHIFT) #define IDR0_TTF_AARCH64 (2 << IDR0_TTF_SHIFT)
#define IDR0_TTF_AARCH32_64 (3 << IDR0_TTF_SHIFT)
#define IDR0_S1P (1 << 1) #define IDR0_S1P (1 << 1)
#define IDR0_S2P (1 << 0) #define IDR0_S2P (1 << 0)
...@@ -342,7 +343,8 @@ ...@@ -342,7 +343,8 @@
#define CMDQ_TLBI_0_VMID_SHIFT 32 #define CMDQ_TLBI_0_VMID_SHIFT 32
#define CMDQ_TLBI_0_ASID_SHIFT 48 #define CMDQ_TLBI_0_ASID_SHIFT 48
#define CMDQ_TLBI_1_LEAF (1UL << 0) #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_SHIFT 12
#define CMDQ_PRI_0_SSID_MASK 0xfffffUL #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) ...@@ -770,11 +772,13 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent)
break; break;
case CMDQ_OP_TLBI_NH_VA: case CMDQ_OP_TLBI_NH_VA:
cmd[0] |= (u64)ent->tlbi.asid << CMDQ_TLBI_0_ASID_SHIFT; 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: case CMDQ_OP_TLBI_S2_IPA:
cmd[0] |= (u64)ent->tlbi.vmid << CMDQ_TLBI_0_VMID_SHIFT; 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.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; break;
case CMDQ_OP_TLBI_NH_ASID: case CMDQ_OP_TLBI_NH_ASID:
cmd[0] |= (u64)ent->tlbi.asid << CMDQ_TLBI_0_ASID_SHIFT; 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) ...@@ -2460,7 +2464,13 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
} }
/* We only support the AArch64 table format at present */ /* 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"); dev_err(smmu->dev, "AArch64 table format not supported!\n");
return -ENXIO; return -ENXIO;
} }
...@@ -2541,8 +2551,7 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu) ...@@ -2541,8 +2551,7 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
dev_warn(smmu->dev, dev_warn(smmu->dev,
"failed to set DMA mask for table walker\n"); "failed to set DMA mask for table walker\n");
if (!smmu->ias) smmu->ias = max(smmu->ias, smmu->oas);
smmu->ias = smmu->oas;
dev_info(smmu->dev, "ias %lu-bit, oas %lu-bit (features 0x%08x)\n", dev_info(smmu->dev, "ias %lu-bit, oas %lu-bit (features 0x%08x)\n",
smmu->ias, smmu->oas, smmu->features); smmu->ias, smmu->oas, smmu->features);
......
...@@ -2301,6 +2301,7 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu, ...@@ -2301,6 +2301,7 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
if (ret) { if (ret) {
spin_unlock_irqrestore(&device_domain_lock, flags); spin_unlock_irqrestore(&device_domain_lock, flags);
free_devinfo_mem(info);
return NULL; return NULL;
} }
......
...@@ -202,9 +202,9 @@ typedef u64 arm_lpae_iopte; ...@@ -202,9 +202,9 @@ typedef u64 arm_lpae_iopte;
static bool selftest_running = false; 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, 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, ...@@ -223,10 +223,10 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
goto out_free; goto out_free;
/* /*
* We depend on the IOMMU being able to work with any physical * We depend on the IOMMU being able to work with any physical
* address directly, so if the DMA layer suggests it can't by * address directly, so if the DMA layer suggests otherwise by
* giving us back some translation, that bodes very badly... * 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; goto out_unmap;
} }
...@@ -243,10 +243,8 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp, ...@@ -243,10 +243,8 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
static void __arm_lpae_free_pages(void *pages, size_t size, static void __arm_lpae_free_pages(void *pages, size_t size,
struct io_pgtable_cfg *cfg) struct io_pgtable_cfg *cfg)
{ {
struct device *dev = cfg->iommu_dev;
if (!selftest_running) 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); size, DMA_TO_DEVICE);
free_pages_exact(pages, size); free_pages_exact(pages, size);
} }
...@@ -254,12 +252,11 @@ static void __arm_lpae_free_pages(void *pages, size_t 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, static void __arm_lpae_set_pte(arm_lpae_iopte *ptep, arm_lpae_iopte pte,
struct io_pgtable_cfg *cfg) struct io_pgtable_cfg *cfg)
{ {
struct device *dev = cfg->iommu_dev;
*ptep = pte; *ptep = pte;
if (!selftest_running) 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); sizeof(pte), DMA_TO_DEVICE);
} }
...@@ -629,6 +626,11 @@ arm_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg) ...@@ -629,6 +626,11 @@ arm_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg)
if (cfg->oas > ARM_LPAE_MAX_ADDR_BITS) if (cfg->oas > ARM_LPAE_MAX_ADDR_BITS)
return NULL; 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); data = kmalloc(sizeof(*data), GFP_KERNEL);
if (!data) if (!data)
return NULL; return NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment