aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r100.c
diff options
context:
space:
mode:
authorJerome Glisse <glisse@freedesktop.org>2009-06-17 07:28:30 -0400
committerDave Airlie <airlied@redhat.com>2009-06-18 19:32:27 -0400
commit068a117ca38f27c9641db7642f24fe9270d9424e (patch)
treee1038db118114aa777312a5eae70b512fa13617b /drivers/gpu/drm/radeon/r100.c
parent8b5c744485b75d940ccb1c83c9a358b20eb91346 (diff)
drm/radeon: command stream checker for r3xx-r5xx hardware
For security purpose we want to make sure the userspace process doesn't access memory beyond buffer it owns. To achieve this we need to check states the userspace program. For color buffer and zbuffer we check that the clipping register will discard access beyond buffers set as color or zbuffer. For vertex buffer we check that no vertex fetch will happen beyond buffer end. For texture we check various texture states (number of mipmap level, texture size, texture depth, ...) to compute the amount of memory the texture fetcher might access. The command stream checking impact the performances so far quick benchmark shows an average of 3% decrease in fps of various applications. It can be optimized a bit more by caching result of checking and thus avoid a full recheck if no states changed since last check. Note that this patch is still incomplete on checking side as it doesn't check 2d rendering states. Signed-off-by: Jerome Glisse <jglisse@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/r100.c')
-rw-r--r--drivers/gpu/drm/radeon/r100.c76
1 files changed, 45 insertions, 31 deletions
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 64a692c0c319..c550932a108f 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -647,7 +647,7 @@ int r100_cp_reset(struct radeon_device *rdev)
647 */ 647 */
648int r100_cs_parse_packet0(struct radeon_cs_parser *p, 648int r100_cs_parse_packet0(struct radeon_cs_parser *p,
649 struct radeon_cs_packet *pkt, 649 struct radeon_cs_packet *pkt,
650 unsigned *auth, unsigned n, 650 const unsigned *auth, unsigned n,
651 radeon_packet0_check_t check) 651 radeon_packet0_check_t check)
652{ 652{
653 unsigned reg; 653 unsigned reg;
@@ -657,6 +657,10 @@ int r100_cs_parse_packet0(struct radeon_cs_parser *p,
657 657
658 idx = pkt->idx + 1; 658 idx = pkt->idx + 1;
659 reg = pkt->reg; 659 reg = pkt->reg;
660 /* Check that register fall into register range
661 * determined by the number of entry (n) in the
662 * safe register bitmap.
663 */
660 if (pkt->one_reg_wr) { 664 if (pkt->one_reg_wr) {
661 if ((reg >> 7) > n) { 665 if ((reg >> 7) > n) {
662 return -EINVAL; 666 return -EINVAL;
@@ -686,24 +690,6 @@ int r100_cs_parse_packet0(struct radeon_cs_parser *p,
686 return 0; 690 return 0;
687} 691}
688 692
689int r100_cs_parse_packet3(struct radeon_cs_parser *p,
690 struct radeon_cs_packet *pkt,
691 unsigned *auth, unsigned n,
692 radeon_packet3_check_t check)
693{
694 unsigned i, m;
695
696 if ((pkt->opcode >> 5) > n) {
697 return -EINVAL;
698 }
699 i = pkt->opcode >> 5;
700 m = 1 << (pkt->opcode & 31);
701 if (auth[i] & m) {
702 return check(p, pkt);
703 }
704 return 0;
705}
706
707void r100_cs_dump_packet(struct radeon_cs_parser *p, 693void r100_cs_dump_packet(struct radeon_cs_parser *p,
708 struct radeon_cs_packet *pkt) 694 struct radeon_cs_packet *pkt)
709{ 695{
@@ -904,6 +890,25 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
904 return 0; 890 return 0;
905} 891}
906 892
893int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p,
894 struct radeon_cs_packet *pkt,
895 struct radeon_object *robj)
896{
897 struct radeon_cs_chunk *ib_chunk;
898 unsigned idx;
899
900 ib_chunk = &p->chunks[p->chunk_ib_idx];
901 idx = pkt->idx + 1;
902 if ((ib_chunk->kdata[idx+2] + 1) > radeon_object_size(robj)) {
903 DRM_ERROR("[drm] Buffer too small for PACKET3 INDX_BUFFER "
904 "(need %u have %lu) !\n",
905 ib_chunk->kdata[idx+2] + 1,
906 radeon_object_size(robj));
907 return -EINVAL;
908 }
909 return 0;
910}
911
907static int r100_packet3_check(struct radeon_cs_parser *p, 912static int r100_packet3_check(struct radeon_cs_parser *p,
908 struct radeon_cs_packet *pkt) 913 struct radeon_cs_packet *pkt)
909{ 914{
@@ -957,6 +962,10 @@ static int r100_packet3_check(struct radeon_cs_parser *p,
957 return r; 962 return r;
958 } 963 }
959 ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); 964 ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
965 r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj);
966 if (r) {
967 return r;
968 }
960 break; 969 break;
961 case 0x23: 970 case 0x23:
962 /* FIXME: cleanup */ 971 /* FIXME: cleanup */
@@ -1002,18 +1011,18 @@ int r100_cs_parse(struct radeon_cs_parser *p)
1002 } 1011 }
1003 p->idx += pkt.count + 2; 1012 p->idx += pkt.count + 2;
1004 switch (pkt.type) { 1013 switch (pkt.type) {
1005 case PACKET_TYPE0: 1014 case PACKET_TYPE0:
1006 r = r100_packet0_check(p, &pkt); 1015 r = r100_packet0_check(p, &pkt);
1007 break; 1016 break;
1008 case PACKET_TYPE2: 1017 case PACKET_TYPE2:
1009 break; 1018 break;
1010 case PACKET_TYPE3: 1019 case PACKET_TYPE3:
1011 r = r100_packet3_check(p, &pkt); 1020 r = r100_packet3_check(p, &pkt);
1012 break; 1021 break;
1013 default: 1022 default:
1014 DRM_ERROR("Unknown packet type %d !\n", 1023 DRM_ERROR("Unknown packet type %d !\n",
1015 pkt.type); 1024 pkt.type);
1016 return -EINVAL; 1025 return -EINVAL;
1017 } 1026 }
1018 if (r) { 1027 if (r) {
1019 return r; 1028 return r;
@@ -1349,6 +1358,11 @@ void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
1349 } 1358 }
1350} 1359}
1351 1360
1361int r100_init(struct radeon_device *rdev)
1362{
1363 return 0;
1364}
1365
1352/* 1366/*
1353 * Debugfs info 1367 * Debugfs info
1354 */ 1368 */