This patch is an initial step to replace Intel SVM code with the following IOMMU SVA ops: intel_svm_bind_mm() => iommu_sva_bind_device() intel_svm_unbind_mm() => iommu_sva_unbind_device() intel_svm_is_pasid_valid() => iommu_sva_get_pasid() The features below will continue to work but are not included in this patch in that they are handled mostly within the IOMMU subsystem. - IO page fault - mmu notifier Consolidation of the above will come after merging generic IOMMU sva code[1]. There should not be any changes needed for SVA users such as accelerator device drivers during this time. [1] http://jpbrucker.net/sva/
Showing the changes to include/linux (2 of 4 files). Show all
Unified · Split
| @@ -723,6 +723,10 @@ extern int intel_svm_finish_prq(struct intel_iommu *iommu); · 722 unmodified lines | |||
| 723 | int intel_svm_bind_gpasid(struct iommu_domain *domain, struct device *dev, | 723 | int intel_svm_bind_gpasid(struct iommu_domain *domain, struct device *dev, |
| 724 | struct iommu_gpasid_bind_data *data); | 724 | struct iommu_gpasid_bind_data *data); |
| 725 | int intel_svm_unbind_gpasid(struct device *dev, int pasid); | 725 | int intel_svm_unbind_gpasid(struct device *dev, int pasid); |
| 726 | struct iommu_sva *intel_svm_bind(struct device *dev, struct mm_struct *mm, | ||
| 727 | void *drvdata); | ||
| 728 | void intel_svm_unbind(struct iommu_sva *handle); | ||
| 729 | int intel_svm_get_pasid(struct iommu_sva *handle); | ||
| 726 | struct svm_dev_ops; | 730 | struct svm_dev_ops; |
| 727 | 731 | ||
| 728 | struct intel_svm_dev { | 732 | struct intel_svm_dev { |
| @@ -730,6 +734,8 @@ struct intel_svm_dev { · 1 unmodified line | |||
| 730 | struct rcu_head rcu; | 734 | struct rcu_head rcu; |
| 731 | struct device *dev; | 735 | struct device *dev; |
| 732 | struct svm_dev_ops *ops; | 736 | struct svm_dev_ops *ops; |
| 737 | struct iommu_sva sva; | ||
| 738 | int pasid; | ||
| 733 | int users; | 739 | int users; |
| 734 | u16 did; | 740 | u16 did; |
| 735 | u16 dev_iotlb:1; | 741 | u16 dev_iotlb:1; |
| @@ -21,7 +21,6 @@ struct svm_dev_ops { · 20 unmodified lines | |||
| 21 | #define SVM_REQ_EXEC (1<<1) | 21 | #define SVM_REQ_EXEC (1<<1) |
| 22 | #define SVM_REQ_PRIV (1<<0) | 22 | #define SVM_REQ_PRIV (1<<0) |
| 23 | 23 | ||
| 24 | |||
| 25 | /* | 24 | /* |
| 26 | * The SVM_FLAG_PRIVATE_PASID flag requests a PASID which is *not* the "main" | 25 | * The SVM_FLAG_PRIVATE_PASID flag requests a PASID which is *not* the "main" |
| 27 | * PASID for the current process. Even if a PASID already exists, a new one | 26 | * PASID for the current process. Even if a PASID already exists, a new one |
| @@ -57,89 +56,4 @@ struct svm_dev_ops { · 29 unmodified lines | |||
| 57 | */ | 56 | */ |
| 58 | #define SVM_FLAG_GUEST_PASID (1<<3) | 57 | #define SVM_FLAG_GUEST_PASID (1<<3) |
| 59 | 58 | ||
| 60 | #ifdef CONFIG_INTEL_IOMMU_SVM | ||
| 61 | |||
| 62 | /** | ||
| 63 | * intel_svm_bind_mm() - Bind the current process to a PASID | ||
| 64 | * @dev: Device to be granted access | ||
| 65 | * @pasid: Address for allocated PASID | ||
| 66 | * @flags: Flags. Later for requesting supervisor mode, etc. | ||
| 67 | * @ops: Callbacks to device driver | ||
| 68 | * | ||
| 69 | * This function attempts to enable PASID support for the given device. | ||
| 70 | * If the @pasid argument is non-%NULL, a PASID is allocated for access | ||
| 71 | * to the MM of the current process. | ||
| 72 | * | ||
| 73 | * By using a %NULL value for the @pasid argument, this function can | ||
| 74 | * be used to simply validate that PASID support is available for the | ||
| 75 | * given device — i.e. that it is behind an IOMMU which has the | ||
| 76 | * requisite support, and is enabled. | ||
| 77 | * | ||
| 78 | * Page faults are handled transparently by the IOMMU code, and there | ||
| 79 | * should be no need for the device driver to be involved. If a page | ||
| 80 | * fault cannot be handled (i.e. is an invalid address rather than | ||
| 81 | * just needs paging in), then the page request will be completed by | ||
| 82 | * the core IOMMU code with appropriate status, and the device itself | ||
| 83 | * can then report the resulting fault to its driver via whatever | ||
| 84 | * mechanism is appropriate. | ||
| 85 | * | ||
| 86 | * Multiple calls from the same process may result in the same PASID | ||
| 87 | * being re-used. A reference count is kept. | ||
| 88 | */ | ||
| 89 | extern int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, | ||
| 90 | struct svm_dev_ops *ops); | ||
| 91 | |||
| 92 | /** | ||
| 93 | * intel_svm_unbind_mm() - Unbind a specified PASID | ||
| 94 | * @dev: Device for which PASID was allocated | ||
| 95 | * @pasid: PASID value to be unbound | ||
| 96 | * | ||
| 97 | * This function allows a PASID to be retired when the device no | ||
| 98 | * longer requires access to the address space of a given process. | ||
| 99 | * | ||
| 100 | * If the use count for the PASID in question reaches zero, the | ||
| 101 | * PASID is revoked and may no longer be used by hardware. | ||
| 102 | * | ||
| 103 | * Device drivers are required to ensure that no access (including | ||
| 104 | * page requests) is currently outstanding for the PASID in question, | ||
| 105 | * before calling this function. | ||
| 106 | */ | ||
| 107 | extern int intel_svm_unbind_mm(struct device *dev, int pasid); | ||
| 108 | |||
| 109 | /** | ||
| 110 | * intel_svm_is_pasid_valid() - check if pasid is valid | ||
| 111 | * @dev: Device for which PASID was allocated | ||
| 112 | * @pasid: PASID value to be checked | ||
| 113 | * | ||
| 114 | * This function checks if the specified pasid is still valid. A | ||
| 115 | * valid pasid means the backing mm is still having a valid user. | ||
| 116 | * For kernel callers init_mm is always valid. for other mm, if mm->mm_users | ||
| 117 | * is non-zero, it is valid. | ||
| 118 | * | ||
| 119 | * returns -EINVAL if invalid pasid, 0 if pasid ref count is invalid | ||
| 120 | * 1 if pasid is valid. | ||
| 121 | */ | ||
| 122 | extern int intel_svm_is_pasid_valid(struct device *dev, int pasid); | ||
| 123 | |||
| 124 | #else /* CONFIG_INTEL_IOMMU_SVM */ | ||
| 125 | |||
| 126 | static inline int intel_svm_bind_mm(struct device *dev, int *pasid, | ||
| 127 | int flags, struct svm_dev_ops *ops) | ||
| 128 | { | ||
| 129 | return -ENOSYS; | ||
| 130 | } | ||
| 131 | |||
| 132 | static inline int intel_svm_unbind_mm(struct device *dev, int pasid) | ||
| 133 | { | ||
| 134 | BUG(); | ||
| 135 | } | ||
| 136 | |||
| 137 | static inline int intel_svm_is_pasid_valid(struct device *dev, int pasid) | ||
| 138 | { | ||
| 139 | return -EINVAL; | ||
| 140 | } | ||
| 141 | #endif /* CONFIG_INTEL_IOMMU_SVM */ | ||
| 142 | |||
| 143 | #define intel_svm_available(dev) (!intel_svm_bind_mm((dev), NULL, 0, NULL)) | ||
| 144 | |||
| 145 | #endif /* __INTEL_SVM_H__ */ | 59 | #endif /* __INTEL_SVM_H__ */ |