| David Woodhouse | 2f26e0a | 2015-09-09 11:40:47 +0100 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright © 2015 Intel Corporation. | 
 | 3 |  * | 
 | 4 |  * Authors: David Woodhouse <David.Woodhouse@intel.com> | 
 | 5 |  * | 
 | 6 |  * This program is free software; you can redistribute it and/or modify it | 
 | 7 |  * under the terms and conditions of the GNU General Public License, | 
 | 8 |  * version 2, as published by the Free Software Foundation. | 
 | 9 |  * | 
 | 10 |  * This program is distributed in the hope it will be useful, but WITHOUT | 
 | 11 |  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
 | 12 |  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | 
 | 13 |  * more details. | 
 | 14 |  */ | 
 | 15 |  | 
 | 16 | #ifndef __INTEL_SVM_H__ | 
 | 17 | #define __INTEL_SVM_H__ | 
 | 18 |  | 
| David Woodhouse | 2f26e0a | 2015-09-09 11:40:47 +0100 | [diff] [blame] | 19 | struct device; | 
 | 20 |  | 
| David Woodhouse | 0204a49 | 2015-10-13 17:18:10 +0100 | [diff] [blame] | 21 | struct svm_dev_ops { | 
 | 22 | 	void (*fault_cb)(struct device *dev, int pasid, u64 address, | 
 | 23 | 			 u32 private, int rwxp, int response); | 
 | 24 | }; | 
 | 25 |  | 
 | 26 | /* Values for rxwp in fault_cb callback */ | 
 | 27 | #define SVM_REQ_READ	(1<<3) | 
 | 28 | #define SVM_REQ_WRITE	(1<<2) | 
 | 29 | #define SVM_REQ_EXEC	(1<<1) | 
 | 30 | #define SVM_REQ_PRIV	(1<<0) | 
 | 31 |  | 
| David Woodhouse | 569e4f7 | 2015-10-15 13:59:14 +0100 | [diff] [blame] | 32 |  | 
 | 33 | /* | 
 | 34 |  * The SVM_FLAG_PRIVATE_PASID flag requests a PASID which is *not* the "main" | 
 | 35 |  * PASID for the current process. Even if a PASID already exists, a new one | 
 | 36 |  * will be allocated. And the PASID allocated with SVM_FLAG_PRIVATE_PASID | 
 | 37 |  * will not be given to subsequent callers. This facility allows a driver to | 
 | 38 |  * disambiguate between multiple device contexts which access the same MM, | 
 | 39 |  * if there is no other way to do so. It should be used sparingly, if at all. | 
 | 40 |  */ | 
| David Woodhouse | 5cec753 | 2015-10-15 15:52:15 +0100 | [diff] [blame] | 41 | #define SVM_FLAG_PRIVATE_PASID		(1<<0) | 
 | 42 |  | 
 | 43 | /* | 
 | 44 |  * The SVM_FLAG_SUPERVISOR_MODE flag requests a PASID which can be used only | 
 | 45 |  * for access to kernel addresses. No IOTLB flushes are automatically done | 
 | 46 |  * for kernel mappings; it is valid only for access to the kernel's static | 
 | 47 |  * 1:1 mapping of physical memory — not to vmalloc or even module mappings. | 
 | 48 |  * A future API addition may permit the use of such ranges, by means of an | 
 | 49 |  * explicit IOTLB flush call (akin to the DMA API's unmap method). | 
 | 50 |  * | 
 | 51 |  * It is unlikely that we will ever hook into flush_tlb_kernel_range() to | 
 | 52 |  * do such IOTLB flushes automatically. | 
 | 53 |  */ | 
 | 54 | #define SVM_FLAG_SUPERVISOR_MODE	(1<<1) | 
| David Woodhouse | 569e4f7 | 2015-10-15 13:59:14 +0100 | [diff] [blame] | 55 |  | 
| David Woodhouse | da4689c | 2015-10-27 08:36:08 +0900 | [diff] [blame] | 56 | #ifdef CONFIG_INTEL_IOMMU_SVM | 
 | 57 |  | 
