1 /* 2 * Copyright (c) 2015 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: * 10 * The above copyright notice and this permission notice (including the next 11 * paragraph) shall be included in all copies or substantial portions of the 12 * Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 */ 22 23 #include "i915_drv.h" 24 25 #include "intel_engine.h" 26 #include "intel_mocs.h" 27 #include "intel_lrc.h" 28 29 /* structures required */ 30 struct drm_i915_mocs_entry { 31 u32 control_value; 32 u16 l3cc_value; 33 u16 used; 34 }; 35 36 struct drm_i915_mocs_table { 37 unsigned int size; 38 unsigned int n_entries; 39 const struct drm_i915_mocs_entry *table; 40 }; 41 42 /* Defines for the tables (XXX_MOCS_0 - XXX_MOCS_63) */ 43 #define _LE_CACHEABILITY(value) ((value) << 0) 44 #define _LE_TGT_CACHE(value) ((value) << 2) 45 #define LE_LRUM(value) ((value) << 4) 46 #define LE_AOM(value) ((value) << 6) 47 #define LE_RSC(value) ((value) << 7) 48 #define LE_SCC(value) ((value) << 8) 49 #define LE_PFM(value) ((value) << 11) 50 #define LE_SCF(value) ((value) << 14) 51 #define LE_COS(value) ((value) << 15) 52 #define LE_SSE(value) ((value) << 17) 53 54 /* Defines for the tables (LNCFMOCS0 - LNCFMOCS31) - two entries per word */ 55 #define L3_ESC(value) ((value) << 0) 56 #define L3_SCC(value) ((value) << 1) 57 #define _L3_CACHEABILITY(value) ((value) << 4) 58 59 /* Helper defines */ 60 #define GEN9_NUM_MOCS_ENTRIES 62 /* 62 out of 64 - 63 & 64 are reserved. */ 61 #define GEN11_NUM_MOCS_ENTRIES 64 /* 63-64 are reserved, but configured. */ 62 63 /* (e)LLC caching options */ 64 #define LE_0_PAGETABLE _LE_CACHEABILITY(0) 65 #define LE_1_UC _LE_CACHEABILITY(1) 66 #define LE_2_WT _LE_CACHEABILITY(2) 67 #define LE_3_WB _LE_CACHEABILITY(3) 68 69 /* Target cache */ 70 #define LE_TC_0_PAGETABLE _LE_TGT_CACHE(0) 71 #define LE_TC_1_LLC _LE_TGT_CACHE(1) 72 #define LE_TC_2_LLC_ELLC _LE_TGT_CACHE(2) 73 #define LE_TC_3_LLC_ELLC_ALT _LE_TGT_CACHE(3) 74 75 /* L3 caching options */ 76 #define L3_0_DIRECT _L3_CACHEABILITY(0) 77 #define L3_1_UC _L3_CACHEABILITY(1) 78 #define L3_2_RESERVED _L3_CACHEABILITY(2) 79 #define L3_3_WB _L3_CACHEABILITY(3) 80 81 #define MOCS_ENTRY(__idx, __control_value, __l3cc_value) \ 82 [__idx] = { \ 83 .control_value = __control_value, \ 84 .l3cc_value = __l3cc_value, \ 85 .used = 1, \ 86 } 87 88 /* 89 * MOCS tables 90 * 91 * These are the MOCS tables that are programmed across all the rings. 92 * The control value is programmed to all the rings that support the 93 * MOCS registers. While the l3cc_values are only programmed to the 94 * LNCFCMOCS0 - LNCFCMOCS32 registers. 95 * 96 * These tables are intended to be kept reasonably consistent across 97 * HW platforms, and for ICL+, be identical across OSes. To achieve 98 * that, for Icelake and above, list of entries is published as part 99 * of bspec. 100 * 101 * Entries not part of the following tables are undefined as far as 102 * userspace is concerned and shouldn't be relied upon. For the time 103 * being they will be initialized to PTE. 104 * 105 * The last two entries are reserved by the hardware. For ICL+ they 106 * should be initialized according to bspec and never used, for older 107 * platforms they should never be written to. 108 * 109 * NOTE: These tables are part of bspec and defined as part of hardware 110 * interface for ICL+. For older platforms, they are part of kernel 111 * ABI. It is expected that, for specific hardware platform, existing 112 * entries will remain constant and the table will only be updated by 113 * adding new entries, filling unused positions. 114 */ 115 #define GEN9_MOCS_ENTRIES \ 116 MOCS_ENTRY(I915_MOCS_UNCACHED, \ 117 LE_1_UC | LE_TC_2_LLC_ELLC, \ 118 L3_1_UC), \ 119 MOCS_ENTRY(I915_MOCS_PTE, \ 120 LE_0_PAGETABLE | LE_TC_2_LLC_ELLC | LE_LRUM(3), \ 121 L3_3_WB) 122 123 static const struct drm_i915_mocs_entry skylake_mocs_table[] = { 124 GEN9_MOCS_ENTRIES, 125 MOCS_ENTRY(I915_MOCS_CACHED, 126 LE_3_WB | LE_TC_2_LLC_ELLC | LE_LRUM(3), 127 L3_3_WB) 128 }; 129 130 /* NOTE: the LE_TGT_CACHE is not used on Broxton */ 131 static const struct drm_i915_mocs_entry broxton_mocs_table[] = { 132 GEN9_MOCS_ENTRIES, 133 MOCS_ENTRY(I915_MOCS_CACHED, 134 LE_1_UC | LE_TC_2_LLC_ELLC | LE_LRUM(3), 135 L3_3_WB) 136 }; 137 138 #define GEN11_MOCS_ENTRIES \ 139 /* Base - Uncached (Deprecated) */ \ 140 MOCS_ENTRY(I915_MOCS_UNCACHED, \ 141 LE_1_UC | LE_TC_1_LLC, \ 142 L3_1_UC), \ 143 /* Base - L3 + LeCC:PAT (Deprecated) */ \ 144 MOCS_ENTRY(I915_MOCS_PTE, \ 145 LE_0_PAGETABLE | LE_TC_1_LLC, \ 146 L3_3_WB), \ 147 /* Base - L3 + LLC */ \ 148 MOCS_ENTRY(2, \ 149 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3), \ 150 L3_3_WB), \ 151 /* Base - Uncached */ \ 152 MOCS_ENTRY(3, \ 153 LE_1_UC | LE_TC_1_LLC, \ 154 L3_1_UC), \ 155 /* Base - L3 */ \ 156 MOCS_ENTRY(4, \ 157 LE_1_UC | LE_TC_1_LLC, \ 158 L3_3_WB), \ 159 /* Base - LLC */ \ 160 MOCS_ENTRY(5, \ 161 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3), \ 162 L3_1_UC), \ 163 /* Age 0 - LLC */ \ 164 MOCS_ENTRY(6, \ 165 LE_3_WB | LE_TC_1_LLC | LE_LRUM(1), \ 166 L3_1_UC), \ 167 /* Age 0 - L3 + LLC */ \ 168 MOCS_ENTRY(7, \ 169 LE_3_WB | LE_TC_1_LLC | LE_LRUM(1), \ 170 L3_3_WB), \ 171 /* Age: Don't Chg. - LLC */ \ 172 MOCS_ENTRY(8, \ 173 LE_3_WB | LE_TC_1_LLC | LE_LRUM(2), \ 174 L3_1_UC), \ 175 /* Age: Don't Chg. - L3 + LLC */ \ 176 MOCS_ENTRY(9, \ 177 LE_3_WB | LE_TC_1_LLC | LE_LRUM(2), \ 178 L3_3_WB), \ 179 /* No AOM - LLC */ \ 180 MOCS_ENTRY(10, \ 181 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_AOM(1), \ 182 L3_1_UC), \ 183 /* No AOM - L3 + LLC */ \ 184 MOCS_ENTRY(11, \ 185 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_AOM(1), \ 186 L3_3_WB), \ 187 /* No AOM; Age 0 - LLC */ \ 188 MOCS_ENTRY(12, \ 189 LE_3_WB | LE_TC_1_LLC | LE_LRUM(1) | LE_AOM(1), \ 190 L3_1_UC), \ 191 /* No AOM; Age 0 - L3 + LLC */ \ 192 MOCS_ENTRY(13, \ 193 LE_3_WB | LE_TC_1_LLC | LE_LRUM(1) | LE_AOM(1), \ 194 L3_3_WB), \ 195 /* No AOM; Age:DC - LLC */ \ 196 MOCS_ENTRY(14, \ 197 LE_3_WB | LE_TC_1_LLC | LE_LRUM(2) | LE_AOM(1), \ 198 L3_1_UC), \ 199 /* No AOM; Age:DC - L3 + LLC */ \ 200 MOCS_ENTRY(15, \ 201 LE_3_WB | LE_TC_1_LLC | LE_LRUM(2) | LE_AOM(1), \ 202 L3_3_WB), \ 203 /* Bypass LLC - Uncached (EHL+) */ \ 204 MOCS_ENTRY(16, \ 205 LE_1_UC | LE_TC_1_LLC | LE_SCF(1), \ 206 L3_1_UC), \ 207 /* Bypass LLC - L3 (Read-Only) (EHL+) */ \ 208 MOCS_ENTRY(17, \ 209 LE_1_UC | LE_TC_1_LLC | LE_SCF(1), \ 210 L3_3_WB), \ 211 /* Self-Snoop - L3 + LLC */ \ 212 MOCS_ENTRY(18, \ 213 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_SSE(3), \ 214 L3_3_WB), \ 215 /* Skip Caching - L3 + LLC(12.5%) */ \ 216 MOCS_ENTRY(19, \ 217 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_SCC(7), \ 218 L3_3_WB), \ 219 /* Skip Caching - L3 + LLC(25%) */ \ 220 MOCS_ENTRY(20, \ 221 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_SCC(3), \ 222 L3_3_WB), \ 223 /* Skip Caching - L3 + LLC(50%) */ \ 224 MOCS_ENTRY(21, \ 225 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_SCC(1), \ 226 L3_3_WB), \ 227 /* Skip Caching - L3 + LLC(75%) */ \ 228 MOCS_ENTRY(22, \ 229 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_RSC(1) | LE_SCC(3), \ 230 L3_3_WB), \ 231 /* Skip Caching - L3 + LLC(87.5%) */ \ 232 MOCS_ENTRY(23, \ 233 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3) | LE_RSC(1) | LE_SCC(7), \ 234 L3_3_WB), \ 235 /* HW Reserved - SW program but never use */ \ 236 MOCS_ENTRY(62, \ 237 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3), \ 238 L3_1_UC), \ 239 /* HW Reserved - SW program but never use */ \ 240 MOCS_ENTRY(63, \ 241 LE_3_WB | LE_TC_1_LLC | LE_LRUM(3), \ 242 L3_1_UC) 243 244 static const struct drm_i915_mocs_entry icelake_mocs_table[] = { 245 GEN11_MOCS_ENTRIES 246 }; 247 248 /** 249 * get_mocs_settings() 250 * @dev_priv: i915 device. 251 * @table: Output table that will be made to point at appropriate 252 * MOCS values for the device. 253 * 254 * This function will return the values of the MOCS table that needs to 255 * be programmed for the platform. It will return the values that need 256 * to be programmed and if they need to be programmed. 257 * 258 * Return: true if there are applicable MOCS settings for the device. 259 */ 260 static bool get_mocs_settings(struct drm_i915_private *dev_priv, 261 struct drm_i915_mocs_table *table) 262 { 263 bool result = false; 264 265 if (INTEL_GEN(dev_priv) >= 11) { 266 table->size = ARRAY_SIZE(icelake_mocs_table); 267 table->table = icelake_mocs_table; 268 table->n_entries = GEN11_NUM_MOCS_ENTRIES; 269 result = true; 270 } else if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) { 271 table->size = ARRAY_SIZE(skylake_mocs_table); 272 table->n_entries = GEN9_NUM_MOCS_ENTRIES; 273 table->table = skylake_mocs_table; 274 result = true; 275 } else if (IS_GEN9_LP(dev_priv)) { 276 table->size = ARRAY_SIZE(broxton_mocs_table); 277 table->n_entries = GEN9_NUM_MOCS_ENTRIES; 278 table->table = broxton_mocs_table; 279 result = true; 280 } else { 281 WARN_ONCE(INTEL_GEN(dev_priv) >= 9, 282 "Platform that should have a MOCS table does not.\n"); 283 } 284 285 /* WaDisableSkipCaching:skl,bxt,kbl,glk */ 286 if (IS_GEN(dev_priv, 9)) { 287 int i; 288 289 for (i = 0; i < table->size; i++) 290 if (WARN_ON(table->table[i].l3cc_value & 291 (L3_ESC(1) | L3_SCC(0x7)))) 292 return false; 293 } 294 295 return result; 296 } 297 298 static i915_reg_t mocs_register(enum intel_engine_id engine_id, int index) 299 { 300 switch (engine_id) { 301 case RCS0: 302 return GEN9_GFX_MOCS(index); 303 case VCS0: 304 return GEN9_MFX0_MOCS(index); 305 case BCS0: 306 return GEN9_BLT_MOCS(index); 307 case VECS0: 308 return GEN9_VEBOX_MOCS(index); 309 case VCS1: 310 return GEN9_MFX1_MOCS(index); 311 case VCS2: 312 return GEN11_MFX2_MOCS(index); 313 default: 314 MISSING_CASE(engine_id); 315 return INVALID_MMIO_REG; 316 } 317 } 318 319 /* 320 * Get control_value from MOCS entry taking into account when it's not used: 321 * I915_MOCS_PTE's value is returned in this case. 322 */ 323 static u32 get_entry_control(const struct drm_i915_mocs_table *table, 324 unsigned int index) 325 { 326 if (table->table[index].used) 327 return table->table[index].control_value; 328 329 return table->table[I915_MOCS_PTE].control_value; 330 } 331 332 /** 333 * intel_mocs_init_engine() - emit the mocs control table 334 * @engine: The engine for whom to emit the registers. 335 * 336 * This function simply emits a MI_LOAD_REGISTER_IMM command for the 337 * given table starting at the given address. 338 */ 339 void intel_mocs_init_engine(struct intel_engine_cs *engine) 340 { 341 struct drm_i915_private *dev_priv = engine->i915; 342 struct drm_i915_mocs_table table; 343 unsigned int index; 344 u32 unused_value; 345 346 if (!get_mocs_settings(dev_priv, &table)) 347 return; 348 349 /* Set unused values to PTE */ 350 unused_value = table.table[I915_MOCS_PTE].control_value; 351 352 for (index = 0; index < table.size; index++) { 353 u32 value = get_entry_control(&table, index); 354 355 I915_WRITE(mocs_register(engine->id, index), value); 356 } 357 358 /* All remaining entries are also unused */ 359 for (; index < table.n_entries; index++) 360 I915_WRITE(mocs_register(engine->id, index), unused_value); 361 } 362 363 /** 364 * emit_mocs_control_table() - emit the mocs control table 365 * @rq: Request to set up the MOCS table for. 366 * @table: The values to program into the control regs. 367 * 368 * This function simply emits a MI_LOAD_REGISTER_IMM command for the 369 * given table starting at the given address. 370 * 371 * Return: 0 on success, otherwise the error status. 372 */ 373 static int emit_mocs_control_table(struct i915_request *rq, 374 const struct drm_i915_mocs_table *table) 375 { 376 enum intel_engine_id engine = rq->engine->id; 377 unsigned int index; 378 u32 unused_value; 379 u32 *cs; 380 381 if (GEM_WARN_ON(table->size > table->n_entries)) 382 return -ENODEV; 383 384 /* Set unused values to PTE */ 385 unused_value = table->table[I915_MOCS_PTE].control_value; 386 387 cs = intel_ring_begin(rq, 2 + 2 * table->n_entries); 388 if (IS_ERR(cs)) 389 return PTR_ERR(cs); 390 391 *cs++ = MI_LOAD_REGISTER_IMM(table->n_entries); 392 393 for (index = 0; index < table->size; index++) { 394 u32 value = get_entry_control(table, index); 395 396 *cs++ = i915_mmio_reg_offset(mocs_register(engine, index)); 397 *cs++ = value; 398 } 399 400 /* All remaining entries are also unused */ 401 for (; index < table->n_entries; index++) { 402 *cs++ = i915_mmio_reg_offset(mocs_register(engine, index)); 403 *cs++ = unused_value; 404 } 405 406 *cs++ = MI_NOOP; 407 intel_ring_advance(rq, cs); 408 409 return 0; 410 } 411 412 /* 413 * Get l3cc_value from MOCS entry taking into account when it's not used: 414 * I915_MOCS_PTE's value is returned in this case. 415 */ 416 static u16 get_entry_l3cc(const struct drm_i915_mocs_table *table, 417 unsigned int index) 418 { 419 if (table->table[index].used) 420 return table->table[index].l3cc_value; 421 422 return table->table[I915_MOCS_PTE].l3cc_value; 423 } 424 425 static inline u32 l3cc_combine(const struct drm_i915_mocs_table *table, 426 u16 low, 427 u16 high) 428 { 429 return low | high << 16; 430 } 431 432 /** 433 * emit_mocs_l3cc_table() - emit the mocs control table 434 * @rq: Request to set up the MOCS table for. 435 * @table: The values to program into the control regs. 436 * 437 * This function simply emits a MI_LOAD_REGISTER_IMM command for the 438 * given table starting at the given address. This register set is 439 * programmed in pairs. 440 * 441 * Return: 0 on success, otherwise the error status. 442 */ 443 static int emit_mocs_l3cc_table(struct i915_request *rq, 444 const struct drm_i915_mocs_table *table) 445 { 446 u16 unused_value; 447 unsigned int i; 448 u32 *cs; 449 450 if (GEM_WARN_ON(table->size > table->n_entries)) 451 return -ENODEV; 452 453 /* Set unused values to PTE */ 454 unused_value = table->table[I915_MOCS_PTE].l3cc_value; 455 456 cs = intel_ring_begin(rq, 2 + table->n_entries); 457 if (IS_ERR(cs)) 458 return PTR_ERR(cs); 459 460 *cs++ = MI_LOAD_REGISTER_IMM(table->n_entries / 2); 461 462 for (i = 0; i < table->size / 2; i++) { 463 u16 low = get_entry_l3cc(table, 2 * i); 464 u16 high = get_entry_l3cc(table, 2 * i + 1); 465 466 *cs++ = i915_mmio_reg_offset(GEN9_LNCFCMOCS(i)); 467 *cs++ = l3cc_combine(table, low, high); 468 } 469 470 /* Odd table size - 1 left over */ 471 if (table->size & 0x01) { 472 u16 low = get_entry_l3cc(table, 2 * i); 473 474 *cs++ = i915_mmio_reg_offset(GEN9_LNCFCMOCS(i)); 475 *cs++ = l3cc_combine(table, low, unused_value); 476 i++; 477 } 478 479 /* All remaining entries are also unused */ 480 for (; i < table->n_entries / 2; i++) { 481 *cs++ = i915_mmio_reg_offset(GEN9_LNCFCMOCS(i)); 482 *cs++ = l3cc_combine(table, unused_value, unused_value); 483 } 484 485 *cs++ = MI_NOOP; 486 intel_ring_advance(rq, cs); 487 488 return 0; 489 } 490 491 /** 492 * intel_mocs_init_l3cc_table() - program the mocs control table 493 * @dev_priv: i915 device private 494 * 495 * This function simply programs the mocs registers for the given table 496 * starting at the given address. This register set is programmed in pairs. 497 * 498 * These registers may get programmed more than once, it is simpler to 499 * re-program 32 registers than maintain the state of when they were programmed. 500 * We are always reprogramming with the same values and this only on context 501 * start. 502 * 503 * Return: Nothing. 504 */ 505 void intel_mocs_init_l3cc_table(struct drm_i915_private *dev_priv) 506 { 507 struct drm_i915_mocs_table table; 508 unsigned int i; 509 u16 unused_value; 510 511 if (!get_mocs_settings(dev_priv, &table)) 512 return; 513 514 /* Set unused values to PTE */ 515 unused_value = table.table[I915_MOCS_PTE].l3cc_value; 516 517 for (i = 0; i < table.size / 2; i++) { 518 u16 low = get_entry_l3cc(&table, 2 * i); 519 u16 high = get_entry_l3cc(&table, 2 * i + 1); 520 521 I915_WRITE(GEN9_LNCFCMOCS(i), 522 l3cc_combine(&table, low, high)); 523 } 524 525 /* Odd table size - 1 left over */ 526 if (table.size & 0x01) { 527 u16 low = get_entry_l3cc(&table, 2 * i); 528 529 I915_WRITE(GEN9_LNCFCMOCS(i), 530 l3cc_combine(&table, low, unused_value)); 531 i++; 532 } 533 534 /* All remaining entries are also unused */ 535 for (; i < table.n_entries / 2; i++) 536 I915_WRITE(GEN9_LNCFCMOCS(i), 537 l3cc_combine(&table, unused_value, unused_value)); 538 } 539 540 /** 541 * intel_rcs_context_init_mocs() - program the MOCS register. 542 * @rq: Request to set up the MOCS tables for. 543 * 544 * This function will emit a batch buffer with the values required for 545 * programming the MOCS register values for all the currently supported 546 * rings. 547 * 548 * These registers are partially stored in the RCS context, so they are 549 * emitted at the same time so that when a context is created these registers 550 * are set up. These registers have to be emitted into the start of the 551 * context as setting the ELSP will re-init some of these registers back 552 * to the hw values. 553 * 554 * Return: 0 on success, otherwise the error status. 555 */ 556 int intel_rcs_context_init_mocs(struct i915_request *rq) 557 { 558 struct drm_i915_mocs_table t; 559 int ret; 560 561 if (get_mocs_settings(rq->i915, &t)) { 562 /* Program the RCS control registers */ 563 ret = emit_mocs_control_table(rq, &t); 564 if (ret) 565 return ret; 566 567 /* Now program the l3cc registers */ 568 ret = emit_mocs_l3cc_table(rq, &t); 569 if (ret) 570 return ret; 571 } 572 573 return 0; 574 } 575