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