1 1.1 riastrad /* $NetBSD: aperture_gm.c,v 1.2 2021/12/18 23:45:31 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad /* 4 1.1 riastrad * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. 5 1.1 riastrad * 6 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining a 7 1.1 riastrad * copy of this software and associated documentation files (the "Software"), 8 1.1 riastrad * to deal in the Software without restriction, including without limitation 9 1.1 riastrad * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 1.1 riastrad * and/or sell copies of the Software, and to permit persons to whom the 11 1.1 riastrad * Software is furnished to do so, subject to the following conditions: 12 1.1 riastrad * 13 1.1 riastrad * The above copyright notice and this permission notice (including the next 14 1.1 riastrad * paragraph) shall be included in all copies or substantial portions of the 15 1.1 riastrad * Software. 16 1.1 riastrad * 17 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 1.1 riastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 1.1 riastrad * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 1.1 riastrad * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 1.1 riastrad * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 1.1 riastrad * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 1.1 riastrad * SOFTWARE. 24 1.1 riastrad * 25 1.1 riastrad * Authors: 26 1.1 riastrad * Kevin Tian <kevin.tian (at) intel.com> 27 1.1 riastrad * Dexuan Cui 28 1.1 riastrad * 29 1.1 riastrad * Contributors: 30 1.1 riastrad * Pei Zhang <pei.zhang (at) intel.com> 31 1.1 riastrad * Min He <min.he (at) intel.com> 32 1.1 riastrad * Niu Bing <bing.niu (at) intel.com> 33 1.1 riastrad * Yulei Zhang <yulei.zhang (at) intel.com> 34 1.1 riastrad * Zhenyu Wang <zhenyuw (at) linux.intel.com> 35 1.1 riastrad * Zhi Wang <zhi.a.wang (at) intel.com> 36 1.1 riastrad * 37 1.1 riastrad */ 38 1.1 riastrad 39 1.1 riastrad #include <sys/cdefs.h> 40 1.1 riastrad __KERNEL_RCSID(0, "$NetBSD: aperture_gm.c,v 1.2 2021/12/18 23:45:31 riastradh Exp $"); 41 1.1 riastrad 42 1.1 riastrad #include "i915_drv.h" 43 1.1 riastrad #include "i915_gem_fence_reg.h" 44 1.1 riastrad #include "gvt.h" 45 1.1 riastrad 46 1.1 riastrad static int alloc_gm(struct intel_vgpu *vgpu, bool high_gm) 47 1.1 riastrad { 48 1.1 riastrad struct intel_gvt *gvt = vgpu->gvt; 49 1.1 riastrad struct drm_i915_private *dev_priv = gvt->dev_priv; 50 1.1 riastrad unsigned int flags; 51 1.1 riastrad u64 start, end, size; 52 1.1 riastrad struct drm_mm_node *node; 53 1.1 riastrad int ret; 54 1.1 riastrad 55 1.1 riastrad if (high_gm) { 56 1.1 riastrad node = &vgpu->gm.high_gm_node; 57 1.1 riastrad size = vgpu_hidden_sz(vgpu); 58 1.1 riastrad start = ALIGN(gvt_hidden_gmadr_base(gvt), I915_GTT_PAGE_SIZE); 59 1.1 riastrad end = ALIGN(gvt_hidden_gmadr_end(gvt), I915_GTT_PAGE_SIZE); 60 1.1 riastrad flags = PIN_HIGH; 61 1.1 riastrad } else { 62 1.1 riastrad node = &vgpu->gm.low_gm_node; 63 1.1 riastrad size = vgpu_aperture_sz(vgpu); 64 1.1 riastrad start = ALIGN(gvt_aperture_gmadr_base(gvt), I915_GTT_PAGE_SIZE); 65 1.1 riastrad end = ALIGN(gvt_aperture_gmadr_end(gvt), I915_GTT_PAGE_SIZE); 66 1.1 riastrad flags = PIN_MAPPABLE; 67 1.1 riastrad } 68 1.1 riastrad 69 1.1 riastrad mutex_lock(&dev_priv->ggtt.vm.mutex); 70 1.1 riastrad mmio_hw_access_pre(dev_priv); 71 1.1 riastrad ret = i915_gem_gtt_insert(&dev_priv->ggtt.vm, node, 72 1.1 riastrad size, I915_GTT_PAGE_SIZE, 73 1.1 riastrad I915_COLOR_UNEVICTABLE, 74 1.1 riastrad start, end, flags); 75 1.1 riastrad mmio_hw_access_post(dev_priv); 76 1.1 riastrad mutex_unlock(&dev_priv->ggtt.vm.mutex); 77 1.1 riastrad if (ret) 78 1.1 riastrad gvt_err("fail to alloc %s gm space from host\n", 79 1.1 riastrad high_gm ? "high" : "low"); 80 1.1 riastrad 81 1.1 riastrad return ret; 82 1.1 riastrad } 83 1.1 riastrad 84 1.1 riastrad static int alloc_vgpu_gm(struct intel_vgpu *vgpu) 85 1.1 riastrad { 86 1.1 riastrad struct intel_gvt *gvt = vgpu->gvt; 87 1.1 riastrad struct drm_i915_private *dev_priv = gvt->dev_priv; 88 1.1 riastrad int ret; 89 1.1 riastrad 90 1.1 riastrad ret = alloc_gm(vgpu, false); 91 1.1 riastrad if (ret) 92 1.1 riastrad return ret; 93 1.1 riastrad 94 1.1 riastrad ret = alloc_gm(vgpu, true); 95 1.1 riastrad if (ret) 96 1.1 riastrad goto out_free_aperture; 97 1.1 riastrad 98 1.1 riastrad gvt_dbg_core("vgpu%d: alloc low GM start %llx size %llx\n", vgpu->id, 99 1.1 riastrad vgpu_aperture_offset(vgpu), vgpu_aperture_sz(vgpu)); 100 1.1 riastrad 101 1.1 riastrad gvt_dbg_core("vgpu%d: alloc high GM start %llx size %llx\n", vgpu->id, 102 1.1 riastrad vgpu_hidden_offset(vgpu), vgpu_hidden_sz(vgpu)); 103 1.1 riastrad 104 1.1 riastrad return 0; 105 1.1 riastrad out_free_aperture: 106 1.1 riastrad mutex_lock(&dev_priv->ggtt.vm.mutex); 107 1.1 riastrad drm_mm_remove_node(&vgpu->gm.low_gm_node); 108 1.1 riastrad mutex_unlock(&dev_priv->ggtt.vm.mutex); 109 1.1 riastrad return ret; 110 1.1 riastrad } 111 1.1 riastrad 112 1.1 riastrad static void free_vgpu_gm(struct intel_vgpu *vgpu) 113 1.1 riastrad { 114 1.1 riastrad struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; 115 1.1 riastrad 116 1.1 riastrad mutex_lock(&dev_priv->ggtt.vm.mutex); 117 1.1 riastrad drm_mm_remove_node(&vgpu->gm.low_gm_node); 118 1.1 riastrad drm_mm_remove_node(&vgpu->gm.high_gm_node); 119 1.1 riastrad mutex_unlock(&dev_priv->ggtt.vm.mutex); 120 1.1 riastrad } 121 1.1 riastrad 122 1.1 riastrad /** 123 1.1 riastrad * intel_vgpu_write_fence - write fence registers owned by a vGPU 124 1.1 riastrad * @vgpu: vGPU instance 125 1.1 riastrad * @fence: vGPU fence register number 126 1.1 riastrad * @value: Fence register value to be written 127 1.1 riastrad * 128 1.1 riastrad * This function is used to write fence registers owned by a vGPU. The vGPU 129 1.1 riastrad * fence register number will be translated into HW fence register number. 130 1.1 riastrad * 131 1.1 riastrad */ 132 1.1 riastrad void intel_vgpu_write_fence(struct intel_vgpu *vgpu, 133 1.1 riastrad u32 fence, u64 value) 134 1.1 riastrad { 135 1.1 riastrad struct intel_gvt *gvt = vgpu->gvt; 136 1.1 riastrad struct drm_i915_private *dev_priv = gvt->dev_priv; 137 1.1 riastrad struct i915_fence_reg *reg; 138 1.1 riastrad i915_reg_t fence_reg_lo, fence_reg_hi; 139 1.1 riastrad 140 1.1 riastrad assert_rpm_wakelock_held(&dev_priv->runtime_pm); 141 1.1 riastrad 142 1.1 riastrad if (WARN_ON(fence >= vgpu_fence_sz(vgpu))) 143 1.1 riastrad return; 144 1.1 riastrad 145 1.1 riastrad reg = vgpu->fence.regs[fence]; 146 1.1 riastrad if (WARN_ON(!reg)) 147 1.1 riastrad return; 148 1.1 riastrad 149 1.1 riastrad fence_reg_lo = FENCE_REG_GEN6_LO(reg->id); 150 1.1 riastrad fence_reg_hi = FENCE_REG_GEN6_HI(reg->id); 151 1.1 riastrad 152 1.1 riastrad I915_WRITE(fence_reg_lo, 0); 153 1.1 riastrad POSTING_READ(fence_reg_lo); 154 1.1 riastrad 155 1.1 riastrad I915_WRITE(fence_reg_hi, upper_32_bits(value)); 156 1.1 riastrad I915_WRITE(fence_reg_lo, lower_32_bits(value)); 157 1.1 riastrad POSTING_READ(fence_reg_lo); 158 1.1 riastrad } 159 1.1 riastrad 160 1.1 riastrad static void _clear_vgpu_fence(struct intel_vgpu *vgpu) 161 1.1 riastrad { 162 1.1 riastrad int i; 163 1.1 riastrad 164 1.1 riastrad for (i = 0; i < vgpu_fence_sz(vgpu); i++) 165 1.1 riastrad intel_vgpu_write_fence(vgpu, i, 0); 166 1.1 riastrad } 167 1.1 riastrad 168 1.1 riastrad static void free_vgpu_fence(struct intel_vgpu *vgpu) 169 1.1 riastrad { 170 1.1 riastrad struct intel_gvt *gvt = vgpu->gvt; 171 1.1 riastrad struct drm_i915_private *dev_priv = gvt->dev_priv; 172 1.1 riastrad struct i915_fence_reg *reg; 173 1.1 riastrad u32 i; 174 1.1 riastrad 175 1.1 riastrad if (WARN_ON(!vgpu_fence_sz(vgpu))) 176 1.1 riastrad return; 177 1.1 riastrad 178 1.1 riastrad intel_runtime_pm_get(&dev_priv->runtime_pm); 179 1.1 riastrad 180 1.1 riastrad mutex_lock(&dev_priv->ggtt.vm.mutex); 181 1.1 riastrad _clear_vgpu_fence(vgpu); 182 1.1 riastrad for (i = 0; i < vgpu_fence_sz(vgpu); i++) { 183 1.1 riastrad reg = vgpu->fence.regs[i]; 184 1.1 riastrad i915_unreserve_fence(reg); 185 1.1 riastrad vgpu->fence.regs[i] = NULL; 186 1.1 riastrad } 187 1.1 riastrad mutex_unlock(&dev_priv->ggtt.vm.mutex); 188 1.1 riastrad 189 1.1 riastrad intel_runtime_pm_put_unchecked(&dev_priv->runtime_pm); 190 1.1 riastrad } 191 1.1 riastrad 192 1.1 riastrad static int alloc_vgpu_fence(struct intel_vgpu *vgpu) 193 1.1 riastrad { 194 1.1 riastrad struct intel_gvt *gvt = vgpu->gvt; 195 1.1 riastrad struct drm_i915_private *dev_priv = gvt->dev_priv; 196 1.1 riastrad struct intel_runtime_pm *rpm = &dev_priv->runtime_pm; 197 1.1 riastrad struct i915_fence_reg *reg; 198 1.1 riastrad int i; 199 1.1 riastrad 200 1.1 riastrad intel_runtime_pm_get(rpm); 201 1.1 riastrad 202 1.1 riastrad /* Request fences from host */ 203 1.1 riastrad mutex_lock(&dev_priv->ggtt.vm.mutex); 204 1.1 riastrad 205 1.1 riastrad for (i = 0; i < vgpu_fence_sz(vgpu); i++) { 206 1.1 riastrad reg = i915_reserve_fence(&dev_priv->ggtt); 207 1.1 riastrad if (IS_ERR(reg)) 208 1.1 riastrad goto out_free_fence; 209 1.1 riastrad 210 1.1 riastrad vgpu->fence.regs[i] = reg; 211 1.1 riastrad } 212 1.1 riastrad 213 1.1 riastrad _clear_vgpu_fence(vgpu); 214 1.1 riastrad 215 1.1 riastrad mutex_unlock(&dev_priv->ggtt.vm.mutex); 216 1.1 riastrad intel_runtime_pm_put_unchecked(rpm); 217 1.1 riastrad return 0; 218 1.1 riastrad out_free_fence: 219 1.1 riastrad gvt_vgpu_err("Failed to alloc fences\n"); 220 1.1 riastrad /* Return fences to host, if fail */ 221 1.1 riastrad for (i = 0; i < vgpu_fence_sz(vgpu); i++) { 222 1.1 riastrad reg = vgpu->fence.regs[i]; 223 1.1 riastrad if (!reg) 224 1.1 riastrad continue; 225 1.1 riastrad i915_unreserve_fence(reg); 226 1.1 riastrad vgpu->fence.regs[i] = NULL; 227 1.1 riastrad } 228 1.1 riastrad mutex_unlock(&dev_priv->ggtt.vm.mutex); 229 1.1 riastrad intel_runtime_pm_put_unchecked(rpm); 230 1.1 riastrad return -ENOSPC; 231 1.1 riastrad } 232 1.1 riastrad 233 1.1 riastrad static void free_resource(struct intel_vgpu *vgpu) 234 1.1 riastrad { 235 1.1 riastrad struct intel_gvt *gvt = vgpu->gvt; 236 1.1 riastrad 237 1.1 riastrad gvt->gm.vgpu_allocated_low_gm_size -= vgpu_aperture_sz(vgpu); 238 1.1 riastrad gvt->gm.vgpu_allocated_high_gm_size -= vgpu_hidden_sz(vgpu); 239 1.1 riastrad gvt->fence.vgpu_allocated_fence_num -= vgpu_fence_sz(vgpu); 240 1.1 riastrad } 241 1.1 riastrad 242 1.1 riastrad static int alloc_resource(struct intel_vgpu *vgpu, 243 1.1 riastrad struct intel_vgpu_creation_params *param) 244 1.1 riastrad { 245 1.1 riastrad struct intel_gvt *gvt = vgpu->gvt; 246 1.1 riastrad unsigned long request, avail, max, taken; 247 1.1 riastrad const char *item; 248 1.1 riastrad 249 1.1 riastrad if (!param->low_gm_sz || !param->high_gm_sz || !param->fence_sz) { 250 1.1 riastrad gvt_vgpu_err("Invalid vGPU creation params\n"); 251 1.1 riastrad return -EINVAL; 252 1.1 riastrad } 253 1.1 riastrad 254 1.1 riastrad item = "low GM space"; 255 1.1 riastrad max = gvt_aperture_sz(gvt) - HOST_LOW_GM_SIZE; 256 1.1 riastrad taken = gvt->gm.vgpu_allocated_low_gm_size; 257 1.1 riastrad avail = max - taken; 258 1.1 riastrad request = MB_TO_BYTES(param->low_gm_sz); 259 1.1 riastrad 260 1.1 riastrad if (request > avail) 261 1.1 riastrad goto no_enough_resource; 262 1.1 riastrad 263 1.1 riastrad vgpu_aperture_sz(vgpu) = ALIGN(request, I915_GTT_PAGE_SIZE); 264 1.1 riastrad 265 1.1 riastrad item = "high GM space"; 266 1.1 riastrad max = gvt_hidden_sz(gvt) - HOST_HIGH_GM_SIZE; 267 1.1 riastrad taken = gvt->gm.vgpu_allocated_high_gm_size; 268 1.1 riastrad avail = max - taken; 269 1.1 riastrad request = MB_TO_BYTES(param->high_gm_sz); 270 1.1 riastrad 271 1.1 riastrad if (request > avail) 272 1.1 riastrad goto no_enough_resource; 273 1.1 riastrad 274 1.1 riastrad vgpu_hidden_sz(vgpu) = ALIGN(request, I915_GTT_PAGE_SIZE); 275 1.1 riastrad 276 1.1 riastrad item = "fence"; 277 1.1 riastrad max = gvt_fence_sz(gvt) - HOST_FENCE; 278 1.1 riastrad taken = gvt->fence.vgpu_allocated_fence_num; 279 1.1 riastrad avail = max - taken; 280 1.1 riastrad request = param->fence_sz; 281 1.1 riastrad 282 1.1 riastrad if (request > avail) 283 1.1 riastrad goto no_enough_resource; 284 1.1 riastrad 285 1.1 riastrad vgpu_fence_sz(vgpu) = request; 286 1.1 riastrad 287 1.1 riastrad gvt->gm.vgpu_allocated_low_gm_size += MB_TO_BYTES(param->low_gm_sz); 288 1.1 riastrad gvt->gm.vgpu_allocated_high_gm_size += MB_TO_BYTES(param->high_gm_sz); 289 1.1 riastrad gvt->fence.vgpu_allocated_fence_num += param->fence_sz; 290 1.1 riastrad return 0; 291 1.1 riastrad 292 1.1 riastrad no_enough_resource: 293 1.1 riastrad gvt_err("fail to allocate resource %s\n", item); 294 1.1 riastrad gvt_err("request %luMB avail %luMB max %luMB taken %luMB\n", 295 1.1 riastrad BYTES_TO_MB(request), BYTES_TO_MB(avail), 296 1.1 riastrad BYTES_TO_MB(max), BYTES_TO_MB(taken)); 297 1.1 riastrad return -ENOSPC; 298 1.1 riastrad } 299 1.1 riastrad 300 1.1 riastrad /** 301 1.1 riastrad * inte_gvt_free_vgpu_resource - free HW resource owned by a vGPU 302 1.1 riastrad * @vgpu: a vGPU 303 1.1 riastrad * 304 1.1 riastrad * This function is used to free the HW resource owned by a vGPU. 305 1.1 riastrad * 306 1.1 riastrad */ 307 1.1 riastrad void intel_vgpu_free_resource(struct intel_vgpu *vgpu) 308 1.1 riastrad { 309 1.1 riastrad free_vgpu_gm(vgpu); 310 1.1 riastrad free_vgpu_fence(vgpu); 311 1.1 riastrad free_resource(vgpu); 312 1.1 riastrad } 313 1.1 riastrad 314 1.1 riastrad /** 315 1.1 riastrad * intel_vgpu_reset_resource - reset resource state owned by a vGPU 316 1.1 riastrad * @vgpu: a vGPU 317 1.1 riastrad * 318 1.1 riastrad * This function is used to reset resource state owned by a vGPU. 319 1.1 riastrad * 320 1.1 riastrad */ 321 1.1 riastrad void intel_vgpu_reset_resource(struct intel_vgpu *vgpu) 322 1.1 riastrad { 323 1.1 riastrad struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; 324 1.1 riastrad 325 1.1 riastrad intel_runtime_pm_get(&dev_priv->runtime_pm); 326 1.1 riastrad _clear_vgpu_fence(vgpu); 327 1.1 riastrad intel_runtime_pm_put_unchecked(&dev_priv->runtime_pm); 328 1.1 riastrad } 329 1.1 riastrad 330 1.1 riastrad /** 331 1.1 riastrad * intel_alloc_vgpu_resource - allocate HW resource for a vGPU 332 1.1 riastrad * @vgpu: vGPU 333 1.1 riastrad * @param: vGPU creation params 334 1.1 riastrad * 335 1.1 riastrad * This function is used to allocate HW resource for a vGPU. User specifies 336 1.1 riastrad * the resource configuration through the creation params. 337 1.1 riastrad * 338 1.1 riastrad * Returns: 339 1.1 riastrad * zero on success, negative error code if failed. 340 1.1 riastrad * 341 1.1 riastrad */ 342 1.1 riastrad int intel_vgpu_alloc_resource(struct intel_vgpu *vgpu, 343 1.1 riastrad struct intel_vgpu_creation_params *param) 344 1.1 riastrad { 345 1.1 riastrad int ret; 346 1.1 riastrad 347 1.1 riastrad ret = alloc_resource(vgpu, param); 348 1.1 riastrad if (ret) 349 1.1 riastrad return ret; 350 1.1 riastrad 351 1.1 riastrad ret = alloc_vgpu_gm(vgpu); 352 1.1 riastrad if (ret) 353 1.1 riastrad goto out_free_resource; 354 1.1 riastrad 355 1.1 riastrad ret = alloc_vgpu_fence(vgpu); 356 1.1 riastrad if (ret) 357 1.1 riastrad goto out_free_vgpu_gm; 358 1.1 riastrad 359 1.1 riastrad return 0; 360 1.1 riastrad 361 1.1 riastrad out_free_vgpu_gm: 362 1.1 riastrad free_vgpu_gm(vgpu); 363 1.1 riastrad out_free_resource: 364 1.1 riastrad free_resource(vgpu); 365 1.1 riastrad return ret; 366 1.1 riastrad } 367