1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include "i915_drv.h"
25#include "i915_pvinfo.h"
26#include "i915_vgpu.h"
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62void intel_vgpu_detect(struct drm_i915_private *dev_priv)
63{
64 struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
65 u64 magic;
66 u16 version_major;
67 void __iomem *shared_area;
68
69 BUILD_BUG_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE);
70
71
72
73
74
75
76
77 if (GRAPHICS_VER(dev_priv) < 6)
78 return;
79
80 shared_area = pci_iomap_range(pdev, 0, VGT_PVINFO_PAGE, VGT_PVINFO_SIZE);
81 if (!shared_area) {
82 drm_err(&dev_priv->drm,
83 "failed to map MMIO bar to check for VGT\n");
84 return;
85 }
86
87 magic = readq(shared_area + vgtif_offset(magic));
88 if (magic != VGT_MAGIC)
89 goto out;
90
91 version_major = readw(shared_area + vgtif_offset(version_major));
92 if (version_major < VGT_VERSION_MAJOR) {
93 drm_info(&dev_priv->drm, "VGT interface version mismatch!\n");
94 goto out;
95 }
96
97 dev_priv->vgpu.caps = readl(shared_area + vgtif_offset(vgt_caps));
98
99 dev_priv->vgpu.active = true;
100 mutex_init(&dev_priv->vgpu.lock);
101 drm_info(&dev_priv->drm, "Virtual GPU for Intel GVT-g detected.\n");
102
103out:
104 pci_iounmap(pdev, shared_area);
105}
106
107void intel_vgpu_register(struct drm_i915_private *i915)
108{
109
110
111
112 if (intel_vgpu_active(i915))
113 intel_uncore_write(&i915->uncore, vgtif_reg(display_ready),
114 VGT_DRV_DISPLAY_READY);
115}
116
117bool intel_vgpu_active(struct drm_i915_private *dev_priv)
118{
119 return dev_priv->vgpu.active;
120}
121
122bool intel_vgpu_has_full_ppgtt(struct drm_i915_private *dev_priv)
123{
124 return dev_priv->vgpu.caps & VGT_CAPS_FULL_PPGTT;
125}
126
127bool intel_vgpu_has_hwsp_emulation(struct drm_i915_private *dev_priv)
128{
129 return dev_priv->vgpu.caps & VGT_CAPS_HWSP_EMULATION;
130}
131
132bool intel_vgpu_has_huge_gtt(struct drm_i915_private *dev_priv)
133{
134 return dev_priv->vgpu.caps & VGT_CAPS_HUGE_GTT;
135}
136
137struct _balloon_info_ {
138
139
140
141
142
143 struct drm_mm_node space[4];
144};
145
146static struct _balloon_info_ bl_info;
147
148static void vgt_deballoon_space(struct i915_ggtt *ggtt,
149 struct drm_mm_node *node)
150{
151 struct drm_i915_private *dev_priv = ggtt->vm.i915;
152 if (!drm_mm_node_allocated(node))
153 return;
154
155 drm_dbg(&dev_priv->drm,
156 "deballoon space: range [0x%llx - 0x%llx] %llu KiB.\n",
157 node->start,
158 node->start + node->size,
159 node->size / 1024);
160
161 ggtt->vm.reserved -= node->size;
162 drm_mm_remove_node(node);
163}
164
165
166
167
168
169
170
171
172void intel_vgt_deballoon(struct i915_ggtt *ggtt)
173{
174 struct drm_i915_private *dev_priv = ggtt->vm.i915;
175 int i;
176
177 if (!intel_vgpu_active(ggtt->vm.i915))
178 return;
179
180 drm_dbg(&dev_priv->drm, "VGT deballoon.\n");
181
182 for (i = 0; i < 4; i++)
183 vgt_deballoon_space(ggtt, &bl_info.space[i]);
184}
185
186static int vgt_balloon_space(struct i915_ggtt *ggtt,
187 struct drm_mm_node *node,
188 unsigned long start, unsigned long end)
189{
190 struct drm_i915_private *dev_priv = ggtt->vm.i915;
191 unsigned long size = end - start;
192 int ret;
193
194 if (start >= end)
195 return -EINVAL;
196
197 drm_info(&dev_priv->drm,
198 "balloon space: range [ 0x%lx - 0x%lx ] %lu KiB.\n",
199 start, end, size / 1024);
200 ret = i915_gem_gtt_reserve(&ggtt->vm, node,
201 size, start, I915_COLOR_UNEVICTABLE,
202 0);
203 if (!ret)
204 ggtt->vm.reserved += size;
205
206 return ret;
207}
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253int intel_vgt_balloon(struct i915_ggtt *ggtt)
254{
255 struct drm_i915_private *dev_priv = ggtt->vm.i915;
256 struct intel_uncore *uncore = &dev_priv->uncore;
257 unsigned long ggtt_end = ggtt->vm.total;
258
259 unsigned long mappable_base, mappable_size, mappable_end;
260 unsigned long unmappable_base, unmappable_size, unmappable_end;
261 int ret;
262
263 if (!intel_vgpu_active(ggtt->vm.i915))
264 return 0;
265
266 mappable_base =
267 intel_uncore_read(uncore, vgtif_reg(avail_rs.mappable_gmadr.base));
268 mappable_size =
269 intel_uncore_read(uncore, vgtif_reg(avail_rs.mappable_gmadr.size));
270 unmappable_base =
271 intel_uncore_read(uncore, vgtif_reg(avail_rs.nonmappable_gmadr.base));
272 unmappable_size =
273 intel_uncore_read(uncore, vgtif_reg(avail_rs.nonmappable_gmadr.size));
274
275 mappable_end = mappable_base + mappable_size;
276 unmappable_end = unmappable_base + unmappable_size;
277
278 drm_info(&dev_priv->drm, "VGT ballooning configuration:\n");
279 drm_info(&dev_priv->drm,
280 "Mappable graphic memory: base 0x%lx size %ldKiB\n",
281 mappable_base, mappable_size / 1024);
282 drm_info(&dev_priv->drm,
283 "Unmappable graphic memory: base 0x%lx size %ldKiB\n",
284 unmappable_base, unmappable_size / 1024);
285
286 if (mappable_end > ggtt->mappable_end ||
287 unmappable_base < ggtt->mappable_end ||
288 unmappable_end > ggtt_end) {
289 drm_err(&dev_priv->drm, "Invalid ballooning configuration!\n");
290 return -EINVAL;
291 }
292
293
294 if (unmappable_base > ggtt->mappable_end) {
295 ret = vgt_balloon_space(ggtt, &bl_info.space[2],
296 ggtt->mappable_end, unmappable_base);
297
298 if (ret)
299 goto err;
300 }
301
302 if (unmappable_end < ggtt_end) {
303 ret = vgt_balloon_space(ggtt, &bl_info.space[3],
304 unmappable_end, ggtt_end);
305 if (ret)
306 goto err_upon_mappable;
307 }
308
309
310 if (mappable_base) {
311 ret = vgt_balloon_space(ggtt, &bl_info.space[0],
312 0, mappable_base);
313
314 if (ret)
315 goto err_upon_unmappable;
316 }
317
318 if (mappable_end < ggtt->mappable_end) {
319 ret = vgt_balloon_space(ggtt, &bl_info.space[1],
320 mappable_end, ggtt->mappable_end);
321
322 if (ret)
323 goto err_below_mappable;
324 }
325
326 drm_info(&dev_priv->drm, "VGT balloon successfully\n");
327 return 0;
328
329err_below_mappable:
330 vgt_deballoon_space(ggtt, &bl_info.space[0]);
331err_upon_unmappable:
332 vgt_deballoon_space(ggtt, &bl_info.space[3]);
333err_upon_mappable:
334 vgt_deballoon_space(ggtt, &bl_info.space[2]);
335err:
336 drm_err(&dev_priv->drm, "VGT balloon fail\n");
337 return ret;
338}
339