1 1.1 riastrad /* $NetBSD: mmio_context.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 * Eddie Dong <eddie.dong (at) intel.com> 27 1.1 riastrad * Kevin Tian <kevin.tian (at) intel.com> 28 1.1 riastrad * 29 1.1 riastrad * Contributors: 30 1.1 riastrad * Zhi Wang <zhi.a.wang (at) intel.com> 31 1.1 riastrad * Changbin Du <changbin.du (at) intel.com> 32 1.1 riastrad * Zhenyu Wang <zhenyuw (at) linux.intel.com> 33 1.1 riastrad * Tina Zhang <tina.zhang (at) intel.com> 34 1.1 riastrad * Bing Niu <bing.niu (at) intel.com> 35 1.1 riastrad * 36 1.1 riastrad */ 37 1.1 riastrad 38 1.1 riastrad #include <sys/cdefs.h> 39 1.1 riastrad __KERNEL_RCSID(0, "$NetBSD: mmio_context.c,v 1.2 2021/12/18 23:45:31 riastradh Exp $"); 40 1.1 riastrad 41 1.1 riastrad #include "i915_drv.h" 42 1.1 riastrad #include "gt/intel_context.h" 43 1.1 riastrad #include "gt/intel_ring.h" 44 1.1 riastrad #include "gvt.h" 45 1.1 riastrad #include "trace.h" 46 1.1 riastrad 47 1.1 riastrad #define GEN9_MOCS_SIZE 64 48 1.1 riastrad 49 1.1 riastrad /* Raw offset is appened to each line for convenience. */ 50 1.1 riastrad static struct engine_mmio gen8_engine_mmio_list[] __cacheline_aligned = { 51 1.1 riastrad {RCS0, GFX_MODE_GEN7, 0xffff, false}, /* 0x229c */ 52 1.1 riastrad {RCS0, GEN9_CTX_PREEMPT_REG, 0x0, false}, /* 0x2248 */ 53 1.1 riastrad {RCS0, HWSTAM, 0x0, false}, /* 0x2098 */ 54 1.1 riastrad {RCS0, INSTPM, 0xffff, true}, /* 0x20c0 */ 55 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 0), 0, false}, /* 0x24d0 */ 56 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 1), 0, false}, /* 0x24d4 */ 57 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 2), 0, false}, /* 0x24d8 */ 58 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 3), 0, false}, /* 0x24dc */ 59 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 4), 0, false}, /* 0x24e0 */ 60 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 5), 0, false}, /* 0x24e4 */ 61 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 6), 0, false}, /* 0x24e8 */ 62 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 7), 0, false}, /* 0x24ec */ 63 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 8), 0, false}, /* 0x24f0 */ 64 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 9), 0, false}, /* 0x24f4 */ 65 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 10), 0, false}, /* 0x24f8 */ 66 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 11), 0, false}, /* 0x24fc */ 67 1.1 riastrad {RCS0, CACHE_MODE_1, 0xffff, true}, /* 0x7004 */ 68 1.1 riastrad {RCS0, GEN7_GT_MODE, 0xffff, true}, /* 0x7008 */ 69 1.1 riastrad {RCS0, CACHE_MODE_0_GEN7, 0xffff, true}, /* 0x7000 */ 70 1.1 riastrad {RCS0, GEN7_COMMON_SLICE_CHICKEN1, 0xffff, true}, /* 0x7010 */ 71 1.1 riastrad {RCS0, HDC_CHICKEN0, 0xffff, true}, /* 0x7300 */ 72 1.1 riastrad {RCS0, VF_GUARDBAND, 0xffff, true}, /* 0x83a4 */ 73 1.1 riastrad 74 1.1 riastrad {BCS0, RING_GFX_MODE(BLT_RING_BASE), 0xffff, false}, /* 0x2229c */ 75 1.1 riastrad {BCS0, RING_MI_MODE(BLT_RING_BASE), 0xffff, false}, /* 0x2209c */ 76 1.1 riastrad {BCS0, RING_INSTPM(BLT_RING_BASE), 0xffff, false}, /* 0x220c0 */ 77 1.1 riastrad {BCS0, RING_HWSTAM(BLT_RING_BASE), 0x0, false}, /* 0x22098 */ 78 1.1 riastrad {BCS0, RING_EXCC(BLT_RING_BASE), 0xffff, false}, /* 0x22028 */ 79 1.1 riastrad {RCS0, INVALID_MMIO_REG, 0, false } /* Terminated */ 80 1.1 riastrad }; 81 1.1 riastrad 82 1.1 riastrad static struct engine_mmio gen9_engine_mmio_list[] __cacheline_aligned = { 83 1.1 riastrad {RCS0, GFX_MODE_GEN7, 0xffff, false}, /* 0x229c */ 84 1.1 riastrad {RCS0, GEN9_CTX_PREEMPT_REG, 0x0, false}, /* 0x2248 */ 85 1.1 riastrad {RCS0, HWSTAM, 0x0, false}, /* 0x2098 */ 86 1.1 riastrad {RCS0, INSTPM, 0xffff, true}, /* 0x20c0 */ 87 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 0), 0, false}, /* 0x24d0 */ 88 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 1), 0, false}, /* 0x24d4 */ 89 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 2), 0, false}, /* 0x24d8 */ 90 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 3), 0, false}, /* 0x24dc */ 91 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 4), 0, false}, /* 0x24e0 */ 92 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 5), 0, false}, /* 0x24e4 */ 93 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 6), 0, false}, /* 0x24e8 */ 94 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 7), 0, false}, /* 0x24ec */ 95 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 8), 0, false}, /* 0x24f0 */ 96 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 9), 0, false}, /* 0x24f4 */ 97 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 10), 0, false}, /* 0x24f8 */ 98 1.1 riastrad {RCS0, RING_FORCE_TO_NONPRIV(RENDER_RING_BASE, 11), 0, false}, /* 0x24fc */ 99 1.1 riastrad {RCS0, CACHE_MODE_1, 0xffff, true}, /* 0x7004 */ 100 1.1 riastrad {RCS0, GEN7_GT_MODE, 0xffff, true}, /* 0x7008 */ 101 1.1 riastrad {RCS0, CACHE_MODE_0_GEN7, 0xffff, true}, /* 0x7000 */ 102 1.1 riastrad {RCS0, GEN7_COMMON_SLICE_CHICKEN1, 0xffff, true}, /* 0x7010 */ 103 1.1 riastrad {RCS0, HDC_CHICKEN0, 0xffff, true}, /* 0x7300 */ 104 1.1 riastrad {RCS0, VF_GUARDBAND, 0xffff, true}, /* 0x83a4 */ 105 1.1 riastrad 106 1.1 riastrad {RCS0, GEN8_PRIVATE_PAT_LO, 0, false}, /* 0x40e0 */ 107 1.1 riastrad {RCS0, GEN8_PRIVATE_PAT_HI, 0, false}, /* 0x40e4 */ 108 1.1 riastrad {RCS0, GEN8_CS_CHICKEN1, 0xffff, true}, /* 0x2580 */ 109 1.1 riastrad {RCS0, COMMON_SLICE_CHICKEN2, 0xffff, true}, /* 0x7014 */ 110 1.1 riastrad {RCS0, GEN9_CS_DEBUG_MODE1, 0xffff, false}, /* 0x20ec */ 111 1.1 riastrad {RCS0, GEN8_L3SQCREG4, 0, false}, /* 0xb118 */ 112 1.1 riastrad {RCS0, GEN7_HALF_SLICE_CHICKEN1, 0xffff, true}, /* 0xe100 */ 113 1.1 riastrad {RCS0, HALF_SLICE_CHICKEN2, 0xffff, true}, /* 0xe180 */ 114 1.1 riastrad {RCS0, HALF_SLICE_CHICKEN3, 0xffff, true}, /* 0xe184 */ 115 1.1 riastrad {RCS0, GEN9_HALF_SLICE_CHICKEN5, 0xffff, true}, /* 0xe188 */ 116 1.1 riastrad {RCS0, GEN9_HALF_SLICE_CHICKEN7, 0xffff, true}, /* 0xe194 */ 117 1.1 riastrad {RCS0, GEN8_ROW_CHICKEN, 0xffff, true}, /* 0xe4f0 */ 118 1.1 riastrad {RCS0, TRVATTL3PTRDW(0), 0, true}, /* 0x4de0 */ 119 1.1 riastrad {RCS0, TRVATTL3PTRDW(1), 0, true}, /* 0x4de4 */ 120 1.1 riastrad {RCS0, TRNULLDETCT, 0, true}, /* 0x4de8 */ 121 1.1 riastrad {RCS0, TRINVTILEDETCT, 0, true}, /* 0x4dec */ 122 1.1 riastrad {RCS0, TRVADR, 0, true}, /* 0x4df0 */ 123 1.1 riastrad {RCS0, TRTTE, 0, true}, /* 0x4df4 */ 124 1.1 riastrad {RCS0, _MMIO(0x4dfc), 0, true}, 125 1.1 riastrad 126 1.1 riastrad {BCS0, RING_GFX_MODE(BLT_RING_BASE), 0xffff, false}, /* 0x2229c */ 127 1.1 riastrad {BCS0, RING_MI_MODE(BLT_RING_BASE), 0xffff, false}, /* 0x2209c */ 128 1.1 riastrad {BCS0, RING_INSTPM(BLT_RING_BASE), 0xffff, false}, /* 0x220c0 */ 129 1.1 riastrad {BCS0, RING_HWSTAM(BLT_RING_BASE), 0x0, false}, /* 0x22098 */ 130 1.1 riastrad {BCS0, RING_EXCC(BLT_RING_BASE), 0xffff, false}, /* 0x22028 */ 131 1.1 riastrad 132 1.1 riastrad {VCS1, RING_EXCC(GEN8_BSD2_RING_BASE), 0xffff, false}, /* 0x1c028 */ 133 1.1 riastrad 134 1.1 riastrad {VECS0, RING_EXCC(VEBOX_RING_BASE), 0xffff, false}, /* 0x1a028 */ 135 1.1 riastrad 136 1.1 riastrad {RCS0, GEN8_HDC_CHICKEN1, 0xffff, true}, /* 0x7304 */ 137 1.1 riastrad {RCS0, GEN9_CTX_PREEMPT_REG, 0x0, false}, /* 0x2248 */ 138 1.1 riastrad {RCS0, GEN7_UCGCTL4, 0x0, false}, /* 0x940c */ 139 1.1 riastrad {RCS0, GAMT_CHKN_BIT_REG, 0x0, false}, /* 0x4ab8 */ 140 1.1 riastrad 141 1.1 riastrad {RCS0, GEN9_GAMT_ECO_REG_RW_IA, 0x0, false}, /* 0x4ab0 */ 142 1.1 riastrad {RCS0, GEN9_CSFE_CHICKEN1_RCS, 0xffff, false}, /* 0x20d4 */ 143 1.1 riastrad {RCS0, _MMIO(0x20D8), 0xffff, true}, /* 0x20d8 */ 144 1.1 riastrad 145 1.1 riastrad {RCS0, GEN8_GARBCNTL, 0x0, false}, /* 0xb004 */ 146 1.1 riastrad {RCS0, GEN7_FF_THREAD_MODE, 0x0, false}, /* 0x20a0 */ 147 1.1 riastrad {RCS0, FF_SLICE_CS_CHICKEN2, 0xffff, false}, /* 0x20e4 */ 148 1.1 riastrad {RCS0, INVALID_MMIO_REG, 0, false } /* Terminated */ 149 1.1 riastrad }; 150 1.1 riastrad 151 1.1 riastrad static struct { 152 1.1 riastrad bool initialized; 153 1.1 riastrad u32 control_table[I915_NUM_ENGINES][GEN9_MOCS_SIZE]; 154 1.1 riastrad u32 l3cc_table[GEN9_MOCS_SIZE / 2]; 155 1.1 riastrad } gen9_render_mocs; 156 1.1 riastrad 157 1.1 riastrad static u32 gen9_mocs_mmio_offset_list[] = { 158 1.1 riastrad [RCS0] = 0xc800, 159 1.1 riastrad [VCS0] = 0xc900, 160 1.1 riastrad [VCS1] = 0xca00, 161 1.1 riastrad [BCS0] = 0xcc00, 162 1.1 riastrad [VECS0] = 0xcb00, 163 1.1 riastrad }; 164 1.1 riastrad 165 1.1 riastrad static void load_render_mocs(struct drm_i915_private *dev_priv) 166 1.1 riastrad { 167 1.1 riastrad struct intel_gvt *gvt = dev_priv->gvt; 168 1.1 riastrad i915_reg_t offset; 169 1.1 riastrad u32 cnt = gvt->engine_mmio_list.mocs_mmio_offset_list_cnt; 170 1.1 riastrad u32 *regs = gvt->engine_mmio_list.mocs_mmio_offset_list; 171 1.1 riastrad int ring_id, i; 172 1.1 riastrad 173 1.1 riastrad /* Platform doesn't have mocs mmios. */ 174 1.1 riastrad if (!regs) 175 1.1 riastrad return; 176 1.1 riastrad 177 1.1 riastrad for (ring_id = 0; ring_id < cnt; ring_id++) { 178 1.1 riastrad if (!HAS_ENGINE(dev_priv, ring_id)) 179 1.1 riastrad continue; 180 1.1 riastrad offset.reg = regs[ring_id]; 181 1.1 riastrad for (i = 0; i < GEN9_MOCS_SIZE; i++) { 182 1.1 riastrad gen9_render_mocs.control_table[ring_id][i] = 183 1.1 riastrad I915_READ_FW(offset); 184 1.1 riastrad offset.reg += 4; 185 1.1 riastrad } 186 1.1 riastrad } 187 1.1 riastrad 188 1.1 riastrad offset.reg = 0xb020; 189 1.1 riastrad for (i = 0; i < GEN9_MOCS_SIZE / 2; i++) { 190 1.1 riastrad gen9_render_mocs.l3cc_table[i] = 191 1.1 riastrad I915_READ_FW(offset); 192 1.1 riastrad offset.reg += 4; 193 1.1 riastrad } 194 1.1 riastrad gen9_render_mocs.initialized = true; 195 1.1 riastrad } 196 1.1 riastrad 197 1.1 riastrad static int 198 1.1 riastrad restore_context_mmio_for_inhibit(struct intel_vgpu *vgpu, 199 1.1 riastrad struct i915_request *req) 200 1.1 riastrad { 201 1.1 riastrad u32 *cs; 202 1.1 riastrad int ret; 203 1.1 riastrad struct engine_mmio *mmio; 204 1.1 riastrad struct intel_gvt *gvt = vgpu->gvt; 205 1.1 riastrad int ring_id = req->engine->id; 206 1.1 riastrad int count = gvt->engine_mmio_list.ctx_mmio_count[ring_id]; 207 1.1 riastrad 208 1.1 riastrad if (count == 0) 209 1.1 riastrad return 0; 210 1.1 riastrad 211 1.1 riastrad ret = req->engine->emit_flush(req, EMIT_BARRIER); 212 1.1 riastrad if (ret) 213 1.1 riastrad return ret; 214 1.1 riastrad 215 1.1 riastrad cs = intel_ring_begin(req, count * 2 + 2); 216 1.1 riastrad if (IS_ERR(cs)) 217 1.1 riastrad return PTR_ERR(cs); 218 1.1 riastrad 219 1.1 riastrad *cs++ = MI_LOAD_REGISTER_IMM(count); 220 1.1 riastrad for (mmio = gvt->engine_mmio_list.mmio; 221 1.1 riastrad i915_mmio_reg_valid(mmio->reg); mmio++) { 222 1.1 riastrad if (mmio->ring_id != ring_id || 223 1.1 riastrad !mmio->in_context) 224 1.1 riastrad continue; 225 1.1 riastrad 226 1.1 riastrad *cs++ = i915_mmio_reg_offset(mmio->reg); 227 1.1 riastrad *cs++ = vgpu_vreg_t(vgpu, mmio->reg) | 228 1.1 riastrad (mmio->mask << 16); 229 1.1 riastrad gvt_dbg_core("add lri reg pair 0x%x:0x%x in inhibit ctx, vgpu:%d, rind_id:%d\n", 230 1.1 riastrad *(cs-2), *(cs-1), vgpu->id, ring_id); 231 1.1 riastrad } 232 1.1 riastrad 233 1.1 riastrad *cs++ = MI_NOOP; 234 1.1 riastrad intel_ring_advance(req, cs); 235 1.1 riastrad 236 1.1 riastrad ret = req->engine->emit_flush(req, EMIT_BARRIER); 237 1.1 riastrad if (ret) 238 1.1 riastrad return ret; 239 1.1 riastrad 240 1.1 riastrad return 0; 241 1.1 riastrad } 242 1.1 riastrad 243 1.1 riastrad static int 244 1.1 riastrad restore_render_mocs_control_for_inhibit(struct intel_vgpu *vgpu, 245 1.1 riastrad struct i915_request *req) 246 1.1 riastrad { 247 1.1 riastrad unsigned int index; 248 1.1 riastrad u32 *cs; 249 1.1 riastrad 250 1.1 riastrad cs = intel_ring_begin(req, 2 * GEN9_MOCS_SIZE + 2); 251 1.1 riastrad if (IS_ERR(cs)) 252 1.1 riastrad return PTR_ERR(cs); 253 1.1 riastrad 254 1.1 riastrad *cs++ = MI_LOAD_REGISTER_IMM(GEN9_MOCS_SIZE); 255 1.1 riastrad 256 1.1 riastrad for (index = 0; index < GEN9_MOCS_SIZE; index++) { 257 1.1 riastrad *cs++ = i915_mmio_reg_offset(GEN9_GFX_MOCS(index)); 258 1.1 riastrad *cs++ = vgpu_vreg_t(vgpu, GEN9_GFX_MOCS(index)); 259 1.1 riastrad gvt_dbg_core("add lri reg pair 0x%x:0x%x in inhibit ctx, vgpu:%d, rind_id:%d\n", 260 1.1 riastrad *(cs-2), *(cs-1), vgpu->id, req->engine->id); 261 1.1 riastrad 262 1.1 riastrad } 263 1.1 riastrad 264 1.1 riastrad *cs++ = MI_NOOP; 265 1.1 riastrad intel_ring_advance(req, cs); 266 1.1 riastrad 267 1.1 riastrad return 0; 268 1.1 riastrad } 269 1.1 riastrad 270 1.1 riastrad static int 271 1.1 riastrad restore_render_mocs_l3cc_for_inhibit(struct intel_vgpu *vgpu, 272 1.1 riastrad struct i915_request *req) 273 1.1 riastrad { 274 1.1 riastrad unsigned int index; 275 1.1 riastrad u32 *cs; 276 1.1 riastrad 277 1.1 riastrad cs = intel_ring_begin(req, 2 * GEN9_MOCS_SIZE / 2 + 2); 278 1.1 riastrad if (IS_ERR(cs)) 279 1.1 riastrad return PTR_ERR(cs); 280 1.1 riastrad 281 1.1 riastrad *cs++ = MI_LOAD_REGISTER_IMM(GEN9_MOCS_SIZE / 2); 282 1.1 riastrad 283 1.1 riastrad for (index = 0; index < GEN9_MOCS_SIZE / 2; index++) { 284 1.1 riastrad *cs++ = i915_mmio_reg_offset(GEN9_LNCFCMOCS(index)); 285 1.1 riastrad *cs++ = vgpu_vreg_t(vgpu, GEN9_LNCFCMOCS(index)); 286 1.1 riastrad gvt_dbg_core("add lri reg pair 0x%x:0x%x in inhibit ctx, vgpu:%d, rind_id:%d\n", 287 1.1 riastrad *(cs-2), *(cs-1), vgpu->id, req->engine->id); 288 1.1 riastrad 289 1.1 riastrad } 290 1.1 riastrad 291 1.1 riastrad *cs++ = MI_NOOP; 292 1.1 riastrad intel_ring_advance(req, cs); 293 1.1 riastrad 294 1.1 riastrad return 0; 295 1.1 riastrad } 296 1.1 riastrad 297 1.1 riastrad /* 298 1.1 riastrad * Use lri command to initialize the mmio which is in context state image for 299 1.1 riastrad * inhibit context, it contains tracked engine mmio, render_mocs and 300 1.1 riastrad * render_mocs_l3cc. 301 1.1 riastrad */ 302 1.1 riastrad int intel_vgpu_restore_inhibit_context(struct intel_vgpu *vgpu, 303 1.1 riastrad struct i915_request *req) 304 1.1 riastrad { 305 1.1 riastrad int ret; 306 1.1 riastrad u32 *cs; 307 1.1 riastrad 308 1.1 riastrad cs = intel_ring_begin(req, 2); 309 1.1 riastrad if (IS_ERR(cs)) 310 1.1 riastrad return PTR_ERR(cs); 311 1.1 riastrad 312 1.1 riastrad *cs++ = MI_ARB_ON_OFF | MI_ARB_DISABLE; 313 1.1 riastrad *cs++ = MI_NOOP; 314 1.1 riastrad intel_ring_advance(req, cs); 315 1.1 riastrad 316 1.1 riastrad ret = restore_context_mmio_for_inhibit(vgpu, req); 317 1.1 riastrad if (ret) 318 1.1 riastrad goto out; 319 1.1 riastrad 320 1.1 riastrad /* no MOCS register in context except render engine */ 321 1.1 riastrad if (req->engine->id != RCS0) 322 1.1 riastrad goto out; 323 1.1 riastrad 324 1.1 riastrad ret = restore_render_mocs_control_for_inhibit(vgpu, req); 325 1.1 riastrad if (ret) 326 1.1 riastrad goto out; 327 1.1 riastrad 328 1.1 riastrad ret = restore_render_mocs_l3cc_for_inhibit(vgpu, req); 329 1.1 riastrad if (ret) 330 1.1 riastrad goto out; 331 1.1 riastrad 332 1.1 riastrad out: 333 1.1 riastrad cs = intel_ring_begin(req, 2); 334 1.1 riastrad if (IS_ERR(cs)) 335 1.1 riastrad return PTR_ERR(cs); 336 1.1 riastrad 337 1.1 riastrad *cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE; 338 1.1 riastrad *cs++ = MI_NOOP; 339 1.1 riastrad intel_ring_advance(req, cs); 340 1.1 riastrad 341 1.1 riastrad return ret; 342 1.1 riastrad } 343 1.1 riastrad 344 1.1 riastrad static u32 gen8_tlb_mmio_offset_list[] = { 345 1.1 riastrad [RCS0] = 0x4260, 346 1.1 riastrad [VCS0] = 0x4264, 347 1.1 riastrad [VCS1] = 0x4268, 348 1.1 riastrad [BCS0] = 0x426c, 349 1.1 riastrad [VECS0] = 0x4270, 350 1.1 riastrad }; 351 1.1 riastrad 352 1.1 riastrad static void handle_tlb_pending_event(struct intel_vgpu *vgpu, int ring_id) 353 1.1 riastrad { 354 1.1 riastrad struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; 355 1.1 riastrad struct intel_uncore *uncore = &dev_priv->uncore; 356 1.1 riastrad struct intel_vgpu_submission *s = &vgpu->submission; 357 1.1 riastrad u32 *regs = vgpu->gvt->engine_mmio_list.tlb_mmio_offset_list; 358 1.1 riastrad u32 cnt = vgpu->gvt->engine_mmio_list.tlb_mmio_offset_list_cnt; 359 1.1 riastrad enum forcewake_domains fw; 360 1.1 riastrad i915_reg_t reg; 361 1.1 riastrad 362 1.1 riastrad if (!regs) 363 1.1 riastrad return; 364 1.1 riastrad 365 1.1 riastrad if (WARN_ON(ring_id >= cnt)) 366 1.1 riastrad return; 367 1.1 riastrad 368 1.1 riastrad if (!test_and_clear_bit(ring_id, (void *)s->tlb_handle_pending)) 369 1.1 riastrad return; 370 1.1 riastrad 371 1.1 riastrad reg = _MMIO(regs[ring_id]); 372 1.1 riastrad 373 1.1 riastrad /* WaForceWakeRenderDuringMmioTLBInvalidate:skl 374 1.1 riastrad * we need to put a forcewake when invalidating RCS TLB caches, 375 1.1 riastrad * otherwise device can go to RC6 state and interrupt invalidation 376 1.1 riastrad * process 377 1.1 riastrad */ 378 1.1 riastrad fw = intel_uncore_forcewake_for_reg(uncore, reg, 379 1.1 riastrad FW_REG_READ | FW_REG_WRITE); 380 1.1 riastrad if (ring_id == RCS0 && INTEL_GEN(dev_priv) >= 9) 381 1.1 riastrad fw |= FORCEWAKE_RENDER; 382 1.1 riastrad 383 1.1 riastrad intel_uncore_forcewake_get(uncore, fw); 384 1.1 riastrad 385 1.1 riastrad intel_uncore_write_fw(uncore, reg, 0x1); 386 1.1 riastrad 387 1.1 riastrad if (wait_for_atomic((intel_uncore_read_fw(uncore, reg) == 0), 50)) 388 1.1 riastrad gvt_vgpu_err("timeout in invalidate ring (%d) tlb\n", ring_id); 389 1.1 riastrad else 390 1.1 riastrad vgpu_vreg_t(vgpu, reg) = 0; 391 1.1 riastrad 392 1.1 riastrad intel_uncore_forcewake_put(uncore, fw); 393 1.1 riastrad 394 1.1 riastrad gvt_dbg_core("invalidate TLB for ring %d\n", ring_id); 395 1.1 riastrad } 396 1.1 riastrad 397 1.1 riastrad static void switch_mocs(struct intel_vgpu *pre, struct intel_vgpu *next, 398 1.1 riastrad int ring_id) 399 1.1 riastrad { 400 1.1 riastrad struct drm_i915_private *dev_priv; 401 1.1 riastrad i915_reg_t offset, l3_offset; 402 1.1 riastrad u32 old_v, new_v; 403 1.1 riastrad 404 1.1 riastrad u32 regs[] = { 405 1.1 riastrad [RCS0] = 0xc800, 406 1.1 riastrad [VCS0] = 0xc900, 407 1.1 riastrad [VCS1] = 0xca00, 408 1.1 riastrad [BCS0] = 0xcc00, 409 1.1 riastrad [VECS0] = 0xcb00, 410 1.1 riastrad }; 411 1.1 riastrad int i; 412 1.1 riastrad 413 1.1 riastrad dev_priv = pre ? pre->gvt->dev_priv : next->gvt->dev_priv; 414 1.1 riastrad if (WARN_ON(ring_id >= ARRAY_SIZE(regs))) 415 1.1 riastrad return; 416 1.1 riastrad 417 1.1 riastrad if (ring_id == RCS0 && IS_GEN(dev_priv, 9)) 418 1.1 riastrad return; 419 1.1 riastrad 420 1.1 riastrad if (!pre && !gen9_render_mocs.initialized) 421 1.1 riastrad load_render_mocs(dev_priv); 422 1.1 riastrad 423 1.1 riastrad offset.reg = regs[ring_id]; 424 1.1 riastrad for (i = 0; i < GEN9_MOCS_SIZE; i++) { 425 1.1 riastrad if (pre) 426 1.1 riastrad old_v = vgpu_vreg_t(pre, offset); 427 1.1 riastrad else 428 1.1 riastrad old_v = gen9_render_mocs.control_table[ring_id][i]; 429 1.1 riastrad if (next) 430 1.1 riastrad new_v = vgpu_vreg_t(next, offset); 431 1.1 riastrad else 432 1.1 riastrad new_v = gen9_render_mocs.control_table[ring_id][i]; 433 1.1 riastrad 434 1.1 riastrad if (old_v != new_v) 435 1.1 riastrad I915_WRITE_FW(offset, new_v); 436 1.1 riastrad 437 1.1 riastrad offset.reg += 4; 438 1.1 riastrad } 439 1.1 riastrad 440 1.1 riastrad if (ring_id == RCS0) { 441 1.1 riastrad l3_offset.reg = 0xb020; 442 1.1 riastrad for (i = 0; i < GEN9_MOCS_SIZE / 2; i++) { 443 1.1 riastrad if (pre) 444 1.1 riastrad old_v = vgpu_vreg_t(pre, l3_offset); 445 1.1 riastrad else 446 1.1 riastrad old_v = gen9_render_mocs.l3cc_table[i]; 447 1.1 riastrad if (next) 448 1.1 riastrad new_v = vgpu_vreg_t(next, l3_offset); 449 1.1 riastrad else 450 1.1 riastrad new_v = gen9_render_mocs.l3cc_table[i]; 451 1.1 riastrad 452 1.1 riastrad if (old_v != new_v) 453 1.1 riastrad I915_WRITE_FW(l3_offset, new_v); 454 1.1 riastrad 455 1.1 riastrad l3_offset.reg += 4; 456 1.1 riastrad } 457 1.1 riastrad } 458 1.1 riastrad } 459 1.1 riastrad 460 1.1 riastrad #define CTX_CONTEXT_CONTROL_VAL 0x03 461 1.1 riastrad 462 1.1 riastrad bool is_inhibit_context(struct intel_context *ce) 463 1.1 riastrad { 464 1.1 riastrad const u32 *reg_state = ce->lrc_reg_state; 465 1.1 riastrad u32 inhibit_mask = 466 1.1 riastrad _MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT); 467 1.1 riastrad 468 1.1 riastrad return inhibit_mask == 469 1.1 riastrad (reg_state[CTX_CONTEXT_CONTROL_VAL] & inhibit_mask); 470 1.1 riastrad } 471 1.1 riastrad 472 1.1 riastrad /* Switch ring mmio values (context). */ 473 1.1 riastrad static void switch_mmio(struct intel_vgpu *pre, 474 1.1 riastrad struct intel_vgpu *next, 475 1.1 riastrad int ring_id) 476 1.1 riastrad { 477 1.1 riastrad struct drm_i915_private *dev_priv; 478 1.1 riastrad struct intel_vgpu_submission *s; 479 1.1 riastrad struct engine_mmio *mmio; 480 1.1 riastrad u32 old_v, new_v; 481 1.1 riastrad 482 1.1 riastrad dev_priv = pre ? pre->gvt->dev_priv : next->gvt->dev_priv; 483 1.1 riastrad if (INTEL_GEN(dev_priv) >= 9) 484 1.1 riastrad switch_mocs(pre, next, ring_id); 485 1.1 riastrad 486 1.1 riastrad for (mmio = dev_priv->gvt->engine_mmio_list.mmio; 487 1.1 riastrad i915_mmio_reg_valid(mmio->reg); mmio++) { 488 1.1 riastrad if (mmio->ring_id != ring_id) 489 1.1 riastrad continue; 490 1.1 riastrad /* 491 1.1 riastrad * No need to do save or restore of the mmio which is in context 492 1.1 riastrad * state image on gen9, it's initialized by lri command and 493 1.1 riastrad * save or restore with context together. 494 1.1 riastrad */ 495 1.1 riastrad if (IS_GEN(dev_priv, 9) && mmio->in_context) 496 1.1 riastrad continue; 497 1.1 riastrad 498 1.1 riastrad // save 499 1.1 riastrad if (pre) { 500 1.1 riastrad vgpu_vreg_t(pre, mmio->reg) = I915_READ_FW(mmio->reg); 501 1.1 riastrad if (mmio->mask) 502 1.1 riastrad vgpu_vreg_t(pre, mmio->reg) &= 503 1.1 riastrad ~(mmio->mask << 16); 504 1.1 riastrad old_v = vgpu_vreg_t(pre, mmio->reg); 505 1.1 riastrad } else 506 1.1 riastrad old_v = mmio->value = I915_READ_FW(mmio->reg); 507 1.1 riastrad 508 1.1 riastrad // restore 509 1.1 riastrad if (next) { 510 1.1 riastrad s = &next->submission; 511 1.1 riastrad /* 512 1.1 riastrad * No need to restore the mmio which is in context state 513 1.1 riastrad * image if it's not inhibit context, it will restore 514 1.1 riastrad * itself. 515 1.1 riastrad */ 516 1.1 riastrad if (mmio->in_context && 517 1.1 riastrad !is_inhibit_context(s->shadow[ring_id])) 518 1.1 riastrad continue; 519 1.1 riastrad 520 1.1 riastrad if (mmio->mask) 521 1.1 riastrad new_v = vgpu_vreg_t(next, mmio->reg) | 522 1.1 riastrad (mmio->mask << 16); 523 1.1 riastrad else 524 1.1 riastrad new_v = vgpu_vreg_t(next, mmio->reg); 525 1.1 riastrad } else { 526 1.1 riastrad if (mmio->in_context) 527 1.1 riastrad continue; 528 1.1 riastrad if (mmio->mask) 529 1.1 riastrad new_v = mmio->value | (mmio->mask << 16); 530 1.1 riastrad else 531 1.1 riastrad new_v = mmio->value; 532 1.1 riastrad } 533 1.1 riastrad 534 1.1 riastrad I915_WRITE_FW(mmio->reg, new_v); 535 1.1 riastrad 536 1.1 riastrad trace_render_mmio(pre ? pre->id : 0, 537 1.1 riastrad next ? next->id : 0, 538 1.1 riastrad "switch", 539 1.1 riastrad i915_mmio_reg_offset(mmio->reg), 540 1.1 riastrad old_v, new_v); 541 1.1 riastrad } 542 1.1 riastrad 543 1.1 riastrad if (next) 544 1.1 riastrad handle_tlb_pending_event(next, ring_id); 545 1.1 riastrad } 546 1.1 riastrad 547 1.1 riastrad /** 548 1.1 riastrad * intel_gvt_switch_render_mmio - switch mmio context of specific engine 549 1.1 riastrad * @pre: the last vGPU that own the engine 550 1.1 riastrad * @next: the vGPU to switch to 551 1.1 riastrad * @ring_id: specify the engine 552 1.1 riastrad * 553 1.1 riastrad * If pre is null indicates that host own the engine. If next is null 554 1.1 riastrad * indicates that we are switching to host workload. 555 1.1 riastrad */ 556 1.1 riastrad void intel_gvt_switch_mmio(struct intel_vgpu *pre, 557 1.1 riastrad struct intel_vgpu *next, int ring_id) 558 1.1 riastrad { 559 1.1 riastrad struct drm_i915_private *dev_priv; 560 1.1 riastrad 561 1.1 riastrad if (WARN_ON(!pre && !next)) 562 1.1 riastrad return; 563 1.1 riastrad 564 1.1 riastrad gvt_dbg_render("switch ring %d from %s to %s\n", ring_id, 565 1.1 riastrad pre ? "vGPU" : "host", next ? "vGPU" : "HOST"); 566 1.1 riastrad 567 1.1 riastrad dev_priv = pre ? pre->gvt->dev_priv : next->gvt->dev_priv; 568 1.1 riastrad 569 1.1 riastrad /** 570 1.1 riastrad * We are using raw mmio access wrapper to improve the 571 1.1 riastrad * performace for batch mmio read/write, so we need 572 1.1 riastrad * handle forcewake mannually. 573 1.1 riastrad */ 574 1.1 riastrad intel_uncore_forcewake_get(&dev_priv->uncore, FORCEWAKE_ALL); 575 1.1 riastrad switch_mmio(pre, next, ring_id); 576 1.1 riastrad intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL); 577 1.1 riastrad } 578 1.1 riastrad 579 1.1 riastrad /** 580 1.1 riastrad * intel_gvt_init_engine_mmio_context - Initiate the engine mmio list 581 1.1 riastrad * @gvt: GVT device 582 1.1 riastrad * 583 1.1 riastrad */ 584 1.1 riastrad void intel_gvt_init_engine_mmio_context(struct intel_gvt *gvt) 585 1.1 riastrad { 586 1.1 riastrad struct engine_mmio *mmio; 587 1.1 riastrad 588 1.1 riastrad if (INTEL_GEN(gvt->dev_priv) >= 9) { 589 1.1 riastrad gvt->engine_mmio_list.mmio = gen9_engine_mmio_list; 590 1.1 riastrad gvt->engine_mmio_list.tlb_mmio_offset_list = gen8_tlb_mmio_offset_list; 591 1.1 riastrad gvt->engine_mmio_list.tlb_mmio_offset_list_cnt = ARRAY_SIZE(gen8_tlb_mmio_offset_list); 592 1.1 riastrad gvt->engine_mmio_list.mocs_mmio_offset_list = gen9_mocs_mmio_offset_list; 593 1.1 riastrad gvt->engine_mmio_list.mocs_mmio_offset_list_cnt = ARRAY_SIZE(gen9_mocs_mmio_offset_list); 594 1.1 riastrad } else { 595 1.1 riastrad gvt->engine_mmio_list.mmio = gen8_engine_mmio_list; 596 1.1 riastrad gvt->engine_mmio_list.tlb_mmio_offset_list = gen8_tlb_mmio_offset_list; 597 1.1 riastrad gvt->engine_mmio_list.tlb_mmio_offset_list_cnt = ARRAY_SIZE(gen8_tlb_mmio_offset_list); 598 1.1 riastrad } 599 1.1 riastrad 600 1.1 riastrad for (mmio = gvt->engine_mmio_list.mmio; 601 1.1 riastrad i915_mmio_reg_valid(mmio->reg); mmio++) { 602 1.1 riastrad if (mmio->in_context) { 603 1.1 riastrad gvt->engine_mmio_list.ctx_mmio_count[mmio->ring_id]++; 604 1.1 riastrad intel_gvt_mmio_set_in_ctx(gvt, mmio->reg.reg); 605 1.1 riastrad } 606 1.1 riastrad } 607 1.1 riastrad } 608