Rev 5354 | Rev 6088 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5354 | Rev 6084 | ||
---|---|---|---|
Line 121... | Line 121... | ||
121 | CMD( MI_REPORT_HEAD, SMI, F, 1, S ), |
121 | CMD( MI_REPORT_HEAD, SMI, F, 1, S ), |
122 | CMD( MI_SUSPEND_FLUSH, SMI, F, 1, S ), |
122 | CMD( MI_SUSPEND_FLUSH, SMI, F, 1, S ), |
123 | CMD( MI_SEMAPHORE_MBOX, SMI, !F, 0xFF, R ), |
123 | CMD( MI_SEMAPHORE_MBOX, SMI, !F, 0xFF, R ), |
124 | CMD( MI_STORE_DWORD_INDEX, SMI, !F, 0xFF, R ), |
124 | CMD( MI_STORE_DWORD_INDEX, SMI, !F, 0xFF, R ), |
125 | CMD( MI_LOAD_REGISTER_IMM(1), SMI, !F, 0xFF, W, |
125 | CMD( MI_LOAD_REGISTER_IMM(1), SMI, !F, 0xFF, W, |
126 | .reg = { .offset = 1, .mask = 0x007FFFFC } ), |
126 | .reg = { .offset = 1, .mask = 0x007FFFFC, .step = 2 } ), |
127 | CMD( MI_STORE_REGISTER_MEM(1), SMI, !F, 0xFF, W | B, |
127 | CMD( MI_STORE_REGISTER_MEM, SMI, F, 3, W | B, |
128 | .reg = { .offset = 1, .mask = 0x007FFFFC }, |
128 | .reg = { .offset = 1, .mask = 0x007FFFFC }, |
129 | .bits = {{ |
129 | .bits = {{ |
130 | .offset = 0, |
130 | .offset = 0, |
131 | .mask = MI_GLOBAL_GTT, |
131 | .mask = MI_GLOBAL_GTT, |
132 | .expected = 0, |
132 | .expected = 0, |
133 | }}, ), |
133 | }}, ), |
134 | CMD( MI_LOAD_REGISTER_MEM, SMI, !F, 0xFF, W | B, |
134 | CMD( MI_LOAD_REGISTER_MEM, SMI, F, 3, W | B, |
135 | .reg = { .offset = 1, .mask = 0x007FFFFC }, |
135 | .reg = { .offset = 1, .mask = 0x007FFFFC }, |
136 | .bits = {{ |
136 | .bits = {{ |
137 | .offset = 0, |
137 | .offset = 0, |
138 | .mask = MI_GLOBAL_GTT, |
138 | .mask = MI_GLOBAL_GTT, |
139 | .expected = 0, |
139 | .expected = 0, |
Line 149... | Line 149... | ||
149 | static const struct drm_i915_cmd_descriptor render_cmds[] = { |
149 | static const struct drm_i915_cmd_descriptor render_cmds[] = { |
150 | CMD( MI_FLUSH, SMI, F, 1, S ), |
150 | CMD( MI_FLUSH, SMI, F, 1, S ), |
151 | CMD( MI_ARB_ON_OFF, SMI, F, 1, R ), |
151 | CMD( MI_ARB_ON_OFF, SMI, F, 1, R ), |
152 | CMD( MI_PREDICATE, SMI, F, 1, S ), |
152 | CMD( MI_PREDICATE, SMI, F, 1, S ), |
153 | CMD( MI_TOPOLOGY_FILTER, SMI, F, 1, S ), |
153 | CMD( MI_TOPOLOGY_FILTER, SMI, F, 1, S ), |
- | 154 | CMD( MI_SET_APPID, SMI, F, 1, S ), |
|
154 | CMD( MI_DISPLAY_FLIP, SMI, !F, 0xFF, R ), |
155 | CMD( MI_DISPLAY_FLIP, SMI, !F, 0xFF, R ), |
155 | CMD( MI_SET_CONTEXT, SMI, !F, 0xFF, R ), |
156 | CMD( MI_SET_CONTEXT, SMI, !F, 0xFF, R ), |
156 | CMD( MI_URB_CLEAR, SMI, !F, 0xFF, S ), |
157 | CMD( MI_URB_CLEAR, SMI, !F, 0xFF, S ), |
157 | CMD( MI_STORE_DWORD_IMM, SMI, !F, 0x3F, B, |
158 | CMD( MI_STORE_DWORD_IMM, SMI, !F, 0x3F, B, |
158 | .bits = {{ |
159 | .bits = {{ |
Line 208... | Line 209... | ||
208 | 209 | ||
209 | static const struct drm_i915_cmd_descriptor hsw_render_cmds[] = { |
210 | static const struct drm_i915_cmd_descriptor hsw_render_cmds[] = { |
210 | CMD( MI_SET_PREDICATE, SMI, F, 1, S ), |
211 | CMD( MI_SET_PREDICATE, SMI, F, 1, S ), |
211 | CMD( MI_RS_CONTROL, SMI, F, 1, S ), |
212 | CMD( MI_RS_CONTROL, SMI, F, 1, S ), |
- | 213 | CMD( MI_URB_ATOMIC_ALLOC, SMI, F, 1, S ), |
|
212 | CMD( MI_URB_ATOMIC_ALLOC, SMI, F, 1, S ), |
214 | CMD( MI_SET_APPID, SMI, F, 1, S ), |
213 | CMD( MI_RS_CONTEXT, SMI, F, 1, S ), |
215 | CMD( MI_RS_CONTEXT, SMI, F, 1, S ), |
214 | CMD( MI_LOAD_SCAN_LINES_INCL, SMI, !F, 0x3F, M ), |
216 | CMD( MI_LOAD_SCAN_LINES_INCL, SMI, !F, 0x3F, M ), |
215 | CMD( MI_LOAD_SCAN_LINES_EXCL, SMI, !F, 0x3F, R ), |
217 | CMD( MI_LOAD_SCAN_LINES_EXCL, SMI, !F, 0x3F, R ), |
216 | CMD( MI_LOAD_REGISTER_REG, SMI, !F, 0xFF, R ), |
218 | CMD( MI_LOAD_REGISTER_REG, SMI, !F, 0xFF, R ), |
Line 227... | Line 229... | ||
227 | CMD( GFX_OP_3DSTATE_BINDING_TABLE_EDIT_PS, S3D, !F, 0x1FF, S ), |
229 | CMD( GFX_OP_3DSTATE_BINDING_TABLE_EDIT_PS, S3D, !F, 0x1FF, S ), |
228 | }; |
230 | }; |
Line 229... | Line 231... | ||
229 | 231 | ||
230 | static const struct drm_i915_cmd_descriptor video_cmds[] = { |
232 | static const struct drm_i915_cmd_descriptor video_cmds[] = { |
- | 233 | CMD( MI_ARB_ON_OFF, SMI, F, 1, R ), |
|
231 | CMD( MI_ARB_ON_OFF, SMI, F, 1, R ), |
234 | CMD( MI_SET_APPID, SMI, F, 1, S ), |
232 | CMD( MI_STORE_DWORD_IMM, SMI, !F, 0xFF, B, |
235 | CMD( MI_STORE_DWORD_IMM, SMI, !F, 0xFF, B, |
233 | .bits = {{ |
236 | .bits = {{ |
234 | .offset = 0, |
237 | .offset = 0, |
235 | .mask = MI_GLOBAL_GTT, |
238 | .mask = MI_GLOBAL_GTT, |
Line 270... | Line 273... | ||
270 | CMD( MFX_WAIT, SMFX, F, 1, S ), |
273 | CMD( MFX_WAIT, SMFX, F, 1, S ), |
271 | }; |
274 | }; |
Line 272... | Line 275... | ||
272 | 275 | ||
273 | static const struct drm_i915_cmd_descriptor vecs_cmds[] = { |
276 | static const struct drm_i915_cmd_descriptor vecs_cmds[] = { |
- | 277 | CMD( MI_ARB_ON_OFF, SMI, F, 1, R ), |
|
274 | CMD( MI_ARB_ON_OFF, SMI, F, 1, R ), |
278 | CMD( MI_SET_APPID, SMI, F, 1, S ), |
275 | CMD( MI_STORE_DWORD_IMM, SMI, !F, 0xFF, B, |
279 | CMD( MI_STORE_DWORD_IMM, SMI, !F, 0xFF, B, |
276 | .bits = {{ |
280 | .bits = {{ |
277 | .offset = 0, |
281 | .offset = 0, |
278 | .mask = MI_GLOBAL_GTT, |
282 | .mask = MI_GLOBAL_GTT, |
Line 389... | Line 393... | ||
389 | { hsw_blt_cmds, ARRAY_SIZE(hsw_blt_cmds) }, |
393 | { hsw_blt_cmds, ARRAY_SIZE(hsw_blt_cmds) }, |
390 | }; |
394 | }; |
Line 391... | Line 395... | ||
391 | 395 | ||
392 | /* |
396 | /* |
- | 397 | * Register whitelists, sorted by increasing register offset. |
|
- | 398 | */ |
|
- | 399 | ||
- | 400 | /* |
|
- | 401 | * An individual whitelist entry granting access to register addr. If |
|
- | 402 | * mask is non-zero the argument of immediate register writes will be |
|
- | 403 | * AND-ed with mask, and the command will be rejected if the result |
|
- | 404 | * doesn't match value. |
|
- | 405 | * |
|
- | 406 | * Registers with non-zero mask are only allowed to be written using |
|
- | 407 | * LRI. |
|
- | 408 | */ |
|
- | 409 | struct drm_i915_reg_descriptor { |
|
- | 410 | u32 addr; |
|
- | 411 | u32 mask; |
|
- | 412 | u32 value; |
|
- | 413 | }; |
|
- | 414 | ||
- | 415 | /* Convenience macro for adding 32-bit registers. */ |
|
- | 416 | #define REG32(address, ...) \ |
|
- | 417 | { .addr = address, __VA_ARGS__ } |
|
- | 418 | ||
- | 419 | /* |
|
393 | * Register whitelists, sorted by increasing register offset. |
420 | * Convenience macro for adding 64-bit registers. |
394 | * |
421 | * |
395 | * Some registers that userspace accesses are 64 bits. The register |
422 | * Some registers that userspace accesses are 64 bits. The register |
396 | * access commands only allow 32-bit accesses. Hence, we have to include |
423 | * access commands only allow 32-bit accesses. Hence, we have to include |
397 | * entries for both halves of the 64-bit registers. |
424 | * entries for both halves of the 64-bit registers. |
- | 425 | */ |
|
- | 426 | #define REG64(addr) \ |
|
Line 398... | Line 427... | ||
398 | */ |
427 | REG32(addr), REG32(addr + sizeof(u32)) |
399 | 428 | ||
400 | /* Convenience macro for adding 64-bit registers */ |
- | |
401 | #define REG64(addr) (addr), (addr + sizeof(u32)) |
- | |
402 | 429 | static const struct drm_i915_reg_descriptor gen7_render_regs[] = { |
|
403 | static const u32 gen7_render_regs[] = { |
430 | REG64(GPGPU_THREADS_DISPATCHED), |
404 | REG64(HS_INVOCATION_COUNT), |
431 | REG64(HS_INVOCATION_COUNT), |
405 | REG64(DS_INVOCATION_COUNT), |
432 | REG64(DS_INVOCATION_COUNT), |
406 | REG64(IA_VERTICES_COUNT), |
433 | REG64(IA_VERTICES_COUNT), |
Line 410... | Line 437... | ||
410 | REG64(GS_PRIMITIVES_COUNT), |
437 | REG64(GS_PRIMITIVES_COUNT), |
411 | REG64(CL_INVOCATION_COUNT), |
438 | REG64(CL_INVOCATION_COUNT), |
412 | REG64(CL_PRIMITIVES_COUNT), |
439 | REG64(CL_PRIMITIVES_COUNT), |
413 | REG64(PS_INVOCATION_COUNT), |
440 | REG64(PS_INVOCATION_COUNT), |
414 | REG64(PS_DEPTH_COUNT), |
441 | REG64(PS_DEPTH_COUNT), |
415 | OACONTROL, /* Only allowed for LRI and SRM. See below. */ |
442 | REG32(OACONTROL), /* Only allowed for LRI and SRM. See below. */ |
416 | REG64(MI_PREDICATE_SRC0), |
443 | REG64(MI_PREDICATE_SRC0), |
417 | REG64(MI_PREDICATE_SRC1), |
444 | REG64(MI_PREDICATE_SRC1), |
418 | GEN7_3DPRIM_END_OFFSET, |
445 | REG32(GEN7_3DPRIM_END_OFFSET), |
419 | GEN7_3DPRIM_START_VERTEX, |
446 | REG32(GEN7_3DPRIM_START_VERTEX), |
420 | GEN7_3DPRIM_VERTEX_COUNT, |
447 | REG32(GEN7_3DPRIM_VERTEX_COUNT), |
421 | GEN7_3DPRIM_INSTANCE_COUNT, |
448 | REG32(GEN7_3DPRIM_INSTANCE_COUNT), |
422 | GEN7_3DPRIM_START_INSTANCE, |
449 | REG32(GEN7_3DPRIM_START_INSTANCE), |
423 | GEN7_3DPRIM_BASE_VERTEX, |
450 | REG32(GEN7_3DPRIM_BASE_VERTEX), |
- | 451 | REG32(GEN7_GPGPU_DISPATCHDIMX), |
|
- | 452 | REG32(GEN7_GPGPU_DISPATCHDIMY), |
|
- | 453 | REG32(GEN7_GPGPU_DISPATCHDIMZ), |
|
424 | REG64(GEN7_SO_NUM_PRIMS_WRITTEN(0)), |
454 | REG64(GEN7_SO_NUM_PRIMS_WRITTEN(0)), |
425 | REG64(GEN7_SO_NUM_PRIMS_WRITTEN(1)), |
455 | REG64(GEN7_SO_NUM_PRIMS_WRITTEN(1)), |
426 | REG64(GEN7_SO_NUM_PRIMS_WRITTEN(2)), |
456 | REG64(GEN7_SO_NUM_PRIMS_WRITTEN(2)), |
427 | REG64(GEN7_SO_NUM_PRIMS_WRITTEN(3)), |
457 | REG64(GEN7_SO_NUM_PRIMS_WRITTEN(3)), |
428 | REG64(GEN7_SO_PRIM_STORAGE_NEEDED(0)), |
458 | REG64(GEN7_SO_PRIM_STORAGE_NEEDED(0)), |
429 | REG64(GEN7_SO_PRIM_STORAGE_NEEDED(1)), |
459 | REG64(GEN7_SO_PRIM_STORAGE_NEEDED(1)), |
430 | REG64(GEN7_SO_PRIM_STORAGE_NEEDED(2)), |
460 | REG64(GEN7_SO_PRIM_STORAGE_NEEDED(2)), |
431 | REG64(GEN7_SO_PRIM_STORAGE_NEEDED(3)), |
461 | REG64(GEN7_SO_PRIM_STORAGE_NEEDED(3)), |
432 | GEN7_SO_WRITE_OFFSET(0), |
462 | REG32(GEN7_SO_WRITE_OFFSET(0)), |
433 | GEN7_SO_WRITE_OFFSET(1), |
463 | REG32(GEN7_SO_WRITE_OFFSET(1)), |
434 | GEN7_SO_WRITE_OFFSET(2), |
464 | REG32(GEN7_SO_WRITE_OFFSET(2)), |
435 | GEN7_SO_WRITE_OFFSET(3), |
465 | REG32(GEN7_SO_WRITE_OFFSET(3)), |
436 | GEN7_L3SQCREG1, |
466 | REG32(GEN7_L3SQCREG1), |
437 | GEN7_L3CNTLREG2, |
467 | REG32(GEN7_L3CNTLREG2), |
438 | GEN7_L3CNTLREG3, |
468 | REG32(GEN7_L3CNTLREG3), |
- | 469 | REG32(HSW_SCRATCH1, |
|
- | 470 | .mask = ~HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE, |
|
- | 471 | .value = 0), |
|
- | 472 | REG32(HSW_ROW_CHICKEN3, |
|
- | 473 | .mask = ~(HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE << 16 | |
|
- | 474 | HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE), |
|
- | 475 | .value = 0), |
|
439 | }; |
476 | }; |
440 | 477 | ||
441 | static const u32 gen7_blt_regs[] = { |
478 | static const struct drm_i915_reg_descriptor gen7_blt_regs[] = { |
442 | BCS_SWCTRL, |
479 | REG32(BCS_SWCTRL), |
443 | }; |
480 | }; |
444 | 481 | ||
445 | static const u32 ivb_master_regs[] = { |
482 | static const struct drm_i915_reg_descriptor ivb_master_regs[] = { |
446 | FORCEWAKE_MT, |
483 | REG32(FORCEWAKE_MT), |
447 | DERRMR, |
484 | REG32(DERRMR), |
448 | GEN7_PIPE_DE_LOAD_SL(PIPE_A), |
485 | REG32(GEN7_PIPE_DE_LOAD_SL(PIPE_A)), |
449 | GEN7_PIPE_DE_LOAD_SL(PIPE_B), |
486 | REG32(GEN7_PIPE_DE_LOAD_SL(PIPE_B)), |
450 | GEN7_PIPE_DE_LOAD_SL(PIPE_C), |
487 | REG32(GEN7_PIPE_DE_LOAD_SL(PIPE_C)), |
451 | }; |
488 | }; |
452 | 489 | ||
453 | static const u32 hsw_master_regs[] = { |
490 | static const struct drm_i915_reg_descriptor hsw_master_regs[] = { |
454 | FORCEWAKE_MT, |
491 | REG32(FORCEWAKE_MT), |
455 | DERRMR, |
492 | REG32(DERRMR), |
456 | }; |
493 | }; |
Line 457... | Line 494... | ||
457 | 494 | ||
- | 495 | #undef REG64 |
|
Line 458... | Line 496... | ||
458 | #undef REG64 |
496 | #undef REG32 |
459 | 497 | ||
460 | static u32 gen7_render_get_cmd_length_mask(u32 cmd_header) |
498 | static u32 gen7_render_get_cmd_length_mask(u32 cmd_header) |
461 | { |
499 | { |
Line 479... | Line 517... | ||
479 | static u32 gen7_bsd_get_cmd_length_mask(u32 cmd_header) |
517 | static u32 gen7_bsd_get_cmd_length_mask(u32 cmd_header) |
480 | { |
518 | { |
481 | u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT; |
519 | u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT; |
482 | u32 subclient = |
520 | u32 subclient = |
483 | (cmd_header & INSTR_SUBCLIENT_MASK) >> INSTR_SUBCLIENT_SHIFT; |
521 | (cmd_header & INSTR_SUBCLIENT_MASK) >> INSTR_SUBCLIENT_SHIFT; |
- | 522 | u32 op = (cmd_header & INSTR_26_TO_24_MASK) >> INSTR_26_TO_24_SHIFT; |
|
Line 484... | Line 523... | ||
484 | 523 | ||
485 | if (client == INSTR_MI_CLIENT) |
524 | if (client == INSTR_MI_CLIENT) |
486 | return 0x3F; |
525 | return 0x3F; |
487 | else if (client == INSTR_RC_CLIENT) { |
526 | else if (client == INSTR_RC_CLIENT) { |
- | 527 | if (subclient == INSTR_MEDIA_SUBCLIENT) { |
|
488 | if (subclient == INSTR_MEDIA_SUBCLIENT) |
528 | if (op == 6) |
489 | return 0xFFF; |
529 | return 0xFFFF; |
- | 530 | else |
|
- | 531 | return 0xFFF; |
|
490 | else |
532 | } else |
491 | return 0xFF; |
533 | return 0xFF; |
Line 492... | Line 534... | ||
492 | } |
534 | } |
493 | 535 | ||
Line 523... | Line 565... | ||
523 | u32 previous = 0; |
565 | u32 previous = 0; |
524 | int j; |
566 | int j; |
Line 525... | Line 567... | ||
525 | 567 | ||
526 | for (j = 0; j < table->count; j++) { |
568 | for (j = 0; j < table->count; j++) { |
527 | const struct drm_i915_cmd_descriptor *desc = |
569 | const struct drm_i915_cmd_descriptor *desc = |
528 | &table->table[i]; |
570 | &table->table[j]; |
Line 529... | Line 571... | ||
529 | u32 curr = desc->cmd.value & desc->cmd.mask; |
571 | u32 curr = desc->cmd.value & desc->cmd.mask; |
530 | 572 | ||
531 | if (curr < previous) { |
573 | if (curr < previous) { |
Line 539... | Line 581... | ||
539 | } |
581 | } |
Line 540... | Line 582... | ||
540 | 582 | ||
541 | return ret; |
583 | return ret; |
Line 542... | Line 584... | ||
542 | } |
584 | } |
- | 585 | ||
- | 586 | static bool check_sorted(int ring_id, |
|
543 | 587 | const struct drm_i915_reg_descriptor *reg_table, |
|
544 | static bool check_sorted(int ring_id, const u32 *reg_table, int reg_count) |
588 | int reg_count) |
545 | { |
589 | { |
546 | int i; |
590 | int i; |
Line 547... | Line 591... | ||
547 | u32 previous = 0; |
591 | u32 previous = 0; |
548 | bool ret = true; |
592 | bool ret = true; |
Line 549... | Line 593... | ||
549 | 593 | ||
550 | for (i = 0; i < reg_count; i++) { |
594 | for (i = 0; i < reg_count; i++) { |
551 | u32 curr = reg_table[i]; |
595 | u32 curr = reg_table[i].addr; |
552 | 596 | ||
Line 714... | Line 758... | ||
714 | } |
758 | } |
Line 715... | Line 759... | ||
715 | 759 | ||
716 | BUG_ON(!validate_cmds_sorted(ring, cmd_tables, cmd_table_count)); |
760 | BUG_ON(!validate_cmds_sorted(ring, cmd_tables, cmd_table_count)); |
Line 717... | Line 761... | ||
717 | BUG_ON(!validate_regs_sorted(ring)); |
761 | BUG_ON(!validate_regs_sorted(ring)); |
- | 762 | ||
718 | 763 | WARN_ON(!hash_empty(ring->cmd_hash)); |
|
719 | if (hash_empty(ring->cmd_hash)) { |
764 | |
720 | ret = init_hash_table(ring, cmd_tables, cmd_table_count); |
765 | ret = init_hash_table(ring, cmd_tables, cmd_table_count); |
721 | if (ret) { |
766 | if (ret) { |
722 | DRM_ERROR("CMD: cmd_parser_init failed!\n"); |
767 | DRM_ERROR("CMD: cmd_parser_init failed!\n"); |
723 | fini_hash_table(ring); |
768 | fini_hash_table(ring); |
724 | return ret; |
- | |
Line 725... | Line 769... | ||
725 | } |
769 | return ret; |
Line 726... | Line 770... | ||
726 | } |
770 | } |
727 | 771 | ||
Line 793... | Line 837... | ||
793 | default_desc->length.mask = mask; |
837 | default_desc->length.mask = mask; |
Line 794... | Line 838... | ||
794 | 838 | ||
795 | return default_desc; |
839 | return default_desc; |
Line 796... | Line 840... | ||
796 | } |
840 | } |
- | 841 | ||
- | 842 | static const struct drm_i915_reg_descriptor * |
|
797 | 843 | find_reg(const struct drm_i915_reg_descriptor *table, |
|
798 | static bool valid_reg(const u32 *table, int count, u32 addr) |
844 | int count, u32 addr) |
799 | { |
845 | { |
Line 800... | Line 846... | ||
800 | if (table && count != 0) { |
846 | if (table) { |
801 | int i; |
847 | int i; |
802 | 848 | ||
803 | for (i = 0; i < count; i++) { |
849 | for (i = 0; i < count; i++) { |
804 | if (table[i] == addr) |
850 | if (table[i].addr == addr) |
Line 805... | Line 851... | ||
805 | return true; |
851 | return &table[i]; |
806 | } |
852 | } |
Line 807... | Line 853... | ||
807 | } |
853 | } |
- | 854 | ||
808 | 855 | return NULL; |
|
809 | return false; |
856 | } |
810 | } |
857 | |
811 | 858 | static u32 *vmap_batch(struct drm_i915_gem_object *obj, |
|
- | 859 | unsigned start, unsigned len) |
|
- | 860 | { |
|
- | 861 | int i; |
|
812 | static u32 *vmap_batch(struct drm_i915_gem_object *obj) |
862 | void *addr = NULL; |
Line 813... | Line 863... | ||
813 | { |
863 | struct sg_page_iter sg_iter; |
814 | int i; |
864 | int first_page = start >> PAGE_SHIFT; |
815 | void *addr = NULL; |
865 | int last_page = (len + start + 4095) >> PAGE_SHIFT; |
816 | struct sg_page_iter sg_iter; |
866 | int npages = last_page - first_page; |
817 | struct page **pages; |
867 | struct page **pages; |
Line 818... | Line 868... | ||
818 | 868 | ||
819 | pages = kmalloc(obj->base.size >> PAGE_SHIFT, sizeof(*pages)); |
869 | pages = kmalloc(obj->base.size >> PAGE_SHIFT, sizeof(*pages)); |
820 | if (pages == NULL) { |
870 | if (pages == NULL) { |
- | 871 | DRM_DEBUG_DRIVER("Failed to get space for pages\n"); |
|
821 | DRM_DEBUG_DRIVER("Failed to get space for pages\n"); |
872 | goto finish; |
822 | goto finish; |
873 | } |
Line 823... | Line 874... | ||
823 | } |
874 | |
824 | 875 | i = 0; |
|
825 | i = 0; |
876 | for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, first_page) { |
826 | for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) { |
877 | pages[i++] = sg_page_iter_page(&sg_iter); |
827 | pages[i] = sg_page_iter_page(&sg_iter); |
878 | if (i == npages) |
Line 828... | Line 879... | ||
828 | i++; |
879 | break; |
829 | } |
880 | } |
830 | 881 | ||
831 | // addr = vmap(pages, i, 0, PAGE_KERNEL); |
882 | addr = vmap(pages, i, 0, PAGE_KERNEL); |
832 | if (addr == NULL) { |
883 | if (addr == NULL) { |
Line -... | Line 884... | ||
- | 884 | DRM_DEBUG_DRIVER("Failed to vmap pages\n"); |
|
- | 885 | goto finish; |
|
- | 886 | } |
|
- | 887 | ||
- | 888 | finish: |
|
- | 889 | if (pages) |
|
- | 890 | drm_free_large(pages); |
|
- | 891 | return (u32*)addr; |
|
- | 892 | } |
|
- | 893 | ||
- | 894 | /* Returns a vmap'd pointer to dest_obj, which the caller must unmap */ |
|
- | 895 | static u32 *copy_batch(struct drm_i915_gem_object *dest_obj, |
|
- | 896 | struct drm_i915_gem_object *src_obj, |
|
- | 897 | u32 batch_start_offset, |
|
- | 898 | u32 batch_len) |
|
- | 899 | { |
|
- | 900 | int needs_clflush = 0; |
|
- | 901 | void *src_base, *src; |
|
- | 902 | void *dst = NULL; |
|
- | 903 | int ret; |
|
- | 904 | ||
- | 905 | if (batch_len > dest_obj->base.size || |
|
- | 906 | batch_len + batch_start_offset > src_obj->base.size) |
|
- | 907 | return ERR_PTR(-E2BIG); |
|
- | 908 | ||
- | 909 | if (WARN_ON(dest_obj->pages_pin_count == 0)) |
|
- | 910 | return ERR_PTR(-ENODEV); |
|
- | 911 | ||
- | 912 | ret = i915_gem_obj_prepare_shmem_read(src_obj, &needs_clflush); |
|
- | 913 | if (ret) { |
|
- | 914 | DRM_DEBUG_DRIVER("CMD: failed to prepare shadow batch\n"); |
|
- | 915 | return ERR_PTR(ret); |
|
- | 916 | } |
|
- | 917 | ||
- | 918 | src_base = vmap_batch(src_obj, batch_start_offset, batch_len); |
|
- | 919 | if (!src_base) { |
|
- | 920 | DRM_DEBUG_DRIVER("CMD: Failed to vmap batch\n"); |
|
- | 921 | ret = -ENOMEM; |
|
- | 922 | goto unpin_src; |
|
- | 923 | } |
|
- | 924 | ||
- | 925 | ret = i915_gem_object_set_to_cpu_domain(dest_obj, true); |
|
- | 926 | if (ret) { |
|
- | 927 | DRM_DEBUG_DRIVER("CMD: Failed to set shadow batch to CPU\n"); |
|
- | 928 | goto unmap_src; |
|
- | 929 | } |
|
- | 930 | ||
- | 931 | dst = vmap_batch(dest_obj, 0, batch_len); |
|
- | 932 | if (!dst) { |
|
- | 933 | DRM_DEBUG_DRIVER("CMD: Failed to vmap shadow batch\n"); |
|
- | 934 | ret = -ENOMEM; |
|
- | 935 | goto unmap_src; |
|
- | 936 | } |
|
- | 937 | ||
- | 938 | src = src_base + offset_in_page(batch_start_offset); |
|
- | 939 | if (needs_clflush) |
|
- | 940 | drm_clflush_virt_range(src, batch_len); |
|
- | 941 | ||
833 | DRM_DEBUG_DRIVER("Failed to vmap pages\n"); |
942 | memcpy(dst, src, batch_len); |
834 | goto finish; |
943 | |
835 | } |
944 | unmap_src: |
836 | 945 | vunmap(src_base); |
|
837 | finish: |
946 | unpin_src: |
Line 860... | Line 969... | ||
860 | return (i915.enable_cmd_parser == 1); |
969 | return (i915.enable_cmd_parser == 1); |
861 | } |
970 | } |
Line 862... | Line 971... | ||
862 | 971 | ||
863 | static bool check_cmd(const struct intel_engine_cs *ring, |
972 | static bool check_cmd(const struct intel_engine_cs *ring, |
864 | const struct drm_i915_cmd_descriptor *desc, |
973 | const struct drm_i915_cmd_descriptor *desc, |
865 | const u32 *cmd, |
974 | const u32 *cmd, u32 length, |
866 | const bool is_master, |
975 | const bool is_master, |
867 | bool *oacontrol_set) |
976 | bool *oacontrol_set) |
868 | { |
977 | { |
869 | if (desc->flags & CMD_DESC_REJECT) { |
978 | if (desc->flags & CMD_DESC_REJECT) { |
Line 876... | Line 985... | ||
876 | *cmd); |
985 | *cmd); |
877 | return false; |
986 | return false; |
878 | } |
987 | } |
Line 879... | Line 988... | ||
879 | 988 | ||
- | 989 | if (desc->flags & CMD_DESC_REGISTER) { |
|
- | 990 | /* |
|
- | 991 | * Get the distance between individual register offset |
|
- | 992 | * fields if the command can perform more than one |
|
- | 993 | * access at a time. |
|
- | 994 | */ |
|
- | 995 | const u32 step = desc->reg.step ? desc->reg.step : length; |
|
- | 996 | u32 offset; |
|
- | 997 | ||
- | 998 | for (offset = desc->reg.offset; offset < length; |
|
880 | if (desc->flags & CMD_DESC_REGISTER) { |
999 | offset += step) { |
- | 1000 | const u32 reg_addr = cmd[offset] & desc->reg.mask; |
|
- | 1001 | const struct drm_i915_reg_descriptor *reg = |
|
- | 1002 | find_reg(ring->reg_table, ring->reg_count, |
|
- | 1003 | reg_addr); |
|
- | 1004 | ||
- | 1005 | if (!reg && is_master) |
|
- | 1006 | reg = find_reg(ring->master_reg_table, |
|
- | 1007 | ring->master_reg_count, |
|
- | 1008 | reg_addr); |
|
- | 1009 | ||
- | 1010 | if (!reg) { |
|
- | 1011 | DRM_DEBUG_DRIVER("CMD: Rejected register 0x%08X in command: 0x%08X (ring=%d)\n", |
|
- | 1012 | reg_addr, *cmd, ring->id); |
|
- | 1013 | return false; |
|
Line 881... | Line 1014... | ||
881 | u32 reg_addr = cmd[desc->reg.offset] & desc->reg.mask; |
1014 | } |
882 | 1015 | ||
883 | /* |
1016 | /* |
884 | * OACONTROL requires some special handling for writes. We |
1017 | * OACONTROL requires some special handling for |
885 | * want to make sure that any batch which enables OA also |
1018 | * writes. We want to make sure that any batch which |
886 | * disables it before the end of the batch. The goal is to |
1019 | * enables OA also disables it before the end of the |
887 | * prevent one process from snooping on the perf data from |
1020 | * batch. The goal is to prevent one process from |
- | 1021 | * snooping on the perf data from another process. To do |
|
888 | * another process. To do that, we need to check the value |
1022 | * that, we need to check the value that will be written |
889 | * that will be written to the register. Hence, limit |
1023 | * to the register. Hence, limit OACONTROL writes to |
890 | * OACONTROL writes to only MI_LOAD_REGISTER_IMM commands. |
1024 | * only MI_LOAD_REGISTER_IMM commands. |
891 | */ |
1025 | */ |
892 | if (reg_addr == OACONTROL) { |
1026 | if (reg_addr == OACONTROL) { |
893 | if (desc->cmd.value == MI_LOAD_REGISTER_MEM) { |
1027 | if (desc->cmd.value == MI_LOAD_REGISTER_MEM) { |
894 | DRM_DEBUG_DRIVER("CMD: Rejected LRM to OACONTROL\n"); |
1028 | DRM_DEBUG_DRIVER("CMD: Rejected LRM to OACONTROL\n"); |
Line 895... | Line 1029... | ||
895 | return false; |
1029 | return false; |
896 | } |
1030 | } |
897 | 1031 | ||
Line -... | Line 1032... | ||
- | 1032 | if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1)) |
|
898 | if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1)) |
1033 | *oacontrol_set = (cmd[offset + 1] != 0); |
899 | *oacontrol_set = (cmd[2] != 0); |
1034 | } |
- | 1035 | ||
900 | } |
1036 | /* |
901 | 1037 | * Check the value written to the register against the |
|
902 | if (!valid_reg(ring->reg_table, |
1038 | * allowed mask/value pair given in the whitelist entry. |
903 | ring->reg_count, reg_addr)) { |
1039 | */ |
904 | if (!is_master || |
- | |
905 | !valid_reg(ring->master_reg_table, |
1040 | if (reg->mask) { |
906 | ring->master_reg_count, |
1041 | if (desc->cmd.value == MI_LOAD_REGISTER_MEM) { |
- | 1042 | DRM_DEBUG_DRIVER("CMD: Rejected LRM to masked register 0x%08X\n", |
|
- | 1043 | reg_addr); |
|
- | 1044 | return false; |
|
- | 1045 | } |
|
- | 1046 | ||
907 | reg_addr)) { |
1047 | if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1) && |
908 | DRM_DEBUG_DRIVER("CMD: Rejected register 0x%08X in command: 0x%08X (ring=%d)\n", |
1048 | (offset + 2 > length || |
909 | reg_addr, |
1049 | (cmd[offset + 1] & reg->mask) != reg->value)) { |
910 | *cmd, |
1050 | DRM_DEBUG_DRIVER("CMD: Rejected LRI to masked register 0x%08X\n", |
911 | ring->id); |
1051 | reg_addr); |
- | 1052 | return false; |
|
Line 912... | Line 1053... | ||
912 | return false; |
1053 | } |
913 | } |
1054 | } |
Line 914... | Line 1055... | ||
914 | } |
1055 | } |
Line 955... | Line 1096... | ||
955 | #if 0 |
1096 | #if 0 |
956 | /** |
1097 | /** |
957 | * i915_parse_cmds() - parse a submitted batch buffer for privilege violations |
1098 | * i915_parse_cmds() - parse a submitted batch buffer for privilege violations |
958 | * @ring: the ring on which the batch is to execute |
1099 | * @ring: the ring on which the batch is to execute |
959 | * @batch_obj: the batch buffer in question |
1100 | * @batch_obj: the batch buffer in question |
- | 1101 | * @shadow_batch_obj: copy of the batch buffer in question |
|
960 | * @batch_start_offset: byte offset in the batch at which execution starts |
1102 | * @batch_start_offset: byte offset in the batch at which execution starts |
- | 1103 | * @batch_len: length of the commands in batch_obj |
|
961 | * @is_master: is the submitting process the drm master? |
1104 | * @is_master: is the submitting process the drm master? |
962 | * |
1105 | * |
963 | * Parses the specified batch buffer looking for privilege violations as |
1106 | * Parses the specified batch buffer looking for privilege violations as |
964 | * described in the overview. |
1107 | * described in the overview. |
965 | * |
1108 | * |
966 | * Return: non-zero if the parser finds violations or otherwise fails; -EACCES |
1109 | * Return: non-zero if the parser finds violations or otherwise fails; -EACCES |
967 | * if the batch appears legal but should use hardware parsing |
1110 | * if the batch appears legal but should use hardware parsing |
968 | */ |
1111 | */ |
969 | int i915_parse_cmds(struct intel_engine_cs *ring, |
1112 | int i915_parse_cmds(struct intel_engine_cs *ring, |
970 | struct drm_i915_gem_object *batch_obj, |
1113 | struct drm_i915_gem_object *batch_obj, |
- | 1114 | struct drm_i915_gem_object *shadow_batch_obj, |
|
971 | u32 batch_start_offset, |
1115 | u32 batch_start_offset, |
- | 1116 | u32 batch_len, |
|
972 | bool is_master) |
1117 | bool is_master) |
973 | { |
1118 | { |
974 | int ret = 0; |
- | |
975 | u32 *cmd, *batch_base, *batch_end; |
1119 | u32 *cmd, *batch_base, *batch_end; |
976 | struct drm_i915_cmd_descriptor default_desc = { 0 }; |
1120 | struct drm_i915_cmd_descriptor default_desc = { 0 }; |
977 | int needs_clflush = 0; |
- | |
978 | bool oacontrol_set = false; /* OACONTROL tracking. See check_cmd() */ |
1121 | bool oacontrol_set = false; /* OACONTROL tracking. See check_cmd() */ |
- | 1122 | int ret = 0; |
|
Line 979... | Line 1123... | ||
979 | 1123 | ||
980 | ret = i915_gem_obj_prepare_shmem_read(batch_obj, &needs_clflush); |
- | |
981 | if (ret) { |
- | |
982 | DRM_DEBUG_DRIVER("CMD: failed to prep read\n"); |
- | |
983 | return ret; |
- | |
984 | } |
- | |
985 | 1124 | batch_base = copy_batch(shadow_batch_obj, batch_obj, |
|
986 | batch_base = vmap_batch(batch_obj); |
1125 | batch_start_offset, batch_len); |
987 | if (!batch_base) { |
1126 | if (IS_ERR(batch_base)) { |
988 | DRM_DEBUG_DRIVER("CMD: Failed to vmap batch\n"); |
- | |
989 | i915_gem_object_unpin_pages(batch_obj); |
1127 | DRM_DEBUG_DRIVER("CMD: Failed to copy batch\n"); |
990 | return -ENOMEM; |
1128 | return PTR_ERR(batch_base); |
Line -... | Line 1129... | ||
- | 1129 | } |
|
991 | } |
1130 | |
992 | 1131 | /* |
|
993 | if (needs_clflush) |
- | |
994 | drm_clflush_virt_range((char *)batch_base, batch_obj->base.size); |
1132 | * We use the batch length as size because the shadow object is as |
- | 1133 | * large or larger and copy_batch() will write MI_NOPs to the extra |
|
995 | 1134 | * space. Parsing should be faster in some cases this way. |
|
Line -... | Line 1135... | ||
- | 1135 | */ |
|
996 | cmd = batch_base + (batch_start_offset / sizeof(*cmd)); |
1136 | batch_end = batch_base + (batch_len / sizeof(*batch_end)); |
997 | batch_end = cmd + (batch_obj->base.size / sizeof(*batch_end)); |
1137 | |
998 | 1138 | cmd = batch_base; |
|
Line 999... | Line 1139... | ||
999 | while (cmd < batch_end) { |
1139 | while (cmd < batch_end) { |
Line 1033... | Line 1173... | ||
1033 | batch_end - cmd); |
1173 | batch_end - cmd); |
1034 | ret = -EINVAL; |
1174 | ret = -EINVAL; |
1035 | break; |
1175 | break; |
1036 | } |
1176 | } |
Line 1037... | Line 1177... | ||
1037 | 1177 | ||
- | 1178 | if (!check_cmd(ring, desc, cmd, length, is_master, |
|
1038 | if (!check_cmd(ring, desc, cmd, is_master, &oacontrol_set)) { |
1179 | &oacontrol_set)) { |
1039 | ret = -EINVAL; |
1180 | ret = -EINVAL; |
1040 | break; |
1181 | break; |
Line 1041... | Line 1182... | ||
1041 | } |
1182 | } |
Line 1051... | Line 1192... | ||
1051 | if (cmd >= batch_end) { |
1192 | if (cmd >= batch_end) { |
1052 | DRM_DEBUG_DRIVER("CMD: Got to the end of the buffer w/o a BBE cmd!\n"); |
1193 | DRM_DEBUG_DRIVER("CMD: Got to the end of the buffer w/o a BBE cmd!\n"); |
1053 | ret = -EINVAL; |
1194 | ret = -EINVAL; |
1054 | } |
1195 | } |
Line 1055... | Line 1196... | ||
1055 | 1196 | ||
1056 | // vunmap(batch_base); |
- | |
1057 | - | ||
Line 1058... | Line 1197... | ||
1058 | i915_gem_object_unpin_pages(batch_obj); |
1197 | vunmap(batch_base); |
1059 | 1198 | ||
1060 | return ret; |
1199 | return ret; |
Line 1076... | Line 1215... | ||
1076 | * |
1215 | * |
1077 | * 1. Initial version. Checks batches and reports violations, but leaves |
1216 | * 1. Initial version. Checks batches and reports violations, but leaves |
1078 | * hardware parsing enabled (so does not allow new use cases). |
1217 | * hardware parsing enabled (so does not allow new use cases). |
1079 | * 2. Allow access to the MI_PREDICATE_SRC0 and |
1218 | * 2. Allow access to the MI_PREDICATE_SRC0 and |
1080 | * MI_PREDICATE_SRC1 registers. |
1219 | * MI_PREDICATE_SRC1 registers. |
- | 1220 | * 3. Allow access to the GPGPU_THREADS_DISPATCHED register. |
|
- | 1221 | * 4. L3 atomic chicken bits of HSW_SCRATCH1 and HSW_ROW_CHICKEN3. |
|
- | 1222 | * 5. GPGPU dispatch compute indirect registers. |
|
1081 | */ |
1223 | */ |
1082 | return 2; |
1224 | return 5; |
1083 | }>>>>>>>>>>> |
1225 | }>>>>>>>>>>>>><> |