linux/drivers/gpu/drm/i915/intel_mocs.c
<<
>>
Prefs
   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 "intel_mocs.h"
  24#include "intel_lrc.h"
  25#include "intel_ringbuffer.h"
  26
  27/* structures required */
  28struct drm_i915_mocs_entry {
  29        u32 control_value;
  30        u16 l3cc_value;
  31};
  32
  33struct drm_i915_mocs_table {
  34        u32 size;
  35        const struct drm_i915_mocs_entry *table;
  36};
  37
  38/* Defines for the tables (XXX_MOCS_0 - XXX_MOCS_63) */
  39#define LE_CACHEABILITY(value)  ((value) << 0)
  40#define LE_TGT_CACHE(value)     ((value) << 2)
  41#define LE_LRUM(value)          ((value) << 4)
  42#define LE_AOM(value)           ((value) << 6)
  43#define LE_RSC(value)           ((value) << 7)
  44#define LE_SCC(value)           ((value) << 8)
  45#define LE_PFM(value)           ((value) << 11)
  46#define LE_SCF(value)           ((value) << 14)
  47
  48/* Defines for the tables (LNCFMOCS0 - LNCFMOCS31) - two entries per word */
  49#define L3_ESC(value)           ((value) << 0)
  50#define L3_SCC(value)           ((value) << 1)
  51#define L3_CACHEABILITY(value)  ((value) << 4)
  52
  53/* Helper defines */
  54#define GEN9_NUM_MOCS_ENTRIES   62  /* 62 out of 64 - 63 & 64 are reserved. */
  55
  56/* (e)LLC caching options */
  57#define LE_PAGETABLE            0
  58#define LE_UC                   1
  59#define LE_WT                   2
  60#define LE_WB                   3
  61
  62/* L3 caching options */
  63#define L3_DIRECT               0
  64#define L3_UC                   1
  65#define L3_RESERVED             2
  66#define L3_WB                   3
  67
  68/* Target cache */
  69#define ELLC                    0
  70#define LLC                     1
  71#define LLC_ELLC                2
  72
  73/*
  74 * MOCS tables
  75 *
  76 * These are the MOCS tables that are programmed across all the rings.
  77 * The control value is programmed to all the rings that support the
  78 * MOCS registers. While the l3cc_values are only programmed to the
  79 * LNCFCMOCS0 - LNCFCMOCS32 registers.
  80 *
  81 * These tables are intended to be kept reasonably consistent across
  82 * platforms. However some of the fields are not applicable to all of
  83 * them.
  84 *
  85 * Entries not part of the following tables are undefined as far as
  86 * userspace is concerned and shouldn't be relied upon.  For the time
  87 * being they will be implicitly initialized to the strictest caching
  88 * configuration (uncached) to guarantee forwards compatibility with
  89 * userspace programs written against more recent kernels providing
  90 * additional MOCS entries.
  91 *
  92 * NOTE: These tables MUST start with being uncached and the length
  93 *       MUST be less than 63 as the last two registers are reserved
  94 *       by the hardware.  These tables are part of the kernel ABI and
  95 *       may only be updated incrementally by adding entries at the
  96 *       end.
  97 */
  98static const struct drm_i915_mocs_entry skylake_mocs_table[] = {
  99        /* { 0x00000009, 0x0010 } */
 100        { (LE_CACHEABILITY(LE_UC) | LE_TGT_CACHE(LLC_ELLC) | LE_LRUM(0) |
 101           LE_AOM(0) | LE_RSC(0) | LE_SCC(0) | LE_PFM(0) | LE_SCF(0)),
 102          (L3_ESC(0) | L3_SCC(0) | L3_CACHEABILITY(L3_UC)) },
 103        /* { 0x00000038, 0x0030 } */
 104        { (LE_CACHEABILITY(LE_PAGETABLE) | LE_TGT_CACHE(LLC_ELLC) | LE_LRUM(3) |
 105           LE_AOM(0) | LE_RSC(0) | LE_SCC(0) | LE_PFM(0) | LE_SCF(0)),
 106          (L3_ESC(0) | L3_SCC(0) | L3_CACHEABILITY(L3_WB)) },
 107        /* { 0x0000003b, 0x0030 } */
 108        { (LE_CACHEABILITY(LE_WB) | LE_TGT_CACHE(LLC_ELLC) | LE_LRUM(3) |
 109           LE_AOM(0) | LE_RSC(0) | LE_SCC(0) | LE_PFM(0) | LE_SCF(0)),
 110          (L3_ESC(0) | L3_SCC(0) | L3_CACHEABILITY(L3_WB)) }
 111};
 112
 113/* NOTE: the LE_TGT_CACHE is not used on Broxton */
 114static const struct drm_i915_mocs_entry broxton_mocs_table[] = {
 115        /* { 0x00000009, 0x0010 } */
 116        { (LE_CACHEABILITY(LE_UC) | LE_TGT_CACHE(LLC_ELLC) | LE_LRUM(0) |
 117           LE_AOM(0) | LE_RSC(0) | LE_SCC(0) | LE_PFM(0) | LE_SCF(0)),
 118          (L3_ESC(0) | L3_SCC(0) | L3_CACHEABILITY(L3_UC)) },
 119        /* { 0x00000038, 0x0030 } */
 120        { (LE_CACHEABILITY(LE_PAGETABLE) | LE_TGT_CACHE(LLC_ELLC) | LE_LRUM(3) |
 121           LE_AOM(0) | LE_RSC(0) | LE_SCC(0) | LE_PFM(0) | LE_SCF(0)),
 122          (L3_ESC(0) | L3_SCC(0) | L3_CACHEABILITY(L3_WB)) },
 123        /* { 0x0000003b, 0x0030 } */
 124        { (LE_CACHEABILITY(LE_WB) | LE_TGT_CACHE(LLC_ELLC) | LE_LRUM(3) |
 125           LE_AOM(0) | LE_RSC(0) | LE_SCC(0) | LE_PFM(0) | LE_SCF(0)),
 126          (L3_ESC(0) | L3_SCC(0) | L3_CACHEABILITY(L3_WB)) }
 127};
 128
 129/**
 130 * get_mocs_settings()
 131 * @dev:        DRM device.
 132 * @table:      Output table that will be made to point at appropriate
 133 *              MOCS values for the device.
 134 *
 135 * This function will return the values of the MOCS table that needs to
 136 * be programmed for the platform. It will return the values that need
 137 * to be programmed and if they need to be programmed.
 138 *
 139 * Return: true if there are applicable MOCS settings for the device.
 140 */
 141static bool get_mocs_settings(struct drm_device *dev,
 142                              struct drm_i915_mocs_table *table)
 143{
 144        bool result = false;
 145
 146        if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
 147                table->size  = ARRAY_SIZE(skylake_mocs_table);
 148                table->table = skylake_mocs_table;
 149                result = true;
 150        } else if (IS_BROXTON(dev)) {
 151                table->size  = ARRAY_SIZE(broxton_mocs_table);
 152                table->table = broxton_mocs_table;
 153                result = true;
 154        } else {
 155                WARN_ONCE(INTEL_INFO(dev)->gen >= 9,
 156                          "Platform that should have a MOCS table does not.\n");
 157        }
 158
 159        return result;
 160}
 161
 162static i915_reg_t mocs_register(enum intel_ring_id ring, int index)
 163{
 164        switch (ring) {
 165        case RCS:
 166                return GEN9_GFX_MOCS(index);
 167        case VCS:
 168                return GEN9_MFX0_MOCS(index);
 169        case BCS:
 170                return GEN9_BLT_MOCS(index);
 171        case VECS:
 172                return GEN9_VEBOX_MOCS(index);
 173        case VCS2:
 174                return GEN9_MFX1_MOCS(index);
 175        default:
 176                MISSING_CASE(ring);
 177                return INVALID_MMIO_REG;
 178        }
 179}
 180
 181/**
 182 * emit_mocs_control_table() - emit the mocs control table
 183 * @req:        Request to set up the MOCS table for.
 184 * @table:      The values to program into the control regs.
 185 * @ring:       The engine for whom to emit the registers.
 186 *
 187 * This function simply emits a MI_LOAD_REGISTER_IMM command for the
 188 * given table starting at the given address.
 189 *
 190 * Return: 0 on success, otherwise the error status.
 191 */
 192static int emit_mocs_control_table(struct drm_i915_gem_request *req,
 193                                   const struct drm_i915_mocs_table *table,
 194                                   enum intel_ring_id ring)
 195{
 196        struct intel_ringbuffer *ringbuf = req->ringbuf;
 197        unsigned int index;
 198        int ret;
 199
 200        if (WARN_ON(table->size > GEN9_NUM_MOCS_ENTRIES))
 201                return -ENODEV;
 202
 203        ret = intel_logical_ring_begin(req, 2 + 2 * GEN9_NUM_MOCS_ENTRIES);
 204        if (ret) {
 205                DRM_DEBUG("intel_logical_ring_begin failed %d\n", ret);
 206                return ret;
 207        }
 208
 209        intel_logical_ring_emit(ringbuf,
 210                                MI_LOAD_REGISTER_IMM(GEN9_NUM_MOCS_ENTRIES));
 211
 212        for (index = 0; index < table->size; index++) {
 213                intel_logical_ring_emit_reg(ringbuf, mocs_register(ring, index));
 214                intel_logical_ring_emit(ringbuf,
 215                                        table->table[index].control_value);
 216        }
 217
 218        /*
 219         * Ok, now set the unused entries to uncached. These entries
 220         * are officially undefined and no contract for the contents
 221         * and settings is given for these entries.
 222         *
 223         * Entry 0 in the table is uncached - so we are just writing
 224         * that value to all the used entries.
 225         */
 226        for (; index < GEN9_NUM_MOCS_ENTRIES; index++) {
 227                intel_logical_ring_emit_reg(ringbuf, mocs_register(ring, index));
 228                intel_logical_ring_emit(ringbuf, table->table[0].control_value);
 229        }
 230
 231        intel_logical_ring_emit(ringbuf, MI_NOOP);
 232        intel_logical_ring_advance(ringbuf);
 233
 234        return 0;
 235}
 236
 237/**
 238 * emit_mocs_l3cc_table() - emit the mocs control table
 239 * @req:        Request to set up the MOCS table for.
 240 * @table:      The values to program into the control regs.
 241 *
 242 * This function simply emits a MI_LOAD_REGISTER_IMM command for the
 243 * given table starting at the given address. This register set is
 244 * programmed in pairs.
 245 *
 246 * Return: 0 on success, otherwise the error status.
 247 */
 248static int emit_mocs_l3cc_table(struct drm_i915_gem_request *req,
 249                                const struct drm_i915_mocs_table *table)
 250{
 251        struct intel_ringbuffer *ringbuf = req->ringbuf;
 252        unsigned int count;
 253        unsigned int i;
 254        u32 value;
 255        u32 filler = (table->table[0].l3cc_value & 0xffff) |
 256                        ((table->table[0].l3cc_value & 0xffff) << 16);
 257        int ret;
 258
 259        if (WARN_ON(table->size > GEN9_NUM_MOCS_ENTRIES))
 260                return -ENODEV;
 261
 262        ret = intel_logical_ring_begin(req, 2 + GEN9_NUM_MOCS_ENTRIES);
 263        if (ret) {
 264                DRM_DEBUG("intel_logical_ring_begin failed %d\n", ret);
 265                return ret;
 266        }
 267
 268        intel_logical_ring_emit(ringbuf,
 269                        MI_LOAD_REGISTER_IMM(GEN9_NUM_MOCS_ENTRIES / 2));
 270
 271        for (i = 0, count = 0; i < table->size / 2; i++, count += 2) {
 272                value = (table->table[count].l3cc_value & 0xffff) |
 273                        ((table->table[count + 1].l3cc_value & 0xffff) << 16);
 274
 275                intel_logical_ring_emit_reg(ringbuf, GEN9_LNCFCMOCS(i));
 276                intel_logical_ring_emit(ringbuf, value);
 277        }
 278
 279        if (table->size & 0x01) {
 280                /* Odd table size - 1 left over */
 281                value = (table->table[count].l3cc_value & 0xffff) |
 282                        ((table->table[0].l3cc_value & 0xffff) << 16);
 283        } else
 284                value = filler;
 285
 286        /*
 287         * Now set the rest of the table to uncached - use entry 0 as
 288         * this will be uncached. Leave the last pair uninitialised as
 289         * they are reserved by the hardware.
 290         */
 291        for (; i < GEN9_NUM_MOCS_ENTRIES / 2; i++) {
 292                intel_logical_ring_emit_reg(ringbuf, GEN9_LNCFCMOCS(i));
 293                intel_logical_ring_emit(ringbuf, value);
 294
 295                value = filler;
 296        }
 297
 298        intel_logical_ring_emit(ringbuf, MI_NOOP);
 299        intel_logical_ring_advance(ringbuf);
 300
 301        return 0;
 302}
 303
 304/**
 305 * intel_rcs_context_init_mocs() - program the MOCS register.
 306 * @req:        Request to set up the MOCS tables for.
 307 *
 308 * This function will emit a batch buffer with the values required for
 309 * programming the MOCS register values for all the currently supported
 310 * rings.
 311 *
 312 * These registers are partially stored in the RCS context, so they are
 313 * emitted at the same time so that when a context is created these registers
 314 * are set up. These registers have to be emitted into the start of the
 315 * context as setting the ELSP will re-init some of these registers back
 316 * to the hw values.
 317 *
 318 * Return: 0 on success, otherwise the error status.
 319 */
 320int intel_rcs_context_init_mocs(struct drm_i915_gem_request *req)
 321{
 322        struct drm_i915_mocs_table t;
 323        int ret;
 324
 325        if (get_mocs_settings(req->ring->dev, &t)) {
 326                struct drm_i915_private *dev_priv = req->i915;
 327                struct intel_engine_cs *ring;
 328                enum intel_ring_id ring_id;
 329
 330                /* Program the control registers */
 331                for_each_ring(ring, dev_priv, ring_id) {
 332                        ret = emit_mocs_control_table(req, &t, ring_id);
 333                        if (ret)
 334                                return ret;
 335                }
 336
 337                /* Now program the l3cc registers */
 338                ret = emit_mocs_l3cc_table(req, &t);
 339                if (ret)
 340                        return ret;
 341        }
 342
 343        return 0;
 344}
 345