Loading Documentation/devicetree/bindings/iommu/arm,smmu.yaml +2 −0 Original line number Diff line number Diff line Loading @@ -38,10 +38,12 @@ properties: - qcom,sc7280-smmu-500 - qcom,sc8180x-smmu-500 - qcom,sdm845-smmu-500 - qcom,sdx55-smmu-500 - qcom,sm6350-smmu-500 - qcom,sm8150-smmu-500 - qcom,sm8250-smmu-500 - qcom,sm8350-smmu-500 - qcom,sm8450-smmu-500 - const: arm,mmu-500 - description: Qcom Adreno GPUs implementing "arm,smmu-v2" items: Loading drivers/iommu/amd/amd_iommu_types.h +0 −2 Original line number Diff line number Diff line Loading @@ -645,8 +645,6 @@ struct amd_iommu { /* DebugFS Info */ struct dentry *debugfs; #endif /* IRQ notifier for IntCapXT interrupt */ struct irq_affinity_notify intcapxt_notify; }; static inline struct amd_iommu *dev_to_amd_iommu(struct device *dev) Loading drivers/iommu/amd/init.c +59 −50 Original line number Diff line number Diff line Loading @@ -806,16 +806,27 @@ static int iommu_ga_log_enable(struct amd_iommu *iommu) { #ifdef CONFIG_IRQ_REMAP u32 status, i; u64 entry; if (!iommu->ga_log) return -EINVAL; status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); /* Check if already running */ if (status & (MMIO_STATUS_GALOG_RUN_MASK)) status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); if (WARN_ON(status & (MMIO_STATUS_GALOG_RUN_MASK))) return 0; entry = iommu_virt_to_phys(iommu->ga_log) | GA_LOG_SIZE_512; memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_BASE_OFFSET, &entry, sizeof(entry)); entry = (iommu_virt_to_phys(iommu->ga_log_tail) & (BIT_ULL(52)-1)) & ~7ULL; memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_TAIL_OFFSET, &entry, sizeof(entry)); writel(0x00, iommu->mmio_base + MMIO_GA_HEAD_OFFSET); writel(0x00, iommu->mmio_base + MMIO_GA_TAIL_OFFSET); iommu_feature_enable(iommu, CONTROL_GAINT_EN); iommu_feature_enable(iommu, CONTROL_GALOG_EN); Loading @@ -825,7 +836,7 @@ static int iommu_ga_log_enable(struct amd_iommu *iommu) break; } if (i >= LOOP_TIMEOUT) if (WARN_ON(i >= LOOP_TIMEOUT)) return -EINVAL; #endif /* CONFIG_IRQ_REMAP */ return 0; Loading @@ -834,8 +845,6 @@ static int iommu_ga_log_enable(struct amd_iommu *iommu) static int iommu_init_ga_log(struct amd_iommu *iommu) { #ifdef CONFIG_IRQ_REMAP u64 entry; if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir)) return 0; Loading @@ -849,16 +858,6 @@ static int iommu_init_ga_log(struct amd_iommu *iommu) if (!iommu->ga_log_tail) goto err_out; entry = iommu_virt_to_phys(iommu->ga_log) | GA_LOG_SIZE_512; memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_BASE_OFFSET, &entry, sizeof(entry)); entry = (iommu_virt_to_phys(iommu->ga_log_tail) & (BIT_ULL(52)-1)) & ~7ULL; memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_TAIL_OFFSET, &entry, sizeof(entry)); writel(0x00, iommu->mmio_base + MMIO_GA_HEAD_OFFSET); writel(0x00, iommu->mmio_base + MMIO_GA_TAIL_OFFSET); return 0; err_out: free_ga_log(iommu); Loading Loading @@ -1523,7 +1522,7 @@ static void amd_iommu_ats_write_check_workaround(struct amd_iommu *iommu) } /* * This function clues the initialization function for one IOMMU * This function glues the initialization function for one IOMMU * together and also allocates the command buffer and programs the * hardware. It does NOT enable the IOMMU. This is done afterwards. */ Loading Loading @@ -2016,48 +2015,18 @@ union intcapxt { }; } __attribute__ ((packed)); /* * There isn't really any need to mask/unmask at the irqchip level because * the 64-bit INTCAPXT registers can be updated atomically without tearing * when the affinity is being updated. */ static void intcapxt_unmask_irq(struct irq_data *data) { } static void intcapxt_mask_irq(struct irq_data *data) { } static struct irq_chip intcapxt_controller; static int intcapxt_irqdomain_activate(struct irq_domain *domain, struct irq_data *irqd, bool reserve) { struct amd_iommu *iommu = irqd->chip_data; struct irq_cfg *cfg = irqd_cfg(irqd); union intcapxt xt; xt.capxt = 0ULL; xt.dest_mode_logical = apic->dest_mode_logical; xt.vector = cfg->vector; xt.destid_0_23 = cfg->dest_apicid & GENMASK(23, 0); xt.destid_24_31 = cfg->dest_apicid >> 24; /** * Current IOMMU implemtation uses the same IRQ for all * 3 IOMMU interrupts. */ writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_EVT_OFFSET); writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_PPR_OFFSET); writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_GALOG_OFFSET); return 0; } static void intcapxt_irqdomain_deactivate(struct irq_domain *domain, struct irq_data *irqd) { intcapxt_mask_irq(irqd); } Loading Loading @@ -2091,6 +2060,38 @@ static void intcapxt_irqdomain_free(struct irq_domain *domain, unsigned int virq irq_domain_free_irqs_top(domain, virq, nr_irqs); } static void intcapxt_unmask_irq(struct irq_data *irqd) { struct amd_iommu *iommu = irqd->chip_data; struct irq_cfg *cfg = irqd_cfg(irqd); union intcapxt xt; xt.capxt = 0ULL; xt.dest_mode_logical = apic->dest_mode_logical; xt.vector = cfg->vector; xt.destid_0_23 = cfg->dest_apicid & GENMASK(23, 0); xt.destid_24_31 = cfg->dest_apicid >> 24; /** * Current IOMMU implementation uses the same IRQ for all * 3 IOMMU interrupts. */ writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_EVT_OFFSET); writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_PPR_OFFSET); writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_GALOG_OFFSET); } static void intcapxt_mask_irq(struct irq_data *irqd) { struct amd_iommu *iommu = irqd->chip_data; writeq(0, iommu->mmio_base + MMIO_INTCAPXT_EVT_OFFSET); writeq(0, iommu->mmio_base + MMIO_INTCAPXT_PPR_OFFSET); writeq(0, iommu->mmio_base + MMIO_INTCAPXT_GALOG_OFFSET); } static int intcapxt_set_affinity(struct irq_data *irqd, const struct cpumask *mask, bool force) { Loading @@ -2100,8 +2101,12 @@ static int intcapxt_set_affinity(struct irq_data *irqd, ret = parent->chip->irq_set_affinity(parent, mask, force); if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE) return ret; return 0; } return intcapxt_irqdomain_activate(irqd->domain, irqd, false); static int intcapxt_set_wake(struct irq_data *irqd, unsigned int on) { return on ? -EOPNOTSUPP : 0; } static struct irq_chip intcapxt_controller = { Loading @@ -2111,7 +2116,8 @@ static struct irq_chip intcapxt_controller = { .irq_ack = irq_chip_ack_parent, .irq_retrigger = irq_chip_retrigger_hierarchy, .irq_set_affinity = intcapxt_set_affinity, .flags = IRQCHIP_SKIP_SET_WAKE, .irq_set_wake = intcapxt_set_wake, .flags = IRQCHIP_MASK_ON_SUSPEND, }; static const struct irq_domain_ops intcapxt_domain_ops = { Loading Loading @@ -2173,7 +2179,6 @@ static int iommu_setup_intcapxt(struct amd_iommu *iommu) return ret; } iommu_feature_enable(iommu, CONTROL_INTCAPXT_EN); return 0; } Loading @@ -2196,6 +2201,10 @@ static int iommu_init_irq(struct amd_iommu *iommu) iommu->int_enabled = true; enable_faults: if (amd_iommu_xt_mode == IRQ_REMAP_X2APIC_MODE) iommu_feature_enable(iommu, CONTROL_INTCAPXT_EN); iommu_feature_enable(iommu, CONTROL_EVT_INT_EN); if (iommu->ppr_log != NULL) Loading drivers/iommu/amd/io_pgtable.c +41 −69 Original line number Diff line number Diff line Loading @@ -74,87 +74,61 @@ static u64 *first_pte_l7(u64 *pte, unsigned long *page_size, * ****************************************************************************/ static void free_page_list(struct page *freelist) static void free_pt_page(u64 *pt, struct list_head *freelist) { while (freelist != NULL) { unsigned long p = (unsigned long)page_address(freelist); struct page *p = virt_to_page(pt); freelist = freelist->freelist; free_page(p); } list_add_tail(&p->lru, freelist); } static struct page *free_pt_page(unsigned long pt, struct page *freelist) static void free_pt_lvl(u64 *pt, struct list_head *freelist, int lvl) { struct page *p = virt_to_page((void *)pt); u64 *p; int i; p->freelist = freelist; for (i = 0; i < 512; ++i) { /* PTE present? */ if (!IOMMU_PTE_PRESENT(pt[i])) continue; return p; } /* Large PTE? */ if (PM_PTE_LEVEL(pt[i]) == 0 || PM_PTE_LEVEL(pt[i]) == 7) continue; #define DEFINE_FREE_PT_FN(LVL, FN) \ static struct page *free_pt_##LVL (unsigned long __pt, struct page *freelist) \ { \ unsigned long p; \ u64 *pt; \ int i; \ \ pt = (u64 *)__pt; \ \ for (i = 0; i < 512; ++i) { \ /* PTE present? */ \ if (!IOMMU_PTE_PRESENT(pt[i])) \ continue; \ \ /* Large PTE? */ \ if (PM_PTE_LEVEL(pt[i]) == 0 || \ PM_PTE_LEVEL(pt[i]) == 7) \ continue; \ \ p = (unsigned long)IOMMU_PTE_PAGE(pt[i]); \ freelist = FN(p, freelist); \ } \ \ return free_pt_page((unsigned long)pt, freelist); \ /* * Free the next level. No need to look at l1 tables here since * they can only contain leaf PTEs; just free them directly. */ p = IOMMU_PTE_PAGE(pt[i]); if (lvl > 2) free_pt_lvl(p, freelist, lvl - 1); else free_pt_page(p, freelist); } DEFINE_FREE_PT_FN(l2, free_pt_page) DEFINE_FREE_PT_FN(l3, free_pt_l2) DEFINE_FREE_PT_FN(l4, free_pt_l3) DEFINE_FREE_PT_FN(l5, free_pt_l4) DEFINE_FREE_PT_FN(l6, free_pt_l5) free_pt_page(pt, freelist); } static struct page *free_sub_pt(unsigned long root, int mode, struct page *freelist) static void free_sub_pt(u64 *root, int mode, struct list_head *freelist) { switch (mode) { case PAGE_MODE_NONE: case PAGE_MODE_7_LEVEL: break; case PAGE_MODE_1_LEVEL: freelist = free_pt_page(root, freelist); free_pt_page(root, freelist); break; case PAGE_MODE_2_LEVEL: freelist = free_pt_l2(root, freelist); break; case PAGE_MODE_3_LEVEL: freelist = free_pt_l3(root, freelist); break; case PAGE_MODE_4_LEVEL: freelist = free_pt_l4(root, freelist); break; case PAGE_MODE_5_LEVEL: freelist = free_pt_l5(root, freelist); break; case PAGE_MODE_6_LEVEL: freelist = free_pt_l6(root, freelist); free_pt_lvl(root, freelist, mode); break; default: BUG(); } return freelist; } void amd_iommu_domain_set_pgtable(struct protection_domain *domain, Loading Loading @@ -362,9 +336,9 @@ static u64 *fetch_pte(struct amd_io_pgtable *pgtable, return pte; } static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist) static void free_clear_pte(u64 *pte, u64 pteval, struct list_head *freelist) { unsigned long pt; u64 *pt; int mode; while (cmpxchg64(pte, pteval, 0) != pteval) { Loading @@ -373,12 +347,12 @@ static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist) } if (!IOMMU_PTE_PRESENT(pteval)) return freelist; return; pt = (unsigned long)IOMMU_PTE_PAGE(pteval); pt = IOMMU_PTE_PAGE(pteval); mode = IOMMU_PTE_MODE(pteval); return free_sub_pt(pt, mode, freelist); free_sub_pt(pt, mode, freelist); } /* Loading @@ -392,7 +366,7 @@ static int iommu_v1_map_page(struct io_pgtable_ops *ops, unsigned long iova, phys_addr_t paddr, size_t size, int prot, gfp_t gfp) { struct protection_domain *dom = io_pgtable_ops_to_domain(ops); struct page *freelist = NULL; LIST_HEAD(freelist); bool updated = false; u64 __pte, *pte; int ret, i, count; Loading @@ -412,9 +386,9 @@ static int iommu_v1_map_page(struct io_pgtable_ops *ops, unsigned long iova, goto out; for (i = 0; i < count; ++i) freelist = free_clear_pte(&pte[i], pte[i], freelist); free_clear_pte(&pte[i], pte[i], &freelist); if (freelist != NULL) if (!list_empty(&freelist)) updated = true; if (count > 1) { Loading Loading @@ -449,7 +423,7 @@ static int iommu_v1_map_page(struct io_pgtable_ops *ops, unsigned long iova, } /* Everything flushed out, free pages now */ free_page_list(freelist); put_pages_list(&freelist); return ret; } Loading Loading @@ -511,8 +485,7 @@ static void v1_free_pgtable(struct io_pgtable *iop) { struct amd_io_pgtable *pgtable = container_of(iop, struct amd_io_pgtable, iop); struct protection_domain *dom; struct page *freelist = NULL; unsigned long root; LIST_HEAD(freelist); if (pgtable->mode == PAGE_MODE_NONE) return; Loading @@ -529,10 +502,9 @@ static void v1_free_pgtable(struct io_pgtable *iop) BUG_ON(pgtable->mode < PAGE_MODE_NONE || pgtable->mode > PAGE_MODE_6_LEVEL); root = (unsigned long)pgtable->root; freelist = free_sub_pt(root, pgtable->mode, freelist); free_sub_pt(pgtable->root, pgtable->mode, &freelist); free_page_list(freelist); put_pages_list(&freelist); } static struct io_pgtable *v1_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie) Loading drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c +1 −1 Original line number Diff line number Diff line Loading @@ -220,7 +220,7 @@ static void arm_smmu_mmu_notifier_free(struct mmu_notifier *mn) kfree(mn_to_smmu(mn)); } static struct mmu_notifier_ops arm_smmu_mmu_notifier_ops = { static const struct mmu_notifier_ops arm_smmu_mmu_notifier_ops = { .invalidate_range = arm_smmu_mm_invalidate_range, .release = arm_smmu_mm_release, .free_notifier = arm_smmu_mmu_notifier_free, Loading Loading
Documentation/devicetree/bindings/iommu/arm,smmu.yaml +2 −0 Original line number Diff line number Diff line Loading @@ -38,10 +38,12 @@ properties: - qcom,sc7280-smmu-500 - qcom,sc8180x-smmu-500 - qcom,sdm845-smmu-500 - qcom,sdx55-smmu-500 - qcom,sm6350-smmu-500 - qcom,sm8150-smmu-500 - qcom,sm8250-smmu-500 - qcom,sm8350-smmu-500 - qcom,sm8450-smmu-500 - const: arm,mmu-500 - description: Qcom Adreno GPUs implementing "arm,smmu-v2" items: Loading
drivers/iommu/amd/amd_iommu_types.h +0 −2 Original line number Diff line number Diff line Loading @@ -645,8 +645,6 @@ struct amd_iommu { /* DebugFS Info */ struct dentry *debugfs; #endif /* IRQ notifier for IntCapXT interrupt */ struct irq_affinity_notify intcapxt_notify; }; static inline struct amd_iommu *dev_to_amd_iommu(struct device *dev) Loading
drivers/iommu/amd/init.c +59 −50 Original line number Diff line number Diff line Loading @@ -806,16 +806,27 @@ static int iommu_ga_log_enable(struct amd_iommu *iommu) { #ifdef CONFIG_IRQ_REMAP u32 status, i; u64 entry; if (!iommu->ga_log) return -EINVAL; status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); /* Check if already running */ if (status & (MMIO_STATUS_GALOG_RUN_MASK)) status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); if (WARN_ON(status & (MMIO_STATUS_GALOG_RUN_MASK))) return 0; entry = iommu_virt_to_phys(iommu->ga_log) | GA_LOG_SIZE_512; memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_BASE_OFFSET, &entry, sizeof(entry)); entry = (iommu_virt_to_phys(iommu->ga_log_tail) & (BIT_ULL(52)-1)) & ~7ULL; memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_TAIL_OFFSET, &entry, sizeof(entry)); writel(0x00, iommu->mmio_base + MMIO_GA_HEAD_OFFSET); writel(0x00, iommu->mmio_base + MMIO_GA_TAIL_OFFSET); iommu_feature_enable(iommu, CONTROL_GAINT_EN); iommu_feature_enable(iommu, CONTROL_GALOG_EN); Loading @@ -825,7 +836,7 @@ static int iommu_ga_log_enable(struct amd_iommu *iommu) break; } if (i >= LOOP_TIMEOUT) if (WARN_ON(i >= LOOP_TIMEOUT)) return -EINVAL; #endif /* CONFIG_IRQ_REMAP */ return 0; Loading @@ -834,8 +845,6 @@ static int iommu_ga_log_enable(struct amd_iommu *iommu) static int iommu_init_ga_log(struct amd_iommu *iommu) { #ifdef CONFIG_IRQ_REMAP u64 entry; if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir)) return 0; Loading @@ -849,16 +858,6 @@ static int iommu_init_ga_log(struct amd_iommu *iommu) if (!iommu->ga_log_tail) goto err_out; entry = iommu_virt_to_phys(iommu->ga_log) | GA_LOG_SIZE_512; memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_BASE_OFFSET, &entry, sizeof(entry)); entry = (iommu_virt_to_phys(iommu->ga_log_tail) & (BIT_ULL(52)-1)) & ~7ULL; memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_TAIL_OFFSET, &entry, sizeof(entry)); writel(0x00, iommu->mmio_base + MMIO_GA_HEAD_OFFSET); writel(0x00, iommu->mmio_base + MMIO_GA_TAIL_OFFSET); return 0; err_out: free_ga_log(iommu); Loading Loading @@ -1523,7 +1522,7 @@ static void amd_iommu_ats_write_check_workaround(struct amd_iommu *iommu) } /* * This function clues the initialization function for one IOMMU * This function glues the initialization function for one IOMMU * together and also allocates the command buffer and programs the * hardware. It does NOT enable the IOMMU. This is done afterwards. */ Loading Loading @@ -2016,48 +2015,18 @@ union intcapxt { }; } __attribute__ ((packed)); /* * There isn't really any need to mask/unmask at the irqchip level because * the 64-bit INTCAPXT registers can be updated atomically without tearing * when the affinity is being updated. */ static void intcapxt_unmask_irq(struct irq_data *data) { } static void intcapxt_mask_irq(struct irq_data *data) { } static struct irq_chip intcapxt_controller; static int intcapxt_irqdomain_activate(struct irq_domain *domain, struct irq_data *irqd, bool reserve) { struct amd_iommu *iommu = irqd->chip_data; struct irq_cfg *cfg = irqd_cfg(irqd); union intcapxt xt; xt.capxt = 0ULL; xt.dest_mode_logical = apic->dest_mode_logical; xt.vector = cfg->vector; xt.destid_0_23 = cfg->dest_apicid & GENMASK(23, 0); xt.destid_24_31 = cfg->dest_apicid >> 24; /** * Current IOMMU implemtation uses the same IRQ for all * 3 IOMMU interrupts. */ writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_EVT_OFFSET); writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_PPR_OFFSET); writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_GALOG_OFFSET); return 0; } static void intcapxt_irqdomain_deactivate(struct irq_domain *domain, struct irq_data *irqd) { intcapxt_mask_irq(irqd); } Loading Loading @@ -2091,6 +2060,38 @@ static void intcapxt_irqdomain_free(struct irq_domain *domain, unsigned int virq irq_domain_free_irqs_top(domain, virq, nr_irqs); } static void intcapxt_unmask_irq(struct irq_data *irqd) { struct amd_iommu *iommu = irqd->chip_data; struct irq_cfg *cfg = irqd_cfg(irqd); union intcapxt xt; xt.capxt = 0ULL; xt.dest_mode_logical = apic->dest_mode_logical; xt.vector = cfg->vector; xt.destid_0_23 = cfg->dest_apicid & GENMASK(23, 0); xt.destid_24_31 = cfg->dest_apicid >> 24; /** * Current IOMMU implementation uses the same IRQ for all * 3 IOMMU interrupts. */ writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_EVT_OFFSET); writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_PPR_OFFSET); writeq(xt.capxt, iommu->mmio_base + MMIO_INTCAPXT_GALOG_OFFSET); } static void intcapxt_mask_irq(struct irq_data *irqd) { struct amd_iommu *iommu = irqd->chip_data; writeq(0, iommu->mmio_base + MMIO_INTCAPXT_EVT_OFFSET); writeq(0, iommu->mmio_base + MMIO_INTCAPXT_PPR_OFFSET); writeq(0, iommu->mmio_base + MMIO_INTCAPXT_GALOG_OFFSET); } static int intcapxt_set_affinity(struct irq_data *irqd, const struct cpumask *mask, bool force) { Loading @@ -2100,8 +2101,12 @@ static int intcapxt_set_affinity(struct irq_data *irqd, ret = parent->chip->irq_set_affinity(parent, mask, force); if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE) return ret; return 0; } return intcapxt_irqdomain_activate(irqd->domain, irqd, false); static int intcapxt_set_wake(struct irq_data *irqd, unsigned int on) { return on ? -EOPNOTSUPP : 0; } static struct irq_chip intcapxt_controller = { Loading @@ -2111,7 +2116,8 @@ static struct irq_chip intcapxt_controller = { .irq_ack = irq_chip_ack_parent, .irq_retrigger = irq_chip_retrigger_hierarchy, .irq_set_affinity = intcapxt_set_affinity, .flags = IRQCHIP_SKIP_SET_WAKE, .irq_set_wake = intcapxt_set_wake, .flags = IRQCHIP_MASK_ON_SUSPEND, }; static const struct irq_domain_ops intcapxt_domain_ops = { Loading Loading @@ -2173,7 +2179,6 @@ static int iommu_setup_intcapxt(struct amd_iommu *iommu) return ret; } iommu_feature_enable(iommu, CONTROL_INTCAPXT_EN); return 0; } Loading @@ -2196,6 +2201,10 @@ static int iommu_init_irq(struct amd_iommu *iommu) iommu->int_enabled = true; enable_faults: if (amd_iommu_xt_mode == IRQ_REMAP_X2APIC_MODE) iommu_feature_enable(iommu, CONTROL_INTCAPXT_EN); iommu_feature_enable(iommu, CONTROL_EVT_INT_EN); if (iommu->ppr_log != NULL) Loading
drivers/iommu/amd/io_pgtable.c +41 −69 Original line number Diff line number Diff line Loading @@ -74,87 +74,61 @@ static u64 *first_pte_l7(u64 *pte, unsigned long *page_size, * ****************************************************************************/ static void free_page_list(struct page *freelist) static void free_pt_page(u64 *pt, struct list_head *freelist) { while (freelist != NULL) { unsigned long p = (unsigned long)page_address(freelist); struct page *p = virt_to_page(pt); freelist = freelist->freelist; free_page(p); } list_add_tail(&p->lru, freelist); } static struct page *free_pt_page(unsigned long pt, struct page *freelist) static void free_pt_lvl(u64 *pt, struct list_head *freelist, int lvl) { struct page *p = virt_to_page((void *)pt); u64 *p; int i; p->freelist = freelist; for (i = 0; i < 512; ++i) { /* PTE present? */ if (!IOMMU_PTE_PRESENT(pt[i])) continue; return p; } /* Large PTE? */ if (PM_PTE_LEVEL(pt[i]) == 0 || PM_PTE_LEVEL(pt[i]) == 7) continue; #define DEFINE_FREE_PT_FN(LVL, FN) \ static struct page *free_pt_##LVL (unsigned long __pt, struct page *freelist) \ { \ unsigned long p; \ u64 *pt; \ int i; \ \ pt = (u64 *)__pt; \ \ for (i = 0; i < 512; ++i) { \ /* PTE present? */ \ if (!IOMMU_PTE_PRESENT(pt[i])) \ continue; \ \ /* Large PTE? */ \ if (PM_PTE_LEVEL(pt[i]) == 0 || \ PM_PTE_LEVEL(pt[i]) == 7) \ continue; \ \ p = (unsigned long)IOMMU_PTE_PAGE(pt[i]); \ freelist = FN(p, freelist); \ } \ \ return free_pt_page((unsigned long)pt, freelist); \ /* * Free the next level. No need to look at l1 tables here since * they can only contain leaf PTEs; just free them directly. */ p = IOMMU_PTE_PAGE(pt[i]); if (lvl > 2) free_pt_lvl(p, freelist, lvl - 1); else free_pt_page(p, freelist); } DEFINE_FREE_PT_FN(l2, free_pt_page) DEFINE_FREE_PT_FN(l3, free_pt_l2) DEFINE_FREE_PT_FN(l4, free_pt_l3) DEFINE_FREE_PT_FN(l5, free_pt_l4) DEFINE_FREE_PT_FN(l6, free_pt_l5) free_pt_page(pt, freelist); } static struct page *free_sub_pt(unsigned long root, int mode, struct page *freelist) static void free_sub_pt(u64 *root, int mode, struct list_head *freelist) { switch (mode) { case PAGE_MODE_NONE: case PAGE_MODE_7_LEVEL: break; case PAGE_MODE_1_LEVEL: freelist = free_pt_page(root, freelist); free_pt_page(root, freelist); break; case PAGE_MODE_2_LEVEL: freelist = free_pt_l2(root, freelist); break; case PAGE_MODE_3_LEVEL: freelist = free_pt_l3(root, freelist); break; case PAGE_MODE_4_LEVEL: freelist = free_pt_l4(root, freelist); break; case PAGE_MODE_5_LEVEL: freelist = free_pt_l5(root, freelist); break; case PAGE_MODE_6_LEVEL: freelist = free_pt_l6(root, freelist); free_pt_lvl(root, freelist, mode); break; default: BUG(); } return freelist; } void amd_iommu_domain_set_pgtable(struct protection_domain *domain, Loading Loading @@ -362,9 +336,9 @@ static u64 *fetch_pte(struct amd_io_pgtable *pgtable, return pte; } static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist) static void free_clear_pte(u64 *pte, u64 pteval, struct list_head *freelist) { unsigned long pt; u64 *pt; int mode; while (cmpxchg64(pte, pteval, 0) != pteval) { Loading @@ -373,12 +347,12 @@ static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist) } if (!IOMMU_PTE_PRESENT(pteval)) return freelist; return; pt = (unsigned long)IOMMU_PTE_PAGE(pteval); pt = IOMMU_PTE_PAGE(pteval); mode = IOMMU_PTE_MODE(pteval); return free_sub_pt(pt, mode, freelist); free_sub_pt(pt, mode, freelist); } /* Loading @@ -392,7 +366,7 @@ static int iommu_v1_map_page(struct io_pgtable_ops *ops, unsigned long iova, phys_addr_t paddr, size_t size, int prot, gfp_t gfp) { struct protection_domain *dom = io_pgtable_ops_to_domain(ops); struct page *freelist = NULL; LIST_HEAD(freelist); bool updated = false; u64 __pte, *pte; int ret, i, count; Loading @@ -412,9 +386,9 @@ static int iommu_v1_map_page(struct io_pgtable_ops *ops, unsigned long iova, goto out; for (i = 0; i < count; ++i) freelist = free_clear_pte(&pte[i], pte[i], freelist); free_clear_pte(&pte[i], pte[i], &freelist); if (freelist != NULL) if (!list_empty(&freelist)) updated = true; if (count > 1) { Loading Loading @@ -449,7 +423,7 @@ static int iommu_v1_map_page(struct io_pgtable_ops *ops, unsigned long iova, } /* Everything flushed out, free pages now */ free_page_list(freelist); put_pages_list(&freelist); return ret; } Loading Loading @@ -511,8 +485,7 @@ static void v1_free_pgtable(struct io_pgtable *iop) { struct amd_io_pgtable *pgtable = container_of(iop, struct amd_io_pgtable, iop); struct protection_domain *dom; struct page *freelist = NULL; unsigned long root; LIST_HEAD(freelist); if (pgtable->mode == PAGE_MODE_NONE) return; Loading @@ -529,10 +502,9 @@ static void v1_free_pgtable(struct io_pgtable *iop) BUG_ON(pgtable->mode < PAGE_MODE_NONE || pgtable->mode > PAGE_MODE_6_LEVEL); root = (unsigned long)pgtable->root; freelist = free_sub_pt(root, pgtable->mode, freelist); free_sub_pt(pgtable->root, pgtable->mode, &freelist); free_page_list(freelist); put_pages_list(&freelist); } static struct io_pgtable *v1_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie) Loading
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c +1 −1 Original line number Diff line number Diff line Loading @@ -220,7 +220,7 @@ static void arm_smmu_mmu_notifier_free(struct mmu_notifier *mn) kfree(mn_to_smmu(mn)); } static struct mmu_notifier_ops arm_smmu_mmu_notifier_ops = { static const struct mmu_notifier_ops arm_smmu_mmu_notifier_ops = { .invalidate_range = arm_smmu_mm_invalidate_range, .release = arm_smmu_mm_release, .free_notifier = arm_smmu_mmu_notifier_free, Loading