Beispiel #1
0
/**
 * 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;
	unsigned int resetting_eng = dmlr ? ALL_ENGINES : engine_mask;

	gvt_dbg_core("------------------------------------------\n");
	gvt_dbg_core("resseting vgpu%d, dmlr %d, engine_mask %08x\n",
		     vgpu->id, dmlr, engine_mask);

	vgpu->resetting_eng = resetting_eng;

	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_submission(vgpu, resetting_eng);
	/* full GPU reset or device model level reset */
	if (engine_mask == ALL_ENGINES || dmlr) {
		intel_vgpu_select_submission_ops(vgpu, ALL_ENGINES, 0);
		/*fence will not be reset during virtual reset */
		if (dmlr) {
			intel_vgpu_reset_gtt(vgpu);
			intel_vgpu_reset_resource(vgpu);
		}

		intel_vgpu_reset_mmio(vgpu, dmlr);
		populate_pvinfo_page(vgpu);
		intel_vgpu_reset_display(vgpu);

		if (dmlr) {
			intel_vgpu_reset_cfg_space(vgpu);
			/* only reset the failsafe mode when dmlr reset */
			vgpu->failsafe = false;
			vgpu->pv_notified = false;
		}
	}

	vgpu->resetting_eng = 0;
	gvt_dbg_core("reset vgpu%d done\n", vgpu->id);
	gvt_dbg_core("------------------------------------------\n");
}
Beispiel #2
0
/**
 * 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);
		intel_vgpu_reset_display(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");
}
Beispiel #3
0
static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
		struct intel_vgpu_creation_params *param)
{
	struct intel_vgpu *vgpu;
	int ret;

	gvt_dbg_core("handle %llu low %llu MB high %llu MB fence %llu\n",
			param->handle, param->low_gm_sz, param->high_gm_sz,
			param->fence_sz);

	vgpu = vzalloc(sizeof(*vgpu));
	if (!vgpu)
		return ERR_PTR(-ENOMEM);

	mutex_lock(&gvt->lock);

	ret = idr_alloc(&gvt->vgpu_idr, vgpu, 1, GVT_MAX_VGPU, GFP_KERNEL);
	if (ret < 0)
		goto out_free_vgpu;

	vgpu->id = ret;
	vgpu->handle = param->handle;
	vgpu->gvt = gvt;
	bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES);

	intel_vgpu_init_cfg_space(vgpu, param->primary);

	ret = intel_vgpu_init_mmio(vgpu);
	if (ret)
		goto out_clean_idr;

	ret = intel_vgpu_alloc_resource(vgpu, param);
	if (ret)
		goto out_clean_vgpu_mmio;

	populate_pvinfo_page(vgpu);

	ret = intel_gvt_hypervisor_attach_vgpu(vgpu);
	if (ret)
		goto out_clean_vgpu_resource;

	ret = intel_vgpu_init_gtt(vgpu);
	if (ret)
		goto out_detach_hypervisor_vgpu;

	ret = intel_vgpu_init_display(vgpu);
	if (ret)
		goto out_clean_gtt;

	ret = intel_vgpu_init_execlist(vgpu);
	if (ret)
		goto out_clean_display;

	ret = intel_vgpu_init_gvt_context(vgpu);
	if (ret)
		goto out_clean_execlist;

	ret = intel_vgpu_init_sched_policy(vgpu);
	if (ret)
		goto out_clean_shadow_ctx;

	vgpu->active = true;
	mutex_unlock(&gvt->lock);

	return vgpu;

out_clean_shadow_ctx:
	intel_vgpu_clean_gvt_context(vgpu);
out_clean_execlist:
	intel_vgpu_clean_execlist(vgpu);
out_clean_display:
	intel_vgpu_clean_display(vgpu);
out_clean_gtt:
	intel_vgpu_clean_gtt(vgpu);
out_detach_hypervisor_vgpu:
	intel_gvt_hypervisor_detach_vgpu(vgpu);
out_clean_vgpu_resource:
	intel_vgpu_free_resource(vgpu);
out_clean_vgpu_mmio:
	intel_vgpu_clean_mmio(vgpu);
out_clean_idr:
	idr_remove(&gvt->vgpu_idr, vgpu->id);
out_free_vgpu:
	vfree(vgpu);
	mutex_unlock(&gvt->lock);
	return ERR_PTR(ret);
}
Beispiel #4
0
static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
		struct intel_vgpu_creation_params *param)
{
	struct intel_vgpu *vgpu;
	int ret;

	gvt_dbg_core("handle %llu low %llu MB high %llu MB fence %llu\n",
			param->handle, param->low_gm_sz, param->high_gm_sz,
			param->fence_sz);

	vgpu = vzalloc(sizeof(*vgpu));
	if (!vgpu)
		return ERR_PTR(-ENOMEM);

	mutex_lock(&gvt->lock);

	ret = idr_alloc(&gvt->vgpu_idr, vgpu, IDLE_VGPU_IDR + 1, GVT_MAX_VGPU,
		GFP_KERNEL);
	if (ret < 0)
		goto out_free_vgpu;

	vgpu->id = ret;
	vgpu->handle = param->handle;
	vgpu->gvt = gvt;
	vgpu->sched_ctl.weight = param->weight;
	INIT_LIST_HEAD(&vgpu->dmabuf_obj_list_head);
	idr_init(&vgpu->object_idr);
	intel_vgpu_init_cfg_space(vgpu, param->primary);

	ret = intel_vgpu_init_mmio(vgpu);
	if (ret)
		goto out_clean_idr;

	ret = intel_vgpu_alloc_resource(vgpu, param);
	if (ret)
		goto out_clean_vgpu_mmio;

	populate_pvinfo_page(vgpu);

	ret = intel_gvt_hypervisor_attach_vgpu(vgpu);
	if (ret)
		goto out_clean_vgpu_resource;

	ret = intel_vgpu_init_gtt(vgpu);
	if (ret)
		goto out_detach_hypervisor_vgpu;

	ret = intel_vgpu_init_opregion(vgpu);
	if (ret)
		goto out_clean_gtt;

	ret = intel_vgpu_init_display(vgpu, param->resolution);
	if (ret)
		goto out_clean_opregion;

	ret = intel_vgpu_setup_submission(vgpu);
	if (ret)
		goto out_clean_display;

	ret = intel_vgpu_init_sched_policy(vgpu);
	if (ret)
		goto out_clean_submission;

	ret = intel_gvt_debugfs_add_vgpu(vgpu);
	if (ret)
		goto out_clean_sched_policy;

	ret = intel_gvt_hypervisor_set_opregion(vgpu);
	if (ret)
		goto out_clean_sched_policy;

	mutex_unlock(&gvt->lock);

	return vgpu;

out_clean_sched_policy:
	intel_vgpu_clean_sched_policy(vgpu);
out_clean_submission:
	intel_vgpu_clean_submission(vgpu);
out_clean_display:
	intel_vgpu_clean_display(vgpu);
out_clean_opregion:
	intel_vgpu_clean_opregion(vgpu);
out_clean_gtt:
	intel_vgpu_clean_gtt(vgpu);
out_detach_hypervisor_vgpu:
	intel_gvt_hypervisor_detach_vgpu(vgpu);
out_clean_vgpu_resource:
	intel_vgpu_free_resource(vgpu);
out_clean_vgpu_mmio:
	intel_vgpu_clean_mmio(vgpu);
out_clean_idr:
	idr_remove(&gvt->vgpu_idr, vgpu->id);
out_free_vgpu:
	vfree(vgpu);
	mutex_unlock(&gvt->lock);
	return ERR_PTR(ret);
}