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