diff options
| -rw-r--r-- | drivers/iommu/arm-smmu.c | 33 | ||||
| -rw-r--r-- | include/linux/iommu.h | 7 |
2 files changed, 30 insertions, 10 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index e46a88700b68..8911850c9444 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | * - v7/v8 long-descriptor format | 24 | * - v7/v8 long-descriptor format |
| 25 | * - Non-secure access to the SMMU | 25 | * - Non-secure access to the SMMU |
| 26 | * - 4k and 64k pages, with contiguous pte hints. | 26 | * - 4k and 64k pages, with contiguous pte hints. |
| 27 | * - Up to 39-bit addressing | 27 | * - Up to 42-bit addressing (dependent on VA_BITS) |
| 28 | * - Context fault reporting | 28 | * - Context fault reporting |
| 29 | */ | 29 | */ |
| 30 | 30 | ||
| @@ -61,12 +61,13 @@ | |||
| 61 | #define ARM_SMMU_GR1(smmu) ((smmu)->base + (smmu)->pagesize) | 61 | #define ARM_SMMU_GR1(smmu) ((smmu)->base + (smmu)->pagesize) |
| 62 | 62 | ||
| 63 | /* Page table bits */ | 63 | /* Page table bits */ |
| 64 | #define ARM_SMMU_PTE_PAGE (((pteval_t)3) << 0) | 64 | #define ARM_SMMU_PTE_XN (((pteval_t)3) << 53) |
| 65 | #define ARM_SMMU_PTE_CONT (((pteval_t)1) << 52) | 65 | #define ARM_SMMU_PTE_CONT (((pteval_t)1) << 52) |
| 66 | #define ARM_SMMU_PTE_AF (((pteval_t)1) << 10) | 66 | #define ARM_SMMU_PTE_AF (((pteval_t)1) << 10) |
| 67 | #define ARM_SMMU_PTE_SH_NS (((pteval_t)0) << 8) | 67 | #define ARM_SMMU_PTE_SH_NS (((pteval_t)0) << 8) |
| 68 | #define ARM_SMMU_PTE_SH_OS (((pteval_t)2) << 8) | 68 | #define ARM_SMMU_PTE_SH_OS (((pteval_t)2) << 8) |
| 69 | #define ARM_SMMU_PTE_SH_IS (((pteval_t)3) << 8) | 69 | #define ARM_SMMU_PTE_SH_IS (((pteval_t)3) << 8) |
| 70 | #define ARM_SMMU_PTE_PAGE (((pteval_t)3) << 0) | ||
| 70 | 71 | ||
| 71 | #if PAGE_SIZE == SZ_4K | 72 | #if PAGE_SIZE == SZ_4K |
| 72 | #define ARM_SMMU_PTE_CONT_ENTRIES 16 | 73 | #define ARM_SMMU_PTE_CONT_ENTRIES 16 |
| @@ -1205,7 +1206,7 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd, | |||
| 1205 | unsigned long pfn, int flags, int stage) | 1206 | unsigned long pfn, int flags, int stage) |
| 1206 | { | 1207 | { |
| 1207 | pte_t *pte, *start; | 1208 | pte_t *pte, *start; |
| 1208 | pteval_t pteval = ARM_SMMU_PTE_PAGE | ARM_SMMU_PTE_AF; | 1209 | pteval_t pteval = ARM_SMMU_PTE_PAGE | ARM_SMMU_PTE_AF | ARM_SMMU_PTE_XN; |
| 1209 | 1210 | ||
| 1210 | if (pmd_none(*pmd)) { | 1211 | if (pmd_none(*pmd)) { |
| 1211 | /* Allocate a new set of tables */ | 1212 | /* Allocate a new set of tables */ |
| @@ -1244,7 +1245,9 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd, | |||
| 1244 | } | 1245 | } |
| 1245 | 1246 | ||
| 1246 | /* If no access, create a faulting entry to avoid TLB fills */ | 1247 | /* If no access, create a faulting entry to avoid TLB fills */ |
| 1247 | if (!(flags & (IOMMU_READ | IOMMU_WRITE))) | 1248 | if (flags & IOMMU_EXEC) |
| 1249 | pteval &= ~ARM_SMMU_PTE_XN; | ||
| 1250 | else if (!(flags & (IOMMU_READ | IOMMU_WRITE))) | ||
| 1248 | pteval &= ~ARM_SMMU_PTE_PAGE; | 1251 | pteval &= ~ARM_SMMU_PTE_PAGE; |
| 1249 | 1252 | ||
| 1250 | pteval |= ARM_SMMU_PTE_SH_IS; | 1253 | pteval |= ARM_SMMU_PTE_SH_IS; |
| @@ -1494,6 +1497,13 @@ static int arm_smmu_add_device(struct device *dev) | |||
| 1494 | { | 1497 | { |
| 1495 | struct arm_smmu_device *child, *parent, *smmu; | 1498 | struct arm_smmu_device *child, *parent, *smmu; |
| 1496 | struct arm_smmu_master *master = NULL; | 1499 | struct arm_smmu_master *master = NULL; |
| 1500 | struct iommu_group *group; | ||
| 1501 | int ret; | ||
| 1502 | |||
| 1503 | if (dev->archdata.iommu) { | ||
| 1504 | dev_warn(dev, "IOMMU driver already assigned to device\n"); | ||
| 1505 | return -EINVAL; | ||
| 1506 | } | ||
| 1497 | 1507 | ||
| 1498 | spin_lock(&arm_smmu_devices_lock); | 1508 | spin_lock(&arm_smmu_devices_lock); |
| 1499 | list_for_each_entry(parent, &arm_smmu_devices, list) { | 1509 | list_for_each_entry(parent, &arm_smmu_devices, list) { |
| @@ -1526,13 +1536,23 @@ static int arm_smmu_add_device(struct device *dev) | |||
| 1526 | if (!master) | 1536 | if (!master) |
| 1527 | return -ENODEV; | 1537 | return -ENODEV; |
| 1528 | 1538 | ||
| 1539 | group = iommu_group_alloc(); | ||
| 1540 | if (IS_ERR(group)) { | ||
| 1541 | dev_err(dev, "Failed to allocate IOMMU group\n"); | ||
| 1542 | return PTR_ERR(group); | ||
| 1543 | } | ||
| 1544 | |||
| 1545 | ret = iommu_group_add_device(group, dev); | ||
| 1546 | iommu_group_put(group); | ||
| 1529 | dev->archdata.iommu = smmu; | 1547 | dev->archdata.iommu = smmu; |
| 1530 | return 0; | 1548 | |
| 1549 | return ret; | ||
| 1531 | } | 1550 | } |
| 1532 | 1551 | ||
| 1533 | static void arm_smmu_remove_device(struct device *dev) | 1552 | static void arm_smmu_remove_device(struct device *dev) |
| 1534 | { | 1553 | { |
| 1535 | dev->archdata.iommu = NULL; | 1554 | dev->archdata.iommu = NULL; |
| 1555 | iommu_group_remove_device(dev); | ||
| 1536 | } | 1556 | } |
| 1537 | 1557 | ||
| 1538 | static struct iommu_ops arm_smmu_ops = { | 1558 | static struct iommu_ops arm_smmu_ops = { |
| @@ -1730,7 +1750,6 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) | |||
| 1730 | * allocation (PTRS_PER_PGD). | 1750 | * allocation (PTRS_PER_PGD). |
| 1731 | */ | 1751 | */ |
| 1732 | #ifdef CONFIG_64BIT | 1752 | #ifdef CONFIG_64BIT |
| 1733 | /* Current maximum output size of 39 bits */ | ||
| 1734 | smmu->s1_output_size = min(39UL, size); | 1753 | smmu->s1_output_size = min(39UL, size); |
| 1735 | #else | 1754 | #else |
| 1736 | smmu->s1_output_size = min(32UL, size); | 1755 | smmu->s1_output_size = min(32UL, size); |
| @@ -1745,7 +1764,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) | |||
| 1745 | } else { | 1764 | } else { |
| 1746 | #ifdef CONFIG_64BIT | 1765 | #ifdef CONFIG_64BIT |
| 1747 | size = (id >> ID2_UBS_SHIFT) & ID2_UBS_MASK; | 1766 | size = (id >> ID2_UBS_SHIFT) & ID2_UBS_MASK; |
| 1748 | size = min(39, arm_smmu_id_size_to_bits(size)); | 1767 | size = min(VA_BITS, arm_smmu_id_size_to_bits(size)); |
| 1749 | #else | 1768 | #else |
| 1750 | size = 32; | 1769 | size = 32; |
| 1751 | #endif | 1770 | #endif |
diff --git a/include/linux/iommu.h b/include/linux/iommu.h index a444c790fa72..709a697c4e02 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h | |||
| @@ -24,9 +24,10 @@ | |||
| 24 | #include <linux/types.h> | 24 | #include <linux/types.h> |
| 25 | #include <trace/events/iommu.h> | 25 | #include <trace/events/iommu.h> |
| 26 | 26 | ||
| 27 | #define IOMMU_READ (1) | 27 | #define IOMMU_READ (1 << 0) |
| 28 | #define IOMMU_WRITE (2) | 28 | #define IOMMU_WRITE (1 << 1) |
| 29 | #define IOMMU_CACHE (4) /* DMA cache coherency */ | 29 | #define IOMMU_CACHE (1 << 2) /* DMA cache coherency */ |
| 30 | #define IOMMU_EXEC (1 << 3) | ||
| 30 | 31 | ||
| 31 | struct iommu_ops; | 32 | struct iommu_ops; |
| 32 | struct iommu_group; | 33 | struct iommu_group; |
