0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include "i915_drv.h"
0025 #include "i915_pvinfo.h"
0026 #include "i915_vgpu.h"
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062 void intel_vgpu_detect(struct drm_i915_private *dev_priv)
0063 {
0064 struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
0065 u64 magic;
0066 u16 version_major;
0067 void __iomem *shared_area;
0068
0069 BUILD_BUG_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE);
0070
0071
0072
0073
0074
0075
0076
0077 if (GRAPHICS_VER(dev_priv) < 6)
0078 return;
0079
0080 shared_area = pci_iomap_range(pdev, 0, VGT_PVINFO_PAGE, VGT_PVINFO_SIZE);
0081 if (!shared_area) {
0082 drm_err(&dev_priv->drm,
0083 "failed to map MMIO bar to check for VGT\n");
0084 return;
0085 }
0086
0087 magic = readq(shared_area + vgtif_offset(magic));
0088 if (magic != VGT_MAGIC)
0089 goto out;
0090
0091 version_major = readw(shared_area + vgtif_offset(version_major));
0092 if (version_major < VGT_VERSION_MAJOR) {
0093 drm_info(&dev_priv->drm, "VGT interface version mismatch!\n");
0094 goto out;
0095 }
0096
0097 dev_priv->vgpu.caps = readl(shared_area + vgtif_offset(vgt_caps));
0098
0099 dev_priv->vgpu.active = true;
0100 mutex_init(&dev_priv->vgpu.lock);
0101 drm_info(&dev_priv->drm, "Virtual GPU for Intel GVT-g detected.\n");
0102
0103 out:
0104 pci_iounmap(pdev, shared_area);
0105 }
0106
0107 void intel_vgpu_register(struct drm_i915_private *i915)
0108 {
0109
0110
0111
0112 if (intel_vgpu_active(i915))
0113 intel_uncore_write(&i915->uncore, vgtif_reg(display_ready),
0114 VGT_DRV_DISPLAY_READY);
0115 }
0116
0117 bool intel_vgpu_active(struct drm_i915_private *dev_priv)
0118 {
0119 return dev_priv->vgpu.active;
0120 }
0121
0122 bool intel_vgpu_has_full_ppgtt(struct drm_i915_private *dev_priv)
0123 {
0124 return dev_priv->vgpu.caps & VGT_CAPS_FULL_PPGTT;
0125 }
0126
0127 bool intel_vgpu_has_hwsp_emulation(struct drm_i915_private *dev_priv)
0128 {
0129 return dev_priv->vgpu.caps & VGT_CAPS_HWSP_EMULATION;
0130 }
0131
0132 bool intel_vgpu_has_huge_gtt(struct drm_i915_private *dev_priv)
0133 {
0134 return dev_priv->vgpu.caps & VGT_CAPS_HUGE_GTT;
0135 }
0136
0137 struct _balloon_info_ {
0138
0139
0140
0141
0142
0143 struct drm_mm_node space[4];
0144 };
0145
0146 static struct _balloon_info_ bl_info;
0147
0148 static void vgt_deballoon_space(struct i915_ggtt *ggtt,
0149 struct drm_mm_node *node)
0150 {
0151 struct drm_i915_private *dev_priv = ggtt->vm.i915;
0152 if (!drm_mm_node_allocated(node))
0153 return;
0154
0155 drm_dbg(&dev_priv->drm,
0156 "deballoon space: range [0x%llx - 0x%llx] %llu KiB.\n",
0157 node->start,
0158 node->start + node->size,
0159 node->size / 1024);
0160
0161 ggtt->vm.reserved -= node->size;
0162 drm_mm_remove_node(node);
0163 }
0164
0165
0166
0167
0168
0169
0170
0171
0172 void intel_vgt_deballoon(struct i915_ggtt *ggtt)
0173 {
0174 struct drm_i915_private *dev_priv = ggtt->vm.i915;
0175 int i;
0176
0177 if (!intel_vgpu_active(ggtt->vm.i915))
0178 return;
0179
0180 drm_dbg(&dev_priv->drm, "VGT deballoon.\n");
0181
0182 for (i = 0; i < 4; i++)
0183 vgt_deballoon_space(ggtt, &bl_info.space[i]);
0184 }
0185
0186 static int vgt_balloon_space(struct i915_ggtt *ggtt,
0187 struct drm_mm_node *node,
0188 unsigned long start, unsigned long end)
0189 {
0190 struct drm_i915_private *dev_priv = ggtt->vm.i915;
0191 unsigned long size = end - start;
0192 int ret;
0193
0194 if (start >= end)
0195 return -EINVAL;
0196
0197 drm_info(&dev_priv->drm,
0198 "balloon space: range [ 0x%lx - 0x%lx ] %lu KiB.\n",
0199 start, end, size / 1024);
0200 ret = i915_gem_gtt_reserve(&ggtt->vm, NULL, node,
0201 size, start, I915_COLOR_UNEVICTABLE,
0202 0);
0203 if (!ret)
0204 ggtt->vm.reserved += size;
0205
0206 return ret;
0207 }
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253 int intel_vgt_balloon(struct i915_ggtt *ggtt)
0254 {
0255 struct drm_i915_private *dev_priv = ggtt->vm.i915;
0256 struct intel_uncore *uncore = &dev_priv->uncore;
0257 unsigned long ggtt_end = ggtt->vm.total;
0258
0259 unsigned long mappable_base, mappable_size, mappable_end;
0260 unsigned long unmappable_base, unmappable_size, unmappable_end;
0261 int ret;
0262
0263 if (!intel_vgpu_active(ggtt->vm.i915))
0264 return 0;
0265
0266 mappable_base =
0267 intel_uncore_read(uncore, vgtif_reg(avail_rs.mappable_gmadr.base));
0268 mappable_size =
0269 intel_uncore_read(uncore, vgtif_reg(avail_rs.mappable_gmadr.size));
0270 unmappable_base =
0271 intel_uncore_read(uncore, vgtif_reg(avail_rs.nonmappable_gmadr.base));
0272 unmappable_size =
0273 intel_uncore_read(uncore, vgtif_reg(avail_rs.nonmappable_gmadr.size));
0274
0275 mappable_end = mappable_base + mappable_size;
0276 unmappable_end = unmappable_base + unmappable_size;
0277
0278 drm_info(&dev_priv->drm, "VGT ballooning configuration:\n");
0279 drm_info(&dev_priv->drm,
0280 "Mappable graphic memory: base 0x%lx size %ldKiB\n",
0281 mappable_base, mappable_size / 1024);
0282 drm_info(&dev_priv->drm,
0283 "Unmappable graphic memory: base 0x%lx size %ldKiB\n",
0284 unmappable_base, unmappable_size / 1024);
0285
0286 if (mappable_end > ggtt->mappable_end ||
0287 unmappable_base < ggtt->mappable_end ||
0288 unmappable_end > ggtt_end) {
0289 drm_err(&dev_priv->drm, "Invalid ballooning configuration!\n");
0290 return -EINVAL;
0291 }
0292
0293
0294 if (unmappable_base > ggtt->mappable_end) {
0295 ret = vgt_balloon_space(ggtt, &bl_info.space[2],
0296 ggtt->mappable_end, unmappable_base);
0297
0298 if (ret)
0299 goto err;
0300 }
0301
0302 if (unmappable_end < ggtt_end) {
0303 ret = vgt_balloon_space(ggtt, &bl_info.space[3],
0304 unmappable_end, ggtt_end);
0305 if (ret)
0306 goto err_upon_mappable;
0307 }
0308
0309
0310 if (mappable_base) {
0311 ret = vgt_balloon_space(ggtt, &bl_info.space[0],
0312 0, mappable_base);
0313
0314 if (ret)
0315 goto err_upon_unmappable;
0316 }
0317
0318 if (mappable_end < ggtt->mappable_end) {
0319 ret = vgt_balloon_space(ggtt, &bl_info.space[1],
0320 mappable_end, ggtt->mappable_end);
0321
0322 if (ret)
0323 goto err_below_mappable;
0324 }
0325
0326 drm_info(&dev_priv->drm, "VGT balloon successfully\n");
0327 return 0;
0328
0329 err_below_mappable:
0330 vgt_deballoon_space(ggtt, &bl_info.space[0]);
0331 err_upon_unmappable:
0332 vgt_deballoon_space(ggtt, &bl_info.space[3]);
0333 err_upon_mappable:
0334 vgt_deballoon_space(ggtt, &bl_info.space[2]);
0335 err:
0336 drm_err(&dev_priv->drm, "VGT balloon fail\n");
0337 return ret;
0338 }