2 * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
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:
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
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
24 * Eddie Dong <eddie.dong@intel.com>
25 * Kevin Tian <kevin.tian@intel.com>
28 * Ping Gao <ping.a.gao@intel.com>
29 * Zhi Wang <zhi.a.wang@intel.com>
30 * Bing Niu <bing.niu@intel.com>
36 #include "i915_pvinfo.h"
38 static void clean_vgpu_mmio(struct intel_vgpu
*vgpu
)
40 vfree(vgpu
->mmio
.vreg
);
41 vgpu
->mmio
.vreg
= vgpu
->mmio
.sreg
= NULL
;
44 static int setup_vgpu_mmio(struct intel_vgpu
*vgpu
)
46 struct intel_gvt
*gvt
= vgpu
->gvt
;
47 const struct intel_gvt_device_info
*info
= &gvt
->device_info
;
49 vgpu
->mmio
.vreg
= vzalloc(info
->mmio_size
* 2);
53 vgpu
->mmio
.sreg
= vgpu
->mmio
.vreg
+ info
->mmio_size
;
55 memcpy(vgpu
->mmio
.vreg
, gvt
->firmware
.mmio
, info
->mmio_size
);
56 memcpy(vgpu
->mmio
.sreg
, gvt
->firmware
.mmio
, info
->mmio_size
);
58 vgpu_vreg(vgpu
, GEN6_GT_THREAD_STATUS_REG
) = 0;
60 /* set the bit 0:2(Core C-State ) to C0 */
61 vgpu_vreg(vgpu
, GEN6_GT_CORE_STATUS
) = 0;
65 static void setup_vgpu_cfg_space(struct intel_vgpu
*vgpu
,
66 struct intel_vgpu_creation_params
*param
)
68 struct intel_gvt
*gvt
= vgpu
->gvt
;
69 const struct intel_gvt_device_info
*info
= &gvt
->device_info
;
73 memcpy(vgpu_cfg_space(vgpu
), gvt
->firmware
.cfg_space
,
74 info
->cfg_space_size
);
76 if (!param
->primary
) {
77 vgpu_cfg_space(vgpu
)[PCI_CLASS_DEVICE
] =
78 INTEL_GVT_PCI_CLASS_VGA_OTHER
;
79 vgpu_cfg_space(vgpu
)[PCI_CLASS_PROG
] =
80 INTEL_GVT_PCI_CLASS_VGA_OTHER
;
83 /* Show guest that there isn't any stolen memory.*/
84 gmch_ctl
= (u16
*)(vgpu_cfg_space(vgpu
) + INTEL_GVT_PCI_GMCH_CONTROL
);
85 *gmch_ctl
&= ~(BDW_GMCH_GMS_MASK
<< BDW_GMCH_GMS_SHIFT
);
87 intel_vgpu_write_pci_bar(vgpu
, PCI_BASE_ADDRESS_2
,
88 gvt_aperture_pa_base(gvt
), true);
90 vgpu_cfg_space(vgpu
)[PCI_COMMAND
] &= ~(PCI_COMMAND_IO
92 | PCI_COMMAND_MASTER
);
94 * Clear the bar upper 32bit and let guest to assign the new value
96 memset(vgpu_cfg_space(vgpu
) + PCI_BASE_ADDRESS_1
, 0, 4);
97 memset(vgpu_cfg_space(vgpu
) + PCI_BASE_ADDRESS_3
, 0, 4);
99 for (i
= 0; i
< INTEL_GVT_MAX_BAR_NUM
; i
++) {
100 vgpu
->cfg_space
.bar
[i
].size
= pci_resource_len(
101 gvt
->dev_priv
->drm
.pdev
, i
* 2);
102 vgpu
->cfg_space
.bar
[i
].tracked
= false;
106 static void populate_pvinfo_page(struct intel_vgpu
*vgpu
)
108 /* setup the ballooning information */
109 vgpu_vreg64(vgpu
, vgtif_reg(magic
)) = VGT_MAGIC
;
110 vgpu_vreg(vgpu
, vgtif_reg(version_major
)) = 1;
111 vgpu_vreg(vgpu
, vgtif_reg(version_minor
)) = 0;
112 vgpu_vreg(vgpu
, vgtif_reg(display_ready
)) = 0;
113 vgpu_vreg(vgpu
, vgtif_reg(vgt_id
)) = vgpu
->id
;
114 vgpu_vreg(vgpu
, vgtif_reg(avail_rs
.mappable_gmadr
.base
)) =
115 vgpu_aperture_gmadr_base(vgpu
);
116 vgpu_vreg(vgpu
, vgtif_reg(avail_rs
.mappable_gmadr
.size
)) =
117 vgpu_aperture_sz(vgpu
);
118 vgpu_vreg(vgpu
, vgtif_reg(avail_rs
.nonmappable_gmadr
.base
)) =
119 vgpu_hidden_gmadr_base(vgpu
);
120 vgpu_vreg(vgpu
, vgtif_reg(avail_rs
.nonmappable_gmadr
.size
)) =
121 vgpu_hidden_sz(vgpu
);
123 vgpu_vreg(vgpu
, vgtif_reg(avail_rs
.fence_num
)) = vgpu_fence_sz(vgpu
);
125 gvt_dbg_core("Populate PVINFO PAGE for vGPU %d\n", vgpu
->id
);
126 gvt_dbg_core("aperture base [GMADR] 0x%llx size 0x%llx\n",
127 vgpu_aperture_gmadr_base(vgpu
), vgpu_aperture_sz(vgpu
));
128 gvt_dbg_core("hidden base [GMADR] 0x%llx size=0x%llx\n",
129 vgpu_hidden_gmadr_base(vgpu
), vgpu_hidden_sz(vgpu
));
130 gvt_dbg_core("fence size %d\n", vgpu_fence_sz(vgpu
));
132 WARN_ON(sizeof(struct vgt_if
) != VGT_PVINFO_SIZE
);
136 * intel_gvt_destroy_vgpu - destroy a virtual GPU
139 * This function is called when user wants to destroy a virtual GPU.
142 void intel_gvt_destroy_vgpu(struct intel_vgpu
*vgpu
)
144 struct intel_gvt
*gvt
= vgpu
->gvt
;
146 mutex_lock(&gvt
->lock
);
148 vgpu
->active
= false;
149 idr_remove(&gvt
->vgpu_idr
, vgpu
->id
);
151 if (atomic_read(&vgpu
->running_workload_num
)) {
152 mutex_unlock(&gvt
->lock
);
153 intel_gvt_wait_vgpu_idle(vgpu
);
154 mutex_lock(&gvt
->lock
);
157 intel_vgpu_stop_schedule(vgpu
);
158 intel_vgpu_clean_sched_policy(vgpu
);
159 intel_vgpu_clean_gvt_context(vgpu
);
160 intel_vgpu_clean_execlist(vgpu
);
161 intel_vgpu_clean_display(vgpu
);
162 intel_vgpu_clean_opregion(vgpu
);
163 intel_vgpu_clean_gtt(vgpu
);
164 intel_gvt_hypervisor_detach_vgpu(vgpu
);
165 intel_vgpu_free_resource(vgpu
);
166 clean_vgpu_mmio(vgpu
);
169 mutex_unlock(&gvt
->lock
);
173 * intel_gvt_create_vgpu - create a virtual GPU
175 * @param: vGPU creation parameters
177 * This function is called when user wants to create a virtual GPU.
180 * pointer to intel_vgpu, error pointer if failed.
182 struct intel_vgpu
*intel_gvt_create_vgpu(struct intel_gvt
*gvt
,
183 struct intel_vgpu_creation_params
*param
)
185 struct intel_vgpu
*vgpu
;
188 gvt_dbg_core("handle %llu low %llu MB high %llu MB fence %llu\n",
189 param
->handle
, param
->low_gm_sz
, param
->high_gm_sz
,
192 vgpu
= vzalloc(sizeof(*vgpu
));
194 return ERR_PTR(-ENOMEM
);
196 mutex_lock(&gvt
->lock
);
198 ret
= idr_alloc(&gvt
->vgpu_idr
, vgpu
, 1, GVT_MAX_VGPU
, GFP_KERNEL
);
203 vgpu
->handle
= param
->handle
;
205 bitmap_zero(vgpu
->tlb_handle_pending
, I915_NUM_ENGINES
);
207 setup_vgpu_cfg_space(vgpu
, param
);
209 ret
= setup_vgpu_mmio(vgpu
);
213 ret
= intel_vgpu_alloc_resource(vgpu
, param
);
215 goto out_clean_vgpu_mmio
;
217 populate_pvinfo_page(vgpu
);
219 ret
= intel_gvt_hypervisor_attach_vgpu(vgpu
);
221 goto out_clean_vgpu_resource
;
223 ret
= intel_vgpu_init_gtt(vgpu
);
225 goto out_detach_hypervisor_vgpu
;
227 if (intel_gvt_host
.hypervisor_type
== INTEL_GVT_HYPERVISOR_KVM
) {
228 ret
= intel_vgpu_init_opregion(vgpu
, 0);
233 ret
= intel_vgpu_init_display(vgpu
);
235 goto out_clean_opregion
;
237 ret
= intel_vgpu_init_execlist(vgpu
);
239 goto out_clean_display
;
241 ret
= intel_vgpu_init_gvt_context(vgpu
);
243 goto out_clean_execlist
;
245 ret
= intel_vgpu_init_sched_policy(vgpu
);
247 goto out_clean_shadow_ctx
;
250 mutex_unlock(&gvt
->lock
);
254 out_clean_shadow_ctx
:
255 intel_vgpu_clean_gvt_context(vgpu
);
257 intel_vgpu_clean_execlist(vgpu
);
259 intel_vgpu_clean_display(vgpu
);
261 intel_vgpu_clean_opregion(vgpu
);
263 intel_vgpu_clean_gtt(vgpu
);
264 out_detach_hypervisor_vgpu
:
265 intel_gvt_hypervisor_detach_vgpu(vgpu
);
266 out_clean_vgpu_resource
:
267 intel_vgpu_free_resource(vgpu
);
269 clean_vgpu_mmio(vgpu
);
272 mutex_unlock(&gvt
->lock
);