Commit | Line | Data |
---|---|---|
82d375d1 ZW |
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 | * Kevin Tian <kevin.tian@intel.com> | |
26 | * | |
27 | * Contributors: | |
28 | * Ping Gao <ping.a.gao@intel.com> | |
29 | * Zhi Wang <zhi.a.wang@intel.com> | |
30 | * Bing Niu <bing.niu@intel.com> | |
31 | * | |
32 | */ | |
33 | ||
34 | #include "i915_drv.h" | |
feddf6e8 ZW |
35 | #include "gvt.h" |
36 | #include "i915_pvinfo.h" | |
82d375d1 | 37 | |
23736d1b | 38 | void populate_pvinfo_page(struct intel_vgpu *vgpu) |
82d375d1 ZW |
39 | { |
40 | /* setup the ballooning information */ | |
90551a12 ZW |
41 | vgpu_vreg64_t(vgpu, vgtif_reg(magic)) = VGT_MAGIC; |
42 | vgpu_vreg_t(vgpu, vgtif_reg(version_major)) = 1; | |
43 | vgpu_vreg_t(vgpu, vgtif_reg(version_minor)) = 0; | |
44 | vgpu_vreg_t(vgpu, vgtif_reg(display_ready)) = 0; | |
45 | vgpu_vreg_t(vgpu, vgtif_reg(vgt_id)) = vgpu->id; | |
a2ae95af | 46 | |
ca6ac684 | 47 | vgpu_vreg_t(vgpu, vgtif_reg(vgt_caps)) = VGT_CAPS_FULL_PPGTT; |
90551a12 | 48 | vgpu_vreg_t(vgpu, vgtif_reg(vgt_caps)) |= VGT_CAPS_HWSP_EMULATION; |
aa36ed6d | 49 | vgpu_vreg_t(vgpu, vgtif_reg(vgt_caps)) |= VGT_CAPS_HUGE_GTT; |
a2ae95af | 50 | |
90551a12 | 51 | vgpu_vreg_t(vgpu, vgtif_reg(avail_rs.mappable_gmadr.base)) = |
82d375d1 | 52 | vgpu_aperture_gmadr_base(vgpu); |
90551a12 | 53 | vgpu_vreg_t(vgpu, vgtif_reg(avail_rs.mappable_gmadr.size)) = |
82d375d1 | 54 | vgpu_aperture_sz(vgpu); |
90551a12 | 55 | vgpu_vreg_t(vgpu, vgtif_reg(avail_rs.nonmappable_gmadr.base)) = |
82d375d1 | 56 | vgpu_hidden_gmadr_base(vgpu); |
90551a12 | 57 | vgpu_vreg_t(vgpu, vgtif_reg(avail_rs.nonmappable_gmadr.size)) = |
82d375d1 ZW |
58 | vgpu_hidden_sz(vgpu); |
59 | ||
90551a12 | 60 | vgpu_vreg_t(vgpu, vgtif_reg(avail_rs.fence_num)) = vgpu_fence_sz(vgpu); |
82d375d1 | 61 | |
1c6ccad8 TZ |
62 | vgpu_vreg_t(vgpu, vgtif_reg(cursor_x_hot)) = UINT_MAX; |
63 | vgpu_vreg_t(vgpu, vgtif_reg(cursor_y_hot)) = UINT_MAX; | |
64 | ||
82d375d1 ZW |
65 | gvt_dbg_core("Populate PVINFO PAGE for vGPU %d\n", vgpu->id); |
66 | gvt_dbg_core("aperture base [GMADR] 0x%llx size 0x%llx\n", | |
67 | vgpu_aperture_gmadr_base(vgpu), vgpu_aperture_sz(vgpu)); | |
68 | gvt_dbg_core("hidden base [GMADR] 0x%llx size=0x%llx\n", | |
69 | vgpu_hidden_gmadr_base(vgpu), vgpu_hidden_sz(vgpu)); | |
70 | gvt_dbg_core("fence size %d\n", vgpu_fence_sz(vgpu)); | |
71 | ||
72 | WARN_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE); | |
73 | } | |
74 | ||
bc90d097 PG |
75 | #define VGPU_MAX_WEIGHT 16 |
76 | #define VGPU_WEIGHT(vgpu_num) \ | |
77 | (VGPU_MAX_WEIGHT / (vgpu_num)) | |
78 | ||
191020b6 ZW |
79 | static struct { |
80 | unsigned int low_mm; | |
81 | unsigned int high_mm; | |
82 | unsigned int fence; | |
bc90d097 PG |
83 | |
84 | /* A vGPU with a weight of 8 will get twice as much GPU as a vGPU | |
85 | * with a weight of 4 on a contended host, different vGPU type has | |
86 | * different weight set. Legal weights range from 1 to 16. | |
87 | */ | |
88 | unsigned int weight; | |
d1a513be | 89 | enum intel_vgpu_edid edid; |
191020b6 ZW |
90 | char *name; |
91 | } vgpu_types[] = { | |
92 | /* Fixed vGPU type table */ | |
bc90d097 PG |
93 | { MB_TO_BYTES(64), MB_TO_BYTES(384), 4, VGPU_WEIGHT(8), GVT_EDID_1024_768, "8" }, |
94 | { MB_TO_BYTES(128), MB_TO_BYTES(512), 4, VGPU_WEIGHT(4), GVT_EDID_1920_1200, "4" }, | |
95 | { MB_TO_BYTES(256), MB_TO_BYTES(1024), 4, VGPU_WEIGHT(2), GVT_EDID_1920_1200, "2" }, | |
96 | { MB_TO_BYTES(512), MB_TO_BYTES(2048), 4, VGPU_WEIGHT(1), GVT_EDID_1920_1200, "1" }, | |
191020b6 ZW |
97 | }; |
98 | ||
1f31c829 ZW |
99 | /** |
100 | * intel_gvt_init_vgpu_types - initialize vGPU type list | |
101 | * @gvt : GVT device | |
102 | * | |
103 | * Initialize vGPU type list based on available resource. | |
104 | * | |
105 | */ | |
106 | int intel_gvt_init_vgpu_types(struct intel_gvt *gvt) | |
107 | { | |
108 | unsigned int num_types; | |
2d6ceb8e | 109 | unsigned int i, low_avail, high_avail; |
1f31c829 ZW |
110 | unsigned int min_low; |
111 | ||
112 | /* vGPU type name is defined as GVTg_Vx_y which contains | |
191020b6 ZW |
113 | * physical GPU generation type (e.g V4 as BDW server, V5 as |
114 | * SKL server). | |
1f31c829 ZW |
115 | * |
116 | * Depend on physical SKU resource, might see vGPU types like | |
117 | * GVTg_V4_8, GVTg_V4_4, GVTg_V4_2, etc. We can create | |
118 | * different types of vGPU on same physical GPU depending on | |
119 | * available resource. Each vGPU type will have "avail_instance" | |
120 | * to indicate how many vGPU instance can be created for this | |
121 | * type. | |
122 | * | |
1f31c829 | 123 | */ |
2d6ceb8e ZW |
124 | low_avail = gvt_aperture_sz(gvt) - HOST_LOW_GM_SIZE; |
125 | high_avail = gvt_hidden_sz(gvt) - HOST_HIGH_GM_SIZE; | |
191020b6 | 126 | num_types = sizeof(vgpu_types) / sizeof(vgpu_types[0]); |
1f31c829 | 127 | |
6396bb22 | 128 | gvt->types = kcalloc(num_types, sizeof(struct intel_vgpu_type), |
1f31c829 ZW |
129 | GFP_KERNEL); |
130 | if (!gvt->types) | |
131 | return -ENOMEM; | |
132 | ||
133 | min_low = MB_TO_BYTES(32); | |
134 | for (i = 0; i < num_types; ++i) { | |
191020b6 | 135 | if (low_avail / vgpu_types[i].low_mm == 0) |
1f31c829 | 136 | break; |
191020b6 ZW |
137 | |
138 | gvt->types[i].low_gm_size = vgpu_types[i].low_mm; | |
139 | gvt->types[i].high_gm_size = vgpu_types[i].high_mm; | |
140 | gvt->types[i].fence = vgpu_types[i].fence; | |
bc90d097 PG |
141 | |
142 | if (vgpu_types[i].weight < 1 || | |
143 | vgpu_types[i].weight > VGPU_MAX_WEIGHT) | |
144 | return -EINVAL; | |
145 | ||
146 | gvt->types[i].weight = vgpu_types[i].weight; | |
d1a513be | 147 | gvt->types[i].resolution = vgpu_types[i].edid; |
191020b6 ZW |
148 | gvt->types[i].avail_instance = min(low_avail / vgpu_types[i].low_mm, |
149 | high_avail / vgpu_types[i].high_mm); | |
1f31c829 | 150 | |
cf819eff | 151 | if (IS_GEN(gvt->dev_priv, 8)) |
191020b6 ZW |
152 | sprintf(gvt->types[i].name, "GVTg_V4_%s", |
153 | vgpu_types[i].name); | |
cf819eff | 154 | else if (IS_GEN(gvt->dev_priv, 9)) |
191020b6 ZW |
155 | sprintf(gvt->types[i].name, "GVTg_V5_%s", |
156 | vgpu_types[i].name); | |
1f31c829 | 157 | |
bc90d097 | 158 | gvt_dbg_core("type[%d]: %s avail %u low %u high %u fence %u weight %u res %s\n", |
191020b6 | 159 | i, gvt->types[i].name, |
1f31c829 ZW |
160 | gvt->types[i].avail_instance, |
161 | gvt->types[i].low_gm_size, | |
d1a513be | 162 | gvt->types[i].high_gm_size, gvt->types[i].fence, |
bc90d097 | 163 | gvt->types[i].weight, |
d1a513be | 164 | vgpu_edid_str(gvt->types[i].resolution)); |
1f31c829 ZW |
165 | } |
166 | ||
167 | gvt->num_types = i; | |
168 | return 0; | |
169 | } | |
170 | ||
171 | void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt) | |
172 | { | |
173 | kfree(gvt->types); | |
174 | } | |
175 | ||
176 | static void intel_gvt_update_vgpu_types(struct intel_gvt *gvt) | |
177 | { | |
178 | int i; | |
179 | unsigned int low_gm_avail, high_gm_avail, fence_avail; | |
191020b6 | 180 | unsigned int low_gm_min, high_gm_min, fence_min; |
1f31c829 ZW |
181 | |
182 | /* Need to depend on maxium hw resource size but keep on | |
183 | * static config for now. | |
184 | */ | |
2d6ceb8e | 185 | low_gm_avail = gvt_aperture_sz(gvt) - HOST_LOW_GM_SIZE - |
1f31c829 | 186 | gvt->gm.vgpu_allocated_low_gm_size; |
2d6ceb8e | 187 | high_gm_avail = gvt_hidden_sz(gvt) - HOST_HIGH_GM_SIZE - |
1f31c829 ZW |
188 | gvt->gm.vgpu_allocated_high_gm_size; |
189 | fence_avail = gvt_fence_sz(gvt) - HOST_FENCE - | |
190 | gvt->fence.vgpu_allocated_fence_num; | |
191 | ||
192 | for (i = 0; i < gvt->num_types; i++) { | |
193 | low_gm_min = low_gm_avail / gvt->types[i].low_gm_size; | |
194 | high_gm_min = high_gm_avail / gvt->types[i].high_gm_size; | |
195 | fence_min = fence_avail / gvt->types[i].fence; | |
191020b6 ZW |
196 | gvt->types[i].avail_instance = min(min(low_gm_min, high_gm_min), |
197 | fence_min); | |
1f31c829 | 198 | |
191020b6 ZW |
199 | gvt_dbg_core("update type[%d]: %s avail %u low %u high %u fence %u\n", |
200 | i, gvt->types[i].name, | |
1f31c829 ZW |
201 | gvt->types[i].avail_instance, gvt->types[i].low_gm_size, |
202 | gvt->types[i].high_gm_size, gvt->types[i].fence); | |
203 | } | |
204 | } | |
205 | ||
82d375d1 | 206 | /** |
b79c52ae | 207 | * intel_gvt_active_vgpu - activate a virtual GPU |
82d375d1 ZW |
208 | * @vgpu: virtual GPU |
209 | * | |
b79c52ae | 210 | * This function is called when user wants to activate a virtual GPU. |
82d375d1 ZW |
211 | * |
212 | */ | |
b79c52ae ZW |
213 | void intel_gvt_activate_vgpu(struct intel_vgpu *vgpu) |
214 | { | |
6d44694d | 215 | mutex_lock(&vgpu->vgpu_lock); |
b79c52ae | 216 | vgpu->active = true; |
6d44694d | 217 | mutex_unlock(&vgpu->vgpu_lock); |
b79c52ae ZW |
218 | } |
219 | ||
220 | /** | |
221 | * intel_gvt_deactive_vgpu - deactivate a virtual GPU | |
222 | * @vgpu: virtual GPU | |
223 | * | |
224 | * This function is called when user wants to deactivate a virtual GPU. | |
f9090d4c | 225 | * The virtual GPU will be stopped. |
b79c52ae ZW |
226 | * |
227 | */ | |
228 | void intel_gvt_deactivate_vgpu(struct intel_vgpu *vgpu) | |
82d375d1 | 229 | { |
f25a49ab | 230 | mutex_lock(&vgpu->vgpu_lock); |
82d375d1 ZW |
231 | |
232 | vgpu->active = false; | |
82d375d1 | 233 | |
1406a14b | 234 | if (atomic_read(&vgpu->submission.running_workload_num)) { |
f25a49ab | 235 | mutex_unlock(&vgpu->vgpu_lock); |
4b63960e | 236 | intel_gvt_wait_vgpu_idle(vgpu); |
f25a49ab | 237 | mutex_lock(&vgpu->vgpu_lock); |
4b63960e ZW |
238 | } |
239 | ||
240 | intel_vgpu_stop_schedule(vgpu); | |
b79c52ae | 241 | |
f25a49ab | 242 | mutex_unlock(&vgpu->vgpu_lock); |
b79c52ae ZW |
243 | } |
244 | ||
f9090d4c HY |
245 | /** |
246 | * intel_gvt_release_vgpu - release a virtual GPU | |
247 | * @vgpu: virtual GPU | |
248 | * | |
249 | * This function is called when user wants to release a virtual GPU. | |
250 | * The virtual GPU will be stopped and all runtime information will be | |
251 | * destroyed. | |
252 | * | |
253 | */ | |
254 | void intel_gvt_release_vgpu(struct intel_vgpu *vgpu) | |
255 | { | |
256 | intel_gvt_deactivate_vgpu(vgpu); | |
257 | ||
258 | mutex_lock(&vgpu->vgpu_lock); | |
259 | intel_vgpu_clean_workloads(vgpu, ALL_ENGINES); | |
260 | intel_vgpu_dmabuf_cleanup(vgpu); | |
261 | mutex_unlock(&vgpu->vgpu_lock); | |
262 | } | |
263 | ||
b79c52ae ZW |
264 | /** |
265 | * intel_gvt_destroy_vgpu - destroy a virtual GPU | |
266 | * @vgpu: virtual GPU | |
267 | * | |
268 | * This function is called when user wants to destroy a virtual GPU. | |
269 | * | |
270 | */ | |
271 | void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu) | |
272 | { | |
273 | struct intel_gvt *gvt = vgpu->gvt; | |
274 | ||
b79c52ae ZW |
275 | WARN(vgpu->active, "vGPU is still active!\n"); |
276 | ||
04d6067f ZW |
277 | /* |
278 | * remove idr first so later clean can judge if need to stop | |
279 | * service if no active vgpu. | |
280 | */ | |
281 | mutex_lock(&gvt->lock); | |
282 | idr_remove(&gvt->vgpu_idr, vgpu->id); | |
283 | mutex_unlock(&gvt->lock); | |
284 | ||
285 | mutex_lock(&vgpu->vgpu_lock); | |
bc7b0be3 | 286 | intel_gvt_debugfs_remove_vgpu(vgpu); |
4b63960e | 287 | intel_vgpu_clean_sched_policy(vgpu); |
874b6a91 | 288 | intel_vgpu_clean_submission(vgpu); |
04d348ae | 289 | intel_vgpu_clean_display(vgpu); |
4d60c5fd | 290 | intel_vgpu_clean_opregion(vgpu); |
7759ca3a | 291 | intel_vgpu_reset_ggtt(vgpu, true); |
2707e444 | 292 | intel_vgpu_clean_gtt(vgpu); |
82d375d1 ZW |
293 | intel_gvt_hypervisor_detach_vgpu(vgpu); |
294 | intel_vgpu_free_resource(vgpu); | |
cdcc4347 | 295 | intel_vgpu_clean_mmio(vgpu); |
e546e281 | 296 | intel_vgpu_dmabuf_cleanup(vgpu); |
f25a49ab | 297 | mutex_unlock(&vgpu->vgpu_lock); |
82d375d1 | 298 | |
f25a49ab | 299 | mutex_lock(&gvt->lock); |
f25a49ab CX |
300 | if (idr_is_empty(&gvt->vgpu_idr)) |
301 | intel_gvt_clean_irq(gvt); | |
1f31c829 | 302 | intel_gvt_update_vgpu_types(gvt); |
82d375d1 | 303 | mutex_unlock(&gvt->lock); |
f25a49ab CX |
304 | |
305 | vfree(vgpu); | |
82d375d1 ZW |
306 | } |
307 | ||
afe04fbe PG |
308 | #define IDLE_VGPU_IDR 0 |
309 | ||
310 | /** | |
311 | * intel_gvt_create_idle_vgpu - create an idle virtual GPU | |
312 | * @gvt: GVT device | |
313 | * | |
314 | * This function is called when user wants to create an idle virtual GPU. | |
315 | * | |
316 | * Returns: | |
317 | * pointer to intel_vgpu, error pointer if failed. | |
318 | */ | |
319 | struct intel_vgpu *intel_gvt_create_idle_vgpu(struct intel_gvt *gvt) | |
320 | { | |
321 | struct intel_vgpu *vgpu; | |
322 | enum intel_engine_id i; | |
323 | int ret; | |
324 | ||
325 | vgpu = vzalloc(sizeof(*vgpu)); | |
326 | if (!vgpu) | |
327 | return ERR_PTR(-ENOMEM); | |
328 | ||
329 | vgpu->id = IDLE_VGPU_IDR; | |
330 | vgpu->gvt = gvt; | |
f25a49ab | 331 | mutex_init(&vgpu->vgpu_lock); |
afe04fbe PG |
332 | |
333 | for (i = 0; i < I915_NUM_ENGINES; i++) | |
1406a14b | 334 | INIT_LIST_HEAD(&vgpu->submission.workload_q_head[i]); |
afe04fbe PG |
335 | |
336 | ret = intel_vgpu_init_sched_policy(vgpu); | |
337 | if (ret) | |
338 | goto out_free_vgpu; | |
339 | ||
340 | vgpu->active = false; | |
341 | ||
342 | return vgpu; | |
343 | ||
344 | out_free_vgpu: | |
345 | vfree(vgpu); | |
346 | return ERR_PTR(ret); | |
347 | } | |
348 | ||
349 | /** | |
350 | * intel_gvt_destroy_vgpu - destroy an idle virtual GPU | |
351 | * @vgpu: virtual GPU | |
352 | * | |
353 | * This function is called when user wants to destroy an idle virtual GPU. | |
354 | * | |
355 | */ | |
356 | void intel_gvt_destroy_idle_vgpu(struct intel_vgpu *vgpu) | |
357 | { | |
f25a49ab | 358 | mutex_lock(&vgpu->vgpu_lock); |
afe04fbe | 359 | intel_vgpu_clean_sched_policy(vgpu); |
f25a49ab CX |
360 | mutex_unlock(&vgpu->vgpu_lock); |
361 | ||
afe04fbe PG |
362 | vfree(vgpu); |
363 | } | |
364 | ||
1f31c829 | 365 | static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt, |
82d375d1 ZW |
366 | struct intel_vgpu_creation_params *param) |
367 | { | |
368 | struct intel_vgpu *vgpu; | |
369 | int ret; | |
370 | ||
371 | gvt_dbg_core("handle %llu low %llu MB high %llu MB fence %llu\n", | |
372 | param->handle, param->low_gm_sz, param->high_gm_sz, | |
373 | param->fence_sz); | |
374 | ||
375 | vgpu = vzalloc(sizeof(*vgpu)); | |
376 | if (!vgpu) | |
377 | return ERR_PTR(-ENOMEM); | |
378 | ||
afe04fbe PG |
379 | ret = idr_alloc(&gvt->vgpu_idr, vgpu, IDLE_VGPU_IDR + 1, GVT_MAX_VGPU, |
380 | GFP_KERNEL); | |
82d375d1 ZW |
381 | if (ret < 0) |
382 | goto out_free_vgpu; | |
383 | ||
384 | vgpu->id = ret; | |
385 | vgpu->handle = param->handle; | |
386 | vgpu->gvt = gvt; | |
bc90d097 | 387 | vgpu->sched_ctl.weight = param->weight; |
f25a49ab | 388 | mutex_init(&vgpu->vgpu_lock); |
d6c6113b | 389 | mutex_init(&vgpu->dmabuf_lock); |
e546e281 | 390 | INIT_LIST_HEAD(&vgpu->dmabuf_obj_list_head); |
e502a2af | 391 | INIT_RADIX_TREE(&vgpu->page_track_tree, GFP_KERNEL); |
e546e281 | 392 | idr_init(&vgpu->object_idr); |
536fc234 | 393 | intel_vgpu_init_cfg_space(vgpu, param->primary); |
82d375d1 | 394 | |
cdcc4347 | 395 | ret = intel_vgpu_init_mmio(vgpu); |
82d375d1 | 396 | if (ret) |
4e537891 | 397 | goto out_clean_idr; |
82d375d1 ZW |
398 | |
399 | ret = intel_vgpu_alloc_resource(vgpu, param); | |
400 | if (ret) | |
401 | goto out_clean_vgpu_mmio; | |
402 | ||
403 | populate_pvinfo_page(vgpu); | |
404 | ||
405 | ret = intel_gvt_hypervisor_attach_vgpu(vgpu); | |
406 | if (ret) | |
407 | goto out_clean_vgpu_resource; | |
408 | ||
2707e444 ZW |
409 | ret = intel_vgpu_init_gtt(vgpu); |
410 | if (ret) | |
411 | goto out_detach_hypervisor_vgpu; | |
412 | ||
4dff110b | 413 | ret = intel_vgpu_init_opregion(vgpu); |
04d348ae | 414 | if (ret) |
8f89743b | 415 | goto out_clean_gtt; |
04d348ae | 416 | |
4dff110b XZ |
417 | ret = intel_vgpu_init_display(vgpu, param->resolution); |
418 | if (ret) | |
419 | goto out_clean_opregion; | |
420 | ||
874b6a91 | 421 | ret = intel_vgpu_setup_submission(vgpu); |
e4734057 | 422 | if (ret) |
ad1d3636 | 423 | goto out_clean_display; |
e4734057 | 424 | |
4b63960e ZW |
425 | ret = intel_vgpu_init_sched_policy(vgpu); |
426 | if (ret) | |
ad1d3636 | 427 | goto out_clean_submission; |
4b63960e | 428 | |
f8871ec8 | 429 | intel_gvt_debugfs_add_vgpu(vgpu); |
bc7b0be3 | 430 | |
b851adea TZ |
431 | ret = intel_gvt_hypervisor_set_opregion(vgpu); |
432 | if (ret) | |
433 | goto out_clean_sched_policy; | |
434 | ||
39c68e87 HY |
435 | /*TODO: add more platforms support */ |
436 | if (IS_SKYLAKE(gvt->dev_priv) || IS_KABYLAKE(gvt->dev_priv)) | |
437 | ret = intel_gvt_hypervisor_set_edid(vgpu, PORT_D); | |
438 | if (ret) | |
439 | goto out_clean_sched_policy; | |
440 | ||
82d375d1 ZW |
441 | return vgpu; |
442 | ||
bc7b0be3 CD |
443 | out_clean_sched_policy: |
444 | intel_vgpu_clean_sched_policy(vgpu); | |
ad1d3636 | 445 | out_clean_submission: |
874b6a91 | 446 | intel_vgpu_clean_submission(vgpu); |
8453d674 ZW |
447 | out_clean_display: |
448 | intel_vgpu_clean_display(vgpu); | |
4dff110b XZ |
449 | out_clean_opregion: |
450 | intel_vgpu_clean_opregion(vgpu); | |
4d60c5fd ZW |
451 | out_clean_gtt: |
452 | intel_vgpu_clean_gtt(vgpu); | |
2707e444 ZW |
453 | out_detach_hypervisor_vgpu: |
454 | intel_gvt_hypervisor_detach_vgpu(vgpu); | |
82d375d1 ZW |
455 | out_clean_vgpu_resource: |
456 | intel_vgpu_free_resource(vgpu); | |
457 | out_clean_vgpu_mmio: | |
cdcc4347 | 458 | intel_vgpu_clean_mmio(vgpu); |
4e537891 JS |
459 | out_clean_idr: |
460 | idr_remove(&gvt->vgpu_idr, vgpu->id); | |
82d375d1 ZW |
461 | out_free_vgpu: |
462 | vfree(vgpu); | |
82d375d1 ZW |
463 | return ERR_PTR(ret); |
464 | } | |
1f31c829 ZW |
465 | |
466 | /** | |
467 | * intel_gvt_create_vgpu - create a virtual GPU | |
468 | * @gvt: GVT device | |
469 | * @type: type of the vGPU to create | |
470 | * | |
471 | * This function is called when user wants to create a virtual GPU. | |
472 | * | |
473 | * Returns: | |
474 | * pointer to intel_vgpu, error pointer if failed. | |
475 | */ | |
476 | struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt, | |
477 | struct intel_vgpu_type *type) | |
478 | { | |
479 | struct intel_vgpu_creation_params param; | |
480 | struct intel_vgpu *vgpu; | |
481 | ||
482 | param.handle = 0; | |
e992faee | 483 | param.primary = 1; |
1f31c829 ZW |
484 | param.low_gm_sz = type->low_gm_size; |
485 | param.high_gm_sz = type->high_gm_size; | |
486 | param.fence_sz = type->fence; | |
bc90d097 | 487 | param.weight = type->weight; |
d1a513be | 488 | param.resolution = type->resolution; |
1f31c829 ZW |
489 | |
490 | /* XXX current param based on MB */ | |
491 | param.low_gm_sz = BYTES_TO_MB(param.low_gm_sz); | |
492 | param.high_gm_sz = BYTES_TO_MB(param.high_gm_sz); | |
493 | ||
f25a49ab | 494 | mutex_lock(&gvt->lock); |
1f31c829 | 495 | vgpu = __intel_gvt_create_vgpu(gvt, ¶m); |
f25a49ab CX |
496 | if (!IS_ERR(vgpu)) |
497 | /* calculate left instance change for types */ | |
498 | intel_gvt_update_vgpu_types(gvt); | |
499 | mutex_unlock(&gvt->lock); | |
1f31c829 ZW |
500 | |
501 | return vgpu; | |
502 | } | |
9ec1e66b JS |
503 | |
504 | /** | |
cfe65f40 CD |
505 | * intel_gvt_reset_vgpu_locked - reset a virtual GPU by DMLR or GT reset |
506 | * @vgpu: virtual GPU | |
507 | * @dmlr: vGPU Device Model Level Reset or GT Reset | |
508 | * @engine_mask: engines to reset for GT reset | |
509 | * | |
510 | * This function is called when user wants to reset a virtual GPU through | |
f25a49ab | 511 | * device model reset or GT reset. The caller should hold the vgpu lock. |
cfe65f40 CD |
512 | * |
513 | * vGPU Device Model Level Reset (DMLR) simulates the PCI level reset to reset | |
514 | * the whole vGPU to default state as when it is created. This vGPU function | |
515 | * is required both for functionary and security concerns.The ultimate goal | |
516 | * of vGPU FLR is that reuse a vGPU instance by virtual machines. When we | |
517 | * assign a vGPU to a virtual machine we must isse such reset first. | |
518 | * | |
519 | * Full GT Reset and Per-Engine GT Reset are soft reset flow for GPU engines | |
520 | * (Render, Blitter, Video, Video Enhancement). It is defined by GPU Spec. | |
521 | * Unlike the FLR, GT reset only reset particular resource of a vGPU per | |
522 | * the reset request. Guest driver can issue a GT reset by programming the | |
523 | * virtual GDRST register to reset specific virtual GPU engine or all | |
524 | * engines. | |
525 | * | |
526 | * The parameter dev_level is to identify if we will do DMLR or GT reset. | |
527 | * The parameter engine_mask is to specific the engines that need to be | |
528 | * resetted. If value ALL_ENGINES is given for engine_mask, it means | |
529 | * the caller requests a full GT reset that we will reset all virtual | |
530 | * GPU engines. For FLR, engine_mask is ignored. | |
531 | */ | |
532 | void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr, | |
3a891a62 | 533 | intel_engine_mask_t engine_mask) |
cfe65f40 CD |
534 | { |
535 | struct intel_gvt *gvt = vgpu->gvt; | |
536 | struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; | |
3a891a62 | 537 | intel_engine_mask_t resetting_eng = dmlr ? ALL_ENGINES : engine_mask; |
cfe65f40 CD |
538 | |
539 | gvt_dbg_core("------------------------------------------\n"); | |
540 | gvt_dbg_core("resseting vgpu%d, dmlr %d, engine_mask %08x\n", | |
541 | vgpu->id, dmlr, engine_mask); | |
6184cc8d CD |
542 | |
543 | vgpu->resetting_eng = resetting_eng; | |
cfe65f40 CD |
544 | |
545 | intel_vgpu_stop_schedule(vgpu); | |
546 | /* | |
547 | * The current_vgpu will set to NULL after stopping the | |
548 | * scheduler when the reset is triggered by current vgpu. | |
549 | */ | |
550 | if (scheduler->current_vgpu == NULL) { | |
f25a49ab | 551 | mutex_unlock(&vgpu->vgpu_lock); |
cfe65f40 | 552 | intel_gvt_wait_vgpu_idle(vgpu); |
f25a49ab | 553 | mutex_lock(&vgpu->vgpu_lock); |
cfe65f40 CD |
554 | } |
555 | ||
06bb372f | 556 | intel_vgpu_reset_submission(vgpu, resetting_eng); |
cfe65f40 CD |
557 | /* full GPU reset or device model level reset */ |
558 | if (engine_mask == ALL_ENGINES || dmlr) { | |
7569a06d | 559 | intel_vgpu_select_submission_ops(vgpu, ALL_ENGINES, 0); |
730c8ead | 560 | intel_vgpu_invalidate_ppgtt(vgpu); |
615c16a9 | 561 | /*fence will not be reset during virtual reset */ |
4d3e67bb CD |
562 | if (dmlr) { |
563 | intel_vgpu_reset_gtt(vgpu); | |
615c16a9 | 564 | intel_vgpu_reset_resource(vgpu); |
4d3e67bb | 565 | } |
615c16a9 | 566 | |
567 | intel_vgpu_reset_mmio(vgpu, dmlr); | |
cfe65f40 CD |
568 | populate_pvinfo_page(vgpu); |
569 | ||
fd64be63 | 570 | if (dmlr) { |
3eb55e6f | 571 | intel_vgpu_reset_display(vgpu); |
cfe65f40 | 572 | intel_vgpu_reset_cfg_space(vgpu); |
fd64be63 MH |
573 | /* only reset the failsafe mode when dmlr reset */ |
574 | vgpu->failsafe = false; | |
575 | vgpu->pv_notified = false; | |
576 | } | |
cfe65f40 CD |
577 | } |
578 | ||
6184cc8d | 579 | vgpu->resetting_eng = 0; |
cfe65f40 CD |
580 | gvt_dbg_core("reset vgpu%d done\n", vgpu->id); |
581 | gvt_dbg_core("------------------------------------------\n"); | |
582 | } | |
583 | ||
584 | /** | |
585 | * intel_gvt_reset_vgpu - reset a virtual GPU (Function Level) | |
9ec1e66b JS |
586 | * @vgpu: virtual GPU |
587 | * | |
588 | * This function is called when user wants to reset a virtual GPU. | |
589 | * | |
590 | */ | |
591 | void intel_gvt_reset_vgpu(struct intel_vgpu *vgpu) | |
592 | { | |
f25a49ab | 593 | mutex_lock(&vgpu->vgpu_lock); |
cfe65f40 | 594 | intel_gvt_reset_vgpu_locked(vgpu, true, 0); |
f25a49ab | 595 | mutex_unlock(&vgpu->vgpu_lock); |
9ec1e66b | 596 | } |