aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/iommu/arm-smmu.c110
1 files changed, 90 insertions, 20 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 217581469f79..7a80f710ba2d 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -404,9 +404,16 @@ struct arm_smmu_cfg {
404#define ARM_SMMU_CB_ASID(cfg) ((cfg)->cbndx) 404#define ARM_SMMU_CB_ASID(cfg) ((cfg)->cbndx)
405#define ARM_SMMU_CB_VMID(cfg) ((cfg)->cbndx + 1) 405#define ARM_SMMU_CB_VMID(cfg) ((cfg)->cbndx + 1)
406 406
407enum arm_smmu_domain_stage {
408 ARM_SMMU_DOMAIN_S1 = 0,
409 ARM_SMMU_DOMAIN_S2,
410 ARM_SMMU_DOMAIN_NESTED,
411};
412
407struct arm_smmu_domain { 413struct arm_smmu_domain {
408 struct arm_smmu_device *smmu; 414 struct arm_smmu_device *smmu;
409 struct arm_smmu_cfg cfg; 415 struct arm_smmu_cfg cfg;
416 enum arm_smmu_domain_stage stage;
410 spinlock_t lock; 417 spinlock_t lock;
411}; 418};
412 419
@@ -906,19 +913,46 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
906 if (smmu_domain->smmu) 913 if (smmu_domain->smmu)
907 goto out_unlock; 914 goto out_unlock;
908 915
909 if (smmu->features & ARM_SMMU_FEAT_TRANS_NESTED) { 916 /*
917 * Mapping the requested stage onto what we support is surprisingly
918 * complicated, mainly because the spec allows S1+S2 SMMUs without
919 * support for nested translation. That means we end up with the
920 * following table:
921 *
922 * Requested Supported Actual
923 * S1 N S1
924 * S1 S1+S2 S1
925 * S1 S2 S2
926 * S1 S1 S1
927 * N N N
928 * N S1+S2 S2
929 * N S2 S2
930 * N S1 S1
931 *
932 * Note that you can't actually request stage-2 mappings.
933 */
934 if (!(smmu->features & ARM_SMMU_FEAT_TRANS_S1))
935 smmu_domain->stage = ARM_SMMU_DOMAIN_S2;
936 if (!(smmu->features & ARM_SMMU_FEAT_TRANS_S2))
937 smmu_domain->stage = ARM_SMMU_DOMAIN_S1;
938
939 switch (smmu_domain->stage) {
940 case ARM_SMMU_DOMAIN_S1:
941 cfg->cbar = CBAR_TYPE_S1_TRANS_S2_BYPASS;
942 start = smmu->num_s2_context_banks;
943 break;
944 case ARM_SMMU_DOMAIN_NESTED:
910 /* 945 /*
911 * We will likely want to change this if/when KVM gets 946 * We will likely want to change this if/when KVM gets
912 * involved. 947 * involved.
913 */ 948 */
914 cfg->cbar = CBAR_TYPE_S1_TRANS_S2_BYPASS; 949 case ARM_SMMU_DOMAIN_S2:
915 start = smmu->num_s2_context_banks;
916 } else if (smmu->features & ARM_SMMU_FEAT_TRANS_S1) {
917 cfg->cbar = CBAR_TYPE_S1_TRANS_S2_BYPASS;
918 start = smmu->num_s2_context_banks;
919 } else {
920 cfg->cbar = CBAR_TYPE_S2_TRANS; 950 cfg->cbar = CBAR_TYPE_S2_TRANS;
921 start = 0; 951 start = 0;
952 break;
953 default:
954 ret = -EINVAL;
955 goto out_unlock;
922 } 956 }
923 957
924 ret = __arm_smmu_alloc_bitmap(smmu->context_map, start, 958 ret = __arm_smmu_alloc_bitmap(smmu->context_map, start,
@@ -1647,20 +1681,56 @@ static void arm_smmu_remove_device(struct device *dev)
1647 iommu_group_remove_device(dev); 1681 iommu_group_remove_device(dev);
1648} 1682}
1649 1683
1684static int arm_smmu_domain_get_attr(struct iommu_domain *domain,
1685 enum iommu_attr attr, void *data)
1686{
1687 struct arm_smmu_domain *smmu_domain = domain->priv;
1688
1689 switch (attr) {
1690 case DOMAIN_ATTR_NESTING:
1691 *(int *)data = (smmu_domain->stage == ARM_SMMU_DOMAIN_NESTED);
1692 return 0;
1693 default:
1694 return -ENODEV;
1695 }
1696}
1697
1698static int arm_smmu_domain_set_attr(struct iommu_domain *domain,
1699 enum iommu_attr attr, void *data)
1700{
1701 struct arm_smmu_domain *smmu_domain = domain->priv;
1702
1703 switch (attr) {
1704 case DOMAIN_ATTR_NESTING:
1705 if (smmu_domain->smmu)
1706 return -EPERM;
1707 if (*(int *)data)
1708 smmu_domain->stage = ARM_SMMU_DOMAIN_NESTED;
1709 else
1710 smmu_domain->stage = ARM_SMMU_DOMAIN_S1;
1711
1712 return 0;
1713 default:
1714 return -ENODEV;
1715 }
1716}
1717
1650static const struct iommu_ops arm_smmu_ops = { 1718static const struct iommu_ops arm_smmu_ops = {
1651 .capable = arm_smmu_capable, 1719 .capable = arm_smmu_capable,
1652 .domain_init = arm_smmu_domain_init, 1720 .domain_init = arm_smmu_domain_init,
1653 .domain_destroy = arm_smmu_domain_destroy, 1721 .domain_destroy = arm_smmu_domain_destroy,
1654 .attach_dev = arm_smmu_attach_dev, 1722 .attach_dev = arm_smmu_attach_dev,
1655 .detach_dev = arm_smmu_detach_dev, 1723 .detach_dev = arm_smmu_detach_dev,
1656 .map = arm_smmu_map, 1724 .map = arm_smmu_map,
1657 .unmap = arm_smmu_unmap, 1725 .unmap = arm_smmu_unmap,
1658 .iova_to_phys = arm_smmu_iova_to_phys, 1726 .iova_to_phys = arm_smmu_iova_to_phys,
1659 .add_device = arm_smmu_add_device, 1727 .add_device = arm_smmu_add_device,
1660 .remove_device = arm_smmu_remove_device, 1728 .remove_device = arm_smmu_remove_device,
1661 .pgsize_bitmap = (SECTION_SIZE | 1729 .domain_get_attr = arm_smmu_domain_get_attr,
1662 ARM_SMMU_PTE_CONT_SIZE | 1730 .domain_set_attr = arm_smmu_domain_set_attr,
1663 PAGE_SIZE), 1731 .pgsize_bitmap = (SECTION_SIZE |
1732 ARM_SMMU_PTE_CONT_SIZE |
1733 PAGE_SIZE),
1664}; 1734};
1665 1735
1666static void arm_smmu_device_reset(struct arm_smmu_device *smmu) 1736static void arm_smmu_device_reset(struct arm_smmu_device *smmu)