aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2015-06-11 14:56:18 -0400
committerAlex Deucher <alexander.deucher@amd.com>2015-06-29 11:21:46 -0400
commitf1689ec1b0b1256d0e69653cd4aaeee44aafdf5c (patch)
treef3e7492dc2576a4d8a17042a6e403807684e5362
parent68fdd3df79ee4bff4d63dab920b01d9ed5731115 (diff)
drm/amdgpu: check VCE relocation buffer range
port of radeon commit 2fc5703abda201f138faf63bdca743d04dbf4b1a. Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Leo Liu <leo.liu@amd.com>
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c119
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h1
3 files changed, 92 insertions, 29 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 22866d1c3d69..963c4ba5dcba 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -1622,6 +1622,7 @@ struct amdgpu_vce {
1622 unsigned fb_version; 1622 unsigned fb_version;
1623 atomic_t handles[AMDGPU_MAX_VCE_HANDLES]; 1623 atomic_t handles[AMDGPU_MAX_VCE_HANDLES];
1624 struct drm_file *filp[AMDGPU_MAX_VCE_HANDLES]; 1624 struct drm_file *filp[AMDGPU_MAX_VCE_HANDLES];
1625 uint32_t img_size[AMDGPU_MAX_VCE_HANDLES];
1625 struct delayed_work idle_work; 1626 struct delayed_work idle_work;
1626 const struct firmware *fw; /* VCE firmware */ 1627 const struct firmware *fw; /* VCE firmware */
1627 struct amdgpu_ring ring[AMDGPU_MAX_VCE_RINGS]; 1628 struct amdgpu_ring ring[AMDGPU_MAX_VCE_RINGS];
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
index 1127a504f118..cb1bff742550 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
@@ -464,10 +464,12 @@ int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
464 * @p: parser context 464 * @p: parser context
465 * @lo: address of lower dword 465 * @lo: address of lower dword
466 * @hi: address of higher dword 466 * @hi: address of higher dword
467 * @size: minimum size
467 * 468 *
468 * Patch relocation inside command stream with real buffer address 469 * Patch relocation inside command stream with real buffer address
469 */ 470 */
470int amdgpu_vce_cs_reloc(struct amdgpu_cs_parser *p, uint32_t ib_idx, int lo, int hi) 471static int amdgpu_vce_cs_reloc(struct amdgpu_cs_parser *p, uint32_t ib_idx,
472 int lo, int hi, unsigned size)
471{ 473{
472 struct amdgpu_bo_va_mapping *mapping; 474 struct amdgpu_bo_va_mapping *mapping;
473 struct amdgpu_ib *ib = &p->ibs[ib_idx]; 475 struct amdgpu_ib *ib = &p->ibs[ib_idx];
@@ -484,6 +486,13 @@ int amdgpu_vce_cs_reloc(struct amdgpu_cs_parser *p, uint32_t ib_idx, int lo, int
484 return -EINVAL; 486 return -EINVAL;
485 } 487 }
486 488
489 if ((addr + (uint64_t)size) >
490 ((uint64_t)mapping->it.last + 1) * AMDGPU_GPU_PAGE_SIZE) {
491 DRM_ERROR("BO to small for addr 0x%010Lx %d %d\n",
492 addr, lo, hi);
493 return -EINVAL;
494 }
495
487 addr -= ((uint64_t)mapping->it.start) * AMDGPU_GPU_PAGE_SIZE; 496 addr -= ((uint64_t)mapping->it.start) * AMDGPU_GPU_PAGE_SIZE;
488 addr += amdgpu_bo_gpu_offset(bo); 497 addr += amdgpu_bo_gpu_offset(bo);
489 498
@@ -494,6 +503,39 @@ int amdgpu_vce_cs_reloc(struct amdgpu_cs_parser *p, uint32_t ib_idx, int lo, int
494} 503}
495 504
496/** 505/**
506 * amdgpu_vce_validate_handle - validate stream handle
507 *
508 * @p: parser context
509 * @handle: handle to validate
510 *
511 * Validates the handle and return the found session index or -EINVAL
512 * we we don't have another free session index.
513 */
514static int amdgpu_vce_validate_handle(struct amdgpu_cs_parser *p,
515 uint32_t handle)
516{
517 unsigned i;
518
519 /* validate the handle */
520 for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) {
521 if (atomic_read(&p->adev->vce.handles[i]) == handle)
522 return i;
523 }
524
525 /* handle not found try to alloc a new one */
526 for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) {
527 if (!atomic_cmpxchg(&p->adev->vce.handles[i], 0, handle)) {
528 p->adev->vce.filp[i] = p->filp;
529 p->adev->vce.img_size[i] = 0;
530 return i;
531 }
532 }
533
534 DRM_ERROR("No more free VCE handles!\n");
535 return -EINVAL;
536}
537
538/**
497 * amdgpu_vce_cs_parse - parse and validate the command stream 539 * amdgpu_vce_cs_parse - parse and validate the command stream
498 * 540 *
499 * @p: parser context 541 * @p: parser context
@@ -501,10 +543,12 @@ int amdgpu_vce_cs_reloc(struct amdgpu_cs_parser *p, uint32_t ib_idx, int lo, int
501 */ 543 */
502int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx) 544int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx)
503{ 545{
504 uint32_t handle = 0;
505 bool destroy = false;
506 int i, r, idx = 0;
507 struct amdgpu_ib *ib = &p->ibs[ib_idx]; 546 struct amdgpu_ib *ib = &p->ibs[ib_idx];
547 int session_idx = -1;
548 bool destroyed = false;
549 uint32_t tmp, handle = 0;
550 uint32_t *size = &tmp;
551 int i, r, idx = 0;
508 552
509 amdgpu_vce_note_usage(p->adev); 553 amdgpu_vce_note_usage(p->adev);
510 554
@@ -517,13 +561,29 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx)
517 return -EINVAL; 561 return -EINVAL;
518 } 562 }
519 563
564 if (destroyed) {
565 DRM_ERROR("No other command allowed after destroy!\n");
566 return -EINVAL;
567 }
568
520 switch (cmd) { 569 switch (cmd) {
521 case 0x00000001: // session 570 case 0x00000001: // session
522 handle = amdgpu_get_ib_value(p, ib_idx, idx + 2); 571 handle = amdgpu_get_ib_value(p, ib_idx, idx + 2);
572 session_idx = amdgpu_vce_validate_handle(p, handle);
573 if (session_idx < 0)
574 return session_idx;
575 size = &p->adev->vce.img_size[session_idx];
523 break; 576 break;
524 577
525 case 0x00000002: // task info 578 case 0x00000002: // task info
579 break;
580
526 case 0x01000001: // create 581 case 0x01000001: // create
582 *size = amdgpu_get_ib_value(p, ib_idx, idx + 8) *
583 amdgpu_get_ib_value(p, ib_idx, idx + 10) *
584 8 * 3 / 2;
585 break;
586
527 case 0x04000001: // config extension 587 case 0x04000001: // config extension
528 case 0x04000002: // pic control 588 case 0x04000002: // pic control
529 case 0x04000005: // rate control 589 case 0x04000005: // rate control
@@ -534,23 +594,39 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx)
534 break; 594 break;
535 595
536 case 0x03000001: // encode 596 case 0x03000001: // encode
537 r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 10, idx + 9); 597 r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 10, idx + 9,
598 *size);
538 if (r) 599 if (r)
539 return r; 600 return r;
540 601
541 r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 12, idx + 11); 602 r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 12, idx + 11,
603 *size / 3);
542 if (r) 604 if (r)
543 return r; 605 return r;
544 break; 606 break;
545 607
546 case 0x02000001: // destroy 608 case 0x02000001: // destroy
547 destroy = true; 609 destroyed = true;
548 break; 610 break;
549 611
550 case 0x05000001: // context buffer 612 case 0x05000001: // context buffer
613 r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 3, idx + 2,
614 *size * 2);
615 if (r)
616 return r;
617 break;
618
551 case 0x05000004: // video bitstream buffer 619 case 0x05000004: // video bitstream buffer
620 tmp = amdgpu_get_ib_value(p, ib_idx, idx + 4);
621 r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 3, idx + 2,
622 tmp);
623 if (r)
624 return r;
625 break;
626
552 case 0x05000005: // feedback buffer 627 case 0x05000005: // feedback buffer
553 r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 3, idx + 2); 628 r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 3, idx + 2,
629 4096);
554 if (r) 630 if (r)
555 return r; 631 return r;
556 break; 632 break;
@@ -560,34 +636,21 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx)
560 return -EINVAL; 636 return -EINVAL;
561 } 637 }
562 638
639 if (session_idx == -1) {
640 DRM_ERROR("no session command at start of IB\n");
641 return -EINVAL;
642 }
643
563 idx += len / 4; 644 idx += len / 4;
564 } 645 }
565 646
566 if (destroy) { 647 if (destroyed) {
567 /* IB contains a destroy msg, free the handle */ 648 /* IB contains a destroy msg, free the handle */
568 for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) 649 for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i)
569 atomic_cmpxchg(&p->adev->vce.handles[i], handle, 0); 650 atomic_cmpxchg(&p->adev->vce.handles[i], handle, 0);
570
571 return 0;
572 }
573
574 /* create or encode, validate the handle */
575 for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) {
576 if (atomic_read(&p->adev->vce.handles[i]) == handle)
577 return 0;
578 }
579
580 /* handle not found try to alloc a new one */
581 for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i) {
582 if (!atomic_cmpxchg(&p->adev->vce.handles[i], 0, handle)) {
583 p->adev->vce.filp[i] = p->filp;
584 return 0;
585 }
586 } 651 }
587 652
588 DRM_ERROR("No more free VCE handles!\n"); 653 return 0;
589
590 return -EINVAL;
591} 654}
592 655
593/** 656/**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h
index b6a9d0956c60..7ccdb5927da5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h
@@ -33,7 +33,6 @@ int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
33int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, 33int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
34 struct amdgpu_fence **fence); 34 struct amdgpu_fence **fence);
35void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp); 35void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp);
36int amdgpu_vce_cs_reloc(struct amdgpu_cs_parser *p, uint32_t ib_idx, int lo, int hi);
37int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx); 36int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx);
38bool amdgpu_vce_ring_emit_semaphore(struct amdgpu_ring *ring, 37bool amdgpu_vce_ring_emit_semaphore(struct amdgpu_ring *ring,
39 struct amdgpu_semaphore *semaphore, 38 struct amdgpu_semaphore *semaphore,