linux/drivers/gpu/drm/i915/i915_cmd_parser.c
<<
>>
Prefs
   1/*
   2 * Copyright © 2013 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 *
  11 * The above copyright notice and this permission notice (including the next
  12 * paragraph) shall be included in all copies or substantial portions of the
  13 * Software.
  14 *
  15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21 * IN THE SOFTWARE.
  22 *
  23 * Authors:
  24 *    Brad Volkin <bradley.d.volkin@intel.com>
  25 *
  26 */
  27
  28#include "i915_drv.h"
  29
  30/**
  31 * DOC: i915 batch buffer command parser
  32 *
  33 * Motivation:
  34 * Certain OpenGL features (e.g. transform feedback, performance monitoring)
  35 * require userspace code to submit batches containing commands such as
  36 * MI_LOAD_REGISTER_IMM to access various registers. Unfortunately, some
  37 * generations of the hardware will noop these commands in "unsecure" batches
  38 * (which includes all userspace batches submitted via i915) even though the
  39 * commands may be safe and represent the intended programming model of the
  40 * device.
  41 *
  42 * The software command parser is similar in operation to the command parsing
  43 * done in hardware for unsecure batches. However, the software parser allows
  44 * some operations that would be noop'd by hardware, if the parser determines
  45 * the operation is safe, and submits the batch as "secure" to prevent hardware
  46 * parsing.
  47 *
  48 * Threats:
  49 * At a high level, the hardware (and software) checks attempt to prevent
  50 * granting userspace undue privileges. There are three categories of privilege.
  51 *
  52 * First, commands which are explicitly defined as privileged or which should
  53 * only be used by the kernel driver. The parser generally rejects such
  54 * commands, though it may allow some from the drm master process.
  55 *
  56 * Second, commands which access registers. To support correct/enhanced
  57 * userspace functionality, particularly certain OpenGL extensions, the parser
  58 * provides a whitelist of registers which userspace may safely access (for both
  59 * normal and drm master processes).
  60 *
  61 * Third, commands which access privileged memory (i.e. GGTT, HWS page, etc).
  62 * The parser always rejects such commands.
  63 *
  64 * The majority of the problematic commands fall in the MI_* range, with only a
  65 * few specific commands on each ring (e.g. PIPE_CONTROL and MI_FLUSH_DW).
  66 *
  67 * Implementation:
  68 * Each ring maintains tables of commands and registers which the parser uses in
  69 * scanning batch buffers submitted to that ring.
  70 *
  71 * Since the set of commands that the parser must check for is significantly
  72 * smaller than the number of commands supported, the parser tables contain only
  73 * those commands required by the parser. This generally works because command
  74 * opcode ranges have standard command length encodings. So for commands that
  75 * the parser does not need to check, it can easily skip them. This is
  76 * implementated via a per-ring length decoding vfunc.
  77 *
  78 * Unfortunately, there are a number of commands that do not follow the standard
  79 * length encoding for their opcode range, primarily amongst the MI_* commands.
  80 * To handle this, the parser provides a way to define explicit "skip" entries
  81 * in the per-ring command tables.
  82 *
  83 * Other command table entries map fairly directly to high level categories
  84 * mentioned above: rejected, master-only, register whitelist. The parser
  85 * implements a number of checks, including the privileged memory checks, via a
  86 * general bitmasking mechanism.
  87 */
  88
  89static u32 gen7_render_get_cmd_length_mask(u32 cmd_header)
  90{
  91        u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT;
  92        u32 subclient =
  93                (cmd_header & INSTR_SUBCLIENT_MASK) >> INSTR_SUBCLIENT_SHIFT;
  94
  95        if (client == INSTR_MI_CLIENT)
  96                return 0x3F;
  97        else if (client == INSTR_RC_CLIENT) {
  98                if (subclient == INSTR_MEDIA_SUBCLIENT)
  99                        return 0xFFFF;
 100                else
 101                        return 0xFF;
 102        }
 103
 104        DRM_DEBUG_DRIVER("CMD: Abnormal rcs cmd length! 0x%08X\n", cmd_header);
 105        return 0;
 106}
 107
 108static u32 gen7_bsd_get_cmd_length_mask(u32 cmd_header)
 109{
 110        u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT;
 111        u32 subclient =
 112                (cmd_header & INSTR_SUBCLIENT_MASK) >> INSTR_SUBCLIENT_SHIFT;
 113
 114        if (client == INSTR_MI_CLIENT)
 115                return 0x3F;
 116        else if (client == INSTR_RC_CLIENT) {
 117                if (subclient == INSTR_MEDIA_SUBCLIENT)
 118                        return 0xFFF;
 119                else
 120                        return 0xFF;
 121        }
 122
 123        DRM_DEBUG_DRIVER("CMD: Abnormal bsd cmd length! 0x%08X\n", cmd_header);
 124        return 0;
 125}
 126
 127static u32 gen7_blt_get_cmd_length_mask(u32 cmd_header)
 128{
 129        u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT;
 130
 131        if (client == INSTR_MI_CLIENT)
 132                return 0x3F;
 133        else if (client == INSTR_BC_CLIENT)
 134                return 0xFF;
 135
 136        DRM_DEBUG_DRIVER("CMD: Abnormal blt cmd length! 0x%08X\n", cmd_header);
 137        return 0;
 138}
 139
 140static void validate_cmds_sorted(struct intel_ring_buffer *ring)
 141{
 142        int i;
 143
 144        if (!ring->cmd_tables || ring->cmd_table_count == 0)
 145                return;
 146
 147        for (i = 0; i < ring->cmd_table_count; i++) {
 148                const struct drm_i915_cmd_table *table = &ring->cmd_tables[i];
 149                u32 previous = 0;
 150                int j;
 151
 152                for (j = 0; j < table->count; j++) {
 153                        const struct drm_i915_cmd_descriptor *desc =
 154                                &table->table[i];
 155                        u32 curr = desc->cmd.value & desc->cmd.mask;
 156
 157                        if (curr < previous)
 158                                DRM_ERROR("CMD: table not sorted ring=%d table=%d entry=%d cmd=0x%08X prev=0x%08X\n",
 159                                          ring->id, i, j, curr, previous);
 160
 161                        previous = curr;
 162                }
 163        }
 164}
 165
 166static void check_sorted(int ring_id, const u32 *reg_table, int reg_count)
 167{
 168        int i;
 169        u32 previous = 0;
 170
 171        for (i = 0; i < reg_count; i++) {
 172                u32 curr = reg_table[i];
 173
 174                if (curr < previous)
 175                        DRM_ERROR("CMD: table not sorted ring=%d entry=%d reg=0x%08X prev=0x%08X\n",
 176                                  ring_id, i, curr, previous);
 177
 178                previous = curr;
 179        }
 180}
 181
 182static void validate_regs_sorted(struct intel_ring_buffer *ring)
 183{
 184        check_sorted(ring->id, ring->reg_table, ring->reg_count);
 185        check_sorted(ring->id, ring->master_reg_table, ring->master_reg_count);
 186}
 187
 188/**
 189 * i915_cmd_parser_init_ring() - set cmd parser related fields for a ringbuffer
 190 * @ring: the ringbuffer to initialize
 191 *
 192 * Optionally initializes fields related to batch buffer command parsing in the
 193 * struct intel_ring_buffer based on whether the platform requires software
 194 * command parsing.
 195 */
 196void i915_cmd_parser_init_ring(struct intel_ring_buffer *ring)
 197{
 198        if (!IS_GEN7(ring->dev))
 199                return;
 200
 201        switch (ring->id) {
 202        case RCS:
 203                ring->get_cmd_length_mask = gen7_render_get_cmd_length_mask;
 204                break;
 205        case VCS:
 206                ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
 207                break;
 208        case BCS:
 209                ring->get_cmd_length_mask = gen7_blt_get_cmd_length_mask;
 210                break;
 211        case VECS:
 212                /* VECS can use the same length_mask function as VCS */
 213                ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
 214                break;
 215        default:
 216                DRM_ERROR("CMD: cmd_parser_init with unknown ring: %d\n",
 217                          ring->id);
 218                BUG();
 219        }
 220
 221        validate_cmds_sorted(ring);
 222        validate_regs_sorted(ring);
 223}
 224
 225static const struct drm_i915_cmd_descriptor*
 226find_cmd_in_table(const struct drm_i915_cmd_table *table,
 227                  u32 cmd_header)
 228{
 229        int i;
 230
 231        for (i = 0; i < table->count; i++) {
 232                const struct drm_i915_cmd_descriptor *desc = &table->table[i];
 233                u32 masked_cmd = desc->cmd.mask & cmd_header;
 234                u32 masked_value = desc->cmd.value & desc->cmd.mask;
 235
 236                if (masked_cmd == masked_value)
 237                        return desc;
 238        }
 239
 240        return NULL;
 241}
 242
 243/*
 244 * Returns a pointer to a descriptor for the command specified by cmd_header.
 245 *
 246 * The caller must supply space for a default descriptor via the default_desc
 247 * parameter. If no descriptor for the specified command exists in the ring's
 248 * command parser tables, this function fills in default_desc based on the
 249 * ring's default length encoding and returns default_desc.
 250 */
 251static const struct drm_i915_cmd_descriptor*
 252find_cmd(struct intel_ring_buffer *ring,
 253         u32 cmd_header,
 254         struct drm_i915_cmd_descriptor *default_desc)
 255{
 256        u32 mask;
 257        int i;
 258
 259        for (i = 0; i < ring->cmd_table_count; i++) {
 260                const struct drm_i915_cmd_descriptor *desc;
 261
 262                desc = find_cmd_in_table(&ring->cmd_tables[i], cmd_header);
 263                if (desc)
 264                        return desc;
 265        }
 266
 267        mask = ring->get_cmd_length_mask(cmd_header);
 268        if (!mask)
 269                return NULL;
 270
 271        BUG_ON(!default_desc);
 272        default_desc->flags = CMD_DESC_SKIP;
 273        default_desc->length.mask = mask;
 274
 275        return default_desc;
 276}
 277
 278static bool valid_reg(const u32 *table, int count, u32 addr)
 279{
 280        if (table && count != 0) {
 281                int i;
 282
 283                for (i = 0; i < count; i++) {
 284                        if (table[i] == addr)
 285                                return true;
 286                }
 287        }
 288
 289        return false;
 290}
 291
 292static u32 *vmap_batch(struct drm_i915_gem_object *obj)
 293{
 294        int i;
 295        void *addr = NULL;
 296        struct sg_page_iter sg_iter;
 297        struct page **pages;
 298
 299        pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages));
 300        if (pages == NULL) {
 301                DRM_DEBUG_DRIVER("Failed to get space for pages\n");
 302                goto finish;
 303        }
 304
 305        i = 0;
 306        for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) {
 307                pages[i] = sg_page_iter_page(&sg_iter);
 308                i++;
 309        }
 310
 311        addr = vmap(pages, i, 0, PAGE_KERNEL);
 312        if (addr == NULL) {
 313                DRM_DEBUG_DRIVER("Failed to vmap pages\n");
 314                goto finish;
 315        }
 316
 317finish:
 318        if (pages)
 319                drm_free_large(pages);
 320        return (u32*)addr;
 321}
 322
 323/**
 324 * i915_needs_cmd_parser() - should a given ring use software command parsing?
 325 * @ring: the ring in question
 326 *
 327 * Only certain platforms require software batch buffer command parsing, and
 328 * only when enabled via module paramter.
 329 *
 330 * Return: true if the ring requires software command parsing
 331 */
 332bool i915_needs_cmd_parser(struct intel_ring_buffer *ring)
 333{
 334        /* No command tables indicates a platform without parsing */
 335        if (!ring->cmd_tables)
 336                return false;
 337
 338        return (i915.enable_cmd_parser == 1);
 339}
 340
 341#define LENGTH_BIAS 2
 342
 343/**
 344 * i915_parse_cmds() - parse a submitted batch buffer for privilege violations
 345 * @ring: the ring on which the batch is to execute
 346 * @batch_obj: the batch buffer in question
 347 * @batch_start_offset: byte offset in the batch at which execution starts
 348 * @is_master: is the submitting process the drm master?
 349 *
 350 * Parses the specified batch buffer looking for privilege violations as
 351 * described in the overview.
 352 *
 353 * Return: non-zero if the parser finds violations or otherwise fails
 354 */
 355int i915_parse_cmds(struct intel_ring_buffer *ring,
 356                    struct drm_i915_gem_object *batch_obj,
 357                    u32 batch_start_offset,
 358                    bool is_master)
 359{
 360        int ret = 0;
 361        u32 *cmd, *batch_base, *batch_end;
 362        struct drm_i915_cmd_descriptor default_desc = { 0 };
 363        int needs_clflush = 0;
 364
 365        ret = i915_gem_obj_prepare_shmem_read(batch_obj, &needs_clflush);
 366        if (ret) {
 367                DRM_DEBUG_DRIVER("CMD: failed to prep read\n");
 368                return ret;
 369        }
 370
 371        batch_base = vmap_batch(batch_obj);
 372        if (!batch_base) {
 373                DRM_DEBUG_DRIVER("CMD: Failed to vmap batch\n");
 374                i915_gem_object_unpin_pages(batch_obj);
 375                return -ENOMEM;
 376        }
 377
 378        if (needs_clflush)
 379                drm_clflush_virt_range((char *)batch_base, batch_obj->base.size);
 380
 381        cmd = batch_base + (batch_start_offset / sizeof(*cmd));
 382        batch_end = cmd + (batch_obj->base.size / sizeof(*batch_end));
 383
 384        while (cmd < batch_end) {
 385                const struct drm_i915_cmd_descriptor *desc;
 386                u32 length;
 387
 388                if (*cmd == MI_BATCH_BUFFER_END)
 389                        break;
 390
 391                desc = find_cmd(ring, *cmd, &default_desc);
 392                if (!desc) {
 393                        DRM_DEBUG_DRIVER("CMD: Unrecognized command: 0x%08X\n",
 394                                         *cmd);
 395                        ret = -EINVAL;
 396                        break;
 397                }
 398
 399                if (desc->flags & CMD_DESC_FIXED)
 400                        length = desc->length.fixed;
 401                else
 402                        length = ((*cmd & desc->length.mask) + LENGTH_BIAS);
 403
 404                if ((batch_end - cmd) < length) {
 405                        DRM_DEBUG_DRIVER("CMD: Command length exceeds batch length: 0x%08X length=%d batchlen=%td\n",
 406                                         *cmd,
 407                                         length,
 408                                         (unsigned long)(batch_end - cmd));
 409                        ret = -EINVAL;
 410                        break;
 411                }
 412
 413                if (desc->flags & CMD_DESC_REJECT) {
 414                        DRM_DEBUG_DRIVER("CMD: Rejected command: 0x%08X\n", *cmd);
 415                        ret = -EINVAL;
 416                        break;
 417                }
 418
 419                if ((desc->flags & CMD_DESC_MASTER) && !is_master) {
 420                        DRM_DEBUG_DRIVER("CMD: Rejected master-only command: 0x%08X\n",
 421                                         *cmd);
 422                        ret = -EINVAL;
 423                        break;
 424                }
 425
 426                if (desc->flags & CMD_DESC_REGISTER) {
 427                        u32 reg_addr = cmd[desc->reg.offset] & desc->reg.mask;
 428
 429                        if (!valid_reg(ring->reg_table,
 430                                       ring->reg_count, reg_addr)) {
 431                                if (!is_master ||
 432                                    !valid_reg(ring->master_reg_table,
 433                                               ring->master_reg_count,
 434                                               reg_addr)) {
 435                                        DRM_DEBUG_DRIVER("CMD: Rejected register 0x%08X in command: 0x%08X (ring=%d)\n",
 436                                                         reg_addr,
 437                                                         *cmd,
 438                                                         ring->id);
 439                                        ret = -EINVAL;
 440                                        break;
 441                                }
 442                        }
 443                }
 444
 445                if (desc->flags & CMD_DESC_BITMASK) {
 446                        int i;
 447
 448                        for (i = 0; i < MAX_CMD_DESC_BITMASKS; i++) {
 449                                u32 dword;
 450
 451                                if (desc->bits[i].mask == 0)
 452                                        break;
 453
 454                                dword = cmd[desc->bits[i].offset] &
 455                                        desc->bits[i].mask;
 456
 457                                if (dword != desc->bits[i].expected) {
 458                                        DRM_DEBUG_DRIVER("CMD: Rejected command 0x%08X for bitmask 0x%08X (exp=0x%08X act=0x%08X) (ring=%d)\n",
 459                                                         *cmd,
 460                                                         desc->bits[i].mask,
 461                                                         desc->bits[i].expected,
 462                                                         dword, ring->id);
 463                                        ret = -EINVAL;
 464                                        break;
 465                                }
 466                        }
 467
 468                        if (ret)
 469                                break;
 470                }
 471
 472                cmd += length;
 473        }
 474
 475        if (cmd >= batch_end) {
 476                DRM_DEBUG_DRIVER("CMD: Got to the end of the buffer w/o a BBE cmd!\n");
 477                ret = -EINVAL;
 478        }
 479
 480        vunmap(batch_base);
 481
 482        i915_gem_object_unpin_pages(batch_obj);
 483
 484        return ret;
 485}
 486