1 /* 2 * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 * 23 * Authors: 24 * Eddie Dong <eddie.dong@intel.com> 25 * Dexuan Cui 26 * Jike Song <jike.song@intel.com> 27 * 28 * Contributors: 29 * Zhi Wang <zhi.a.wang@intel.com> 30 * 31 */ 32 33 #ifndef _GVT_MPT_H_ 34 #define _GVT_MPT_H_ 35 36 /** 37 * DOC: Hypervisor Service APIs for GVT-g Core Logic 38 * 39 * This is the glue layer between specific hypervisor MPT modules and GVT-g core 40 * logic. Each kind of hypervisor MPT module provides a collection of function 41 * callbacks and will be attached to GVT host when the driver is loading. 42 * GVT-g core logic will call these APIs to request specific services from 43 * hypervisor. 44 */ 45 46 /** 47 * intel_gvt_hypervisor_detect_host - check if GVT-g is running within 48 * hypervisor host/privilged domain 49 * 50 * Returns: 51 * Zero on success, -ENODEV if current kernel is running inside a VM 52 */ 53 static inline int intel_gvt_hypervisor_detect_host(void) 54 { 55 return intel_gvt_host.mpt->detect_host(); 56 } 57 58 /** 59 * intel_gvt_hypervisor_attach_vgpu - call hypervisor to initialize vGPU 60 * related stuffs inside hypervisor. 61 * 62 * Returns: 63 * Zero on success, negative error code if failed. 64 */ 65 static inline int intel_gvt_hypervisor_attach_vgpu(struct intel_vgpu *vgpu) 66 { 67 return intel_gvt_host.mpt->attach_vgpu(vgpu, &vgpu->handle); 68 } 69 70 /** 71 * intel_gvt_hypervisor_detach_vgpu - call hypervisor to release vGPU 72 * related stuffs inside hypervisor. 73 * 74 * Returns: 75 * Zero on success, negative error code if failed. 76 */ 77 static inline void intel_gvt_hypervisor_detach_vgpu(struct intel_vgpu *vgpu) 78 { 79 intel_gvt_host.mpt->detach_vgpu(vgpu->handle); 80 } 81 82 #define MSI_CAP_CONTROL(offset) (offset + 2) 83 #define MSI_CAP_ADDRESS(offset) (offset + 4) 84 #define MSI_CAP_DATA(offset) (offset + 8) 85 #define MSI_CAP_EN 0x1 86 87 /** 88 * intel_gvt_hypervisor_inject_msi - inject a MSI interrupt into vGPU 89 * 90 * Returns: 91 * Zero on success, negative error code if failed. 92 */ 93 static inline int intel_gvt_hypervisor_inject_msi(struct intel_vgpu *vgpu) 94 { 95 unsigned long offset = vgpu->gvt->device_info.msi_cap_offset; 96 u16 control, data; 97 u32 addr; 98 int ret; 99 100 control = *(u16 *)(vgpu_cfg_space(vgpu) + MSI_CAP_CONTROL(offset)); 101 addr = *(u32 *)(vgpu_cfg_space(vgpu) + MSI_CAP_ADDRESS(offset)); 102 data = *(u16 *)(vgpu_cfg_space(vgpu) + MSI_CAP_DATA(offset)); 103 104 /* Do not generate MSI if MSIEN is disable */ 105 if (!(control & MSI_CAP_EN)) 106 return 0; 107 108 if (WARN(control & GENMASK(15, 1), "only support one MSI format\n")) 109 return -EINVAL; 110 111 gvt_dbg_irq("vgpu%d: inject msi address %x data%x\n", vgpu->id, addr, 112 data); 113 114 ret = intel_gvt_host.mpt->inject_msi(vgpu->handle, addr, data); 115 if (ret) 116 return ret; 117 return 0; 118 } 119 120 /** 121 * intel_gvt_hypervisor_set_wp_page - translate a host VA into MFN 122 * @p: host kernel virtual address 123 * 124 * Returns: 125 * MFN on success, INTEL_GVT_INVALID_ADDR if failed. 126 */ 127 static inline unsigned long intel_gvt_hypervisor_virt_to_mfn(void *p) 128 { 129 return intel_gvt_host.mpt->from_virt_to_mfn(p); 130 } 131 132 /** 133 * intel_gvt_hypervisor_set_wp_page - set a guest page to write-protected 134 * @vgpu: a vGPU 135 * @p: intel_vgpu_guest_page 136 * 137 * Returns: 138 * Zero on success, negative error code if failed. 139 */ 140 static inline int intel_gvt_hypervisor_set_wp_page(struct intel_vgpu *vgpu, 141 struct intel_vgpu_guest_page *p) 142 { 143 int ret; 144 145 if (p->writeprotection) 146 return 0; 147 148 ret = intel_gvt_host.mpt->set_wp_page(vgpu->handle, p->gfn); 149 if (ret) 150 return ret; 151 p->writeprotection = true; 152 atomic_inc(&vgpu->gtt.n_write_protected_guest_page); 153 return 0; 154 } 155 156 /** 157 * intel_gvt_hypervisor_unset_wp_page - remove the write-protection of a 158 * guest page 159 * @vgpu: a vGPU 160 * @p: intel_vgpu_guest_page 161 * 162 * Returns: 163 * Zero on success, negative error code if failed. 164 */ 165 static inline int intel_gvt_hypervisor_unset_wp_page(struct intel_vgpu *vgpu, 166 struct intel_vgpu_guest_page *p) 167 { 168 int ret; 169 170 if (!p->writeprotection) 171 return 0; 172 173 ret = intel_gvt_host.mpt->unset_wp_page(vgpu->handle, p->gfn); 174 if (ret) 175 return ret; 176 p->writeprotection = false; 177 atomic_dec(&vgpu->gtt.n_write_protected_guest_page); 178 return 0; 179 } 180 181 /** 182 * intel_gvt_hypervisor_read_gpa - copy data from GPA to host data buffer 183 * @vgpu: a vGPU 184 * @gpa: guest physical address 185 * @buf: host data buffer 186 * @len: data length 187 * 188 * Returns: 189 * Zero on success, negative error code if failed. 190 */ 191 static inline int intel_gvt_hypervisor_read_gpa(struct intel_vgpu *vgpu, 192 unsigned long gpa, void *buf, unsigned long len) 193 { 194 return intel_gvt_host.mpt->read_gpa(vgpu->handle, gpa, buf, len); 195 } 196 197 /** 198 * intel_gvt_hypervisor_write_gpa - copy data from host data buffer to GPA 199 * @vgpu: a vGPU 200 * @gpa: guest physical address 201 * @buf: host data buffer 202 * @len: data length 203 * 204 * Returns: 205 * Zero on success, negative error code if failed. 206 */ 207 static inline int intel_gvt_hypervisor_write_gpa(struct intel_vgpu *vgpu, 208 unsigned long gpa, void *buf, unsigned long len) 209 { 210 return intel_gvt_host.mpt->write_gpa(vgpu->handle, gpa, buf, len); 211 } 212 213 /** 214 * intel_gvt_hypervisor_gfn_to_mfn - translate a GFN to MFN 215 * @vgpu: a vGPU 216 * @gpfn: guest pfn 217 * 218 * Returns: 219 * MFN on success, INTEL_GVT_INVALID_ADDR if failed. 220 */ 221 static inline unsigned long intel_gvt_hypervisor_gfn_to_mfn( 222 struct intel_vgpu *vgpu, unsigned long gfn) 223 { 224 return intel_gvt_host.mpt->gfn_to_mfn(vgpu->handle, gfn); 225 } 226 227 enum { 228 GVT_MAP_APERTURE = 0, 229 GVT_MAP_OPREGION, 230 }; 231 232 /** 233 * intel_gvt_hypervisor_map_gfn_to_mfn - map a GFN region to MFN 234 * @vgpu: a vGPU 235 * @gfn: guest PFN 236 * @mfn: host PFN 237 * @nr: amount of PFNs 238 * @map: map or unmap 239 * @type: map type 240 * 241 * Returns: 242 * Zero on success, negative error code if failed. 243 */ 244 static inline int intel_gvt_hypervisor_map_gfn_to_mfn( 245 struct intel_vgpu *vgpu, unsigned long gfn, 246 unsigned long mfn, unsigned int nr, 247 bool map, int type) 248 { 249 return intel_gvt_host.mpt->map_gfn_to_mfn(vgpu->handle, gfn, mfn, nr, 250 map, type); 251 } 252 253 /** 254 * intel_gvt_hypervisor_set_trap_area - Trap a guest PA region 255 * @vgpu: a vGPU 256 * @start: the beginning of the guest physical address region 257 * @end: the end of the guest physical address region 258 * @map: map or unmap 259 * 260 * Returns: 261 * Zero on success, negative error code if failed. 262 */ 263 static inline int intel_gvt_hypervisor_set_trap_area( 264 struct intel_vgpu *vgpu, u64 start, u64 end, bool map) 265 { 266 return intel_gvt_host.mpt->set_trap_area(vgpu->handle, start, end, map); 267 } 268 269 #endif /* _GVT_MPT_H_ */ 270