]>
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 | |
90551a12 ZW |
47 | vgpu_vreg_t(vgpu, vgtif_reg(vgt_caps)) = VGT_CAPS_FULL_48BIT_PPGTT; |
48 | vgpu_vreg_t(vgpu, vgtif_reg(vgt_caps)) |= VGT_CAPS_HWSP_EMULATION; | |
a2ae95af | 49 | |
90551a12 | 50 | vgpu_vreg_t(vgpu, vgtif_reg(avail_rs.mappable_gmadr.base)) = |
82d375d1 | 51 | vgpu_aperture_gmadr_base(vgpu); |
90551a12 | 52 | vgpu_vreg_t(vgpu, vgtif_reg(avail_rs.mappable_gmadr.size)) = |
82d375d1 | 53 | vgpu_aperture_sz(vgpu); |
90551a12 | 54 | vgpu_vreg_t(vgpu, vgtif_reg(avail_rs.nonmappable_gmadr.base)) = |
82d375d1 | 55 | vgpu_hidden_gmadr_base(vgpu); |
90551a12 | 56 | vgpu_vreg_t(vgpu, vgtif_reg(avail_rs.nonmappable_gmadr.size)) = |
82d375d1 ZW |
57 | vgpu_hidden_sz(vgpu); |
58 | ||
90551a12 | 59 | vgpu_vreg_t(vgpu, vgtif_reg(avail_rs.fence_num)) = vgpu_fence_sz(vgpu); |
82d375d1 ZW |
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); | |
e546e281 | 239 | intel_vgpu_dmabuf_cleanup(vgpu); |
b79c52ae ZW |
240 | |
241 | mutex_unlock(&gvt->lock); | |
242 | } | |
243 | ||
244 | /** | |
245 | * intel_gvt_destroy_vgpu - destroy a virtual GPU | |
246 | * @vgpu: virtual GPU | |
247 | * | |
248 | * This function is called when user wants to destroy a virtual GPU. | |
249 | * | |
250 | */ | |
251 | void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu) | |
252 | { | |
253 | struct intel_gvt *gvt = vgpu->gvt; | |
254 | ||
255 | mutex_lock(&gvt->lock); | |
256 | ||
257 | WARN(vgpu->active, "vGPU is still active!\n"); | |
258 | ||
bc7b0be3 | 259 | intel_gvt_debugfs_remove_vgpu(vgpu); |
b79c52ae | 260 | idr_remove(&gvt->vgpu_idr, vgpu->id); |
14b4434b ZW |
261 | if (idr_is_empty(&gvt->vgpu_idr)) |
262 | intel_gvt_clean_irq(gvt); | |
4b63960e | 263 | intel_vgpu_clean_sched_policy(vgpu); |
874b6a91 | 264 | intel_vgpu_clean_submission(vgpu); |
04d348ae | 265 | intel_vgpu_clean_display(vgpu); |
4d60c5fd | 266 | intel_vgpu_clean_opregion(vgpu); |
2707e444 | 267 | intel_vgpu_clean_gtt(vgpu); |
82d375d1 ZW |
268 | intel_gvt_hypervisor_detach_vgpu(vgpu); |
269 | intel_vgpu_free_resource(vgpu); | |
cdcc4347 | 270 | intel_vgpu_clean_mmio(vgpu); |
e546e281 | 271 | intel_vgpu_dmabuf_cleanup(vgpu); |
82d375d1 ZW |
272 | vfree(vgpu); |
273 | ||
1f31c829 | 274 | intel_gvt_update_vgpu_types(gvt); |
82d375d1 ZW |
275 | mutex_unlock(&gvt->lock); |
276 | } | |
277 | ||
afe04fbe PG |
278 | #define IDLE_VGPU_IDR 0 |
279 | ||
280 | /** | |
281 | * intel_gvt_create_idle_vgpu - create an idle virtual GPU | |
282 | * @gvt: GVT device | |
283 | * | |
284 | * This function is called when user wants to create an idle virtual GPU. | |
285 | * | |
286 | * Returns: | |
287 | * pointer to intel_vgpu, error pointer if failed. | |
288 | */ | |
289 | struct intel_vgpu *intel_gvt_create_idle_vgpu(struct intel_gvt *gvt) | |
290 | { | |
291 | struct intel_vgpu *vgpu; | |
292 | enum intel_engine_id i; | |
293 | int ret; | |
294 | ||
295 | vgpu = vzalloc(sizeof(*vgpu)); | |
296 | if (!vgpu) | |
297 | return ERR_PTR(-ENOMEM); | |
298 | ||
299 | vgpu->id = IDLE_VGPU_IDR; | |
300 | vgpu->gvt = gvt; | |
301 | ||
302 | for (i = 0; i < I915_NUM_ENGINES; i++) | |
1406a14b | 303 | INIT_LIST_HEAD(&vgpu->submission.workload_q_head[i]); |
afe04fbe PG |
304 | |
305 | ret = intel_vgpu_init_sched_policy(vgpu); | |
306 | if (ret) | |
307 | goto out_free_vgpu; | |
308 | ||
309 | vgpu->active = false; | |
310 | ||
311 | return vgpu; | |
312 | ||
313 | out_free_vgpu: | |
314 | vfree(vgpu); | |
315 | return ERR_PTR(ret); | |
316 | } | |
317 | ||
318 | /** | |
319 | * intel_gvt_destroy_vgpu - destroy an idle virtual GPU | |
320 | * @vgpu: virtual GPU | |
321 | * | |
322 | * This function is called when user wants to destroy an idle virtual GPU. | |
323 | * | |
324 | */ | |
325 | void intel_gvt_destroy_idle_vgpu(struct intel_vgpu *vgpu) | |
326 | { | |
327 | intel_vgpu_clean_sched_policy(vgpu); | |
328 | vfree(vgpu); | |
329 | } | |
330 | ||
1f31c829 | 331 | static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt, |
82d375d1 ZW |
332 | struct intel_vgpu_creation_params *param) |
333 | { | |
334 | struct intel_vgpu *vgpu; | |
335 | int ret; | |
336 | ||
337 | gvt_dbg_core("handle %llu low %llu MB high %llu MB fence %llu\n", | |
338 | param->handle, param->low_gm_sz, param->high_gm_sz, | |
339 | param->fence_sz); | |
340 | ||
341 | vgpu = vzalloc(sizeof(*vgpu)); | |
342 | if (!vgpu) | |
343 | return ERR_PTR(-ENOMEM); | |
344 | ||
345 | mutex_lock(&gvt->lock); | |
346 | ||
afe04fbe PG |
347 | ret = idr_alloc(&gvt->vgpu_idr, vgpu, IDLE_VGPU_IDR + 1, GVT_MAX_VGPU, |
348 | GFP_KERNEL); | |
82d375d1 ZW |
349 | if (ret < 0) |
350 | goto out_free_vgpu; | |
351 | ||
352 | vgpu->id = ret; | |
353 | vgpu->handle = param->handle; | |
354 | vgpu->gvt = gvt; | |
bc90d097 | 355 | vgpu->sched_ctl.weight = param->weight; |
e546e281 | 356 | INIT_LIST_HEAD(&vgpu->dmabuf_obj_list_head); |
e502a2af | 357 | INIT_RADIX_TREE(&vgpu->page_track_tree, GFP_KERNEL); |
e546e281 | 358 | idr_init(&vgpu->object_idr); |
536fc234 | 359 | intel_vgpu_init_cfg_space(vgpu, param->primary); |
82d375d1 | 360 | |
cdcc4347 | 361 | ret = intel_vgpu_init_mmio(vgpu); |
82d375d1 | 362 | if (ret) |
4e537891 | 363 | goto out_clean_idr; |
82d375d1 ZW |
364 | |
365 | ret = intel_vgpu_alloc_resource(vgpu, param); | |
366 | if (ret) | |
367 | goto out_clean_vgpu_mmio; | |
368 | ||
369 | populate_pvinfo_page(vgpu); | |
370 | ||
371 | ret = intel_gvt_hypervisor_attach_vgpu(vgpu); | |
372 | if (ret) | |
373 | goto out_clean_vgpu_resource; | |
374 | ||
2707e444 ZW |
375 | ret = intel_vgpu_init_gtt(vgpu); |
376 | if (ret) | |
377 | goto out_detach_hypervisor_vgpu; | |
378 | ||
4dff110b | 379 | ret = intel_vgpu_init_opregion(vgpu); |
04d348ae | 380 | if (ret) |
8f89743b | 381 | goto out_clean_gtt; |
04d348ae | 382 | |
4dff110b XZ |
383 | ret = intel_vgpu_init_display(vgpu, param->resolution); |
384 | if (ret) | |
385 | goto out_clean_opregion; | |
386 | ||
874b6a91 | 387 | ret = intel_vgpu_setup_submission(vgpu); |
e4734057 | 388 | if (ret) |
ad1d3636 | 389 | goto out_clean_display; |
e4734057 | 390 | |
4b63960e ZW |
391 | ret = intel_vgpu_init_sched_policy(vgpu); |
392 | if (ret) | |
ad1d3636 | 393 | goto out_clean_submission; |
4b63960e | 394 | |
bc7b0be3 CD |
395 | ret = intel_gvt_debugfs_add_vgpu(vgpu); |
396 | if (ret) | |
397 | goto out_clean_sched_policy; | |
398 | ||
b851adea TZ |
399 | ret = intel_gvt_hypervisor_set_opregion(vgpu); |
400 | if (ret) | |
401 | goto out_clean_sched_policy; | |
402 | ||
82d375d1 ZW |
403 | mutex_unlock(&gvt->lock); |
404 | ||
405 | return vgpu; | |
406 | ||
bc7b0be3 CD |
407 | out_clean_sched_policy: |
408 | intel_vgpu_clean_sched_policy(vgpu); | |
ad1d3636 | 409 | out_clean_submission: |
874b6a91 | 410 | intel_vgpu_clean_submission(vgpu); |
8453d674 ZW |
411 | out_clean_display: |
412 | intel_vgpu_clean_display(vgpu); | |
4dff110b XZ |
413 | out_clean_opregion: |
414 | intel_vgpu_clean_opregion(vgpu); | |
4d60c5fd ZW |
415 | out_clean_gtt: |
416 | intel_vgpu_clean_gtt(vgpu); | |
2707e444 ZW |
417 | out_detach_hypervisor_vgpu: |
418 | intel_gvt_hypervisor_detach_vgpu(vgpu); | |
82d375d1 ZW |
419 | out_clean_vgpu_resource: |
420 | intel_vgpu_free_resource(vgpu); | |
421 | out_clean_vgpu_mmio: | |
cdcc4347 | 422 | intel_vgpu_clean_mmio(vgpu); |
4e537891 JS |
423 | out_clean_idr: |
424 | idr_remove(&gvt->vgpu_idr, vgpu->id); | |
82d375d1 ZW |
425 | out_free_vgpu: |
426 | vfree(vgpu); | |
427 | mutex_unlock(&gvt->lock); | |
428 | return ERR_PTR(ret); | |
429 | } | |
1f31c829 ZW |
430 | |
431 | /** | |
432 | * intel_gvt_create_vgpu - create a virtual GPU | |
433 | * @gvt: GVT device | |
434 | * @type: type of the vGPU to create | |
435 | * | |
436 | * This function is called when user wants to create a virtual GPU. | |
437 | * | |
438 | * Returns: | |
439 | * pointer to intel_vgpu, error pointer if failed. | |
440 | */ | |
441 | struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt, | |
442 | struct intel_vgpu_type *type) | |
443 | { | |
444 | struct intel_vgpu_creation_params param; | |
445 | struct intel_vgpu *vgpu; | |
446 | ||
447 | param.handle = 0; | |
e992faee | 448 | param.primary = 1; |
1f31c829 ZW |
449 | param.low_gm_sz = type->low_gm_size; |
450 | param.high_gm_sz = type->high_gm_size; | |
451 | param.fence_sz = type->fence; | |
bc90d097 | 452 | param.weight = type->weight; |
d1a513be | 453 | param.resolution = type->resolution; |
1f31c829 ZW |
454 | |
455 | /* XXX current param based on MB */ | |
456 | param.low_gm_sz = BYTES_TO_MB(param.low_gm_sz); | |
457 | param.high_gm_sz = BYTES_TO_MB(param.high_gm_sz); | |
458 | ||
459 | vgpu = __intel_gvt_create_vgpu(gvt, ¶m); | |
460 | if (IS_ERR(vgpu)) | |
461 | return vgpu; | |
462 | ||
463 | /* calculate left instance change for types */ | |
464 | intel_gvt_update_vgpu_types(gvt); | |
465 | ||
466 | return vgpu; | |
467 | } | |
9ec1e66b JS |
468 | |
469 | /** | |
cfe65f40 CD |
470 | * intel_gvt_reset_vgpu_locked - reset a virtual GPU by DMLR or GT reset |
471 | * @vgpu: virtual GPU | |
472 | * @dmlr: vGPU Device Model Level Reset or GT Reset | |
473 | * @engine_mask: engines to reset for GT reset | |
474 | * | |
475 | * This function is called when user wants to reset a virtual GPU through | |
476 | * device model reset or GT reset. The caller should hold the gvt lock. | |
477 | * | |
478 | * vGPU Device Model Level Reset (DMLR) simulates the PCI level reset to reset | |
479 | * the whole vGPU to default state as when it is created. This vGPU function | |
480 | * is required both for functionary and security concerns.The ultimate goal | |
481 | * of vGPU FLR is that reuse a vGPU instance by virtual machines. When we | |
482 | * assign a vGPU to a virtual machine we must isse such reset first. | |
483 | * | |
484 | * Full GT Reset and Per-Engine GT Reset are soft reset flow for GPU engines | |
485 | * (Render, Blitter, Video, Video Enhancement). It is defined by GPU Spec. | |
486 | * Unlike the FLR, GT reset only reset particular resource of a vGPU per | |
487 | * the reset request. Guest driver can issue a GT reset by programming the | |
488 | * virtual GDRST register to reset specific virtual GPU engine or all | |
489 | * engines. | |
490 | * | |
491 | * The parameter dev_level is to identify if we will do DMLR or GT reset. | |
492 | * The parameter engine_mask is to specific the engines that need to be | |
493 | * resetted. If value ALL_ENGINES is given for engine_mask, it means | |
494 | * the caller requests a full GT reset that we will reset all virtual | |
495 | * GPU engines. For FLR, engine_mask is ignored. | |
496 | */ | |
497 | void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr, | |
498 | unsigned int engine_mask) | |
499 | { | |
500 | struct intel_gvt *gvt = vgpu->gvt; | |
501 | struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; | |
6184cc8d | 502 | unsigned int resetting_eng = dmlr ? ALL_ENGINES : engine_mask; |
cfe65f40 CD |
503 | |
504 | gvt_dbg_core("------------------------------------------\n"); | |
505 | gvt_dbg_core("resseting vgpu%d, dmlr %d, engine_mask %08x\n", | |
506 | vgpu->id, dmlr, engine_mask); | |
6184cc8d CD |
507 | |
508 | vgpu->resetting_eng = resetting_eng; | |
cfe65f40 CD |
509 | |
510 | intel_vgpu_stop_schedule(vgpu); | |
511 | /* | |
512 | * The current_vgpu will set to NULL after stopping the | |
513 | * scheduler when the reset is triggered by current vgpu. | |
514 | */ | |
515 | if (scheduler->current_vgpu == NULL) { | |
516 | mutex_unlock(&gvt->lock); | |
517 | intel_gvt_wait_vgpu_idle(vgpu); | |
518 | mutex_lock(&gvt->lock); | |
519 | } | |
520 | ||
06bb372f | 521 | intel_vgpu_reset_submission(vgpu, resetting_eng); |
cfe65f40 CD |
522 | /* full GPU reset or device model level reset */ |
523 | if (engine_mask == ALL_ENGINES || dmlr) { | |
7569a06d | 524 | intel_vgpu_select_submission_ops(vgpu, ALL_ENGINES, 0); |
730c8ead | 525 | intel_vgpu_invalidate_ppgtt(vgpu); |
615c16a9 | 526 | /*fence will not be reset during virtual reset */ |
4d3e67bb CD |
527 | if (dmlr) { |
528 | intel_vgpu_reset_gtt(vgpu); | |
615c16a9 | 529 | intel_vgpu_reset_resource(vgpu); |
4d3e67bb | 530 | } |
615c16a9 | 531 | |
532 | intel_vgpu_reset_mmio(vgpu, dmlr); | |
cfe65f40 | 533 | populate_pvinfo_page(vgpu); |
6294b61b | 534 | intel_vgpu_reset_display(vgpu); |
cfe65f40 | 535 | |
fd64be63 | 536 | if (dmlr) { |
cfe65f40 | 537 | intel_vgpu_reset_cfg_space(vgpu); |
fd64be63 MH |
538 | /* only reset the failsafe mode when dmlr reset */ |
539 | vgpu->failsafe = false; | |
540 | vgpu->pv_notified = false; | |
541 | } | |
cfe65f40 CD |
542 | } |
543 | ||
6184cc8d | 544 | vgpu->resetting_eng = 0; |
cfe65f40 CD |
545 | gvt_dbg_core("reset vgpu%d done\n", vgpu->id); |
546 | gvt_dbg_core("------------------------------------------\n"); | |
547 | } | |
548 | ||
549 | /** | |
550 | * intel_gvt_reset_vgpu - reset a virtual GPU (Function Level) | |
9ec1e66b JS |
551 | * @vgpu: virtual GPU |
552 | * | |
553 | * This function is called when user wants to reset a virtual GPU. | |
554 | * | |
555 | */ | |
556 | void intel_gvt_reset_vgpu(struct intel_vgpu *vgpu) | |
557 | { | |
cfe65f40 CD |
558 | mutex_lock(&vgpu->gvt->lock); |
559 | intel_gvt_reset_vgpu_locked(vgpu, true, 0); | |
560 | mutex_unlock(&vgpu->gvt->lock); | |
9ec1e66b | 561 | } |