|
@@ -35,79 +35,6 @@
|
|
|
#include "gvt.h"
|
|
|
#include "i915_pvinfo.h"
|
|
|
|
|
|
-static void clean_vgpu_mmio(struct intel_vgpu *vgpu)
|
|
|
-{
|
|
|
- vfree(vgpu->mmio.vreg);
|
|
|
- vgpu->mmio.vreg = vgpu->mmio.sreg = NULL;
|
|
|
-}
|
|
|
-
|
|
|
-int setup_vgpu_mmio(struct intel_vgpu *vgpu)
|
|
|
-{
|
|
|
- struct intel_gvt *gvt = vgpu->gvt;
|
|
|
- const struct intel_gvt_device_info *info = &gvt->device_info;
|
|
|
-
|
|
|
- if (vgpu->mmio.vreg)
|
|
|
- memset(vgpu->mmio.vreg, 0, info->mmio_size * 2);
|
|
|
- else {
|
|
|
- vgpu->mmio.vreg = vzalloc(info->mmio_size * 2);
|
|
|
- if (!vgpu->mmio.vreg)
|
|
|
- return -ENOMEM;
|
|
|
- }
|
|
|
-
|
|
|
- vgpu->mmio.sreg = vgpu->mmio.vreg + info->mmio_size;
|
|
|
-
|
|
|
- memcpy(vgpu->mmio.vreg, gvt->firmware.mmio, info->mmio_size);
|
|
|
- memcpy(vgpu->mmio.sreg, gvt->firmware.mmio, info->mmio_size);
|
|
|
-
|
|
|
- vgpu_vreg(vgpu, GEN6_GT_THREAD_STATUS_REG) = 0;
|
|
|
-
|
|
|
- /* set the bit 0:2(Core C-State ) to C0 */
|
|
|
- vgpu_vreg(vgpu, GEN6_GT_CORE_STATUS) = 0;
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-static void setup_vgpu_cfg_space(struct intel_vgpu *vgpu,
|
|
|
- struct intel_vgpu_creation_params *param)
|
|
|
-{
|
|
|
- struct intel_gvt *gvt = vgpu->gvt;
|
|
|
- const struct intel_gvt_device_info *info = &gvt->device_info;
|
|
|
- u16 *gmch_ctl;
|
|
|
- int i;
|
|
|
-
|
|
|
- memcpy(vgpu_cfg_space(vgpu), gvt->firmware.cfg_space,
|
|
|
- info->cfg_space_size);
|
|
|
-
|
|
|
- if (!param->primary) {
|
|
|
- vgpu_cfg_space(vgpu)[PCI_CLASS_DEVICE] =
|
|
|
- INTEL_GVT_PCI_CLASS_VGA_OTHER;
|
|
|
- vgpu_cfg_space(vgpu)[PCI_CLASS_PROG] =
|
|
|
- INTEL_GVT_PCI_CLASS_VGA_OTHER;
|
|
|
- }
|
|
|
-
|
|
|
- /* Show guest that there isn't any stolen memory.*/
|
|
|
- gmch_ctl = (u16 *)(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_GMCH_CONTROL);
|
|
|
- *gmch_ctl &= ~(BDW_GMCH_GMS_MASK << BDW_GMCH_GMS_SHIFT);
|
|
|
-
|
|
|
- intel_vgpu_write_pci_bar(vgpu, PCI_BASE_ADDRESS_2,
|
|
|
- gvt_aperture_pa_base(gvt), true);
|
|
|
-
|
|
|
- vgpu_cfg_space(vgpu)[PCI_COMMAND] &= ~(PCI_COMMAND_IO
|
|
|
- | PCI_COMMAND_MEMORY
|
|
|
- | PCI_COMMAND_MASTER);
|
|
|
- /*
|
|
|
- * Clear the bar upper 32bit and let guest to assign the new value
|
|
|
- */
|
|
|
- memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_1, 0, 4);
|
|
|
- memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_3, 0, 4);
|
|
|
- memset(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_OPREGION, 0, 4);
|
|
|
-
|
|
|
- for (i = 0; i < INTEL_GVT_MAX_BAR_NUM; i++) {
|
|
|
- vgpu->cfg_space.bar[i].size = pci_resource_len(
|
|
|
- gvt->dev_priv->drm.pdev, i * 2);
|
|
|
- vgpu->cfg_space.bar[i].tracked = false;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
void populate_pvinfo_page(struct intel_vgpu *vgpu)
|
|
|
{
|
|
|
/* setup the ballooning information */
|
|
@@ -177,7 +104,7 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt)
|
|
|
if (low_avail / min_low == 0)
|
|
|
break;
|
|
|
gvt->types[i].low_gm_size = min_low;
|
|
|
- gvt->types[i].high_gm_size = 3 * gvt->types[i].low_gm_size;
|
|
|
+ gvt->types[i].high_gm_size = max((min_low<<3), MB_TO_BYTES(384U));
|
|
|
gvt->types[i].fence = 4;
|
|
|
gvt->types[i].max_instance = low_avail / min_low;
|
|
|
gvt->types[i].avail_instance = gvt->types[i].max_instance;
|
|
@@ -217,7 +144,7 @@ static void intel_gvt_update_vgpu_types(struct intel_gvt *gvt)
|
|
|
*/
|
|
|
low_gm_avail = MB_TO_BYTES(256) - HOST_LOW_GM_SIZE -
|
|
|
gvt->gm.vgpu_allocated_low_gm_size;
|
|
|
- high_gm_avail = MB_TO_BYTES(256) * 3 - HOST_HIGH_GM_SIZE -
|
|
|
+ high_gm_avail = MB_TO_BYTES(256) * 8UL - HOST_HIGH_GM_SIZE -
|
|
|
gvt->gm.vgpu_allocated_high_gm_size;
|
|
|
fence_avail = gvt_fence_sz(gvt) - HOST_FENCE -
|
|
|
gvt->fence.vgpu_allocated_fence_num;
|
|
@@ -268,7 +195,7 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu)
|
|
|
intel_vgpu_clean_gtt(vgpu);
|
|
|
intel_gvt_hypervisor_detach_vgpu(vgpu);
|
|
|
intel_vgpu_free_resource(vgpu);
|
|
|
- clean_vgpu_mmio(vgpu);
|
|
|
+ intel_vgpu_clean_mmio(vgpu);
|
|
|
vfree(vgpu);
|
|
|
|
|
|
intel_gvt_update_vgpu_types(gvt);
|
|
@@ -300,11 +227,11 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
|
|
|
vgpu->gvt = gvt;
|
|
|
bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES);
|
|
|
|
|
|
- setup_vgpu_cfg_space(vgpu, param);
|
|
|
+ intel_vgpu_init_cfg_space(vgpu, param->primary);
|
|
|
|
|
|
- ret = setup_vgpu_mmio(vgpu);
|
|
|
+ ret = intel_vgpu_init_mmio(vgpu);
|
|
|
if (ret)
|
|
|
- goto out_free_vgpu;
|
|
|
+ goto out_clean_idr;
|
|
|
|
|
|
ret = intel_vgpu_alloc_resource(vgpu, param);
|
|
|
if (ret)
|
|
@@ -354,7 +281,9 @@ out_detach_hypervisor_vgpu:
|
|
|
out_clean_vgpu_resource:
|
|
|
intel_vgpu_free_resource(vgpu);
|
|
|
out_clean_vgpu_mmio:
|
|
|
- clean_vgpu_mmio(vgpu);
|
|
|
+ intel_vgpu_clean_mmio(vgpu);
|
|
|
+out_clean_idr:
|
|
|
+ idr_remove(&gvt->vgpu_idr, vgpu->id);
|
|
|
out_free_vgpu:
|
|
|
vfree(vgpu);
|
|
|
mutex_unlock(&gvt->lock);
|
|
@@ -398,7 +327,75 @@ struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * intel_gvt_reset_vgpu - reset a virtual GPU
|
|
|
+ * intel_gvt_reset_vgpu_locked - reset a virtual GPU by DMLR or GT reset
|
|
|
+ * @vgpu: virtual GPU
|
|
|
+ * @dmlr: vGPU Device Model Level Reset or GT Reset
|
|
|
+ * @engine_mask: engines to reset for GT reset
|
|
|
+ *
|
|
|
+ * This function is called when user wants to reset a virtual GPU through
|
|
|
+ * device model reset or GT reset. The caller should hold the gvt lock.
|
|
|
+ *
|
|
|
+ * vGPU Device Model Level Reset (DMLR) simulates the PCI level reset to reset
|
|
|
+ * the whole vGPU to default state as when it is created. This vGPU function
|
|
|
+ * is required both for functionary and security concerns.The ultimate goal
|
|
|
+ * of vGPU FLR is that reuse a vGPU instance by virtual machines. When we
|
|
|
+ * assign a vGPU to a virtual machine we must isse such reset first.
|
|
|
+ *
|
|
|
+ * Full GT Reset and Per-Engine GT Reset are soft reset flow for GPU engines
|
|
|
+ * (Render, Blitter, Video, Video Enhancement). It is defined by GPU Spec.
|
|
|
+ * Unlike the FLR, GT reset only reset particular resource of a vGPU per
|
|
|
+ * the reset request. Guest driver can issue a GT reset by programming the
|
|
|
+ * virtual GDRST register to reset specific virtual GPU engine or all
|
|
|
+ * engines.
|
|
|
+ *
|
|
|
+ * The parameter dev_level is to identify if we will do DMLR or GT reset.
|
|
|
+ * The parameter engine_mask is to specific the engines that need to be
|
|
|
+ * resetted. If value ALL_ENGINES is given for engine_mask, it means
|
|
|
+ * the caller requests a full GT reset that we will reset all virtual
|
|
|
+ * GPU engines. For FLR, engine_mask is ignored.
|
|
|
+ */
|
|
|
+void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr,
|
|
|
+ unsigned int engine_mask)
|
|
|
+{
|
|
|
+ struct intel_gvt *gvt = vgpu->gvt;
|
|
|
+ struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
|
|
|
+
|
|
|
+ gvt_dbg_core("------------------------------------------\n");
|
|
|
+ gvt_dbg_core("resseting vgpu%d, dmlr %d, engine_mask %08x\n",
|
|
|
+ vgpu->id, dmlr, engine_mask);
|
|
|
+ vgpu->resetting = true;
|
|
|
+
|
|
|
+ intel_vgpu_stop_schedule(vgpu);
|
|
|
+ /*
|
|
|
+ * The current_vgpu will set to NULL after stopping the
|
|
|
+ * scheduler when the reset is triggered by current vgpu.
|
|
|
+ */
|
|
|
+ if (scheduler->current_vgpu == NULL) {
|
|
|
+ mutex_unlock(&gvt->lock);
|
|
|
+ intel_gvt_wait_vgpu_idle(vgpu);
|
|
|
+ mutex_lock(&gvt->lock);
|
|
|
+ }
|
|
|
+
|
|
|
+ intel_vgpu_reset_execlist(vgpu, dmlr ? ALL_ENGINES : engine_mask);
|
|
|
+
|
|
|
+ /* full GPU reset or device model level reset */
|
|
|
+ if (engine_mask == ALL_ENGINES || dmlr) {
|
|
|
+ intel_vgpu_reset_gtt(vgpu, dmlr);
|
|
|
+ intel_vgpu_reset_resource(vgpu);
|
|
|
+ intel_vgpu_reset_mmio(vgpu);
|
|
|
+ populate_pvinfo_page(vgpu);
|
|
|
+
|
|
|
+ if (dmlr)
|
|
|
+ intel_vgpu_reset_cfg_space(vgpu);
|
|
|
+ }
|
|
|
+
|
|
|
+ vgpu->resetting = false;
|
|
|
+ gvt_dbg_core("reset vgpu%d done\n", vgpu->id);
|
|
|
+ gvt_dbg_core("------------------------------------------\n");
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * intel_gvt_reset_vgpu - reset a virtual GPU (Function Level)
|
|
|
* @vgpu: virtual GPU
|
|
|
*
|
|
|
* This function is called when user wants to reset a virtual GPU.
|
|
@@ -406,4 +403,7 @@ struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt,
|
|
|
*/
|
|
|
void intel_gvt_reset_vgpu(struct intel_vgpu *vgpu)
|
|
|
{
|
|
|
+ mutex_lock(&vgpu->gvt->lock);
|
|
|
+ intel_gvt_reset_vgpu_locked(vgpu, true, 0);
|
|
|
+ mutex_unlock(&vgpu->gvt->lock);
|
|
|
}
|