/** * 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"); }
/** * 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"); }
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); }
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); }