···158158 POSTING_READ(fence_reg_lo);159159}160160161161+static void _clear_vgpu_fence(struct intel_vgpu *vgpu)162162+{163163+ int i;164164+165165+ for (i = 0; i < vgpu_fence_sz(vgpu); i++)166166+ intel_vgpu_write_fence(vgpu, i, 0);167167+}168168+161169static void free_vgpu_fence(struct intel_vgpu *vgpu)162170{163171 struct intel_gvt *gvt = vgpu->gvt;···179171 intel_runtime_pm_get(dev_priv);180172181173 mutex_lock(&dev_priv->drm.struct_mutex);174174+ _clear_vgpu_fence(vgpu);182175 for (i = 0; i < vgpu_fence_sz(vgpu); i++) {183176 reg = vgpu->fence.regs[i];184184- intel_vgpu_write_fence(vgpu, i, 0);185177 list_add_tail(®->link,186178 &dev_priv->mm.fence_list);187179 }···209201 continue;210202 list_del(pos);211203 vgpu->fence.regs[i] = reg;212212- intel_vgpu_write_fence(vgpu, i, 0);213204 if (++i == vgpu_fence_sz(vgpu))214205 break;215206 }216207 if (i != vgpu_fence_sz(vgpu))217208 goto out_free_fence;209209+210210+ _clear_vgpu_fence(vgpu);218211219212 mutex_unlock(&dev_priv->drm.struct_mutex);220213 intel_runtime_pm_put(dev_priv);···313304 free_vgpu_gm(vgpu);314305 free_vgpu_fence(vgpu);315306 free_resource(vgpu);307307+}308308+309309+/**310310+ * intel_vgpu_reset_resource - reset resource state owned by a vGPU311311+ * @vgpu: a vGPU312312+ *313313+ * This function is used to reset resource state owned by a vGPU.314314+ *315315+ */316316+void intel_vgpu_reset_resource(struct intel_vgpu *vgpu)317317+{318318+ struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;319319+320320+ intel_runtime_pm_get(dev_priv);321321+ _clear_vgpu_fence(vgpu);322322+ intel_runtime_pm_put(dev_priv);316323}317324318325/**
+74
drivers/gpu/drm/i915/gvt/cfg_space.c
···282282 }283283 return 0;284284}285285+286286+/**287287+ * intel_vgpu_init_cfg_space - init vGPU configuration space when create vGPU288288+ *289289+ * @vgpu: a vGPU290290+ * @primary: is the vGPU presented as primary291291+ *292292+ */293293+void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu,294294+ bool primary)295295+{296296+ struct intel_gvt *gvt = vgpu->gvt;297297+ const struct intel_gvt_device_info *info = &gvt->device_info;298298+ u16 *gmch_ctl;299299+ int i;300300+301301+ memcpy(vgpu_cfg_space(vgpu), gvt->firmware.cfg_space,302302+ info->cfg_space_size);303303+304304+ if (!primary) {305305+ vgpu_cfg_space(vgpu)[PCI_CLASS_DEVICE] =306306+ INTEL_GVT_PCI_CLASS_VGA_OTHER;307307+ vgpu_cfg_space(vgpu)[PCI_CLASS_PROG] =308308+ INTEL_GVT_PCI_CLASS_VGA_OTHER;309309+ }310310+311311+ /* Show guest that there isn't any stolen memory.*/312312+ gmch_ctl = (u16 *)(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_GMCH_CONTROL);313313+ *gmch_ctl &= ~(BDW_GMCH_GMS_MASK << BDW_GMCH_GMS_SHIFT);314314+315315+ intel_vgpu_write_pci_bar(vgpu, PCI_BASE_ADDRESS_2,316316+ gvt_aperture_pa_base(gvt), true);317317+318318+ vgpu_cfg_space(vgpu)[PCI_COMMAND] &= ~(PCI_COMMAND_IO319319+ | PCI_COMMAND_MEMORY320320+ | PCI_COMMAND_MASTER);321321+ /*322322+ * Clear the bar upper 32bit and let guest to assign the new value323323+ */324324+ memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_1, 0, 4);325325+ memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_3, 0, 4);326326+ memset(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_OPREGION, 0, 4);327327+328328+ for (i = 0; i < INTEL_GVT_MAX_BAR_NUM; i++) {329329+ vgpu->cfg_space.bar[i].size = pci_resource_len(330330+ gvt->dev_priv->drm.pdev, i * 2);331331+ vgpu->cfg_space.bar[i].tracked = false;332332+ }333333+}334334+335335+/**336336+ * intel_vgpu_reset_cfg_space - reset vGPU configuration space337337+ *338338+ * @vgpu: a vGPU339339+ *340340+ */341341+void intel_vgpu_reset_cfg_space(struct intel_vgpu *vgpu)342342+{343343+ u8 cmd = vgpu_cfg_space(vgpu)[PCI_COMMAND];344344+ bool primary = vgpu_cfg_space(vgpu)[PCI_CLASS_DEVICE] !=345345+ INTEL_GVT_PCI_CLASS_VGA_OTHER;346346+347347+ if (cmd & PCI_COMMAND_MEMORY) {348348+ trap_gttmmio(vgpu, false);349349+ map_aperture(vgpu, false);350350+ }351351+352352+ /**353353+ * Currently we only do such reset when vGPU is not354354+ * owned by any VM, so we simply restore entire cfg355355+ * space to default value.356356+ */357357+ intel_vgpu_init_cfg_space(vgpu, primary);358358+}
+27
drivers/gpu/drm/i915/gvt/gtt.c
···22772277 for (offset = 0; offset < num_entries; offset++)22782278 ops->set_entry(NULL, &e, index + offset, false, 0, vgpu);22792279}22802280+22812281+/**22822282+ * intel_vgpu_reset_gtt - reset the all GTT related status22832283+ * @vgpu: a vGPU22842284+ * @dmlr: true for vGPU Device Model Level Reset, false for GT Reset22852285+ *22862286+ * This function is called from vfio core to reset reset all22872287+ * GTT related status, including GGTT, PPGTT, scratch page.22882288+ *22892289+ */22902290+void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu, bool dmlr)22912291+{22922292+ int i;22932293+22942294+ ppgtt_free_all_shadow_page(vgpu);22952295+ if (!dmlr)22962296+ return;22972297+22982298+ intel_vgpu_reset_ggtt(vgpu);22992299+23002300+ /* clear scratch page for security */23012301+ for (i = GTT_TYPE_PPGTT_PTE_PT; i < GTT_TYPE_MAX; i++) {23022302+ if (vgpu->gtt.scratch_pt[i].page != NULL)23032303+ memset(page_address(vgpu->gtt.scratch_pt[i].page),23042304+ 0, PAGE_SIZE);23052305+ }23062306+}
···3535#include "gvt.h"3636#include "i915_pvinfo.h"37373838-static void clean_vgpu_mmio(struct intel_vgpu *vgpu)3939-{4040- vfree(vgpu->mmio.vreg);4141- vgpu->mmio.vreg = vgpu->mmio.sreg = NULL;4242-}4343-4444-int setup_vgpu_mmio(struct intel_vgpu *vgpu)4545-{4646- struct intel_gvt *gvt = vgpu->gvt;4747- const struct intel_gvt_device_info *info = &gvt->device_info;4848-4949- if (vgpu->mmio.vreg)5050- memset(vgpu->mmio.vreg, 0, info->mmio_size * 2);5151- else {5252- vgpu->mmio.vreg = vzalloc(info->mmio_size * 2);5353- if (!vgpu->mmio.vreg)5454- return -ENOMEM;5555- }5656-5757- vgpu->mmio.sreg = vgpu->mmio.vreg + info->mmio_size;5858-5959- memcpy(vgpu->mmio.vreg, gvt->firmware.mmio, info->mmio_size);6060- memcpy(vgpu->mmio.sreg, gvt->firmware.mmio, info->mmio_size);6161-6262- vgpu_vreg(vgpu, GEN6_GT_THREAD_STATUS_REG) = 0;6363-6464- /* set the bit 0:2(Core C-State ) to C0 */6565- vgpu_vreg(vgpu, GEN6_GT_CORE_STATUS) = 0;6666- return 0;6767-}6868-6969-static void setup_vgpu_cfg_space(struct intel_vgpu *vgpu,7070- struct intel_vgpu_creation_params *param)7171-{7272- struct intel_gvt *gvt = vgpu->gvt;7373- const struct intel_gvt_device_info *info = &gvt->device_info;7474- u16 *gmch_ctl;7575- int i;7676-7777- memcpy(vgpu_cfg_space(vgpu), gvt->firmware.cfg_space,7878- info->cfg_space_size);7979-8080- if (!param->primary) {8181- vgpu_cfg_space(vgpu)[PCI_CLASS_DEVICE] =8282- INTEL_GVT_PCI_CLASS_VGA_OTHER;8383- vgpu_cfg_space(vgpu)[PCI_CLASS_PROG] =8484- INTEL_GVT_PCI_CLASS_VGA_OTHER;8585- }8686-8787- /* Show guest that there isn't any stolen memory.*/8888- gmch_ctl = (u16 *)(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_GMCH_CONTROL);8989- *gmch_ctl &= ~(BDW_GMCH_GMS_MASK << BDW_GMCH_GMS_SHIFT);9090-9191- intel_vgpu_write_pci_bar(vgpu, PCI_BASE_ADDRESS_2,9292- gvt_aperture_pa_base(gvt), true);9393-9494- vgpu_cfg_space(vgpu)[PCI_COMMAND] &= ~(PCI_COMMAND_IO9595- | PCI_COMMAND_MEMORY9696- | PCI_COMMAND_MASTER);9797- /*9898- * Clear the bar upper 32bit and let guest to assign the new value9999- */100100- memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_1, 0, 4);101101- memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_3, 0, 4);102102- memset(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_OPREGION, 0, 4);103103-104104- for (i = 0; i < INTEL_GVT_MAX_BAR_NUM; i++) {105105- vgpu->cfg_space.bar[i].size = pci_resource_len(106106- gvt->dev_priv->drm.pdev, i * 2);107107- vgpu->cfg_space.bar[i].tracked = false;108108- }109109-}110110-11138void populate_pvinfo_page(struct intel_vgpu *vgpu)11239{11340 /* setup the ballooning information */···195268 intel_vgpu_clean_gtt(vgpu);196269 intel_gvt_hypervisor_detach_vgpu(vgpu);197270 intel_vgpu_free_resource(vgpu);198198- clean_vgpu_mmio(vgpu);271271+ intel_vgpu_clean_mmio(vgpu);199272 vfree(vgpu);200273201274 intel_gvt_update_vgpu_types(gvt);···227300 vgpu->gvt = gvt;228301 bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES);229302230230- setup_vgpu_cfg_space(vgpu, param);303303+ intel_vgpu_init_cfg_space(vgpu, param->primary);231304232232- ret = setup_vgpu_mmio(vgpu);305305+ ret = intel_vgpu_init_mmio(vgpu);233306 if (ret)234307 goto out_clean_idr;235308···281354out_clean_vgpu_resource:282355 intel_vgpu_free_resource(vgpu);283356out_clean_vgpu_mmio:284284- clean_vgpu_mmio(vgpu);357357+ intel_vgpu_clean_mmio(vgpu);285358out_clean_idr:286359 idr_remove(&gvt->vgpu_idr, vgpu->id);287360out_free_vgpu:···327400}328401329402/**330330- * intel_gvt_reset_vgpu - reset a virtual GPU403403+ * intel_gvt_reset_vgpu_locked - reset a virtual GPU by DMLR or GT reset404404+ * @vgpu: virtual GPU405405+ * @dmlr: vGPU Device Model Level Reset or GT Reset406406+ * @engine_mask: engines to reset for GT reset407407+ *408408+ * This function is called when user wants to reset a virtual GPU through409409+ * device model reset or GT reset. The caller should hold the gvt lock.410410+ *411411+ * vGPU Device Model Level Reset (DMLR) simulates the PCI level reset to reset412412+ * the whole vGPU to default state as when it is created. This vGPU function413413+ * is required both for functionary and security concerns.The ultimate goal414414+ * of vGPU FLR is that reuse a vGPU instance by virtual machines. When we415415+ * assign a vGPU to a virtual machine we must isse such reset first.416416+ *417417+ * Full GT Reset and Per-Engine GT Reset are soft reset flow for GPU engines418418+ * (Render, Blitter, Video, Video Enhancement). It is defined by GPU Spec.419419+ * Unlike the FLR, GT reset only reset particular resource of a vGPU per420420+ * the reset request. Guest driver can issue a GT reset by programming the421421+ * virtual GDRST register to reset specific virtual GPU engine or all422422+ * engines.423423+ *424424+ * The parameter dev_level is to identify if we will do DMLR or GT reset.425425+ * The parameter engine_mask is to specific the engines that need to be426426+ * resetted. If value ALL_ENGINES is given for engine_mask, it means427427+ * the caller requests a full GT reset that we will reset all virtual428428+ * GPU engines. For FLR, engine_mask is ignored.429429+ */430430+void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr,431431+ unsigned int engine_mask)432432+{433433+ struct intel_gvt *gvt = vgpu->gvt;434434+ struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;435435+436436+ gvt_dbg_core("------------------------------------------\n");437437+ gvt_dbg_core("resseting vgpu%d, dmlr %d, engine_mask %08x\n",438438+ vgpu->id, dmlr, engine_mask);439439+ vgpu->resetting = true;440440+441441+ intel_vgpu_stop_schedule(vgpu);442442+ /*443443+ * The current_vgpu will set to NULL after stopping the444444+ * scheduler when the reset is triggered by current vgpu.445445+ */446446+ if (scheduler->current_vgpu == NULL) {447447+ mutex_unlock(&gvt->lock);448448+ intel_gvt_wait_vgpu_idle(vgpu);449449+ mutex_lock(&gvt->lock);450450+ }451451+452452+ intel_vgpu_reset_execlist(vgpu, dmlr ? ALL_ENGINES : engine_mask);453453+454454+ /* full GPU reset or device model level reset */455455+ if (engine_mask == ALL_ENGINES || dmlr) {456456+ intel_vgpu_reset_gtt(vgpu, dmlr);457457+ intel_vgpu_reset_resource(vgpu);458458+ intel_vgpu_reset_mmio(vgpu);459459+ populate_pvinfo_page(vgpu);460460+461461+ if (dmlr)462462+ intel_vgpu_reset_cfg_space(vgpu);463463+ }464464+465465+ vgpu->resetting = false;466466+ gvt_dbg_core("reset vgpu%d done\n", vgpu->id);467467+ gvt_dbg_core("------------------------------------------\n");468468+}469469+470470+/**471471+ * intel_gvt_reset_vgpu - reset a virtual GPU (Function Level)331472 * @vgpu: virtual GPU332473 *333474 * This function is called when user wants to reset a virtual GPU.···403408 */404409void intel_gvt_reset_vgpu(struct intel_vgpu *vgpu)405410{411411+ mutex_lock(&vgpu->gvt->lock);412412+ intel_gvt_reset_vgpu_locked(vgpu, true, 0);413413+ mutex_unlock(&vgpu->gvt->lock);406414}