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 * Jike Song <jike.song@intel.com> 26 * 27 * Contributors: 28 * Zhi Wang <zhi.a.wang@intel.com> 29 * Min He <min.he@intel.com> 30 * Bing Niu <bing.niu@intel.com> 31 * 32 */ 33 34 #include "i915_drv.h" 35 #include "gvt.h" 36 #include "intel_pci_config.h" 37 38 enum { 39 INTEL_GVT_PCI_BAR_GTTMMIO = 0, 40 INTEL_GVT_PCI_BAR_APERTURE, 41 INTEL_GVT_PCI_BAR_PIO, 42 INTEL_GVT_PCI_BAR_MAX, 43 }; 44 45 /* bitmap for writable bits (RW or RW1C bits, but cannot co-exist in one 46 * byte) byte by byte in standard pci configuration space. (not the full 47 * 256 bytes.) 48 */ 49 static const u8 pci_cfg_space_rw_bmp[PCI_INTERRUPT_LINE + 4] = { 50 [PCI_COMMAND] = 0xff, 0x07, 51 [PCI_STATUS] = 0x00, 0xf9, /* the only one RW1C byte */ 52 [PCI_CACHE_LINE_SIZE] = 0xff, 53 [PCI_BASE_ADDRESS_0 ... PCI_CARDBUS_CIS - 1] = 0xff, 54 [PCI_ROM_ADDRESS] = 0x01, 0xf8, 0xff, 0xff, 55 [PCI_INTERRUPT_LINE] = 0xff, 56 }; 57 58 /** 59 * vgpu_pci_cfg_mem_write - write virtual cfg space memory 60 * @vgpu: target vgpu 61 * @off: offset 62 * @src: src ptr to write 63 * @bytes: number of bytes 64 * 65 * Use this function to write virtual cfg space memory. 66 * For standard cfg space, only RW bits can be changed, 67 * and we emulates the RW1C behavior of PCI_STATUS register. 68 */ 69 static void vgpu_pci_cfg_mem_write(struct intel_vgpu *vgpu, unsigned int off, 70 u8 *src, unsigned int bytes) 71 { 72 u8 *cfg_base = vgpu_cfg_space(vgpu); 73 u8 mask, new, old; 74 pci_power_t pwr; 75 int i = 0; 76 77 for (; i < bytes && (off + i < sizeof(pci_cfg_space_rw_bmp)); i++) { 78 mask = pci_cfg_space_rw_bmp[off + i]; 79 old = cfg_base[off + i]; 80 new = src[i] & mask; 81 82 /** 83 * The PCI_STATUS high byte has RW1C bits, here 84 * emulates clear by writing 1 for these bits. 85 * Writing a 0b to RW1C bits has no effect. 86 */ 87 if (off + i == PCI_STATUS + 1) 88 new = (~new & old) & mask; 89 90 cfg_base[off + i] = (old & ~mask) | new; 91 } 92 93 /* For other configuration space directly copy as it is. */ 94 if (i < bytes) 95 memcpy(cfg_base + off + i, src + i, bytes - i); 96 97 if (off == vgpu->cfg_space.pmcsr_off && vgpu->cfg_space.pmcsr_off) { 98 pwr = (pci_power_t __force)(*(u16*)(&vgpu_cfg_space(vgpu)[off]) 99 & PCI_PM_CTRL_STATE_MASK); 100 if (pwr == PCI_D3hot) 101 vgpu->d3_entered = true; 102 gvt_dbg_core("vgpu-%d power status changed to %d\n", 103 vgpu->id, pwr); 104 } 105 } 106 107 /** 108 * intel_vgpu_emulate_cfg_read - emulate vGPU configuration space read 109 * @vgpu: target vgpu 110 * @offset: offset 111 * @p_data: return data ptr 112 * @bytes: number of bytes to read 113 * 114 * Returns: 115 * Zero on success, negative error code if failed. 116 */ 117 int intel_vgpu_emulate_cfg_read(struct intel_vgpu *vgpu, unsigned int offset, 118 void *p_data, unsigned int bytes) 119 { 120 struct drm_i915_private *i915 = vgpu->gvt->gt->i915; 121 122 if (drm_WARN_ON(&i915->drm, bytes > 4)) 123 return -EINVAL; 124 125 if (drm_WARN_ON(&i915->drm, 126 offset + bytes > vgpu->gvt->device_info.cfg_space_size)) 127 return -EINVAL; 128 129 memcpy(p_data, vgpu_cfg_space(vgpu) + offset, bytes); 130 return 0; 131 } 132 133 static void map_aperture(struct intel_vgpu *vgpu, bool map) 134 { 135 if (map != vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked) 136 vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked = map; 137 } 138 139 static void trap_gttmmio(struct intel_vgpu *vgpu, bool trap) 140 { 141 if (trap != vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].tracked) 142 vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].tracked = trap; 143 } 144 145 static int emulate_pci_command_write(struct intel_vgpu *vgpu, 146 unsigned int offset, void *p_data, unsigned int bytes) 147 { 148 u8 old = vgpu_cfg_space(vgpu)[offset]; 149 u8 new = *(u8 *)p_data; 150 u8 changed = old ^ new; 151 152 vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes); 153 if (!(changed & PCI_COMMAND_MEMORY)) 154 return 0; 155 156 if (old & PCI_COMMAND_MEMORY) { 157 trap_gttmmio(vgpu, false); 158 map_aperture(vgpu, false); 159 } else { 160 trap_gttmmio(vgpu, true); 161 map_aperture(vgpu, true); 162 } 163 164 return 0; 165 } 166 167 static int emulate_pci_rom_bar_write(struct intel_vgpu *vgpu, 168 unsigned int offset, void *p_data, unsigned int bytes) 169 { 170 u32 *pval = (u32 *)(vgpu_cfg_space(vgpu) + offset); 171 u32 new = *(u32 *)(p_data); 172 173 if ((new & PCI_ROM_ADDRESS_MASK) == PCI_ROM_ADDRESS_MASK) 174 /* We don't have rom, return size of 0. */ 175 *pval = 0; 176 else 177 vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes); 178 return 0; 179 } 180 181 static void emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset, 182 void *p_data, unsigned int bytes) 183 { 184 u32 new = *(u32 *)(p_data); 185 bool lo = IS_ALIGNED(offset, 8); 186 u64 size; 187 bool mmio_enabled = 188 vgpu_cfg_space(vgpu)[PCI_COMMAND] & PCI_COMMAND_MEMORY; 189 struct intel_vgpu_pci_bar *bars = vgpu->cfg_space.bar; 190 191 /* 192 * Power-up software can determine how much address 193 * space the device requires by writing a value of 194 * all 1's to the register and then reading the value 195 * back. The device will return 0's in all don't-care 196 * address bits. 197 */ 198 if (new == 0xffffffff) { 199 switch (offset) { 200 case PCI_BASE_ADDRESS_0: 201 case PCI_BASE_ADDRESS_1: 202 size = ~(bars[INTEL_GVT_PCI_BAR_GTTMMIO].size -1); 203 intel_vgpu_write_pci_bar(vgpu, offset, 204 size >> (lo ? 0 : 32), lo); 205 /* 206 * Untrap the BAR, since guest hasn't configured a 207 * valid GPA 208 */ 209 trap_gttmmio(vgpu, false); 210 break; 211 case PCI_BASE_ADDRESS_2: 212 case PCI_BASE_ADDRESS_3: 213 size = ~(bars[INTEL_GVT_PCI_BAR_APERTURE].size -1); 214 intel_vgpu_write_pci_bar(vgpu, offset, 215 size >> (lo ? 0 : 32), lo); 216 map_aperture(vgpu, false); 217 break; 218 default: 219 /* Unimplemented BARs */ 220 intel_vgpu_write_pci_bar(vgpu, offset, 0x0, false); 221 } 222 } else { 223 switch (offset) { 224 case PCI_BASE_ADDRESS_0: 225 case PCI_BASE_ADDRESS_1: 226 /* 227 * Untrap the old BAR first, since guest has 228 * re-configured the BAR 229 */ 230 trap_gttmmio(vgpu, false); 231 intel_vgpu_write_pci_bar(vgpu, offset, new, lo); 232 trap_gttmmio(vgpu, mmio_enabled); 233 break; 234 case PCI_BASE_ADDRESS_2: 235 case PCI_BASE_ADDRESS_3: 236 map_aperture(vgpu, false); 237 intel_vgpu_write_pci_bar(vgpu, offset, new, lo); 238 map_aperture(vgpu, mmio_enabled); 239 break; 240 default: 241 intel_vgpu_write_pci_bar(vgpu, offset, new, lo); 242 } 243 } 244 } 245 246 /** 247 * intel_vgpu_emulate_cfg_read - emulate vGPU configuration space write 248 * @vgpu: target vgpu 249 * @offset: offset 250 * @p_data: write data ptr 251 * @bytes: number of bytes to write 252 * 253 * Returns: 254 * Zero on success, negative error code if failed. 255 */ 256 int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset, 257 void *p_data, unsigned int bytes) 258 { 259 struct drm_i915_private *i915 = vgpu->gvt->gt->i915; 260 int ret; 261 262 if (drm_WARN_ON(&i915->drm, bytes > 4)) 263 return -EINVAL; 264 265 if (drm_WARN_ON(&i915->drm, 266 offset + bytes > vgpu->gvt->device_info.cfg_space_size)) 267 return -EINVAL; 268 269 /* First check if it's PCI_COMMAND */ 270 if (IS_ALIGNED(offset, 2) && offset == PCI_COMMAND) { 271 if (drm_WARN_ON(&i915->drm, bytes > 2)) 272 return -EINVAL; 273 return emulate_pci_command_write(vgpu, offset, p_data, bytes); 274 } 275 276 switch (rounddown(offset, 4)) { 277 case PCI_ROM_ADDRESS: 278 if (drm_WARN_ON(&i915->drm, !IS_ALIGNED(offset, 4))) 279 return -EINVAL; 280 return emulate_pci_rom_bar_write(vgpu, offset, p_data, bytes); 281 282 case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_5: 283 if (drm_WARN_ON(&i915->drm, !IS_ALIGNED(offset, 4))) 284 return -EINVAL; 285 emulate_pci_bar_write(vgpu, offset, p_data, bytes); 286 break; 287 case INTEL_GVT_PCI_SWSCI: 288 if (drm_WARN_ON(&i915->drm, !IS_ALIGNED(offset, 4))) 289 return -EINVAL; 290 ret = intel_vgpu_emulate_opregion_request(vgpu, *(u32 *)p_data); 291 if (ret) 292 return ret; 293 break; 294 295 case INTEL_GVT_PCI_OPREGION: 296 if (drm_WARN_ON(&i915->drm, !IS_ALIGNED(offset, 4))) 297 return -EINVAL; 298 ret = intel_vgpu_opregion_base_write_handler(vgpu, 299 *(u32 *)p_data); 300 if (ret) 301 return ret; 302 303 vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes); 304 break; 305 default: 306 vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes); 307 break; 308 } 309 return 0; 310 } 311 312 /** 313 * intel_vgpu_init_cfg_space - init vGPU configuration space when create vGPU 314 * 315 * @vgpu: a vGPU 316 * @primary: is the vGPU presented as primary 317 * 318 */ 319 void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu, 320 bool primary) 321 { 322 struct intel_gvt *gvt = vgpu->gvt; 323 struct pci_dev *pdev = to_pci_dev(gvt->gt->i915->drm.dev); 324 const struct intel_gvt_device_info *info = &gvt->device_info; 325 u16 *gmch_ctl; 326 u8 next; 327 328 memcpy(vgpu_cfg_space(vgpu), gvt->firmware.cfg_space, 329 info->cfg_space_size); 330 331 if (!primary) { 332 vgpu_cfg_space(vgpu)[PCI_CLASS_DEVICE] = 333 INTEL_GVT_PCI_CLASS_VGA_OTHER; 334 vgpu_cfg_space(vgpu)[PCI_CLASS_PROG] = 335 INTEL_GVT_PCI_CLASS_VGA_OTHER; 336 } 337 338 /* Show guest that there isn't any stolen memory.*/ 339 gmch_ctl = (u16 *)(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_GMCH_CONTROL); 340 *gmch_ctl &= ~(BDW_GMCH_GMS_MASK << BDW_GMCH_GMS_SHIFT); 341 342 intel_vgpu_write_pci_bar(vgpu, PCI_BASE_ADDRESS_2, 343 gvt_aperture_pa_base(gvt), true); 344 345 vgpu_cfg_space(vgpu)[PCI_COMMAND] &= ~(PCI_COMMAND_IO 346 | PCI_COMMAND_MEMORY 347 | PCI_COMMAND_MASTER); 348 /* 349 * Clear the bar upper 32bit and let guest to assign the new value 350 */ 351 memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_1, 0, 4); 352 memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_3, 0, 4); 353 memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_4, 0, 8); 354 memset(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_OPREGION, 0, 4); 355 356 vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].size = 357 pci_resource_len(pdev, GTTMMADR_BAR); 358 vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].size = 359 pci_resource_len(pdev, GTT_APERTURE_BAR); 360 361 memset(vgpu_cfg_space(vgpu) + PCI_ROM_ADDRESS, 0, 4); 362 363 /* PM Support */ 364 vgpu->cfg_space.pmcsr_off = 0; 365 if (vgpu_cfg_space(vgpu)[PCI_STATUS] & PCI_STATUS_CAP_LIST) { 366 next = vgpu_cfg_space(vgpu)[PCI_CAPABILITY_LIST]; 367 do { 368 if (vgpu_cfg_space(vgpu)[next + PCI_CAP_LIST_ID] == PCI_CAP_ID_PM) { 369 vgpu->cfg_space.pmcsr_off = next + PCI_PM_CTRL; 370 break; 371 } 372 next = vgpu_cfg_space(vgpu)[next + PCI_CAP_LIST_NEXT]; 373 } while (next); 374 } 375 } 376 377 /** 378 * intel_vgpu_reset_cfg_space - reset vGPU configuration space 379 * 380 * @vgpu: a vGPU 381 * 382 */ 383 void intel_vgpu_reset_cfg_space(struct intel_vgpu *vgpu) 384 { 385 u8 cmd = vgpu_cfg_space(vgpu)[PCI_COMMAND]; 386 bool primary = vgpu_cfg_space(vgpu)[PCI_CLASS_DEVICE] != 387 INTEL_GVT_PCI_CLASS_VGA_OTHER; 388 389 if (cmd & PCI_COMMAND_MEMORY) { 390 trap_gttmmio(vgpu, false); 391 map_aperture(vgpu, false); 392 } 393 394 /** 395 * Currently we only do such reset when vGPU is not 396 * owned by any VM, so we simply restore entire cfg 397 * space to default value. 398 */ 399 intel_vgpu_init_cfg_space(vgpu, primary); 400 } 401