182d375d1SZhi Wang /* 282d375d1SZhi Wang * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. 382d375d1SZhi Wang * 482d375d1SZhi Wang * Permission is hereby granted, free of charge, to any person obtaining a 582d375d1SZhi Wang * copy of this software and associated documentation files (the "Software"), 682d375d1SZhi Wang * to deal in the Software without restriction, including without limitation 782d375d1SZhi Wang * the rights to use, copy, modify, merge, publish, distribute, sublicense, 882d375d1SZhi Wang * and/or sell copies of the Software, and to permit persons to whom the 982d375d1SZhi Wang * Software is furnished to do so, subject to the following conditions: 1082d375d1SZhi Wang * 1182d375d1SZhi Wang * The above copyright notice and this permission notice (including the next 1282d375d1SZhi Wang * paragraph) shall be included in all copies or substantial portions of the 1382d375d1SZhi Wang * Software. 1482d375d1SZhi Wang * 1582d375d1SZhi Wang * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1682d375d1SZhi Wang * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1782d375d1SZhi Wang * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1882d375d1SZhi Wang * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1982d375d1SZhi Wang * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2082d375d1SZhi Wang * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2182d375d1SZhi Wang * SOFTWARE. 2282d375d1SZhi Wang * 2382d375d1SZhi Wang * Authors: 2482d375d1SZhi Wang * Eddie Dong <eddie.dong@intel.com> 2582d375d1SZhi Wang * Kevin Tian <kevin.tian@intel.com> 2682d375d1SZhi Wang * 2782d375d1SZhi Wang * Contributors: 2882d375d1SZhi Wang * Ping Gao <ping.a.gao@intel.com> 2982d375d1SZhi Wang * Zhi Wang <zhi.a.wang@intel.com> 3082d375d1SZhi Wang * Bing Niu <bing.niu@intel.com> 3182d375d1SZhi Wang * 3282d375d1SZhi Wang */ 3382d375d1SZhi Wang 3482d375d1SZhi Wang #include "i915_drv.h" 35feddf6e8SZhenyu Wang #include "gvt.h" 36feddf6e8SZhenyu Wang #include "i915_pvinfo.h" 3782d375d1SZhi Wang 3823736d1bSPing Gao void populate_pvinfo_page(struct intel_vgpu *vgpu) 3982d375d1SZhi Wang { 4082d375d1SZhi Wang /* setup the ballooning information */ 4182d375d1SZhi Wang vgpu_vreg64(vgpu, vgtif_reg(magic)) = VGT_MAGIC; 4282d375d1SZhi Wang vgpu_vreg(vgpu, vgtif_reg(version_major)) = 1; 4382d375d1SZhi Wang vgpu_vreg(vgpu, vgtif_reg(version_minor)) = 0; 4482d375d1SZhi Wang vgpu_vreg(vgpu, vgtif_reg(display_ready)) = 0; 4582d375d1SZhi Wang vgpu_vreg(vgpu, vgtif_reg(vgt_id)) = vgpu->id; 4682d375d1SZhi Wang vgpu_vreg(vgpu, vgtif_reg(avail_rs.mappable_gmadr.base)) = 4782d375d1SZhi Wang vgpu_aperture_gmadr_base(vgpu); 4882d375d1SZhi Wang vgpu_vreg(vgpu, vgtif_reg(avail_rs.mappable_gmadr.size)) = 4982d375d1SZhi Wang vgpu_aperture_sz(vgpu); 5082d375d1SZhi Wang vgpu_vreg(vgpu, vgtif_reg(avail_rs.nonmappable_gmadr.base)) = 5182d375d1SZhi Wang vgpu_hidden_gmadr_base(vgpu); 5282d375d1SZhi Wang vgpu_vreg(vgpu, vgtif_reg(avail_rs.nonmappable_gmadr.size)) = 5382d375d1SZhi Wang vgpu_hidden_sz(vgpu); 5482d375d1SZhi Wang 5582d375d1SZhi Wang vgpu_vreg(vgpu, vgtif_reg(avail_rs.fence_num)) = vgpu_fence_sz(vgpu); 5682d375d1SZhi Wang 5782d375d1SZhi Wang gvt_dbg_core("Populate PVINFO PAGE for vGPU %d\n", vgpu->id); 5882d375d1SZhi Wang gvt_dbg_core("aperture base [GMADR] 0x%llx size 0x%llx\n", 5982d375d1SZhi Wang vgpu_aperture_gmadr_base(vgpu), vgpu_aperture_sz(vgpu)); 6082d375d1SZhi Wang gvt_dbg_core("hidden base [GMADR] 0x%llx size=0x%llx\n", 6182d375d1SZhi Wang vgpu_hidden_gmadr_base(vgpu), vgpu_hidden_sz(vgpu)); 6282d375d1SZhi Wang gvt_dbg_core("fence size %d\n", vgpu_fence_sz(vgpu)); 6382d375d1SZhi Wang 6482d375d1SZhi Wang WARN_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE); 6582d375d1SZhi Wang } 6682d375d1SZhi Wang 6782d375d1SZhi Wang /** 681f31c829SZhenyu Wang * intel_gvt_init_vgpu_types - initialize vGPU type list 691f31c829SZhenyu Wang * @gvt : GVT device 701f31c829SZhenyu Wang * 711f31c829SZhenyu Wang * Initialize vGPU type list based on available resource. 721f31c829SZhenyu Wang * 731f31c829SZhenyu Wang */ 741f31c829SZhenyu Wang int intel_gvt_init_vgpu_types(struct intel_gvt *gvt) 751f31c829SZhenyu Wang { 761f31c829SZhenyu Wang unsigned int num_types; 772d6ceb8eSZhenyu Wang unsigned int i, low_avail, high_avail; 781f31c829SZhenyu Wang unsigned int min_low; 791f31c829SZhenyu Wang 801f31c829SZhenyu Wang /* vGPU type name is defined as GVTg_Vx_y which contains 811f31c829SZhenyu Wang * physical GPU generation type and 'y' means maximum vGPU 821f31c829SZhenyu Wang * instances user can create on one physical GPU for this 831f31c829SZhenyu Wang * type. 841f31c829SZhenyu Wang * 851f31c829SZhenyu Wang * Depend on physical SKU resource, might see vGPU types like 861f31c829SZhenyu Wang * GVTg_V4_8, GVTg_V4_4, GVTg_V4_2, etc. We can create 871f31c829SZhenyu Wang * different types of vGPU on same physical GPU depending on 881f31c829SZhenyu Wang * available resource. Each vGPU type will have "avail_instance" 891f31c829SZhenyu Wang * to indicate how many vGPU instance can be created for this 901f31c829SZhenyu Wang * type. 911f31c829SZhenyu Wang * 921f31c829SZhenyu Wang */ 932d6ceb8eSZhenyu Wang low_avail = gvt_aperture_sz(gvt) - HOST_LOW_GM_SIZE; 942d6ceb8eSZhenyu Wang high_avail = gvt_hidden_sz(gvt) - HOST_HIGH_GM_SIZE; 951f31c829SZhenyu Wang num_types = 4; 961f31c829SZhenyu Wang 971f31c829SZhenyu Wang gvt->types = kzalloc(num_types * sizeof(struct intel_vgpu_type), 981f31c829SZhenyu Wang GFP_KERNEL); 991f31c829SZhenyu Wang if (!gvt->types) 1001f31c829SZhenyu Wang return -ENOMEM; 1011f31c829SZhenyu Wang 1021f31c829SZhenyu Wang min_low = MB_TO_BYTES(32); 1031f31c829SZhenyu Wang for (i = 0; i < num_types; ++i) { 1041f31c829SZhenyu Wang if (low_avail / min_low == 0) 1051f31c829SZhenyu Wang break; 1061f31c829SZhenyu Wang gvt->types[i].low_gm_size = min_low; 107888530b5SZhenyu Wang gvt->types[i].high_gm_size = max((min_low<<3), MB_TO_BYTES(384U)); 1081f31c829SZhenyu Wang gvt->types[i].fence = 4; 1092d6ceb8eSZhenyu Wang gvt->types[i].max_instance = min(low_avail / min_low, 1102d6ceb8eSZhenyu Wang high_avail / gvt->types[i].high_gm_size); 1111f31c829SZhenyu Wang gvt->types[i].avail_instance = gvt->types[i].max_instance; 1121f31c829SZhenyu Wang 1131f31c829SZhenyu Wang if (IS_GEN8(gvt->dev_priv)) 1141f31c829SZhenyu Wang sprintf(gvt->types[i].name, "GVTg_V4_%u", 1151f31c829SZhenyu Wang gvt->types[i].max_instance); 1161f31c829SZhenyu Wang else if (IS_GEN9(gvt->dev_priv)) 1171f31c829SZhenyu Wang sprintf(gvt->types[i].name, "GVTg_V5_%u", 1181f31c829SZhenyu Wang gvt->types[i].max_instance); 1191f31c829SZhenyu Wang 1201f31c829SZhenyu Wang min_low <<= 1; 1211f31c829SZhenyu Wang gvt_dbg_core("type[%d]: %s max %u avail %u low %u high %u fence %u\n", 1221f31c829SZhenyu Wang i, gvt->types[i].name, gvt->types[i].max_instance, 1231f31c829SZhenyu Wang gvt->types[i].avail_instance, 1241f31c829SZhenyu Wang gvt->types[i].low_gm_size, 1251f31c829SZhenyu Wang gvt->types[i].high_gm_size, gvt->types[i].fence); 1261f31c829SZhenyu Wang } 1271f31c829SZhenyu Wang 1281f31c829SZhenyu Wang gvt->num_types = i; 1291f31c829SZhenyu Wang return 0; 1301f31c829SZhenyu Wang } 1311f31c829SZhenyu Wang 1321f31c829SZhenyu Wang void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt) 1331f31c829SZhenyu Wang { 1341f31c829SZhenyu Wang kfree(gvt->types); 1351f31c829SZhenyu Wang } 1361f31c829SZhenyu Wang 1371f31c829SZhenyu Wang static void intel_gvt_update_vgpu_types(struct intel_gvt *gvt) 1381f31c829SZhenyu Wang { 1391f31c829SZhenyu Wang int i; 1401f31c829SZhenyu Wang unsigned int low_gm_avail, high_gm_avail, fence_avail; 1411f31c829SZhenyu Wang unsigned int low_gm_min, high_gm_min, fence_min, total_min; 1421f31c829SZhenyu Wang 1431f31c829SZhenyu Wang /* Need to depend on maxium hw resource size but keep on 1441f31c829SZhenyu Wang * static config for now. 1451f31c829SZhenyu Wang */ 1462d6ceb8eSZhenyu Wang low_gm_avail = gvt_aperture_sz(gvt) - HOST_LOW_GM_SIZE - 1471f31c829SZhenyu Wang gvt->gm.vgpu_allocated_low_gm_size; 1482d6ceb8eSZhenyu Wang high_gm_avail = gvt_hidden_sz(gvt) - HOST_HIGH_GM_SIZE - 1491f31c829SZhenyu Wang gvt->gm.vgpu_allocated_high_gm_size; 1501f31c829SZhenyu Wang fence_avail = gvt_fence_sz(gvt) - HOST_FENCE - 1511f31c829SZhenyu Wang gvt->fence.vgpu_allocated_fence_num; 1521f31c829SZhenyu Wang 1531f31c829SZhenyu Wang for (i = 0; i < gvt->num_types; i++) { 1541f31c829SZhenyu Wang low_gm_min = low_gm_avail / gvt->types[i].low_gm_size; 1551f31c829SZhenyu Wang high_gm_min = high_gm_avail / gvt->types[i].high_gm_size; 1561f31c829SZhenyu Wang fence_min = fence_avail / gvt->types[i].fence; 1571f31c829SZhenyu Wang total_min = min(min(low_gm_min, high_gm_min), fence_min); 1581f31c829SZhenyu Wang gvt->types[i].avail_instance = min(gvt->types[i].max_instance, 1591f31c829SZhenyu Wang total_min); 1601f31c829SZhenyu Wang 1611f31c829SZhenyu Wang gvt_dbg_core("update type[%d]: %s max %u avail %u low %u high %u fence %u\n", 1621f31c829SZhenyu Wang i, gvt->types[i].name, gvt->types[i].max_instance, 1631f31c829SZhenyu Wang gvt->types[i].avail_instance, gvt->types[i].low_gm_size, 1641f31c829SZhenyu Wang gvt->types[i].high_gm_size, gvt->types[i].fence); 1651f31c829SZhenyu Wang } 1661f31c829SZhenyu Wang } 1671f31c829SZhenyu Wang 1681f31c829SZhenyu Wang /** 16982d375d1SZhi Wang * intel_gvt_destroy_vgpu - destroy a virtual GPU 17082d375d1SZhi Wang * @vgpu: virtual GPU 17182d375d1SZhi Wang * 17282d375d1SZhi Wang * This function is called when user wants to destroy a virtual GPU. 17382d375d1SZhi Wang * 17482d375d1SZhi Wang */ 17582d375d1SZhi Wang void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu) 17682d375d1SZhi Wang { 17782d375d1SZhi Wang struct intel_gvt *gvt = vgpu->gvt; 17882d375d1SZhi Wang 17982d375d1SZhi Wang mutex_lock(&gvt->lock); 18082d375d1SZhi Wang 18182d375d1SZhi Wang vgpu->active = false; 18282d375d1SZhi Wang idr_remove(&gvt->vgpu_idr, vgpu->id); 18382d375d1SZhi Wang 1844b63960eSZhi Wang if (atomic_read(&vgpu->running_workload_num)) { 1854b63960eSZhi Wang mutex_unlock(&gvt->lock); 1864b63960eSZhi Wang intel_gvt_wait_vgpu_idle(vgpu); 1874b63960eSZhi Wang mutex_lock(&gvt->lock); 1884b63960eSZhi Wang } 1894b63960eSZhi Wang 1904b63960eSZhi Wang intel_vgpu_stop_schedule(vgpu); 1914b63960eSZhi Wang intel_vgpu_clean_sched_policy(vgpu); 192e4734057SZhi Wang intel_vgpu_clean_gvt_context(vgpu); 19328c4c6caSZhi Wang intel_vgpu_clean_execlist(vgpu); 19404d348aeSZhi Wang intel_vgpu_clean_display(vgpu); 1954d60c5fdSZhi Wang intel_vgpu_clean_opregion(vgpu); 1962707e444SZhi Wang intel_vgpu_clean_gtt(vgpu); 19782d375d1SZhi Wang intel_gvt_hypervisor_detach_vgpu(vgpu); 19882d375d1SZhi Wang intel_vgpu_free_resource(vgpu); 199cdcc4347SChangbin Du intel_vgpu_clean_mmio(vgpu); 20082d375d1SZhi Wang vfree(vgpu); 20182d375d1SZhi Wang 2021f31c829SZhenyu Wang intel_gvt_update_vgpu_types(gvt); 20382d375d1SZhi Wang mutex_unlock(&gvt->lock); 20482d375d1SZhi Wang } 20582d375d1SZhi Wang 2061f31c829SZhenyu Wang static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt, 20782d375d1SZhi Wang struct intel_vgpu_creation_params *param) 20882d375d1SZhi Wang { 20982d375d1SZhi Wang struct intel_vgpu *vgpu; 21082d375d1SZhi Wang int ret; 21182d375d1SZhi Wang 21282d375d1SZhi Wang gvt_dbg_core("handle %llu low %llu MB high %llu MB fence %llu\n", 21382d375d1SZhi Wang param->handle, param->low_gm_sz, param->high_gm_sz, 21482d375d1SZhi Wang param->fence_sz); 21582d375d1SZhi Wang 21682d375d1SZhi Wang vgpu = vzalloc(sizeof(*vgpu)); 21782d375d1SZhi Wang if (!vgpu) 21882d375d1SZhi Wang return ERR_PTR(-ENOMEM); 21982d375d1SZhi Wang 22082d375d1SZhi Wang mutex_lock(&gvt->lock); 22182d375d1SZhi Wang 22282d375d1SZhi Wang ret = idr_alloc(&gvt->vgpu_idr, vgpu, 1, GVT_MAX_VGPU, GFP_KERNEL); 22382d375d1SZhi Wang if (ret < 0) 22482d375d1SZhi Wang goto out_free_vgpu; 22582d375d1SZhi Wang 22682d375d1SZhi Wang vgpu->id = ret; 22782d375d1SZhi Wang vgpu->handle = param->handle; 22882d375d1SZhi Wang vgpu->gvt = gvt; 22917865713SZhi Wang bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES); 23082d375d1SZhi Wang 231536fc234SChangbin Du intel_vgpu_init_cfg_space(vgpu, param->primary); 23282d375d1SZhi Wang 233cdcc4347SChangbin Du ret = intel_vgpu_init_mmio(vgpu); 23482d375d1SZhi Wang if (ret) 2354e537891SJike Song goto out_clean_idr; 23682d375d1SZhi Wang 23782d375d1SZhi Wang ret = intel_vgpu_alloc_resource(vgpu, param); 23882d375d1SZhi Wang if (ret) 23982d375d1SZhi Wang goto out_clean_vgpu_mmio; 24082d375d1SZhi Wang 24182d375d1SZhi Wang populate_pvinfo_page(vgpu); 24282d375d1SZhi Wang 24382d375d1SZhi Wang ret = intel_gvt_hypervisor_attach_vgpu(vgpu); 24482d375d1SZhi Wang if (ret) 24582d375d1SZhi Wang goto out_clean_vgpu_resource; 24682d375d1SZhi Wang 2472707e444SZhi Wang ret = intel_vgpu_init_gtt(vgpu); 2482707e444SZhi Wang if (ret) 2492707e444SZhi Wang goto out_detach_hypervisor_vgpu; 2502707e444SZhi Wang 25104d348aeSZhi Wang ret = intel_vgpu_init_display(vgpu); 25204d348aeSZhi Wang if (ret) 2538f89743bSJike Song goto out_clean_gtt; 25404d348aeSZhi Wang 2558453d674SZhi Wang ret = intel_vgpu_init_execlist(vgpu); 2568453d674SZhi Wang if (ret) 2578453d674SZhi Wang goto out_clean_display; 2588453d674SZhi Wang 259e4734057SZhi Wang ret = intel_vgpu_init_gvt_context(vgpu); 260e4734057SZhi Wang if (ret) 261e4734057SZhi Wang goto out_clean_execlist; 262e4734057SZhi Wang 2634b63960eSZhi Wang ret = intel_vgpu_init_sched_policy(vgpu); 2644b63960eSZhi Wang if (ret) 2654b63960eSZhi Wang goto out_clean_shadow_ctx; 2664b63960eSZhi Wang 26782d375d1SZhi Wang vgpu->active = true; 26882d375d1SZhi Wang mutex_unlock(&gvt->lock); 26982d375d1SZhi Wang 27082d375d1SZhi Wang return vgpu; 27182d375d1SZhi Wang 2724b63960eSZhi Wang out_clean_shadow_ctx: 2734b63960eSZhi Wang intel_vgpu_clean_gvt_context(vgpu); 274e4734057SZhi Wang out_clean_execlist: 275e4734057SZhi Wang intel_vgpu_clean_execlist(vgpu); 2768453d674SZhi Wang out_clean_display: 2778453d674SZhi Wang intel_vgpu_clean_display(vgpu); 2784d60c5fdSZhi Wang out_clean_gtt: 2794d60c5fdSZhi Wang intel_vgpu_clean_gtt(vgpu); 2802707e444SZhi Wang out_detach_hypervisor_vgpu: 2812707e444SZhi Wang intel_gvt_hypervisor_detach_vgpu(vgpu); 28282d375d1SZhi Wang out_clean_vgpu_resource: 28382d375d1SZhi Wang intel_vgpu_free_resource(vgpu); 28482d375d1SZhi Wang out_clean_vgpu_mmio: 285cdcc4347SChangbin Du intel_vgpu_clean_mmio(vgpu); 2864e537891SJike Song out_clean_idr: 2874e537891SJike Song idr_remove(&gvt->vgpu_idr, vgpu->id); 28882d375d1SZhi Wang out_free_vgpu: 28982d375d1SZhi Wang vfree(vgpu); 29082d375d1SZhi Wang mutex_unlock(&gvt->lock); 29182d375d1SZhi Wang return ERR_PTR(ret); 29282d375d1SZhi Wang } 2931f31c829SZhenyu Wang 2941f31c829SZhenyu Wang /** 2951f31c829SZhenyu Wang * intel_gvt_create_vgpu - create a virtual GPU 2961f31c829SZhenyu Wang * @gvt: GVT device 2971f31c829SZhenyu Wang * @type: type of the vGPU to create 2981f31c829SZhenyu Wang * 2991f31c829SZhenyu Wang * This function is called when user wants to create a virtual GPU. 3001f31c829SZhenyu Wang * 3011f31c829SZhenyu Wang * Returns: 3021f31c829SZhenyu Wang * pointer to intel_vgpu, error pointer if failed. 3031f31c829SZhenyu Wang */ 3041f31c829SZhenyu Wang struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt, 3051f31c829SZhenyu Wang struct intel_vgpu_type *type) 3061f31c829SZhenyu Wang { 3071f31c829SZhenyu Wang struct intel_vgpu_creation_params param; 3081f31c829SZhenyu Wang struct intel_vgpu *vgpu; 3091f31c829SZhenyu Wang 3101f31c829SZhenyu Wang param.handle = 0; 311e992faeeSDu, Changbin param.primary = 1; 3121f31c829SZhenyu Wang param.low_gm_sz = type->low_gm_size; 3131f31c829SZhenyu Wang param.high_gm_sz = type->high_gm_size; 3141f31c829SZhenyu Wang param.fence_sz = type->fence; 3151f31c829SZhenyu Wang 3161f31c829SZhenyu Wang /* XXX current param based on MB */ 3171f31c829SZhenyu Wang param.low_gm_sz = BYTES_TO_MB(param.low_gm_sz); 3181f31c829SZhenyu Wang param.high_gm_sz = BYTES_TO_MB(param.high_gm_sz); 3191f31c829SZhenyu Wang 3201f31c829SZhenyu Wang vgpu = __intel_gvt_create_vgpu(gvt, ¶m); 3211f31c829SZhenyu Wang if (IS_ERR(vgpu)) 3221f31c829SZhenyu Wang return vgpu; 3231f31c829SZhenyu Wang 3241f31c829SZhenyu Wang /* calculate left instance change for types */ 3251f31c829SZhenyu Wang intel_gvt_update_vgpu_types(gvt); 3261f31c829SZhenyu Wang 3271f31c829SZhenyu Wang return vgpu; 3281f31c829SZhenyu Wang } 3299ec1e66bSJike Song 3309ec1e66bSJike Song /** 331cfe65f40SChangbin Du * intel_gvt_reset_vgpu_locked - reset a virtual GPU by DMLR or GT reset 332cfe65f40SChangbin Du * @vgpu: virtual GPU 333cfe65f40SChangbin Du * @dmlr: vGPU Device Model Level Reset or GT Reset 334cfe65f40SChangbin Du * @engine_mask: engines to reset for GT reset 335cfe65f40SChangbin Du * 336cfe65f40SChangbin Du * This function is called when user wants to reset a virtual GPU through 337cfe65f40SChangbin Du * device model reset or GT reset. The caller should hold the gvt lock. 338cfe65f40SChangbin Du * 339cfe65f40SChangbin Du * vGPU Device Model Level Reset (DMLR) simulates the PCI level reset to reset 340cfe65f40SChangbin Du * the whole vGPU to default state as when it is created. This vGPU function 341cfe65f40SChangbin Du * is required both for functionary and security concerns.The ultimate goal 342cfe65f40SChangbin Du * of vGPU FLR is that reuse a vGPU instance by virtual machines. When we 343cfe65f40SChangbin Du * assign a vGPU to a virtual machine we must isse such reset first. 344cfe65f40SChangbin Du * 345cfe65f40SChangbin Du * Full GT Reset and Per-Engine GT Reset are soft reset flow for GPU engines 346cfe65f40SChangbin Du * (Render, Blitter, Video, Video Enhancement). It is defined by GPU Spec. 347cfe65f40SChangbin Du * Unlike the FLR, GT reset only reset particular resource of a vGPU per 348cfe65f40SChangbin Du * the reset request. Guest driver can issue a GT reset by programming the 349cfe65f40SChangbin Du * virtual GDRST register to reset specific virtual GPU engine or all 350cfe65f40SChangbin Du * engines. 351cfe65f40SChangbin Du * 352cfe65f40SChangbin Du * The parameter dev_level is to identify if we will do DMLR or GT reset. 353cfe65f40SChangbin Du * The parameter engine_mask is to specific the engines that need to be 354cfe65f40SChangbin Du * resetted. If value ALL_ENGINES is given for engine_mask, it means 355cfe65f40SChangbin Du * the caller requests a full GT reset that we will reset all virtual 356cfe65f40SChangbin Du * GPU engines. For FLR, engine_mask is ignored. 357cfe65f40SChangbin Du */ 358cfe65f40SChangbin Du void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr, 359cfe65f40SChangbin Du unsigned int engine_mask) 360cfe65f40SChangbin Du { 361cfe65f40SChangbin Du struct intel_gvt *gvt = vgpu->gvt; 362cfe65f40SChangbin Du struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; 363cfe65f40SChangbin Du 364cfe65f40SChangbin Du gvt_dbg_core("------------------------------------------\n"); 365cfe65f40SChangbin Du gvt_dbg_core("resseting vgpu%d, dmlr %d, engine_mask %08x\n", 366cfe65f40SChangbin Du vgpu->id, dmlr, engine_mask); 367cfe65f40SChangbin Du vgpu->resetting = true; 368cfe65f40SChangbin Du 369cfe65f40SChangbin Du intel_vgpu_stop_schedule(vgpu); 370cfe65f40SChangbin Du /* 371cfe65f40SChangbin Du * The current_vgpu will set to NULL after stopping the 372cfe65f40SChangbin Du * scheduler when the reset is triggered by current vgpu. 373cfe65f40SChangbin Du */ 374cfe65f40SChangbin Du if (scheduler->current_vgpu == NULL) { 375cfe65f40SChangbin Du mutex_unlock(&gvt->lock); 376cfe65f40SChangbin Du intel_gvt_wait_vgpu_idle(vgpu); 377cfe65f40SChangbin Du mutex_lock(&gvt->lock); 378cfe65f40SChangbin Du } 379cfe65f40SChangbin Du 380cfe65f40SChangbin Du intel_vgpu_reset_execlist(vgpu, dmlr ? ALL_ENGINES : engine_mask); 381cfe65f40SChangbin Du 382cfe65f40SChangbin Du /* full GPU reset or device model level reset */ 383cfe65f40SChangbin Du if (engine_mask == ALL_ENGINES || dmlr) { 384cfe65f40SChangbin Du intel_vgpu_reset_gtt(vgpu, dmlr); 385cfe65f40SChangbin Du intel_vgpu_reset_resource(vgpu); 386cfe65f40SChangbin Du intel_vgpu_reset_mmio(vgpu); 387cfe65f40SChangbin Du populate_pvinfo_page(vgpu); 388cfe65f40SChangbin Du 389cfe65f40SChangbin Du if (dmlr) 390cfe65f40SChangbin Du intel_vgpu_reset_cfg_space(vgpu); 391cfe65f40SChangbin Du } 392cfe65f40SChangbin Du 393cfe65f40SChangbin Du vgpu->resetting = false; 394cfe65f40SChangbin Du gvt_dbg_core("reset vgpu%d done\n", vgpu->id); 395cfe65f40SChangbin Du gvt_dbg_core("------------------------------------------\n"); 396cfe65f40SChangbin Du } 397cfe65f40SChangbin Du 398cfe65f40SChangbin Du /** 399cfe65f40SChangbin Du * intel_gvt_reset_vgpu - reset a virtual GPU (Function Level) 4009ec1e66bSJike Song * @vgpu: virtual GPU 4019ec1e66bSJike Song * 4029ec1e66bSJike Song * This function is called when user wants to reset a virtual GPU. 4039ec1e66bSJike Song * 4049ec1e66bSJike Song */ 4059ec1e66bSJike Song void intel_gvt_reset_vgpu(struct intel_vgpu *vgpu) 4069ec1e66bSJike Song { 407cfe65f40SChangbin Du mutex_lock(&vgpu->gvt->lock); 408cfe65f40SChangbin Du intel_gvt_reset_vgpu_locked(vgpu, true, 0); 409cfe65f40SChangbin Du mutex_unlock(&vgpu->gvt->lock); 4109ec1e66bSJike Song } 411