| David Woodhouse | 2f26e0a | 2015-09-09 11:40:47 +0100 | [diff] [blame] | 58 | /** | 
 | 59 |  * intel_svm_bind_mm() - Bind the current process to a PASID | 
 | 60 |  * @dev:	Device to be granted acccess | 
 | 61 |  * @pasid:	Address for allocated PASID | 
| David Woodhouse | 0204a49 | 2015-10-13 17:18:10 +0100 | [diff] [blame] | 62 |  * @flags:	Flags. Later for requesting supervisor mode, etc. | 
 | 63 |  * @ops:	Callbacks to device driver | 
| David Woodhouse | 2f26e0a | 2015-09-09 11:40:47 +0100 | [diff] [blame] | 64 |  * | 
 | 65 |  * This function attempts to enable PASID support for the given device. | 
 | 66 |  * If the @pasid argument is non-%NULL, a PASID is allocated for access | 
 | 67 |  * to the MM of the current process. | 
 | 68 |  * | 
 | 69 |  * By using a %NULL value for the @pasid argument, this function can | 
 | 70 |  * be used to simply validate that PASID support is available for the | 
 | 71 |  * given device — i.e. that it is behind an IOMMU which has the | 
 | 72 |  * requisite support, and is enabled. | 
 | 73 |  * | 
 | 74 |  * Page faults are handled transparently by the IOMMU code, and there | 
 | 75 |  * should be no need for the device driver to be involved. If a page | 
 | 76 |  * fault cannot be handled (i.e. is an invalid address rather than | 
 | 77 |  * just needs paging in), then the page request will be completed by | 
 | 78 |  * the core IOMMU code with appropriate status, and the device itself | 
 | 79 |  * can then report the resulting fault to its driver via whatever | 
 | 80 |  * mechanism is appropriate. | 
 | 81 |  * | 
 | 82 |  * Multiple calls from the same process may result in the same PASID | 
 | 83 |  * being re-used. A reference count is kept. | 
 | 84 |  */ | 
| David Woodhouse | 0204a49 | 2015-10-13 17:18:10 +0100 | [diff] [blame] | 85 | extern int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, | 
 | 86 | 			     struct svm_dev_ops *ops); | 
| David Woodhouse | 2f26e0a | 2015-09-09 11:40:47 +0100 | [diff] [blame] | 87 |  | 
 | 88 | /** | 
 | 89 |  * intel_svm_unbind_mm() - Unbind a specified PASID | 
 | 90 |  * @dev:	Device for which PASID was allocated | 
 | 91 |  * @pasid:	PASID value to be unbound | 
 | 92 |  * | 
 | 93 |  * This function allows a PASID to be retired when the device no | 
 | 94 |  * longer requires access to the address space of a given process. | 
 | 95 |  * | 
 | 96 |  * If the use count for the PASID in question reaches zero, the | 
 | 97 |  * PASID is revoked and may no longer be used by hardware. | 
 | 98 |  * | 
 | 99 |  * Device drivers are required to ensure that no access (including | 
 | 100 |  * page requests) is currently outstanding for the PASID in question, | 
 | 101 |  * before calling this function. | 
 | 102 |  */ | 
 | 103 | extern int intel_svm_unbind_mm(struct device *dev, int pasid); | 
 | 104 |  | 
 | 105 | #else /* CONFIG_INTEL_IOMMU_SVM */ | 
 | 106 |  | 
| David Woodhouse | 0204a49 | 2015-10-13 17:18:10 +0100 | [diff] [blame] | 107 | static inline int intel_svm_bind_mm(struct device *dev, int *pasid, | 
 | 108 | 				    int flags, struct svm_dev_ops *ops) | 
| David Woodhouse | 2f26e0a | 2015-09-09 11:40:47 +0100 | [diff] [blame] | 109 | { | 
 | 110 | 	return -ENOSYS; | 
 | 111 | } | 
 | 112 |  | 
 | 113 | static inline int intel_svm_unbind_mm(struct device *dev, int pasid) | 
 | 114 | { | 
 | 115 | 	BUG(); | 
 | 116 | } | 
 | 117 | #endif /* CONFIG_INTEL_IOMMU_SVM */ | 
 | 118 |  | 
| David Woodhouse | 0204a49 | 2015-10-13 17:18:10 +0100 | [diff] [blame] | 119 | #define intel_svm_available(dev) (!intel_svm_bind_mm((dev), NULL, 0, NULL)) | 
| David Woodhouse | 2f26e0a | 2015-09-09 11:40:47 +0100 | [diff] [blame] | 120 |  | 
 | 121 | #endif /* __INTEL_SVM_H__ */ |