diff options
Diffstat (limited to 'drivers/iommu/arm-smmu.c')
-rw-r--r-- | drivers/iommu/arm-smmu.c | 105 |
1 files changed, 63 insertions, 42 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 8911850c9444..1d9ab39af29f 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c | |||
@@ -79,7 +79,6 @@ | |||
79 | 79 | ||
80 | #define ARM_SMMU_PTE_CONT_SIZE (PAGE_SIZE * ARM_SMMU_PTE_CONT_ENTRIES) | 80 | #define ARM_SMMU_PTE_CONT_SIZE (PAGE_SIZE * ARM_SMMU_PTE_CONT_ENTRIES) |
81 | #define ARM_SMMU_PTE_CONT_MASK (~(ARM_SMMU_PTE_CONT_SIZE - 1)) | 81 | #define ARM_SMMU_PTE_CONT_MASK (~(ARM_SMMU_PTE_CONT_SIZE - 1)) |
82 | #define ARM_SMMU_PTE_HWTABLE_SIZE (PTRS_PER_PTE * sizeof(pte_t)) | ||
83 | 82 | ||
84 | /* Stage-1 PTE */ | 83 | /* Stage-1 PTE */ |
85 | #define ARM_SMMU_PTE_AP_UNPRIV (((pteval_t)1) << 6) | 84 | #define ARM_SMMU_PTE_AP_UNPRIV (((pteval_t)1) << 6) |
@@ -191,6 +190,9 @@ | |||
191 | #define ARM_SMMU_GR1_CBAR(n) (0x0 + ((n) << 2)) | 190 | #define ARM_SMMU_GR1_CBAR(n) (0x0 + ((n) << 2)) |
192 | #define CBAR_VMID_SHIFT 0 | 191 | #define CBAR_VMID_SHIFT 0 |
193 | #define CBAR_VMID_MASK 0xff | 192 | #define CBAR_VMID_MASK 0xff |
193 | #define CBAR_S1_BPSHCFG_SHIFT 8 | ||
194 | #define CBAR_S1_BPSHCFG_MASK 3 | ||
195 | #define CBAR_S1_BPSHCFG_NSH 3 | ||
194 | #define CBAR_S1_MEMATTR_SHIFT 12 | 196 | #define CBAR_S1_MEMATTR_SHIFT 12 |
195 | #define CBAR_S1_MEMATTR_MASK 0xf | 197 | #define CBAR_S1_MEMATTR_MASK 0xf |
196 | #define CBAR_S1_MEMATTR_WB 0xf | 198 | #define CBAR_S1_MEMATTR_WB 0xf |
@@ -393,7 +395,7 @@ struct arm_smmu_domain { | |||
393 | struct arm_smmu_cfg root_cfg; | 395 | struct arm_smmu_cfg root_cfg; |
394 | phys_addr_t output_mask; | 396 | phys_addr_t output_mask; |
395 | 397 | ||
396 | struct mutex lock; | 398 | spinlock_t lock; |
397 | }; | 399 | }; |
398 | 400 | ||
399 | static DEFINE_SPINLOCK(arm_smmu_devices_lock); | 401 | static DEFINE_SPINLOCK(arm_smmu_devices_lock); |
@@ -632,6 +634,28 @@ static irqreturn_t arm_smmu_global_fault(int irq, void *dev) | |||
632 | return IRQ_HANDLED; | 634 | return IRQ_HANDLED; |
633 | } | 635 | } |
634 | 636 | ||
637 | static void arm_smmu_flush_pgtable(struct arm_smmu_device *smmu, void *addr, | ||
638 | size_t size) | ||
639 | { | ||
640 | unsigned long offset = (unsigned long)addr & ~PAGE_MASK; | ||
641 | |||
642 | |||
643 | /* Ensure new page tables are visible to the hardware walker */ | ||
644 | if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK) { | ||
645 | dsb(); | ||
646 | } else { | ||
647 | /* | ||
648 | * If the SMMU can't walk tables in the CPU caches, treat them | ||
649 | * like non-coherent DMA since we need to flush the new entries | ||
650 | * all the way out to memory. There's no possibility of | ||
651 | * recursion here as the SMMU table walker will not be wired | ||
652 | * through another SMMU. | ||
653 | */ | ||
654 | dma_map_page(smmu->dev, virt_to_page(addr), offset, size, | ||
655 | DMA_TO_DEVICE); | ||
656 | } | ||
657 | } | ||
658 | |||
635 | static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) | 659 | static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) |
636 | { | 660 | { |
637 | u32 reg; | 661 | u32 reg; |
@@ -650,11 +674,16 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) | |||
650 | if (smmu->version == 1) | 674 | if (smmu->version == 1) |
651 | reg |= root_cfg->irptndx << CBAR_IRPTNDX_SHIFT; | 675 | reg |= root_cfg->irptndx << CBAR_IRPTNDX_SHIFT; |
652 | 676 | ||
653 | /* Use the weakest memory type, so it is overridden by the pte */ | 677 | /* |
654 | if (stage1) | 678 | * Use the weakest shareability/memory types, so they are |
655 | reg |= (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT); | 679 | * overridden by the ttbcr/pte. |
656 | else | 680 | */ |
681 | if (stage1) { | ||
682 | reg |= (CBAR_S1_BPSHCFG_NSH << CBAR_S1_BPSHCFG_SHIFT) | | ||
683 | (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT); | ||
684 | } else { | ||
657 | reg |= ARM_SMMU_CB_VMID(root_cfg) << CBAR_VMID_SHIFT; | 685 | reg |= ARM_SMMU_CB_VMID(root_cfg) << CBAR_VMID_SHIFT; |
686 | } | ||
658 | writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(root_cfg->cbndx)); | 687 | writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(root_cfg->cbndx)); |
659 | 688 | ||
660 | if (smmu->version > 1) { | 689 | if (smmu->version > 1) { |
@@ -715,6 +744,8 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain) | |||
715 | } | 744 | } |
716 | 745 | ||
717 | /* TTBR0 */ | 746 | /* TTBR0 */ |
747 | arm_smmu_flush_pgtable(smmu, root_cfg->pgd, | ||
748 | PTRS_PER_PGD * sizeof(pgd_t)); | ||
718 | reg = __pa(root_cfg->pgd); | 749 | reg = __pa(root_cfg->pgd); |
719 | writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_LO); | 750 | writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0_LO); |
720 | reg = (phys_addr_t)__pa(root_cfg->pgd) >> 32; | 751 | reg = (phys_addr_t)__pa(root_cfg->pgd) >> 32; |
@@ -901,7 +932,7 @@ static int arm_smmu_domain_init(struct iommu_domain *domain) | |||
901 | goto out_free_domain; | 932 | goto out_free_domain; |
902 | smmu_domain->root_cfg.pgd = pgd; | 933 | smmu_domain->root_cfg.pgd = pgd; |
903 | 934 | ||
904 | mutex_init(&smmu_domain->lock); | 935 | spin_lock_init(&smmu_domain->lock); |
905 | domain->priv = smmu_domain; | 936 | domain->priv = smmu_domain; |
906 | return 0; | 937 | return 0; |
907 | 938 | ||
@@ -1128,6 +1159,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) | |||
1128 | struct arm_smmu_domain *smmu_domain = domain->priv; | 1159 | struct arm_smmu_domain *smmu_domain = domain->priv; |
1129 | struct arm_smmu_device *device_smmu = dev->archdata.iommu; | 1160 | struct arm_smmu_device *device_smmu = dev->archdata.iommu; |
1130 | struct arm_smmu_master *master; | 1161 | struct arm_smmu_master *master; |
1162 | unsigned long flags; | ||
1131 | 1163 | ||
1132 | if (!device_smmu) { | 1164 | if (!device_smmu) { |
1133 | dev_err(dev, "cannot attach to SMMU, is it on the same bus?\n"); | 1165 | dev_err(dev, "cannot attach to SMMU, is it on the same bus?\n"); |
@@ -1138,7 +1170,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) | |||
1138 | * Sanity check the domain. We don't currently support domains | 1170 | * Sanity check the domain. We don't currently support domains |
1139 | * that cross between different SMMU chains. | 1171 | * that cross between different SMMU chains. |
1140 | */ | 1172 | */ |
1141 | mutex_lock(&smmu_domain->lock); | 1173 | spin_lock_irqsave(&smmu_domain->lock, flags); |
1142 | if (!smmu_domain->leaf_smmu) { | 1174 | if (!smmu_domain->leaf_smmu) { |
1143 | /* Now that we have a master, we can finalise the domain */ | 1175 | /* Now that we have a master, we can finalise the domain */ |
1144 | ret = arm_smmu_init_domain_context(domain, dev); | 1176 | ret = arm_smmu_init_domain_context(domain, dev); |
@@ -1153,7 +1185,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) | |||
1153 | dev_name(device_smmu->dev)); | 1185 | dev_name(device_smmu->dev)); |
1154 | goto err_unlock; | 1186 | goto err_unlock; |
1155 | } | 1187 | } |
1156 | mutex_unlock(&smmu_domain->lock); | 1188 | spin_unlock_irqrestore(&smmu_domain->lock, flags); |
1157 | 1189 | ||
1158 | /* Looks ok, so add the device to the domain */ | 1190 | /* Looks ok, so add the device to the domain */ |
1159 | master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node); | 1191 | master = find_smmu_master(smmu_domain->leaf_smmu, dev->of_node); |
@@ -1163,7 +1195,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) | |||
1163 | return arm_smmu_domain_add_master(smmu_domain, master); | 1195 | return arm_smmu_domain_add_master(smmu_domain, master); |
1164 | 1196 | ||
1165 | err_unlock: | 1197 | err_unlock: |
1166 | mutex_unlock(&smmu_domain->lock); | 1198 | spin_unlock_irqrestore(&smmu_domain->lock, flags); |
1167 | return ret; | 1199 | return ret; |
1168 | } | 1200 | } |
1169 | 1201 | ||
@@ -1177,23 +1209,6 @@ static void arm_smmu_detach_dev(struct iommu_domain *domain, struct device *dev) | |||
1177 | arm_smmu_domain_remove_master(smmu_domain, master); | 1209 | arm_smmu_domain_remove_master(smmu_domain, master); |
1178 | } | 1210 | } |
1179 | 1211 | ||
1180 | static void arm_smmu_flush_pgtable(struct arm_smmu_device *smmu, void *addr, | ||
1181 | size_t size) | ||
1182 | { | ||
1183 | unsigned long offset = (unsigned long)addr & ~PAGE_MASK; | ||
1184 | |||
1185 | /* | ||
1186 | * If the SMMU can't walk tables in the CPU caches, treat them | ||
1187 | * like non-coherent DMA since we need to flush the new entries | ||
1188 | * all the way out to memory. There's no possibility of recursion | ||
1189 | * here as the SMMU table walker will not be wired through another | ||
1190 | * SMMU. | ||
1191 | */ | ||
1192 | if (!(smmu->features & ARM_SMMU_FEAT_COHERENT_WALK)) | ||
1193 | dma_map_page(smmu->dev, virt_to_page(addr), offset, size, | ||
1194 | DMA_TO_DEVICE); | ||
1195 | } | ||
1196 | |||
1197 | static bool arm_smmu_pte_is_contiguous_range(unsigned long addr, | 1212 | static bool arm_smmu_pte_is_contiguous_range(unsigned long addr, |
1198 | unsigned long end) | 1213 | unsigned long end) |
1199 | { | 1214 | { |
@@ -1210,12 +1225,11 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd, | |||
1210 | 1225 | ||
1211 | if (pmd_none(*pmd)) { | 1226 | if (pmd_none(*pmd)) { |
1212 | /* Allocate a new set of tables */ | 1227 | /* Allocate a new set of tables */ |
1213 | pgtable_t table = alloc_page(PGALLOC_GFP); | 1228 | pgtable_t table = alloc_page(GFP_ATOMIC|__GFP_ZERO); |
1214 | if (!table) | 1229 | if (!table) |
1215 | return -ENOMEM; | 1230 | return -ENOMEM; |
1216 | 1231 | ||
1217 | arm_smmu_flush_pgtable(smmu, page_address(table), | 1232 | arm_smmu_flush_pgtable(smmu, page_address(table), PAGE_SIZE); |
1218 | ARM_SMMU_PTE_HWTABLE_SIZE); | ||
1219 | if (!pgtable_page_ctor(table)) { | 1233 | if (!pgtable_page_ctor(table)) { |
1220 | __free_page(table); | 1234 | __free_page(table); |
1221 | return -ENOMEM; | 1235 | return -ENOMEM; |
@@ -1317,9 +1331,15 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud, | |||
1317 | 1331 | ||
1318 | #ifndef __PAGETABLE_PMD_FOLDED | 1332 | #ifndef __PAGETABLE_PMD_FOLDED |
1319 | if (pud_none(*pud)) { | 1333 | if (pud_none(*pud)) { |
1320 | pmd = pmd_alloc_one(NULL, addr); | 1334 | pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC); |
1321 | if (!pmd) | 1335 | if (!pmd) |
1322 | return -ENOMEM; | 1336 | return -ENOMEM; |
1337 | |||
1338 | arm_smmu_flush_pgtable(smmu, pmd, PAGE_SIZE); | ||
1339 | pud_populate(NULL, pud, pmd); | ||
1340 | arm_smmu_flush_pgtable(smmu, pud, sizeof(*pud)); | ||
1341 | |||
1342 | pmd += pmd_index(addr); | ||
1323 | } else | 1343 | } else |
1324 | #endif | 1344 | #endif |
1325 | pmd = pmd_offset(pud, addr); | 1345 | pmd = pmd_offset(pud, addr); |
@@ -1328,8 +1348,6 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud, | |||
1328 | next = pmd_addr_end(addr, end); | 1348 | next = pmd_addr_end(addr, end); |
1329 | ret = arm_smmu_alloc_init_pte(smmu, pmd, addr, end, pfn, | 1349 | ret = arm_smmu_alloc_init_pte(smmu, pmd, addr, end, pfn, |
1330 | flags, stage); | 1350 | flags, stage); |
1331 | pud_populate(NULL, pud, pmd); | ||
1332 | arm_smmu_flush_pgtable(smmu, pud, sizeof(*pud)); | ||
1333 | phys += next - addr; | 1351 | phys += next - addr; |
1334 | } while (pmd++, addr = next, addr < end); | 1352 | } while (pmd++, addr = next, addr < end); |
1335 | 1353 | ||
@@ -1346,9 +1364,15 @@ static int arm_smmu_alloc_init_pud(struct arm_smmu_device *smmu, pgd_t *pgd, | |||
1346 | 1364 | ||
1347 | #ifndef __PAGETABLE_PUD_FOLDED | 1365 | #ifndef __PAGETABLE_PUD_FOLDED |
1348 | if (pgd_none(*pgd)) { | 1366 | if (pgd_none(*pgd)) { |
1349 | pud = pud_alloc_one(NULL, addr); | 1367 | pud = (pud_t *)get_zeroed_page(GFP_ATOMIC); |
1350 | if (!pud) | 1368 | if (!pud) |
1351 | return -ENOMEM; | 1369 | return -ENOMEM; |
1370 | |||
1371 | arm_smmu_flush_pgtable(smmu, pud, PAGE_SIZE); | ||
1372 | pgd_populate(NULL, pgd, pud); | ||
1373 | arm_smmu_flush_pgtable(smmu, pgd, sizeof(*pgd)); | ||
1374 | |||
1375 | pud += pud_index(addr); | ||
1352 | } else | 1376 | } else |
1353 | #endif | 1377 | #endif |
1354 | pud = pud_offset(pgd, addr); | 1378 | pud = pud_offset(pgd, addr); |
@@ -1357,8 +1381,6 @@ static int arm_smmu_alloc_init_pud(struct arm_smmu_device *smmu, pgd_t *pgd, | |||
1357 | next = pud_addr_end(addr, end); | 1381 | next = pud_addr_end(addr, end); |
1358 | ret = arm_smmu_alloc_init_pmd(smmu, pud, addr, next, phys, | 1382 | ret = arm_smmu_alloc_init_pmd(smmu, pud, addr, next, phys, |
1359 | flags, stage); | 1383 | flags, stage); |
1360 | pgd_populate(NULL, pud, pgd); | ||
1361 | arm_smmu_flush_pgtable(smmu, pgd, sizeof(*pgd)); | ||
1362 | phys += next - addr; | 1384 | phys += next - addr; |
1363 | } while (pud++, addr = next, addr < end); | 1385 | } while (pud++, addr = next, addr < end); |
1364 | 1386 | ||
@@ -1375,6 +1397,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain, | |||
1375 | struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg; | 1397 | struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg; |
1376 | pgd_t *pgd = root_cfg->pgd; | 1398 | pgd_t *pgd = root_cfg->pgd; |
1377 | struct arm_smmu_device *smmu = root_cfg->smmu; | 1399 | struct arm_smmu_device *smmu = root_cfg->smmu; |
1400 | unsigned long irqflags; | ||
1378 | 1401 | ||
1379 | if (root_cfg->cbar == CBAR_TYPE_S2_TRANS) { | 1402 | if (root_cfg->cbar == CBAR_TYPE_S2_TRANS) { |
1380 | stage = 2; | 1403 | stage = 2; |
@@ -1397,7 +1420,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain, | |||
1397 | if (paddr & ~output_mask) | 1420 | if (paddr & ~output_mask) |
1398 | return -ERANGE; | 1421 | return -ERANGE; |
1399 | 1422 | ||
1400 | mutex_lock(&smmu_domain->lock); | 1423 | spin_lock_irqsave(&smmu_domain->lock, irqflags); |
1401 | pgd += pgd_index(iova); | 1424 | pgd += pgd_index(iova); |
1402 | end = iova + size; | 1425 | end = iova + size; |
1403 | do { | 1426 | do { |
@@ -1413,11 +1436,7 @@ static int arm_smmu_handle_mapping(struct arm_smmu_domain *smmu_domain, | |||
1413 | } while (pgd++, iova != end); | 1436 | } while (pgd++, iova != end); |
1414 | 1437 | ||
1415 | out_unlock: | 1438 | out_unlock: |
1416 | mutex_unlock(&smmu_domain->lock); | 1439 | spin_unlock_irqrestore(&smmu_domain->lock, irqflags); |
1417 | |||
1418 | /* Ensure new page tables are visible to the hardware walker */ | ||
1419 | if (smmu->features & ARM_SMMU_FEAT_COHERENT_WALK) | ||
1420 | dsb(); | ||
1421 | 1440 | ||
1422 | return ret; | 1441 | return ret; |
1423 | } | 1442 | } |
@@ -1987,8 +2006,10 @@ static int __init arm_smmu_init(void) | |||
1987 | if (!iommu_present(&platform_bus_type)) | 2006 | if (!iommu_present(&platform_bus_type)) |
1988 | bus_set_iommu(&platform_bus_type, &arm_smmu_ops); | 2007 | bus_set_iommu(&platform_bus_type, &arm_smmu_ops); |
1989 | 2008 | ||
2009 | #ifdef CONFIG_ARM_AMBA | ||
1990 | if (!iommu_present(&amba_bustype)) | 2010 | if (!iommu_present(&amba_bustype)) |
1991 | bus_set_iommu(&amba_bustype, &arm_smmu_ops); | 2011 | bus_set_iommu(&amba_bustype, &arm_smmu_ops); |
2012 | #endif | ||
1992 | 2013 | ||
1993 | return 0; | 2014 | return 0; |
1994 | } | 2015 | } |