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 19struct device; 20 21struct 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 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 */ 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) 55 56#ifdef CONFIG_INTEL_IOMMU_SVM 57 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 62 * @flags: Flags. Later for requesting supervisor mode, etc. 63 * @ops: Callbacks to device driver 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 */ 85extern int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, 86 struct svm_dev_ops *ops); 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 */ 103extern int intel_svm_unbind_mm(struct device *dev, int pasid); 104 105#else /* CONFIG_INTEL_IOMMU_SVM */ 106 107static inline int intel_svm_bind_mm(struct device *dev, int *pasid, 108 int flags, struct svm_dev_ops *ops) 109{ 110 return -ENOSYS; 111} 112 113static inline int intel_svm_unbind_mm(struct device *dev, int pasid) 114{ 115 BUG(); 116} 117#endif /* CONFIG_INTEL_IOMMU_SVM */ 118 119#define intel_svm_available(dev) (!intel_svm_bind_mm((dev), NULL, 0, NULL)) 120 121#endif /* __INTEL_SVM_H__ */ 122